Source file
src/net/http/netconn_test.go
1
2
3
4
5 package http_test
6
7 import (
8 "bytes"
9 "context"
10 "internal/synctest"
11 "io"
12 "math"
13 "net"
14 "net/netip"
15 "os"
16 "sync"
17 "time"
18 )
19
20 func fakeNetListen() *fakeNetListener {
21 li := &fakeNetListener{
22 setc: make(chan struct{}, 1),
23 unsetc: make(chan struct{}, 1),
24 addr: netip.MustParseAddrPort("127.0.0.1:8000"),
25 locPort: 10000,
26 }
27 li.unsetc <- struct{}{}
28 return li
29 }
30
31 type fakeNetListener struct {
32 setc, unsetc chan struct{}
33 queue []net.Conn
34 closed bool
35 addr netip.AddrPort
36 locPort uint16
37
38 onDial func()
39 onClose func(*fakeNetConn)
40
41 trackConns bool
42 conns []*fakeNetConn
43 }
44
45 func (li *fakeNetListener) lock() {
46 select {
47 case <-li.setc:
48 case <-li.unsetc:
49 }
50 }
51
52 func (li *fakeNetListener) unlock() {
53 if li.closed || len(li.queue) > 0 {
54 li.setc <- struct{}{}
55 } else {
56 li.unsetc <- struct{}{}
57 }
58 }
59
60 func (li *fakeNetListener) connect() *fakeNetConn {
61 if li.onDial != nil {
62 li.onDial()
63 }
64 li.lock()
65 defer li.unlock()
66 locAddr := netip.AddrPortFrom(netip.AddrFrom4([4]byte{127, 0, 0, 1}), li.locPort)
67 li.locPort++
68 c0, c1 := fakeNetPipe(li.addr, locAddr)
69 c0.onClose = li.onClose
70 c1.onClose = li.onClose
71 li.queue = append(li.queue, c0)
72 if li.trackConns {
73 li.conns = append(li.conns, c0)
74 }
75 return c1
76 }
77
78 func (li *fakeNetListener) Accept() (net.Conn, error) {
79 <-li.setc
80 defer li.unlock()
81 if li.closed {
82 return nil, net.ErrClosed
83 }
84 c := li.queue[0]
85 li.queue = li.queue[1:]
86 return c, nil
87 }
88
89 func (li *fakeNetListener) Close() error {
90 li.lock()
91 defer li.unlock()
92 li.closed = true
93 return nil
94 }
95
96 func (li *fakeNetListener) Addr() net.Addr {
97 return net.TCPAddrFromAddrPort(li.addr)
98 }
99
100
101
102
103
104
105 func fakeNetPipe(s1ap, s2ap netip.AddrPort) (r, w *fakeNetConn) {
106 s1addr := net.TCPAddrFromAddrPort(s1ap)
107 s2addr := net.TCPAddrFromAddrPort(s2ap)
108 s1 := newSynctestNetConnHalf(s1addr)
109 s2 := newSynctestNetConnHalf(s2addr)
110 c1 := &fakeNetConn{loc: s1, rem: s2}
111 c2 := &fakeNetConn{loc: s2, rem: s1}
112 c1.peer = c2
113 c2.peer = c1
114 return c1, c2
115 }
116
117
118 type fakeNetConn struct {
119
120
121
122 loc, rem *fakeNetConnHalf
123
124
125 autoWait bool
126
127
128 peer *fakeNetConn
129
130 onClose func(*fakeNetConn)
131 }
132
133
134 func (c *fakeNetConn) Read(b []byte) (n int, err error) {
135 if c.autoWait {
136 synctest.Wait()
137 }
138 return c.loc.read(b)
139 }
140
141
142
143 func (c *fakeNetConn) Peek() []byte {
144 if c.autoWait {
145 synctest.Wait()
146 }
147 return c.loc.peek()
148 }
149
150
151 func (c *fakeNetConn) Write(b []byte) (n int, err error) {
152 if c.autoWait {
153 defer synctest.Wait()
154 }
155 return c.rem.write(b)
156 }
157
158
159 func (c *fakeNetConn) IsClosedByPeer() bool {
160 if c.autoWait {
161 synctest.Wait()
162 }
163 c.rem.lock()
164 defer c.rem.unlock()
165
166
167 return c.rem.readErr == net.ErrClosed
168 }
169
170
171 func (c *fakeNetConn) Close() error {
172 if c.onClose != nil {
173 c.onClose(c)
174 }
175
176 c.loc.lock()
177 c.loc.writeErr = net.ErrClosed
178 c.loc.readErr = net.ErrClosed
179 c.loc.buf.Reset()
180 c.loc.unlock()
181
182 c.rem.lock()
183 if c.rem.readErr == nil {
184 c.rem.readErr = io.EOF
185 }
186 c.rem.writeErr = net.ErrClosed
187 c.rem.unlock()
188 if c.autoWait {
189 synctest.Wait()
190 }
191 return nil
192 }
193
194
195 func (c *fakeNetConn) LocalAddr() net.Addr {
196 return c.loc.addr
197 }
198
199
200 func (c *fakeNetConn) RemoteAddr() net.Addr {
201 return c.rem.addr
202 }
203
204
205 func (c *fakeNetConn) SetDeadline(t time.Time) error {
206 c.SetReadDeadline(t)
207 c.SetWriteDeadline(t)
208 return nil
209 }
210
211
212 func (c *fakeNetConn) SetReadDeadline(t time.Time) error {
213 c.loc.rctx.setDeadline(t)
214 return nil
215 }
216
217
218 func (c *fakeNetConn) SetWriteDeadline(t time.Time) error {
219 c.rem.wctx.setDeadline(t)
220 return nil
221 }
222
223
224
225 func (c *fakeNetConn) SetReadBufferSize(size int) {
226 c.loc.setReadBufferSize(size)
227 }
228
229
230
231 type fakeNetConnHalf struct {
232 addr net.Addr
233
234
235 rctx, wctx deadlineContext
236
237
238
239
240
241
242
243 lockr chan struct{}
244 lockw chan struct{}
245 lockrw chan struct{}
246 lockc chan struct{}
247
248 bufMax int
249 buf bytes.Buffer
250 readErr error
251 writeErr error
252 }
253
254 func newSynctestNetConnHalf(addr net.Addr) *fakeNetConnHalf {
255 h := &fakeNetConnHalf{
256 addr: addr,
257 lockw: make(chan struct{}, 1),
258 lockr: make(chan struct{}, 1),
259 lockrw: make(chan struct{}, 1),
260 lockc: make(chan struct{}, 1),
261 bufMax: math.MaxInt,
262 }
263 h.unlock()
264 return h
265 }
266
267
268 func (h *fakeNetConnHalf) lock() {
269 select {
270 case <-h.lockw:
271 case <-h.lockr:
272 case <-h.lockrw:
273 case <-h.lockc:
274 }
275 }
276
277
278 func (h *fakeNetConnHalf) unlock() {
279 canRead := h.readErr != nil || h.buf.Len() > 0
280 canWrite := h.writeErr != nil || h.bufMax > h.buf.Len()
281 switch {
282 case canRead && canWrite:
283 h.lockrw <- struct{}{}
284 case canRead:
285 h.lockr <- struct{}{}
286 case canWrite:
287 h.lockw <- struct{}{}
288 default:
289 h.lockc <- struct{}{}
290 }
291 }
292
293
294 func (h *fakeNetConnHalf) waitAndLockForRead() error {
295
296
297 select {
298 case <-h.lockr:
299 return nil
300 case <-h.lockrw:
301 return nil
302 default:
303 }
304 ctx := h.rctx.context()
305 select {
306 case <-h.lockr:
307 return nil
308 case <-h.lockrw:
309 return nil
310 case <-ctx.Done():
311 return context.Cause(ctx)
312 }
313 }
314
315
316 func (h *fakeNetConnHalf) waitAndLockForWrite() error {
317
318
319 select {
320 case <-h.lockw:
321 return nil
322 case <-h.lockrw:
323 return nil
324 default:
325 }
326 ctx := h.wctx.context()
327 select {
328 case <-h.lockw:
329 return nil
330 case <-h.lockrw:
331 return nil
332 case <-ctx.Done():
333 return context.Cause(ctx)
334 }
335 }
336
337 func (h *fakeNetConnHalf) peek() []byte {
338 h.lock()
339 defer h.unlock()
340 return h.buf.Bytes()
341 }
342
343 func (h *fakeNetConnHalf) read(b []byte) (n int, err error) {
344 if err := h.waitAndLockForRead(); err != nil {
345 return 0, err
346 }
347 defer h.unlock()
348 if h.buf.Len() == 0 && h.readErr != nil {
349 return 0, h.readErr
350 }
351 return h.buf.Read(b)
352 }
353
354 func (h *fakeNetConnHalf) setReadBufferSize(size int) {
355 h.lock()
356 defer h.unlock()
357 h.bufMax = size
358 }
359
360 func (h *fakeNetConnHalf) write(b []byte) (n int, err error) {
361 for n < len(b) {
362 nn, err := h.writePartial(b[n:])
363 n += nn
364 if err != nil {
365 return n, err
366 }
367 }
368 return n, nil
369 }
370
371 func (h *fakeNetConnHalf) writePartial(b []byte) (n int, err error) {
372 if err := h.waitAndLockForWrite(); err != nil {
373 return 0, err
374 }
375 defer h.unlock()
376 if h.writeErr != nil {
377 return 0, h.writeErr
378 }
379 writeMax := h.bufMax - h.buf.Len()
380 if writeMax < len(b) {
381 b = b[:writeMax]
382 }
383 return h.buf.Write(b)
384 }
385
386
387 type deadlineContext struct {
388 mu sync.Mutex
389 ctx context.Context
390 cancel context.CancelCauseFunc
391 timer *time.Timer
392 }
393
394
395 func (t *deadlineContext) context() context.Context {
396 t.mu.Lock()
397 defer t.mu.Unlock()
398 if t.ctx == nil {
399 t.ctx, t.cancel = context.WithCancelCause(context.Background())
400 }
401 return t.ctx
402 }
403
404
405 func (t *deadlineContext) setDeadline(deadline time.Time) {
406 t.mu.Lock()
407 defer t.mu.Unlock()
408
409
410 if t.ctx == nil || t.cancel == nil {
411 t.ctx, t.cancel = context.WithCancelCause(context.Background())
412 }
413
414 if t.timer != nil {
415 t.timer.Stop()
416 }
417 if deadline.IsZero() {
418
419 return
420 }
421 now := time.Now()
422 if !deadline.After(now) {
423
424 t.cancel(os.ErrDeadlineExceeded)
425 t.cancel = nil
426 return
427 }
428 if t.timer != nil {
429
430 t.timer.Reset(deadline.Sub(now))
431 return
432 }
433
434 t.timer = time.AfterFunc(deadline.Sub(now), func() {
435 t.mu.Lock()
436 defer t.mu.Unlock()
437 t.cancel(os.ErrDeadlineExceeded)
438 t.cancel = nil
439 })
440 }
441
View as plain text