我试图为一个简单的程序编写测试,该程序从inotify总线读取事件,过滤它们,然后将它们放在一个通道上。我在实际运行代码时没有看到任何问题,但是在下面的测试的最后一行中,从该通道读取时偶尔会死锁(大约30%的时间),尽管我可以说,事件是始终被放置在频道上。
这是功能:
func eventFilter(watcher *rfsnotify.RWatcher, excludes []string, out chan<- fsnotify.Event) {
for {
select {
case event := <-watcher.Events:
log.Debug(fmt.Sprintf("Got event %v", event))
if isExcluded(event.Name, excludes) {
log.Info("Ignoring excluded file: %v", event)
} else if isRelevantOp(event) {
log.Info(fmt.Sprintf("Handling event %v", event))
out <- event
} else {
log.Info(fmt.Sprintf("Ignoring event %v", event))
}
case err := <-watcher.Errors:
log.Error(fmt.Sprintf("Error: %v", err))
}
}
}
以下是测试代码:
var hook *logrusTest.Hook
var testDir string
var rWatcher *rfsnotify.RWatcher
func TestMain(m *testing.M) {
// initialize bad globals, amongst other things
log.SetLevel(log.DebugLevel)
hook = logrusTest.NewGlobal()
// Create directory to watch
testDir = tempMkdir()
defer os.RemoveAll(testDir)
rWatcher, _ = rfsnotify.NewWatcher()
defer rWatcher.Close()
err := rWatcher.AddRecursive(testDir)
if err != nil {
log.Fatal("Failed to add watcher: ", err)
}
os.Exit(m.Run())
}
func TestEventFilterMove(t *testing.T) {
ch := make(chan fsnotify.Event, 10)
go eventFilter(rWatcher, []string{"test"}, ch)
testFileSrc := filepath.Join(testDir, "TestFsnotifyEvents.testfileSrc")
testFileDest := filepath.Join(testDir, "TestFsnotifyEvents.testfileDest")
f, err := os.OpenFile(testFileSrc, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
t.Fatalf("creating test file failed: %s", err)
}
f.WriteString("data")
f.Sync()
hook.Reset()
err = os.Rename(testFileSrc, testFileDest)
if err != nil {
t.Fatalf("renaming test file failed: %s", err)
}
time.Sleep(100 * time.Millisecond)
expectedLogs := []string{
fmt.Sprintf("Got event \"%v\": CREATE|UPDATE", testFileDest),
fmt.Sprintf("Handling event \"%v\": CREATE|UPDATE", testFileDest),
fmt.Sprintf("Got event \"%v\": RENAME", testFileSrc),
fmt.Sprintf("Ignoring event \"%v\": RENAME", testFileSrc),
}
var actualLogs []string
for _, logEntry := range hook.AllEntries() {
actualLogs = append(actualLogs, logEntry.Message)
}
assert.ElementsMatch(t, actualLogs, expectedLogs)
hook.Reset()
_ = <-ch
assert.Equal(t, 0, len(ch))
}