diff --git a/.travis.yml b/.travis.yml index 981d1bb8..568aaa12 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,9 +2,10 @@ sudo: false language: go go: - - 1.8.x - - 1.9.x - - tip + - "stable" + - "1.10.4" + - "1.9.x" + - "1.8.x" matrix: allow_failures: @@ -12,10 +13,10 @@ matrix: fast_finish: true before_script: - - go get -u github.com/golang/lint/golint + - go get -u golang.org/x/lint/golint script: - - go test -v --race ./... + - go test --race ./... after_script: - test -z "$(gofmt -s -l -w . | tee /dev/stderr)" diff --git a/example_test.go b/example_test.go index 700502cb..b4f9f956 100644 --- a/example_test.go +++ b/example_test.go @@ -23,12 +23,18 @@ func ExampleNewWatcher() { go func() { for { select { - case event := <-watcher.Events: + case event, ok := <-watcher.Events: + if !ok { + return + } log.Println("event:", event) if event.Op&fsnotify.Write == fsnotify.Write { log.Println("modified file:", event.Name) } - case err := <-watcher.Errors: + case err, ok := <-watcher.Errors: + if !ok { + return + } log.Println("error:", err) } } diff --git a/inotify_test.go b/inotify_test.go index 54f3f00e..2c11d2ed 100644 --- a/inotify_test.go +++ b/inotify_test.go @@ -11,6 +11,7 @@ import ( "os" "path/filepath" "strings" + "sync" "testing" "time" ) @@ -390,9 +391,12 @@ func TestInotifyOverflow(t *testing.T) { errChan := make(chan error, numDirs*numFiles) + // All events need to be in the inotify queue before pulling events off it to trigger this error. + wg := sync.WaitGroup{} for dn := 0; dn < numDirs; dn++ { testSubdir := fmt.Sprintf("%s/%d", testDir, dn) + wg.Add(1) go func() { for fn := 0; fn < numFiles; fn++ { testFile := fmt.Sprintf("%s/%d", testSubdir, fn) @@ -409,8 +413,10 @@ func TestInotifyOverflow(t *testing.T) { continue } } + wg.Done() }() } + wg.Wait() creates := 0 overflows := 0 diff --git a/integration_darwin_test.go b/integration_darwin_test.go index cd6adc27..c43d00c6 100644 --- a/integration_darwin_test.go +++ b/integration_darwin_test.go @@ -7,12 +7,24 @@ package fsnotify import ( "os" "path/filepath" + "strconv" + "strings" "testing" "time" "golang.org/x/sys/unix" ) +// darwinVersion returns version os Darwin (17 is macOS 10.13). +func darwinVersion() (int, error) { + s, err := unix.Sysctl("kern.osrelease") + if err != nil { + return 0, err + } + s = strings.Split(s, ".")[0] + return strconv.Atoi(s) +} + // testExchangedataForWatcher tests the watcher with the exchangedata operation on macOS. // // This is widely used for atomic saves on macOS, e.g. TextMate and in Apple's NSDocument. @@ -20,6 +32,14 @@ import ( // See https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man2/exchangedata.2.html // Also see: https://github.com/textmate/textmate/blob/cd016be29489eba5f3c09b7b70b06da134dda550/Frameworks/io/src/swap_file_data.cc#L20 func testExchangedataForWatcher(t *testing.T, watchDir bool) { + osVersion, err := darwinVersion() + if err != nil { + t.Fatal("unable to get Darwin version:", err) + } + if osVersion >= 17 { + t.Skip("Exchangedata is deprecated in macOS 10.13") + } + // Create directory to watch testDir1 := tempMkdir(t) @@ -55,7 +75,7 @@ func testExchangedataForWatcher(t *testing.T, watchDir bool) { // Receive errors on the error channel on a separate goroutine go func() { for err := range watcher.Errors { - t.Fatalf("error received: %s", err) + t.Errorf("error received: %s", err) } }() diff --git a/integration_test.go b/integration_test.go index 8b7e9d3e..7096344d 100644 --- a/integration_test.go +++ b/integration_test.go @@ -194,7 +194,7 @@ func TestFsnotifyMultipleCreates(t *testing.T) { // Receive errors on the error channel on a separate goroutine go func() { for err := range watcher.Errors { - t.Fatalf("error received: %s", err) + t.Errorf("error received: %s", err) } }() @@ -339,7 +339,7 @@ func TestFsnotifyDirOnly(t *testing.T) { // Receive errors on the error channel on a separate goroutine go func() { for err := range watcher.Errors { - t.Fatalf("error received: %s", err) + t.Errorf("error received: %s", err) } }() @@ -444,7 +444,7 @@ func TestFsnotifyDeleteWatchedDir(t *testing.T) { // Receive errors on the error channel on a separate goroutine go func() { for err := range watcher.Errors { - t.Fatalf("error received: %s", err) + t.Errorf("error received: %s", err) } }() @@ -489,7 +489,7 @@ func TestFsnotifySubDir(t *testing.T) { // Receive errors on the error channel on a separate goroutine go func() { for err := range watcher.Errors { - t.Fatalf("error received: %s", err) + t.Errorf("error received: %s", err) } }() @@ -581,7 +581,7 @@ func TestFsnotifyRename(t *testing.T) { // Receive errors on the error channel on a separate goroutine go func() { for err := range watcher.Errors { - t.Fatalf("error received: %s", err) + t.Errorf("error received: %s", err) } }() @@ -663,7 +663,7 @@ func TestFsnotifyRenameToCreate(t *testing.T) { // Receive errors on the error channel on a separate goroutine go func() { for err := range watcher.Errors { - t.Fatalf("error received: %s", err) + t.Errorf("error received: %s", err) } }() @@ -756,7 +756,7 @@ func TestFsnotifyRenameToOverwrite(t *testing.T) { // Receive errors on the error channel on a separate goroutine go func() { for err := range watcher.Errors { - t.Fatalf("error received: %s", err) + t.Errorf("error received: %s", err) } }() @@ -874,7 +874,7 @@ func TestFsnotifyAttrib(t *testing.T) { // Receive errors on the error channel on a separate goroutine go func() { for err := range watcher.Errors { - t.Fatalf("error received: %s", err) + t.Errorf("error received: %s", err) } }()