1// Copyright 2009 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//go:build !js 6 7package net 8 9import ( 10 "errors" 11 "fmt" 12 "internal/testenv" 13 "io" 14 "net/internal/socktest" 15 "os" 16 "runtime" 17 "testing" 18 "time" 19) 20 21func TestCloseRead(t *testing.T) { 22 switch runtime.GOOS { 23 case "plan9": 24 t.Skipf("not supported on %s", runtime.GOOS) 25 } 26 t.Parallel() 27 28 for _, network := range []string{"tcp", "unix", "unixpacket"} { 29 network := network 30 t.Run(network, func(t *testing.T) { 31 if !testableNetwork(network) { 32 t.Skipf("network %s is not testable on the current platform", network) 33 } 34 t.Parallel() 35 36 ln := newLocalListener(t, network) 37 switch network { 38 case "unix", "unixpacket": 39 defer os.Remove(ln.Addr().String()) 40 } 41 defer ln.Close() 42 43 c, err := Dial(ln.Addr().Network(), ln.Addr().String()) 44 if err != nil { 45 t.Fatal(err) 46 } 47 switch network { 48 case "unix", "unixpacket": 49 defer os.Remove(c.LocalAddr().String()) 50 } 51 defer c.Close() 52 53 switch c := c.(type) { 54 case *TCPConn: 55 err = c.CloseRead() 56 case *UnixConn: 57 err = c.CloseRead() 58 } 59 if err != nil { 60 if perr := parseCloseError(err, true); perr != nil { 61 t.Error(perr) 62 } 63 t.Fatal(err) 64 } 65 var b [1]byte 66 n, err := c.Read(b[:]) 67 if n != 0 || err == nil { 68 t.Fatalf("got (%d, %v); want (0, error)", n, err) 69 } 70 }) 71 } 72} 73 74func TestCloseWrite(t *testing.T) { 75 switch runtime.GOOS { 76 case "plan9": 77 t.Skipf("not supported on %s", runtime.GOOS) 78 } 79 80 t.Parallel() 81 deadline, _ := t.Deadline() 82 if !deadline.IsZero() { 83 // Leave 10% headroom on the deadline to report errors and clean up. 84 deadline = deadline.Add(-time.Until(deadline) / 10) 85 } 86 87 for _, network := range []string{"tcp", "unix", "unixpacket"} { 88 network := network 89 t.Run(network, func(t *testing.T) { 90 if !testableNetwork(network) { 91 t.Skipf("network %s is not testable on the current platform", network) 92 } 93 t.Parallel() 94 95 handler := func(ls *localServer, ln Listener) { 96 c, err := ln.Accept() 97 if err != nil { 98 t.Error(err) 99 return 100 } 101 if !deadline.IsZero() { 102 c.SetDeadline(deadline) 103 } 104 defer c.Close() 105 106 var b [1]byte 107 n, err := c.Read(b[:]) 108 if n != 0 || err != io.EOF { 109 t.Errorf("got (%d, %v); want (0, io.EOF)", n, err) 110 return 111 } 112 switch c := c.(type) { 113 case *TCPConn: 114 err = c.CloseWrite() 115 case *UnixConn: 116 err = c.CloseWrite() 117 } 118 if err != nil { 119 if perr := parseCloseError(err, true); perr != nil { 120 t.Error(perr) 121 } 122 t.Error(err) 123 return 124 } 125 n, err = c.Write(b[:]) 126 if err == nil { 127 t.Errorf("got (%d, %v); want (any, error)", n, err) 128 return 129 } 130 } 131 132 ls := newLocalServer(t, network) 133 defer ls.teardown() 134 if err := ls.buildup(handler); err != nil { 135 t.Fatal(err) 136 } 137 138 c, err := Dial(ls.Listener.Addr().Network(), ls.Listener.Addr().String()) 139 if err != nil { 140 t.Fatal(err) 141 } 142 if !deadline.IsZero() { 143 c.SetDeadline(deadline) 144 } 145 switch network { 146 case "unix", "unixpacket": 147 defer os.Remove(c.LocalAddr().String()) 148 } 149 defer c.Close() 150 151 switch c := c.(type) { 152 case *TCPConn: 153 err = c.CloseWrite() 154 case *UnixConn: 155 err = c.CloseWrite() 156 } 157 if err != nil { 158 if perr := parseCloseError(err, true); perr != nil { 159 t.Error(perr) 160 } 161 t.Fatal(err) 162 } 163 var b [1]byte 164 n, err := c.Read(b[:]) 165 if n != 0 || err != io.EOF { 166 t.Fatalf("got (%d, %v); want (0, io.EOF)", n, err) 167 } 168 n, err = c.Write(b[:]) 169 if err == nil { 170 t.Fatalf("got (%d, %v); want (any, error)", n, err) 171 } 172 }) 173 } 174} 175 176func TestConnClose(t *testing.T) { 177 t.Parallel() 178 for _, network := range []string{"tcp", "unix", "unixpacket"} { 179 network := network 180 t.Run(network, func(t *testing.T) { 181 if !testableNetwork(network) { 182 t.Skipf("network %s is not testable on the current platform", network) 183 } 184 t.Parallel() 185 186 ln := newLocalListener(t, network) 187 switch network { 188 case "unix", "unixpacket": 189 defer os.Remove(ln.Addr().String()) 190 } 191 defer ln.Close() 192 193 c, err := Dial(ln.Addr().Network(), ln.Addr().String()) 194 if err != nil { 195 t.Fatal(err) 196 } 197 switch network { 198 case "unix", "unixpacket": 199 defer os.Remove(c.LocalAddr().String()) 200 } 201 defer c.Close() 202 203 if err := c.Close(); err != nil { 204 if perr := parseCloseError(err, false); perr != nil { 205 t.Error(perr) 206 } 207 t.Fatal(err) 208 } 209 var b [1]byte 210 n, err := c.Read(b[:]) 211 if n != 0 || err == nil { 212 t.Fatalf("got (%d, %v); want (0, error)", n, err) 213 } 214 }) 215 } 216} 217 218func TestListenerClose(t *testing.T) { 219 t.Parallel() 220 for _, network := range []string{"tcp", "unix", "unixpacket"} { 221 network := network 222 t.Run(network, func(t *testing.T) { 223 if !testableNetwork(network) { 224 t.Skipf("network %s is not testable on the current platform", network) 225 } 226 t.Parallel() 227 228 ln := newLocalListener(t, network) 229 switch network { 230 case "unix", "unixpacket": 231 defer os.Remove(ln.Addr().String()) 232 } 233 234 if err := ln.Close(); err != nil { 235 if perr := parseCloseError(err, false); perr != nil { 236 t.Error(perr) 237 } 238 t.Fatal(err) 239 } 240 c, err := ln.Accept() 241 if err == nil { 242 c.Close() 243 t.Fatal("should fail") 244 } 245 246 // Note: we cannot ensure that a subsequent Dial does not succeed, because 247 // we do not in general have any guarantee that ln.Addr is not immediately 248 // reused. (TCP sockets enter a TIME_WAIT state when closed, but that only 249 // applies to existing connections for the port — it does not prevent the 250 // port itself from being used for entirely new connections in the 251 // meantime.) 252 }) 253 } 254} 255 256func TestPacketConnClose(t *testing.T) { 257 t.Parallel() 258 for _, network := range []string{"udp", "unixgram"} { 259 network := network 260 t.Run(network, func(t *testing.T) { 261 if !testableNetwork(network) { 262 t.Skipf("network %s is not testable on the current platform", network) 263 } 264 t.Parallel() 265 266 c := newLocalPacketListener(t, network) 267 switch network { 268 case "unixgram": 269 defer os.Remove(c.LocalAddr().String()) 270 } 271 defer c.Close() 272 273 if err := c.Close(); err != nil { 274 if perr := parseCloseError(err, false); perr != nil { 275 t.Error(perr) 276 } 277 t.Fatal(err) 278 } 279 var b [1]byte 280 n, _, err := c.ReadFrom(b[:]) 281 if n != 0 || err == nil { 282 t.Fatalf("got (%d, %v); want (0, error)", n, err) 283 } 284 }) 285 } 286} 287 288func TestListenCloseListen(t *testing.T) { 289 const maxTries = 10 290 for tries := 0; tries < maxTries; tries++ { 291 ln := newLocalListener(t, "tcp") 292 addr := ln.Addr().String() 293 // TODO: This is racy. The selected address could be reused in between this 294 // Close and the subsequent Listen. 295 if err := ln.Close(); err != nil { 296 if perr := parseCloseError(err, false); perr != nil { 297 t.Error(perr) 298 } 299 t.Fatal(err) 300 } 301 ln, err := Listen("tcp", addr) 302 if err == nil { 303 // Success. (This test didn't always make it here earlier.) 304 ln.Close() 305 return 306 } 307 t.Errorf("failed on try %d/%d: %v", tries+1, maxTries, err) 308 } 309 t.Fatalf("failed to listen/close/listen on same address after %d tries", maxTries) 310} 311 312// See golang.org/issue/6163, golang.org/issue/6987. 313func TestAcceptIgnoreAbortedConnRequest(t *testing.T) { 314 switch runtime.GOOS { 315 case "plan9": 316 t.Skipf("%s does not have full support of socktest", runtime.GOOS) 317 } 318 319 syserr := make(chan error) 320 go func() { 321 defer close(syserr) 322 for _, err := range abortedConnRequestErrors { 323 syserr <- err 324 } 325 }() 326 sw.Set(socktest.FilterAccept, func(so *socktest.Status) (socktest.AfterFilter, error) { 327 if err, ok := <-syserr; ok { 328 return nil, err 329 } 330 return nil, nil 331 }) 332 defer sw.Set(socktest.FilterAccept, nil) 333 334 operr := make(chan error, 1) 335 handler := func(ls *localServer, ln Listener) { 336 defer close(operr) 337 c, err := ln.Accept() 338 if err != nil { 339 if perr := parseAcceptError(err); perr != nil { 340 operr <- perr 341 } 342 operr <- err 343 return 344 } 345 c.Close() 346 } 347 ls := newLocalServer(t, "tcp") 348 defer ls.teardown() 349 if err := ls.buildup(handler); err != nil { 350 t.Fatal(err) 351 } 352 353 c, err := Dial(ls.Listener.Addr().Network(), ls.Listener.Addr().String()) 354 if err != nil { 355 t.Fatal(err) 356 } 357 c.Close() 358 359 for err := range operr { 360 t.Error(err) 361 } 362} 363 364func TestZeroByteRead(t *testing.T) { 365 t.Parallel() 366 for _, network := range []string{"tcp", "unix", "unixpacket"} { 367 network := network 368 t.Run(network, func(t *testing.T) { 369 if !testableNetwork(network) { 370 t.Skipf("network %s is not testable on the current platform", network) 371 } 372 t.Parallel() 373 374 ln := newLocalListener(t, network) 375 connc := make(chan Conn, 1) 376 go func() { 377 defer ln.Close() 378 c, err := ln.Accept() 379 if err != nil { 380 t.Error(err) 381 } 382 connc <- c // might be nil 383 }() 384 c, err := Dial(network, ln.Addr().String()) 385 if err != nil { 386 t.Fatal(err) 387 } 388 defer c.Close() 389 sc := <-connc 390 if sc == nil { 391 return 392 } 393 defer sc.Close() 394 395 if runtime.GOOS == "windows" { 396 // A zero byte read on Windows caused a wait for readability first. 397 // Rather than change that behavior, satisfy it in this test. 398 // See Issue 15735. 399 go io.WriteString(sc, "a") 400 } 401 402 n, err := c.Read(nil) 403 if n != 0 || err != nil { 404 t.Errorf("%s: zero byte client read = %v, %v; want 0, nil", network, n, err) 405 } 406 407 if runtime.GOOS == "windows" { 408 // Same as comment above. 409 go io.WriteString(c, "a") 410 } 411 n, err = sc.Read(nil) 412 if n != 0 || err != nil { 413 t.Errorf("%s: zero byte server read = %v, %v; want 0, nil", network, n, err) 414 } 415 }) 416 } 417} 418 419// withTCPConnPair sets up a TCP connection between two peers, then 420// runs peer1 and peer2 concurrently. withTCPConnPair returns when 421// both have completed. 422func withTCPConnPair(t *testing.T, peer1, peer2 func(c *TCPConn) error) { 423 ln := newLocalListener(t, "tcp") 424 defer ln.Close() 425 errc := make(chan error, 2) 426 go func() { 427 c1, err := ln.Accept() 428 if err != nil { 429 errc <- err 430 return 431 } 432 defer c1.Close() 433 errc <- peer1(c1.(*TCPConn)) 434 }() 435 go func() { 436 c2, err := Dial("tcp", ln.Addr().String()) 437 if err != nil { 438 errc <- err 439 return 440 } 441 defer c2.Close() 442 errc <- peer2(c2.(*TCPConn)) 443 }() 444 for i := 0; i < 2; i++ { 445 if err := <-errc; err != nil { 446 t.Fatal(err) 447 } 448 } 449} 450 451// Tests that a blocked Read is interrupted by a concurrent SetReadDeadline 452// modifying that Conn's read deadline to the past. 453// See golang.org/cl/30164 which documented this. The net/http package 454// depends on this. 455func TestReadTimeoutUnblocksRead(t *testing.T) { 456 serverDone := make(chan struct{}) 457 server := func(cs *TCPConn) error { 458 defer close(serverDone) 459 errc := make(chan error, 1) 460 go func() { 461 defer close(errc) 462 go func() { 463 // TODO: find a better way to wait 464 // until we're blocked in the cs.Read 465 // call below. Sleep is lame. 466 time.Sleep(100 * time.Millisecond) 467 468 // Interrupt the upcoming Read, unblocking it: 469 cs.SetReadDeadline(time.Unix(123, 0)) // time in the past 470 }() 471 var buf [1]byte 472 n, err := cs.Read(buf[:1]) 473 if n != 0 || err == nil { 474 errc <- fmt.Errorf("Read = %v, %v; want 0, non-nil", n, err) 475 } 476 }() 477 select { 478 case err := <-errc: 479 return err 480 case <-time.After(5 * time.Second): 481 buf := make([]byte, 2<<20) 482 buf = buf[:runtime.Stack(buf, true)] 483 println("Stacks at timeout:\n", string(buf)) 484 return errors.New("timeout waiting for Read to finish") 485 } 486 487 } 488 // Do nothing in the client. Never write. Just wait for the 489 // server's half to be done. 490 client := func(*TCPConn) error { 491 <-serverDone 492 return nil 493 } 494 withTCPConnPair(t, client, server) 495} 496 497// Issue 17695: verify that a blocked Read is woken up by a Close. 498func TestCloseUnblocksRead(t *testing.T) { 499 t.Parallel() 500 server := func(cs *TCPConn) error { 501 // Give the client time to get stuck in a Read: 502 time.Sleep(20 * time.Millisecond) 503 cs.Close() 504 return nil 505 } 506 client := func(ss *TCPConn) error { 507 n, err := ss.Read([]byte{0}) 508 if n != 0 || err != io.EOF { 509 return fmt.Errorf("Read = %v, %v; want 0, EOF", n, err) 510 } 511 return nil 512 } 513 withTCPConnPair(t, client, server) 514} 515 516// Issue 24808: verify that ECONNRESET is not temporary for read. 517func TestNotTemporaryRead(t *testing.T) { 518 if runtime.GOOS == "freebsd" { 519 testenv.SkipFlaky(t, 25289) 520 } 521 if runtime.GOOS == "aix" { 522 testenv.SkipFlaky(t, 29685) 523 } 524 t.Parallel() 525 server := func(cs *TCPConn) error { 526 cs.SetLinger(0) 527 // Give the client time to get stuck in a Read. 528 time.Sleep(50 * time.Millisecond) 529 cs.Close() 530 return nil 531 } 532 client := func(ss *TCPConn) error { 533 _, err := ss.Read([]byte{0}) 534 if err == nil { 535 return errors.New("Read succeeded unexpectedly") 536 } else if err == io.EOF { 537 // This happens on Plan 9. 538 return nil 539 } else if ne, ok := err.(Error); !ok { 540 return fmt.Errorf("unexpected error %v", err) 541 } else if ne.Temporary() { 542 return fmt.Errorf("unexpected temporary error %v", err) 543 } 544 return nil 545 } 546 withTCPConnPair(t, client, server) 547} 548 549// The various errors should implement the Error interface. 550func TestErrors(t *testing.T) { 551 var ( 552 _ Error = &OpError{} 553 _ Error = &ParseError{} 554 _ Error = &AddrError{} 555 _ Error = UnknownNetworkError("") 556 _ Error = InvalidAddrError("") 557 _ Error = &timeoutError{} 558 _ Error = &DNSConfigError{} 559 _ Error = &DNSError{} 560 ) 561 562 // ErrClosed was introduced as type error, so we can't check 563 // it using a declaration. 564 if _, ok := ErrClosed.(Error); !ok { 565 t.Fatal("ErrClosed does not implement Error") 566 } 567} 568