]> Cypherpunks repositories - gostls13.git/commitdiff
net: deflake dual IP stack tests
authorMikio Hara <mikioh.mikioh@gmail.com>
Sun, 5 Apr 2015 08:00:14 +0000 (17:00 +0900)
committerMikio Hara <mikioh.mikioh@gmail.com>
Tue, 7 Apr 2015 13:32:28 +0000 (13:32 +0000)
This change deflakes TestDialerDualStackFDLeak, TestDialerDualStack,
TestResolve{TCP,UDP,IP}Addr by removing external dependencies.

Fixes #8764.

Change-Id: I5cca0a93776cf05652e0e6a4a4ff4af392ccb885
Reviewed-on: https://go-review.googlesource.com/8485
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/net/dial_test.go
src/net/ipraw_test.go
src/net/lookup_test.go
src/net/main_test.go
src/net/tcp_test.go
src/net/udp_test.go

index d808ae225749c6b645a0864c54d1d283cdf47e45..7b36f811a940178271912221d1da142eb8238128 100644 (file)
@@ -5,15 +5,11 @@
 package net
 
 import (
-       "bytes"
        "fmt"
        "net/internal/socktest"
-       "os"
-       "os/exec"
        "reflect"
        "regexp"
        "runtime"
-       "strconv"
        "sync"
        "testing"
        "time"
@@ -216,38 +212,27 @@ func TestDialTimeoutFDLeak(t *testing.T) {
        }
 }
 
-func numTCP() (ntcp, nopen, nclose int, err error) {
-       lsof, err := exec.Command("lsof", "-n", "-p", strconv.Itoa(os.Getpid())).Output()
-       if err != nil {
-               return 0, 0, 0, err
-       }
-       ntcp += bytes.Count(lsof, []byte("TCP"))
-       for _, state := range []string{"LISTEN", "SYN_SENT", "SYN_RECEIVED", "ESTABLISHED"} {
-               nopen += bytes.Count(lsof, []byte(state))
-       }
-       for _, state := range []string{"CLOSED", "CLOSE_WAIT", "LAST_ACK", "FIN_WAIT_1", "FIN_WAIT_2", "CLOSING", "TIME_WAIT"} {
-               nclose += bytes.Count(lsof, []byte(state))
+func TestDialerDualStackFDLeak(t *testing.T) {
+       switch runtime.GOOS {
+       case "plan9":
+               t.Skipf("%s does not have full support of socktest", runtime.GOOS)
+       case "windows":
+               t.Skipf("not implemented a way to cancel dial racers in TCP SYN-SENT state on %s", runtime.GOOS)
        }
-       return ntcp, nopen, nclose, nil
-}
-
-func TestDialMultiFDLeak(t *testing.T) {
-       t.Skip("flaky test - golang.org/issue/8764")
-
        if !supportsIPv4 || !supportsIPv6 {
-               t.Skip("neither ipv4 nor ipv6 is supported")
+               t.Skip("ipv4 or ipv6 is not supported")
        }
 
+       origTestHookLookupIP := testHookLookupIP
+       defer func() { testHookLookupIP = origTestHookLookupIP }()
+       testHookLookupIP = lookupLocalhost
        handler := func(dss *dualStackServer, ln Listener) {
                for {
-                       if c, err := ln.Accept(); err != nil {
+                       c, err := ln.Accept()
+                       if err != nil {
                                return
-                       } else {
-                               // It just keeps established
-                               // connections like a half-dead server
-                               // does.
-                               dss.putConn(c)
                        }
+                       c.Close()
                }
        }
        dss, err := newDualStackServer([]streamListener{
@@ -255,56 +240,35 @@ func TestDialMultiFDLeak(t *testing.T) {
                {network: "tcp6", address: "::1"},
        })
        if err != nil {
-               t.Fatalf("newDualStackServer failed: %v", err)
+               t.Fatal(err)
        }
        defer dss.teardown()
        if err := dss.buildup(handler); err != nil {
-               t.Fatalf("dualStackServer.buildup failed: %v", err)
-       }
-
-       _, before, _, err := numTCP()
-       if err != nil {
-               t.Skipf("skipping test; error finding or running lsof: %v", err)
+               t.Fatal(err)
        }
 
-       var wg sync.WaitGroup
-       portnum, _, _ := dtoi(dss.port, 0)
-       ras := addrList{
-               // Losers that will fail to connect, see RFC 6890.
-               &TCPAddr{IP: IPv4(198, 18, 0, 254), Port: portnum},
-               &TCPAddr{IP: ParseIP("2001:2::254"), Port: portnum},
-
-               // Winner candidates of this race.
-               &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: portnum},
-               &TCPAddr{IP: IPv6loopback, Port: portnum},
-
-               // Losers that will have established connections.
-               &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: portnum},
-               &TCPAddr{IP: IPv6loopback, Port: portnum},
-       }
-       const T1 = 10 * time.Millisecond
-       const T2 = 2 * T1
+       before := sw.Sockets()
+       const T = 100 * time.Millisecond
        const N = 10
+       var wg sync.WaitGroup
+       wg.Add(N)
+       d := &Dialer{DualStack: true, Timeout: T}
        for i := 0; i < N; i++ {
-               wg.Add(1)
                go func() {
                        defer wg.Done()
-                       if c, err := dialMulti("tcp", "fast failover test", nil, ras, time.Now().Add(T1)); err == nil {
-                               c.Close()
+                       c, err := d.Dial("tcp", JoinHostPort("localhost", dss.port))
+                       if err != nil {
+                               t.Error(err)
+                               return
                        }
+                       c.Close()
                }()
        }
        wg.Wait()
-       time.Sleep(T2)
-
-       ntcp, after, nclose, err := numTCP()
-       if err != nil {
-               t.Skipf("skipping test; error finding or running lsof: %v", err)
-       }
-       t.Logf("tcp sessions: %v, open sessions: %v, closing sessions: %v", ntcp, after, nclose)
-
-       if after != before {
-               t.Fatalf("got %v open sessions; expected %v", after, before)
+       time.Sleep(2 * T) // wait for the dial racers to stop
+       after := sw.Sockets()
+       if len(after) != len(before) {
+               t.Errorf("got %d; want %d", len(after), len(before))
        }
 }
 
@@ -347,24 +311,20 @@ func TestDialerLocalAddr(t *testing.T) {
 }
 
 func TestDialerDualStack(t *testing.T) {
-       switch runtime.GOOS {
-       case "nacl":
-               t.Skipf("skipping test on %q", runtime.GOOS)
-       }
-
-       if ips, err := LookupIP("localhost"); err != nil {
-               t.Fatalf("LookupIP failed: %v", err)
-       } else if len(ips) < 2 || !supportsIPv4 || !supportsIPv6 {
-               t.Skip("localhost doesn't have a pair of different address family IP addresses")
+       if !supportsIPv4 || !supportsIPv6 {
+               t.Skip("ipv4 or ipv6 is not supported")
        }
 
+       origTestHookLookupIP := testHookLookupIP
+       defer func() { testHookLookupIP = origTestHookLookupIP }()
+       testHookLookupIP = lookupLocalhost
        handler := func(dss *dualStackServer, ln Listener) {
                for {
-                       if c, err := ln.Accept(); err != nil {
+                       c, err := ln.Accept()
+                       if err != nil {
                                return
-                       } else {
-                               c.Close()
                        }
+                       c.Close()
                }
        }
        dss, err := newDualStackServer([]streamListener{
@@ -372,26 +332,30 @@ func TestDialerDualStack(t *testing.T) {
                {network: "tcp6", address: "::1"},
        })
        if err != nil {
-               t.Fatalf("newDualStackServer failed: %v", err)
+               t.Fatal(err)
        }
        defer dss.teardown()
        if err := dss.buildup(handler); err != nil {
-               t.Fatalf("dualStackServer.buildup failed: %v", err)
+               t.Fatal(err)
        }
 
-       d := &Dialer{DualStack: true}
+       const T = 100 * time.Millisecond
+       d := &Dialer{DualStack: true, Timeout: T}
        for range dss.lns {
-               if c, err := d.Dial("tcp", JoinHostPort("localhost", dss.port)); err != nil {
-                       t.Errorf("Dial failed: %v", err)
-               } else {
-                       if addr := c.LocalAddr().(*TCPAddr); addr.IP.To4() != nil {
-                               dss.teardownNetwork("tcp4")
-                       } else if addr.IP.To16() != nil && addr.IP.To4() == nil {
-                               dss.teardownNetwork("tcp6")
-                       }
-                       c.Close()
+               c, err := d.Dial("tcp", JoinHostPort("localhost", dss.port))
+               if err != nil {
+                       t.Error(err)
+                       continue
+               }
+               switch addr := c.LocalAddr().(*TCPAddr); {
+               case addr.IP.To4() != nil:
+                       dss.teardownNetwork("tcp4")
+               case addr.IP.To16() != nil && addr.IP.To4() == nil:
+                       dss.teardownNetwork("tcp6")
                }
+               c.Close()
        }
+       time.Sleep(2 * T) // wait for the dial racers to stop
 }
 
 func TestDialerKeepAlive(t *testing.T) {
index f93b9ef0b05bc1af837d90b6dff7a74ed9e36be1..6d917bcac8c7c283defb5a6378d298e21708b93e 100644 (file)
@@ -5,7 +5,6 @@
 package net
 
 import (
-       "fmt"
        "reflect"
        "testing"
 )
@@ -17,7 +16,7 @@ import (
 //     golang.org/x/net/icmp
 
 type resolveIPAddrTest struct {
-       net           string
+       network       string
        litAddrOrName string
        addr          *IPAddr
        err           error
@@ -44,34 +43,30 @@ var resolveIPAddrTests = []resolveIPAddrTest{
        {"tcp", "1.2.3.4:123", nil, UnknownNetworkError("tcp")},
 }
 
-func init() {
-       if ifi := loopbackInterface(); ifi != nil {
-               index := fmt.Sprintf("%v", ifi.Index)
-               resolveIPAddrTests = append(resolveIPAddrTests, []resolveIPAddrTest{
-                       {"ip6", "fe80::1%" + ifi.Name, &IPAddr{IP: ParseIP("fe80::1"), Zone: zoneToString(ifi.Index)}, nil},
-                       {"ip6", "fe80::1%" + index, &IPAddr{IP: ParseIP("fe80::1"), Zone: index}, nil},
-               }...)
-       }
-       if ips, err := LookupIP("localhost"); err == nil && len(ips) > 1 && supportsIPv4 && supportsIPv6 {
-               resolveIPAddrTests = append(resolveIPAddrTests, []resolveIPAddrTest{
-                       {"ip", "localhost", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
-                       {"ip4", "localhost", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
-                       {"ip6", "localhost", &IPAddr{IP: IPv6loopback}, nil},
-               }...)
-       }
-}
-
 func TestResolveIPAddr(t *testing.T) {
        if !testableNetwork("ip+nopriv") {
                t.Skip("ip+nopriv test")
        }
 
-       for _, tt := range resolveIPAddrTests {
-               addr, err := ResolveIPAddr(tt.net, tt.litAddrOrName)
+       origTestHookLookupIP := testHookLookupIP
+       defer func() { testHookLookupIP = origTestHookLookupIP }()
+       testHookLookupIP = lookupLocalhost
+
+       for i, tt := range resolveIPAddrTests {
+               addr, err := ResolveIPAddr(tt.network, tt.litAddrOrName)
                if err != tt.err {
-                       t.Fatalf("ResolveIPAddr(%v, %v) failed: %v", tt.net, tt.litAddrOrName, err)
+                       t.Errorf("#%d: %v", i, err)
                } else if !reflect.DeepEqual(addr, tt.addr) {
-                       t.Fatalf("got %#v; expected %#v", addr, tt.addr)
+                       t.Errorf("#%d: got %#v; want %#v", i, addr, tt.addr)
+               }
+               if err != nil {
+                       continue
+               }
+               rtaddr, err := ResolveIPAddr(addr.Network(), addr.String())
+               if err != nil {
+                       t.Errorf("#%d: %v", i, err)
+               } else if !reflect.DeepEqual(rtaddr, addr) {
+                       t.Errorf("#%d: got %#v; want %#v", i, rtaddr, addr)
                }
        }
 }
index 658b32a885f77edb1db974c659d8c4a462a2b188..ad55f31cb3c7a384d83ca7763e9891a1c9baa96e 100644 (file)
@@ -2,9 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// TODO It would be nice to use a mock DNS server, to eliminate
-// external dependencies.
-
 package net
 
 import (
@@ -14,6 +11,18 @@ import (
        "time"
 )
 
+func lookupLocalhost(fn func(string) ([]IPAddr, error), host string) ([]IPAddr, error) {
+       switch host {
+       case "localhost":
+               return []IPAddr{
+                       {IP: IPv4(127, 0, 0, 1)},
+                       {IP: IPv6loopback},
+               }, nil
+       default:
+               return fn(host)
+       }
+}
+
 var lookupGoogleSRVTests = []struct {
        service, proto, name string
        cname, target        string
index ac56d31a2526ec310a2f29162c389da595e2b16c..e9d14658f43c63a18a425db34dc7d506fcf1282e 100644 (file)
@@ -48,6 +48,7 @@ var (
 )
 
 func TestMain(m *testing.M) {
+       setupTestData()
        installTestHooks()
 
        st := m.Run()
@@ -62,6 +63,45 @@ func TestMain(m *testing.M) {
        os.Exit(st)
 }
 
+func setupTestData() {
+       if supportsIPv4 {
+               resolveTCPAddrTests = append(resolveTCPAddrTests, []resolveTCPAddrTest{
+                       {"tcp", "localhost:1", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 1}, nil},
+                       {"tcp4", "localhost:2", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 2}, nil},
+               }...)
+               resolveUDPAddrTests = append(resolveUDPAddrTests, []resolveUDPAddrTest{
+                       {"udp", "localhost:1", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 1}, nil},
+                       {"udp4", "localhost:2", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 2}, nil},
+               }...)
+               resolveIPAddrTests = append(resolveIPAddrTests, []resolveIPAddrTest{
+                       {"ip", "localhost", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
+                       {"ip4", "localhost", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
+               }...)
+       }
+
+       if supportsIPv6 {
+               resolveTCPAddrTests = append(resolveTCPAddrTests, resolveTCPAddrTest{"tcp6", "localhost:3", &TCPAddr{IP: IPv6loopback, Port: 3}, nil})
+               resolveUDPAddrTests = append(resolveUDPAddrTests, resolveUDPAddrTest{"udp6", "localhost:3", &UDPAddr{IP: IPv6loopback, Port: 3}, nil})
+               resolveIPAddrTests = append(resolveIPAddrTests, resolveIPAddrTest{"ip6", "localhost", &IPAddr{IP: IPv6loopback}, nil})
+       }
+
+       if ifi := loopbackInterface(); ifi != nil {
+               index := fmt.Sprintf("%v", ifi.Index)
+               resolveTCPAddrTests = append(resolveTCPAddrTests, []resolveTCPAddrTest{
+                       {"tcp6", "[fe80::1%" + ifi.Name + "]:1", &TCPAddr{IP: ParseIP("fe80::1"), Port: 1, Zone: zoneToString(ifi.Index)}, nil},
+                       {"tcp6", "[fe80::1%" + index + "]:2", &TCPAddr{IP: ParseIP("fe80::1"), Port: 2, Zone: index}, nil},
+               }...)
+               resolveUDPAddrTests = append(resolveUDPAddrTests, []resolveUDPAddrTest{
+                       {"udp6", "[fe80::1%" + ifi.Name + "]:1", &UDPAddr{IP: ParseIP("fe80::1"), Port: 1, Zone: zoneToString(ifi.Index)}, nil},
+                       {"udp6", "[fe80::1%" + index + "]:2", &UDPAddr{IP: ParseIP("fe80::1"), Port: 2, Zone: index}, nil},
+               }...)
+               resolveIPAddrTests = append(resolveIPAddrTests, []resolveIPAddrTest{
+                       {"ip6", "fe80::1%" + ifi.Name, &IPAddr{IP: ParseIP("fe80::1"), Zone: zoneToString(ifi.Index)}, nil},
+                       {"ip6", "fe80::1%" + index, &IPAddr{IP: ParseIP("fe80::1"), Zone: index}, nil},
+               }...)
+       }
+}
+
 func printLeakedGoroutines() {
        gss := leakedGoroutines()
        if len(gss) == 0 {
index 299135728881a4d5f857afec6b4576e25c23b535..9b2c8b3cd3945c30f7352b59421adbaae2c0d800 100644 (file)
@@ -5,7 +5,6 @@
 package net
 
 import (
-       "fmt"
        "io"
        "reflect"
        "runtime"
@@ -288,7 +287,7 @@ func benchmarkTCPConcurrentReadWrite(b *testing.B, laddr string) {
 }
 
 type resolveTCPAddrTest struct {
-       net           string
+       network       string
        litAddrOrName string
        addr          *TCPAddr
        err           error
@@ -298,8 +297,8 @@ var resolveTCPAddrTests = []resolveTCPAddrTest{
        {"tcp", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil},
        {"tcp4", "127.0.0.1:65535", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 65535}, nil},
 
-       {"tcp", "[::1]:1", &TCPAddr{IP: ParseIP("::1"), Port: 1}, nil},
-       {"tcp6", "[::1]:65534", &TCPAddr{IP: ParseIP("::1"), Port: 65534}, nil},
+       {"tcp", "[::1]:0", &TCPAddr{IP: ParseIP("::1"), Port: 0}, nil},
+       {"tcp6", "[::1]:65535", &TCPAddr{IP: ParseIP("::1"), Port: 65535}, nil},
 
        {"tcp", "[::1%en0]:1", &TCPAddr{IP: ParseIP("::1"), Port: 1, Zone: "en0"}, nil},
        {"tcp6", "[::1%911]:2", &TCPAddr{IP: ParseIP("::1"), Port: 2, Zone: "911"}, nil},
@@ -312,41 +311,26 @@ var resolveTCPAddrTests = []resolveTCPAddrTest{
        {"http", "127.0.0.1:0", nil, UnknownNetworkError("http")},
 }
 
-func init() {
-       if ifi := loopbackInterface(); ifi != nil {
-               index := fmt.Sprintf("%v", ifi.Index)
-               resolveTCPAddrTests = append(resolveTCPAddrTests, []resolveTCPAddrTest{
-                       {"tcp6", "[fe80::1%" + ifi.Name + "]:3", &TCPAddr{IP: ParseIP("fe80::1"), Port: 3, Zone: zoneToString(ifi.Index)}, nil},
-                       {"tcp6", "[fe80::1%" + index + "]:4", &TCPAddr{IP: ParseIP("fe80::1"), Port: 4, Zone: index}, nil},
-               }...)
-       }
-       if ips, err := LookupIP("localhost"); err == nil && len(ips) > 1 && supportsIPv4 && supportsIPv6 {
-               resolveTCPAddrTests = append(resolveTCPAddrTests, []resolveTCPAddrTest{
-                       {"tcp", "localhost:5", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5}, nil},
-                       {"tcp4", "localhost:6", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 6}, nil},
-                       {"tcp6", "localhost:7", &TCPAddr{IP: IPv6loopback, Port: 7}, nil},
-               }...)
-       }
-}
-
 func TestResolveTCPAddr(t *testing.T) {
-       for _, tt := range resolveTCPAddrTests {
-               addr, err := ResolveTCPAddr(tt.net, tt.litAddrOrName)
+       origTestHookLookupIP := testHookLookupIP
+       defer func() { testHookLookupIP = origTestHookLookupIP }()
+       testHookLookupIP = lookupLocalhost
+
+       for i, tt := range resolveTCPAddrTests {
+               addr, err := ResolveTCPAddr(tt.network, tt.litAddrOrName)
                if err != tt.err {
-                       t.Fatalf("ResolveTCPAddr(%q, %q) failed: %v", tt.net, tt.litAddrOrName, err)
+                       t.Errorf("#%d: %v", i, err)
+               } else if !reflect.DeepEqual(addr, tt.addr) {
+                       t.Errorf("#%d: got %#v; want %#v", i, addr, tt.addr)
                }
-               if !reflect.DeepEqual(addr, tt.addr) {
-                       t.Fatalf("ResolveTCPAddr(%q, %q) = %#v, want %#v", tt.net, tt.litAddrOrName, addr, tt.addr)
+               if err != nil {
+                       continue
                }
-               if err == nil {
-                       str := addr.String()
-                       addr1, err := ResolveTCPAddr(tt.net, str)
-                       if err != nil {
-                               t.Fatalf("ResolveTCPAddr(%q, %q) [from %q]: %v", tt.net, str, tt.litAddrOrName, err)
-                       }
-                       if !reflect.DeepEqual(addr1, addr) {
-                               t.Fatalf("ResolveTCPAddr(%q, %q) [from %q] = %#v, want %#v", tt.net, str, tt.litAddrOrName, addr1, addr)
-                       }
+               rtaddr, err := ResolveTCPAddr(addr.Network(), addr.String())
+               if err != nil {
+                       t.Errorf("#%d: %v", i, err)
+               } else if !reflect.DeepEqual(rtaddr, addr) {
+                       t.Errorf("#%d: got %#v; want %#v", i, rtaddr, addr)
                }
        }
 }
index 2be2c319a70dbb98d07cce81331e013f5ce4b879..6f689b67f3bb53b0bf789441f335004cb92b4eb1 100644 (file)
@@ -7,30 +7,55 @@ package net
 import (
        "reflect"
        "runtime"
-       "strings"
        "testing"
        "time"
 )
 
+type resolveUDPAddrTest struct {
+       network       string
+       litAddrOrName string
+       addr          *UDPAddr
+       err           error
+}
+
+var resolveUDPAddrTests = []resolveUDPAddrTest{
+       {"udp", "127.0.0.1:0", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil},
+       {"udp4", "127.0.0.1:65535", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 65535}, nil},
+
+       {"udp", "[::1]:0", &UDPAddr{IP: ParseIP("::1"), Port: 0}, nil},
+       {"udp6", "[::1]:65535", &UDPAddr{IP: ParseIP("::1"), Port: 65535}, nil},
+
+       {"udp", "[::1%en0]:1", &UDPAddr{IP: ParseIP("::1"), Port: 1, Zone: "en0"}, nil},
+       {"udp6", "[::1%911]:2", &UDPAddr{IP: ParseIP("::1"), Port: 2, Zone: "911"}, nil},
+
+       {"", "127.0.0.1:0", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, // Go 1.0 behavior
+       {"", "[::1]:0", &UDPAddr{IP: ParseIP("::1"), Port: 0}, nil},         // Go 1.0 behavior
+
+       {"udp", ":12345", &UDPAddr{Port: 12345}, nil},
+
+       {"http", "127.0.0.1:0", nil, UnknownNetworkError("http")},
+}
+
 func TestResolveUDPAddr(t *testing.T) {
-       for _, tt := range resolveTCPAddrTests {
-               net := strings.Replace(tt.net, "tcp", "udp", -1)
-               addr, err := ResolveUDPAddr(net, tt.litAddrOrName)
+       origTestHookLookupIP := testHookLookupIP
+       defer func() { testHookLookupIP = origTestHookLookupIP }()
+       testHookLookupIP = lookupLocalhost
+
+       for i, tt := range resolveUDPAddrTests {
+               addr, err := ResolveUDPAddr(tt.network, tt.litAddrOrName)
                if err != tt.err {
-                       t.Fatalf("ResolveUDPAddr(%q, %q) failed: %v", net, tt.litAddrOrName, err)
+                       t.Errorf("#%d: %v", i, err)
+               } else if !reflect.DeepEqual(addr, tt.addr) {
+                       t.Errorf("#%d: got %#v; want %#v", i, addr, tt.addr)
                }
-               if !reflect.DeepEqual(addr, (*UDPAddr)(tt.addr)) {
-                       t.Fatalf("ResolveUDPAddr(%q, %q) = %#v, want %#v", net, tt.litAddrOrName, addr, tt.addr)
+               if err != nil {
+                       continue
                }
-               if err == nil {
-                       str := addr.String()
-                       addr1, err := ResolveUDPAddr(net, str)
-                       if err != nil {
-                               t.Fatalf("ResolveUDPAddr(%q, %q) [from %q]: %v", net, str, tt.litAddrOrName, err)
-                       }
-                       if !reflect.DeepEqual(addr1, addr) {
-                               t.Fatalf("ResolveUDPAddr(%q, %q) [from %q] = %#v, want %#v", net, str, tt.litAddrOrName, addr1, addr)
-                       }
+               rtaddr, err := ResolveUDPAddr(addr.Network(), addr.String())
+               if err != nil {
+                       t.Errorf("#%d: %v", i, err)
+               } else if !reflect.DeepEqual(rtaddr, addr) {
+                       t.Errorf("#%d: got %#v; want %#v", i, rtaddr, addr)
                }
        }
 }