I have a function that watches certian file via fsnotify and calls a callback when the file changes. If the callback returns false, the watching is ended:
import (
"github.com/golang/glog"
"github.com/fsnotify/fsnotify"
)
type WatcherFunc func(err error) bool
func WatchFileChanges(filename string, watcherFunc WatcherFunc) {
watcher, err := fsnotify.NewWatcher()
if err != nil {
glog.Errorf("Got error creating watcher %s", err)
}
defer watcher.Close()
done := make(chan bool)
go func() {
for {
select {
case event := <-watcher.Events:
glog.Infof("inotify event %s", event)
if event.Op&fsnotify.Write == fsnotify.Write {
glog.Infof("modified file %s, calling watcher func", event.Name)
if !watcherFunc(nil) {
close(done)
}
}
case err := <-watcher.Errors:
glog.Errorf("Got error watching %s, calling watcher func", err)
if !watcherFunc(err) {
close(done)
}
}
}
}()
glog.Infof("Start watching file %s", filename)
err = watcher.Add(filename)
if err != nil {
glog.Errorf("Got error adding watcher %s", err)
}
<-done
}
Then I thought it would be nice to have a test for that, so I started out with a simple test case:
import (
"io/ioutil"
"os"
"testing"
)
func TestStuff(t *testing.T) {
tmpfile, err := ioutil.TempFile("", "test")
if err != nil {
t.Fatal("Failed to create tmp file")
}
defer os.Remove(tmpfile.Name())
watcherFunc := func (err error) bool {
return false
}
WatchFileChanges(tmpfile.Name(), watcherFunc)
}
What I wanted do to here is to do a few modifications to the file, collect the events in an array, return then false
from the watcherFunc
and then assert on the array. The thing is, of course the test just hangs and waits for events, as the goroutine was started.
Is there any way how I can test a function like this, like … starting a different thread (?) that updates/modifies the file?