1// Copyright 2009 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//go:build !js
6
7package net
8
9import (
10	"errors"
11	"fmt"
12	"internal/testenv"
13	"io"
14	"net/internal/socktest"
15	"os"
16	"runtime"
17	"testing"
18	"time"
19)
20
21func TestCloseRead(t *testing.T) {
22	switch runtime.GOOS {
23	case "plan9":
24		t.Skipf("not supported on %s", runtime.GOOS)
25	}
26	t.Parallel()
27
28	for _, network := range []string{"tcp", "unix", "unixpacket"} {
29		network := network
30		t.Run(network, func(t *testing.T) {
31			if !testableNetwork(network) {
32				t.Skipf("network %s is not testable on the current platform", network)
33			}
34			t.Parallel()
35
36			ln := newLocalListener(t, network)
37			switch network {
38			case "unix", "unixpacket":
39				defer os.Remove(ln.Addr().String())
40			}
41			defer ln.Close()
42
43			c, err := Dial(ln.Addr().Network(), ln.Addr().String())
44			if err != nil {
45				t.Fatal(err)
46			}
47			switch network {
48			case "unix", "unixpacket":
49				defer os.Remove(c.LocalAddr().String())
50			}
51			defer c.Close()
52
53			switch c := c.(type) {
54			case *TCPConn:
55				err = c.CloseRead()
56			case *UnixConn:
57				err = c.CloseRead()
58			}
59			if err != nil {
60				if perr := parseCloseError(err, true); perr != nil {
61					t.Error(perr)
62				}
63				t.Fatal(err)
64			}
65			var b [1]byte
66			n, err := c.Read(b[:])
67			if n != 0 || err == nil {
68				t.Fatalf("got (%d, %v); want (0, error)", n, err)
69			}
70		})
71	}
72}
73
74func TestCloseWrite(t *testing.T) {
75	switch runtime.GOOS {
76	case "plan9":
77		t.Skipf("not supported on %s", runtime.GOOS)
78	}
79
80	t.Parallel()
81	deadline, _ := t.Deadline()
82	if !deadline.IsZero() {
83		// Leave 10% headroom on the deadline to report errors and clean up.
84		deadline = deadline.Add(-time.Until(deadline) / 10)
85	}
86
87	for _, network := range []string{"tcp", "unix", "unixpacket"} {
88		network := network
89		t.Run(network, func(t *testing.T) {
90			if !testableNetwork(network) {
91				t.Skipf("network %s is not testable on the current platform", network)
92			}
93			t.Parallel()
94
95			handler := func(ls *localServer, ln Listener) {
96				c, err := ln.Accept()
97				if err != nil {
98					t.Error(err)
99					return
100				}
101				if !deadline.IsZero() {
102					c.SetDeadline(deadline)
103				}
104				defer c.Close()
105
106				var b [1]byte
107				n, err := c.Read(b[:])
108				if n != 0 || err != io.EOF {
109					t.Errorf("got (%d, %v); want (0, io.EOF)", n, err)
110					return
111				}
112				switch c := c.(type) {
113				case *TCPConn:
114					err = c.CloseWrite()
115				case *UnixConn:
116					err = c.CloseWrite()
117				}
118				if err != nil {
119					if perr := parseCloseError(err, true); perr != nil {
120						t.Error(perr)
121					}
122					t.Error(err)
123					return
124				}
125				n, err = c.Write(b[:])
126				if err == nil {
127					t.Errorf("got (%d, %v); want (any, error)", n, err)
128					return
129				}
130			}
131
132			ls := newLocalServer(t, network)
133			defer ls.teardown()
134			if err := ls.buildup(handler); err != nil {
135				t.Fatal(err)
136			}
137
138			c, err := Dial(ls.Listener.Addr().Network(), ls.Listener.Addr().String())
139			if err != nil {
140				t.Fatal(err)
141			}
142			if !deadline.IsZero() {
143				c.SetDeadline(deadline)
144			}
145			switch network {
146			case "unix", "unixpacket":
147				defer os.Remove(c.LocalAddr().String())
148			}
149			defer c.Close()
150
151			switch c := c.(type) {
152			case *TCPConn:
153				err = c.CloseWrite()
154			case *UnixConn:
155				err = c.CloseWrite()
156			}
157			if err != nil {
158				if perr := parseCloseError(err, true); perr != nil {
159					t.Error(perr)
160				}
161				t.Fatal(err)
162			}
163			var b [1]byte
164			n, err := c.Read(b[:])
165			if n != 0 || err != io.EOF {
166				t.Fatalf("got (%d, %v); want (0, io.EOF)", n, err)
167			}
168			n, err = c.Write(b[:])
169			if err == nil {
170				t.Fatalf("got (%d, %v); want (any, error)", n, err)
171			}
172		})
173	}
174}
175
176func TestConnClose(t *testing.T) {
177	t.Parallel()
178	for _, network := range []string{"tcp", "unix", "unixpacket"} {
179		network := network
180		t.Run(network, func(t *testing.T) {
181			if !testableNetwork(network) {
182				t.Skipf("network %s is not testable on the current platform", network)
183			}
184			t.Parallel()
185
186			ln := newLocalListener(t, network)
187			switch network {
188			case "unix", "unixpacket":
189				defer os.Remove(ln.Addr().String())
190			}
191			defer ln.Close()
192
193			c, err := Dial(ln.Addr().Network(), ln.Addr().String())
194			if err != nil {
195				t.Fatal(err)
196			}
197			switch network {
198			case "unix", "unixpacket":
199				defer os.Remove(c.LocalAddr().String())
200			}
201			defer c.Close()
202
203			if err := c.Close(); err != nil {
204				if perr := parseCloseError(err, false); perr != nil {
205					t.Error(perr)
206				}
207				t.Fatal(err)
208			}
209			var b [1]byte
210			n, err := c.Read(b[:])
211			if n != 0 || err == nil {
212				t.Fatalf("got (%d, %v); want (0, error)", n, err)
213			}
214		})
215	}
216}
217
218func TestListenerClose(t *testing.T) {
219	t.Parallel()
220	for _, network := range []string{"tcp", "unix", "unixpacket"} {
221		network := network
222		t.Run(network, func(t *testing.T) {
223			if !testableNetwork(network) {
224				t.Skipf("network %s is not testable on the current platform", network)
225			}
226			t.Parallel()
227
228			ln := newLocalListener(t, network)
229			switch network {
230			case "unix", "unixpacket":
231				defer os.Remove(ln.Addr().String())
232			}
233
234			if err := ln.Close(); err != nil {
235				if perr := parseCloseError(err, false); perr != nil {
236					t.Error(perr)
237				}
238				t.Fatal(err)
239			}
240			c, err := ln.Accept()
241			if err == nil {
242				c.Close()
243				t.Fatal("should fail")
244			}
245
246			// Note: we cannot ensure that a subsequent Dial does not succeed, because
247			// we do not in general have any guarantee that ln.Addr is not immediately
248			// reused. (TCP sockets enter a TIME_WAIT state when closed, but that only
249			// applies to existing connections for the port — it does not prevent the
250			// port itself from being used for entirely new connections in the
251			// meantime.)
252		})
253	}
254}
255
256func TestPacketConnClose(t *testing.T) {
257	t.Parallel()
258	for _, network := range []string{"udp", "unixgram"} {
259		network := network
260		t.Run(network, func(t *testing.T) {
261			if !testableNetwork(network) {
262				t.Skipf("network %s is not testable on the current platform", network)
263			}
264			t.Parallel()
265
266			c := newLocalPacketListener(t, network)
267			switch network {
268			case "unixgram":
269				defer os.Remove(c.LocalAddr().String())
270			}
271			defer c.Close()
272
273			if err := c.Close(); err != nil {
274				if perr := parseCloseError(err, false); perr != nil {
275					t.Error(perr)
276				}
277				t.Fatal(err)
278			}
279			var b [1]byte
280			n, _, err := c.ReadFrom(b[:])
281			if n != 0 || err == nil {
282				t.Fatalf("got (%d, %v); want (0, error)", n, err)
283			}
284		})
285	}
286}
287
288func TestListenCloseListen(t *testing.T) {
289	const maxTries = 10
290	for tries := 0; tries < maxTries; tries++ {
291		ln := newLocalListener(t, "tcp")
292		addr := ln.Addr().String()
293		// TODO: This is racy. The selected address could be reused in between this
294		// Close and the subsequent Listen.
295		if err := ln.Close(); err != nil {
296			if perr := parseCloseError(err, false); perr != nil {
297				t.Error(perr)
298			}
299			t.Fatal(err)
300		}
301		ln, err := Listen("tcp", addr)
302		if err == nil {
303			// Success. (This test didn't always make it here earlier.)
304			ln.Close()
305			return
306		}
307		t.Errorf("failed on try %d/%d: %v", tries+1, maxTries, err)
308	}
309	t.Fatalf("failed to listen/close/listen on same address after %d tries", maxTries)
310}
311
312// See golang.org/issue/6163, golang.org/issue/6987.
313func TestAcceptIgnoreAbortedConnRequest(t *testing.T) {
314	switch runtime.GOOS {
315	case "plan9":
316		t.Skipf("%s does not have full support of socktest", runtime.GOOS)
317	}
318
319	syserr := make(chan error)
320	go func() {
321		defer close(syserr)
322		for _, err := range abortedConnRequestErrors {
323			syserr <- err
324		}
325	}()
326	sw.Set(socktest.FilterAccept, func(so *socktest.Status) (socktest.AfterFilter, error) {
327		if err, ok := <-syserr; ok {
328			return nil, err
329		}
330		return nil, nil
331	})
332	defer sw.Set(socktest.FilterAccept, nil)
333
334	operr := make(chan error, 1)
335	handler := func(ls *localServer, ln Listener) {
336		defer close(operr)
337		c, err := ln.Accept()
338		if err != nil {
339			if perr := parseAcceptError(err); perr != nil {
340				operr <- perr
341			}
342			operr <- err
343			return
344		}
345		c.Close()
346	}
347	ls := newLocalServer(t, "tcp")
348	defer ls.teardown()
349	if err := ls.buildup(handler); err != nil {
350		t.Fatal(err)
351	}
352
353	c, err := Dial(ls.Listener.Addr().Network(), ls.Listener.Addr().String())
354	if err != nil {
355		t.Fatal(err)
356	}
357	c.Close()
358
359	for err := range operr {
360		t.Error(err)
361	}
362}
363
364func TestZeroByteRead(t *testing.T) {
365	t.Parallel()
366	for _, network := range []string{"tcp", "unix", "unixpacket"} {
367		network := network
368		t.Run(network, func(t *testing.T) {
369			if !testableNetwork(network) {
370				t.Skipf("network %s is not testable on the current platform", network)
371			}
372			t.Parallel()
373
374			ln := newLocalListener(t, network)
375			connc := make(chan Conn, 1)
376			go func() {
377				defer ln.Close()
378				c, err := ln.Accept()
379				if err != nil {
380					t.Error(err)
381				}
382				connc <- c // might be nil
383			}()
384			c, err := Dial(network, ln.Addr().String())
385			if err != nil {
386				t.Fatal(err)
387			}
388			defer c.Close()
389			sc := <-connc
390			if sc == nil {
391				return
392			}
393			defer sc.Close()
394
395			if runtime.GOOS == "windows" {
396				// A zero byte read on Windows caused a wait for readability first.
397				// Rather than change that behavior, satisfy it in this test.
398				// See Issue 15735.
399				go io.WriteString(sc, "a")
400			}
401
402			n, err := c.Read(nil)
403			if n != 0 || err != nil {
404				t.Errorf("%s: zero byte client read = %v, %v; want 0, nil", network, n, err)
405			}
406
407			if runtime.GOOS == "windows" {
408				// Same as comment above.
409				go io.WriteString(c, "a")
410			}
411			n, err = sc.Read(nil)
412			if n != 0 || err != nil {
413				t.Errorf("%s: zero byte server read = %v, %v; want 0, nil", network, n, err)
414			}
415		})
416	}
417}
418
419// withTCPConnPair sets up a TCP connection between two peers, then
420// runs peer1 and peer2 concurrently. withTCPConnPair returns when
421// both have completed.
422func withTCPConnPair(t *testing.T, peer1, peer2 func(c *TCPConn) error) {
423	ln := newLocalListener(t, "tcp")
424	defer ln.Close()
425	errc := make(chan error, 2)
426	go func() {
427		c1, err := ln.Accept()
428		if err != nil {
429			errc <- err
430			return
431		}
432		defer c1.Close()
433		errc <- peer1(c1.(*TCPConn))
434	}()
435	go func() {
436		c2, err := Dial("tcp", ln.Addr().String())
437		if err != nil {
438			errc <- err
439			return
440		}
441		defer c2.Close()
442		errc <- peer2(c2.(*TCPConn))
443	}()
444	for i := 0; i < 2; i++ {
445		if err := <-errc; err != nil {
446			t.Fatal(err)
447		}
448	}
449}
450
451// Tests that a blocked Read is interrupted by a concurrent SetReadDeadline
452// modifying that Conn's read deadline to the past.
453// See golang.org/cl/30164 which documented this. The net/http package
454// depends on this.
455func TestReadTimeoutUnblocksRead(t *testing.T) {
456	serverDone := make(chan struct{})
457	server := func(cs *TCPConn) error {
458		defer close(serverDone)
459		errc := make(chan error, 1)
460		go func() {
461			defer close(errc)
462			go func() {
463				// TODO: find a better way to wait
464				// until we're blocked in the cs.Read
465				// call below. Sleep is lame.
466				time.Sleep(100 * time.Millisecond)
467
468				// Interrupt the upcoming Read, unblocking it:
469				cs.SetReadDeadline(time.Unix(123, 0)) // time in the past
470			}()
471			var buf [1]byte
472			n, err := cs.Read(buf[:1])
473			if n != 0 || err == nil {
474				errc <- fmt.Errorf("Read = %v, %v; want 0, non-nil", n, err)
475			}
476		}()
477		select {
478		case err := <-errc:
479			return err
480		case <-time.After(5 * time.Second):
481			buf := make([]byte, 2<<20)
482			buf = buf[:runtime.Stack(buf, true)]
483			println("Stacks at timeout:\n", string(buf))
484			return errors.New("timeout waiting for Read to finish")
485		}
486
487	}
488	// Do nothing in the client. Never write. Just wait for the
489	// server's half to be done.
490	client := func(*TCPConn) error {
491		<-serverDone
492		return nil
493	}
494	withTCPConnPair(t, client, server)
495}
496
497// Issue 17695: verify that a blocked Read is woken up by a Close.
498func TestCloseUnblocksRead(t *testing.T) {
499	t.Parallel()
500	server := func(cs *TCPConn) error {
501		// Give the client time to get stuck in a Read:
502		time.Sleep(20 * time.Millisecond)
503		cs.Close()
504		return nil
505	}
506	client := func(ss *TCPConn) error {
507		n, err := ss.Read([]byte{0})
508		if n != 0 || err != io.EOF {
509			return fmt.Errorf("Read = %v, %v; want 0, EOF", n, err)
510		}
511		return nil
512	}
513	withTCPConnPair(t, client, server)
514}
515
516// Issue 24808: verify that ECONNRESET is not temporary for read.
517func TestNotTemporaryRead(t *testing.T) {
518	if runtime.GOOS == "freebsd" {
519		testenv.SkipFlaky(t, 25289)
520	}
521	if runtime.GOOS == "aix" {
522		testenv.SkipFlaky(t, 29685)
523	}
524	t.Parallel()
525	server := func(cs *TCPConn) error {
526		cs.SetLinger(0)
527		// Give the client time to get stuck in a Read.
528		time.Sleep(50 * time.Millisecond)
529		cs.Close()
530		return nil
531	}
532	client := func(ss *TCPConn) error {
533		_, err := ss.Read([]byte{0})
534		if err == nil {
535			return errors.New("Read succeeded unexpectedly")
536		} else if err == io.EOF {
537			// This happens on Plan 9.
538			return nil
539		} else if ne, ok := err.(Error); !ok {
540			return fmt.Errorf("unexpected error %v", err)
541		} else if ne.Temporary() {
542			return fmt.Errorf("unexpected temporary error %v", err)
543		}
544		return nil
545	}
546	withTCPConnPair(t, client, server)
547}
548
549// The various errors should implement the Error interface.
550func TestErrors(t *testing.T) {
551	var (
552		_ Error = &OpError{}
553		_ Error = &ParseError{}
554		_ Error = &AddrError{}
555		_ Error = UnknownNetworkError("")
556		_ Error = InvalidAddrError("")
557		_ Error = &timeoutError{}
558		_ Error = &DNSConfigError{}
559		_ Error = &DNSError{}
560	)
561
562	// ErrClosed was introduced as type error, so we can't check
563	// it using a declaration.
564	if _, ok := ErrClosed.(Error); !ok {
565		t.Fatal("ErrClosed does not implement Error")
566	}
567}
568