test(watcher): a marker link planted during the run is refused and not retried (#158)
Review round 2 on PR #195: the marker writes had no test, so reverting them to by-path writes, or the refusal to log-only, stayed green. The link is planted from inside the fake model call, between the walk's Lstat and the marker write, for both markers and both an outside and an in-brain relative target; red on all four flips. The marker-entry skip is now checked for .failed too. Also pins cleanRel's acceptance of a backslash as a filename byte in brainfs itself, and stops the buildAndWrite control claiming writes it does not count. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -82,17 +82,73 @@ func TestProcessDirDoesNotAppendTheLogThroughASymlink(t *testing.T) {
|
||||
// marker: the note is skipped and nothing is created at the link's target.
|
||||
// (os.Stat followed the link, saw nothing, and processed the note again.)
|
||||
func TestProcessDirTreatsAnyEntryAtTheMarkerPathAsAMarker(t *testing.T) {
|
||||
brainDir := setupBrainDir(t)
|
||||
outside := filepath.Join(t.TempDir(), "created")
|
||||
require.NoError(t, os.WriteFile(filepath.Join(brainDir, "raw", "n.md"), []byte("note"), 0o644))
|
||||
require.NoError(t, os.Symlink(outside, filepath.Join(brainDir, "raw", "n.md.processed")))
|
||||
calls := 0
|
||||
cfg := Config{BrainDir: brainDir, Interval: time.Hour, Pipeline: pipeline.Config{
|
||||
Complete: func(context.Context, string, string) (string, error) { calls++; return "[]", nil }, Schema: "# Schema"}}
|
||||
_ = processDir(context.Background(), cfg, "2026-10-05")
|
||||
assert.Zero(t, calls, "the note was processed despite an entry at its marker path")
|
||||
_, err := os.Lstat(outside)
|
||||
assert.True(t, os.IsNotExist(err), "a file was created at the marker link's target")
|
||||
for _, kind := range []string{"processed", "failed"} {
|
||||
t.Run(kind, func(t *testing.T) {
|
||||
brainDir := setupBrainDir(t)
|
||||
outside := filepath.Join(t.TempDir(), "created")
|
||||
require.NoError(t, os.WriteFile(filepath.Join(brainDir, "raw", "n.md"), []byte("note"), 0o644))
|
||||
require.NoError(t, os.Symlink(outside, filepath.Join(brainDir, "raw", "n.md."+kind)))
|
||||
calls := 0
|
||||
cfg := Config{BrainDir: brainDir, Interval: time.Hour, Pipeline: pipeline.Config{
|
||||
Complete: func(context.Context, string, string) (string, error) { calls++; return "[]", nil }, Schema: "# Schema"}}
|
||||
_ = processDir(context.Background(), cfg, "2026-10-05")
|
||||
assert.Zero(t, calls, "the note was processed despite an entry at its marker path")
|
||||
_, err := os.Lstat(outside)
|
||||
assert.True(t, os.IsNotExist(err), "a file was created at the marker link's target")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// The marker write itself is reachable while pipeline.Run is in flight
|
||||
// (in production, an LLM call): a link planted at the marker path then is
|
||||
// refused, and the note is remembered, so removing the link (as
|
||||
// symlinkguard does) does not make the watcher call the model again.
|
||||
func TestProcessDirRefusesAMarkerLinkPlantedDuringTheRunAndDoesNotRetry(t *testing.T) {
|
||||
for _, kind := range []string{"processed", "failed"} {
|
||||
for _, target := range []string{"outside", "in-brain"} {
|
||||
t.Run(kind+"/"+target, func(t *testing.T) {
|
||||
brainDir := setupBrainDir(t)
|
||||
raw := filepath.Join(brainDir, "raw")
|
||||
marker := filepath.Join(raw, "n.md."+kind)
|
||||
require.NoError(t, os.WriteFile(filepath.Join(raw, "n.md"), []byte("note"), 0o644))
|
||||
// The in-brain target is relative, so os.Root itself would
|
||||
// follow it; only the regular-file check refuses it.
|
||||
victim := filepath.Join(raw, "victim")
|
||||
link := filepath.Join(t.TempDir(), "created")
|
||||
if target == "in-brain" {
|
||||
require.NoError(t, os.WriteFile(victim, []byte("untouched"), 0o644))
|
||||
link = "victim"
|
||||
}
|
||||
ok := okPipeline().Complete
|
||||
calls := 0
|
||||
cfg := Config{BrainDir: brainDir, Interval: time.Hour, Pipeline: pipeline.Config{Schema: "# Schema",
|
||||
Complete: func(ctx context.Context, sys, user string) (string, error) {
|
||||
calls++
|
||||
require.NoError(t, os.Symlink(link, marker))
|
||||
if kind == "failed" {
|
||||
return "", errors.New("model down")
|
||||
}
|
||||
return ok(ctx, sys, user)
|
||||
}}}
|
||||
for i := 0; i < 3; i++ {
|
||||
errs := processDir(context.Background(), cfg, "2026-10-05")
|
||||
if i == 0 {
|
||||
require.NotEmpty(t, errs, "the planted link was not refused")
|
||||
}
|
||||
_ = os.Remove(marker)
|
||||
}
|
||||
assert.Equal(t, 1, calls, "the note was retried after its marker write was refused")
|
||||
if target == "in-brain" {
|
||||
got, err := os.ReadFile(victim)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "untouched", string(got), "the marker was written through the link")
|
||||
} else {
|
||||
_, err := os.Lstat(link)
|
||||
assert.True(t, os.IsNotExist(err), "the marker was written through the link")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A refused archive copy must not retry every interval: the note is
|
||||
|
||||
Reference in New Issue
Block a user