package fileutil import ( "context" "os" "path/filepath" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestWatcher(t *testing.T) { tmpdir := t.TempDir() err := os.WriteFile(filepath.Join(tmpdir, "test1.txt"), []byte{1}, 0o666) require.NoError(t, err) w := NewWatcher() w.Watch(context.Background(), []string{filepath.Join(tmpdir, "test1.txt")}) ch := w.Bind() t.Cleanup(func() { w.Unbind(ch) }) err = os.WriteFile(filepath.Join(tmpdir, "test1.txt"), []byte{1, 2}, 0o666) require.NoError(t, err) expectChange(t, ch) } func TestWatcherSymlink(t *testing.T) { tmpdir := t.TempDir() err := os.WriteFile(filepath.Join(tmpdir, "test1.txt"), []byte{1}, 0o666) require.NoError(t, err) err = os.WriteFile(filepath.Join(tmpdir, "test2.txt"), []byte{1, 2}, 0o666) require.NoError(t, err) assert.NoError(t, os.Symlink(filepath.Join(tmpdir, "test1.txt"), filepath.Join(tmpdir, "symlink1.txt"))) w := NewWatcher() w.Watch(context.Background(), []string{filepath.Join(tmpdir, "symlink1.txt")}) ch := w.Bind() t.Cleanup(func() { w.Unbind(ch) }) assert.NoError(t, os.WriteFile(filepath.Join(tmpdir, "test1.txt"), []byte{1, 2, 3}, 0o666)) expectChange(t, ch) assert.NoError(t, os.Symlink(filepath.Join(tmpdir, "test2.txt"), filepath.Join(tmpdir, "symlink2.txt"))) assert.NoError(t, os.Rename(filepath.Join(tmpdir, "symlink2.txt"), filepath.Join(tmpdir, "symlink1.txt"))) expectChange(t, ch) } func TestWatcher_FileRemoval(t *testing.T) { tmpdir := t.TempDir() err := os.WriteFile(filepath.Join(tmpdir, "test1.txt"), []byte{1}, 0o666) require.NoError(t, err) w := NewWatcher() w.Watch(context.Background(), []string{filepath.Join(tmpdir, "test1.txt")}) ch := w.Bind() t.Cleanup(func() { w.Unbind(ch) }) err = os.Remove(filepath.Join(tmpdir, "test1.txt")) require.NoError(t, err) expectChange(t, ch) err = os.WriteFile(filepath.Join(tmpdir, "test1.txt"), []byte{1, 2}, 0o666) require.NoError(t, err) expectChange(t, ch) } func expectChange(t *testing.T, ch chan context.Context) { t.Helper() cnt := 0 select { case <-ch: cnt++ case <-time.After(10 * time.Second): } if cnt == 0 { t.Error("expected change signal") } }