英文:
How to test a function that watches a file in a goroutine
问题
我有一个函数,通过fsnotify监视特定的文件,并在文件更改时调用回调函数。如果回调函数返回false,则停止监视:
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
}
然后我想为它编写一个测试,所以我从一个简单的测试用例开始:
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)
}
我想在这里对文件进行一些修改,将事件收集到一个数组中,然后从watcherFunc
返回false
,最后对数组进行断言。问题是,当启动了goroutine时,测试会一直挂起等待事件。
有没有办法测试这样的函数,比如...启动一个不同的线程(?)来更新/修改文件?
英文:
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?
答案1
得分: 0
当然可以。你可以启动一个 goroutine 来执行你想要的更新操作。
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
}
go func() {
// 在这里进行更新操作
}()
WatchFileChanges(tmpfile.Name(), watcherFunc)
}
在这个示例中,你可以在 go func()
中执行你想要的更新操作。
英文:
> Is there any way how I can test a function like this, like … starting a different thread (?) that updates/modifies the file?
Of course... start a goroutine that does the updates you want.
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
}
go func() {
// Do updates here
}()
WatchFileChanges(tmpfile.Name(), watcherFunc)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论