OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / net / nettest / conntest.go
1 // Copyright 2016 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 // Package nettest provides utilities for network testing.
6 package nettest
7
8 import (
9         "bytes"
10         "encoding/binary"
11         "io"
12         "io/ioutil"
13         "math/rand"
14         "net"
15         "runtime"
16         "sync"
17         "testing"
18         "time"
19 )
20
21 var (
22         aLongTimeAgo = time.Unix(233431200, 0)
23         neverTimeout = time.Time{}
24 )
25
26 // MakePipe creates a connection between two endpoints and returns the pair
27 // as c1 and c2, such that anything written to c1 is read by c2 and vice-versa.
28 // The stop function closes all resources, including c1, c2, and the underlying
29 // net.Listener (if there is one), and should not be nil.
30 type MakePipe func() (c1, c2 net.Conn, stop func(), err error)
31
32 // TestConn tests that a net.Conn implementation properly satisfies the interface.
33 // The tests should not produce any false positives, but may experience
34 // false negatives. Thus, some issues may only be detected when the test is
35 // run multiple times. For maximal effectiveness, run the tests under the
36 // race detector.
37 func TestConn(t *testing.T, mp MakePipe) {
38         testConn(t, mp)
39 }
40
41 type connTester func(t *testing.T, c1, c2 net.Conn)
42
43 func timeoutWrapper(t *testing.T, mp MakePipe, f connTester) {
44         c1, c2, stop, err := mp()
45         if err != nil {
46                 t.Fatalf("unable to make pipe: %v", err)
47         }
48         var once sync.Once
49         defer once.Do(func() { stop() })
50         timer := time.AfterFunc(time.Minute, func() {
51                 once.Do(func() {
52                         t.Error("test timed out; terminating pipe")
53                         stop()
54                 })
55         })
56         defer timer.Stop()
57         f(t, c1, c2)
58 }
59
60 // testBasicIO tests that the data sent on c1 is properly received on c2.
61 func testBasicIO(t *testing.T, c1, c2 net.Conn) {
62         want := make([]byte, 1<<20)
63         rand.New(rand.NewSource(0)).Read(want)
64
65         dataCh := make(chan []byte)
66         go func() {
67                 rd := bytes.NewReader(want)
68                 if err := chunkedCopy(c1, rd); err != nil {
69                         t.Errorf("unexpected c1.Write error: %v", err)
70                 }
71                 if err := c1.Close(); err != nil {
72                         t.Errorf("unexpected c1.Close error: %v", err)
73                 }
74         }()
75
76         go func() {
77                 wr := new(bytes.Buffer)
78                 if err := chunkedCopy(wr, c2); err != nil {
79                         t.Errorf("unexpected c2.Read error: %v", err)
80                 }
81                 if err := c2.Close(); err != nil {
82                         t.Errorf("unexpected c2.Close error: %v", err)
83                 }
84                 dataCh <- wr.Bytes()
85         }()
86
87         if got := <-dataCh; !bytes.Equal(got, want) {
88                 t.Errorf("transmitted data differs")
89         }
90 }
91
92 // testPingPong tests that the two endpoints can synchronously send data to
93 // each other in a typical request-response pattern.
94 func testPingPong(t *testing.T, c1, c2 net.Conn) {
95         var wg sync.WaitGroup
96         defer wg.Wait()
97
98         pingPonger := func(c net.Conn) {
99                 defer wg.Done()
100                 buf := make([]byte, 8)
101                 var prev uint64
102                 for {
103                         if _, err := io.ReadFull(c, buf); err != nil {
104                                 if err == io.EOF {
105                                         break
106                                 }
107                                 t.Errorf("unexpected Read error: %v", err)
108                         }
109
110                         v := binary.LittleEndian.Uint64(buf)
111                         binary.LittleEndian.PutUint64(buf, v+1)
112                         if prev != 0 && prev+2 != v {
113                                 t.Errorf("mismatching value: got %d, want %d", v, prev+2)
114                         }
115                         prev = v
116                         if v == 1000 {
117                                 break
118                         }
119
120                         if _, err := c.Write(buf); err != nil {
121                                 t.Errorf("unexpected Write error: %v", err)
122                                 break
123                         }
124                 }
125                 if err := c.Close(); err != nil {
126                         t.Errorf("unexpected Close error: %v", err)
127                 }
128         }
129
130         wg.Add(2)
131         go pingPonger(c1)
132         go pingPonger(c2)
133
134         // Start off the chain reaction.
135         if _, err := c1.Write(make([]byte, 8)); err != nil {
136                 t.Errorf("unexpected c1.Write error: %v", err)
137         }
138 }
139
140 // testRacyRead tests that it is safe to mutate the input Read buffer
141 // immediately after cancelation has occurred.
142 func testRacyRead(t *testing.T, c1, c2 net.Conn) {
143         go chunkedCopy(c2, rand.New(rand.NewSource(0)))
144
145         var wg sync.WaitGroup
146         defer wg.Wait()
147
148         c1.SetReadDeadline(time.Now().Add(time.Millisecond))
149         for i := 0; i < 10; i++ {
150                 wg.Add(1)
151                 go func() {
152                         defer wg.Done()
153
154                         b1 := make([]byte, 1024)
155                         b2 := make([]byte, 1024)
156                         for j := 0; j < 100; j++ {
157                                 _, err := c1.Read(b1)
158                                 copy(b1, b2) // Mutate b1 to trigger potential race
159                                 if err != nil {
160                                         checkForTimeoutError(t, err)
161                                         c1.SetReadDeadline(time.Now().Add(time.Millisecond))
162                                 }
163                         }
164                 }()
165         }
166 }
167
168 // testRacyWrite tests that it is safe to mutate the input Write buffer
169 // immediately after cancelation has occurred.
170 func testRacyWrite(t *testing.T, c1, c2 net.Conn) {
171         go chunkedCopy(ioutil.Discard, c2)
172
173         var wg sync.WaitGroup
174         defer wg.Wait()
175
176         c1.SetWriteDeadline(time.Now().Add(time.Millisecond))
177         for i := 0; i < 10; i++ {
178                 wg.Add(1)
179                 go func() {
180                         defer wg.Done()
181
182                         b1 := make([]byte, 1024)
183                         b2 := make([]byte, 1024)
184                         for j := 0; j < 100; j++ {
185                                 _, err := c1.Write(b1)
186                                 copy(b1, b2) // Mutate b1 to trigger potential race
187                                 if err != nil {
188                                         checkForTimeoutError(t, err)
189                                         c1.SetWriteDeadline(time.Now().Add(time.Millisecond))
190                                 }
191                         }
192                 }()
193         }
194 }
195
196 // testReadTimeout tests that Read timeouts do not affect Write.
197 func testReadTimeout(t *testing.T, c1, c2 net.Conn) {
198         go chunkedCopy(ioutil.Discard, c2)
199
200         c1.SetReadDeadline(aLongTimeAgo)
201         _, err := c1.Read(make([]byte, 1024))
202         checkForTimeoutError(t, err)
203         if _, err := c1.Write(make([]byte, 1024)); err != nil {
204                 t.Errorf("unexpected Write error: %v", err)
205         }
206 }
207
208 // testWriteTimeout tests that Write timeouts do not affect Read.
209 func testWriteTimeout(t *testing.T, c1, c2 net.Conn) {
210         go chunkedCopy(c2, rand.New(rand.NewSource(0)))
211
212         c1.SetWriteDeadline(aLongTimeAgo)
213         _, err := c1.Write(make([]byte, 1024))
214         checkForTimeoutError(t, err)
215         if _, err := c1.Read(make([]byte, 1024)); err != nil {
216                 t.Errorf("unexpected Read error: %v", err)
217         }
218 }
219
220 // testPastTimeout tests that a deadline set in the past immediately times out
221 // Read and Write requests.
222 func testPastTimeout(t *testing.T, c1, c2 net.Conn) {
223         go chunkedCopy(c2, c2)
224
225         testRoundtrip(t, c1)
226
227         c1.SetDeadline(aLongTimeAgo)
228         n, err := c1.Write(make([]byte, 1024))
229         if n != 0 {
230                 t.Errorf("unexpected Write count: got %d, want 0", n)
231         }
232         checkForTimeoutError(t, err)
233         n, err = c1.Read(make([]byte, 1024))
234         if n != 0 {
235                 t.Errorf("unexpected Read count: got %d, want 0", n)
236         }
237         checkForTimeoutError(t, err)
238
239         testRoundtrip(t, c1)
240 }
241
242 // testPresentTimeout tests that a deadline set while there are pending
243 // Read and Write operations immediately times out those operations.
244 func testPresentTimeout(t *testing.T, c1, c2 net.Conn) {
245         var wg sync.WaitGroup
246         defer wg.Wait()
247         wg.Add(3)
248
249         deadlineSet := make(chan bool, 1)
250         go func() {
251                 defer wg.Done()
252                 time.Sleep(100 * time.Millisecond)
253                 deadlineSet <- true
254                 c1.SetReadDeadline(aLongTimeAgo)
255                 c1.SetWriteDeadline(aLongTimeAgo)
256         }()
257         go func() {
258                 defer wg.Done()
259                 n, err := c1.Read(make([]byte, 1024))
260                 if n != 0 {
261                         t.Errorf("unexpected Read count: got %d, want 0", n)
262                 }
263                 checkForTimeoutError(t, err)
264                 if len(deadlineSet) == 0 {
265                         t.Error("Read timed out before deadline is set")
266                 }
267         }()
268         go func() {
269                 defer wg.Done()
270                 var err error
271                 for err == nil {
272                         _, err = c1.Write(make([]byte, 1024))
273                 }
274                 checkForTimeoutError(t, err)
275                 if len(deadlineSet) == 0 {
276                         t.Error("Write timed out before deadline is set")
277                 }
278         }()
279 }
280
281 // testFutureTimeout tests that a future deadline will eventually time out
282 // Read and Write operations.
283 func testFutureTimeout(t *testing.T, c1, c2 net.Conn) {
284         var wg sync.WaitGroup
285         wg.Add(2)
286
287         c1.SetDeadline(time.Now().Add(100 * time.Millisecond))
288         go func() {
289                 defer wg.Done()
290                 _, err := c1.Read(make([]byte, 1024))
291                 checkForTimeoutError(t, err)
292         }()
293         go func() {
294                 defer wg.Done()
295                 var err error
296                 for err == nil {
297                         _, err = c1.Write(make([]byte, 1024))
298                 }
299                 checkForTimeoutError(t, err)
300         }()
301         wg.Wait()
302
303         go chunkedCopy(c2, c2)
304         resyncConn(t, c1)
305         testRoundtrip(t, c1)
306 }
307
308 // testCloseTimeout tests that calling Close immediately times out pending
309 // Read and Write operations.
310 func testCloseTimeout(t *testing.T, c1, c2 net.Conn) {
311         go chunkedCopy(c2, c2)
312
313         var wg sync.WaitGroup
314         defer wg.Wait()
315         wg.Add(3)
316
317         // Test for cancelation upon connection closure.
318         c1.SetDeadline(neverTimeout)
319         go func() {
320                 defer wg.Done()
321                 time.Sleep(100 * time.Millisecond)
322                 c1.Close()
323         }()
324         go func() {
325                 defer wg.Done()
326                 var err error
327                 buf := make([]byte, 1024)
328                 for err == nil {
329                         _, err = c1.Read(buf)
330                 }
331         }()
332         go func() {
333                 defer wg.Done()
334                 var err error
335                 buf := make([]byte, 1024)
336                 for err == nil {
337                         _, err = c1.Write(buf)
338                 }
339         }()
340 }
341
342 // testConcurrentMethods tests that the methods of net.Conn can safely
343 // be called concurrently.
344 func testConcurrentMethods(t *testing.T, c1, c2 net.Conn) {
345         if runtime.GOOS == "plan9" {
346                 t.Skip("skipping on plan9; see https://golang.org/issue/20489")
347         }
348         go chunkedCopy(c2, c2)
349
350         // The results of the calls may be nonsensical, but this should
351         // not trigger a race detector warning.
352         var wg sync.WaitGroup
353         for i := 0; i < 100; i++ {
354                 wg.Add(7)
355                 go func() {
356                         defer wg.Done()
357                         c1.Read(make([]byte, 1024))
358                 }()
359                 go func() {
360                         defer wg.Done()
361                         c1.Write(make([]byte, 1024))
362                 }()
363                 go func() {
364                         defer wg.Done()
365                         c1.SetDeadline(time.Now().Add(10 * time.Millisecond))
366                 }()
367                 go func() {
368                         defer wg.Done()
369                         c1.SetReadDeadline(aLongTimeAgo)
370                 }()
371                 go func() {
372                         defer wg.Done()
373                         c1.SetWriteDeadline(aLongTimeAgo)
374                 }()
375                 go func() {
376                         defer wg.Done()
377                         c1.LocalAddr()
378                 }()
379                 go func() {
380                         defer wg.Done()
381                         c1.RemoteAddr()
382                 }()
383         }
384         wg.Wait() // At worst, the deadline is set 10ms into the future
385
386         resyncConn(t, c1)
387         testRoundtrip(t, c1)
388 }
389
390 // checkForTimeoutError checks that the error satisfies the Error interface
391 // and that Timeout returns true.
392 func checkForTimeoutError(t *testing.T, err error) {
393         if nerr, ok := err.(net.Error); ok {
394                 if !nerr.Timeout() {
395                         t.Errorf("err.Timeout() = false, want true")
396                 }
397         } else {
398                 t.Errorf("got %T, want net.Error", err)
399         }
400 }
401
402 // testRoundtrip writes something into c and reads it back.
403 // It assumes that everything written into c is echoed back to itself.
404 func testRoundtrip(t *testing.T, c net.Conn) {
405         if err := c.SetDeadline(neverTimeout); err != nil {
406                 t.Errorf("roundtrip SetDeadline error: %v", err)
407         }
408
409         const s = "Hello, world!"
410         buf := []byte(s)
411         if _, err := c.Write(buf); err != nil {
412                 t.Errorf("roundtrip Write error: %v", err)
413         }
414         if _, err := io.ReadFull(c, buf); err != nil {
415                 t.Errorf("roundtrip Read error: %v", err)
416         }
417         if string(buf) != s {
418                 t.Errorf("roundtrip data mismatch: got %q, want %q", buf, s)
419         }
420 }
421
422 // resyncConn resynchronizes the connection into a sane state.
423 // It assumes that everything written into c is echoed back to itself.
424 // It assumes that 0xff is not currently on the wire or in the read buffer.
425 func resyncConn(t *testing.T, c net.Conn) {
426         c.SetDeadline(neverTimeout)
427         errCh := make(chan error)
428         go func() {
429                 _, err := c.Write([]byte{0xff})
430                 errCh <- err
431         }()
432         buf := make([]byte, 1024)
433         for {
434                 n, err := c.Read(buf)
435                 if n > 0 && bytes.IndexByte(buf[:n], 0xff) == n-1 {
436                         break
437                 }
438                 if err != nil {
439                         t.Errorf("unexpected Read error: %v", err)
440                         break
441                 }
442         }
443         if err := <-errCh; err != nil {
444                 t.Errorf("unexpected Write error: %v", err)
445         }
446 }
447
448 // chunkedCopy copies from r to w in fixed-width chunks to avoid
449 // causing a Write that exceeds the maximum packet size for packet-based
450 // connections like "unixpacket".
451 // We assume that the maximum packet size is at least 1024.
452 func chunkedCopy(w io.Writer, r io.Reader) error {
453         b := make([]byte, 1024)
454         _, err := io.CopyBuffer(struct{ io.Writer }{w}, struct{ io.Reader }{r}, b)
455         return err
456 }