2013-02-11 Sebastian Huber <sebastian.huber@embedded-brains.de>
[official-gcc.git] / libgo / go / net / server_test.go
blobeba1e7d96915fc80ae3f5d3eb5ee375aba78515f
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 "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 linux 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: "/tmp/gotest1.net", cnet: "unix", caddr: "/tmp/gotest1.net.local"},
90 {snet: "unix", saddr: "@gotest2/net", cnet: "unix", caddr: "@gotest2/net.local", linux: 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.linux) {
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.Errorf("SplitHostPort(%q) failed: %v", taddr, err)
117 return
119 taddr = tt.caddr + ":" + port
122 runStreamConnClient(t, tt.cnet, taddr, tt.empty)
123 <-done // make sure server stopped
125 switch tt.snet {
126 case "unix":
127 os.Remove(tt.saddr)
128 os.Remove(tt.caddr)
133 var seqpacketConnServerTests = []struct {
134 net string
135 saddr string // server address
136 caddr string // client address
137 empty bool // test with empty data
139 {net: "unixpacket", saddr: "/tmp/gotest3.net", caddr: "/tmp/gotest3.net.local"},
140 {net: "unixpacket", saddr: "@gotest4/net", caddr: "@gotest4/net.local"},
143 func TestSeqpacketConnServer(t *testing.T) {
144 if runtime.GOOS != "linux" {
145 t.Skipf("skipping test on %q", runtime.GOOS)
148 for _, tt := range seqpacketConnServerTests {
149 listening := make(chan string)
150 done := make(chan int)
151 switch tt.net {
152 case "unixpacket":
153 os.Remove(tt.saddr)
154 os.Remove(tt.caddr)
157 go runStreamConnServer(t, tt.net, tt.saddr, listening, done)
158 taddr := <-listening // wait for server to start
160 runStreamConnClient(t, tt.net, taddr, tt.empty)
161 <-done // make sure server stopped
163 switch tt.net {
164 case "unixpacket":
165 os.Remove(tt.saddr)
166 os.Remove(tt.caddr)
171 func runStreamConnServer(t *testing.T, net, laddr string, listening chan<- string, done chan<- int) {
172 l, err := Listen(net, laddr)
173 if err != nil {
174 t.Errorf("Listen(%q, %q) failed: %v", net, laddr, err)
175 listening <- "<nil>"
176 done <- 1
177 return
179 defer l.Close()
180 listening <- l.Addr().String()
182 echo := func(rw io.ReadWriter, done chan<- int) {
183 buf := make([]byte, 1024)
184 for {
185 n, err := rw.Read(buf[0:])
186 if err != nil || n == 0 || string(buf[:n]) == "END" {
187 break
189 rw.Write(buf[0:n])
191 done <- 1
194 run:
195 for {
196 c, err := l.Accept()
197 if err != nil {
198 continue run
200 echodone := make(chan int)
201 go echo(c, echodone)
202 <-echodone // make sure echo stopped
203 c.Close()
204 break run
206 done <- 1
209 func runStreamConnClient(t *testing.T, net, taddr string, isEmpty bool) {
210 c, err := Dial(net, taddr)
211 if err != nil {
212 t.Errorf("Dial(%q, %q) failed: %v", net, taddr, err)
213 return
215 defer c.Close()
216 c.SetReadDeadline(time.Now().Add(1 * time.Second))
218 var wb []byte
219 if !isEmpty {
220 wb = []byte("StreamConnClient by Dial\n")
222 if n, err := c.Write(wb); err != nil || n != len(wb) {
223 t.Errorf("Write failed: %v, %v; want %v, <nil>", n, err, len(wb))
224 return
227 rb := make([]byte, 1024)
228 if n, err := c.Read(rb[0:]); err != nil || n != len(wb) {
229 t.Errorf("Read failed: %v, %v; want %v, <nil>", n, err, len(wb))
230 return
233 // Send explicit ending for unixpacket.
234 // Older Linux kernels do not stop reads on close.
235 switch net {
236 case "unixpacket":
237 c.Write([]byte("END"))
241 // Do not test empty datagrams by default.
242 // It causes unexplained timeouts on some systems,
243 // including Snow Leopard. I think that the kernel
244 // doesn't quite expect them.
245 var testDatagram = flag.Bool("datagram", false, "whether to test udp and unixgram")
247 var datagramPacketConnServerTests = []struct {
248 snet string // server side
249 saddr string
250 cnet string // client side
251 caddr string
252 ipv6 bool // test with underlying AF_INET6 socket
253 ipv4map bool // test with IPv6 IPv4-mapping functionality
254 dial bool // test with Dial or DialUnix
255 empty bool // test with empty data
256 linux bool // test with abstract unix domain socket, a Linux-ism
258 {snet: "udp", saddr: "", cnet: "udp", caddr: "127.0.0.1"},
259 {snet: "udp", saddr: "0.0.0.0", cnet: "udp", caddr: "127.0.0.1"},
260 {snet: "udp", saddr: "[::ffff:0.0.0.0]", cnet: "udp", caddr: "127.0.0.1"},
261 {snet: "udp", saddr: "[::]", cnet: "udp", caddr: "[::1]", ipv6: true},
263 {snet: "udp", saddr: "", cnet: "udp", caddr: "[::1]", ipv4map: true},
264 {snet: "udp", saddr: "0.0.0.0", cnet: "udp", caddr: "[::1]", ipv4map: true},
265 {snet: "udp", saddr: "[::ffff:0.0.0.0]", cnet: "udp", caddr: "[::1]", ipv4map: true},
266 {snet: "udp", saddr: "[::]", cnet: "udp", caddr: "127.0.0.1", ipv4map: true},
268 {snet: "udp", saddr: "", cnet: "udp4", caddr: "127.0.0.1"},
269 {snet: "udp", saddr: "0.0.0.0", cnet: "udp4", caddr: "127.0.0.1"},
270 {snet: "udp", saddr: "[::ffff:0.0.0.0]", cnet: "udp4", caddr: "127.0.0.1"},
271 {snet: "udp", saddr: "[::]", cnet: "udp6", caddr: "[::1]", ipv6: true},
273 {snet: "udp", saddr: "", cnet: "udp6", caddr: "[::1]", ipv4map: true},
274 {snet: "udp", saddr: "0.0.0.0", cnet: "udp6", caddr: "[::1]", ipv4map: true},
275 {snet: "udp", saddr: "[::ffff:0.0.0.0]", cnet: "udp6", caddr: "[::1]", ipv4map: true},
276 {snet: "udp", saddr: "[::]", cnet: "udp4", caddr: "127.0.0.1", ipv4map: true},
278 {snet: "udp", saddr: "127.0.0.1", cnet: "udp", caddr: "127.0.0.1"},
279 {snet: "udp", saddr: "[::ffff:127.0.0.1]", cnet: "udp", caddr: "127.0.0.1"},
280 {snet: "udp", saddr: "[::1]", cnet: "udp", caddr: "[::1]", ipv6: true},
282 {snet: "udp4", saddr: "", cnet: "udp4", caddr: "127.0.0.1"},
283 {snet: "udp4", saddr: "0.0.0.0", cnet: "udp4", caddr: "127.0.0.1"},
284 {snet: "udp4", saddr: "[::ffff:0.0.0.0]", cnet: "udp4", caddr: "127.0.0.1"},
286 {snet: "udp4", saddr: "127.0.0.1", cnet: "udp4", caddr: "127.0.0.1"},
288 {snet: "udp6", saddr: "", cnet: "udp6", caddr: "[::1]", ipv6: true},
289 {snet: "udp6", saddr: "[::]", cnet: "udp6", caddr: "[::1]", ipv6: true},
291 {snet: "udp6", saddr: "[::1]", cnet: "udp6", caddr: "[::1]", ipv6: true},
293 {snet: "udp", saddr: "127.0.0.1", cnet: "udp", caddr: "127.0.0.1", dial: true},
294 {snet: "udp", saddr: "127.0.0.1", cnet: "udp", caddr: "127.0.0.1", empty: true},
295 {snet: "udp", saddr: "127.0.0.1", cnet: "udp", caddr: "127.0.0.1", dial: true, empty: true},
297 {snet: "udp", saddr: "[::1]", cnet: "udp", caddr: "[::1]", ipv6: true, dial: true},
298 {snet: "udp", saddr: "[::1]", cnet: "udp", caddr: "[::1]", ipv6: true, empty: true},
299 {snet: "udp", saddr: "[::1]", cnet: "udp", caddr: "[::1]", ipv6: true, dial: true, empty: true},
301 {snet: "unixgram", saddr: "/tmp/gotest5.net", cnet: "unixgram", caddr: "/tmp/gotest5.net.local"},
302 {snet: "unixgram", saddr: "/tmp/gotest5.net", cnet: "unixgram", caddr: "/tmp/gotest5.net.local", dial: true},
303 {snet: "unixgram", saddr: "/tmp/gotest5.net", cnet: "unixgram", caddr: "/tmp/gotest5.net.local", empty: true},
304 {snet: "unixgram", saddr: "/tmp/gotest5.net", cnet: "unixgram", caddr: "/tmp/gotest5.net.local", dial: true, empty: true},
306 {snet: "unixgram", saddr: "@gotest6/net", cnet: "unixgram", caddr: "@gotest6/net.local", linux: true},
309 func TestDatagramPacketConnServer(t *testing.T) {
310 if !*testDatagram {
311 return
314 for _, tt := range datagramPacketConnServerTests {
315 if skipServerTest(tt.snet, "unixgram", tt.saddr, tt.ipv6, tt.ipv4map, tt.linux) {
316 continue
319 listening := make(chan string)
320 done := make(chan int)
321 switch tt.snet {
322 case "udp", "udp4", "udp6":
323 tt.saddr += ":0"
324 case "unixgram":
325 os.Remove(tt.saddr)
326 os.Remove(tt.caddr)
329 go runDatagramPacketConnServer(t, tt.snet, tt.saddr, listening, done)
330 taddr := <-listening // wait for server to start
332 switch tt.cnet {
333 case "udp", "udp4", "udp6":
334 _, port, err := SplitHostPort(taddr)
335 if err != nil {
336 t.Errorf("SplitHostPort(%q) failed: %v", taddr, err)
337 return
339 taddr = tt.caddr + ":" + port
340 tt.caddr += ":0"
342 if tt.dial {
343 runDatagramConnClient(t, tt.cnet, tt.caddr, taddr, tt.empty)
344 } else {
345 runDatagramPacketConnClient(t, tt.cnet, tt.caddr, taddr, tt.empty)
347 <-done // tell server to stop
348 <-done // make sure server stopped
350 switch tt.snet {
351 case "unixgram":
352 os.Remove(tt.saddr)
353 os.Remove(tt.caddr)
358 func runDatagramPacketConnServer(t *testing.T, net, laddr string, listening chan<- string, done chan<- int) {
359 c, err := ListenPacket(net, laddr)
360 if err != nil {
361 t.Errorf("ListenPacket(%q, %q) failed: %v", net, laddr, err)
362 listening <- "<nil>"
363 done <- 1
364 return
366 defer c.Close()
367 listening <- c.LocalAddr().String()
369 buf := make([]byte, 1024)
370 run:
371 for {
372 c.SetReadDeadline(time.Now().Add(10 * time.Millisecond))
373 n, ra, err := c.ReadFrom(buf[0:])
374 if nerr, ok := err.(Error); ok && nerr.Timeout() {
375 select {
376 case done <- 1:
377 break run
378 default:
379 continue run
382 if err != nil {
383 break run
385 if _, err = c.WriteTo(buf[0:n], ra); err != nil {
386 t.Errorf("WriteTo(%v) failed: %v", ra, err)
387 break run
390 done <- 1
393 func runDatagramConnClient(t *testing.T, net, laddr, taddr string, isEmpty bool) {
394 var c Conn
395 var err error
396 switch net {
397 case "udp", "udp4", "udp6":
398 c, err = Dial(net, taddr)
399 if err != nil {
400 t.Errorf("Dial(%q, %q) failed: %v", net, taddr, err)
401 return
403 case "unixgram":
404 c, err = DialUnix(net, &UnixAddr{laddr, net}, &UnixAddr{taddr, net})
405 if err != nil {
406 t.Errorf("DialUnix(%q, {%q, %q}) failed: %v", net, laddr, taddr, err)
407 return
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.Errorf("Write failed: %v, %v; want %v, <nil>", n, err, len(wb))
419 return
422 rb := make([]byte, 1024)
423 if n, err := c.Read(rb[0:]); err != nil || n != len(wb) {
424 t.Errorf("Read failed: %v, %v; want %v, <nil>", n, err, len(wb))
425 return
429 func runDatagramPacketConnClient(t *testing.T, net, laddr, taddr string, isEmpty bool) {
430 var ra Addr
431 var err error
432 switch net {
433 case "udp", "udp4", "udp6":
434 ra, err = ResolveUDPAddr(net, taddr)
435 if err != nil {
436 t.Errorf("ResolveUDPAddr(%q, %q) failed: %v", net, taddr, err)
437 return
439 case "unixgram":
440 ra, err = ResolveUnixAddr(net, taddr)
441 if err != nil {
442 t.Errorf("ResolveUxixAddr(%q, %q) failed: %v", net, taddr, err)
443 return
446 c, err := ListenPacket(net, laddr)
447 if err != nil {
448 t.Errorf("ListenPacket(%q, %q) faild: %v", net, laddr, err)
449 return
451 defer c.Close()
452 c.SetReadDeadline(time.Now().Add(1 * time.Second))
454 var wb []byte
455 if !isEmpty {
456 wb = []byte("DatagramPacketConnClient by ListenPacket\n")
458 if n, err := c.WriteTo(wb[0:], ra); err != nil || n != len(wb) {
459 t.Errorf("WriteTo(%v) failed: %v, %v; want %v, <nil>", ra, n, err, len(wb))
460 return
463 rb := make([]byte, 1024)
464 if n, _, err := c.ReadFrom(rb[0:]); err != nil || n != len(wb) {
465 t.Errorf("ReadFrom failed: %v, %v; want %v, <nil>", n, err, len(wb))
466 return