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 BenchmarkReadOverlapped(b *testing.B) {
141 benchmarkRead(b, true)
142 }
143
144 func BenchmarkReadSync(b *testing.B) {
145 benchmarkRead(b, false)
146 }
147
148 func benchmarkRead(b *testing.B, overlapped bool) {
149 name := filepath.Join(b.TempDir(), "foo")
150 const content = "hello world"
151 err := os.WriteFile(name, []byte(content), 0644)
152 if err != nil {
153 b.Fatal(err)
154 }
155 file := newFile(b, name, overlapped)
156 var buf [len(content)]byte
157 for b.Loop() {
158 _, err := io.ReadFull(file, buf[:])
159 if err != nil {
160 b.Fatal(err)
161 }
162 if _, err := file.Seek(0, io.SeekStart); err != nil {
163 b.Fatal(err)
164 }
165 }
166 }
167
View as plain text