fix(ingestion): an unlistable brain root is a scan error, not clean
PR #159 round 2: with the brain root at mode 0100 (enterable, not listable) WalkDir failed at the root, Scan discarded the error and reported clean, and startup passed while search, which goes straight into wiki/, served a planted symlink. Scan now returns the root's walk error, so startup refuses on anything but a missing root. Also pins that a cleared set is reported again when it reappears. Refs #157 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -153,3 +153,37 @@ func TestWatchToleratesANonPositiveInterval(t *testing.T) {
|
||||
t.Fatal("Watch did not return on cancel")
|
||||
}
|
||||
}
|
||||
|
||||
// PR #159 round 2: a brain root that can be entered but not listed (mode
|
||||
// 0100) made WalkDir fail at the root; the error was discarded and Scan
|
||||
// reported clean, while search (which goes straight into wiki/) still served
|
||||
// a planted symlink. A root that cannot be listed is now an error.
|
||||
func TestScanOfAnUnlistableRootIsAnError(t *testing.T) {
|
||||
if os.Geteuid() == 0 {
|
||||
t.Skip("root lists mode-0100 directories")
|
||||
}
|
||||
brain := t.TempDir()
|
||||
require.NoError(t, os.MkdirAll(filepath.Join(brain, "wiki"), 0o755))
|
||||
require.NoError(t, os.Symlink(t.TempDir(), filepath.Join(brain, "wiki", "leak.md")))
|
||||
require.NoError(t, os.Chmod(brain, 0o100))
|
||||
t.Cleanup(func() { _ = os.Chmod(brain, 0o755) })
|
||||
_, err := Scan(brain)
|
||||
require.Error(t, err)
|
||||
assert.False(t, errors.Is(err, os.ErrNotExist), "an unlistable root is not a missing root")
|
||||
}
|
||||
|
||||
// The same set that disappears and comes back is reported again.
|
||||
func TestWatchReportsASetAgainAfterItWasCleared(t *testing.T) {
|
||||
brain := t.TempDir()
|
||||
link := filepath.Join(brain, "planted")
|
||||
n := &recNotifier{}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
go Watch(ctx, brain, 10*time.Millisecond, n)
|
||||
require.NoError(t, os.Symlink(t.TempDir(), link))
|
||||
require.Eventually(t, func() bool { return n.count() == 1 }, 2*time.Second, 10*time.Millisecond)
|
||||
require.NoError(t, os.Remove(link))
|
||||
time.Sleep(60 * time.Millisecond)
|
||||
require.NoError(t, os.Symlink(t.TempDir(), link))
|
||||
require.Eventually(t, func() bool { return n.count() == 2 }, 2*time.Second, 10*time.Millisecond)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user