libgo: Update to Go 1.1.1.
[official-gcc.git] / libgo / go / net / server_test.go
blob9194a8ec24dd077fcd7b7defa15e78970528f594
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 "strconv"
13 "testing"
14 "time"
17 func skipServerTest(net, unixsotype, addr string, ipv6, ipv4map, linuxonly bool) bool {
18 switch runtime.GOOS {
19 case "linux":
20 case "plan9", "windows":
21 // "unix" sockets are not supported on Windows and Plan 9.
22 if net == unixsotype {
23 return true
25 default:
26 if net == unixsotype && linuxonly {
27 return true
30 switch addr {
31 case "", "0.0.0.0", "[::ffff:0.0.0.0]", "[::]":
32 if testing.Short() || !*testExternal {
33 return true
36 if ipv6 && !supportsIPv6 {
37 return true
39 if ipv4map && !supportsIPv4map {
40 return true
42 return false
45 func tempfile(filename string) string {
46 // use /tmp in case it is prohibited to create
47 // UNIX sockets in TMPDIR
48 return "/tmp/" + filename + "." + strconv.Itoa(os.Getpid())
51 var streamConnServerTests = []struct {
52 snet string // server side
53 saddr string
54 cnet string // client side
55 caddr string
56 ipv6 bool // test with underlying AF_INET6 socket
57 ipv4map bool // test with IPv6 IPv4-mapping functionality
58 empty bool // test with empty data
59 linux bool // test with abstract unix domain socket, a Linux-ism
61 {snet: "tcp", saddr: "", cnet: "tcp", caddr: "127.0.0.1"},
62 {snet: "tcp", saddr: "0.0.0.0", cnet: "tcp", caddr: "127.0.0.1"},
63 {snet: "tcp", saddr: "[::ffff:0.0.0.0]", cnet: "tcp", caddr: "127.0.0.1"},
64 {snet: "tcp", saddr: "[::]", cnet: "tcp", caddr: "[::1]", ipv6: true},
66 {snet: "tcp", saddr: "", cnet: "tcp", caddr: "[::1]", ipv4map: true},
67 {snet: "tcp", saddr: "0.0.0.0", cnet: "tcp", caddr: "[::1]", ipv4map: true},
68 {snet: "tcp", saddr: "[::ffff:0.0.0.0]", cnet: "tcp", caddr: "[::1]", ipv4map: true},
69 {snet: "tcp", saddr: "[::]", cnet: "tcp", caddr: "127.0.0.1", ipv4map: true},
71 {snet: "tcp", saddr: "", cnet: "tcp4", caddr: "127.0.0.1"},
72 {snet: "tcp", saddr: "0.0.0.0", cnet: "tcp4", caddr: "127.0.0.1"},
73 {snet: "tcp", saddr: "[::ffff:0.0.0.0]", cnet: "tcp4", caddr: "127.0.0.1"},
74 {snet: "tcp", saddr: "[::]", cnet: "tcp6", caddr: "[::1]", ipv6: true},
76 {snet: "tcp", saddr: "", cnet: "tcp6", caddr: "[::1]", ipv4map: true},
77 {snet: "tcp", saddr: "0.0.0.0", cnet: "tcp6", caddr: "[::1]", ipv4map: true},
78 {snet: "tcp", saddr: "[::ffff:0.0.0.0]", cnet: "tcp6", caddr: "[::1]", ipv4map: true},
79 {snet: "tcp", saddr: "[::]", cnet: "tcp4", caddr: "127.0.0.1", ipv4map: true},
81 {snet: "tcp", saddr: "127.0.0.1", cnet: "tcp", caddr: "127.0.0.1"},
82 {snet: "tcp", saddr: "[::ffff:127.0.0.1]", cnet: "tcp", caddr: "127.0.0.1"},
83 {snet: "tcp", saddr: "[::1]", cnet: "tcp", caddr: "[::1]", ipv6: true},
85 {snet: "tcp4", saddr: "", cnet: "tcp4", caddr: "127.0.0.1"},
86 {snet: "tcp4", saddr: "0.0.0.0", cnet: "tcp4", caddr: "127.0.0.1"},
87 {snet: "tcp4", saddr: "[::ffff:0.0.0.0]", cnet: "tcp4", caddr: "127.0.0.1"},
89 {snet: "tcp4", saddr: "127.0.0.1", cnet: "tcp4", caddr: "127.0.0.1"},
91 {snet: "tcp6", saddr: "", cnet: "tcp6", caddr: "[::1]", ipv6: true},
92 {snet: "tcp6", saddr: "[::]", cnet: "tcp6", caddr: "[::1]", ipv6: true},
94 {snet: "tcp6", saddr: "[::1]", cnet: "tcp6", caddr: "[::1]", ipv6: true},
96 {snet: "unix", saddr: tempfile("gotest1.net"), cnet: "unix", caddr: tempfile("gotest1.net.local")},
97 {snet: "unix", saddr: "@gotest2/net", cnet: "unix", caddr: "@gotest2/net.local", linux: true},
100 func TestStreamConnServer(t *testing.T) {
101 for _, tt := range streamConnServerTests {
102 if skipServerTest(tt.snet, "unix", tt.saddr, tt.ipv6, tt.ipv4map, tt.linux) {
103 continue
106 listening := make(chan string)
107 done := make(chan int)
108 switch tt.snet {
109 case "tcp", "tcp4", "tcp6":
110 tt.saddr += ":0"
111 case "unix":
112 os.Remove(tt.saddr)
113 os.Remove(tt.caddr)
116 go runStreamConnServer(t, tt.snet, tt.saddr, listening, done)
117 taddr := <-listening // wait for server to start
119 switch tt.cnet {
120 case "tcp", "tcp4", "tcp6":
121 _, port, err := SplitHostPort(taddr)
122 if err != nil {
123 t.Fatalf("SplitHostPort(%q) failed: %v", taddr, err)
125 taddr = tt.caddr + ":" + port
128 runStreamConnClient(t, tt.cnet, taddr, tt.empty)
129 <-done // make sure server stopped
131 switch tt.snet {
132 case "unix":
133 os.Remove(tt.saddr)
134 os.Remove(tt.caddr)
139 var seqpacketConnServerTests = []struct {
140 net string
141 saddr string // server address
142 caddr string // client address
143 empty bool // test with empty data
145 {net: "unixpacket", saddr: tempfile("/gotest3.net"), caddr: tempfile("gotest3.net.local")},
146 {net: "unixpacket", saddr: "@gotest4/net", caddr: "@gotest4/net.local"},
149 func TestSeqpacketConnServer(t *testing.T) {
150 if runtime.GOOS != "linux" {
151 t.Skipf("skipping test on %q", runtime.GOOS)
154 for _, tt := range seqpacketConnServerTests {
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 linux 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: tempfile("gotest5.net"), cnet: "unixgram", caddr: tempfile("gotest5.net.local")},
305 {snet: "unixgram", saddr: tempfile("gotest5.net"), cnet: "unixgram", caddr: tempfile("gotest5.net.local"), dial: true},
306 {snet: "unixgram", saddr: tempfile("gotest5.net"), cnet: "unixgram", caddr: tempfile("gotest5.net.local"), empty: true},
307 {snet: "unixgram", saddr: tempfile("gotest5.net"), cnet: "unixgram", caddr: tempfile("gotest5.net.local"), dial: true, empty: true},
309 {snet: "unixgram", saddr: "@gotest6/net", cnet: "unixgram", caddr: "@gotest6/net.local", linux: 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.linux) {
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))