]> Cypherpunks repositories - gostls13.git/commitdiff
net: replace server tests
authorMikio Hara <mikioh.mikioh@gmail.com>
Tue, 21 Apr 2015 13:10:09 +0000 (22:10 +0900)
committerMikio Hara <mikioh.mikioh@gmail.com>
Wed, 22 Apr 2015 00:29:40 +0000 (00:29 +0000)
This change replaces server tests with new ones that require features
introduced after go1 release, such as runtime-integrated network poller,
Dialer, etc.

Change-Id: Icf1f94f08f33caacd499cfccbe74cda8d05eed30
Reviewed-on: https://go-review.googlesource.com/9195
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/net/server_test.go
src/net/timeout_test.go

index f064782783ba92f5e62daf962b515812a907dc59..d433ecfa4bf6c36627f82539b11e8d196b44f270 100644 (file)
 package net
 
 import (
-       "io"
        "os"
        "testing"
-       "time"
 )
 
-var streamConnServerTests = []struct {
-       snet  string // server side
-       saddr string
-       cnet  string // client side
-       caddr string
-       empty bool // test with empty data
+var tcpServerTests = []struct {
+       snet, saddr string // server endpoint
+       tnet, taddr string // target endpoint for client
 }{
-       {snet: "tcp", saddr: ":0", cnet: "tcp", caddr: "127.0.0.1"},
-       {snet: "tcp", saddr: "0.0.0.0:0", cnet: "tcp", caddr: "127.0.0.1"},
-       {snet: "tcp", saddr: "[::ffff:0.0.0.0]:0", cnet: "tcp", caddr: "127.0.0.1"},
-       {snet: "tcp", saddr: "[::]:0", cnet: "tcp", caddr: "::1"},
+       {snet: "tcp", saddr: ":0", tnet: "tcp", taddr: "127.0.0.1"},
+       {snet: "tcp", saddr: "0.0.0.0:0", tnet: "tcp", taddr: "127.0.0.1"},
+       {snet: "tcp", saddr: "[::ffff:0.0.0.0]:0", tnet: "tcp", taddr: "127.0.0.1"},
+       {snet: "tcp", saddr: "[::]:0", tnet: "tcp", taddr: "::1"},
 
-       {snet: "tcp", saddr: ":0", cnet: "tcp", caddr: "::1"},
-       {snet: "tcp", saddr: "0.0.0.0:0", cnet: "tcp", caddr: "::1"},
-       {snet: "tcp", saddr: "[::ffff:0.0.0.0]:0", cnet: "tcp", caddr: "::1"},
-       {snet: "tcp", saddr: "[::]:0", cnet: "tcp", caddr: "127.0.0.1"},
+       {snet: "tcp", saddr: ":0", tnet: "tcp", taddr: "::1"},
+       {snet: "tcp", saddr: "0.0.0.0:0", tnet: "tcp", taddr: "::1"},
+       {snet: "tcp", saddr: "[::ffff:0.0.0.0]:0", tnet: "tcp", taddr: "::1"},
+       {snet: "tcp", saddr: "[::]:0", tnet: "tcp", taddr: "127.0.0.1"},
 
-       {snet: "tcp", saddr: ":0", cnet: "tcp4", caddr: "127.0.0.1"},
-       {snet: "tcp", saddr: "0.0.0.0:0", cnet: "tcp4", caddr: "127.0.0.1"},
-       {snet: "tcp", saddr: "[::ffff:0.0.0.0]:0", cnet: "tcp4", caddr: "127.0.0.1"},
-       {snet: "tcp", saddr: "[::]:0", cnet: "tcp6", caddr: "::1"},
+       {snet: "tcp", saddr: ":0", tnet: "tcp4", taddr: "127.0.0.1"},
+       {snet: "tcp", saddr: "0.0.0.0:0", tnet: "tcp4", taddr: "127.0.0.1"},
+       {snet: "tcp", saddr: "[::ffff:0.0.0.0]:0", tnet: "tcp4", taddr: "127.0.0.1"},
+       {snet: "tcp", saddr: "[::]:0", tnet: "tcp6", taddr: "::1"},
 
-       {snet: "tcp", saddr: ":0", cnet: "tcp6", caddr: "::1"},
-       {snet: "tcp", saddr: "0.0.0.0:0", cnet: "tcp6", caddr: "::1"},
-       {snet: "tcp", saddr: "[::ffff:0.0.0.0]:0", cnet: "tcp6", caddr: "::1"},
-       {snet: "tcp", saddr: "[::]:0", cnet: "tcp4", caddr: "127.0.0.1"},
+       {snet: "tcp", saddr: ":0", tnet: "tcp6", taddr: "::1"},
+       {snet: "tcp", saddr: "0.0.0.0:0", tnet: "tcp6", taddr: "::1"},
+       {snet: "tcp", saddr: "[::ffff:0.0.0.0]:0", tnet: "tcp6", taddr: "::1"},
+       {snet: "tcp", saddr: "[::]:0", tnet: "tcp4", taddr: "127.0.0.1"},
 
-       {snet: "tcp", saddr: "127.0.0.1:0", cnet: "tcp", caddr: "127.0.0.1"},
-       {snet: "tcp", saddr: "[::ffff:127.0.0.1]:0", cnet: "tcp", caddr: "127.0.0.1"},
-       {snet: "tcp", saddr: "[::1]:0", cnet: "tcp", caddr: "::1"},
+       {snet: "tcp", saddr: "127.0.0.1:0", tnet: "tcp", taddr: "127.0.0.1"},
+       {snet: "tcp", saddr: "[::ffff:127.0.0.1]:0", tnet: "tcp", taddr: "127.0.0.1"},
+       {snet: "tcp", saddr: "[::1]:0", tnet: "tcp", taddr: "::1"},
 
-       {snet: "tcp4", saddr: ":0", cnet: "tcp4", caddr: "127.0.0.1"},
-       {snet: "tcp4", saddr: "0.0.0.0:0", cnet: "tcp4", caddr: "127.0.0.1"},
-       {snet: "tcp4", saddr: "[::ffff:0.0.0.0]:0", cnet: "tcp4", caddr: "127.0.0.1"},
+       {snet: "tcp4", saddr: ":0", tnet: "tcp4", taddr: "127.0.0.1"},
+       {snet: "tcp4", saddr: "0.0.0.0:0", tnet: "tcp4", taddr: "127.0.0.1"},
+       {snet: "tcp4", saddr: "[::ffff:0.0.0.0]:0", tnet: "tcp4", taddr: "127.0.0.1"},
 
-       {snet: "tcp4", saddr: "127.0.0.1:0", cnet: "tcp4", caddr: "127.0.0.1"},
+       {snet: "tcp4", saddr: "127.0.0.1:0", tnet: "tcp4", taddr: "127.0.0.1"},
 
-       {snet: "tcp6", saddr: ":0", cnet: "tcp6", caddr: "::1"},
-       {snet: "tcp6", saddr: "[::]:0", cnet: "tcp6", caddr: "::1"},
+       {snet: "tcp6", saddr: ":0", tnet: "tcp6", taddr: "::1"},
+       {snet: "tcp6", saddr: "[::]:0", tnet: "tcp6", taddr: "::1"},
 
-       {snet: "tcp6", saddr: "[::1]:0", cnet: "tcp6", caddr: "::1"},
-
-       {snet: "unix", saddr: testUnixAddr(), cnet: "unix", caddr: testUnixAddr()},
-       {snet: "unix", saddr: "@gotest2/net", cnet: "unix", caddr: "@gotest2/net.local"},
+       {snet: "tcp6", saddr: "[::1]:0", tnet: "tcp6", taddr: "::1"},
 }
 
-func TestStreamConnServer(t *testing.T) {
-       for _, tt := range streamConnServerTests {
-               if !testableListenArgs(tt.snet, tt.saddr, tt.caddr) {
-                       t.Logf("skipping %s test", tt.snet+":"+tt.saddr+"->"+tt.caddr)
+// TestTCPServer tests concurrent accept-read-write servers.
+func TestTCPServer(t *testing.T) {
+       const N = 3
+
+       for i, tt := range tcpServerTests {
+               if !testableListenArgs(tt.snet, tt.saddr, tt.taddr) {
+                       t.Logf("skipping %s test", tt.snet+":"+tt.saddr+"->"+tt.taddr)
                        continue
                }
 
-               listening := make(chan string)
-               done := make(chan int)
-               switch tt.snet {
-               case "unix":
-                       os.Remove(tt.saddr)
-                       os.Remove(tt.caddr)
+               ln, err := Listen(tt.snet, tt.saddr)
+               if err != nil {
+                       if perr := parseDialError(err); perr != nil {
+                               t.Error(perr)
+                       }
+                       t.Fatal(err)
                }
 
-               go runStreamConnServer(t, tt.snet, tt.saddr, listening, done)
-               taddr := <-listening // wait for server to start
-
-               switch tt.cnet {
-               case "tcp", "tcp4", "tcp6":
-                       _, port, err := SplitHostPort(taddr)
+               var lss []*localServer
+               var tpchs []chan error
+               for i := 0; i < N; i++ {
+                       ls, err := (&streamListener{Listener: ln}).newLocalServer()
                        if err != nil {
-                               t.Fatalf("SplitHostPort(%q) failed: %v", taddr, err)
+                               t.Fatal(err)
+                       }
+                       lss = append(lss, ls)
+                       tpchs = append(tpchs, make(chan error, 1))
+               }
+               defer func() {
+                       for _, ls := range lss {
+                               ls.teardown()
+                       }
+               }()
+               for i := 0; i < N; i++ {
+                       ch := tpchs[i]
+                       handler := func(ls *localServer, ln Listener) { transponder(ln, ch) }
+                       if err := lss[i].buildup(handler); err != nil {
+                               t.Fatal(err)
                        }
-                       taddr = JoinHostPort(tt.caddr, port)
                }
 
-               runStreamConnClient(t, tt.cnet, taddr, tt.empty)
-               <-done // make sure server stopped
+               var trchs []chan error
+               for i := 0; i < N; i++ {
+                       _, port, err := SplitHostPort(lss[i].Listener.Addr().String())
+                       if err != nil {
+                               t.Fatal(err)
+                       }
+                       d := Dialer{Timeout: someTimeout}
+                       c, err := d.Dial(tt.tnet, JoinHostPort(tt.taddr, port))
+                       if err != nil {
+                               if perr := parseDialError(err); perr != nil {
+                                       t.Error(perr)
+                               }
+                               t.Fatal(err)
+                       }
+                       defer c.Close()
+                       trchs = append(trchs, make(chan error, 1))
+                       go transceiver(c, []byte("TCP SERVER TEST"), trchs[i])
+               }
 
-               switch tt.snet {
-               case "unix":
-                       os.Remove(tt.saddr)
-                       os.Remove(tt.caddr)
+               for _, ch := range trchs {
+                       for err := range ch {
+                               t.Errorf("#%d: %v", i, err)
+                       }
+               }
+               for _, ch := range tpchs {
+                       for err := range ch {
+                               t.Errorf("#%d: %v", i, err)
+                       }
                }
        }
 }
 
-var seqpacketConnServerTests = []struct {
-       net   string
-       saddr string // server address
-       caddr string // client address
-       empty bool   // test with empty data
+var unixAndUnixpacketServerTests = []struct {
+       network, address string
 }{
-       {net: "unixpacket", saddr: testUnixAddr(), caddr: testUnixAddr()},
-       {net: "unixpacket", saddr: "@gotest4/net", caddr: "@gotest4/net.local"},
+       {"unix", testUnixAddr()},
+       {"unix", "@nettest/go/unix"},
+
+       {"unixpacket", testUnixAddr()},
+       {"unixpacket", "@nettest/go/unixpacket"},
 }
 
-func TestSeqpacketConnServer(t *testing.T) {
-       for _, tt := range seqpacketConnServerTests {
-               if !testableListenArgs(tt.net, tt.saddr, tt.caddr) {
-                       t.Logf("skipping %s test", tt.net+":"+tt.saddr+"->"+tt.caddr)
+// TestUnixAndUnixpacketServer tests concurrent accept-read-write
+// servers
+func TestUnixAndUnixpacketServer(t *testing.T) {
+       const N = 3
+
+       for i, tt := range unixAndUnixpacketServerTests {
+               if !testableListenArgs(tt.network, tt.address, "") {
+                       t.Logf("skipping %s test", tt.network+":"+tt.address+"->")
                        continue
                }
-               listening := make(chan string)
-               done := make(chan int)
-               switch tt.net {
-               case "unixpacket":
-                       os.Remove(tt.saddr)
-                       os.Remove(tt.caddr)
-               }
-
-               go runStreamConnServer(t, tt.net, tt.saddr, listening, done)
-               taddr := <-listening // wait for server to start
-
-               runStreamConnClient(t, tt.net, taddr, tt.empty)
-               <-done // make sure server stopped
 
-               switch tt.net {
-               case "unixpacket":
-                       os.Remove(tt.saddr)
-                       os.Remove(tt.caddr)
+               ln, err := Listen(tt.network, tt.address)
+               if err != nil {
+                       if perr := parseDialError(err); perr != nil {
+                               t.Error(perr)
+                       }
+                       t.Fatal(err)
                }
-       }
-}
 
-func runStreamConnServer(t *testing.T, net, laddr string, listening chan<- string, done chan<- int) {
-       defer close(done)
-       l, err := Listen(net, laddr)
-       if err != nil {
-               t.Errorf("Listen(%q, %q) failed: %v", net, laddr, err)
-               listening <- "<nil>"
-               return
-       }
-       defer l.Close()
-       listening <- l.Addr().String()
-
-       echo := func(rw io.ReadWriter, done chan<- int) {
-               buf := make([]byte, 1024)
-               for {
-                       n, err := rw.Read(buf[0:])
-                       if err != nil || n == 0 || string(buf[:n]) == "END" {
-                               break
+               var lss []*localServer
+               var tpchs []chan error
+               for i := 0; i < N; i++ {
+                       ls, err := (&streamListener{Listener: ln}).newLocalServer()
+                       if err != nil {
+                               t.Fatal(err)
                        }
-                       rw.Write(buf[0:n])
+                       lss = append(lss, ls)
+                       tpchs = append(tpchs, make(chan error, 1))
                }
-               close(done)
-       }
-
-run:
-       for {
-               c, err := l.Accept()
-               if err != nil {
-                       t.Logf("Accept failed: %v", err)
-                       continue run
+               defer func() {
+                       for _, ls := range lss {
+                               ls.teardown()
+                       }
+               }()
+               for i := 0; i < N; i++ {
+                       ch := tpchs[i]
+                       handler := func(ls *localServer, ln Listener) { transponder(ln, ch) }
+                       if err := lss[i].buildup(handler); err != nil {
+                               t.Fatal(err)
+                       }
                }
-               echodone := make(chan int)
-               go echo(c, echodone)
-               <-echodone // make sure echo stopped
-               c.Close()
-               break run
-       }
-}
 
-func runStreamConnClient(t *testing.T, net, taddr string, isEmpty bool) {
-       c, err := Dial(net, taddr)
-       if err != nil {
-               t.Fatalf("Dial(%q, %q) failed: %v", net, taddr, err)
-       }
-       defer c.Close()
-       c.SetReadDeadline(time.Now().Add(1 * time.Second))
-
-       var wb []byte
-       if !isEmpty {
-               wb = []byte("StreamConnClient by Dial\n")
-       }
-       if n, err := c.Write(wb); err != nil || n != len(wb) {
-               t.Fatalf("Write failed: %v, %v; want %v, <nil>", n, err, len(wb))
-       }
-
-       rb := make([]byte, 1024)
-       if n, err := c.Read(rb[0:]); err != nil || n != len(wb) {
-               t.Fatalf("Read failed: %v, %v; want %v, <nil>", n, err, len(wb))
-       }
+               var trchs []chan error
+               for i := 0; i < N; i++ {
+                       d := Dialer{Timeout: someTimeout}
+                       c, err := d.Dial(lss[i].Listener.Addr().Network(), lss[i].Listener.Addr().String())
+                       if err != nil {
+                               if perr := parseDialError(err); perr != nil {
+                                       t.Error(perr)
+                               }
+                               t.Fatal(err)
+                       }
+                       defer os.Remove(c.LocalAddr().String())
+                       defer c.Close()
+                       trchs = append(trchs, make(chan error, 1))
+                       go transceiver(c, []byte("UNIX AND UNIXPACKET SERVER TEST"), trchs[i])
+               }
 
-       // Send explicit ending for unixpacket.
-       // Older Linux kernels do not stop reads on close.
-       switch net {
-       case "unixpacket":
-               c.Write([]byte("END"))
+               for _, ch := range trchs {
+                       for err := range ch {
+                               t.Errorf("#%d: %v", i, err)
+                       }
+               }
+               for _, ch := range tpchs {
+                       for err := range ch {
+                               t.Errorf("#%d: %v", i, err)
+                       }
+               }
        }
 }
 
-var datagramPacketConnServerTests = []struct {
-       snet  string // server side
-       saddr string
-       cnet  string // client side
-       caddr string
-       dial  bool // test with Dial or DialUnix
-       empty bool // test with empty data
+var udpServerTests = []struct {
+       snet, saddr string // server endpoint
+       tnet, taddr string // target endpoint for client
+       dial        bool   // test with Dial
 }{
-       {snet: "udp", saddr: ":0", cnet: "udp", caddr: "127.0.0.1"},
-       {snet: "udp", saddr: "0.0.0.0:0", cnet: "udp", caddr: "127.0.0.1"},
-       {snet: "udp", saddr: "[::ffff:0.0.0.0]:0", cnet: "udp", caddr: "127.0.0.1"},
-       {snet: "udp", saddr: "[::]:0", cnet: "udp", caddr: "::1"},
-
-       {snet: "udp", saddr: ":0", cnet: "udp", caddr: "::1"},
-       {snet: "udp", saddr: "0.0.0.0:0", cnet: "udp", caddr: "::1"},
-       {snet: "udp", saddr: "[::ffff:0.0.0.0]:0", cnet: "udp", caddr: "::1"},
-       {snet: "udp", saddr: "[::]:0", cnet: "udp", caddr: "127.0.0.1"},
+       {snet: "udp", saddr: ":0", tnet: "udp", taddr: "127.0.0.1"},
+       {snet: "udp", saddr: "0.0.0.0:0", tnet: "udp", taddr: "127.0.0.1"},
+       {snet: "udp", saddr: "[::ffff:0.0.0.0]:0", tnet: "udp", taddr: "127.0.0.1"},
+       {snet: "udp", saddr: "[::]:0", tnet: "udp", taddr: "::1"},
 
-       {snet: "udp", saddr: ":0", cnet: "udp4", caddr: "127.0.0.1"},
-       {snet: "udp", saddr: "0.0.0.0:0", cnet: "udp4", caddr: "127.0.0.1"},
-       {snet: "udp", saddr: "[::ffff:0.0.0.0]:0", cnet: "udp4", caddr: "127.0.0.1"},
-       {snet: "udp", saddr: "[::]:0", cnet: "udp6", caddr: "::1"},
+       {snet: "udp", saddr: ":0", tnet: "udp", taddr: "::1"},
+       {snet: "udp", saddr: "0.0.0.0:0", tnet: "udp", taddr: "::1"},
+       {snet: "udp", saddr: "[::ffff:0.0.0.0]:0", tnet: "udp", taddr: "::1"},
+       {snet: "udp", saddr: "[::]:0", tnet: "udp", taddr: "127.0.0.1"},
 
-       {snet: "udp", saddr: ":0", cnet: "udp6", caddr: "::1"},
-       {snet: "udp", saddr: "0.0.0.0:0", cnet: "udp6", caddr: "::1"},
-       {snet: "udp", saddr: "[::ffff:0.0.0.0]:0", cnet: "udp6", caddr: "::1"},
-       {snet: "udp", saddr: "[::]:0", cnet: "udp4", caddr: "127.0.0.1"},
+       {snet: "udp", saddr: ":0", tnet: "udp4", taddr: "127.0.0.1"},
+       {snet: "udp", saddr: "0.0.0.0:0", tnet: "udp4", taddr: "127.0.0.1"},
+       {snet: "udp", saddr: "[::ffff:0.0.0.0]:0", tnet: "udp4", taddr: "127.0.0.1"},
+       {snet: "udp", saddr: "[::]:0", tnet: "udp6", taddr: "::1"},
 
-       {snet: "udp", saddr: "127.0.0.1:0", cnet: "udp", caddr: "127.0.0.1"},
-       {snet: "udp", saddr: "[::ffff:127.0.0.1]:0", cnet: "udp", caddr: "127.0.0.1"},
-       {snet: "udp", saddr: "[::1]:0", cnet: "udp", caddr: "::1"},
+       {snet: "udp", saddr: ":0", tnet: "udp6", taddr: "::1"},
+       {snet: "udp", saddr: "0.0.0.0:0", tnet: "udp6", taddr: "::1"},
+       {snet: "udp", saddr: "[::ffff:0.0.0.0]:0", tnet: "udp6", taddr: "::1"},
+       {snet: "udp", saddr: "[::]:0", tnet: "udp4", taddr: "127.0.0.1"},
 
-       {snet: "udp4", saddr: ":0", cnet: "udp4", caddr: "127.0.0.1"},
-       {snet: "udp4", saddr: "0.0.0.0:0", cnet: "udp4", caddr: "127.0.0.1"},
-       {snet: "udp4", saddr: "[::ffff:0.0.0.0]:0", cnet: "udp4", caddr: "127.0.0.1"},
+       {snet: "udp", saddr: "127.0.0.1:0", tnet: "udp", taddr: "127.0.0.1"},
+       {snet: "udp", saddr: "[::ffff:127.0.0.1]:0", tnet: "udp", taddr: "127.0.0.1"},
+       {snet: "udp", saddr: "[::1]:0", tnet: "udp", taddr: "::1"},
 
-       {snet: "udp4", saddr: "127.0.0.1:0", cnet: "udp4", caddr: "127.0.0.1"},
+       {snet: "udp4", saddr: ":0", tnet: "udp4", taddr: "127.0.0.1"},
+       {snet: "udp4", saddr: "0.0.0.0:0", tnet: "udp4", taddr: "127.0.0.1"},
+       {snet: "udp4", saddr: "[::ffff:0.0.0.0]:0", tnet: "udp4", taddr: "127.0.0.1"},
 
-       {snet: "udp6", saddr: ":0", cnet: "udp6", caddr: "::1"},
-       {snet: "udp6", saddr: "[::]:0", cnet: "udp6", caddr: "::1"},
+       {snet: "udp4", saddr: "127.0.0.1:0", tnet: "udp4", taddr: "127.0.0.1"},
 
-       {snet: "udp6", saddr: "[::1]:0", cnet: "udp6", caddr: "::1"},
+       {snet: "udp6", saddr: ":0", tnet: "udp6", taddr: "::1"},
+       {snet: "udp6", saddr: "[::]:0", tnet: "udp6", taddr: "::1"},
 
-       {snet: "udp", saddr: "127.0.0.1:0", cnet: "udp", caddr: "127.0.0.1", dial: true},
-       {snet: "udp", saddr: "127.0.0.1:0", cnet: "udp", caddr: "127.0.0.1", empty: true},
-       {snet: "udp", saddr: "127.0.0.1:0", cnet: "udp", caddr: "127.0.0.1", dial: true, empty: true},
+       {snet: "udp6", saddr: "[::1]:0", tnet: "udp6", taddr: "::1"},
 
-       {snet: "udp", saddr: "[::1]:0", cnet: "udp", caddr: "::1", dial: true},
-       {snet: "udp", saddr: "[::1]:0", cnet: "udp", caddr: "::1", empty: true},
-       {snet: "udp", saddr: "[::1]:0", cnet: "udp", caddr: "::1", dial: true, empty: true},
+       {snet: "udp", saddr: "127.0.0.1:0", tnet: "udp", taddr: "127.0.0.1", dial: true},
 
-       {snet: "unixgram", saddr: testUnixAddr(), cnet: "unixgram", caddr: testUnixAddr()},
-       {snet: "unixgram", saddr: testUnixAddr(), cnet: "unixgram", caddr: testUnixAddr(), dial: true},
-       {snet: "unixgram", saddr: testUnixAddr(), cnet: "unixgram", caddr: testUnixAddr(), empty: true},
-       {snet: "unixgram", saddr: testUnixAddr(), cnet: "unixgram", caddr: testUnixAddr(), dial: true, empty: true},
-
-       {snet: "unixgram", saddr: "@gotest6/net", cnet: "unixgram", caddr: "@gotest6/net.local"},
+       {snet: "udp", saddr: "[::1]:0", tnet: "udp", taddr: "::1", dial: true},
 }
 
-func runDatagramPacketConnServer(t *testing.T, net, laddr string, listening chan<- string, done chan<- int) {
-       c, err := ListenPacket(net, laddr)
-       if err != nil {
-               t.Errorf("ListenPacket(%q, %q) failed: %v", net, laddr, err)
-               listening <- "<nil>"
-               done <- 1
-               return
-       }
-       defer c.Close()
-       listening <- c.LocalAddr().String()
-
-       buf := make([]byte, 1024)
-run:
-       for {
-               c.SetReadDeadline(time.Now().Add(10 * time.Millisecond))
-               n, ra, err := c.ReadFrom(buf[0:])
-               if nerr, ok := err.(Error); ok && nerr.Timeout() {
-                       select {
-                       case done <- 1:
-                               break run
-                       default:
-                               continue run
+func TestUDPServer(t *testing.T) {
+       for i, tt := range udpServerTests {
+               if !testableListenArgs(tt.snet, tt.saddr, tt.taddr) {
+                       t.Logf("skipping %s test", tt.snet+":"+tt.saddr+"->"+tt.taddr)
+                       continue
+               }
+
+               c1, err := ListenPacket(tt.snet, tt.saddr)
+               if err != nil {
+                       if perr := parseDialError(err); perr != nil {
+                               t.Error(perr)
                        }
+                       t.Fatal(err)
                }
+
+               ls, err := (&packetListener{PacketConn: c1}).newLocalServer()
                if err != nil {
-                       break run
+                       t.Fatal(err)
                }
-               if _, err = c.WriteTo(buf[0:n], ra); err != nil {
-                       t.Errorf("WriteTo(%v) failed: %v", ra, err)
-                       break run
+               defer ls.teardown()
+               tpch := make(chan error, 1)
+               handler := func(ls *localPacketServer, c PacketConn) { packetTransponder(c, tpch) }
+               if err := ls.buildup(handler); err != nil {
+                       t.Fatal(err)
                }
-       }
-       done <- 1
-}
 
-func runDatagramConnClient(t *testing.T, net, laddr, taddr string, isEmpty bool) {
-       var c Conn
-       var err error
-       switch net {
-       case "udp", "udp4", "udp6":
-               c, err = Dial(net, taddr)
+               trch := make(chan error, 1)
+               _, port, err := SplitHostPort(ls.PacketConn.LocalAddr().String())
                if err != nil {
-                       t.Fatalf("Dial(%q, %q) failed: %v", net, taddr, err)
+                       t.Fatal(err)
                }
-       case "unixgram":
-               c, err = DialUnix(net, &UnixAddr{Name: laddr, Net: net}, &UnixAddr{Name: taddr, Net: net})
-               if err != nil {
-                       t.Fatalf("DialUnix(%q, {%q, %q}) failed: %v", net, laddr, taddr, err)
+               if tt.dial {
+                       d := Dialer{Timeout: someTimeout}
+                       c2, err := d.Dial(tt.tnet, JoinHostPort(tt.taddr, port))
+                       if err != nil {
+                               if perr := parseDialError(err); perr != nil {
+                                       t.Error(perr)
+                               }
+                               t.Fatal(err)
+                       }
+                       defer c2.Close()
+                       go transceiver(c2, []byte("UDP SERVER TEST"), trch)
+               } else {
+                       c2, err := ListenPacket(tt.tnet, JoinHostPort(tt.taddr, "0"))
+                       if err != nil {
+                               if perr := parseDialError(err); perr != nil {
+                                       t.Error(perr)
+                               }
+                               t.Fatal(err)
+                       }
+                       defer c2.Close()
+                       dst, err := ResolveUDPAddr(tt.tnet, JoinHostPort(tt.taddr, port))
+                       if err != nil {
+                               t.Fatal(err)
+                       }
+                       go packetTransceiver(c2, []byte("UDP SERVER TEST"), dst, trch)
                }
-       }
-       defer c.Close()
-       c.SetReadDeadline(time.Now().Add(1 * time.Second))
 
-       var wb []byte
-       if !isEmpty {
-               wb = []byte("DatagramConnClient by Dial\n")
-       }
-       if n, err := c.Write(wb[0:]); err != nil || n != len(wb) {
-               t.Fatalf("Write failed: %v, %v; want %v, <nil>", n, err, len(wb))
+               for err := range trch {
+                       t.Errorf("#%d: %v", i, err)
+               }
+               for err := range tpch {
+                       t.Errorf("#%d: %v", i, err)
+               }
        }
+}
 
-       rb := make([]byte, 1024)
-       if n, err := c.Read(rb[0:]); err != nil || n != len(wb) {
-               t.Fatalf("Read failed: %v, %v; want %v, <nil>", n, err, len(wb))
-       }
+var unixgramServerTests = []struct {
+       saddr string // server endpoint
+       caddr string // client endpoint
+       dial  bool   // test with Dial
+}{
+       {saddr: testUnixAddr(), caddr: testUnixAddr()},
+       {saddr: testUnixAddr(), caddr: testUnixAddr(), dial: true},
+
+       {saddr: "@nettest/go/unixgram/server", caddr: "@nettest/go/unixgram/client"},
 }
 
-func runDatagramPacketConnClient(t *testing.T, net, laddr, taddr string, isEmpty bool) {
-       var ra Addr
-       var err error
-       switch net {
-       case "udp", "udp4", "udp6":
-               ra, err = ResolveUDPAddr(net, taddr)
+func TestUnixgramServer(t *testing.T) {
+       for i, tt := range unixgramServerTests {
+               if !testableListenArgs("unixgram", tt.saddr, "") {
+                       t.Logf("skipping %s test", "unixgram:"+tt.saddr+"->"+tt.caddr)
+                       continue
+               }
+
+               c1, err := ListenPacket("unixgram", tt.saddr)
                if err != nil {
-                       t.Fatalf("ResolveUDPAddr(%q, %q) failed: %v", net, taddr, err)
+                       if perr := parseDialError(err); perr != nil {
+                               t.Error(perr)
+                       }
+                       t.Fatal(err)
                }
-       case "unixgram":
-               ra, err = ResolveUnixAddr(net, taddr)
+
+               ls, err := (&packetListener{PacketConn: c1}).newLocalServer()
                if err != nil {
-                       t.Fatalf("ResolveUxixAddr(%q, %q) failed: %v", net, taddr, err)
+                       t.Fatal(err)
+               }
+               defer ls.teardown()
+               tpch := make(chan error, 1)
+               handler := func(ls *localPacketServer, c PacketConn) { packetTransponder(c, tpch) }
+               if err := ls.buildup(handler); err != nil {
+                       t.Fatal(err)
                }
-       }
-       c, err := ListenPacket(net, laddr)
-       if err != nil {
-               t.Fatalf("ListenPacket(%q, %q) failed: %v", net, laddr, err)
-       }
-       defer c.Close()
-       c.SetReadDeadline(time.Now().Add(1 * time.Second))
 
-       var wb []byte
-       if !isEmpty {
-               wb = []byte("DatagramPacketConnClient by ListenPacket\n")
-       }
-       if n, err := c.WriteTo(wb[0:], ra); err != nil || n != len(wb) {
-               t.Fatalf("WriteTo(%v) failed: %v, %v; want %v, <nil>", ra, n, err, len(wb))
-       }
+               trch := make(chan error, 1)
+               if tt.dial {
+                       d := Dialer{Timeout: someTimeout, LocalAddr: &UnixAddr{Net: "unixgram", Name: tt.caddr}}
+                       c2, err := d.Dial("unixgram", ls.PacketConn.LocalAddr().String())
+                       if err != nil {
+                               if perr := parseDialError(err); perr != nil {
+                                       t.Error(perr)
+                               }
+                               t.Fatal(err)
+                       }
+                       defer os.Remove(c2.LocalAddr().String())
+                       defer c2.Close()
+                       go transceiver(c2, []byte(c2.LocalAddr().String()), trch)
+               } else {
+                       c2, err := ListenPacket("unixgram", tt.caddr)
+                       if err != nil {
+                               if perr := parseDialError(err); perr != nil {
+                                       t.Error(perr)
+                               }
+                               t.Fatal(err)
+                       }
+                       defer os.Remove(c2.LocalAddr().String())
+                       defer c2.Close()
+                       go packetTransceiver(c2, []byte("UNIXGRAM SERVER TEST"), ls.PacketConn.LocalAddr(), trch)
+               }
 
-       rb := make([]byte, 1024)
-       if n, _, err := c.ReadFrom(rb[0:]); err != nil || n != len(wb) {
-               t.Fatalf("ReadFrom failed: %v, %v; want %v, <nil>", n, err, len(wb))
+               for err := range trch {
+                       t.Errorf("#%d: %v", i, err)
+               }
+               for err := range tpch {
+                       t.Errorf("#%d: %v", i, err)
+               }
        }
 }
index 3ef22fa76f7673053efe5e9f4b946f1de6f72c46..c9a826e1068a89db0fb0250f7ff7083401808903 100644 (file)
@@ -307,15 +307,14 @@ func TestTimeoutUDP(t *testing.T) {
                t.Skipf("skipping test on %q", runtime.GOOS)
        }
 
-       // set up a listener that won't talk back
-       listening := make(chan string)
-       done := make(chan int)
-       go runDatagramPacketConnServer(t, "udp", "127.0.0.1:0", listening, done)
-       addr := <-listening
-
-       testTimeout(t, "udp", addr, false)
-       testTimeout(t, "udp", addr, true)
-       <-done
+       c, err := newLocalPacketListener("udp") // a listener that won't talk back
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       testTimeout(t, "udp", c.LocalAddr().String(), false)
+       testTimeout(t, "udp", c.LocalAddr().String(), true)
+       c.Close()
 }
 
 func TestTimeoutTCP(t *testing.T) {
@@ -324,14 +323,25 @@ func TestTimeoutTCP(t *testing.T) {
                t.Skipf("skipping test on %q", runtime.GOOS)
        }
 
-       // set up a listener that won't talk back
-       listening := make(chan string)
-       done := make(chan int)
-       go runStreamConnServer(t, "tcp", "127.0.0.1:0", listening, done)
-       addr := <-listening
+       handler := func(ls *localServer, ln Listener) { // a listener that won't talk back
+               for {
+                       c, err := ln.Accept()
+                       if err != nil {
+                               break
+                       }
+                       defer c.Close()
+               }
+       }
+       ls, err := newLocalServer("tcp")
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer ls.teardown()
+       if err := ls.buildup(handler); err != nil {
+               t.Fatal(err)
+       }
 
-       testTimeout(t, "tcp", addr, false)
-       <-done
+       testTimeout(t, "tcp", ls.Listener.Addr().String(), false)
 }
 
 func TestDeadlineReset(t *testing.T) {