]> Cypherpunks repositories - gostls13.git/commitdiff
net: improve server and file tests
authorMikio Hara <mikioh.mikioh@gmail.com>
Tue, 6 Mar 2012 00:43:45 +0000 (09:43 +0900)
committerMikio Hara <mikioh.mikioh@gmail.com>
Tue, 6 Mar 2012 00:43:45 +0000 (09:43 +0900)
* Splits into three server tests.
  - TestStreamConnServer for tcp, tcp4, tcp6 and unix networks
  - TestSeqpacketConnServer for unixpacket networks
  - TestDatagramPacketConnServer for udp, udp4, udp6 and unixgram networks
* Adds both PacketConn and Conn test clients to datagram packet conn tests.
* Fixes wildcard listen test cases on dual IP stack platform.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5701066

src/pkg/net/file_test.go
src/pkg/net/server_test.go
src/pkg/net/timeout_test.go

index 2d057ff70b67e157ad08818fde5c96153dd24c60..44e5686175c50ab594f71fbb6e81290a2952901f 100644 (file)
@@ -7,7 +7,6 @@ package net
 import (
        "os"
        "reflect"
-       "runtime"
        "testing"
 )
 
@@ -27,7 +26,8 @@ type connFile interface {
 }
 
 func testFileListener(t *testing.T, net, laddr string) {
-       if net == "tcp" {
+       switch net {
+       case "tcp", "tcp4", "tcp6":
                laddr += ":0" // any available port
        }
        l, err := Listen(net, laddr)
@@ -55,15 +55,46 @@ func testFileListener(t *testing.T, net, laddr string) {
        }
 }
 
+var fileListenerTests = []struct {
+       net   string
+       laddr string
+       ipv6  bool // test with underlying AF_INET6 socket
+       linux bool // test with abstract unix domain socket, a Linux-ism
+}{
+       {net: "tcp", laddr: ""},
+       {net: "tcp", laddr: "0.0.0.0"},
+       {net: "tcp", laddr: "[::ffff:0.0.0.0]"},
+       {net: "tcp", laddr: "[::]", ipv6: true},
+
+       {net: "tcp", laddr: "127.0.0.1"},
+       {net: "tcp", laddr: "[::ffff:127.0.0.1]"},
+       {net: "tcp", laddr: "[::1]", ipv6: true},
+
+       {net: "tcp4", laddr: ""},
+       {net: "tcp4", laddr: "0.0.0.0"},
+       {net: "tcp4", laddr: "[::ffff:0.0.0.0]"},
+
+       {net: "tcp4", laddr: "127.0.0.1"},
+       {net: "tcp4", laddr: "[::ffff:127.0.0.1]"},
+
+       {net: "tcp6", laddr: "", ipv6: true},
+       {net: "tcp6", laddr: "[::]", ipv6: true},
+
+       {net: "tcp6", laddr: "[::1]", ipv6: true},
+
+       {net: "unix", laddr: "@gotest/net", linux: true},
+       {net: "unixpacket", laddr: "@gotest/net", linux: true},
+}
+
 func TestFileListener(t *testing.T) {
-       if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
-               return
-       }
-       testFileListener(t, "tcp", "127.0.0.1")
-       testFileListener(t, "tcp", "[::ffff:127.0.0.1]")
-       if runtime.GOOS == "linux" {
-               testFileListener(t, "unix", "@gotest/net")
-               testFileListener(t, "unixpacket", "@gotest/net")
+       for _, tt := range fileListenerTests {
+               if skipServerTest(tt.net, "unix", tt.laddr, tt.ipv6, false, tt.linux) {
+                       continue
+               }
+               if skipServerTest(tt.net, "unixpacket", tt.laddr, tt.ipv6, false, tt.linux) {
+                       continue
+               }
+               testFileListener(t, tt.net, tt.laddr)
        }
 }
 
@@ -93,9 +124,13 @@ func testFilePacketConn(t *testing.T, pcf packetConnFile, listen bool) {
 }
 
 func testFilePacketConnListen(t *testing.T, net, laddr string) {
+       switch net {
+       case "udp", "udp4", "udp6":
+               laddr += ":0" // any available port
+       }
        l, err := ListenPacket(net, laddr)
        if err != nil {
-               t.Fatalf("Listen failed: %v", err)
+               t.Fatalf("ListenPacket failed: %v", err)
        }
        testFilePacketConn(t, l.(packetConnFile), true)
        if err := l.Close(); err != nil {
@@ -104,6 +139,10 @@ func testFilePacketConnListen(t *testing.T, net, laddr string) {
 }
 
 func testFilePacketConnDial(t *testing.T, net, raddr string) {
+       switch net {
+       case "udp", "udp4", "udp6":
+               raddr += ":12345"
+       }
        c, err := Dial(net, raddr)
        if err != nil {
                t.Fatalf("Dial failed: %v", err)
@@ -114,17 +153,36 @@ func testFilePacketConnDial(t *testing.T, net, raddr string) {
        }
 }
 
+var filePacketConnTests = []struct {
+       net   string
+       addr  string
+       ipv6  bool // test with underlying AF_INET6 socket
+       linux bool // test with abstract unix domain socket, a Linux-ism
+}{
+       {net: "udp", addr: "127.0.0.1"},
+       {net: "udp", addr: "[::ffff:127.0.0.1]"},
+       {net: "udp", addr: "[::1]", ipv6: true},
+
+       {net: "udp4", addr: "127.0.0.1"},
+       {net: "udp4", addr: "[::ffff:127.0.0.1]"},
+
+       {net: "udp6", addr: "[::1]", ipv6: true},
+
+       {net: "unixgram", addr: "@gotest3/net", linux: true},
+}
+
 func TestFilePacketConn(t *testing.T) {
-       if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
-               return
-       }
-       testFilePacketConnListen(t, "udp", "127.0.0.1:0")
-       testFilePacketConnDial(t, "udp", "127.0.0.1:12345")
-       testFilePacketConnDial(t, "udp", "[::ffff:127.0.0.1]:12345")
-       if supportsIPv6 {
-               testFilePacketConnListen(t, "udp", "[::1]:0")
-       }
-       if runtime.GOOS == "linux" {
-               testFilePacketConnListen(t, "unixgram", "@gotest1/net")
+       for _, tt := range filePacketConnTests {
+               if skipServerTest(tt.net, "unixgram", tt.addr, tt.ipv6, false, tt.linux) {
+                       continue
+               }
+               testFilePacketConnListen(t, tt.net, tt.addr)
+               switch tt.addr {
+               case "", "0.0.0.0", "[::ffff:0.0.0.0]", "[::]":
+               default:
+                       if tt.net != "unixgram" {
+                               testFilePacketConnDial(t, tt.net, tt.addr)
+                       }
+               }
        }
 }
index 2531e364d74b2789eaee3edeb1ace46fb925ce66..64a979634d17e93fa42d497616904f1e0d57fb04 100644 (file)
@@ -9,229 +9,460 @@ import (
        "io"
        "os"
        "runtime"
-       "strings"
        "testing"
        "time"
 )
 
-// Do not test empty datagrams by default.
-// It causes unexplained timeouts on some systems,
-// including Snow Leopard.  I think that the kernel
-// doesn't quite expect them.
-var testUDP = flag.Bool("udp", false, "whether to test UDP datagrams")
+func skipServerTest(net, unixsotype, addr string, ipv6, ipv4map, linuxonly bool) bool {
+       switch runtime.GOOS {
+       case "linux":
+       case "plan9", "windows":
+               // "unix" sockets are not supported on Windows and Plan 9.
+               if net == unixsotype {
+                       return true
+               }
+       default:
+               if net == unixsotype && linuxonly {
+                       return true
+               }
+       }
+       switch addr {
+       case "", "0.0.0.0", "[::ffff:0.0.0.0]", "[::]":
+               if avoidOSXFirewallDialogPopup() {
+                       return true
+               }
+       }
+       if ipv6 && !supportsIPv6 {
+               return true
+       }
+       if ipv4map && !supportsIPv4map {
+               return true
+       }
+       return false
+}
 
-func runEcho(fd io.ReadWriter, done chan<- int) {
-       var buf [1024]byte
+var streamConnServerTests = []struct {
+       snet    string // server side
+       saddr   string
+       cnet    string // client side
+       caddr   string
+       ipv6    bool // test with underlying AF_INET6 socket
+       ipv4map bool // test with IPv6 IPv4-mapping functionality
+       empty   bool // test with empty data
+       linux   bool // test with abstract unix domain socket, a Linux-ism
+}{
+       {snet: "tcp", saddr: "", cnet: "tcp", caddr: "127.0.0.1"},
+       {snet: "tcp", saddr: "0.0.0.0", cnet: "tcp", caddr: "127.0.0.1"},
+       {snet: "tcp", saddr: "[::ffff:0.0.0.0]", cnet: "tcp", caddr: "127.0.0.1"},
+       {snet: "tcp", saddr: "[::]", cnet: "tcp", caddr: "[::1]", ipv6: true},
 
-       for {
-               n, err := fd.Read(buf[0:])
-               if err != nil || n == 0 || string(buf[:n]) == "END" {
-                       break
+       {snet: "tcp", saddr: "", cnet: "tcp", caddr: "[::1]", ipv4map: true},
+       {snet: "tcp", saddr: "0.0.0.0", cnet: "tcp", caddr: "[::1]", ipv4map: true},
+       {snet: "tcp", saddr: "[::ffff:0.0.0.0]", cnet: "tcp", caddr: "[::1]", ipv4map: true},
+       {snet: "tcp", saddr: "[::]", cnet: "tcp", caddr: "127.0.0.1", ipv4map: true},
+
+       {snet: "tcp", saddr: "", cnet: "tcp4", caddr: "127.0.0.1"},
+       {snet: "tcp", saddr: "0.0.0.0", cnet: "tcp4", caddr: "127.0.0.1"},
+       {snet: "tcp", saddr: "[::ffff:0.0.0.0]", cnet: "tcp4", caddr: "127.0.0.1"},
+       {snet: "tcp", saddr: "[::]", cnet: "tcp6", caddr: "[::1]", ipv6: true},
+
+       {snet: "tcp", saddr: "", cnet: "tcp6", caddr: "[::1]", ipv4map: true},
+       {snet: "tcp", saddr: "0.0.0.0", cnet: "tcp6", caddr: "[::1]", ipv4map: true},
+       {snet: "tcp", saddr: "[::ffff:0.0.0.0]", cnet: "tcp6", caddr: "[::1]", ipv4map: true},
+       {snet: "tcp", saddr: "[::]", cnet: "tcp4", caddr: "127.0.0.1", ipv4map: true},
+
+       {snet: "tcp", saddr: "127.0.0.1", cnet: "tcp", caddr: "127.0.0.1"},
+       {snet: "tcp", saddr: "[::ffff:127.0.0.1]", cnet: "tcp", caddr: "127.0.0.1"},
+       {snet: "tcp", saddr: "[::1]", cnet: "tcp", caddr: "[::1]", ipv6: true},
+
+       {snet: "tcp4", saddr: "", cnet: "tcp4", caddr: "127.0.0.1"},
+       {snet: "tcp4", saddr: "0.0.0.0", cnet: "tcp4", caddr: "127.0.0.1"},
+       {snet: "tcp4", saddr: "[::ffff:0.0.0.0]", cnet: "tcp4", caddr: "127.0.0.1"},
+
+       {snet: "tcp4", saddr: "127.0.0.1", cnet: "tcp4", caddr: "127.0.0.1"},
+
+       {snet: "tcp6", saddr: "", cnet: "tcp6", caddr: "[::1]", ipv6: true},
+       {snet: "tcp6", saddr: "[::]", cnet: "tcp6", caddr: "[::1]", ipv6: true},
+
+       {snet: "tcp6", saddr: "[::1]", cnet: "tcp6", caddr: "[::1]", ipv6: true},
+
+       {snet: "unix", saddr: "/tmp/gotest1.net", cnet: "unix", caddr: "/tmp/gotest1.net.local"},
+       {snet: "unix", saddr: "@gotest2/net", cnet: "unix", caddr: "@gotest2/net.local", linux: true},
+}
+
+func TestStreamConnServer(t *testing.T) {
+       for _, tt := range streamConnServerTests {
+               if skipServerTest(tt.snet, "unix", tt.saddr, tt.ipv6, tt.ipv4map, tt.linux) {
+                       continue
+               }
+
+               listening := make(chan string)
+               done := make(chan int)
+               switch tt.snet {
+               case "tcp", "tcp4", "tcp6":
+                       tt.saddr += ":0"
+               case "unix":
+                       os.Remove(tt.saddr)
+                       os.Remove(tt.caddr)
+               }
+
+               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)
+                       if err != nil {
+                               t.Errorf("SplitHostPort(%q) failed: %v", taddr, err)
+                               return
+                       }
+                       taddr = tt.caddr + ":" + port
+               }
+
+               runStreamConnClient(t, tt.cnet, taddr, tt.empty)
+               <-done // make sure server stopped
+
+               switch tt.snet {
+               case "unix":
+                       os.Remove(tt.saddr)
+                       os.Remove(tt.caddr)
+               }
+       }
+}
+
+var seqpacketConnServerTests = []struct {
+       net   string
+       saddr string // server address
+       caddr string // client address
+       empty bool   // test with empty data
+}{
+       {net: "unixpacket", saddr: "/tmp/gotest3.net", caddr: "/tmp/gotest3.net.local"},
+       {net: "unixpacket", saddr: "@gotest4/net", caddr: "@gotest4/net.local"},
+}
+
+func TestSeqpacketConnServer(t *testing.T) {
+       if runtime.GOOS != "linux" {
+               return
+       }
+
+       for _, tt := range seqpacketConnServerTests {
+               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)
                }
-               fd.Write(buf[0:n])
        }
-       done <- 1
 }
 
-func runServe(t *testing.T, network, addr string, listening chan<- string, done chan<- int) {
-       l, err := Listen(network, addr)
+func runStreamConnServer(t *testing.T, net, laddr string, listening chan<- string, done chan<- int) {
+       l, err := Listen(net, laddr)
        if err != nil {
-               t.Fatalf("net.Listen(%q, %q) = _, %v", network, addr, err)
+               t.Errorf("Listen(%q, %q) failed: %v", net, laddr, err)
+               listening <- "<nil>"
+               done <- 1
+               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
+                       }
+                       rw.Write(buf[0:n])
+               }
+               done <- 1
+       }
+
+run:
        for {
-               fd, err := l.Accept()
+               c, err := l.Accept()
                if err != nil {
-                       break
+                       continue run
                }
                echodone := make(chan int)
-               go runEcho(fd, echodone)
-               <-echodone // make sure Echo stops
-               l.Close()
+               go echo(c, echodone)
+               <-echodone // make sure echo stopped
+               c.Close()
+               break run
        }
        done <- 1
 }
 
-func connect(t *testing.T, network, addr string, isEmpty bool) {
-       var fd Conn
-       var err error
-       if network == "unixgram" {
-               fd, err = DialUnix(network, &UnixAddr{addr + ".local", network}, &UnixAddr{addr, network})
-       } else {
-               fd, err = Dial(network, addr)
-       }
+func runStreamConnClient(t *testing.T, net, taddr string, isEmpty bool) {
+       c, err := Dial(net, taddr)
        if err != nil {
-               t.Fatalf("net.Dial(%q, %q) = _, %v", network, addr, err)
+               t.Errorf("Dial(%q, %q) failed: %v", net, taddr, err)
+               return
        }
-       fd.SetReadDeadline(time.Now().Add(1 * time.Second))
+       defer c.Close()
+       c.SetReadDeadline(time.Now().Add(1 * time.Second))
 
-       var b []byte
+       var wb []byte
        if !isEmpty {
-               b = []byte("hello, world\n")
+               wb = []byte("StreamConnClient by Dial\n")
        }
-       var b1 [100]byte
-
-       n, err1 := fd.Write(b)
-       if n != len(b) {
-               t.Fatalf("fd.Write(%q) = %d, %v", b, n, err1)
+       if n, err := c.Write(wb); err != nil || n != len(wb) {
+               t.Errorf("Write failed: %v, %v; want %v, <nil>", n, err, len(wb))
+               return
        }
 
-       n, err1 = fd.Read(b1[0:])
-       if n != len(b) || err1 != nil {
-               t.Fatalf("fd.Read() = %d, %v (want %d, nil)", n, err1, len(b))
+       rb := make([]byte, 1024)
+       if n, err := c.Read(rb[0:]); err != nil || n != len(wb) {
+               t.Errorf("Read failed: %v, %v; want %v, <nil>", n, err, len(wb))
+               return
        }
 
        // Send explicit ending for unixpacket.
        // Older Linux kernels do not stop reads on close.
-       if network == "unixpacket" {
-               fd.Write([]byte("END"))
+       switch net {
+       case "unixpacket":
+               c.Write([]byte("END"))
        }
-
-       fd.Close()
 }
 
-func doTest(t *testing.T, network, listenaddr, dialaddr string) {
-       t.Logf("Test %q %q %q", network, listenaddr, dialaddr)
-       switch listenaddr {
-       case "", "0.0.0.0", "[::]", "[::ffff:0.0.0.0]":
-               if testing.Short() || !*testExternal {
-                       t.Logf("skip wildcard listen during short test")
-                       return
-               }
-       }
-       listening := make(chan string)
-       done := make(chan int)
-       if network == "tcp" || network == "tcp4" || network == "tcp6" {
-               listenaddr += ":0" // any available port
-       }
-       go runServe(t, network, listenaddr, listening, done)
-       addr := <-listening // wait for server to start
-       if network == "tcp" || network == "tcp4" || network == "tcp6" {
-               dialaddr += addr[strings.LastIndex(addr, ":"):]
-       }
-       connect(t, network, dialaddr, false)
-       <-done // make sure server stopped
-}
+// Do not test empty datagrams by default.
+// It causes unexplained timeouts on some systems,
+// including Snow Leopard.  I think that the kernel
+// doesn't quite expect them.
+var testDatagram = flag.Bool("datagram", false, "whether to test udp and unixgram")
 
-func TestTCPServer(t *testing.T) {
-       doTest(t, "tcp", "", "127.0.0.1")
-       doTest(t, "tcp", "0.0.0.0", "127.0.0.1")
-       doTest(t, "tcp", "127.0.0.1", "127.0.0.1")
-       doTest(t, "tcp4", "", "127.0.0.1")
-       doTest(t, "tcp4", "0.0.0.0", "127.0.0.1")
-       doTest(t, "tcp4", "127.0.0.1", "127.0.0.1")
-       if supportsIPv6 {
-               doTest(t, "tcp", "[::]", "[::1]")
-               doTest(t, "tcp", "[::1]", "[::1]")
-               doTest(t, "tcp6", "", "[::1]")
-               doTest(t, "tcp6", "[::]", "[::1]")
-               doTest(t, "tcp6", "[::1]", "[::1]")
-       }
-       if supportsIPv4map {
-               doTest(t, "tcp", "[::ffff:0.0.0.0]", "127.0.0.1")
-               doTest(t, "tcp", "[::]", "127.0.0.1")
-               doTest(t, "tcp4", "[::ffff:0.0.0.0]", "127.0.0.1")
-               doTest(t, "tcp", "127.0.0.1", "[::ffff:127.0.0.1]")
-               doTest(t, "tcp", "[::ffff:127.0.0.1]", "127.0.0.1")
-               doTest(t, "tcp4", "127.0.0.1", "[::ffff:127.0.0.1]")
-               doTest(t, "tcp4", "[::ffff:127.0.0.1]", "127.0.0.1")
-       }
+var datagramPacketConnServerTests = []struct {
+       snet    string // server side
+       saddr   string
+       cnet    string // client side
+       caddr   string
+       ipv6    bool // test with underlying AF_INET6 socket
+       ipv4map bool // test with IPv6 IPv4-mapping functionality
+       dial    bool // test with Dial or DialUnix
+       empty   bool // test with empty data
+       linux   bool // test with abstract unix domain socket, a Linux-ism
+}{
+       {snet: "udp", saddr: "", cnet: "udp", caddr: "127.0.0.1"},
+       {snet: "udp", saddr: "0.0.0.0", cnet: "udp", caddr: "127.0.0.1"},
+       {snet: "udp", saddr: "[::ffff:0.0.0.0]", cnet: "udp", caddr: "127.0.0.1"},
+       {snet: "udp", saddr: "[::]", cnet: "udp", caddr: "[::1]", ipv6: true},
+
+       {snet: "udp", saddr: "", cnet: "udp", caddr: "[::1]", ipv4map: true},
+       {snet: "udp", saddr: "0.0.0.0", cnet: "udp", caddr: "[::1]", ipv4map: true},
+       {snet: "udp", saddr: "[::ffff:0.0.0.0]", cnet: "udp", caddr: "[::1]", ipv4map: true},
+       {snet: "udp", saddr: "[::]", cnet: "udp", caddr: "127.0.0.1", ipv4map: true},
+
+       {snet: "udp", saddr: "", cnet: "udp4", caddr: "127.0.0.1"},
+       {snet: "udp", saddr: "0.0.0.0", cnet: "udp4", caddr: "127.0.0.1"},
+       {snet: "udp", saddr: "[::ffff:0.0.0.0]", cnet: "udp4", caddr: "127.0.0.1"},
+       {snet: "udp", saddr: "[::]", cnet: "udp6", caddr: "[::1]", ipv6: true},
+
+       {snet: "udp", saddr: "", cnet: "udp6", caddr: "[::1]", ipv4map: true},
+       {snet: "udp", saddr: "0.0.0.0", cnet: "udp6", caddr: "[::1]", ipv4map: true},
+       {snet: "udp", saddr: "[::ffff:0.0.0.0]", cnet: "udp6", caddr: "[::1]", ipv4map: true},
+       {snet: "udp", saddr: "[::]", cnet: "udp4", caddr: "127.0.0.1", ipv4map: true},
+
+       {snet: "udp", saddr: "127.0.0.1", cnet: "udp", caddr: "127.0.0.1"},
+       {snet: "udp", saddr: "[::ffff:127.0.0.1]", cnet: "udp", caddr: "127.0.0.1"},
+       {snet: "udp", saddr: "[::1]", cnet: "udp", caddr: "[::1]", ipv6: true},
+
+       {snet: "udp4", saddr: "", cnet: "udp4", caddr: "127.0.0.1"},
+       {snet: "udp4", saddr: "0.0.0.0", cnet: "udp4", caddr: "127.0.0.1"},
+       {snet: "udp4", saddr: "[::ffff:0.0.0.0]", cnet: "udp4", caddr: "127.0.0.1"},
+
+       {snet: "udp4", saddr: "127.0.0.1", cnet: "udp4", caddr: "127.0.0.1"},
+
+       {snet: "udp6", saddr: "", cnet: "udp6", caddr: "[::1]", ipv6: true},
+       {snet: "udp6", saddr: "[::]", cnet: "udp6", caddr: "[::1]", ipv6: true},
+
+       {snet: "udp6", saddr: "[::1]", cnet: "udp6", caddr: "[::1]", ipv6: true},
+
+       {snet: "udp", saddr: "127.0.0.1", cnet: "udp", caddr: "127.0.0.1", dial: true},
+       {snet: "udp", saddr: "127.0.0.1", cnet: "udp", caddr: "127.0.0.1", empty: true},
+       {snet: "udp", saddr: "127.0.0.1", cnet: "udp", caddr: "127.0.0.1", dial: true, empty: true},
+
+       {snet: "udp", saddr: "[::1]", cnet: "udp", caddr: "[::1]", ipv6: true, dial: true},
+       {snet: "udp", saddr: "[::1]", cnet: "udp", caddr: "[::1]", ipv6: true, empty: true},
+       {snet: "udp", saddr: "[::1]", cnet: "udp", caddr: "[::1]", ipv6: true, dial: true, empty: true},
+
+       {snet: "unixgram", saddr: "/tmp/gotest5.net", cnet: "unixgram", caddr: "/tmp/gotest5.net.local"},
+       {snet: "unixgram", saddr: "/tmp/gotest5.net", cnet: "unixgram", caddr: "/tmp/gotest5.net.local", dial: true},
+       {snet: "unixgram", saddr: "/tmp/gotest5.net", cnet: "unixgram", caddr: "/tmp/gotest5.net.local", empty: true},
+       {snet: "unixgram", saddr: "/tmp/gotest5.net", cnet: "unixgram", caddr: "/tmp/gotest5.net.local", dial: true, empty: true},
+
+       {snet: "unixgram", saddr: "@gotest6/net", cnet: "unixgram", caddr: "@gotest6/net.local", linux: true},
 }
 
-func TestUnixServer(t *testing.T) {
-       // "unix" sockets are not supported on windows and Plan 9.
-       if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
+func TestDatagramPacketConnServer(t *testing.T) {
+       if !*testDatagram {
                return
        }
-       os.Remove("/tmp/gotest.net")
-       doTest(t, "unix", "/tmp/gotest.net", "/tmp/gotest.net")
-       os.Remove("/tmp/gotest.net")
-       if runtime.GOOS == "linux" {
-               doTest(t, "unixpacket", "/tmp/gotest.net", "/tmp/gotest.net")
-               os.Remove("/tmp/gotest.net")
-               // Test abstract unix domain socket, a Linux-ism
-               doTest(t, "unix", "@gotest/net", "@gotest/net")
-               doTest(t, "unixpacket", "@gotest/net", "@gotest/net")
+
+       for _, tt := range datagramPacketConnServerTests {
+               if skipServerTest(tt.snet, "unixgram", tt.saddr, tt.ipv6, tt.ipv4map, tt.linux) {
+                       continue
+               }
+
+               listening := make(chan string)
+               done := make(chan int)
+               switch tt.snet {
+               case "udp", "udp4", "udp6":
+                       tt.saddr += ":0"
+               case "unixgram":
+                       os.Remove(tt.saddr)
+                       os.Remove(tt.caddr)
+               }
+
+               go runDatagramPacketConnServer(t, tt.snet, tt.saddr, listening, done)
+               taddr := <-listening // wait for server to start
+
+               switch tt.cnet {
+               case "udp", "udp4", "udp6":
+                       _, port, err := SplitHostPort(taddr)
+                       if err != nil {
+                               t.Errorf("SplitHostPort(%q) failed: %v", taddr, err)
+                               return
+                       }
+                       taddr = tt.caddr + ":" + port
+                       tt.caddr += ":0"
+               }
+               if tt.dial {
+                       runDatagramConnClient(t, tt.cnet, tt.caddr, taddr, tt.empty)
+               } else {
+                       runDatagramPacketConnClient(t, tt.cnet, tt.caddr, taddr, tt.empty)
+               }
+               <-done // tell server to stop
+               <-done // make sure server stopped
+
+               switch tt.snet {
+               case "unixgram":
+                       os.Remove(tt.saddr)
+                       os.Remove(tt.caddr)
+               }
        }
 }
 
-func runPacket(t *testing.T, network, addr string, listening chan<- string, done chan<- int) {
-       c, err := ListenPacket(network, addr)
+func runDatagramPacketConnServer(t *testing.T, net, laddr string, listening chan<- string, done chan<- int) {
+       c, err := ListenPacket(net, laddr)
        if err != nil {
-               t.Fatalf("net.ListenPacket(%q, %q) = _, %v", network, addr, err)
+               t.Errorf("ListenPacket(%q, %q) failed: %v", net, laddr, err)
+               listening <- "<nil>"
+               done <- 1
+               return
        }
+       defer c.Close()
        listening <- c.LocalAddr().String()
-       var buf [1000]byte
-Run:
+
+       buf := make([]byte, 1024)
+run:
        for {
                c.SetReadDeadline(time.Now().Add(10 * time.Millisecond))
-               n, addr, err := c.ReadFrom(buf[0:])
-               if e, ok := err.(Error); ok && e.Timeout() {
+               n, ra, err := c.ReadFrom(buf[0:])
+               if nerr, ok := err.(Error); ok && nerr.Timeout() {
                        select {
                        case done <- 1:
-                               break Run
+                               break run
                        default:
-                               continue Run
+                               continue run
                        }
                }
                if err != nil {
-                       break
+                       break run
                }
-               if _, err = c.WriteTo(buf[0:n], addr); err != nil {
-                       t.Fatalf("WriteTo %v: %v", addr, err)
+               if _, err = c.WriteTo(buf[0:n], ra); err != nil {
+                       t.Errorf("WriteTo(%v) failed: %v", ra, err)
+                       break run
                }
        }
-       c.Close()
        done <- 1
 }
 
-func doTestPacket(t *testing.T, network, listenaddr, dialaddr string, isEmpty bool) {
-       t.Logf("TestPacket %q %q %q", network, listenaddr, dialaddr)
-       listening := make(chan string)
-       done := make(chan int)
-       if network == "udp" {
-               listenaddr += ":0" // any available port
-       }
-       go runPacket(t, network, listenaddr, listening, done)
-       addr := <-listening // wait for server to start
-       if network == "udp" {
-               dialaddr += addr[strings.LastIndex(addr, ":"):]
-       }
-       connect(t, network, dialaddr, isEmpty)
-       <-done // tell server to stop
-       <-done // wait for stop
-}
+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)
+               if err != nil {
+                       t.Errorf("Dial(%q, %q) failed: %v", net, taddr, err)
+                       return
+               }
+       case "unixgram":
+               c, err = DialUnix(net, &UnixAddr{laddr, net}, &UnixAddr{taddr, net})
+               if err != nil {
+                       t.Errorf("DialUnix(%q, {%q, %q}) failed: %v", net, laddr, taddr, err)
+                       return
+               }
+       }
+       defer c.Close()
+       c.SetReadDeadline(time.Now().Add(1 * time.Second))
 
-func TestUDPServer(t *testing.T) {
-       if !*testUDP {
+       var wb []byte
+       if !isEmpty {
+               wb = []byte("DatagramConnClient by Dial\n")
+       }
+       if n, err := c.Write(wb[0:]); err != nil || n != len(wb) {
+               t.Errorf("Write failed: %v, %v; want %v, <nil>", n, err, len(wb))
                return
        }
-       for _, isEmpty := range []bool{false, true} {
-               doTestPacket(t, "udp", "0.0.0.0", "127.0.0.1", isEmpty)
-               doTestPacket(t, "udp", "", "127.0.0.1", isEmpty)
-               if supportsIPv4map {
-                       doTestPacket(t, "udp", "[::]", "[::ffff:127.0.0.1]", isEmpty)
-                       doTestPacket(t, "udp", "[::]", "127.0.0.1", isEmpty)
-                       doTestPacket(t, "udp", "0.0.0.0", "[::ffff:127.0.0.1]", isEmpty)
-               }
+
+       rb := make([]byte, 1024)
+       if n, err := c.Read(rb[0:]); err != nil || n != len(wb) {
+               t.Errorf("Read failed: %v, %v; want %v, <nil>", n, err, len(wb))
+               return
        }
 }
 
-func TestUnixDatagramServer(t *testing.T) {
-       // "unix" sockets are not supported on windows and Plan 9.
-       if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
+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)
+               if err != nil {
+                       t.Errorf("ResolveUDPAddr(%q, %q) failed: %v", net, taddr, err)
+                       return
+               }
+       case "unixgram":
+               ra, err = ResolveUnixAddr(net, taddr)
+               if err != nil {
+                       t.Errorf("ResolveUxixAddr(%q, %q) failed: %v", net, taddr, err)
+                       return
+               }
+       }
+       c, err := ListenPacket(net, laddr)
+       if err != nil {
+               t.Errorf("ListenPacket(%q, %q) faild: %v", net, laddr, err)
                return
        }
-       for _, isEmpty := range []bool{false} {
-               os.Remove("/tmp/gotest1.net")
-               os.Remove("/tmp/gotest1.net.local")
-               doTestPacket(t, "unixgram", "/tmp/gotest1.net", "/tmp/gotest1.net", isEmpty)
-               os.Remove("/tmp/gotest1.net")
-               os.Remove("/tmp/gotest1.net.local")
-               if runtime.GOOS == "linux" {
-                       // Test abstract unix domain socket, a Linux-ism
-                       doTestPacket(t, "unixgram", "@gotest1/net", "@gotest1/net", isEmpty)
-               }
+       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.Errorf("WriteTo(%v) failed: %v, %v; want %v, <nil>", ra, n, err, len(wb))
+               return
+       }
+
+       rb := make([]byte, 1024)
+       if n, _, err := c.ReadFrom(rb[0:]); err != nil || n != len(wb) {
+               t.Errorf("ReadFrom failed: %v, %v; want %v, <nil>", n, err, len(wb))
+               return
        }
 }
index ef350f0f946f99fad4c4a996a8cc703ff3507f1f..acae7fa03ba6eb48f356b31e3fe1a3578a73857c 100644 (file)
@@ -11,13 +11,13 @@ import (
        "time"
 )
 
-func testTimeout(t *testing.T, network, addr string, readFrom bool) {
-       fd, err := Dial(network, addr)
+func testTimeout(t *testing.T, net, addr string, readFrom bool) {
+       c, err := Dial(net, addr)
        if err != nil {
-               t.Errorf("dial %s %s failed: %v", network, addr, err)
+               t.Errorf("Dial(%q, %q) failed: %v", net, addr, err)
                return
        }
-       defer fd.Close()
+       defer c.Close()
        what := "Read"
        if readFrom {
                what = "ReadFrom"
@@ -26,22 +26,22 @@ func testTimeout(t *testing.T, network, addr string, readFrom bool) {
        errc := make(chan error, 1)
        go func() {
                t0 := time.Now()
-               fd.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
+               c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
                var b [100]byte
                var n int
-               var err1 error
+               var err error
                if readFrom {
-                       n, _, err1 = fd.(PacketConn).ReadFrom(b[0:])
+                       n, _, err = c.(PacketConn).ReadFrom(b[0:])
                } else {
-                       n, err1 = fd.Read(b[0:])
+                       n, err = c.Read(b[0:])
                }
                t1 := time.Now()
-               if n != 0 || err1 == nil || !err1.(Error).Timeout() {
-                       errc <- fmt.Errorf("fd.%s on %s %s did not return 0, timeout: %v, %v", what, network, addr, n, err1)
+               if n != 0 || err == nil || !err.(Error).Timeout() {
+                       errc <- fmt.Errorf("%s(%q, %q) did not return 0, timeout: %v, %v", what, net, addr, n, err)
                        return
                }
                if dt := t1.Sub(t0); dt < 50*time.Millisecond || !testing.Short() && dt > 250*time.Millisecond {
-                       errc <- fmt.Errorf("fd.%s on %s %s took %s, expected 0.1s", what, network, addr, dt)
+                       errc <- fmt.Errorf("%s(%q, %q) took %s, expected 0.1s", what, net, addr, dt)
                        return
                }
                errc <- nil
@@ -52,7 +52,7 @@ func testTimeout(t *testing.T, network, addr string, readFrom bool) {
                        t.Error(err)
                }
        case <-time.After(1 * time.Second):
-               t.Errorf("%s on %s %s took over 1 second, expected 0.1s", what, network, addr)
+               t.Errorf("%s(%q, %q) took over 1 second, expected 0.1s", what, net, addr)
        }
 }
 
@@ -60,18 +60,27 @@ func TestTimeoutUDP(t *testing.T) {
        if runtime.GOOS == "plan9" {
                return
        }
-       testTimeout(t, "udp", "127.0.0.1:53", false)
-       testTimeout(t, "udp", "127.0.0.1:53", true)
+
+       // 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
 }
 
 func TestTimeoutTCP(t *testing.T) {
        if runtime.GOOS == "plan9" {
                return
        }
+
        // set up a listener that won't talk back
        listening := make(chan string)
        done := make(chan int)
-       go runServe(t, "tcp", "127.0.0.1:0", listening, done)
+       go runStreamConnServer(t, "tcp", "127.0.0.1:0", listening, done)
        addr := <-listening
 
        testTimeout(t, "tcp", addr, false)