179 lines
4.1 KiB
Go
179 lines
4.1 KiB
Go
package watcher
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestWatcherDetectsChange(t *testing.T) {
|
|
dir := t.TempDir()
|
|
path := filepath.Join(dir, "test.json")
|
|
if err := os.WriteFile(path, []byte(`{"version": 1}`), 0644); err != nil {
|
|
t.Fatalf("failed to write test file: %v", err)
|
|
}
|
|
|
|
changeDetected := make(chan bool, 1)
|
|
onChange := func() {
|
|
select {
|
|
case changeDetected <- true:
|
|
default:
|
|
}
|
|
}
|
|
|
|
fw := NewFileWatcher(path, 100*time.Millisecond, onChange)
|
|
fw.Start()
|
|
defer fw.Stop()
|
|
|
|
// Wait for initial hash to be computed
|
|
time.Sleep(200 * time.Millisecond)
|
|
|
|
// Modify the file
|
|
if err := os.WriteFile(path, []byte(`{"version": 2}`), 0644); err != nil {
|
|
t.Fatalf("failed to modify test file: %v", err)
|
|
}
|
|
|
|
// Wait for change detection
|
|
select {
|
|
case detected := <-changeDetected:
|
|
if !detected {
|
|
t.Error("expected change detection, got false")
|
|
}
|
|
case <-time.After(2 * time.Second):
|
|
t.Error("timeout waiting for file change detection")
|
|
}
|
|
}
|
|
|
|
func TestWatcherNoChange(t *testing.T) {
|
|
dir := t.TempDir()
|
|
path := filepath.Join(dir, "test.json")
|
|
if err := os.WriteFile(path, []byte(`{"version": 1}`), 0644); err != nil {
|
|
t.Fatalf("failed to write test file: %v", err)
|
|
}
|
|
|
|
changeDetected := make(chan bool, 1)
|
|
onChange := func() {
|
|
select {
|
|
case changeDetected <- true:
|
|
default:
|
|
}
|
|
}
|
|
|
|
fw := NewFileWatcher(path, 100*time.Millisecond, onChange)
|
|
fw.Start()
|
|
defer fw.Stop()
|
|
|
|
// Wait without modifying the file
|
|
time.Sleep(300 * time.Millisecond)
|
|
|
|
// Should not detect a change
|
|
select {
|
|
case <-changeDetected:
|
|
t.Error("unexpected change detection without file modification")
|
|
default:
|
|
// Expected: no change detected
|
|
}
|
|
}
|
|
|
|
func TestWatcherMultipleChanges(t *testing.T) {
|
|
dir := t.TempDir()
|
|
path := filepath.Join(dir, "test.json")
|
|
if err := os.WriteFile(path, []byte(`{"v": 1}`), 0644); err != nil {
|
|
t.Fatalf("failed to write test file: %v", err)
|
|
}
|
|
|
|
changeCount := 0
|
|
var mu chan struct{}
|
|
|
|
onChange := func() {
|
|
changeCount++
|
|
if mu != nil {
|
|
mu <- struct{}{}
|
|
}
|
|
}
|
|
|
|
fw := NewFileWatcher(path, 50*time.Millisecond, onChange)
|
|
fw.Start()
|
|
defer fw.Stop()
|
|
|
|
// Wait for initial hash
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
// Make 3 changes
|
|
for i := 2; i <= 4; i++ {
|
|
if err := os.WriteFile(path, []byte(`{"v": `+string(rune('0'+i))+`}`), 0644); err != nil {
|
|
t.Fatalf("failed to modify file: %v", err)
|
|
}
|
|
time.Sleep(150 * time.Millisecond)
|
|
}
|
|
|
|
if changeCount < 2 {
|
|
t.Errorf("expected at least 2 change detections, got %d", changeCount)
|
|
}
|
|
}
|
|
|
|
func TestWatcherStop(t *testing.T) {
|
|
dir := t.TempDir()
|
|
path := filepath.Join(dir, "test.json")
|
|
if err := os.WriteFile(path, []byte(`{"v": 1}`), 0644); err != nil {
|
|
t.Fatalf("failed to write test file: %v", err)
|
|
}
|
|
|
|
fw := NewFileWatcher(path, 50*time.Millisecond, func() {})
|
|
fw.Start()
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
fw.Stop()
|
|
|
|
// Should not panic on double stop or further operations
|
|
time.Sleep(100 * time.Millisecond)
|
|
}
|
|
|
|
func TestWatcherNonexistentFile(t *testing.T) {
|
|
onChange := func() {
|
|
t.Error("onChange should not be called for nonexistent file")
|
|
}
|
|
|
|
fw := NewFileWatcher("/nonexistent/file.json", 100*time.Millisecond, onChange)
|
|
fw.Start()
|
|
defer fw.Stop()
|
|
|
|
// Wait — should not call onChange since file doesn't exist
|
|
time.Sleep(300 * time.Millisecond)
|
|
}
|
|
|
|
func TestWatcherReproducible(t *testing.T) {
|
|
dir := t.TempDir()
|
|
path := filepath.Join(dir, "test.json")
|
|
if err := os.WriteFile(path, []byte(`{"data": "value"}`), 0644); err != nil {
|
|
t.Fatalf("failed to write test file: %v", err)
|
|
}
|
|
|
|
// Create two watchers on the same file
|
|
var detected1, detected2 bool
|
|
|
|
fw1 := NewFileWatcher(path, 50*time.Millisecond, func() { detected1 = true })
|
|
fw2 := NewFileWatcher(path, 50*time.Millisecond, func() { detected2 = true })
|
|
|
|
fw1.Start()
|
|
fw2.Start()
|
|
defer fw1.Stop()
|
|
defer fw2.Stop()
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
// Modify file
|
|
if err := os.WriteFile(path, []byte(`{"data": "changed"}`), 0644); err != nil {
|
|
t.Fatalf("failed to modify file: %v", err)
|
|
}
|
|
|
|
time.Sleep(300 * time.Millisecond)
|
|
|
|
if !detected1 {
|
|
t.Error("watcher 1 did not detect change")
|
|
}
|
|
if !detected2 {
|
|
t.Error("watcher 2 did not detect change")
|
|
}
|
|
} |