From dd84b9d64fb98746a230cd24233ff50a562c39c9 Mon Sep 17 00:00:00 2001 From: 简律纯 Date: Fri, 28 Apr 2023 01:36:44 +0800 Subject: --- cli/internal/filewatcher/filewatcher_test.go | 152 +++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 cli/internal/filewatcher/filewatcher_test.go (limited to 'cli/internal/filewatcher/filewatcher_test.go') diff --git a/cli/internal/filewatcher/filewatcher_test.go b/cli/internal/filewatcher/filewatcher_test.go new file mode 100644 index 0000000..72b48ba --- /dev/null +++ b/cli/internal/filewatcher/filewatcher_test.go @@ -0,0 +1,152 @@ +package filewatcher + +import ( + "fmt" + "sync" + "testing" + "time" + + "github.com/hashicorp/go-hclog" + "github.com/vercel/turbo/cli/internal/fs" + "github.com/vercel/turbo/cli/internal/turbopath" + "gotest.tools/v3/assert" +) + +type testClient struct { + mu sync.Mutex + createEvents []Event + notify chan Event +} + +func (c *testClient) OnFileWatchEvent(ev Event) { + if ev.EventType == FileAdded { + c.mu.Lock() + defer c.mu.Unlock() + c.createEvents = append(c.createEvents, ev) + c.notify <- ev + } +} + +func (c *testClient) OnFileWatchError(err error) {} + +func (c *testClient) OnFileWatchClosed() {} + +func expectFilesystemEvent(t *testing.T, ch <-chan Event, expected Event) { + // mark this method as a helper + t.Helper() + timeout := time.After(1 * time.Second) + for { + select { + case ev := <-ch: + t.Logf("got event %v", ev) + if ev.Path == expected.Path && ev.EventType == expected.EventType { + return + } + case <-timeout: + t.Errorf("Timed out waiting for filesystem event at %v", expected.Path) + return + } + } +} + +func expectNoFilesystemEvent(t *testing.T, ch <-chan Event) { + // mark this method as a helper + t.Helper() + select { + case ev, ok := <-ch: + if ok { + t.Errorf("got unexpected filesystem event %v", ev) + } else { + t.Error("filewatching closed unexpectedly") + } + case <-time.After(500 * time.Millisecond): + return + } +} + +func expectWatching(t *testing.T, c *testClient, dirs []turbopath.AbsoluteSystemPath) { + t.Helper() + now := time.Now() + filename := fmt.Sprintf("test-%v", now.UnixMilli()) + for _, dir := range dirs { + file := dir.UntypedJoin(filename) + err := file.WriteFile([]byte("hello"), 0755) + assert.NilError(t, err, "WriteFile") + expectFilesystemEvent(t, c.notify, Event{ + Path: file, + EventType: FileAdded, + }) + } +} + +func TestFileWatching(t *testing.T) { + logger := hclog.Default() + logger.SetLevel(hclog.Debug) + repoRoot := fs.AbsoluteSystemPathFromUpstream(t.TempDir()) + err := repoRoot.UntypedJoin(".git").MkdirAll(0775) + assert.NilError(t, err, "MkdirAll") + err = repoRoot.UntypedJoin("node_modules", "some-dep").MkdirAll(0775) + assert.NilError(t, err, "MkdirAll") + err = repoRoot.UntypedJoin("parent", "child").MkdirAll(0775) + assert.NilError(t, err, "MkdirAll") + err = repoRoot.UntypedJoin("parent", "sibling").MkdirAll(0775) + assert.NilError(t, err, "MkdirAll") + + // Directory layout: + // / + // .git/ + // node_modules/ + // some-dep/ + // parent/ + // child/ + // sibling/ + + watcher, err := GetPlatformSpecificBackend(logger) + assert.NilError(t, err, "GetPlatformSpecificBackend") + fw := New(logger, repoRoot, watcher) + err = fw.Start() + assert.NilError(t, err, "fw.Start") + + // Add a client + ch := make(chan Event, 1) + c := &testClient{ + notify: ch, + } + fw.AddClient(c) + expectedWatching := []turbopath.AbsoluteSystemPath{ + repoRoot, + repoRoot.UntypedJoin("parent"), + repoRoot.UntypedJoin("parent", "child"), + repoRoot.UntypedJoin("parent", "sibling"), + } + expectWatching(t, c, expectedWatching) + + fooPath := repoRoot.UntypedJoin("parent", "child", "foo") + err = fooPath.WriteFile([]byte("hello"), 0644) + assert.NilError(t, err, "WriteFile") + expectFilesystemEvent(t, ch, Event{ + EventType: FileAdded, + Path: fooPath, + }) + + deepPath := repoRoot.UntypedJoin("parent", "sibling", "deep", "path") + err = deepPath.MkdirAll(0775) + assert.NilError(t, err, "MkdirAll") + // We'll catch an event for "deep", but not "deep/path" since + // we don't have a recursive watch + expectFilesystemEvent(t, ch, Event{ + Path: repoRoot.UntypedJoin("parent", "sibling", "deep"), + EventType: FileAdded, + }) + expectFilesystemEvent(t, ch, Event{ + Path: repoRoot.UntypedJoin("parent", "sibling", "deep", "path"), + EventType: FileAdded, + }) + expectedWatching = append(expectedWatching, deepPath, repoRoot.UntypedJoin("parent", "sibling", "deep")) + expectWatching(t, c, expectedWatching) + + gitFilePath := repoRoot.UntypedJoin(".git", "git-file") + err = gitFilePath.WriteFile([]byte("nope"), 0644) + assert.NilError(t, err, "WriteFile") + expectNoFilesystemEvent(t, ch) +} -- cgit v1.2.3-70-g09d2