1+ package server
2+
3+ import (
4+ "context"
5+ "strings"
6+ "testing"
7+ "time"
8+ )
9+
10+ // mockSlave implements Slave for testing purposes.
11+ type mockSlave struct {}
12+
13+ func (s * mockSlave ) Read (p []byte ) (n int , err error ) { return 0 , nil }
14+ func (s * mockSlave ) Write (p []byte ) (n int , err error ) { return len (p ), nil }
15+ func (s * mockSlave ) Close () error { return nil }
16+ func (s * mockSlave ) WindowTitleVariables () map [string ]interface {} { return nil }
17+ func (s * mockSlave ) ResizeTerminal (width int , height int ) error { return nil }
18+
19+ // mockFactory implements Factory for testing purposes.
20+ type mockFactory struct {}
21+
22+ func (f * mockFactory ) Name () string { return "mock" }
23+ func (f * mockFactory ) New (params map [string ][]string , headers map [string ][]string ) (Slave , error ) {
24+ return & mockSlave {}, nil
25+ }
26+
27+ func TestMultiInterfaceBinding_SingleAddress (t * testing.T ) {
28+ // Backward compat: a single address (no comma) should work as before
29+ opts := & Options {
30+ Address : "127.0.0.1" ,
31+ Port : "0" ,
32+ Quiet : true ,
33+ }
34+
35+ server , err := New (& mockFactory {}, opts )
36+ if err != nil {
37+ t .Fatalf ("failed to create server: %v" , err )
38+ }
39+
40+ ctx , cancel := context .WithCancel (context .Background ())
41+ defer cancel ()
42+
43+ errCh := make (chan error , 1 )
44+ go func () {
45+ errCh <- server .Run (ctx )
46+ }()
47+
48+ time .Sleep (100 * time .Millisecond )
49+
50+ select {
51+ case err := <- errCh :
52+ t .Fatalf ("server.Run returned unexpectedly: %v" , err )
53+ default :
54+ }
55+
56+ cancel ()
57+ <- errCh
58+ }
59+
60+ func TestMultiInterfaceBinding_MultipleAddresses (t * testing.T ) {
61+ // Test binding to 127.0.0.1 on a random port — verify server starts
62+ opts := & Options {
63+ Address : "127.0.0.1" ,
64+ Port : "0" ,
65+ Quiet : true ,
66+ }
67+
68+ server , err := New (& mockFactory {}, opts )
69+ if err != nil {
70+ t .Fatalf ("failed to create server: %v" , err )
71+ }
72+
73+ ctx , cancel := context .WithCancel (context .Background ())
74+ defer cancel ()
75+
76+ errCh := make (chan error , 1 )
77+ go func () {
78+ errCh <- server .Run (ctx )
79+ }()
80+
81+ time .Sleep (100 * time .Millisecond )
82+
83+ select {
84+ case err := <- errCh :
85+ t .Fatalf ("server.Run returned unexpectedly: %v" , err )
86+ default :
87+ }
88+
89+ cancel ()
90+ <- errCh
91+ }
92+
93+ func TestMultiInterfaceBinding_InvalidAddress (t * testing.T ) {
94+ opts := & Options {
95+ Address : "999.999.999.999" ,
96+ Port : "8080" ,
97+ Quiet : true ,
98+ }
99+
100+ server , err := New (& mockFactory {}, opts )
101+ if err != nil {
102+ t .Fatalf ("failed to create server: %v" , err )
103+ }
104+
105+ ctx , cancel := context .WithCancel (context .Background ())
106+ defer cancel ()
107+
108+ err = server .Run (ctx )
109+ if err == nil {
110+ t .Fatal ("expected error for invalid address, got nil" )
111+ }
112+ if ! strings .Contains (err .Error (), "failed to listen" ) {
113+ t .Fatalf ("expected error containing 'failed to listen', got: %v" , err )
114+ }
115+ }
116+
117+ func TestMultiInterfaceBinding_OneAddressFails (t * testing.T ) {
118+ // When one address in a comma-separated list is invalid, the entire
119+ // server should fail and close any already-opened listeners.
120+ opts := & Options {
121+ Address : "127.0.0.1,999.999.999.999" ,
122+ Port : "0" ,
123+ Quiet : true ,
124+ }
125+
126+ server , err := New (& mockFactory {}, opts )
127+ if err != nil {
128+ t .Fatalf ("failed to create server: %v" , err )
129+ }
130+
131+ ctx , cancel := context .WithCancel (context .Background ())
132+ defer cancel ()
133+
134+ err = server .Run (ctx )
135+ if err == nil {
136+ t .Fatal ("expected error when one address is invalid, got nil" )
137+ }
138+ if ! strings .Contains (err .Error (), "failed to listen" ) {
139+ t .Fatalf ("expected error containing 'failed to listen', got: %v" , err )
140+ }
141+ }
142+
143+ func TestMultiInterfaceBinding_AddressTrimming (t * testing.T ) {
144+ // Spaces around addresses should be trimmed
145+ opts := & Options {
146+ Address : " 127.0.0.1 " ,
147+ Port : "0" ,
148+ Quiet : true ,
149+ }
150+
151+ server , err := New (& mockFactory {}, opts )
152+ if err != nil {
153+ t .Fatalf ("failed to create server: %v" , err )
154+ }
155+
156+ ctx , cancel := context .WithCancel (context .Background ())
157+ defer cancel ()
158+
159+ errCh := make (chan error , 1 )
160+ go func () {
161+ errCh <- server .Run (ctx )
162+ }()
163+
164+ time .Sleep (100 * time .Millisecond )
165+
166+ select {
167+ case err := <- errCh :
168+ t .Fatalf ("server.Run returned unexpectedly: %v" , err )
169+ default :
170+ }
171+
172+ cancel ()
173+ <- errCh
174+ }
0 commit comments