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