kra-new/internal/data/config_watch_test.go

60 lines
1.4 KiB
Go

package data
import (
"os"
"path/filepath"
"sync"
"testing"
"time"
"kra/internal/config"
)
func TestConfigWatcherStopWaitsForDebouncedReload(t *testing.T) {
root := t.TempDir()
configPath := filepath.Join(root, "config.yaml")
rawConfig := []byte("data:\n database:\n driver: sqlite\n path: " + filepath.ToSlash(root) + "\nadmin: {}\n")
if err := os.WriteFile(configPath, rawConfig, 0o600); err != nil {
t.Fatal(err)
}
runtime := config.NewStore(&config.Config{Data: &config.Data{}, Admin: &config.Admin{ConfigPath: configPath}})
started := make(chan struct{})
release := make(chan struct{})
var startOnce sync.Once
stopListener := runtime.Subscribe(func(*config.Config) {
startOnce.Do(func() { close(started) })
<-release
})
defer stopListener()
data := &Data{runtime: runtime}
stop := data.watchConfig()
// A write event schedules the 100ms debounce reload.
if err := os.WriteFile(configPath, rawConfig, 0o600); err != nil {
t.Fatal(err)
}
select {
case <-started:
case <-time.After(3 * time.Second):
stop()
t.Fatal("debounced reload did not start")
}
stopped := make(chan struct{})
go func() {
stop()
close(stopped)
}()
select {
case <-stopped:
t.Fatal("watcher stop returned before reload callback finished")
case <-time.After(100 * time.Millisecond):
}
close(release)
select {
case <-stopped:
case <-time.After(time.Second):
t.Fatal("watcher stop did not wait for callback completion")
}
}