package fsnotify
import (
- "fmt"
- "math/rand"
+ "io/ioutil"
"os"
"os/exec"
"path/filepath"
"time"
)
-var r *rand.Rand
-
-func init() {
- r = rand.New(rand.NewSource(time.Now().UnixNano()))
-}
-
-func testTempDir() string {
- osTempDir := os.TempDir()
- randDir := fmt.Sprintf("%d", r.Int())
- return filepath.Join(osTempDir, randDir)
-}
-
// An atomic counter
type counter struct {
val int32
}
func (c *counter) increment() {
- cas := atomic.CompareAndSwapInt32
- old := atomic.LoadInt32(&c.val)
- for swp := cas(&c.val, old, old+1); !swp; swp = cas(&c.val, old, old+1) {
- old = atomic.LoadInt32(&c.val)
- }
+ atomic.AddInt32(&c.val, 1)
}
func (c *counter) value() int32 {
atomic.StoreInt32(&c.val, 0)
}
-func TestFsnotifyMultipleOperations(t *testing.T) {
- // Create an fsnotify watcher instance and initialize it
+// tempMkdir makes a temporary directory
+func tempMkdir(t *testing.T) string {
+ dir, err := ioutil.TempDir("", "fsnotify")
+ if err != nil {
+ t.Fatalf("failed to create test directory: %s", err)
+ }
+ return dir
+}
+
+// newWatcher initializes an fsnotify Watcher instance.
+func newWatcher(t *testing.T) *Watcher {
watcher, err := NewWatcher()
if err != nil {
t.Fatalf("NewWatcher() failed: %s", err)
}
+ return watcher
+}
+
+// addWatch adds a watch for a directory
+func addWatch(t *testing.T, watcher *Watcher, dir string) {
+ if err := watcher.Watch(dir); err != nil {
+ t.Fatalf("watcher.Watch(%q) failed: %s", dir, err)
+ }
+}
+
+func TestFsnotifyMultipleOperations(t *testing.T) {
+ watcher := newWatcher(t)
// Receive errors on the error channel on a separate goroutine
go func() {
}
}()
- var testDir string = testTempDir()
- var testDirToMoveFiles string = testTempDir()
-
// Create directory to watch
- if err := os.Mkdir(testDir, 0777); err != nil {
- t.Fatalf("failed to create test directory: %s", err)
- }
+ testDir := tempMkdir(t)
defer os.RemoveAll(testDir)
- // Create directory to that's not watched
- if err := os.Mkdir(testDirToMoveFiles, 0777); err != nil {
- t.Fatalf("failed to create test directory: %s", err)
- }
+ // Create directory that's not watched
+ testDirToMoveFiles := tempMkdir(t)
defer os.RemoveAll(testDirToMoveFiles)
- var testFile string = filepath.Join(testDir, "TestFsnotifySeq.testfile")
- var testFileRenamed string = filepath.Join(testDirToMoveFiles, "TestFsnotifySeqRename.testfile")
+ testFile := filepath.Join(testDir, "TestFsnotifySeq.testfile")
+ testFileRenamed := filepath.Join(testDirToMoveFiles, "TestFsnotifySeqRename.testfile")
+
+ addWatch(t, watcher, testDir)
- // Add a watch for testDir
- err = watcher.Watch(testDir)
- if err != nil {
- t.Fatalf("watcher.Watch() failed: %s", err)
- }
// Receive events on the event channel on a separate goroutine
eventstream := watcher.Event
var createReceived, modifyReceived, deleteReceived, renameReceived counter
// Create a file
// This should add at least one event to the fsnotify event queue
var f *os.File
- f, err = os.OpenFile(testFile, os.O_WRONLY|os.O_CREATE, 0666)
+ f, err := os.OpenFile(testFile, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
t.Fatalf("creating test file failed: %s", err)
}
time.Sleep(50 * time.Millisecond) // give system time to sync write change before delete
- err = testRename(testFile, testFileRenamed)
- if err != nil {
+ if err := testRename(testFile, testFileRenamed); err != nil {
t.Fatalf("rename failed: %s", err)
}
}
func TestFsnotifyMultipleCreates(t *testing.T) {
- // Create an fsnotify watcher instance and initialize it
- watcher, err := NewWatcher()
- if err != nil {
- t.Fatalf("NewWatcher() failed: %s", err)
- }
+ watcher := newWatcher(t)
// Receive errors on the error channel on a separate goroutine
go func() {
}
}()
- var testDir string = testTempDir()
-
// Create directory to watch
- if err := os.Mkdir(testDir, 0777); err != nil {
- t.Fatalf("failed to create test directory: %s", err)
- }
+ testDir := tempMkdir(t)
defer os.RemoveAll(testDir)
- var testFile string = filepath.Join(testDir, "TestFsnotifySeq.testfile")
+ testFile := filepath.Join(testDir, "TestFsnotifySeq.testfile")
+
+ addWatch(t, watcher, testDir)
- // Add a watch for testDir
- err = watcher.Watch(testDir)
- if err != nil {
- t.Fatalf("watcher.Watch() failed: %s", err)
- }
// Receive events on the event channel on a separate goroutine
eventstream := watcher.Event
var createReceived, modifyReceived, deleteReceived counter
// Create a file
// This should add at least one event to the fsnotify event queue
var f *os.File
- f, err = os.OpenFile(testFile, os.O_WRONLY|os.O_CREATE, 0666)
+ f, err := os.OpenFile(testFile, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
t.Fatalf("creating test file failed: %s", err)
}
}
func TestFsnotifyDirOnly(t *testing.T) {
- // Create an fsnotify watcher instance and initialize it
- watcher, err := NewWatcher()
- if err != nil {
- t.Fatalf("NewWatcher() failed: %s", err)
- }
-
- var testDir string = testTempDir()
+ watcher := newWatcher(t)
// Create directory to watch
- if err := os.Mkdir(testDir, 0777); err != nil {
- t.Fatalf("failed to create test directory: %s", err)
- }
+ testDir := tempMkdir(t)
defer os.RemoveAll(testDir)
// Create a file before watching directory
// This should NOT add any events to the fsnotify event queue
- var testFileAlreadyExists string = filepath.Join(testDir, "TestFsnotifyEventsExisting.testfile")
+ testFileAlreadyExists := filepath.Join(testDir, "TestFsnotifyEventsExisting.testfile")
{
var f *os.File
- f, err = os.OpenFile(testFileAlreadyExists, os.O_WRONLY|os.O_CREATE, 0666)
+ f, err := os.OpenFile(testFileAlreadyExists, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
t.Fatalf("creating test file failed: %s", err)
}
f.Close()
}
- // Add a watch for testDir
- err = watcher.Watch(testDir)
- if err != nil {
- t.Fatalf("watcher.Watch() failed: %s", err)
- }
+ addWatch(t, watcher, testDir)
// Receive errors on the error channel on a separate goroutine
go func() {
}
}()
- var testFile string = filepath.Join(testDir, "TestFsnotifyDirOnly.testfile")
+ testFile := filepath.Join(testDir, "TestFsnotifyDirOnly.testfile")
// Receive events on the event channel on a separate goroutine
eventstream := watcher.Event
// Create a file
// This should add at least one event to the fsnotify event queue
var f *os.File
- f, err = os.OpenFile(testFile, os.O_WRONLY|os.O_CREATE, 0666)
+ f, err := os.OpenFile(testFile, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
t.Fatalf("creating test file failed: %s", err)
}
}
func TestFsnotifyDeleteWatchedDir(t *testing.T) {
- // Create an fsnotify watcher instance and initialize it
- watcher, err := NewWatcher()
- if err != nil {
- t.Fatalf("NewWatcher() failed: %s", err)
- }
+ watcher := newWatcher(t)
defer watcher.Close()
- var testDir string = testTempDir()
-
// Create directory to watch
- if err := os.Mkdir(testDir, 0777); err != nil {
- t.Fatalf("failed to create test directory: %s", err)
- }
+ testDir := tempMkdir(t)
+ defer os.RemoveAll(testDir)
// Create a file before watching directory
- var testFileAlreadyExists string = filepath.Join(testDir, "TestFsnotifyEventsExisting.testfile")
+ testFileAlreadyExists := filepath.Join(testDir, "TestFsnotifyEventsExisting.testfile")
{
var f *os.File
- f, err = os.OpenFile(testFileAlreadyExists, os.O_WRONLY|os.O_CREATE, 0666)
+ f, err := os.OpenFile(testFileAlreadyExists, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
t.Fatalf("creating test file failed: %s", err)
}
f.Close()
}
- // Add a watch for testDir
- err = watcher.Watch(testDir)
- if err != nil {
- t.Fatalf("watcher.Watch() failed: %s", err)
- }
+ addWatch(t, watcher, testDir)
// Add a watch for testFile
- err = watcher.Watch(testFileAlreadyExists)
- if err != nil {
- t.Fatalf("watcher.Watch() failed: %s", err)
- }
+ addWatch(t, watcher, testFileAlreadyExists)
// Receive errors on the error channel on a separate goroutine
go func() {
}
func TestFsnotifySubDir(t *testing.T) {
- // Create an fsnotify watcher instance and initialize it
- watcher, err := NewWatcher()
- if err != nil {
- t.Fatalf("NewWatcher() failed: %s", err)
- }
-
- var testDir string = testTempDir()
- var testFile1 string = filepath.Join(testDir, "TestFsnotifyFile1.testfile")
- var testSubDir string = filepath.Join(testDir, "sub")
- var testSubDirFile string = filepath.Join(testDir, "sub/TestFsnotifyFile1.testfile")
+ watcher := newWatcher(t)
// Create directory to watch
- if err := os.Mkdir(testDir, 0777); err != nil {
- t.Fatalf("failed to create test directory: %s", err)
- }
+ testDir := tempMkdir(t)
defer os.RemoveAll(testDir)
+ testFile1 := filepath.Join(testDir, "TestFsnotifyFile1.testfile")
+ testSubDir := filepath.Join(testDir, "sub")
+ testSubDirFile := filepath.Join(testDir, "sub/TestFsnotifyFile1.testfile")
+
// Receive errors on the error channel on a separate goroutine
go func() {
for err := range watcher.Error {
done <- true
}()
- // Add a watch for testDir
- err = watcher.Watch(testDir)
- if err != nil {
- t.Fatalf("watcher.Watch() failed: %s", err)
- }
+ addWatch(t, watcher, testDir)
// Create sub-directory
if err := os.Mkdir(testSubDir, 0777); err != nil {
// Create a file
var f *os.File
- f, err = os.OpenFile(testFile1, os.O_WRONLY|os.O_CREATE, 0666)
+ f, err := os.OpenFile(testFile1, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
t.Fatalf("creating test file failed: %s", err)
}
}
func TestFsnotifyRename(t *testing.T) {
- // Create an fsnotify watcher instance and initialize it
- watcher, err := NewWatcher()
- if err != nil {
- t.Fatalf("NewWatcher() failed: %s", err)
- }
-
- var testDir string = testTempDir()
+ watcher := newWatcher(t)
// Create directory to watch
- if err := os.Mkdir(testDir, 0777); err != nil {
- t.Fatalf("failed to create test directory: %s", err)
- }
+ testDir := tempMkdir(t)
defer os.RemoveAll(testDir)
- // Add a watch for testDir
- err = watcher.Watch(testDir)
- if err != nil {
- t.Fatalf("watcher.Watch() failed: %s", err)
- }
+ addWatch(t, watcher, testDir)
// Receive errors on the error channel on a separate goroutine
go func() {
}
}()
- var testFile string = filepath.Join(testDir, "TestFsnotifyEvents.testfile")
- var testFileRenamed string = filepath.Join(testDir, "TestFsnotifyEvents.testfileRenamed")
+ testFile := filepath.Join(testDir, "TestFsnotifyEvents.testfile")
+ testFileRenamed := filepath.Join(testDir, "TestFsnotifyEvents.testfileRenamed")
// Receive events on the event channel on a separate goroutine
eventstream := watcher.Event
// Create a file
// This should add at least one event to the fsnotify event queue
var f *os.File
- f, err = os.OpenFile(testFile, os.O_WRONLY|os.O_CREATE, 0666)
+ f, err := os.OpenFile(testFile, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
t.Fatalf("creating test file failed: %s", err)
}
f.Close()
// Add a watch for testFile
- err = watcher.Watch(testFile)
- if err != nil {
- t.Fatalf("watcher.Watch() failed: %s", err)
- }
+ addWatch(t, watcher, testFile)
- err = testRename(testFile, testFileRenamed)
- if err != nil {
+ if err := testRename(testFile, testFileRenamed); err != nil {
t.Fatalf("rename failed: %s", err)
}
}
func TestFsnotifyRenameToCreate(t *testing.T) {
- // Create an fsnotify watcher instance and initialize it
- watcher, err := NewWatcher()
- if err != nil {
- t.Fatalf("NewWatcher() failed: %s", err)
- }
-
- var testDir string = testTempDir()
- var testDirFrom string = testTempDir()
+ watcher := newWatcher(t)
// Create directory to watch
- if err := os.Mkdir(testDir, 0777); err != nil {
- t.Fatalf("failed to create test directory: %s", err)
- }
+ testDir := tempMkdir(t)
defer os.RemoveAll(testDir)
// Create directory to get file
- if err := os.Mkdir(testDirFrom, 0777); err != nil {
- t.Fatalf("failed to create test directory: %s", err)
- }
+ testDirFrom := tempMkdir(t)
defer os.RemoveAll(testDirFrom)
- // Add a watch for testDir
- err = watcher.Watch(testDir)
- if err != nil {
- t.Fatalf("watcher.Watch() failed: %s", err)
- }
+ addWatch(t, watcher, testDir)
// Receive errors on the error channel on a separate goroutine
go func() {
}
}()
- var testFile string = filepath.Join(testDirFrom, "TestFsnotifyEvents.testfile")
- var testFileRenamed string = filepath.Join(testDir, "TestFsnotifyEvents.testfileRenamed")
+ testFile := filepath.Join(testDirFrom, "TestFsnotifyEvents.testfile")
+ testFileRenamed := filepath.Join(testDir, "TestFsnotifyEvents.testfileRenamed")
// Receive events on the event channel on a separate goroutine
eventstream := watcher.Event
// Create a file
// This should add at least one event to the fsnotify event queue
var f *os.File
- f, err = os.OpenFile(testFile, os.O_WRONLY|os.O_CREATE, 0666)
+ f, err := os.OpenFile(testFile, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
t.Fatalf("creating test file failed: %s", err)
}
f.Sync()
f.Close()
- err = testRename(testFile, testFileRenamed)
- if err != nil {
+ if err := testRename(testFile, testFileRenamed); err != nil {
t.Fatalf("rename failed: %s", err)
}
case "plan9", "windows":
t.Skipf("skipping test on %q (os.Rename over existing file does not create event).", runtime.GOOS)
}
- // Create an fsnotify watcher instance and initialize it
- watcher, err := NewWatcher()
- if err != nil {
- t.Fatalf("NewWatcher() failed: %s", err)
- }
-
- var testDir string = testTempDir()
- var testDirFrom string = testTempDir()
- var testFile string = filepath.Join(testDirFrom, "TestFsnotifyEvents.testfile")
- var testFileRenamed string = filepath.Join(testDir, "TestFsnotifyEvents.testfileRenamed")
+ watcher := newWatcher(t)
// Create directory to watch
- if err := os.Mkdir(testDir, 0777); err != nil {
- t.Fatalf("failed to create test directory: %s", err)
- }
+ testDir := tempMkdir(t)
defer os.RemoveAll(testDir)
// Create directory to get file
- if err := os.Mkdir(testDirFrom, 0777); err != nil {
- t.Fatalf("failed to create test directory: %s", err)
- }
+ testDirFrom := tempMkdir(t)
defer os.RemoveAll(testDirFrom)
+ testFile := filepath.Join(testDirFrom, "TestFsnotifyEvents.testfile")
+ testFileRenamed := filepath.Join(testDir, "TestFsnotifyEvents.testfileRenamed")
+
// Create a file
var fr *os.File
- fr, err = os.OpenFile(testFileRenamed, os.O_WRONLY|os.O_CREATE, 0666)
+ fr, err := os.OpenFile(testFileRenamed, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
t.Fatalf("creating test file failed: %s", err)
}
fr.Sync()
fr.Close()
- // Add a watch for testDir
- err = watcher.Watch(testDir)
- if err != nil {
- t.Fatalf("watcher.Watch() failed: %s", err)
- }
+ addWatch(t, watcher, testDir)
// Receive errors on the error channel on a separate goroutine
go func() {
f.Sync()
f.Close()
- err = testRename(testFile, testFileRenamed)
- if err != nil {
+ if err := testRename(testFile, testFileRenamed); err != nil {
t.Fatalf("rename failed: %s", err)
}
}
func TestRemovalOfWatch(t *testing.T) {
- var testDir string = testTempDir()
-
// Create directory to watch
- if err := os.Mkdir(testDir, 0777); err != nil {
- t.Fatalf("failed to create test directory: %s", err)
- }
+ testDir := tempMkdir(t)
defer os.RemoveAll(testDir)
// Create a file before watching directory
- var testFileAlreadyExists string = filepath.Join(testDir, "TestFsnotifyEventsExisting.testfile")
+ testFileAlreadyExists := filepath.Join(testDir, "TestFsnotifyEventsExisting.testfile")
{
var f *os.File
f, err := os.OpenFile(testFileAlreadyExists, os.O_WRONLY|os.O_CREATE, 0666)
f.Close()
}
- watcher, err := NewWatcher()
- if err != nil {
- t.Fatalf("NewWatcher() failed: %s", err)
- }
+ watcher := newWatcher(t)
defer watcher.Close()
- watcher.Watch(testDir)
- err = watcher.RemoveWatch(testDir)
- if err != nil {
+ addWatch(t, watcher, testDir)
+ if err := watcher.RemoveWatch(testDir); err != nil {
t.Fatalf("Could not remove the watch: %v\n", err)
}
f.WriteString("data")
f.Sync()
f.Close()
- err = os.Chmod(testFileAlreadyExists, 0700)
- if err != nil {
+ if err := os.Chmod(testFileAlreadyExists, 0700); err != nil {
t.Fatalf("chmod failed: %s", err)
}
time.Sleep(400 * time.Millisecond)
if runtime.GOOS == "windows" {
t.Skip("attributes don't work on Windows.")
}
- // Create an fsnotify watcher instance and initialize it
- watcher, err := NewWatcher()
- if err != nil {
- t.Fatalf("NewWatcher() failed: %s", err)
- }
- var testDir string = testTempDir()
+ watcher := newWatcher(t)
// Create directory to watch
- if err := os.Mkdir(testDir, 0777); err != nil {
- t.Fatalf("failed to create test directory: %s", err)
- }
+ testDir := tempMkdir(t)
defer os.RemoveAll(testDir)
// Receive errors on the error channel on a separate goroutine
}
}()
- var testFile string = filepath.Join(testDir, "TestFsnotifyAttrib.testfile")
+ testFile := filepath.Join(testDir, "TestFsnotifyAttrib.testfile")
// Receive events on the event channel on a separate goroutine
eventstream := watcher.Event
// Create a file
// This should add at least one event to the fsnotify event queue
var f *os.File
- f, err = os.OpenFile(testFile, os.O_WRONLY|os.O_CREATE, 0666)
+ f, err := os.OpenFile(testFile, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
t.Fatalf("creating test file failed: %s", err)
}
f.Close()
// Add a watch for testFile
- err = watcher.Watch(testFile)
- if err != nil {
- t.Fatalf("watcher.Watch() failed: %s", err)
- }
+ addWatch(t, watcher, testFile)
- err = os.Chmod(testFile, 0700)
- if err != nil {
+ if err := os.Chmod(testFile, 0700); err != nil {
t.Fatalf("chmod failed: %s", err)
}
// Doing a chmod on the file should trigger an event with the "attrib" flag set (the contents
// of the file are not changed though)
- err = os.Chmod(testFile, 0600)
- if err != nil {
+ if err := os.Chmod(testFile, 0600); err != nil {
t.Fatalf("chmod failed: %s", err)
}
}
func TestFsnotifyClose(t *testing.T) {
- watcher, _ := NewWatcher()
+ watcher := newWatcher(t)
watcher.Close()
var done int32
t.Fatal("double Close() test failed: second Close() call didn't return")
}
- err := watcher.Watch(testTempDir())
- if err == nil {
+ testDir := tempMkdir(t)
+ defer os.RemoveAll(testDir)
+
+ if err := watcher.Watch(testDir); err == nil {
t.Fatal("expected error on Watch() after Close(), got nil")
}
}