1// Copyright 2015 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.
4
5// +build !js
6
7package net
8
9import (
10	"context"
11	"fmt"
12	"internal/poll"
13	"io"
14	"io/ioutil"
15	"net/internal/socktest"
16	"os"
17	"runtime"
18	"strings"
19	"testing"
20	"time"
21)
22
23func (e *OpError) isValid() error {
24	if e.Op == "" {
25		return fmt.Errorf("OpError.Op is empty: %v", e)
26	}
27	if e.Net == "" {
28		return fmt.Errorf("OpError.Net is empty: %v", e)
29	}
30	for _, addr := range []Addr{e.Source, e.Addr} {
31		switch addr := addr.(type) {
32		case nil:
33		case *TCPAddr:
34			if addr == nil {
35				return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
36			}
37		case *UDPAddr:
38			if addr == nil {
39				return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
40			}
41		case *IPAddr:
42			if addr == nil {
43				return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
44			}
45		case *IPNet:
46			if addr == nil {
47				return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
48			}
49		case *UnixAddr:
50			if addr == nil {
51				return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
52			}
53		case *pipeAddr:
54			if addr == nil {
55				return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
56			}
57		case fileAddr:
58			if addr == "" {
59				return fmt.Errorf("OpError.Source or Addr is empty: %#v, %v", addr, e)
60			}
61		default:
62			return fmt.Errorf("OpError.Source or Addr is unknown type: %T, %v", addr, e)
63		}
64	}
65	if e.Err == nil {
66		return fmt.Errorf("OpError.Err is empty: %v", e)
67	}
68	return nil
69}
70
71// parseDialError parses nestedErr and reports whether it is a valid
72// error value from Dial, Listen functions.
73// It returns nil when nestedErr is valid.
74func parseDialError(nestedErr error) error {
75	if nestedErr == nil {
76		return nil
77	}
78
79	switch err := nestedErr.(type) {
80	case *OpError:
81		if err := err.isValid(); err != nil {
82			return err
83		}
84		nestedErr = err.Err
85		goto second
86	}
87	return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
88
89second:
90	if isPlatformError(nestedErr) {
91		return nil
92	}
93	switch err := nestedErr.(type) {
94	case *AddrError, addrinfoErrno, *DNSError, InvalidAddrError, *ParseError, *poll.TimeoutError, UnknownNetworkError:
95		return nil
96	case *os.SyscallError:
97		nestedErr = err.Err
98		goto third
99	case *os.PathError: // for Plan 9
100		nestedErr = err.Err
101		goto third
102	}
103	switch nestedErr {
104	case errCanceled, poll.ErrNetClosing, errMissingAddress, errNoSuitableAddress,
105		context.DeadlineExceeded, context.Canceled:
106		return nil
107	}
108	return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
109
110third:
111	if isPlatformError(nestedErr) {
112		return nil
113	}
114	return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
115}
116
117var dialErrorTests = []struct {
118	network, address string
119}{
120	{"foo", ""},
121	{"bar", "baz"},
122	{"datakit", "mh/astro/r70"},
123	{"tcp", ""},
124	{"tcp", "127.0.0.1:☺"},
125	{"tcp", "no-such-name:80"},
126	{"tcp", "mh/astro/r70:http"},
127
128	{"tcp", JoinHostPort("127.0.0.1", "-1")},
129	{"tcp", JoinHostPort("127.0.0.1", "123456789")},
130	{"udp", JoinHostPort("127.0.0.1", "-1")},
131	{"udp", JoinHostPort("127.0.0.1", "123456789")},
132	{"ip:icmp", "127.0.0.1"},
133
134	{"unix", "/path/to/somewhere"},
135	{"unixgram", "/path/to/somewhere"},
136	{"unixpacket", "/path/to/somewhere"},
137}
138
139func TestDialError(t *testing.T) {
140	switch runtime.GOOS {
141	case "plan9":
142		t.Skipf("%s does not have full support of socktest", runtime.GOOS)
143	}
144
145	origTestHookLookupIP := testHookLookupIP
146	defer func() { testHookLookupIP = origTestHookLookupIP }()
147	testHookLookupIP = func(ctx context.Context, fn func(context.Context, string, string) ([]IPAddr, error), network, host string) ([]IPAddr, error) {
148		return nil, &DNSError{Err: "dial error test", Name: "name", Server: "server", IsTimeout: true}
149	}
150	sw.Set(socktest.FilterConnect, func(so *socktest.Status) (socktest.AfterFilter, error) {
151		return nil, errOpNotSupported
152	})
153	defer sw.Set(socktest.FilterConnect, nil)
154
155	d := Dialer{Timeout: someTimeout}
156	for i, tt := range dialErrorTests {
157		c, err := d.Dial(tt.network, tt.address)
158		if err == nil {
159			t.Errorf("#%d: should fail; %s:%s->%s", i, c.LocalAddr().Network(), c.LocalAddr(), c.RemoteAddr())
160			c.Close()
161			continue
162		}
163		if tt.network == "tcp" || tt.network == "udp" {
164			nerr := err
165			if op, ok := nerr.(*OpError); ok {
166				nerr = op.Err
167			}
168			if sys, ok := nerr.(*os.SyscallError); ok {
169				nerr = sys.Err
170			}
171			if nerr == errOpNotSupported {
172				t.Errorf("#%d: should fail without %v; %s:%s->", i, nerr, tt.network, tt.address)
173				continue
174			}
175		}
176		if c != nil {
177			t.Errorf("Dial returned non-nil interface %T(%v) with err != nil", c, c)
178		}
179		if err = parseDialError(err); err != nil {
180			t.Errorf("#%d: %v", i, err)
181			continue
182		}
183	}
184}
185
186func TestProtocolDialError(t *testing.T) {
187	switch runtime.GOOS {
188	case "solaris", "illumos":
189		t.Skipf("not supported on %s", runtime.GOOS)
190	}
191
192	for _, network := range []string{"tcp", "udp", "ip:4294967296", "unix", "unixpacket", "unixgram"} {
193		var err error
194		switch network {
195		case "tcp":
196			_, err = DialTCP(network, nil, &TCPAddr{Port: 1 << 16})
197		case "udp":
198			_, err = DialUDP(network, nil, &UDPAddr{Port: 1 << 16})
199		case "ip:4294967296":
200			_, err = DialIP(network, nil, nil)
201		case "unix", "unixpacket", "unixgram":
202			_, err = DialUnix(network, nil, &UnixAddr{Name: "//"})
203		}
204		if err == nil {
205			t.Errorf("%s: should fail", network)
206			continue
207		}
208		if err = parseDialError(err); err != nil {
209			t.Errorf("%s: %v", network, err)
210			continue
211		}
212	}
213}
214
215func TestDialAddrError(t *testing.T) {
216	switch runtime.GOOS {
217	case "plan9":
218		t.Skipf("not supported on %s", runtime.GOOS)
219	}
220	if !supportsIPv4() || !supportsIPv6() {
221		t.Skip("both IPv4 and IPv6 are required")
222	}
223
224	for _, tt := range []struct {
225		network string
226		lit     string
227		addr    *TCPAddr
228	}{
229		{"tcp4", "::1", nil},
230		{"tcp4", "", &TCPAddr{IP: IPv6loopback}},
231		// We don't test the {"tcp6", "byte sequence", nil}
232		// case for now because there is no easy way to
233		// control name resolution.
234		{"tcp6", "", &TCPAddr{IP: IP{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}}},
235	} {
236		var err error
237		var c Conn
238		var op string
239		if tt.lit != "" {
240			c, err = Dial(tt.network, JoinHostPort(tt.lit, "0"))
241			op = fmt.Sprintf("Dial(%q, %q)", tt.network, JoinHostPort(tt.lit, "0"))
242		} else {
243			c, err = DialTCP(tt.network, nil, tt.addr)
244			op = fmt.Sprintf("DialTCP(%q, %q)", tt.network, tt.addr)
245		}
246		if err == nil {
247			c.Close()
248			t.Errorf("%s succeeded, want error", op)
249			continue
250		}
251		if perr := parseDialError(err); perr != nil {
252			t.Errorf("%s: %v", op, perr)
253			continue
254		}
255		operr := err.(*OpError).Err
256		aerr, ok := operr.(*AddrError)
257		if !ok {
258			t.Errorf("%s: %v is %T, want *AddrError", op, err, operr)
259			continue
260		}
261		want := tt.lit
262		if tt.lit == "" {
263			want = tt.addr.IP.String()
264		}
265		if aerr.Addr != want {
266			t.Errorf("%s: %v, error Addr=%q, want %q", op, err, aerr.Addr, want)
267		}
268	}
269}
270
271var listenErrorTests = []struct {
272	network, address string
273}{
274	{"foo", ""},
275	{"bar", "baz"},
276	{"datakit", "mh/astro/r70"},
277	{"tcp", "127.0.0.1:☺"},
278	{"tcp", "no-such-name:80"},
279	{"tcp", "mh/astro/r70:http"},
280
281	{"tcp", JoinHostPort("127.0.0.1", "-1")},
282	{"tcp", JoinHostPort("127.0.0.1", "123456789")},
283
284	{"unix", "/path/to/somewhere"},
285	{"unixpacket", "/path/to/somewhere"},
286}
287
288func TestListenError(t *testing.T) {
289	switch runtime.GOOS {
290	case "plan9":
291		t.Skipf("%s does not have full support of socktest", runtime.GOOS)
292	}
293
294	origTestHookLookupIP := testHookLookupIP
295	defer func() { testHookLookupIP = origTestHookLookupIP }()
296	testHookLookupIP = func(_ context.Context, fn func(context.Context, string, string) ([]IPAddr, error), network, host string) ([]IPAddr, error) {
297		return nil, &DNSError{Err: "listen error test", Name: "name", Server: "server", IsTimeout: true}
298	}
299	sw.Set(socktest.FilterListen, func(so *socktest.Status) (socktest.AfterFilter, error) {
300		return nil, errOpNotSupported
301	})
302	defer sw.Set(socktest.FilterListen, nil)
303
304	for i, tt := range listenErrorTests {
305		ln, err := Listen(tt.network, tt.address)
306		if err == nil {
307			t.Errorf("#%d: should fail; %s:%s->", i, ln.Addr().Network(), ln.Addr())
308			ln.Close()
309			continue
310		}
311		if tt.network == "tcp" {
312			nerr := err
313			if op, ok := nerr.(*OpError); ok {
314				nerr = op.Err
315			}
316			if sys, ok := nerr.(*os.SyscallError); ok {
317				nerr = sys.Err
318			}
319			if nerr == errOpNotSupported {
320				t.Errorf("#%d: should fail without %v; %s:%s->", i, nerr, tt.network, tt.address)
321				continue
322			}
323		}
324		if ln != nil {
325			t.Errorf("Listen returned non-nil interface %T(%v) with err != nil", ln, ln)
326		}
327		if err = parseDialError(err); err != nil {
328			t.Errorf("#%d: %v", i, err)
329			continue
330		}
331	}
332}
333
334var listenPacketErrorTests = []struct {
335	network, address string
336}{
337	{"foo", ""},
338	{"bar", "baz"},
339	{"datakit", "mh/astro/r70"},
340	{"udp", "127.0.0.1:☺"},
341	{"udp", "no-such-name:80"},
342	{"udp", "mh/astro/r70:http"},
343
344	{"udp", JoinHostPort("127.0.0.1", "-1")},
345	{"udp", JoinHostPort("127.0.0.1", "123456789")},
346}
347
348func TestListenPacketError(t *testing.T) {
349	switch runtime.GOOS {
350	case "plan9":
351		t.Skipf("%s does not have full support of socktest", runtime.GOOS)
352	}
353
354	origTestHookLookupIP := testHookLookupIP
355	defer func() { testHookLookupIP = origTestHookLookupIP }()
356	testHookLookupIP = func(_ context.Context, fn func(context.Context, string, string) ([]IPAddr, error), network, host string) ([]IPAddr, error) {
357		return nil, &DNSError{Err: "listen error test", Name: "name", Server: "server", IsTimeout: true}
358	}
359
360	for i, tt := range listenPacketErrorTests {
361		c, err := ListenPacket(tt.network, tt.address)
362		if err == nil {
363			t.Errorf("#%d: should fail; %s:%s->", i, c.LocalAddr().Network(), c.LocalAddr())
364			c.Close()
365			continue
366		}
367		if c != nil {
368			t.Errorf("ListenPacket returned non-nil interface %T(%v) with err != nil", c, c)
369		}
370		if err = parseDialError(err); err != nil {
371			t.Errorf("#%d: %v", i, err)
372			continue
373		}
374	}
375}
376
377func TestProtocolListenError(t *testing.T) {
378	switch runtime.GOOS {
379	case "plan9":
380		t.Skipf("not supported on %s", runtime.GOOS)
381	}
382
383	for _, network := range []string{"tcp", "udp", "ip:4294967296", "unix", "unixpacket", "unixgram"} {
384		var err error
385		switch network {
386		case "tcp":
387			_, err = ListenTCP(network, &TCPAddr{Port: 1 << 16})
388		case "udp":
389			_, err = ListenUDP(network, &UDPAddr{Port: 1 << 16})
390		case "ip:4294967296":
391			_, err = ListenIP(network, nil)
392		case "unix", "unixpacket":
393			_, err = ListenUnix(network, &UnixAddr{Name: "//"})
394		case "unixgram":
395			_, err = ListenUnixgram(network, &UnixAddr{Name: "//"})
396		}
397		if err == nil {
398			t.Errorf("%s: should fail", network)
399			continue
400		}
401		if err = parseDialError(err); err != nil {
402			t.Errorf("%s: %v", network, err)
403			continue
404		}
405	}
406}
407
408// parseReadError parses nestedErr and reports whether it is a valid
409// error value from Read functions.
410// It returns nil when nestedErr is valid.
411func parseReadError(nestedErr error) error {
412	if nestedErr == nil {
413		return nil
414	}
415
416	switch err := nestedErr.(type) {
417	case *OpError:
418		if err := err.isValid(); err != nil {
419			return err
420		}
421		nestedErr = err.Err
422		goto second
423	}
424	if nestedErr == io.EOF {
425		return nil
426	}
427	return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
428
429second:
430	if isPlatformError(nestedErr) {
431		return nil
432	}
433	switch err := nestedErr.(type) {
434	case *os.SyscallError:
435		nestedErr = err.Err
436		goto third
437	}
438	switch nestedErr {
439	case poll.ErrNetClosing, poll.ErrTimeout, poll.ErrNotPollable:
440		return nil
441	}
442	return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
443
444third:
445	if isPlatformError(nestedErr) {
446		return nil
447	}
448	return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
449}
450
451// parseWriteError parses nestedErr and reports whether it is a valid
452// error value from Write functions.
453// It returns nil when nestedErr is valid.
454func parseWriteError(nestedErr error) error {
455	if nestedErr == nil {
456		return nil
457	}
458
459	switch err := nestedErr.(type) {
460	case *OpError:
461		if err := err.isValid(); err != nil {
462			return err
463		}
464		nestedErr = err.Err
465		goto second
466	}
467	return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
468
469second:
470	if isPlatformError(nestedErr) {
471		return nil
472	}
473	switch err := nestedErr.(type) {
474	case *AddrError, addrinfoErrno, *DNSError, InvalidAddrError, *ParseError, *poll.TimeoutError, UnknownNetworkError:
475		return nil
476	case *os.SyscallError:
477		nestedErr = err.Err
478		goto third
479	}
480	switch nestedErr {
481	case errCanceled, poll.ErrNetClosing, errMissingAddress, poll.ErrTimeout, ErrWriteToConnected, io.ErrUnexpectedEOF:
482		return nil
483	}
484	return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
485
486third:
487	if isPlatformError(nestedErr) {
488		return nil
489	}
490	return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
491}
492
493// parseCloseError parses nestedErr and reports whether it is a valid
494// error value from Close functions.
495// It returns nil when nestedErr is valid.
496func parseCloseError(nestedErr error, isShutdown bool) error {
497	if nestedErr == nil {
498		return nil
499	}
500
501	// Because historically we have not exported the error that we
502	// return for an operation on a closed network connection,
503	// there are programs that test for the exact error string.
504	// Verify that string here so that we don't break those
505	// programs unexpectedly. See issues #4373 and #19252.
506	want := "use of closed network connection"
507	if !isShutdown && !strings.Contains(nestedErr.Error(), want) {
508		return fmt.Errorf("error string %q does not contain expected string %q", nestedErr, want)
509	}
510
511	switch err := nestedErr.(type) {
512	case *OpError:
513		if err := err.isValid(); err != nil {
514			return err
515		}
516		nestedErr = err.Err
517		goto second
518	}
519	return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
520
521second:
522	if isPlatformError(nestedErr) {
523		return nil
524	}
525	switch err := nestedErr.(type) {
526	case *os.SyscallError:
527		nestedErr = err.Err
528		goto third
529	case *os.PathError: // for Plan 9
530		nestedErr = err.Err
531		goto third
532	}
533	switch nestedErr {
534	case poll.ErrNetClosing:
535		return nil
536	}
537	return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
538
539third:
540	if isPlatformError(nestedErr) {
541		return nil
542	}
543	switch nestedErr {
544	case os.ErrClosed: // for Plan 9
545		return nil
546	}
547	return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
548}
549
550func TestCloseError(t *testing.T) {
551	ln, err := newLocalListener("tcp")
552	if err != nil {
553		t.Fatal(err)
554	}
555	defer ln.Close()
556	c, err := Dial(ln.Addr().Network(), ln.Addr().String())
557	if err != nil {
558		t.Fatal(err)
559	}
560	defer c.Close()
561
562	for i := 0; i < 3; i++ {
563		err = c.(*TCPConn).CloseRead()
564		if perr := parseCloseError(err, true); perr != nil {
565			t.Errorf("#%d: %v", i, perr)
566		}
567	}
568	for i := 0; i < 3; i++ {
569		err = c.(*TCPConn).CloseWrite()
570		if perr := parseCloseError(err, true); perr != nil {
571			t.Errorf("#%d: %v", i, perr)
572		}
573	}
574	for i := 0; i < 3; i++ {
575		err = c.Close()
576		if perr := parseCloseError(err, false); perr != nil {
577			t.Errorf("#%d: %v", i, perr)
578		}
579		err = ln.Close()
580		if perr := parseCloseError(err, false); perr != nil {
581			t.Errorf("#%d: %v", i, perr)
582		}
583	}
584
585	pc, err := ListenPacket("udp", "127.0.0.1:0")
586	if err != nil {
587		t.Fatal(err)
588	}
589	defer pc.Close()
590
591	for i := 0; i < 3; i++ {
592		err = pc.Close()
593		if perr := parseCloseError(err, false); perr != nil {
594			t.Errorf("#%d: %v", i, perr)
595		}
596	}
597}
598
599// parseAcceptError parses nestedErr and reports whether it is a valid
600// error value from Accept functions.
601// It returns nil when nestedErr is valid.
602func parseAcceptError(nestedErr error) error {
603	if nestedErr == nil {
604		return nil
605	}
606
607	switch err := nestedErr.(type) {
608	case *OpError:
609		if err := err.isValid(); err != nil {
610			return err
611		}
612		nestedErr = err.Err
613		goto second
614	}
615	return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
616
617second:
618	if isPlatformError(nestedErr) {
619		return nil
620	}
621	switch err := nestedErr.(type) {
622	case *os.SyscallError:
623		nestedErr = err.Err
624		goto third
625	case *os.PathError: // for Plan 9
626		nestedErr = err.Err
627		goto third
628	}
629	switch nestedErr {
630	case poll.ErrNetClosing, poll.ErrTimeout, poll.ErrNotPollable:
631		return nil
632	}
633	return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
634
635third:
636	if isPlatformError(nestedErr) {
637		return nil
638	}
639	return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
640}
641
642func TestAcceptError(t *testing.T) {
643	handler := func(ls *localServer, ln Listener) {
644		for {
645			ln.(*TCPListener).SetDeadline(time.Now().Add(5 * time.Millisecond))
646			c, err := ln.Accept()
647			if perr := parseAcceptError(err); perr != nil {
648				t.Error(perr)
649			}
650			if err != nil {
651				if c != nil {
652					t.Errorf("Accept returned non-nil interface %T(%v) with err != nil", c, c)
653				}
654				if nerr, ok := err.(Error); !ok || (!nerr.Timeout() && !nerr.Temporary()) {
655					return
656				}
657				continue
658			}
659			c.Close()
660		}
661	}
662	ls, err := newLocalServer("tcp")
663	if err != nil {
664		t.Fatal(err)
665	}
666	if err := ls.buildup(handler); err != nil {
667		ls.teardown()
668		t.Fatal(err)
669	}
670
671	time.Sleep(100 * time.Millisecond)
672	ls.teardown()
673}
674
675// parseCommonError parses nestedErr and reports whether it is a valid
676// error value from miscellaneous functions.
677// It returns nil when nestedErr is valid.
678func parseCommonError(nestedErr error) error {
679	if nestedErr == nil {
680		return nil
681	}
682
683	switch err := nestedErr.(type) {
684	case *OpError:
685		if err := err.isValid(); err != nil {
686			return err
687		}
688		nestedErr = err.Err
689		goto second
690	}
691	return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
692
693second:
694	if isPlatformError(nestedErr) {
695		return nil
696	}
697	switch err := nestedErr.(type) {
698	case *os.SyscallError:
699		nestedErr = err.Err
700		goto third
701	case *os.LinkError:
702		nestedErr = err.Err
703		goto third
704	case *os.PathError:
705		nestedErr = err.Err
706		goto third
707	}
708	switch nestedErr {
709	case poll.ErrNetClosing:
710		return nil
711	}
712	return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
713
714third:
715	if isPlatformError(nestedErr) {
716		return nil
717	}
718	return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
719}
720
721func TestFileError(t *testing.T) {
722	switch runtime.GOOS {
723	case "windows":
724		t.Skipf("not supported on %s", runtime.GOOS)
725	}
726
727	f, err := ioutil.TempFile("", "go-nettest")
728	if err != nil {
729		t.Fatal(err)
730	}
731	defer os.Remove(f.Name())
732	defer f.Close()
733
734	c, err := FileConn(f)
735	if err != nil {
736		if c != nil {
737			t.Errorf("FileConn returned non-nil interface %T(%v) with err != nil", c, c)
738		}
739		if perr := parseCommonError(err); perr != nil {
740			t.Error(perr)
741		}
742	} else {
743		c.Close()
744		t.Error("should fail")
745	}
746	ln, err := FileListener(f)
747	if err != nil {
748		if ln != nil {
749			t.Errorf("FileListener returned non-nil interface %T(%v) with err != nil", ln, ln)
750		}
751		if perr := parseCommonError(err); perr != nil {
752			t.Error(perr)
753		}
754	} else {
755		ln.Close()
756		t.Error("should fail")
757	}
758	pc, err := FilePacketConn(f)
759	if err != nil {
760		if pc != nil {
761			t.Errorf("FilePacketConn returned non-nil interface %T(%v) with err != nil", pc, pc)
762		}
763		if perr := parseCommonError(err); perr != nil {
764			t.Error(perr)
765		}
766	} else {
767		pc.Close()
768		t.Error("should fail")
769	}
770
771	ln, err = newLocalListener("tcp")
772	if err != nil {
773		t.Fatal(err)
774	}
775
776	for i := 0; i < 3; i++ {
777		f, err := ln.(*TCPListener).File()
778		if err != nil {
779			if perr := parseCommonError(err); perr != nil {
780				t.Error(perr)
781			}
782		} else {
783			f.Close()
784		}
785		ln.Close()
786	}
787}
788
789func parseLookupPortError(nestedErr error) error {
790	if nestedErr == nil {
791		return nil
792	}
793
794	switch nestedErr.(type) {
795	case *AddrError, *DNSError:
796		return nil
797	case *os.PathError: // for Plan 9
798		return nil
799	}
800	return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
801}
802