github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/os/timeout_test.go (about) 1 // Copyright 2017 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 !nacl 6 // +build !js 7 // +build !plan9 8 // +build !windows 9 10 package os_test 11 12 import ( 13 "fmt" 14 "internal/poll" 15 "io" 16 "io/ioutil" 17 "math/rand" 18 "os" 19 "os/signal" 20 "runtime" 21 "sync" 22 "syscall" 23 "testing" 24 "time" 25 ) 26 27 func TestNonpollableDeadline(t *testing.T) { 28 // On BSD systems regular files seem to be pollable, 29 // so just run this test on Linux. 30 if runtime.GOOS != "linux" { 31 t.Skipf("skipping on %s", runtime.GOOS) 32 } 33 34 f, err := ioutil.TempFile("", "ostest") 35 if err != nil { 36 t.Fatal(err) 37 } 38 defer os.Remove(f.Name()) 39 defer f.Close() 40 deadline := time.Now().Add(10 * time.Second) 41 if err := f.SetDeadline(deadline); err != os.ErrNoDeadline { 42 t.Errorf("SetDeadline on file returned %v, wanted %v", err, os.ErrNoDeadline) 43 } 44 if err := f.SetReadDeadline(deadline); err != os.ErrNoDeadline { 45 t.Errorf("SetReadDeadline on file returned %v, wanted %v", err, os.ErrNoDeadline) 46 } 47 if err := f.SetWriteDeadline(deadline); err != os.ErrNoDeadline { 48 t.Errorf("SetWriteDeadline on file returned %v, wanted %v", err, os.ErrNoDeadline) 49 } 50 } 51 52 // noDeadline is a zero time.Time value, which cancels a deadline. 53 var noDeadline time.Time 54 55 var readTimeoutTests = []struct { 56 timeout time.Duration 57 xerrs [2]error // expected errors in transition 58 }{ 59 // Tests that read deadlines work, even if there's data ready 60 // to be read. 61 {-5 * time.Second, [2]error{poll.ErrTimeout, poll.ErrTimeout}}, 62 63 {50 * time.Millisecond, [2]error{nil, poll.ErrTimeout}}, 64 } 65 66 func TestReadTimeout(t *testing.T) { 67 t.Parallel() 68 69 r, w, err := os.Pipe() 70 if err != nil { 71 t.Fatal(err) 72 } 73 defer r.Close() 74 defer w.Close() 75 76 if _, err := w.Write([]byte("READ TIMEOUT TEST")); err != nil { 77 t.Fatal(err) 78 } 79 80 for i, tt := range readTimeoutTests { 81 if err := r.SetReadDeadline(time.Now().Add(tt.timeout)); err != nil { 82 t.Fatalf("#%d: %v", i, err) 83 } 84 var b [1]byte 85 for j, xerr := range tt.xerrs { 86 for { 87 n, err := r.Read(b[:]) 88 if xerr != nil { 89 if !os.IsTimeout(err) { 90 t.Fatalf("#%d/%d: %v", i, j, err) 91 } 92 } 93 if err == nil { 94 time.Sleep(tt.timeout / 3) 95 continue 96 } 97 if n != 0 { 98 t.Fatalf("#%d/%d: read %d; want 0", i, j, n) 99 } 100 break 101 } 102 } 103 } 104 } 105 106 func TestReadTimeoutMustNotReturn(t *testing.T) { 107 t.Parallel() 108 109 r, w, err := os.Pipe() 110 if err != nil { 111 t.Fatal(err) 112 } 113 defer r.Close() 114 defer w.Close() 115 116 max := time.NewTimer(100 * time.Millisecond) 117 defer max.Stop() 118 ch := make(chan error) 119 go func() { 120 if err := r.SetDeadline(time.Now().Add(-5 * time.Second)); err != nil { 121 t.Error(err) 122 } 123 if err := r.SetWriteDeadline(time.Now().Add(-5 * time.Second)); err != nil { 124 t.Error(err) 125 } 126 if err := r.SetReadDeadline(noDeadline); err != nil { 127 t.Error(err) 128 } 129 var b [1]byte 130 _, err := r.Read(b[:]) 131 ch <- err 132 }() 133 134 select { 135 case err := <-ch: 136 t.Fatalf("expected Read to not return, but it returned with %v", err) 137 case <-max.C: 138 w.Close() 139 err := <-ch // wait for tester goroutine to stop 140 if os.IsTimeout(err) { 141 t.Fatal(err) 142 } 143 } 144 } 145 146 var writeTimeoutTests = []struct { 147 timeout time.Duration 148 xerrs [2]error // expected errors in transition 149 }{ 150 // Tests that write deadlines work, even if there's buffer 151 // space available to write. 152 {-5 * time.Second, [2]error{poll.ErrTimeout, poll.ErrTimeout}}, 153 154 {10 * time.Millisecond, [2]error{nil, poll.ErrTimeout}}, 155 } 156 157 func TestWriteTimeout(t *testing.T) { 158 t.Parallel() 159 160 for i, tt := range writeTimeoutTests { 161 t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) { 162 r, w, err := os.Pipe() 163 if err != nil { 164 t.Fatal(err) 165 } 166 defer r.Close() 167 defer w.Close() 168 169 if err := w.SetWriteDeadline(time.Now().Add(tt.timeout)); err != nil { 170 t.Fatalf("%v", err) 171 } 172 for j, xerr := range tt.xerrs { 173 for { 174 n, err := w.Write([]byte("WRITE TIMEOUT TEST")) 175 if xerr != nil { 176 if !os.IsTimeout(err) { 177 t.Fatalf("%d: %v", j, err) 178 } 179 } 180 if err == nil { 181 time.Sleep(tt.timeout / 3) 182 continue 183 } 184 if n != 0 { 185 t.Fatalf("%d: wrote %d; want 0", j, n) 186 } 187 break 188 } 189 } 190 }) 191 } 192 } 193 194 func TestWriteTimeoutMustNotReturn(t *testing.T) { 195 t.Parallel() 196 197 r, w, err := os.Pipe() 198 if err != nil { 199 t.Fatal(err) 200 } 201 defer r.Close() 202 defer w.Close() 203 204 max := time.NewTimer(100 * time.Millisecond) 205 defer max.Stop() 206 ch := make(chan error) 207 go func() { 208 if err := w.SetDeadline(time.Now().Add(-5 * time.Second)); err != nil { 209 t.Error(err) 210 } 211 if err := w.SetReadDeadline(time.Now().Add(-5 * time.Second)); err != nil { 212 t.Error(err) 213 } 214 if err := w.SetWriteDeadline(noDeadline); err != nil { 215 t.Error(err) 216 } 217 var b [1]byte 218 for { 219 if _, err := w.Write(b[:]); err != nil { 220 ch <- err 221 break 222 } 223 } 224 }() 225 226 select { 227 case err := <-ch: 228 t.Fatalf("expected Write to not return, but it returned with %v", err) 229 case <-max.C: 230 r.Close() 231 err := <-ch // wait for tester goroutine to stop 232 if os.IsTimeout(err) { 233 t.Fatal(err) 234 } 235 } 236 } 237 238 func timeoutReader(r *os.File, d, min, max time.Duration, ch chan<- error) { 239 var err error 240 defer func() { ch <- err }() 241 242 t0 := time.Now() 243 if err = r.SetReadDeadline(time.Now().Add(d)); err != nil { 244 return 245 } 246 b := make([]byte, 256) 247 var n int 248 n, err = r.Read(b) 249 t1 := time.Now() 250 if n != 0 || err == nil || !os.IsTimeout(err) { 251 err = fmt.Errorf("Read did not return (0, timeout): (%d, %v)", n, err) 252 return 253 } 254 if dt := t1.Sub(t0); min > dt || dt > max && !testing.Short() { 255 err = fmt.Errorf("Read took %s; expected %s", dt, d) 256 return 257 } 258 } 259 260 func TestReadTimeoutFluctuation(t *testing.T) { 261 t.Parallel() 262 263 r, w, err := os.Pipe() 264 if err != nil { 265 t.Fatal(err) 266 } 267 defer r.Close() 268 defer w.Close() 269 270 max := time.NewTimer(time.Second) 271 defer max.Stop() 272 ch := make(chan error) 273 go timeoutReader(r, 100*time.Millisecond, 50*time.Millisecond, 250*time.Millisecond, ch) 274 275 select { 276 case <-max.C: 277 t.Fatal("Read took over 1s; expected 0.1s") 278 case err := <-ch: 279 if !os.IsTimeout(err) { 280 t.Fatal(err) 281 } 282 } 283 } 284 285 func timeoutWriter(w *os.File, d, min, max time.Duration, ch chan<- error) { 286 var err error 287 defer func() { ch <- err }() 288 289 t0 := time.Now() 290 if err = w.SetWriteDeadline(time.Now().Add(d)); err != nil { 291 return 292 } 293 var n int 294 for { 295 n, err = w.Write([]byte("TIMEOUT WRITER")) 296 if err != nil { 297 break 298 } 299 } 300 t1 := time.Now() 301 if err == nil || !os.IsTimeout(err) { 302 err = fmt.Errorf("Write did not return (any, timeout): (%d, %v)", n, err) 303 return 304 } 305 if dt := t1.Sub(t0); min > dt || dt > max && !testing.Short() { 306 err = fmt.Errorf("Write took %s; expected %s", dt, d) 307 return 308 } 309 } 310 311 func TestWriteTimeoutFluctuation(t *testing.T) { 312 t.Parallel() 313 314 r, w, err := os.Pipe() 315 if err != nil { 316 t.Fatal(err) 317 } 318 defer r.Close() 319 defer w.Close() 320 321 d := time.Second 322 max := time.NewTimer(d) 323 defer max.Stop() 324 ch := make(chan error) 325 go timeoutWriter(w, 100*time.Millisecond, 50*time.Millisecond, 250*time.Millisecond, ch) 326 327 select { 328 case <-max.C: 329 t.Fatalf("Write took over %v; expected 0.1s", d) 330 case err := <-ch: 331 if !os.IsTimeout(err) { 332 t.Fatal(err) 333 } 334 } 335 } 336 337 func TestVariousDeadlines(t *testing.T) { 338 t.Parallel() 339 testVariousDeadlines(t) 340 } 341 342 func TestVariousDeadlines1Proc(t *testing.T) { 343 // Cannot use t.Parallel - modifies global GOMAXPROCS. 344 if testing.Short() { 345 t.Skip("skipping in short mode") 346 } 347 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1)) 348 testVariousDeadlines(t) 349 } 350 351 func TestVariousDeadlines4Proc(t *testing.T) { 352 // Cannot use t.Parallel - modifies global GOMAXPROCS. 353 if testing.Short() { 354 t.Skip("skipping in short mode") 355 } 356 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) 357 testVariousDeadlines(t) 358 } 359 360 type neverEnding byte 361 362 func (b neverEnding) Read(p []byte) (int, error) { 363 for i := range p { 364 p[i] = byte(b) 365 } 366 return len(p), nil 367 } 368 369 func testVariousDeadlines(t *testing.T) { 370 type result struct { 371 n int64 372 err error 373 d time.Duration 374 } 375 376 handler := func(w *os.File, pasvch chan result) { 377 // The writer, with no timeouts of its own, 378 // sending bytes to clients as fast as it can. 379 t0 := time.Now() 380 n, err := io.Copy(w, neverEnding('a')) 381 dt := time.Since(t0) 382 pasvch <- result{n, err, dt} 383 } 384 385 for _, timeout := range []time.Duration{ 386 1 * time.Nanosecond, 387 2 * time.Nanosecond, 388 5 * time.Nanosecond, 389 50 * time.Nanosecond, 390 100 * time.Nanosecond, 391 200 * time.Nanosecond, 392 500 * time.Nanosecond, 393 750 * time.Nanosecond, 394 1 * time.Microsecond, 395 5 * time.Microsecond, 396 25 * time.Microsecond, 397 250 * time.Microsecond, 398 500 * time.Microsecond, 399 1 * time.Millisecond, 400 5 * time.Millisecond, 401 100 * time.Millisecond, 402 250 * time.Millisecond, 403 500 * time.Millisecond, 404 1 * time.Second, 405 } { 406 numRuns := 3 407 if testing.Short() { 408 numRuns = 1 409 if timeout > 500*time.Microsecond { 410 continue 411 } 412 } 413 for run := 0; run < numRuns; run++ { 414 t.Run(fmt.Sprintf("%v-%d", timeout, run+1), func(t *testing.T) { 415 r, w, err := os.Pipe() 416 if err != nil { 417 t.Fatal(err) 418 } 419 defer r.Close() 420 defer w.Close() 421 422 pasvch := make(chan result) 423 go handler(w, pasvch) 424 425 tooLong := 5 * time.Second 426 max := time.NewTimer(tooLong) 427 defer max.Stop() 428 actvch := make(chan result) 429 go func() { 430 t0 := time.Now() 431 if err := r.SetDeadline(t0.Add(timeout)); err != nil { 432 t.Error(err) 433 } 434 n, err := io.Copy(ioutil.Discard, r) 435 dt := time.Since(t0) 436 r.Close() 437 actvch <- result{n, err, dt} 438 }() 439 440 select { 441 case res := <-actvch: 442 if os.IsTimeout(res.err) { 443 t.Logf("good client timeout after %v, reading %d bytes", res.d, res.n) 444 } else { 445 t.Fatalf("client Copy = %d, %v; want timeout", res.n, res.err) 446 } 447 case <-max.C: 448 t.Fatalf("timeout (%v) waiting for client to timeout (%v) reading", tooLong, timeout) 449 } 450 451 select { 452 case res := <-pasvch: 453 t.Logf("writer in %v wrote %d: %v", res.d, res.n, res.err) 454 case <-max.C: 455 t.Fatalf("timeout waiting for writer to finish writing") 456 } 457 }) 458 } 459 } 460 } 461 462 func TestReadWriteDeadlineRace(t *testing.T) { 463 t.Parallel() 464 465 N := 1000 466 if testing.Short() { 467 N = 50 468 } 469 470 r, w, err := os.Pipe() 471 if err != nil { 472 t.Fatal(err) 473 } 474 defer r.Close() 475 defer w.Close() 476 477 var wg sync.WaitGroup 478 wg.Add(3) 479 go func() { 480 defer wg.Done() 481 tic := time.NewTicker(2 * time.Microsecond) 482 defer tic.Stop() 483 for i := 0; i < N; i++ { 484 if err := r.SetReadDeadline(time.Now().Add(2 * time.Microsecond)); err != nil { 485 break 486 } 487 if err := w.SetWriteDeadline(time.Now().Add(2 * time.Microsecond)); err != nil { 488 break 489 } 490 <-tic.C 491 } 492 }() 493 go func() { 494 defer wg.Done() 495 var b [1]byte 496 for i := 0; i < N; i++ { 497 _, err := r.Read(b[:]) 498 if err != nil && !os.IsTimeout(err) { 499 t.Error("Read returned non-timeout error", err) 500 } 501 } 502 }() 503 go func() { 504 defer wg.Done() 505 var b [1]byte 506 for i := 0; i < N; i++ { 507 _, err := w.Write(b[:]) 508 if err != nil && !os.IsTimeout(err) { 509 t.Error("Write returned non-timeout error", err) 510 } 511 } 512 }() 513 wg.Wait() // wait for tester goroutine to stop 514 } 515 516 // TestRacyRead tests that it is safe to mutate the input Read buffer 517 // immediately after cancelation has occurred. 518 func TestRacyRead(t *testing.T) { 519 t.Parallel() 520 521 r, w, err := os.Pipe() 522 if err != nil { 523 t.Fatal(err) 524 } 525 defer r.Close() 526 defer w.Close() 527 528 var wg sync.WaitGroup 529 defer wg.Wait() 530 531 go io.Copy(w, rand.New(rand.NewSource(0))) 532 533 r.SetReadDeadline(time.Now().Add(time.Millisecond)) 534 for i := 0; i < 10; i++ { 535 wg.Add(1) 536 go func() { 537 defer wg.Done() 538 539 b1 := make([]byte, 1024) 540 b2 := make([]byte, 1024) 541 for j := 0; j < 100; j++ { 542 _, err := r.Read(b1) 543 copy(b1, b2) // Mutate b1 to trigger potential race 544 if err != nil { 545 if !os.IsTimeout(err) { 546 t.Error(err) 547 } 548 r.SetReadDeadline(time.Now().Add(time.Millisecond)) 549 } 550 } 551 }() 552 } 553 } 554 555 // TestRacyWrite tests that it is safe to mutate the input Write buffer 556 // immediately after cancelation has occurred. 557 func TestRacyWrite(t *testing.T) { 558 t.Parallel() 559 560 r, w, err := os.Pipe() 561 if err != nil { 562 t.Fatal(err) 563 } 564 defer r.Close() 565 defer w.Close() 566 567 var wg sync.WaitGroup 568 defer wg.Wait() 569 570 go io.Copy(ioutil.Discard, r) 571 572 w.SetWriteDeadline(time.Now().Add(time.Millisecond)) 573 for i := 0; i < 10; i++ { 574 wg.Add(1) 575 go func() { 576 defer wg.Done() 577 578 b1 := make([]byte, 1024) 579 b2 := make([]byte, 1024) 580 for j := 0; j < 100; j++ { 581 _, err := w.Write(b1) 582 copy(b1, b2) // Mutate b1 to trigger potential race 583 if err != nil { 584 if !os.IsTimeout(err) { 585 t.Error(err) 586 } 587 w.SetWriteDeadline(time.Now().Add(time.Millisecond)) 588 } 589 } 590 }() 591 } 592 } 593 594 // Closing a TTY while reading from it should not hang. Issue 23943. 595 func TestTTYClose(t *testing.T) { 596 // Ignore SIGTTIN in case we are running in the background. 597 signal.Ignore(syscall.SIGTTIN) 598 defer signal.Reset(syscall.SIGTTIN) 599 600 f, err := os.Open("/dev/tty") 601 if err != nil { 602 t.Skipf("skipping because opening /dev/tty failed: %v", err) 603 } 604 605 go func() { 606 var buf [1]byte 607 f.Read(buf[:]) 608 }() 609 610 // Give the goroutine a chance to enter the read. 611 // It doesn't matter much if it occasionally fails to do so, 612 // we won't be testing what we want to test but the test will pass. 613 time.Sleep(time.Millisecond) 614 615 c := make(chan bool) 616 go func() { 617 defer close(c) 618 f.Close() 619 }() 620 621 select { 622 case <-c: 623 case <-time.After(time.Second): 624 t.Error("timed out waiting for close") 625 } 626 627 // On some systems the goroutines may now be hanging. 628 // There's not much we can do about that. 629 }