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") }