libgo: update to go1.9
[official-gcc.git] / libgo / go / golang_org / x / net / nettest / conntest.go
blob5bd3a8c68c587bd0f76a5fa066706d32498fb3f9
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.
5 // Package nettest provides utilities for network testing.
6 package nettest
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"
21 var (
22 aLongTimeAgo = time.Unix(233431200, 0)
23 neverTimeout = time.Time{}
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)
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)
41 type connTester func(t *testing.T, c1, c2 net.Conn)
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)
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()
56 defer timer.Stop()
57 f(t, c1, c2)
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)
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)
71 if err := c1.Close(); err != nil {
72 t.Errorf("unexpected c1.Close error: %v", err)
74 }()
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)
81 if err := c2.Close(); err != nil {
82 t.Errorf("unexpected c2.Close error: %v", err)
84 dataCh <- wr.Bytes()
85 }()
87 if got := <-dataCh; !bytes.Equal(got, want) {
88 t.Errorf("transmitted data differs")
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()
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
107 t.Errorf("unexpected Read error: %v", err)
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)
115 prev = v
116 if v == 1000 {
117 break
120 if _, err := c.Write(buf); err != nil {
121 t.Errorf("unexpected Write error: %v", err)
122 break
125 if err := c.Close(); err != nil {
126 t.Errorf("unexpected Close error: %v", err)
130 wg.Add(2)
131 go pingPonger(c1)
132 go pingPonger(c2)
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)
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)))
145 var wg sync.WaitGroup
146 defer wg.Wait()
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()
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))
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)
173 var wg sync.WaitGroup
174 defer wg.Wait()
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()
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))
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)
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)
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)))
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)
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)
225 testRoundtrip(t, c1)
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)
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)
237 checkForTimeoutError(t, err)
239 testRoundtrip(t, c1)
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)
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)
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)
263 checkForTimeoutError(t, err)
264 if len(deadlineSet) == 0 {
265 t.Error("Read timed out before deadline is set")
268 go func() {
269 defer wg.Done()
270 var err error
271 for err == nil {
272 _, err = c1.Write(make([]byte, 1024))
274 checkForTimeoutError(t, err)
275 if len(deadlineSet) == 0 {
276 t.Error("Write timed out before deadline is set")
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)
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)
293 go func() {
294 defer wg.Done()
295 var err error
296 for err == nil {
297 _, err = c1.Write(make([]byte, 1024))
299 checkForTimeoutError(t, err)
301 wg.Wait()
303 go chunkedCopy(c2, c2)
304 resyncConn(t, c1)
305 testRoundtrip(t, c1)
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)
313 var wg sync.WaitGroup
314 defer wg.Wait()
315 wg.Add(3)
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()
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)
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)
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")
348 go chunkedCopy(c2, c2)
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))
359 go func() {
360 defer wg.Done()
361 c1.Write(make([]byte, 1024))
363 go func() {
364 defer wg.Done()
365 c1.SetDeadline(time.Now().Add(10 * time.Millisecond))
367 go func() {
368 defer wg.Done()
369 c1.SetReadDeadline(aLongTimeAgo)
371 go func() {
372 defer wg.Done()
373 c1.SetWriteDeadline(aLongTimeAgo)
375 go func() {
376 defer wg.Done()
377 c1.LocalAddr()
379 go func() {
380 defer wg.Done()
381 c1.RemoteAddr()
384 wg.Wait() // At worst, the deadline is set 10ms into the future
386 resyncConn(t, c1)
387 testRoundtrip(t, c1)
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")
397 } else {
398 t.Errorf("got %T, want net.Error", err)
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)
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)
414 if _, err := io.ReadFull(c, buf); err != nil {
415 t.Errorf("roundtrip Read error: %v", err)
417 if string(buf) != s {
418 t.Errorf("roundtrip data mismatch: got %q, want %q", buf, s)
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
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
438 if err != nil {
439 t.Errorf("unexpected Read error: %v", err)
440 break
443 if err := <-errCh; err != nil {
444 t.Errorf("unexpected Write error: %v", err)
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