1// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package net
6
7import (
8	"fmt"
9	"os"
10	"testing"
11)
12
13var tcpServerTests = []struct {
14	snet, saddr string // server endpoint
15	tnet, taddr string // target endpoint for client
16}{
17	{snet: "tcp", saddr: ":0", tnet: "tcp", taddr: "127.0.0.1"},
18	{snet: "tcp", saddr: "0.0.0.0:0", tnet: "tcp", taddr: "127.0.0.1"},
19	{snet: "tcp", saddr: "[::ffff:0.0.0.0]:0", tnet: "tcp", taddr: "127.0.0.1"},
20	{snet: "tcp", saddr: "[::]:0", tnet: "tcp", taddr: "::1"},
21
22	{snet: "tcp", saddr: ":0", tnet: "tcp", taddr: "::1"},
23	{snet: "tcp", saddr: "0.0.0.0:0", tnet: "tcp", taddr: "::1"},
24	{snet: "tcp", saddr: "[::ffff:0.0.0.0]:0", tnet: "tcp", taddr: "::1"},
25	{snet: "tcp", saddr: "[::]:0", tnet: "tcp", taddr: "127.0.0.1"},
26
27	{snet: "tcp", saddr: ":0", tnet: "tcp4", taddr: "127.0.0.1"},
28	{snet: "tcp", saddr: "0.0.0.0:0", tnet: "tcp4", taddr: "127.0.0.1"},
29	{snet: "tcp", saddr: "[::ffff:0.0.0.0]:0", tnet: "tcp4", taddr: "127.0.0.1"},
30	{snet: "tcp", saddr: "[::]:0", tnet: "tcp6", taddr: "::1"},
31
32	{snet: "tcp", saddr: ":0", tnet: "tcp6", taddr: "::1"},
33	{snet: "tcp", saddr: "0.0.0.0:0", tnet: "tcp6", taddr: "::1"},
34	{snet: "tcp", saddr: "[::ffff:0.0.0.0]:0", tnet: "tcp6", taddr: "::1"},
35	{snet: "tcp", saddr: "[::]:0", tnet: "tcp4", taddr: "127.0.0.1"},
36
37	{snet: "tcp", saddr: "127.0.0.1:0", tnet: "tcp", taddr: "127.0.0.1"},
38	{snet: "tcp", saddr: "[::ffff:127.0.0.1]:0", tnet: "tcp", taddr: "127.0.0.1"},
39	{snet: "tcp", saddr: "[::1]:0", tnet: "tcp", taddr: "::1"},
40
41	{snet: "tcp4", saddr: ":0", tnet: "tcp4", taddr: "127.0.0.1"},
42	{snet: "tcp4", saddr: "0.0.0.0:0", tnet: "tcp4", taddr: "127.0.0.1"},
43	{snet: "tcp4", saddr: "[::ffff:0.0.0.0]:0", tnet: "tcp4", taddr: "127.0.0.1"},
44
45	{snet: "tcp4", saddr: "127.0.0.1:0", tnet: "tcp4", taddr: "127.0.0.1"},
46
47	{snet: "tcp6", saddr: ":0", tnet: "tcp6", taddr: "::1"},
48	{snet: "tcp6", saddr: "[::]:0", tnet: "tcp6", taddr: "::1"},
49
50	{snet: "tcp6", saddr: "[::1]:0", tnet: "tcp6", taddr: "::1"},
51}
52
53// TestTCPServer tests concurrent accept-read-write servers.
54func TestTCPServer(t *testing.T) {
55	const N = 3
56
57	for i, tt := range tcpServerTests {
58		t.Run(tt.snet+" "+tt.saddr+"<-"+tt.taddr, func(t *testing.T) {
59			if !testableListenArgs(tt.snet, tt.saddr, tt.taddr) {
60				t.Skip("not testable")
61			}
62
63			ln, err := Listen(tt.snet, tt.saddr)
64			if err != nil {
65				if perr := parseDialError(err); perr != nil {
66					t.Error(perr)
67				}
68				t.Fatal(err)
69			}
70
71			var lss []*localServer
72			var tpchs []chan error
73			defer func() {
74				for _, ls := range lss {
75					ls.teardown()
76				}
77			}()
78			for i := 0; i < N; i++ {
79				ls := (&streamListener{Listener: ln}).newLocalServer()
80				lss = append(lss, ls)
81				tpchs = append(tpchs, make(chan error, 1))
82			}
83			for i := 0; i < N; i++ {
84				ch := tpchs[i]
85				handler := func(ls *localServer, ln Listener) { ls.transponder(ln, ch) }
86				if err := lss[i].buildup(handler); err != nil {
87					t.Fatal(err)
88				}
89			}
90
91			var trchs []chan error
92			for i := 0; i < N; i++ {
93				_, port, err := SplitHostPort(lss[i].Listener.Addr().String())
94				if err != nil {
95					t.Fatal(err)
96				}
97				d := Dialer{Timeout: someTimeout}
98				c, err := d.Dial(tt.tnet, JoinHostPort(tt.taddr, port))
99				if err != nil {
100					if perr := parseDialError(err); perr != nil {
101						t.Error(perr)
102					}
103					t.Fatal(err)
104				}
105				defer c.Close()
106				trchs = append(trchs, make(chan error, 1))
107				go transceiver(c, []byte("TCP SERVER TEST"), trchs[i])
108			}
109
110			for _, ch := range trchs {
111				for err := range ch {
112					t.Errorf("#%d: %v", i, err)
113				}
114			}
115			for _, ch := range tpchs {
116				for err := range ch {
117					t.Errorf("#%d: %v", i, err)
118				}
119			}
120		})
121	}
122}
123
124// TestUnixAndUnixpacketServer tests concurrent accept-read-write
125// servers
126func TestUnixAndUnixpacketServer(t *testing.T) {
127	var unixAndUnixpacketServerTests = []struct {
128		network, address string
129	}{
130		{"unix", testUnixAddr(t)},
131		{"unix", "@nettest/go/unix"},
132
133		{"unixpacket", testUnixAddr(t)},
134		{"unixpacket", "@nettest/go/unixpacket"},
135	}
136
137	const N = 3
138
139	for i, tt := range unixAndUnixpacketServerTests {
140		if !testableListenArgs(tt.network, tt.address, "") {
141			t.Logf("skipping %s test", tt.network+" "+tt.address)
142			continue
143		}
144
145		ln, err := Listen(tt.network, tt.address)
146		if err != nil {
147			if perr := parseDialError(err); perr != nil {
148				t.Error(perr)
149			}
150			t.Fatal(err)
151		}
152
153		var lss []*localServer
154		var tpchs []chan error
155		defer func() {
156			for _, ls := range lss {
157				ls.teardown()
158			}
159		}()
160		for i := 0; i < N; i++ {
161			ls := (&streamListener{Listener: ln}).newLocalServer()
162			lss = append(lss, ls)
163			tpchs = append(tpchs, make(chan error, 1))
164		}
165		for i := 0; i < N; i++ {
166			ch := tpchs[i]
167			handler := func(ls *localServer, ln Listener) { ls.transponder(ln, ch) }
168			if err := lss[i].buildup(handler); err != nil {
169				t.Fatal(err)
170			}
171		}
172
173		var trchs []chan error
174		for i := 0; i < N; i++ {
175			d := Dialer{Timeout: someTimeout}
176			c, err := d.Dial(lss[i].Listener.Addr().Network(), lss[i].Listener.Addr().String())
177			if err != nil {
178				if perr := parseDialError(err); perr != nil {
179					t.Error(perr)
180				}
181				t.Fatal(err)
182			}
183
184			if addr := c.LocalAddr(); addr != nil {
185				t.Logf("connected %s->%s", addr, lss[i].Listener.Addr())
186			}
187
188			defer c.Close()
189			trchs = append(trchs, make(chan error, 1))
190			go transceiver(c, []byte("UNIX AND UNIXPACKET SERVER TEST"), trchs[i])
191		}
192
193		for _, ch := range trchs {
194			for err := range ch {
195				t.Errorf("#%d: %v", i, err)
196			}
197		}
198		for _, ch := range tpchs {
199			for err := range ch {
200				t.Errorf("#%d: %v", i, err)
201			}
202		}
203	}
204}
205
206var udpServerTests = []struct {
207	snet, saddr string // server endpoint
208	tnet, taddr string // target endpoint for client
209	dial        bool   // test with Dial
210}{
211	{snet: "udp", saddr: ":0", tnet: "udp", taddr: "127.0.0.1"},
212	{snet: "udp", saddr: "0.0.0.0:0", tnet: "udp", taddr: "127.0.0.1"},
213	{snet: "udp", saddr: "[::ffff:0.0.0.0]:0", tnet: "udp", taddr: "127.0.0.1"},
214	{snet: "udp", saddr: "[::]:0", tnet: "udp", taddr: "::1"},
215
216	{snet: "udp", saddr: ":0", tnet: "udp", taddr: "::1"},
217	{snet: "udp", saddr: "0.0.0.0:0", tnet: "udp", taddr: "::1"},
218	{snet: "udp", saddr: "[::ffff:0.0.0.0]:0", tnet: "udp", taddr: "::1"},
219	{snet: "udp", saddr: "[::]:0", tnet: "udp", taddr: "127.0.0.1"},
220
221	{snet: "udp", saddr: ":0", tnet: "udp4", taddr: "127.0.0.1"},
222	{snet: "udp", saddr: "0.0.0.0:0", tnet: "udp4", taddr: "127.0.0.1"},
223	{snet: "udp", saddr: "[::ffff:0.0.0.0]:0", tnet: "udp4", taddr: "127.0.0.1"},
224	{snet: "udp", saddr: "[::]:0", tnet: "udp6", taddr: "::1"},
225
226	{snet: "udp", saddr: ":0", tnet: "udp6", taddr: "::1"},
227	{snet: "udp", saddr: "0.0.0.0:0", tnet: "udp6", taddr: "::1"},
228	{snet: "udp", saddr: "[::ffff:0.0.0.0]:0", tnet: "udp6", taddr: "::1"},
229	{snet: "udp", saddr: "[::]:0", tnet: "udp4", taddr: "127.0.0.1"},
230
231	{snet: "udp", saddr: "127.0.0.1:0", tnet: "udp", taddr: "127.0.0.1"},
232	{snet: "udp", saddr: "[::ffff:127.0.0.1]:0", tnet: "udp", taddr: "127.0.0.1"},
233	{snet: "udp", saddr: "[::1]:0", tnet: "udp", taddr: "::1"},
234
235	{snet: "udp4", saddr: ":0", tnet: "udp4", taddr: "127.0.0.1"},
236	{snet: "udp4", saddr: "0.0.0.0:0", tnet: "udp4", taddr: "127.0.0.1"},
237	{snet: "udp4", saddr: "[::ffff:0.0.0.0]:0", tnet: "udp4", taddr: "127.0.0.1"},
238
239	{snet: "udp4", saddr: "127.0.0.1:0", tnet: "udp4", taddr: "127.0.0.1"},
240
241	{snet: "udp6", saddr: ":0", tnet: "udp6", taddr: "::1"},
242	{snet: "udp6", saddr: "[::]:0", tnet: "udp6", taddr: "::1"},
243
244	{snet: "udp6", saddr: "[::1]:0", tnet: "udp6", taddr: "::1"},
245
246	{snet: "udp", saddr: "127.0.0.1:0", tnet: "udp", taddr: "127.0.0.1", dial: true},
247
248	{snet: "udp", saddr: "[::1]:0", tnet: "udp", taddr: "::1", dial: true},
249}
250
251func TestUDPServer(t *testing.T) {
252	for i, tt := range udpServerTests {
253		i, tt := i, tt
254		t.Run(fmt.Sprint(i), func(t *testing.T) {
255			if !testableListenArgs(tt.snet, tt.saddr, tt.taddr) {
256				t.Skipf("skipping %s %s<-%s test", tt.snet, tt.saddr, tt.taddr)
257			}
258			t.Logf("%s %s<-%s", tt.snet, tt.saddr, tt.taddr)
259
260			c1, err := ListenPacket(tt.snet, tt.saddr)
261			if err != nil {
262				if perr := parseDialError(err); perr != nil {
263					t.Error(perr)
264				}
265				t.Fatal(err)
266			}
267
268			ls := (&packetListener{PacketConn: c1}).newLocalServer()
269			defer ls.teardown()
270			tpch := make(chan error, 1)
271			handler := func(ls *localPacketServer, c PacketConn) { packetTransponder(c, tpch) }
272			if err := ls.buildup(handler); err != nil {
273				t.Fatal(err)
274			}
275
276			trch := make(chan error, 1)
277			_, port, err := SplitHostPort(ls.PacketConn.LocalAddr().String())
278			if err != nil {
279				t.Fatal(err)
280			}
281			if tt.dial {
282				d := Dialer{Timeout: someTimeout}
283				c2, err := d.Dial(tt.tnet, JoinHostPort(tt.taddr, port))
284				if err != nil {
285					if perr := parseDialError(err); perr != nil {
286						t.Error(perr)
287					}
288					t.Fatal(err)
289				}
290				defer c2.Close()
291				go transceiver(c2, []byte("UDP SERVER TEST"), trch)
292			} else {
293				c2, err := ListenPacket(tt.tnet, JoinHostPort(tt.taddr, "0"))
294				if err != nil {
295					if perr := parseDialError(err); perr != nil {
296						t.Error(perr)
297					}
298					t.Fatal(err)
299				}
300				defer c2.Close()
301				dst, err := ResolveUDPAddr(tt.tnet, JoinHostPort(tt.taddr, port))
302				if err != nil {
303					t.Fatal(err)
304				}
305				go packetTransceiver(c2, []byte("UDP SERVER TEST"), dst, trch)
306			}
307
308			for trch != nil || tpch != nil {
309				select {
310				case err, ok := <-trch:
311					if !ok {
312						trch = nil
313					}
314					if err != nil {
315						t.Errorf("client: %v", err)
316					}
317				case err, ok := <-tpch:
318					if !ok {
319						tpch = nil
320					}
321					if err != nil {
322						t.Errorf("server: %v", err)
323					}
324				}
325			}
326		})
327	}
328}
329
330func TestUnixgramServer(t *testing.T) {
331	var unixgramServerTests = []struct {
332		saddr string // server endpoint
333		caddr string // client endpoint
334		dial  bool   // test with Dial
335	}{
336		{saddr: testUnixAddr(t), caddr: testUnixAddr(t)},
337		{saddr: testUnixAddr(t), caddr: testUnixAddr(t), dial: true},
338
339		{saddr: "@nettest/go/unixgram/server", caddr: "@nettest/go/unixgram/client"},
340	}
341
342	for i, tt := range unixgramServerTests {
343		i, tt := i, tt
344		t.Run(fmt.Sprint(i), func(t *testing.T) {
345			if !testableListenArgs("unixgram", tt.saddr, "") {
346				t.Skipf("skipping unixgram %s<-%s test", tt.saddr, tt.caddr)
347			}
348			t.Logf("unixgram %s<-%s", tt.saddr, tt.caddr)
349
350			c1, err := ListenPacket("unixgram", tt.saddr)
351			if err != nil {
352				if perr := parseDialError(err); perr != nil {
353					t.Error(perr)
354				}
355				t.Fatal(err)
356			}
357
358			ls := (&packetListener{PacketConn: c1}).newLocalServer()
359			defer ls.teardown()
360			tpch := make(chan error, 1)
361			handler := func(ls *localPacketServer, c PacketConn) { packetTransponder(c, tpch) }
362			if err := ls.buildup(handler); err != nil {
363				t.Fatal(err)
364			}
365
366			trch := make(chan error, 1)
367			if tt.dial {
368				d := Dialer{Timeout: someTimeout, LocalAddr: &UnixAddr{Net: "unixgram", Name: tt.caddr}}
369				c2, err := d.Dial("unixgram", ls.PacketConn.LocalAddr().String())
370				if err != nil {
371					if perr := parseDialError(err); perr != nil {
372						t.Error(perr)
373					}
374					t.Fatal(err)
375				}
376				defer os.Remove(c2.LocalAddr().String())
377				defer c2.Close()
378				go transceiver(c2, []byte(c2.LocalAddr().String()), trch)
379			} else {
380				c2, err := ListenPacket("unixgram", tt.caddr)
381				if err != nil {
382					if perr := parseDialError(err); perr != nil {
383						t.Error(perr)
384					}
385					t.Fatal(err)
386				}
387				defer os.Remove(c2.LocalAddr().String())
388				defer c2.Close()
389				go packetTransceiver(c2, []byte("UNIXGRAM SERVER TEST"), ls.PacketConn.LocalAddr(), trch)
390			}
391
392			for trch != nil || tpch != nil {
393				select {
394				case err, ok := <-trch:
395					if !ok {
396						trch = nil
397					}
398					if err != nil {
399						t.Errorf("client: %v", err)
400					}
401				case err, ok := <-tpch:
402					if !ok {
403						tpch = nil
404					}
405					if err != nil {
406						t.Errorf("server: %v", err)
407					}
408				}
409			}
410		})
411	}
412}
413