Poll source files/directories and regenerate output on change. Output path is excluded from watching; errors don't stop the loop. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
93 lines
2.6 KiB
Go
93 lines
2.6 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"sync/atomic"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestWatchSnapshotExcludesOutput(t *testing.T) {
|
|
dir := t.TempDir()
|
|
out := filepath.Join(dir, "out")
|
|
if err := os.MkdirAll(out, 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
src := filepath.Join(dir, "schema.dbml")
|
|
if err := os.WriteFile(src, []byte("a"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
before := takeWatchSnapshot([]string{dir}, out)
|
|
if err := os.WriteFile(filepath.Join(out, "gen.go"), []byte("x"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if after := takeWatchSnapshot([]string{dir}, out); !before.equal(after) {
|
|
t.Errorf("writing into the excluded output path changed the snapshot")
|
|
}
|
|
if err := os.WriteFile(src, []byte("changed"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if after := takeWatchSnapshot([]string{dir}, out); before.equal(after) {
|
|
t.Errorf("modifying a source file did not change the snapshot")
|
|
}
|
|
}
|
|
|
|
func TestWatchLoopRerunsOnChange(t *testing.T) {
|
|
dir := t.TempDir()
|
|
src := filepath.Join(dir, "schema.dbml")
|
|
if err := os.WriteFile(src, []byte("a"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
var runs atomic.Int32
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
done := make(chan struct{})
|
|
go func() {
|
|
defer close(done)
|
|
watchLoop(ctx, io.Discard, []string{src}, "", 10*time.Millisecond, func() error {
|
|
runs.Add(1)
|
|
return nil
|
|
})
|
|
}()
|
|
|
|
waitFor(t, func() bool { return runs.Load() == 1 })
|
|
if err := os.WriteFile(src, []byte("changed content"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
waitFor(t, func() bool { return runs.Load() == 2 })
|
|
cancel()
|
|
<-done
|
|
}
|
|
|
|
func TestRunConvertWatchValidation(t *testing.T) {
|
|
oldPath, oldList, oldDry, oldInt := convertSourcePath, convertFromList, convertDryRun, convertWatchInterval
|
|
defer func() {
|
|
convertSourcePath, convertFromList, convertDryRun, convertWatchInterval = oldPath, oldList, oldDry, oldInt
|
|
}()
|
|
convertSourcePath, convertFromList, convertDryRun, convertWatchInterval = "", nil, false, time.Second
|
|
if err := runConvertWatch(context.Background(), &bytes.Buffer{}, nil); err == nil {
|
|
t.Error("expected error without --from-path/--from-list")
|
|
}
|
|
convertSourcePath, convertDryRun = "x.dbml", true
|
|
if err := runConvertWatch(context.Background(), &bytes.Buffer{}, nil); err == nil {
|
|
t.Error("expected error combining --watch with --dry-run")
|
|
}
|
|
}
|
|
|
|
func waitFor(t *testing.T, cond func() bool) {
|
|
t.Helper()
|
|
deadline := time.Now().Add(5 * time.Second)
|
|
for time.Now().Before(deadline) {
|
|
if cond() {
|
|
return
|
|
}
|
|
time.Sleep(5 * time.Millisecond)
|
|
}
|
|
t.Fatal("condition not met in time")
|
|
}
|