Files
hyperguild/ingestion/internal/mcp/readexcerpt_root_test.go
T
mathiasandClaude Opus 5.5 b6f7dac46e
CI / Lint / Test / Vet (pull_request) Successful in 44s
CI / Mirror to GitHub (pull_request) Skipped
fix(brain): context, brain_get and brain_read read through brainfs (#157, slice 2)
Option 1 of #157, slice 2. readExcerpt (brain_context), api.ReadNote
(brain_get / read-after-write) and notes.ReadScoped (brain_read) read
the Syncthing-shared brain by path. Under a symlink swap race each
leaked an outside file hundreds of thousands of times in 1.5s, including
brain_read, whose Lstat check was raced by the reopen-by-name; a FIFO
blocked os.ReadFile.

- All three read through brainfs (os.Root, regular files only,
  non-blocking open, type check on the handle).
- brainfs.ReadRegularMax checks a size limit on the opened handle;
  notes keeps its ErrTooLarge.
- New internal/brainfs/brainfstest: the shared swap-race harness
  (symlink and held-writer FIFO swappers, awaited before TempDir
  cleanup; AssertNoLeak / AssertNoHang) for this and later slices.

Tests red first: each reader under a symlink-swap race and a held-writer
FIFO race, plus static checks. Flipped: readExcerpt back to os.ReadFile
is red.

Refs #157

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 00:22:47 +02:00

35 lines
1.3 KiB
Go

package mcp
import (
"os"
"path/filepath"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/mathiasbq/hyperguild/ingestion/internal/brainfs/brainfstest"
)
// hyperguild#157 slice 2: readExcerpt (brain_context) read by path, so a
// symlink in the Syncthing-shared brain put an outside file in context, and
// a FIFO hung it. It now reads through brainfs.
func TestReadExcerptIsConfinedToRegularFilesInTheBrain(t *testing.T) {
brain := t.TempDir()
facts := filepath.Join(brain, "wiki", "w", "facts")
require.NoError(t, os.MkdirAll(facts, 0o755))
require.NoError(t, os.Symlink(brainfstest.Outside(t), filepath.Join(facts, "leak.md")))
assert.NotContains(t, readExcerpt(brain, "wiki/w/facts/leak.md", 500), brainfstest.Sentinel)
p := filepath.Join(facts, "r.md")
require.NoError(t, os.WriteFile(p, []byte("---\nx: y\n---\ninside"), 0o644))
assert.Equal(t, "inside", readExcerpt(brain, "wiki/w/facts/r.md", 500))
brainfstest.AssertNoLeak(t, p, "---\nx: y\n---\ninside", 1500*time.Millisecond, func() string {
return readExcerpt(brain, "wiki/w/facts/r.md", 500)
})
brainfstest.AssertNoHang(t, p, "---\nx: y\n---\ninside", 1500*time.Millisecond, 6*time.Second, func() {
_ = readExcerpt(brain, "wiki/w/facts/r.md", 500)
})
}