]> Cypherpunks.ru repositories - gostls13.git/blob - src/net/net_fake_test.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / src / net / net_fake_test.go
1 // Copyright 2023 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 || wasip1
6
7 package net
8
9 // GOOS=js and GOOS=wasip1 do not have typical socket networking capabilities
10 // found on other platforms. To help run test suites of the stdlib packages,
11 // an in-memory "fake network" facility is implemented.
12 //
13 // The tests in this files are intended to validate the behavior of the fake
14 // network stack on these platforms.
15
16 import (
17         "errors"
18         "syscall"
19         "testing"
20 )
21
22 func TestFakePortExhaustion(t *testing.T) {
23         if testing.Short() {
24                 t.Skipf("skipping test that opens 1<<16 connections")
25         }
26
27         ln := newLocalListener(t, "tcp")
28         done := make(chan struct{})
29         go func() {
30                 var accepted []Conn
31                 defer func() {
32                         for _, c := range accepted {
33                                 c.Close()
34                         }
35                         close(done)
36                 }()
37
38                 for {
39                         c, err := ln.Accept()
40                         if err != nil {
41                                 return
42                         }
43                         accepted = append(accepted, c)
44                 }
45         }()
46
47         var dialed []Conn
48         defer func() {
49                 ln.Close()
50                 for _, c := range dialed {
51                         c.Close()
52                 }
53                 <-done
54         }()
55
56         // Since this test is not running in parallel, we expect to be able to open
57         // all 65535 valid (fake) ports. The listener is already using one, so
58         // we should be able to Dial the remaining 65534.
59         for len(dialed) < (1<<16)-2 {
60                 c, err := Dial(ln.Addr().Network(), ln.Addr().String())
61                 if err != nil {
62                         t.Fatalf("unexpected error from Dial with %v connections: %v", len(dialed), err)
63                 }
64                 dialed = append(dialed, c)
65                 if testing.Verbose() && len(dialed)%(1<<12) == 0 {
66                         t.Logf("dialed %d connections", len(dialed))
67                 }
68         }
69         t.Logf("dialed %d connections", len(dialed))
70
71         // Now that all of the ports are in use, dialing another should fail due
72         // to port exhaustion, which (for POSIX-like socket APIs) should return
73         // an EADDRINUSE error.
74         c, err := Dial(ln.Addr().Network(), ln.Addr().String())
75         if err == nil {
76                 c.Close()
77         }
78         if errors.Is(err, syscall.EADDRINUSE) {
79                 t.Logf("Dial returned expected error: %v", err)
80         } else {
81                 t.Errorf("unexpected error from Dial: %v\nwant: %v", err, syscall.EADDRINUSE)
82         }
83
84         // Opening a Listener should fail at this point too.
85         ln2, err := Listen("tcp", "localhost:0")
86         if err == nil {
87                 ln2.Close()
88         }
89         if errors.Is(err, syscall.EADDRINUSE) {
90                 t.Logf("Listen returned expected error: %v", err)
91         } else {
92                 t.Errorf("unexpected error from Listen: %v\nwant: %v", err, syscall.EADDRINUSE)
93         }
94
95         // When we close an arbitrary connection, we should be able to reuse its port
96         // even if the server hasn't yet seen the ECONNRESET for the connection.
97         dialed[0].Close()
98         dialed = dialed[1:]
99         t.Logf("closed one connection")
100         c, err = Dial(ln.Addr().Network(), ln.Addr().String())
101         if err == nil {
102                 c.Close()
103                 t.Logf("Dial succeeded")
104         } else {
105                 t.Errorf("unexpected error from Dial: %v", err)
106         }
107 }