github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/exp/fsnotify/fsnotify_test.go (about) 1 // Copyright 2010 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 !plan9,!solaris 6 7 package fsnotify 8 9 import ( 10 "io/ioutil" 11 "os" 12 "os/exec" 13 "path/filepath" 14 "runtime" 15 "sync/atomic" 16 "testing" 17 "time" 18 ) 19 20 // An atomic counter 21 type counter struct { 22 val int32 23 } 24 25 func (c *counter) increment() { 26 atomic.AddInt32(&c.val, 1) 27 } 28 29 func (c *counter) value() int32 { 30 return atomic.LoadInt32(&c.val) 31 } 32 33 func (c *counter) reset() { 34 atomic.StoreInt32(&c.val, 0) 35 } 36 37 // tempMkdir makes a temporary directory 38 func tempMkdir(t *testing.T) string { 39 dir, err := ioutil.TempDir("", "fsnotify") 40 if err != nil { 41 t.Fatalf("failed to create test directory: %s", err) 42 } 43 return dir 44 } 45 46 // newWatcher initializes an fsnotify Watcher instance. 47 func newWatcher(t *testing.T) *Watcher { 48 watcher, err := NewWatcher() 49 if err != nil { 50 t.Fatalf("NewWatcher() failed: %s", err) 51 } 52 return watcher 53 } 54 55 // addWatch adds a watch for a directory 56 func addWatch(t *testing.T, watcher *Watcher, dir string) { 57 if err := watcher.Watch(dir); err != nil { 58 t.Fatalf("watcher.Watch(%q) failed: %s", dir, err) 59 } 60 } 61 62 func TestFsnotifyMultipleOperations(t *testing.T) { 63 watcher := newWatcher(t) 64 65 // Receive errors on the error channel on a separate goroutine 66 go func() { 67 for err := range watcher.Error { 68 t.Fatalf("error received: %s", err) 69 } 70 }() 71 72 // Create directory to watch 73 testDir := tempMkdir(t) 74 defer os.RemoveAll(testDir) 75 76 // Create directory that's not watched 77 testDirToMoveFiles := tempMkdir(t) 78 defer os.RemoveAll(testDirToMoveFiles) 79 80 testFile := filepath.Join(testDir, "TestFsnotifySeq.testfile") 81 testFileRenamed := filepath.Join(testDirToMoveFiles, "TestFsnotifySeqRename.testfile") 82 83 addWatch(t, watcher, testDir) 84 85 // Receive events on the event channel on a separate goroutine 86 eventstream := watcher.Event 87 var createReceived, modifyReceived, deleteReceived, renameReceived counter 88 done := make(chan bool) 89 go func() { 90 for event := range eventstream { 91 // Only count relevant events 92 if event.Name == filepath.Clean(testDir) || event.Name == filepath.Clean(testFile) { 93 t.Logf("event received: %s", event) 94 if event.IsDelete() { 95 deleteReceived.increment() 96 } 97 if event.IsModify() { 98 modifyReceived.increment() 99 } 100 if event.IsCreate() { 101 createReceived.increment() 102 } 103 if event.IsRename() { 104 renameReceived.increment() 105 } 106 } else { 107 t.Logf("unexpected event received: %s", event) 108 } 109 } 110 done <- true 111 }() 112 113 // Create a file 114 // This should add at least one event to the fsnotify event queue 115 var f *os.File 116 f, err := os.OpenFile(testFile, os.O_WRONLY|os.O_CREATE, 0666) 117 if err != nil { 118 t.Fatalf("creating test file failed: %s", err) 119 } 120 f.Sync() 121 122 time.Sleep(time.Millisecond) 123 f.WriteString("data") 124 f.Sync() 125 f.Close() 126 127 time.Sleep(50 * time.Millisecond) // give system time to sync write change before delete 128 129 if err := testRename(testFile, testFileRenamed); err != nil { 130 t.Fatalf("rename failed: %s", err) 131 } 132 133 // Modify the file outside of the watched dir 134 f, err = os.Open(testFileRenamed) 135 if err != nil { 136 t.Fatalf("open test renamed file failed: %s", err) 137 } 138 f.WriteString("data") 139 f.Sync() 140 f.Close() 141 142 time.Sleep(50 * time.Millisecond) // give system time to sync write change before delete 143 144 // Recreate the file that was moved 145 f, err = os.OpenFile(testFile, os.O_WRONLY|os.O_CREATE, 0666) 146 if err != nil { 147 t.Fatalf("creating test file failed: %s", err) 148 } 149 f.Close() 150 time.Sleep(50 * time.Millisecond) // give system time to sync write change before delete 151 152 // We expect this event to be received almost immediately, but let's wait 500 ms to be sure 153 time.Sleep(500 * time.Millisecond) 154 cReceived := createReceived.value() 155 if cReceived != 2 { 156 t.Fatalf("incorrect number of create events received after 500 ms (%d vs %d)", cReceived, 2) 157 } 158 mReceived := modifyReceived.value() 159 if mReceived != 1 { 160 t.Fatalf("incorrect number of modify events received after 500 ms (%d vs %d)", mReceived, 1) 161 } 162 dReceived := deleteReceived.value() 163 rReceived := renameReceived.value() 164 if dReceived+rReceived != 1 { 165 t.Fatalf("incorrect number of rename+delete events received after 500 ms (%d vs %d)", rReceived+dReceived, 1) 166 } 167 168 // Try closing the fsnotify instance 169 t.Log("calling Close()") 170 watcher.Close() 171 t.Log("waiting for the event channel to become closed...") 172 select { 173 case <-done: 174 t.Log("event channel closed") 175 case <-time.After(2 * time.Second): 176 t.Fatal("event stream was not closed after 2 seconds") 177 } 178 } 179 180 func TestFsnotifyMultipleCreates(t *testing.T) { 181 watcher := newWatcher(t) 182 183 // Receive errors on the error channel on a separate goroutine 184 go func() { 185 for err := range watcher.Error { 186 t.Fatalf("error received: %s", err) 187 } 188 }() 189 190 // Create directory to watch 191 testDir := tempMkdir(t) 192 defer os.RemoveAll(testDir) 193 194 testFile := filepath.Join(testDir, "TestFsnotifySeq.testfile") 195 196 addWatch(t, watcher, testDir) 197 198 // Receive events on the event channel on a separate goroutine 199 eventstream := watcher.Event 200 var createReceived, modifyReceived, deleteReceived counter 201 done := make(chan bool) 202 go func() { 203 for event := range eventstream { 204 // Only count relevant events 205 if event.Name == filepath.Clean(testDir) || event.Name == filepath.Clean(testFile) { 206 t.Logf("event received: %s", event) 207 if event.IsDelete() { 208 deleteReceived.increment() 209 } 210 if event.IsCreate() { 211 createReceived.increment() 212 } 213 if event.IsModify() { 214 modifyReceived.increment() 215 } 216 } else { 217 t.Logf("unexpected event received: %s", event) 218 } 219 } 220 done <- true 221 }() 222 223 // Create a file 224 // This should add at least one event to the fsnotify event queue 225 var f *os.File 226 f, err := os.OpenFile(testFile, os.O_WRONLY|os.O_CREATE, 0666) 227 if err != nil { 228 t.Fatalf("creating test file failed: %s", err) 229 } 230 f.Sync() 231 232 time.Sleep(time.Millisecond) 233 f.WriteString("data") 234 f.Sync() 235 f.Close() 236 237 time.Sleep(50 * time.Millisecond) // give system time to sync write change before delete 238 239 os.Remove(testFile) 240 241 time.Sleep(50 * time.Millisecond) // give system time to sync write change before delete 242 243 // Recreate the file 244 f, err = os.OpenFile(testFile, os.O_WRONLY|os.O_CREATE, 0666) 245 if err != nil { 246 t.Fatalf("creating test file failed: %s", err) 247 } 248 f.Close() 249 time.Sleep(50 * time.Millisecond) // give system time to sync write change before delete 250 251 // Modify 252 f, err = os.OpenFile(testFile, os.O_WRONLY, 0666) 253 if err != nil { 254 t.Fatalf("creating test file failed: %s", err) 255 } 256 f.Sync() 257 258 time.Sleep(time.Millisecond) 259 f.WriteString("data") 260 f.Sync() 261 f.Close() 262 263 time.Sleep(50 * time.Millisecond) // give system time to sync write change before delete 264 265 // Modify 266 f, err = os.OpenFile(testFile, os.O_WRONLY, 0666) 267 if err != nil { 268 t.Fatalf("creating test file failed: %s", err) 269 } 270 f.Sync() 271 272 time.Sleep(time.Millisecond) 273 f.WriteString("data") 274 f.Sync() 275 f.Close() 276 277 time.Sleep(50 * time.Millisecond) // give system time to sync write change before delete 278 279 // We expect this event to be received almost immediately, but let's wait 500 ms to be sure 280 time.Sleep(500 * time.Millisecond) 281 cReceived := createReceived.value() 282 if cReceived != 2 { 283 t.Fatalf("incorrect number of create events received after 500 ms (%d vs %d)", cReceived, 2) 284 } 285 mReceived := modifyReceived.value() 286 if mReceived < 3 { 287 t.Fatalf("incorrect number of modify events received after 500 ms (%d vs atleast %d)", mReceived, 3) 288 } 289 dReceived := deleteReceived.value() 290 if dReceived != 1 { 291 t.Fatalf("incorrect number of rename+delete events received after 500 ms (%d vs %d)", dReceived, 1) 292 } 293 294 // Try closing the fsnotify instance 295 t.Log("calling Close()") 296 watcher.Close() 297 t.Log("waiting for the event channel to become closed...") 298 select { 299 case <-done: 300 t.Log("event channel closed") 301 case <-time.After(2 * time.Second): 302 t.Fatal("event stream was not closed after 2 seconds") 303 } 304 } 305 306 func TestFsnotifyDirOnly(t *testing.T) { 307 watcher := newWatcher(t) 308 309 // Create directory to watch 310 testDir := tempMkdir(t) 311 defer os.RemoveAll(testDir) 312 313 // Create a file before watching directory 314 // This should NOT add any events to the fsnotify event queue 315 testFileAlreadyExists := filepath.Join(testDir, "TestFsnotifyEventsExisting.testfile") 316 { 317 var f *os.File 318 f, err := os.OpenFile(testFileAlreadyExists, os.O_WRONLY|os.O_CREATE, 0666) 319 if err != nil { 320 t.Fatalf("creating test file failed: %s", err) 321 } 322 f.Sync() 323 f.Close() 324 } 325 326 addWatch(t, watcher, testDir) 327 328 // Receive errors on the error channel on a separate goroutine 329 go func() { 330 for err := range watcher.Error { 331 t.Fatalf("error received: %s", err) 332 } 333 }() 334 335 testFile := filepath.Join(testDir, "TestFsnotifyDirOnly.testfile") 336 337 // Receive events on the event channel on a separate goroutine 338 eventstream := watcher.Event 339 var createReceived, modifyReceived, deleteReceived counter 340 done := make(chan bool) 341 go func() { 342 for event := range eventstream { 343 // Only count relevant events 344 if event.Name == filepath.Clean(testDir) || event.Name == filepath.Clean(testFile) || event.Name == filepath.Clean(testFileAlreadyExists) { 345 t.Logf("event received: %s", event) 346 if event.IsDelete() { 347 deleteReceived.increment() 348 } 349 if event.IsModify() { 350 modifyReceived.increment() 351 } 352 if event.IsCreate() { 353 createReceived.increment() 354 } 355 } else { 356 t.Logf("unexpected event received: %s", event) 357 } 358 } 359 done <- true 360 }() 361 362 // Create a file 363 // This should add at least one event to the fsnotify event queue 364 var f *os.File 365 f, err := os.OpenFile(testFile, os.O_WRONLY|os.O_CREATE, 0666) 366 if err != nil { 367 t.Fatalf("creating test file failed: %s", err) 368 } 369 f.Sync() 370 371 time.Sleep(time.Millisecond) 372 f.WriteString("data") 373 f.Sync() 374 f.Close() 375 376 time.Sleep(50 * time.Millisecond) // give system time to sync write change before delete 377 378 os.Remove(testFile) 379 os.Remove(testFileAlreadyExists) 380 381 // We expect this event to be received almost immediately, but let's wait 500 ms to be sure 382 time.Sleep(500 * time.Millisecond) 383 cReceived := createReceived.value() 384 if cReceived != 1 { 385 t.Fatalf("incorrect number of create events received after 500 ms (%d vs %d)", cReceived, 1) 386 } 387 mReceived := modifyReceived.value() 388 if mReceived != 1 { 389 t.Fatalf("incorrect number of modify events received after 500 ms (%d vs %d)", mReceived, 1) 390 } 391 dReceived := deleteReceived.value() 392 if dReceived != 2 { 393 t.Fatalf("incorrect number of delete events received after 500 ms (%d vs %d)", dReceived, 2) 394 } 395 396 // Try closing the fsnotify instance 397 t.Log("calling Close()") 398 watcher.Close() 399 t.Log("waiting for the event channel to become closed...") 400 select { 401 case <-done: 402 t.Log("event channel closed") 403 case <-time.After(2 * time.Second): 404 t.Fatal("event stream was not closed after 2 seconds") 405 } 406 } 407 408 func TestFsnotifyDeleteWatchedDir(t *testing.T) { 409 watcher := newWatcher(t) 410 defer watcher.Close() 411 412 // Create directory to watch 413 testDir := tempMkdir(t) 414 defer os.RemoveAll(testDir) 415 416 // Create a file before watching directory 417 testFileAlreadyExists := filepath.Join(testDir, "TestFsnotifyEventsExisting.testfile") 418 { 419 var f *os.File 420 f, err := os.OpenFile(testFileAlreadyExists, os.O_WRONLY|os.O_CREATE, 0666) 421 if err != nil { 422 t.Fatalf("creating test file failed: %s", err) 423 } 424 f.Sync() 425 f.Close() 426 } 427 428 addWatch(t, watcher, testDir) 429 430 // Add a watch for testFile 431 addWatch(t, watcher, testFileAlreadyExists) 432 433 // Receive errors on the error channel on a separate goroutine 434 go func() { 435 for err := range watcher.Error { 436 t.Fatalf("error received: %s", err) 437 } 438 }() 439 440 // Receive events on the event channel on a separate goroutine 441 eventstream := watcher.Event 442 var deleteReceived counter 443 go func() { 444 for event := range eventstream { 445 // Only count relevant events 446 if event.Name == filepath.Clean(testDir) || event.Name == filepath.Clean(testFileAlreadyExists) { 447 t.Logf("event received: %s", event) 448 if event.IsDelete() { 449 deleteReceived.increment() 450 } 451 } else { 452 t.Logf("unexpected event received: %s", event) 453 } 454 } 455 }() 456 457 os.RemoveAll(testDir) 458 459 // We expect this event to be received almost immediately, but let's wait 500 ms to be sure 460 time.Sleep(500 * time.Millisecond) 461 dReceived := deleteReceived.value() 462 if dReceived < 2 { 463 t.Fatalf("did not receive at least %d delete events, received %d after 500 ms", 2, dReceived) 464 } 465 } 466 467 func TestFsnotifySubDir(t *testing.T) { 468 watcher := newWatcher(t) 469 470 // Create directory to watch 471 testDir := tempMkdir(t) 472 defer os.RemoveAll(testDir) 473 474 testFile1 := filepath.Join(testDir, "TestFsnotifyFile1.testfile") 475 testSubDir := filepath.Join(testDir, "sub") 476 testSubDirFile := filepath.Join(testDir, "sub/TestFsnotifyFile1.testfile") 477 478 // Receive errors on the error channel on a separate goroutine 479 go func() { 480 for err := range watcher.Error { 481 t.Fatalf("error received: %s", err) 482 } 483 }() 484 485 // Receive events on the event channel on a separate goroutine 486 eventstream := watcher.Event 487 var createReceived, deleteReceived counter 488 done := make(chan bool) 489 go func() { 490 for event := range eventstream { 491 // Only count relevant events 492 if event.Name == filepath.Clean(testDir) || event.Name == filepath.Clean(testSubDir) || event.Name == filepath.Clean(testFile1) { 493 t.Logf("event received: %s", event) 494 if event.IsCreate() { 495 createReceived.increment() 496 } 497 if event.IsDelete() { 498 deleteReceived.increment() 499 } 500 } else { 501 t.Logf("unexpected event received: %s", event) 502 } 503 } 504 done <- true 505 }() 506 507 addWatch(t, watcher, testDir) 508 509 // Create sub-directory 510 if err := os.Mkdir(testSubDir, 0777); err != nil { 511 t.Fatalf("failed to create test sub-directory: %s", err) 512 } 513 514 // Create a file 515 var f *os.File 516 f, err := os.OpenFile(testFile1, os.O_WRONLY|os.O_CREATE, 0666) 517 if err != nil { 518 t.Fatalf("creating test file failed: %s", err) 519 } 520 f.Sync() 521 f.Close() 522 523 // Create a file (Should not see this! we are not watching subdir) 524 var fs *os.File 525 fs, err = os.OpenFile(testSubDirFile, os.O_WRONLY|os.O_CREATE, 0666) 526 if err != nil { 527 t.Fatalf("creating test file failed: %s", err) 528 } 529 fs.Sync() 530 fs.Close() 531 532 time.Sleep(200 * time.Millisecond) 533 534 // Make sure receive deletes for both file and sub-directory 535 os.RemoveAll(testSubDir) 536 os.Remove(testFile1) 537 538 // We expect this event to be received almost immediately, but let's wait 500 ms to be sure 539 time.Sleep(500 * time.Millisecond) 540 cReceived := createReceived.value() 541 if cReceived != 2 { 542 t.Fatalf("incorrect number of create events received after 500 ms (%d vs %d)", cReceived, 2) 543 } 544 dReceived := deleteReceived.value() 545 if dReceived != 2 { 546 t.Fatalf("incorrect number of delete events received after 500 ms (%d vs %d)", dReceived, 2) 547 } 548 549 // Try closing the fsnotify instance 550 t.Log("calling Close()") 551 watcher.Close() 552 t.Log("waiting for the event channel to become closed...") 553 select { 554 case <-done: 555 t.Log("event channel closed") 556 case <-time.After(2 * time.Second): 557 t.Fatal("event stream was not closed after 2 seconds") 558 } 559 } 560 561 func TestFsnotifyRename(t *testing.T) { 562 watcher := newWatcher(t) 563 564 // Create directory to watch 565 testDir := tempMkdir(t) 566 defer os.RemoveAll(testDir) 567 568 addWatch(t, watcher, testDir) 569 570 // Receive errors on the error channel on a separate goroutine 571 go func() { 572 for err := range watcher.Error { 573 t.Fatalf("error received: %s", err) 574 } 575 }() 576 577 testFile := filepath.Join(testDir, "TestFsnotifyEvents.testfile") 578 testFileRenamed := filepath.Join(testDir, "TestFsnotifyEvents.testfileRenamed") 579 580 // Receive events on the event channel on a separate goroutine 581 eventstream := watcher.Event 582 var renameReceived counter 583 done := make(chan bool) 584 go func() { 585 for event := range eventstream { 586 // Only count relevant events 587 if event.Name == filepath.Clean(testDir) || event.Name == filepath.Clean(testFile) || event.Name == filepath.Clean(testFileRenamed) { 588 if event.IsRename() { 589 renameReceived.increment() 590 } 591 t.Logf("event received: %s", event) 592 } else { 593 t.Logf("unexpected event received: %s", event) 594 } 595 } 596 done <- true 597 }() 598 599 // Create a file 600 // This should add at least one event to the fsnotify event queue 601 var f *os.File 602 f, err := os.OpenFile(testFile, os.O_WRONLY|os.O_CREATE, 0666) 603 if err != nil { 604 t.Fatalf("creating test file failed: %s", err) 605 } 606 f.Sync() 607 608 f.WriteString("data") 609 f.Sync() 610 f.Close() 611 612 // Add a watch for testFile 613 addWatch(t, watcher, testFile) 614 615 if err := testRename(testFile, testFileRenamed); err != nil { 616 t.Fatalf("rename failed: %s", err) 617 } 618 619 // We expect this event to be received almost immediately, but let's wait 500 ms to be sure 620 time.Sleep(500 * time.Millisecond) 621 if renameReceived.value() == 0 { 622 t.Fatal("fsnotify rename events have not been received after 500 ms") 623 } 624 625 // Try closing the fsnotify instance 626 t.Log("calling Close()") 627 watcher.Close() 628 t.Log("waiting for the event channel to become closed...") 629 select { 630 case <-done: 631 t.Log("event channel closed") 632 case <-time.After(2 * time.Second): 633 t.Fatal("event stream was not closed after 2 seconds") 634 } 635 636 os.Remove(testFileRenamed) 637 } 638 639 func TestFsnotifyRenameToCreate(t *testing.T) { 640 watcher := newWatcher(t) 641 642 // Create directory to watch 643 testDir := tempMkdir(t) 644 defer os.RemoveAll(testDir) 645 646 // Create directory to get file 647 testDirFrom := tempMkdir(t) 648 defer os.RemoveAll(testDirFrom) 649 650 addWatch(t, watcher, testDir) 651 652 // Receive errors on the error channel on a separate goroutine 653 go func() { 654 for err := range watcher.Error { 655 t.Fatalf("error received: %s", err) 656 } 657 }() 658 659 testFile := filepath.Join(testDirFrom, "TestFsnotifyEvents.testfile") 660 testFileRenamed := filepath.Join(testDir, "TestFsnotifyEvents.testfileRenamed") 661 662 // Receive events on the event channel on a separate goroutine 663 eventstream := watcher.Event 664 var createReceived counter 665 done := make(chan bool) 666 go func() { 667 for event := range eventstream { 668 // Only count relevant events 669 if event.Name == filepath.Clean(testDir) || event.Name == filepath.Clean(testFile) || event.Name == filepath.Clean(testFileRenamed) { 670 if event.IsCreate() { 671 createReceived.increment() 672 } 673 t.Logf("event received: %s", event) 674 } else { 675 t.Logf("unexpected event received: %s", event) 676 } 677 } 678 done <- true 679 }() 680 681 // Create a file 682 // This should add at least one event to the fsnotify event queue 683 var f *os.File 684 f, err := os.OpenFile(testFile, os.O_WRONLY|os.O_CREATE, 0666) 685 if err != nil { 686 t.Fatalf("creating test file failed: %s", err) 687 } 688 f.Sync() 689 f.Close() 690 691 if err := testRename(testFile, testFileRenamed); err != nil { 692 t.Fatalf("rename failed: %s", err) 693 } 694 695 // We expect this event to be received almost immediately, but let's wait 500 ms to be sure 696 time.Sleep(500 * time.Millisecond) 697 if createReceived.value() == 0 { 698 t.Fatal("fsnotify create events have not been received after 500 ms") 699 } 700 701 // Try closing the fsnotify instance 702 t.Log("calling Close()") 703 watcher.Close() 704 t.Log("waiting for the event channel to become closed...") 705 select { 706 case <-done: 707 t.Log("event channel closed") 708 case <-time.After(2 * time.Second): 709 t.Fatal("event stream was not closed after 2 seconds") 710 } 711 712 os.Remove(testFileRenamed) 713 } 714 715 func TestFsnotifyRenameToOverwrite(t *testing.T) { 716 switch runtime.GOOS { 717 case "plan9", "windows": 718 t.Skipf("skipping test on %q (os.Rename over existing file does not create event).", runtime.GOOS) 719 } 720 721 watcher := newWatcher(t) 722 723 // Create directory to watch 724 testDir := tempMkdir(t) 725 defer os.RemoveAll(testDir) 726 727 // Create directory to get file 728 testDirFrom := tempMkdir(t) 729 defer os.RemoveAll(testDirFrom) 730 731 testFile := filepath.Join(testDirFrom, "TestFsnotifyEvents.testfile") 732 testFileRenamed := filepath.Join(testDir, "TestFsnotifyEvents.testfileRenamed") 733 734 // Create a file 735 var fr *os.File 736 fr, err := os.OpenFile(testFileRenamed, os.O_WRONLY|os.O_CREATE, 0666) 737 if err != nil { 738 t.Fatalf("creating test file failed: %s", err) 739 } 740 fr.Sync() 741 fr.Close() 742 743 addWatch(t, watcher, testDir) 744 745 // Receive errors on the error channel on a separate goroutine 746 go func() { 747 for err := range watcher.Error { 748 t.Fatalf("error received: %s", err) 749 } 750 }() 751 752 // Receive events on the event channel on a separate goroutine 753 eventstream := watcher.Event 754 var eventReceived counter 755 done := make(chan bool) 756 go func() { 757 for event := range eventstream { 758 // Only count relevant events 759 if event.Name == filepath.Clean(testFileRenamed) { 760 eventReceived.increment() 761 t.Logf("event received: %s", event) 762 } else { 763 t.Logf("unexpected event received: %s", event) 764 } 765 } 766 done <- true 767 }() 768 769 // Create a file 770 // This should add at least one event to the fsnotify event queue 771 var f *os.File 772 f, err = os.OpenFile(testFile, os.O_WRONLY|os.O_CREATE, 0666) 773 if err != nil { 774 t.Fatalf("creating test file failed: %s", err) 775 } 776 f.Sync() 777 f.Close() 778 779 if err := testRename(testFile, testFileRenamed); err != nil { 780 t.Fatalf("rename failed: %s", err) 781 } 782 783 // We expect this event to be received almost immediately, but let's wait 500 ms to be sure 784 time.Sleep(500 * time.Millisecond) 785 if eventReceived.value() == 0 { 786 t.Fatal("fsnotify events have not been received after 500 ms") 787 } 788 789 // Try closing the fsnotify instance 790 t.Log("calling Close()") 791 watcher.Close() 792 t.Log("waiting for the event channel to become closed...") 793 select { 794 case <-done: 795 t.Log("event channel closed") 796 case <-time.After(2 * time.Second): 797 t.Fatal("event stream was not closed after 2 seconds") 798 } 799 800 os.Remove(testFileRenamed) 801 } 802 803 func TestRemovalOfWatch(t *testing.T) { 804 // Create directory to watch 805 testDir := tempMkdir(t) 806 defer os.RemoveAll(testDir) 807 808 // Create a file before watching directory 809 testFileAlreadyExists := filepath.Join(testDir, "TestFsnotifyEventsExisting.testfile") 810 { 811 var f *os.File 812 f, err := os.OpenFile(testFileAlreadyExists, os.O_WRONLY|os.O_CREATE, 0666) 813 if err != nil { 814 t.Fatalf("creating test file failed: %s", err) 815 } 816 f.Sync() 817 f.Close() 818 } 819 820 watcher := newWatcher(t) 821 defer watcher.Close() 822 823 addWatch(t, watcher, testDir) 824 if err := watcher.RemoveWatch(testDir); err != nil { 825 t.Fatalf("Could not remove the watch: %v\n", err) 826 } 827 828 go func() { 829 select { 830 case ev := <-watcher.Event: 831 t.Fatalf("We received event: %v\n", ev) 832 case <-time.After(500 * time.Millisecond): 833 t.Log("No event received, as expected.") 834 } 835 }() 836 837 time.Sleep(200 * time.Millisecond) 838 // Modify the file outside of the watched dir 839 f, err := os.Open(testFileAlreadyExists) 840 if err != nil { 841 t.Fatalf("Open test file failed: %s", err) 842 } 843 f.WriteString("data") 844 f.Sync() 845 f.Close() 846 if err := os.Chmod(testFileAlreadyExists, 0700); err != nil { 847 t.Fatalf("chmod failed: %s", err) 848 } 849 time.Sleep(400 * time.Millisecond) 850 } 851 852 func TestFsnotifyAttrib(t *testing.T) { 853 if runtime.GOOS == "windows" { 854 t.Skip("attributes don't work on Windows.") 855 } 856 857 watcher := newWatcher(t) 858 859 // Create directory to watch 860 testDir := tempMkdir(t) 861 defer os.RemoveAll(testDir) 862 863 // Receive errors on the error channel on a separate goroutine 864 go func() { 865 for err := range watcher.Error { 866 t.Fatalf("error received: %s", err) 867 } 868 }() 869 870 testFile := filepath.Join(testDir, "TestFsnotifyAttrib.testfile") 871 872 // Receive events on the event channel on a separate goroutine 873 eventstream := watcher.Event 874 // The modifyReceived counter counts IsModify events that are not IsAttrib, 875 // and the attribReceived counts IsAttrib events (which are also IsModify as 876 // a consequence). 877 var modifyReceived counter 878 var attribReceived counter 879 done := make(chan bool) 880 go func() { 881 for event := range eventstream { 882 // Only count relevant events 883 if event.Name == filepath.Clean(testDir) || event.Name == filepath.Clean(testFile) { 884 if event.IsModify() { 885 modifyReceived.increment() 886 } 887 if event.IsAttrib() { 888 attribReceived.increment() 889 } 890 t.Logf("event received: %s", event) 891 } else { 892 t.Logf("unexpected event received: %s", event) 893 } 894 } 895 done <- true 896 }() 897 898 // Create a file 899 // This should add at least one event to the fsnotify event queue 900 var f *os.File 901 f, err := os.OpenFile(testFile, os.O_WRONLY|os.O_CREATE, 0666) 902 if err != nil { 903 t.Fatalf("creating test file failed: %s", err) 904 } 905 f.Sync() 906 907 f.WriteString("data") 908 f.Sync() 909 f.Close() 910 911 // Add a watch for testFile 912 addWatch(t, watcher, testFile) 913 914 if err := os.Chmod(testFile, 0700); err != nil { 915 t.Fatalf("chmod failed: %s", err) 916 } 917 918 // We expect this event to be received almost immediately, but let's wait 500 ms to be sure 919 // Creating/writing a file changes also the mtime, so IsAttrib should be set to true here 920 time.Sleep(500 * time.Millisecond) 921 if modifyReceived.value() == 0 { 922 t.Fatal("fsnotify modify events have not received after 500 ms") 923 } 924 if attribReceived.value() == 0 { 925 t.Fatal("fsnotify attribute events have not received after 500 ms") 926 } 927 928 // Modifying the contents of the file does not set the attrib flag (although eg. the mtime 929 // might have been modified). 930 modifyReceived.reset() 931 attribReceived.reset() 932 933 f, err = os.OpenFile(testFile, os.O_WRONLY, 0) 934 if err != nil { 935 t.Fatalf("reopening test file failed: %s", err) 936 } 937 938 f.WriteString("more data") 939 f.Sync() 940 f.Close() 941 942 time.Sleep(500 * time.Millisecond) 943 944 if modifyReceived.value() != 1 { 945 t.Fatal("didn't receive a modify event after changing test file contents") 946 } 947 948 if attribReceived.value() != 0 { 949 t.Fatal("did receive an unexpected attrib event after changing test file contents") 950 } 951 952 modifyReceived.reset() 953 attribReceived.reset() 954 955 // Doing a chmod on the file should trigger an event with the "attrib" flag set (the contents 956 // of the file are not changed though) 957 if err := os.Chmod(testFile, 0600); err != nil { 958 t.Fatalf("chmod failed: %s", err) 959 } 960 961 time.Sleep(500 * time.Millisecond) 962 963 if attribReceived.value() != 1 { 964 t.Fatal("didn't receive an attribute change after 500ms") 965 } 966 967 // Try closing the fsnotify instance 968 t.Log("calling Close()") 969 watcher.Close() 970 t.Log("waiting for the event channel to become closed...") 971 select { 972 case <-done: 973 t.Log("event channel closed") 974 case <-time.After(1e9): 975 t.Fatal("event stream was not closed after 1 second") 976 } 977 978 os.Remove(testFile) 979 } 980 981 func TestFsnotifyClose(t *testing.T) { 982 watcher := newWatcher(t) 983 watcher.Close() 984 985 var done int32 986 go func() { 987 watcher.Close() 988 atomic.StoreInt32(&done, 1) 989 }() 990 991 time.Sleep(50e6) // 50 ms 992 if atomic.LoadInt32(&done) == 0 { 993 t.Fatal("double Close() test failed: second Close() call didn't return") 994 } 995 996 testDir := tempMkdir(t) 997 defer os.RemoveAll(testDir) 998 999 if err := watcher.Watch(testDir); err == nil { 1000 t.Fatal("expected error on Watch() after Close(), got nil") 1001 } 1002 } 1003 1004 func testRename(file1, file2 string) error { 1005 switch runtime.GOOS { 1006 case "windows", "plan9": 1007 return os.Rename(file1, file2) 1008 default: 1009 cmd := exec.Command("mv", file1, file2) 1010 return cmd.Run() 1011 } 1012 }