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