2015-05-18 Steven G. Kargl <kargl@gcc.gnu.org>
[official-gcc.git] / libgo / go / net / server_test.go
blob6a2bb924329d37fd65653cb01bd7b9ef917e0502
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.
5 package net
7 import (
8 "flag"
9 "io"
10 "os"
11 "runtime"
12 "testing"
13 "time"
16 func skipServerTest(net, unixsotype, addr string, ipv6, ipv4map, linuxOnly bool) bool {
17 switch runtime.GOOS {
18 case "linux":
19 case "nacl", "plan9", "windows":
20 // "unix" sockets are not supported on Windows and Plan 9.
21 if net == unixsotype {
22 return true
24 default:
25 if net == unixsotype && linuxOnly {
26 return true
29 switch addr {
30 case "", "0.0.0.0", "[::ffff:0.0.0.0]", "[::]":
31 if testing.Short() || !*testExternal {
32 return true
35 if ipv6 && !supportsIPv6 {
36 return true
38 if ipv4map && !supportsIPv4map {
39 return true
41 return false
44 var streamConnServerTests = []struct {
45 snet string // server side
46 saddr string
47 cnet string // client side
48 caddr string
49 ipv6 bool // test with underlying AF_INET6 socket
50 ipv4map bool // test with IPv6 IPv4-mapping functionality
51 empty bool // test with empty data
52 linuxOnly bool // test with abstract unix domain socket, a Linux-ism
54 {snet: "tcp", saddr: "", cnet: "tcp", caddr: "127.0.0.1"},
55 {snet: "tcp", saddr: "0.0.0.0", cnet: "tcp", caddr: "127.0.0.1"},
56 {snet: "tcp", saddr: "[::ffff:0.0.0.0]", cnet: "tcp", caddr: "127.0.0.1"},
57 {snet: "tcp", saddr: "[::]", cnet: "tcp", caddr: "[::1]", ipv6: true},
59 {snet: "tcp", saddr: "", cnet: "tcp", caddr: "[::1]", ipv4map: true},
60 {snet: "tcp", saddr: "0.0.0.0", cnet: "tcp", caddr: "[::1]", ipv4map: true},
61 {snet: "tcp", saddr: "[::ffff:0.0.0.0]", cnet: "tcp", caddr: "[::1]", ipv4map: true},
62 {snet: "tcp", saddr: "[::]", cnet: "tcp", caddr: "127.0.0.1", ipv4map: true},
64 {snet: "tcp", saddr: "", cnet: "tcp4", caddr: "127.0.0.1"},
65 {snet: "tcp", saddr: "0.0.0.0", cnet: "tcp4", caddr: "127.0.0.1"},
66 {snet: "tcp", saddr: "[::ffff:0.0.0.0]", cnet: "tcp4", caddr: "127.0.0.1"},
67 {snet: "tcp", saddr: "[::]", cnet: "tcp6", caddr: "[::1]", ipv6: true},
69 {snet: "tcp", saddr: "", cnet: "tcp6", caddr: "[::1]", ipv4map: true},
70 {snet: "tcp", saddr: "0.0.0.0", cnet: "tcp6", caddr: "[::1]", ipv4map: true},
71 {snet: "tcp", saddr: "[::ffff:0.0.0.0]", cnet: "tcp6", caddr: "[::1]", ipv4map: true},
72 {snet: "tcp", saddr: "[::]", cnet: "tcp4", caddr: "127.0.0.1", ipv4map: true},
74 {snet: "tcp", saddr: "127.0.0.1", cnet: "tcp", caddr: "127.0.0.1"},
75 {snet: "tcp", saddr: "[::ffff:127.0.0.1]", cnet: "tcp", caddr: "127.0.0.1"},
76 {snet: "tcp", saddr: "[::1]", cnet: "tcp", caddr: "[::1]", ipv6: true},
78 {snet: "tcp4", saddr: "", cnet: "tcp4", caddr: "127.0.0.1"},
79 {snet: "tcp4", saddr: "0.0.0.0", cnet: "tcp4", caddr: "127.0.0.1"},
80 {snet: "tcp4", saddr: "[::ffff:0.0.0.0]", cnet: "tcp4", caddr: "127.0.0.1"},
82 {snet: "tcp4", saddr: "127.0.0.1", cnet: "tcp4", caddr: "127.0.0.1"},
84 {snet: "tcp6", saddr: "", cnet: "tcp6", caddr: "[::1]", ipv6: true},
85 {snet: "tcp6", saddr: "[::]", cnet: "tcp6", caddr: "[::1]", ipv6: true},
87 {snet: "tcp6", saddr: "[::1]", cnet: "tcp6", caddr: "[::1]", ipv6: true},
89 {snet: "unix", saddr: testUnixAddr(), cnet: "unix", caddr: testUnixAddr()},
90 {snet: "unix", saddr: "@gotest2/net", cnet: "unix", caddr: "@gotest2/net.local", linuxOnly: true},
93 func TestStreamConnServer(t *testing.T) {
94 for _, tt := range streamConnServerTests {
95 if skipServerTest(tt.snet, "unix", tt.saddr, tt.ipv6, tt.ipv4map, tt.linuxOnly) {
96 continue
99 listening := make(chan string)
100 done := make(chan int)
101 switch tt.snet {
102 case "tcp", "tcp4", "tcp6":
103 tt.saddr += ":0"
104 case "unix":
105 os.Remove(tt.saddr)
106 os.Remove(tt.caddr)
109 go runStreamConnServer(t, tt.snet, tt.saddr, listening, done)
110 taddr := <-listening // wait for server to start
112 switch tt.cnet {
113 case "tcp", "tcp4", "tcp6":
114 _, port, err := SplitHostPort(taddr)
115 if err != nil {
116 t.Fatalf("SplitHostPort(%q) failed: %v", taddr, err)
118 taddr = tt.caddr + ":" + port
121 runStreamConnClient(t, tt.cnet, taddr, tt.empty)
122 <-done // make sure server stopped
124 switch tt.snet {
125 case "unix":
126 os.Remove(tt.saddr)
127 os.Remove(tt.caddr)
132 var seqpacketConnServerTests = []struct {
133 net string
134 saddr string // server address
135 caddr string // client address
136 empty bool // test with empty data
137 linuxOnly bool // test with abstract unix domain socket, a Linux-ism
139 {net: "unixpacket", saddr: testUnixAddr(), caddr: testUnixAddr()},
140 {net: "unixpacket", saddr: "@gotest4/net", caddr: "@gotest4/net.local", linuxOnly: true},
143 func TestSeqpacketConnServer(t *testing.T) {
144 switch runtime.GOOS {
145 case "darwin", "nacl", "openbsd", "plan9", "windows":
146 fallthrough
147 case "freebsd": // FreeBSD 8 doesn't support unixpacket
148 t.Skipf("skipping test on %q", runtime.GOOS)
151 for _, tt := range seqpacketConnServerTests {
152 if runtime.GOOS != "linux" && tt.linuxOnly {
153 continue
155 listening := make(chan string)
156 done := make(chan int)
157 switch tt.net {
158 case "unixpacket":
159 os.Remove(tt.saddr)
160 os.Remove(tt.caddr)
163 go runStreamConnServer(t, tt.net, tt.saddr, listening, done)
164 taddr := <-listening // wait for server to start
166 runStreamConnClient(t, tt.net, taddr, tt.empty)
167 <-done // make sure server stopped
169 switch tt.net {
170 case "unixpacket":
171 os.Remove(tt.saddr)
172 os.Remove(tt.caddr)
177 func runStreamConnServer(t *testing.T, net, laddr string, listening chan<- string, done chan<- int) {
178 defer close(done)
179 l, err := Listen(net, laddr)
180 if err != nil {
181 t.Errorf("Listen(%q, %q) failed: %v", net, laddr, err)
182 listening <- "<nil>"
183 return
185 defer l.Close()
186 listening <- l.Addr().String()
188 echo := func(rw io.ReadWriter, done chan<- int) {
189 buf := make([]byte, 1024)
190 for {
191 n, err := rw.Read(buf[0:])
192 if err != nil || n == 0 || string(buf[:n]) == "END" {
193 break
195 rw.Write(buf[0:n])
197 close(done)
200 run:
201 for {
202 c, err := l.Accept()
203 if err != nil {
204 t.Logf("Accept failed: %v", err)
205 continue run
207 echodone := make(chan int)
208 go echo(c, echodone)
209 <-echodone // make sure echo stopped
210 c.Close()
211 break run
215 func runStreamConnClient(t *testing.T, net, taddr string, isEmpty bool) {
216 c, err := Dial(net, taddr)
217 if err != nil {
218 t.Fatalf("Dial(%q, %q) failed: %v", net, taddr, err)
220 defer c.Close()
221 c.SetReadDeadline(time.Now().Add(1 * time.Second))
223 var wb []byte
224 if !isEmpty {
225 wb = []byte("StreamConnClient by Dial\n")
227 if n, err := c.Write(wb); err != nil || n != len(wb) {
228 t.Fatalf("Write failed: %v, %v; want %v, <nil>", n, err, len(wb))
231 rb := make([]byte, 1024)
232 if n, err := c.Read(rb[0:]); err != nil || n != len(wb) {
233 t.Fatalf("Read failed: %v, %v; want %v, <nil>", n, err, len(wb))
236 // Send explicit ending for unixpacket.
237 // Older Linux kernels do not stop reads on close.
238 switch net {
239 case "unixpacket":
240 c.Write([]byte("END"))
244 // Do not test empty datagrams by default.
245 // It causes unexplained timeouts on some systems,
246 // including Snow Leopard. I think that the kernel
247 // doesn't quite expect them.
248 var testDatagram = flag.Bool("datagram", false, "whether to test udp and unixgram")
250 var datagramPacketConnServerTests = []struct {
251 snet string // server side
252 saddr string
253 cnet string // client side
254 caddr string
255 ipv6 bool // test with underlying AF_INET6 socket
256 ipv4map bool // test with IPv6 IPv4-mapping functionality
257 dial bool // test with Dial or DialUnix
258 empty bool // test with empty data
259 linuxOnly bool // test with abstract unix domain socket, a Linux-ism
261 {snet: "udp", saddr: "", cnet: "udp", caddr: "127.0.0.1"},
262 {snet: "udp", saddr: "0.0.0.0", cnet: "udp", caddr: "127.0.0.1"},
263 {snet: "udp", saddr: "[::ffff:0.0.0.0]", cnet: "udp", caddr: "127.0.0.1"},
264 {snet: "udp", saddr: "[::]", cnet: "udp", caddr: "[::1]", ipv6: true},
266 {snet: "udp", saddr: "", cnet: "udp", caddr: "[::1]", ipv4map: true},
267 {snet: "udp", saddr: "0.0.0.0", cnet: "udp", caddr: "[::1]", ipv4map: true},
268 {snet: "udp", saddr: "[::ffff:0.0.0.0]", cnet: "udp", caddr: "[::1]", ipv4map: true},
269 {snet: "udp", saddr: "[::]", cnet: "udp", caddr: "127.0.0.1", ipv4map: true},
271 {snet: "udp", saddr: "", cnet: "udp4", caddr: "127.0.0.1"},
272 {snet: "udp", saddr: "0.0.0.0", cnet: "udp4", caddr: "127.0.0.1"},
273 {snet: "udp", saddr: "[::ffff:0.0.0.0]", cnet: "udp4", caddr: "127.0.0.1"},
274 {snet: "udp", saddr: "[::]", cnet: "udp6", caddr: "[::1]", ipv6: true},
276 {snet: "udp", saddr: "", cnet: "udp6", caddr: "[::1]", ipv4map: true},
277 {snet: "udp", saddr: "0.0.0.0", cnet: "udp6", caddr: "[::1]", ipv4map: true},
278 {snet: "udp", saddr: "[::ffff:0.0.0.0]", cnet: "udp6", caddr: "[::1]", ipv4map: true},
279 {snet: "udp", saddr: "[::]", cnet: "udp4", caddr: "127.0.0.1", ipv4map: true},
281 {snet: "udp", saddr: "127.0.0.1", cnet: "udp", caddr: "127.0.0.1"},
282 {snet: "udp", saddr: "[::ffff:127.0.0.1]", cnet: "udp", caddr: "127.0.0.1"},
283 {snet: "udp", saddr: "[::1]", cnet: "udp", caddr: "[::1]", ipv6: true},
285 {snet: "udp4", saddr: "", cnet: "udp4", caddr: "127.0.0.1"},
286 {snet: "udp4", saddr: "0.0.0.0", cnet: "udp4", caddr: "127.0.0.1"},
287 {snet: "udp4", saddr: "[::ffff:0.0.0.0]", cnet: "udp4", caddr: "127.0.0.1"},
289 {snet: "udp4", saddr: "127.0.0.1", cnet: "udp4", caddr: "127.0.0.1"},
291 {snet: "udp6", saddr: "", cnet: "udp6", caddr: "[::1]", ipv6: true},
292 {snet: "udp6", saddr: "[::]", cnet: "udp6", caddr: "[::1]", ipv6: true},
294 {snet: "udp6", saddr: "[::1]", cnet: "udp6", caddr: "[::1]", ipv6: true},
296 {snet: "udp", saddr: "127.0.0.1", cnet: "udp", caddr: "127.0.0.1", dial: true},
297 {snet: "udp", saddr: "127.0.0.1", cnet: "udp", caddr: "127.0.0.1", empty: true},
298 {snet: "udp", saddr: "127.0.0.1", cnet: "udp", caddr: "127.0.0.1", dial: true, empty: true},
300 {snet: "udp", saddr: "[::1]", cnet: "udp", caddr: "[::1]", ipv6: true, dial: true},
301 {snet: "udp", saddr: "[::1]", cnet: "udp", caddr: "[::1]", ipv6: true, empty: true},
302 {snet: "udp", saddr: "[::1]", cnet: "udp", caddr: "[::1]", ipv6: true, dial: true, empty: true},
304 {snet: "unixgram", saddr: testUnixAddr(), cnet: "unixgram", caddr: testUnixAddr()},
305 {snet: "unixgram", saddr: testUnixAddr(), cnet: "unixgram", caddr: testUnixAddr(), dial: true},
306 {snet: "unixgram", saddr: testUnixAddr(), cnet: "unixgram", caddr: testUnixAddr(), empty: true},
307 {snet: "unixgram", saddr: testUnixAddr(), cnet: "unixgram", caddr: testUnixAddr(), dial: true, empty: true},
309 {snet: "unixgram", saddr: "@gotest6/net", cnet: "unixgram", caddr: "@gotest6/net.local", linuxOnly: true},
312 func TestDatagramPacketConnServer(t *testing.T) {
313 if !*testDatagram {
314 return
317 for _, tt := range datagramPacketConnServerTests {
318 if skipServerTest(tt.snet, "unixgram", tt.saddr, tt.ipv6, tt.ipv4map, tt.linuxOnly) {
319 continue
322 listening := make(chan string)
323 done := make(chan int)
324 switch tt.snet {
325 case "udp", "udp4", "udp6":
326 tt.saddr += ":0"
327 case "unixgram":
328 os.Remove(tt.saddr)
329 os.Remove(tt.caddr)
332 go runDatagramPacketConnServer(t, tt.snet, tt.saddr, listening, done)
333 taddr := <-listening // wait for server to start
335 switch tt.cnet {
336 case "udp", "udp4", "udp6":
337 _, port, err := SplitHostPort(taddr)
338 if err != nil {
339 t.Fatalf("SplitHostPort(%q) failed: %v", taddr, err)
341 taddr = tt.caddr + ":" + port
342 tt.caddr += ":0"
344 if tt.dial {
345 runDatagramConnClient(t, tt.cnet, tt.caddr, taddr, tt.empty)
346 } else {
347 runDatagramPacketConnClient(t, tt.cnet, tt.caddr, taddr, tt.empty)
349 <-done // tell server to stop
350 <-done // make sure server stopped
352 switch tt.snet {
353 case "unixgram":
354 os.Remove(tt.saddr)
355 os.Remove(tt.caddr)
360 func runDatagramPacketConnServer(t *testing.T, net, laddr string, listening chan<- string, done chan<- int) {
361 c, err := ListenPacket(net, laddr)
362 if err != nil {
363 t.Errorf("ListenPacket(%q, %q) failed: %v", net, laddr, err)
364 listening <- "<nil>"
365 done <- 1
366 return
368 defer c.Close()
369 listening <- c.LocalAddr().String()
371 buf := make([]byte, 1024)
372 run:
373 for {
374 c.SetReadDeadline(time.Now().Add(10 * time.Millisecond))
375 n, ra, err := c.ReadFrom(buf[0:])
376 if nerr, ok := err.(Error); ok && nerr.Timeout() {
377 select {
378 case done <- 1:
379 break run
380 default:
381 continue run
384 if err != nil {
385 break run
387 if _, err = c.WriteTo(buf[0:n], ra); err != nil {
388 t.Errorf("WriteTo(%v) failed: %v", ra, err)
389 break run
392 done <- 1
395 func runDatagramConnClient(t *testing.T, net, laddr, taddr string, isEmpty bool) {
396 var c Conn
397 var err error
398 switch net {
399 case "udp", "udp4", "udp6":
400 c, err = Dial(net, taddr)
401 if err != nil {
402 t.Fatalf("Dial(%q, %q) failed: %v", net, taddr, err)
404 case "unixgram":
405 c, err = DialUnix(net, &UnixAddr{Name: laddr, Net: net}, &UnixAddr{Name: taddr, Net: net})
406 if err != nil {
407 t.Fatalf("DialUnix(%q, {%q, %q}) failed: %v", net, laddr, taddr, err)
410 defer c.Close()
411 c.SetReadDeadline(time.Now().Add(1 * time.Second))
413 var wb []byte
414 if !isEmpty {
415 wb = []byte("DatagramConnClient by Dial\n")
417 if n, err := c.Write(wb[0:]); err != nil || n != len(wb) {
418 t.Fatalf("Write failed: %v, %v; want %v, <nil>", n, err, len(wb))
421 rb := make([]byte, 1024)
422 if n, err := c.Read(rb[0:]); err != nil || n != len(wb) {
423 t.Fatalf("Read failed: %v, %v; want %v, <nil>", n, err, len(wb))
427 func runDatagramPacketConnClient(t *testing.T, net, laddr, taddr string, isEmpty bool) {
428 var ra Addr
429 var err error
430 switch net {
431 case "udp", "udp4", "udp6":
432 ra, err = ResolveUDPAddr(net, taddr)
433 if err != nil {
434 t.Fatalf("ResolveUDPAddr(%q, %q) failed: %v", net, taddr, err)
436 case "unixgram":
437 ra, err = ResolveUnixAddr(net, taddr)
438 if err != nil {
439 t.Fatalf("ResolveUxixAddr(%q, %q) failed: %v", net, taddr, err)
442 c, err := ListenPacket(net, laddr)
443 if err != nil {
444 t.Fatalf("ListenPacket(%q, %q) faild: %v", net, laddr, err)
446 defer c.Close()
447 c.SetReadDeadline(time.Now().Add(1 * time.Second))
449 var wb []byte
450 if !isEmpty {
451 wb = []byte("DatagramPacketConnClient by ListenPacket\n")
453 if n, err := c.WriteTo(wb[0:], ra); err != nil || n != len(wb) {
454 t.Fatalf("WriteTo(%v) failed: %v, %v; want %v, <nil>", ra, n, err, len(wb))
457 rb := make([]byte, 1024)
458 if n, _, err := c.ReadFrom(rb[0:]); err != nil || n != len(wb) {
459 t.Fatalf("ReadFrom failed: %v, %v; want %v, <nil>", n, err, len(wb))