a89f62171962095b4bd2269fd433c836ceedaa75
[platform/upstream/gcc.git] / libgo / go / net / tcpsock_test.go
1 // Copyright 2012 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 // +build !js
6
7 package net
8
9 import (
10         "fmt"
11         "internal/testenv"
12         "io"
13         "os"
14         "reflect"
15         "runtime"
16         "sync"
17         "testing"
18         "time"
19 )
20
21 func BenchmarkTCP4OneShot(b *testing.B) {
22         benchmarkTCP(b, false, false, "127.0.0.1:0")
23 }
24
25 func BenchmarkTCP4OneShotTimeout(b *testing.B) {
26         benchmarkTCP(b, false, true, "127.0.0.1:0")
27 }
28
29 func BenchmarkTCP4Persistent(b *testing.B) {
30         benchmarkTCP(b, true, false, "127.0.0.1:0")
31 }
32
33 func BenchmarkTCP4PersistentTimeout(b *testing.B) {
34         benchmarkTCP(b, true, true, "127.0.0.1:0")
35 }
36
37 func BenchmarkTCP6OneShot(b *testing.B) {
38         if !supportsIPv6() {
39                 b.Skip("ipv6 is not supported")
40         }
41         benchmarkTCP(b, false, false, "[::1]:0")
42 }
43
44 func BenchmarkTCP6OneShotTimeout(b *testing.B) {
45         if !supportsIPv6() {
46                 b.Skip("ipv6 is not supported")
47         }
48         benchmarkTCP(b, false, true, "[::1]:0")
49 }
50
51 func BenchmarkTCP6Persistent(b *testing.B) {
52         if !supportsIPv6() {
53                 b.Skip("ipv6 is not supported")
54         }
55         benchmarkTCP(b, true, false, "[::1]:0")
56 }
57
58 func BenchmarkTCP6PersistentTimeout(b *testing.B) {
59         if !supportsIPv6() {
60                 b.Skip("ipv6 is not supported")
61         }
62         benchmarkTCP(b, true, true, "[::1]:0")
63 }
64
65 func benchmarkTCP(b *testing.B, persistent, timeout bool, laddr string) {
66         testHookUninstaller.Do(uninstallTestHooks)
67
68         const msgLen = 512
69         conns := b.N
70         numConcurrent := runtime.GOMAXPROCS(-1) * 2
71         msgs := 1
72         if persistent {
73                 conns = numConcurrent
74                 msgs = b.N / conns
75                 if msgs == 0 {
76                         msgs = 1
77                 }
78                 if conns > b.N {
79                         conns = b.N
80                 }
81         }
82         sendMsg := func(c Conn, buf []byte) bool {
83                 n, err := c.Write(buf)
84                 if n != len(buf) || err != nil {
85                         b.Log(err)
86                         return false
87                 }
88                 return true
89         }
90         recvMsg := func(c Conn, buf []byte) bool {
91                 for read := 0; read != len(buf); {
92                         n, err := c.Read(buf)
93                         read += n
94                         if err != nil {
95                                 b.Log(err)
96                                 return false
97                         }
98                 }
99                 return true
100         }
101         ln, err := Listen("tcp", laddr)
102         if err != nil {
103                 b.Fatal(err)
104         }
105         defer ln.Close()
106         serverSem := make(chan bool, numConcurrent)
107         // Acceptor.
108         go func() {
109                 for {
110                         c, err := ln.Accept()
111                         if err != nil {
112                                 break
113                         }
114                         serverSem <- true
115                         // Server connection.
116                         go func(c Conn) {
117                                 defer func() {
118                                         c.Close()
119                                         <-serverSem
120                                 }()
121                                 if timeout {
122                                         c.SetDeadline(time.Now().Add(time.Hour)) // Not intended to fire.
123                                 }
124                                 var buf [msgLen]byte
125                                 for m := 0; m < msgs; m++ {
126                                         if !recvMsg(c, buf[:]) || !sendMsg(c, buf[:]) {
127                                                 break
128                                         }
129                                 }
130                         }(c)
131                 }
132         }()
133         clientSem := make(chan bool, numConcurrent)
134         for i := 0; i < conns; i++ {
135                 clientSem <- true
136                 // Client connection.
137                 go func() {
138                         defer func() {
139                                 <-clientSem
140                         }()
141                         c, err := Dial("tcp", ln.Addr().String())
142                         if err != nil {
143                                 b.Log(err)
144                                 return
145                         }
146                         defer c.Close()
147                         if timeout {
148                                 c.SetDeadline(time.Now().Add(time.Hour)) // Not intended to fire.
149                         }
150                         var buf [msgLen]byte
151                         for m := 0; m < msgs; m++ {
152                                 if !sendMsg(c, buf[:]) || !recvMsg(c, buf[:]) {
153                                         break
154                                 }
155                         }
156                 }()
157         }
158         for i := 0; i < numConcurrent; i++ {
159                 clientSem <- true
160                 serverSem <- true
161         }
162 }
163
164 func BenchmarkTCP4ConcurrentReadWrite(b *testing.B) {
165         benchmarkTCPConcurrentReadWrite(b, "127.0.0.1:0")
166 }
167
168 func BenchmarkTCP6ConcurrentReadWrite(b *testing.B) {
169         if !supportsIPv6() {
170                 b.Skip("ipv6 is not supported")
171         }
172         benchmarkTCPConcurrentReadWrite(b, "[::1]:0")
173 }
174
175 func benchmarkTCPConcurrentReadWrite(b *testing.B, laddr string) {
176         testHookUninstaller.Do(uninstallTestHooks)
177
178         // The benchmark creates GOMAXPROCS client/server pairs.
179         // Each pair creates 4 goroutines: client reader/writer and server reader/writer.
180         // The benchmark stresses concurrent reading and writing to the same connection.
181         // Such pattern is used in net/http and net/rpc.
182
183         b.StopTimer()
184
185         P := runtime.GOMAXPROCS(0)
186         N := b.N / P
187         W := 1000
188
189         // Setup P client/server connections.
190         clients := make([]Conn, P)
191         servers := make([]Conn, P)
192         ln, err := Listen("tcp", laddr)
193         if err != nil {
194                 b.Fatal(err)
195         }
196         defer ln.Close()
197         done := make(chan bool)
198         go func() {
199                 for p := 0; p < P; p++ {
200                         s, err := ln.Accept()
201                         if err != nil {
202                                 b.Error(err)
203                                 return
204                         }
205                         servers[p] = s
206                 }
207                 done <- true
208         }()
209         for p := 0; p < P; p++ {
210                 c, err := Dial("tcp", ln.Addr().String())
211                 if err != nil {
212                         b.Fatal(err)
213                 }
214                 clients[p] = c
215         }
216         <-done
217
218         b.StartTimer()
219
220         var wg sync.WaitGroup
221         wg.Add(4 * P)
222         for p := 0; p < P; p++ {
223                 // Client writer.
224                 go func(c Conn) {
225                         defer wg.Done()
226                         var buf [1]byte
227                         for i := 0; i < N; i++ {
228                                 v := byte(i)
229                                 for w := 0; w < W; w++ {
230                                         v *= v
231                                 }
232                                 buf[0] = v
233                                 _, err := c.Write(buf[:])
234                                 if err != nil {
235                                         b.Error(err)
236                                         return
237                                 }
238                         }
239                 }(clients[p])
240
241                 // Pipe between server reader and server writer.
242                 pipe := make(chan byte, 128)
243
244                 // Server reader.
245                 go func(s Conn) {
246                         defer wg.Done()
247                         var buf [1]byte
248                         for i := 0; i < N; i++ {
249                                 _, err := s.Read(buf[:])
250                                 if err != nil {
251                                         b.Error(err)
252                                         return
253                                 }
254                                 pipe <- buf[0]
255                         }
256                 }(servers[p])
257
258                 // Server writer.
259                 go func(s Conn) {
260                         defer wg.Done()
261                         var buf [1]byte
262                         for i := 0; i < N; i++ {
263                                 v := <-pipe
264                                 for w := 0; w < W; w++ {
265                                         v *= v
266                                 }
267                                 buf[0] = v
268                                 _, err := s.Write(buf[:])
269                                 if err != nil {
270                                         b.Error(err)
271                                         return
272                                 }
273                         }
274                         s.Close()
275                 }(servers[p])
276
277                 // Client reader.
278                 go func(c Conn) {
279                         defer wg.Done()
280                         var buf [1]byte
281                         for i := 0; i < N; i++ {
282                                 _, err := c.Read(buf[:])
283                                 if err != nil {
284                                         b.Error(err)
285                                         return
286                                 }
287                         }
288                         c.Close()
289                 }(clients[p])
290         }
291         wg.Wait()
292 }
293
294 type resolveTCPAddrTest struct {
295         network       string
296         litAddrOrName string
297         addr          *TCPAddr
298         err           error
299 }
300
301 var resolveTCPAddrTests = []resolveTCPAddrTest{
302         {"tcp", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil},
303         {"tcp4", "127.0.0.1:65535", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 65535}, nil},
304
305         {"tcp", "[::1]:0", &TCPAddr{IP: ParseIP("::1"), Port: 0}, nil},
306         {"tcp6", "[::1]:65535", &TCPAddr{IP: ParseIP("::1"), Port: 65535}, nil},
307
308         {"tcp", "[::1%en0]:1", &TCPAddr{IP: ParseIP("::1"), Port: 1, Zone: "en0"}, nil},
309         {"tcp6", "[::1%911]:2", &TCPAddr{IP: ParseIP("::1"), Port: 2, Zone: "911"}, nil},
310
311         {"", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, // Go 1.0 behavior
312         {"", "[::1]:0", &TCPAddr{IP: ParseIP("::1"), Port: 0}, nil},         // Go 1.0 behavior
313
314         {"tcp", ":12345", &TCPAddr{Port: 12345}, nil},
315
316         {"http", "127.0.0.1:0", nil, UnknownNetworkError("http")},
317
318         {"tcp", "127.0.0.1:http", &TCPAddr{IP: ParseIP("127.0.0.1"), Port: 80}, nil},
319         {"tcp", "[::ffff:127.0.0.1]:http", &TCPAddr{IP: ParseIP("::ffff:127.0.0.1"), Port: 80}, nil},
320         {"tcp", "[2001:db8::1]:http", &TCPAddr{IP: ParseIP("2001:db8::1"), Port: 80}, nil},
321         {"tcp4", "127.0.0.1:http", &TCPAddr{IP: ParseIP("127.0.0.1"), Port: 80}, nil},
322         {"tcp4", "[::ffff:127.0.0.1]:http", &TCPAddr{IP: ParseIP("127.0.0.1"), Port: 80}, nil},
323         {"tcp6", "[2001:db8::1]:http", &TCPAddr{IP: ParseIP("2001:db8::1"), Port: 80}, nil},
324
325         {"tcp4", "[2001:db8::1]:http", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "2001:db8::1"}},
326         {"tcp6", "127.0.0.1:http", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "127.0.0.1"}},
327         {"tcp6", "[::ffff:127.0.0.1]:http", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "::ffff:127.0.0.1"}},
328 }
329
330 func TestResolveTCPAddr(t *testing.T) {
331         origTestHookLookupIP := testHookLookupIP
332         defer func() { testHookLookupIP = origTestHookLookupIP }()
333         testHookLookupIP = lookupLocalhost
334
335         for _, tt := range resolveTCPAddrTests {
336                 addr, err := ResolveTCPAddr(tt.network, tt.litAddrOrName)
337                 if !reflect.DeepEqual(addr, tt.addr) || !reflect.DeepEqual(err, tt.err) {
338                         t.Errorf("ResolveTCPAddr(%q, %q) = %#v, %v, want %#v, %v", tt.network, tt.litAddrOrName, addr, err, tt.addr, tt.err)
339                         continue
340                 }
341                 if err == nil {
342                         addr2, err := ResolveTCPAddr(addr.Network(), addr.String())
343                         if !reflect.DeepEqual(addr2, tt.addr) || err != tt.err {
344                                 t.Errorf("(%q, %q): ResolveTCPAddr(%q, %q) = %#v, %v, want %#v, %v", tt.network, tt.litAddrOrName, addr.Network(), addr.String(), addr2, err, tt.addr, tt.err)
345                         }
346                 }
347         }
348 }
349
350 var tcpListenerNameTests = []struct {
351         net   string
352         laddr *TCPAddr
353 }{
354         {"tcp4", &TCPAddr{IP: IPv4(127, 0, 0, 1)}},
355         {"tcp4", &TCPAddr{}},
356         {"tcp4", nil},
357 }
358
359 func TestTCPListenerName(t *testing.T) {
360         testenv.MustHaveExternalNetwork(t)
361
362         for _, tt := range tcpListenerNameTests {
363                 ln, err := ListenTCP(tt.net, tt.laddr)
364                 if err != nil {
365                         t.Fatal(err)
366                 }
367                 defer ln.Close()
368                 la := ln.Addr()
369                 if a, ok := la.(*TCPAddr); !ok || a.Port == 0 {
370                         t.Fatalf("got %v; expected a proper address with non-zero port number", la)
371                 }
372         }
373 }
374
375 func TestIPv6LinkLocalUnicastTCP(t *testing.T) {
376         testenv.MustHaveExternalNetwork(t)
377
378         if !supportsIPv6() {
379                 t.Skip("IPv6 is not supported")
380         }
381
382         for i, tt := range ipv6LinkLocalUnicastTCPTests {
383                 ln, err := Listen(tt.network, tt.address)
384                 if err != nil {
385                         // It might return "LookupHost returned no
386                         // suitable address" error on some platforms.
387                         t.Log(err)
388                         continue
389                 }
390                 ls, err := (&streamListener{Listener: ln}).newLocalServer()
391                 if err != nil {
392                         t.Fatal(err)
393                 }
394                 defer ls.teardown()
395                 ch := make(chan error, 1)
396                 handler := func(ls *localServer, ln Listener) { transponder(ln, ch) }
397                 if err := ls.buildup(handler); err != nil {
398                         t.Fatal(err)
399                 }
400                 if la, ok := ln.Addr().(*TCPAddr); !ok || !tt.nameLookup && la.Zone == "" {
401                         t.Fatalf("got %v; expected a proper address with zone identifier", la)
402                 }
403
404                 c, err := Dial(tt.network, ls.Listener.Addr().String())
405                 if err != nil {
406                         t.Fatal(err)
407                 }
408                 defer c.Close()
409                 if la, ok := c.LocalAddr().(*TCPAddr); !ok || !tt.nameLookup && la.Zone == "" {
410                         t.Fatalf("got %v; expected a proper address with zone identifier", la)
411                 }
412                 if ra, ok := c.RemoteAddr().(*TCPAddr); !ok || !tt.nameLookup && ra.Zone == "" {
413                         t.Fatalf("got %v; expected a proper address with zone identifier", ra)
414                 }
415
416                 if _, err := c.Write([]byte("TCP OVER IPV6 LINKLOCAL TEST")); err != nil {
417                         t.Fatal(err)
418                 }
419                 b := make([]byte, 32)
420                 if _, err := c.Read(b); err != nil {
421                         t.Fatal(err)
422                 }
423
424                 for err := range ch {
425                         t.Errorf("#%d: %v", i, err)
426                 }
427         }
428 }
429
430 func TestTCPConcurrentAccept(t *testing.T) {
431         defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
432         ln, err := Listen("tcp", "127.0.0.1:0")
433         if err != nil {
434                 t.Fatal(err)
435         }
436         const N = 10
437         var wg sync.WaitGroup
438         wg.Add(N)
439         for i := 0; i < N; i++ {
440                 go func() {
441                         for {
442                                 c, err := ln.Accept()
443                                 if err != nil {
444                                         break
445                                 }
446                                 c.Close()
447                         }
448                         wg.Done()
449                 }()
450         }
451         attempts := 10 * N
452         fails := 0
453         d := &Dialer{Timeout: 200 * time.Millisecond}
454         for i := 0; i < attempts; i++ {
455                 c, err := d.Dial("tcp", ln.Addr().String())
456                 if err != nil {
457                         fails++
458                 } else {
459                         c.Close()
460                 }
461         }
462         ln.Close()
463         wg.Wait()
464         if fails > attempts/9 { // see issues 7400 and 7541
465                 t.Fatalf("too many Dial failed: %v", fails)
466         }
467         if fails > 0 {
468                 t.Logf("# of failed Dials: %v", fails)
469         }
470 }
471
472 func TestTCPReadWriteAllocs(t *testing.T) {
473         if runtime.Compiler == "gccgo" {
474                 t.Skip("skipping for gccgo until escape analysis is enabled")
475         }
476
477         switch runtime.GOOS {
478         case "plan9":
479                 // The implementation of asynchronous cancelable
480                 // I/O on Plan 9 allocates memory.
481                 // See net/fd_io_plan9.go.
482                 t.Skipf("not supported on %s", runtime.GOOS)
483         case "nacl":
484                 // NaCl needs to allocate pseudo file descriptor
485                 // stuff. See syscall/fd_nacl.go.
486                 t.Skipf("not supported on %s", runtime.GOOS)
487         }
488
489         ln, err := Listen("tcp", "127.0.0.1:0")
490         if err != nil {
491                 t.Fatal(err)
492         }
493         defer ln.Close()
494         var server Conn
495         errc := make(chan error, 1)
496         go func() {
497                 var err error
498                 server, err = ln.Accept()
499                 errc <- err
500         }()
501         client, err := Dial("tcp", ln.Addr().String())
502         if err != nil {
503                 t.Fatal(err)
504         }
505         defer client.Close()
506         if err := <-errc; err != nil {
507                 t.Fatal(err)
508         }
509         defer server.Close()
510
511         var buf [128]byte
512         allocs := testing.AllocsPerRun(1000, func() {
513                 _, err := server.Write(buf[:])
514                 if err != nil {
515                         t.Fatal(err)
516                 }
517                 _, err = io.ReadFull(client, buf[:])
518                 if err != nil {
519                         t.Fatal(err)
520                 }
521         })
522         // For gccgo changed "> 0" to "> 7".
523         if allocs > 7 {
524                 t.Fatalf("got %v; want 0", allocs)
525         }
526
527         var bufwrt [128]byte
528         ch := make(chan bool)
529         defer close(ch)
530         go func() {
531                 for <-ch {
532                         _, err := server.Write(bufwrt[:])
533                         errc <- err
534                 }
535         }()
536         allocs = testing.AllocsPerRun(1000, func() {
537                 ch <- true
538                 if _, err = io.ReadFull(client, buf[:]); err != nil {
539                         t.Fatal(err)
540                 }
541                 if err := <-errc; err != nil {
542                         t.Fatal(err)
543                 }
544         })
545         if allocs > 0 {
546                 t.Fatalf("got %v; want 0", allocs)
547         }
548 }
549
550 func TestTCPStress(t *testing.T) {
551         const conns = 2
552         const msgLen = 512
553         msgs := int(1e4)
554         if testing.Short() {
555                 msgs = 1e2
556         }
557
558         sendMsg := func(c Conn, buf []byte) bool {
559                 n, err := c.Write(buf)
560                 if n != len(buf) || err != nil {
561                         t.Log(err)
562                         return false
563                 }
564                 return true
565         }
566         recvMsg := func(c Conn, buf []byte) bool {
567                 for read := 0; read != len(buf); {
568                         n, err := c.Read(buf)
569                         read += n
570                         if err != nil {
571                                 t.Log(err)
572                                 return false
573                         }
574                 }
575                 return true
576         }
577
578         ln, err := Listen("tcp", "127.0.0.1:0")
579         if err != nil {
580                 t.Fatal(err)
581         }
582         done := make(chan bool)
583         // Acceptor.
584         go func() {
585                 defer func() {
586                         done <- true
587                 }()
588                 for {
589                         c, err := ln.Accept()
590                         if err != nil {
591                                 break
592                         }
593                         // Server connection.
594                         go func(c Conn) {
595                                 defer c.Close()
596                                 var buf [msgLen]byte
597                                 for m := 0; m < msgs; m++ {
598                                         if !recvMsg(c, buf[:]) || !sendMsg(c, buf[:]) {
599                                                 break
600                                         }
601                                 }
602                         }(c)
603                 }
604         }()
605         for i := 0; i < conns; i++ {
606                 // Client connection.
607                 go func() {
608                         defer func() {
609                                 done <- true
610                         }()
611                         c, err := Dial("tcp", ln.Addr().String())
612                         if err != nil {
613                                 t.Log(err)
614                                 return
615                         }
616                         defer c.Close()
617                         var buf [msgLen]byte
618                         for m := 0; m < msgs; m++ {
619                                 if !sendMsg(c, buf[:]) || !recvMsg(c, buf[:]) {
620                                         break
621                                 }
622                         }
623                 }()
624         }
625         for i := 0; i < conns; i++ {
626                 <-done
627         }
628         ln.Close()
629         <-done
630 }
631
632 func TestTCPSelfConnect(t *testing.T) {
633         if runtime.GOOS == "windows" {
634                 // TODO(brainman): do not know why it hangs.
635                 t.Skip("known-broken test on windows")
636         }
637
638         ln, err := newLocalListener("tcp")
639         if err != nil {
640                 t.Fatal(err)
641         }
642         var d Dialer
643         c, err := d.Dial(ln.Addr().Network(), ln.Addr().String())
644         if err != nil {
645                 ln.Close()
646                 t.Fatal(err)
647         }
648         network := c.LocalAddr().Network()
649         laddr := *c.LocalAddr().(*TCPAddr)
650         c.Close()
651         ln.Close()
652
653         // Try to connect to that address repeatedly.
654         n := 100000
655         if testing.Short() {
656                 n = 1000
657         }
658         switch runtime.GOOS {
659         case "darwin", "dragonfly", "freebsd", "netbsd", "openbsd", "plan9", "illumos", "solaris", "windows":
660                 // Non-Linux systems take a long time to figure
661                 // out that there is nothing listening on localhost.
662                 n = 100
663         }
664         for i := 0; i < n; i++ {
665                 d.Timeout = time.Millisecond
666                 c, err := d.Dial(network, laddr.String())
667                 if err == nil {
668                         addr := c.LocalAddr().(*TCPAddr)
669                         if addr.Port == laddr.Port || addr.IP.Equal(laddr.IP) {
670                                 t.Errorf("Dial %v should fail", addr)
671                         } else {
672                                 t.Logf("Dial %v succeeded - possibly racing with other listener", addr)
673                         }
674                         c.Close()
675                 }
676         }
677 }
678
679 // Test that >32-bit reads work on 64-bit systems.
680 // On 32-bit systems this tests that maxint reads work.
681 func TestTCPBig(t *testing.T) {
682         if !*testTCPBig {
683                 t.Skip("test disabled; use -tcpbig to enable")
684         }
685
686         for _, writev := range []bool{false, true} {
687                 t.Run(fmt.Sprintf("writev=%v", writev), func(t *testing.T) {
688                         ln, err := newLocalListener("tcp")
689                         if err != nil {
690                                 t.Fatal(err)
691                         }
692                         defer ln.Close()
693
694                         x := int(1 << 30)
695                         x = x*5 + 1<<20 // just over 5 GB on 64-bit, just over 1GB on 32-bit
696                         done := make(chan int)
697                         go func() {
698                                 defer close(done)
699                                 c, err := ln.Accept()
700                                 if err != nil {
701                                         t.Error(err)
702                                         return
703                                 }
704                                 buf := make([]byte, x)
705                                 var n int
706                                 if writev {
707                                         var n64 int64
708                                         n64, err = (&Buffers{buf}).WriteTo(c)
709                                         n = int(n64)
710                                 } else {
711                                         n, err = c.Write(buf)
712                                 }
713                                 if n != len(buf) || err != nil {
714                                         t.Errorf("Write(buf) = %d, %v, want %d, nil", n, err, x)
715                                 }
716                                 c.Close()
717                         }()
718
719                         c, err := Dial("tcp", ln.Addr().String())
720                         if err != nil {
721                                 t.Fatal(err)
722                         }
723                         buf := make([]byte, x)
724                         n, err := io.ReadFull(c, buf)
725                         if n != len(buf) || err != nil {
726                                 t.Errorf("Read(buf) = %d, %v, want %d, nil", n, err, x)
727                         }
728                         c.Close()
729                         <-done
730                 })
731         }
732 }
733
734 func TestCopyPipeIntoTCP(t *testing.T) {
735         ln, err := newLocalListener("tcp")
736         if err != nil {
737                 t.Fatal(err)
738         }
739         defer ln.Close()
740
741         errc := make(chan error, 1)
742         defer func() {
743                 if err := <-errc; err != nil {
744                         t.Error(err)
745                 }
746         }()
747         go func() {
748                 c, err := ln.Accept()
749                 if err != nil {
750                         errc <- err
751                         return
752                 }
753                 defer c.Close()
754
755                 buf := make([]byte, 100)
756                 n, err := io.ReadFull(c, buf)
757                 if err != io.ErrUnexpectedEOF || n != 2 {
758                         errc <- fmt.Errorf("got err=%q n=%v; want err=%q n=2", err, n, io.ErrUnexpectedEOF)
759                         return
760                 }
761
762                 errc <- nil
763         }()
764
765         c, err := Dial("tcp", ln.Addr().String())
766         if err != nil {
767                 t.Fatal(err)
768         }
769         defer c.Close()
770
771         r, w, err := os.Pipe()
772         if err != nil {
773                 t.Fatal(err)
774         }
775         defer r.Close()
776
777         errc2 := make(chan error, 1)
778         defer func() {
779                 if err := <-errc2; err != nil {
780                         t.Error(err)
781                 }
782         }()
783
784         defer w.Close()
785
786         go func() {
787                 _, err := io.Copy(c, r)
788                 errc2 <- err
789         }()
790
791         // Split write into 2 packets. That makes Windows TransmitFile
792         // drop second packet.
793         packet := make([]byte, 1)
794         _, err = w.Write(packet)
795         if err != nil {
796                 t.Fatal(err)
797         }
798         time.Sleep(100 * time.Millisecond)
799         _, err = w.Write(packet)
800         if err != nil {
801                 t.Fatal(err)
802         }
803 }
804
805 func BenchmarkSetReadDeadline(b *testing.B) {
806         ln, err := newLocalListener("tcp")
807         if err != nil {
808                 b.Fatal(err)
809         }
810         defer ln.Close()
811         var serv Conn
812         done := make(chan error)
813         go func() {
814                 var err error
815                 serv, err = ln.Accept()
816                 done <- err
817         }()
818         c, err := Dial("tcp", ln.Addr().String())
819         if err != nil {
820                 b.Fatal(err)
821         }
822         defer c.Close()
823         if err := <-done; err != nil {
824                 b.Fatal(err)
825         }
826         defer serv.Close()
827         c.SetWriteDeadline(time.Now().Add(2 * time.Hour))
828         deadline := time.Now().Add(time.Hour)
829         b.ResetTimer()
830         for i := 0; i < b.N; i++ {
831                 c.SetReadDeadline(deadline)
832                 deadline = deadline.Add(1)
833         }
834 }