Source file
src/internal/poll/fd_windows_test.go
1
2
3
4
5 package poll_test
6
7 import (
8 "errors"
9 "internal/poll"
10 "internal/syscall/windows"
11 "io"
12 "os"
13 "path/filepath"
14 "syscall"
15 "testing"
16 "unsafe"
17 )
18
19 func init() {
20 poll.InitWSA()
21 }
22
23 func TestWSASocketConflict(t *testing.T) {
24 t.Parallel()
25 s, err := windows.WSASocket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP, nil, 0, windows.WSA_FLAG_OVERLAPPED)
26 if err != nil {
27 t.Fatal(err)
28 }
29 fd := poll.FD{Sysfd: s, IsStream: true, ZeroReadIsEOF: true}
30 if err = fd.Init("tcp", true); err != nil {
31 syscall.CloseHandle(s)
32 t.Fatal(err)
33 }
34 defer fd.Close()
35
36 const SIO_TCP_INFO = syscall.IOC_INOUT | syscall.IOC_VENDOR | 39
37 inbuf := uint32(0)
38 var outbuf _TCP_INFO_v0
39 cbbr := uint32(0)
40
41 var ov syscall.Overlapped
42
43
44 ov.HEvent, _ = windows.CreateEvent(nil, 0, 0, nil)
45 if ov.HEvent == 0 {
46 t.Fatalf("could not create the event!")
47 }
48 defer syscall.CloseHandle(ov.HEvent)
49
50 if err = fd.WSAIoctl(
51 SIO_TCP_INFO,
52 (*byte)(unsafe.Pointer(&inbuf)),
53 uint32(unsafe.Sizeof(inbuf)),
54 (*byte)(unsafe.Pointer(&outbuf)),
55 uint32(unsafe.Sizeof(outbuf)),
56 &cbbr,
57 &ov,
58 0,
59 ); err != nil && !errors.Is(err, syscall.ERROR_IO_PENDING) {
60 t.Fatalf("could not perform the WSAIoctl: %v", err)
61 }
62
63 if err != nil && errors.Is(err, syscall.ERROR_IO_PENDING) {
64
65
66 if res, err := syscall.WaitForSingleObject(ov.HEvent, syscall.INFINITE); res != 0 {
67 t.Fatalf("waiting for the completion of the overlapped IO failed: %v", err)
68 }
69 }
70 }
71
72 type _TCP_INFO_v0 struct {
73 State uint32
74 Mss uint32
75 ConnectionTimeMs uint64
76 TimestampsEnabled bool
77 RttUs uint32
78 MinRttUs uint32
79 BytesInFlight uint32
80 Cwnd uint32
81 SndWnd uint32
82 RcvWnd uint32
83 RcvBuf uint32
84 BytesOut uint64
85 BytesIn uint64
86 BytesReordered uint32
87 BytesRetrans uint32
88 FastRetrans uint32
89 DupAcksIn uint32
90 TimeoutEpisodes uint32
91 SynRetrans uint8
92 }
93
94 func newFD(t testing.TB, h syscall.Handle, kind string, overlapped bool) *poll.FD {
95 fd := poll.FD{
96 Sysfd: h,
97 IsStream: true,
98 ZeroReadIsEOF: true,
99 }
100 err := fd.Init(kind, overlapped)
101 if overlapped && err != nil {
102
103 fd.Close()
104 t.Fatal(err)
105 }
106 t.Cleanup(func() {
107 fd.Close()
108 })
109 return &fd
110 }
111
112 func newFile(t testing.TB, name string, overlapped bool) *poll.FD {
113 namep, err := syscall.UTF16PtrFromString(name)
114 if err != nil {
115 t.Fatal(err)
116 }
117 flags := syscall.FILE_ATTRIBUTE_NORMAL
118 if overlapped {
119 flags |= syscall.FILE_FLAG_OVERLAPPED
120 }
121 h, err := syscall.CreateFile(namep,
122 syscall.GENERIC_READ|syscall.GENERIC_WRITE,
123 syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_READ,
124 nil, syscall.OPEN_ALWAYS, uint32(flags), 0)
125 if err != nil {
126 t.Fatal(err)
127 }
128 typ, err := syscall.GetFileType(h)
129 if err != nil {
130 syscall.CloseHandle(h)
131 t.Fatal(err)
132 }
133 kind := "file"
134 if typ == syscall.FILE_TYPE_PIPE {
135 kind = "pipe"
136 }
137 return newFD(t, h, kind, overlapped)
138 }
139
140 func TestFileSkipsCompletionPortOnSuccess(t *testing.T) {
141 t.Parallel()
142 fd := newFile(t, filepath.Join(t.TempDir(), "foo"), true)
143 if !poll.SkipsCompletionPortOnSuccess(fd) {
144 t.Fatal("expected file handles to skip completion port on success")
145 }
146 }
147
148 func TestSocketSkipsCompletionPortOnSuccess(t *testing.T) {
149
150 t.Parallel()
151 s, err := windows.WSASocket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP, nil, 0, windows.WSA_FLAG_OVERLAPPED)
152 if err != nil {
153 t.Fatal(err)
154 }
155 fd := newFD(t, s, "tcp", true)
156 if !poll.SkipsCompletionPortOnSuccess(fd) {
157 t.Fatal("expected socket handles to skip completion port on success")
158 }
159 }
160
161 func BenchmarkReadOverlapped(b *testing.B) {
162 benchmarkRead(b, true)
163 }
164
165 func BenchmarkReadSync(b *testing.B) {
166 benchmarkRead(b, false)
167 }
168
169 func benchmarkRead(b *testing.B, overlapped bool) {
170 name := filepath.Join(b.TempDir(), "foo")
171 const content = "hello world"
172 err := os.WriteFile(name, []byte(content), 0644)
173 if err != nil {
174 b.Fatal(err)
175 }
176 file := newFile(b, name, overlapped)
177 var buf [len(content)]byte
178 for b.Loop() {
179 _, err := io.ReadFull(file, buf[:])
180 if err != nil {
181 b.Fatal(err)
182 }
183 if _, err := file.Seek(0, io.SeekStart); err != nil {
184 b.Fatal(err)
185 }
186 }
187 }
188
View as plain text