Source file
src/internal/poll/fd_windows_test.go
1
2
3
4
5 package poll_test
6
7 import (
8 "errors"
9 "fmt"
10 "internal/poll"
11 "internal/syscall/windows"
12 "os"
13 "sync"
14 "syscall"
15 "testing"
16 "unsafe"
17 )
18
19 type loggedFD struct {
20 Net string
21 FD *poll.FD
22 Err error
23 }
24
25 var (
26 logMu sync.Mutex
27 loggedFDs map[syscall.Handle]*loggedFD
28 )
29
30 func logFD(net string, fd *poll.FD, err error) {
31 logMu.Lock()
32 defer logMu.Unlock()
33
34 loggedFDs[fd.Sysfd] = &loggedFD{
35 Net: net,
36 FD: fd,
37 Err: err,
38 }
39 }
40
41 func init() {
42 loggedFDs = make(map[syscall.Handle]*loggedFD)
43 *poll.LogInitFD = logFD
44
45 poll.InitWSA()
46 }
47
48 func findLoggedFD(h syscall.Handle) (lfd *loggedFD, found bool) {
49 logMu.Lock()
50 defer logMu.Unlock()
51
52 lfd, found = loggedFDs[h]
53 return lfd, found
54 }
55
56
57
58 func checkFileIsNotPartOfNetpoll(f *os.File) error {
59 lfd, found := findLoggedFD(syscall.Handle(f.Fd()))
60 if !found {
61 return fmt.Errorf("%v fd=%v: is not found in the log", f.Name(), f.Fd())
62 }
63 if lfd.FD.IsPartOfNetpoll() {
64 return fmt.Errorf("%v fd=%v: is part of netpoll, but should not be (logged: net=%v err=%v)", f.Name(), f.Fd(), lfd.Net, lfd.Err)
65 }
66 return nil
67 }
68
69 func TestFileFdsAreInitialised(t *testing.T) {
70 exe, err := os.Executable()
71 if err != nil {
72 t.Fatal(err)
73 }
74 f, err := os.Open(exe)
75 if err != nil {
76 t.Fatal(err)
77 }
78 defer f.Close()
79
80 err = checkFileIsNotPartOfNetpoll(f)
81 if err != nil {
82 t.Fatal(err)
83 }
84 }
85
86 func TestSerialFdsAreInitialised(t *testing.T) {
87 for _, name := range []string{"COM1", "COM2", "COM3", "COM4"} {
88 t.Run(name, func(t *testing.T) {
89 h, err := syscall.CreateFile(syscall.StringToUTF16Ptr(name),
90 syscall.GENERIC_READ|syscall.GENERIC_WRITE,
91 0,
92 nil,
93 syscall.OPEN_EXISTING,
94 syscall.FILE_ATTRIBUTE_NORMAL|syscall.FILE_FLAG_OVERLAPPED,
95 0)
96 if err != nil {
97 if errno, ok := err.(syscall.Errno); ok {
98 switch errno {
99 case syscall.ERROR_FILE_NOT_FOUND,
100 syscall.ERROR_ACCESS_DENIED:
101 t.Log("Skipping: ", err)
102 return
103 }
104 }
105 t.Fatal(err)
106 }
107 f := os.NewFile(uintptr(h), name)
108 defer f.Close()
109
110 err = checkFileIsNotPartOfNetpoll(f)
111 if err != nil {
112 t.Fatal(err)
113 }
114 })
115 }
116 }
117
118 func TestWSASocketConflict(t *testing.T) {
119 s, err := windows.WSASocket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP, nil, 0, windows.WSA_FLAG_OVERLAPPED)
120 if err != nil {
121 t.Fatal(err)
122 }
123 fd := poll.FD{Sysfd: s, IsStream: true, ZeroReadIsEOF: true}
124 _, err = fd.Init("tcp", true)
125 if err != nil {
126 syscall.CloseHandle(s)
127 t.Fatal(err)
128 }
129 defer fd.Close()
130
131 const SIO_TCP_INFO = syscall.IOC_INOUT | syscall.IOC_VENDOR | 39
132 inbuf := uint32(0)
133 var outbuf _TCP_INFO_v0
134 cbbr := uint32(0)
135
136 var ov syscall.Overlapped
137
138
139 ov.HEvent, _ = windows.CreateEvent(nil, 0, 0, nil)
140 if ov.HEvent == 0 {
141 t.Fatalf("could not create the event!")
142 }
143 defer syscall.CloseHandle(ov.HEvent)
144
145 if err = fd.WSAIoctl(
146 SIO_TCP_INFO,
147 (*byte)(unsafe.Pointer(&inbuf)),
148 uint32(unsafe.Sizeof(inbuf)),
149 (*byte)(unsafe.Pointer(&outbuf)),
150 uint32(unsafe.Sizeof(outbuf)),
151 &cbbr,
152 &ov,
153 0,
154 ); err != nil && !errors.Is(err, syscall.ERROR_IO_PENDING) {
155 t.Fatalf("could not perform the WSAIoctl: %v", err)
156 }
157
158 if err != nil && errors.Is(err, syscall.ERROR_IO_PENDING) {
159
160
161 if res, err := syscall.WaitForSingleObject(ov.HEvent, syscall.INFINITE); res != 0 {
162 t.Fatalf("waiting for the completion of the overlapped IO failed: %v", err)
163 }
164 }
165 }
166
167 type _TCP_INFO_v0 struct {
168 State uint32
169 Mss uint32
170 ConnectionTimeMs uint64
171 TimestampsEnabled bool
172 RttUs uint32
173 MinRttUs uint32
174 BytesInFlight uint32
175 Cwnd uint32
176 SndWnd uint32
177 RcvWnd uint32
178 RcvBuf uint32
179 BytesOut uint64
180 BytesIn uint64
181 BytesReordered uint32
182 BytesRetrans uint32
183 FastRetrans uint32
184 DupAcksIn uint32
185 TimeoutEpisodes uint32
186 SynRetrans uint8
187 }
188
View as plain text