package api_test import ( "os" "path/filepath" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/mathiasbq/hyperguild/ingestion/internal/api" "github.com/mathiasbq/hyperguild/ingestion/internal/brainfs/brainfstest" ) // hyperguild#157 slice 2: ReadNote (brain_get, read-after-write) read by // path; it now reads through brainfs. func TestReadNoteRefusesSymlinksAndSurvivesSwapRaces(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"))) _, body, _, err := api.ReadNote(brain, "wiki/w/facts/leak.md") assert.Error(t, err) assert.NotContains(t, body, brainfstest.Sentinel) // A link to a file elsewhere in the brain: os.Root allows it, only the // regular-file check refuses it (hyperguild#171). brainfstest.WriteSentinelAt(t, filepath.Join(brain, "raw", "s.md")) require.NoError(t, os.Symlink(filepath.Join("..", "..", "..", "raw", "s.md"), filepath.Join(facts, "inlink.md"))) _, body, _, err = api.ReadNote(brain, "wiki/w/facts/inlink.md") assert.Error(t, err) assert.NotContains(t, body, brainfstest.Sentinel) p := filepath.Join(facts, "r.md") require.NoError(t, os.WriteFile(p, []byte("---\nx: y\n---\ninside"), 0o644)) fm, body, _, err := api.ReadNote(brain, "wiki/w/facts/r.md") require.NoError(t, err) assert.Equal(t, "y", fm["x"]) assert.Contains(t, body, "inside") read := func() string { fm, body, _, _ := api.ReadNote(brain, "wiki/w/facts/r.md") s := body for k, v := range fm { s += k + v } return s } brainfstest.AssertNoLeak(t, p, "---\nx: y\n---\ninside", 1500*time.Millisecond, read) inBrain := brainfstest.WriteSentinelAt(t, filepath.Join(brain, "raw", "s.md")) brainfstest.AssertNoLeakFrom(t, p, "---\nx: y\n---\ninside", inBrain, 1500*time.Millisecond, read) brainfstest.AssertNoHang(t, p, "---\nx: y\n---\ninside", 1500*time.Millisecond, 6*time.Second, func() { _ = read() }) }