1// Copyright 2011 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 windows 6 7package winfsnotify 8 9import ( 10 "io/ioutil" 11 "os" 12 "sync/atomic" 13 "testing" 14 "time" 15) 16 17func expect(t *testing.T, eventstream <-chan *Event, name string, mask uint32) { 18 t.Logf(`expected: "%s": 0x%x`, name, mask) 19 select { 20 case event := <-eventstream: 21 if event == nil { 22 t.Fatal("nil event received") 23 } 24 t.Logf("received: %s", event) 25 if event.Name != name || event.Mask != mask { 26 t.Fatal("did not receive expected event") 27 } 28 case <-time.After(1 * time.Second): 29 t.Fatal("timed out waiting for event") 30 } 31} 32 33func TestNotifyEvents(t *testing.T) { 34 watcher, err := NewWatcher() 35 if err != nil { 36 t.Fatalf("NewWatcher() failed: %s", err) 37 } 38 39 testDir := "TestNotifyEvents.testdirectory" 40 testFile := testDir + "/TestNotifyEvents.testfile" 41 testFile2 := testFile + ".new" 42 const mask = FS_ALL_EVENTS & ^(FS_ATTRIB|FS_CLOSE) | FS_IGNORED 43 44 // Add a watch for testDir 45 os.RemoveAll(testDir) 46 if err = os.Mkdir(testDir, 0777); err != nil { 47 t.Fatalf("Failed to create test directory: %s", err) 48 } 49 defer os.RemoveAll(testDir) 50 err = watcher.AddWatch(testDir, mask) 51 if err != nil { 52 t.Fatalf("Watcher.Watch() failed: %s", err) 53 } 54 55 // Receive errors on the error channel on a separate goroutine 56 go func() { 57 for err := range watcher.Error { 58 t.Fatalf("error received: %s", err) 59 } 60 }() 61 62 // Create a file 63 file, err := os.Create(testFile) 64 if err != nil { 65 t.Fatalf("creating test file failed: %s", err) 66 } 67 expect(t, watcher.Event, testFile, FS_CREATE) 68 69 err = watcher.AddWatch(testFile, mask) 70 if err != nil { 71 t.Fatalf("Watcher.Watch() failed: %s", err) 72 } 73 74 if _, err = file.WriteString("hello, world"); err != nil { 75 t.Fatalf("failed to write to test file: %s", err) 76 } 77 if err = file.Close(); err != nil { 78 t.Fatalf("failed to close test file: %s", err) 79 } 80 expect(t, watcher.Event, testFile, FS_MODIFY) 81 expect(t, watcher.Event, testFile, FS_MODIFY) 82 83 if err = os.Rename(testFile, testFile2); err != nil { 84 t.Fatalf("failed to rename test file: %s", err) 85 } 86 expect(t, watcher.Event, testFile, FS_MOVED_FROM) 87 expect(t, watcher.Event, testFile2, FS_MOVED_TO) 88 expect(t, watcher.Event, testFile, FS_MOVE_SELF) 89 90 if err = os.RemoveAll(testDir); err != nil { 91 t.Fatalf("failed to remove test directory: %s", err) 92 } 93 expect(t, watcher.Event, testFile2, FS_DELETE_SELF) 94 expect(t, watcher.Event, testFile2, FS_IGNORED) 95 expect(t, watcher.Event, testFile2, FS_DELETE) 96 expect(t, watcher.Event, testDir, FS_DELETE_SELF) 97 expect(t, watcher.Event, testDir, FS_IGNORED) 98 99 t.Log("calling Close()") 100 if err = watcher.Close(); err != nil { 101 t.Fatalf("failed to close watcher: %s", err) 102 } 103} 104 105func TestNotifyClose(t *testing.T) { 106 watcher, _ := NewWatcher() 107 watcher.Close() 108 109 var done int32 110 go func() { 111 watcher.Close() 112 atomic.StoreInt32(&done, 1) 113 }() 114 115 time.Sleep(50 * time.Millisecond) 116 if atomic.LoadInt32(&done) == 0 { 117 t.Fatal("double Close() test failed: second Close() call didn't return") 118 } 119 120 dir, err := ioutil.TempDir("", "wininotify") 121 if err != nil { 122 t.Fatalf("TempDir failed: %s", err) 123 } 124 defer os.RemoveAll(dir) 125 126 err = watcher.Watch(dir) 127 if err == nil { 128 t.Fatal("expected error on Watch() after Close(), got nil") 129 } 130} 131