From ac84ddf5a954b4202c6546d7ad1e9e8a2dcdfe4f Mon Sep 17 00:00:00 2001 From: Mathias Date: Mon, 5 Oct 2026 23:19:02 +0200 Subject: [PATCH] test: pin CreateRegular directly and promote/reject with in-brain targets (#188) Review round 2 on PR #189: CreateRegular (promote's and reject's only write path) had no test; replacing mkdirReal with root.MkdirAll, dropping cleanRel or calling PutRegular all stayed green, and the promote/reject test planted only outside targets, which os.Root refuses on its own. - TestCreateRegularCreatesOnlyNewFilesThroughRealDirectories: in-brain symlinked parent, unclean path, existing file and dangling link (fs.ErrExist, nothing changed), positive control with missing parents. - TestPromoteAndRejectRefuseAnInBrainSymlinkedDestinationDirectory. All three flips are red now. Co-Authored-By: Claude Opus 5.5 --- .../internal/api/promote_redirect_test.go | 27 ++++++++++++++ ingestion/internal/brainfs/brainfs_test.go | 36 +++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/ingestion/internal/api/promote_redirect_test.go b/ingestion/internal/api/promote_redirect_test.go index 49a21f2..4e91c1e 100644 --- a/ingestion/internal/api/promote_redirect_test.go +++ b/ingestion/internal/api/promote_redirect_test.go @@ -58,3 +58,30 @@ func TestStampProvenanceFileRefusesANoteBehindASymlinkedDirectory(t *testing.T) got, _ = os.ReadFile(real) assert.Contains(t, string(got), "written_by: x") } + +// The same through an in-brain symlinked wing and raw/rejected, which +// os.Root alone would follow. +func TestPromoteAndRejectRefuseAnInBrainSymlinkedDestinationDirectory(t *testing.T) { + brain := t.TempDir() + raw := filepath.Join(brain, "raw") + require.NoError(t, os.MkdirAll(raw, 0o755)) + require.NoError(t, os.WriteFile(filepath.Join(raw, "2026-10-05-n.md"), []byte("---\ntitle: n\n---\nbody\n"), 0o644)) + target := filepath.Join(brain, "archive") + require.NoError(t, os.MkdirAll(target, 0o755)) + require.NoError(t, os.MkdirAll(filepath.Join(brain, "wiki"), 0o755)) + require.NoError(t, os.Symlink(filepath.Join("..", "archive"), filepath.Join(brain, "wiki", "lw"))) + require.NoError(t, os.Symlink(filepath.Join("..", "archive"), filepath.Join(raw, "rejected"))) + + _, err := api.PromoteNote(brain, api.PromoteOptions{Filename: "2026-10-05-n.md", Wing: "lw", Hall: "facts"}) + assert.Error(t, err) + _, err = api.RejectNote(brain, api.RejectOptions{Filename: "2026-10-05-n.md"}) + assert.Error(t, err) + ents, _ := os.ReadDir(target) + assert.Empty(t, ents, "a note was written at the in-brain link's target") + _, err = os.Stat(filepath.Join(raw, "2026-10-05-n.md")) + assert.NoError(t, err, "the raw source is kept") + + require.NoError(t, os.Remove(filepath.Join(raw, "rejected"))) + _, err = api.RejectNote(brain, api.RejectOptions{Filename: "2026-10-05-n.md"}) + require.NoError(t, err, "positive control: reject into a real raw/rejected") +} diff --git a/ingestion/internal/brainfs/brainfs_test.go b/ingestion/internal/brainfs/brainfs_test.go index 11b8b7d..0f5570b 100644 --- a/ingestion/internal/brainfs/brainfs_test.go +++ b/ingestion/internal/brainfs/brainfs_test.go @@ -493,3 +493,39 @@ func TestRemoveRefusesAPathBehindASymlinkedDirectoryAndRemovesOnlyTheLink(t *tes _, err = os.Stat(filepath.Join(dir, "wiki", "n.md")) assert.True(t, os.IsNotExist(err)) } + +// CreateRegular is the only write path for promote and reject: it creates +// missing parents through the root, refuses an in-brain symlinked parent and +// an unclean path, and never replaces anything already there (fs.ErrExist, +// content unchanged), including a dangling link. +func TestCreateRegularCreatesOnlyNewFilesThroughRealDirectories(t *testing.T) { + dir := t.TempDir() + require.NoError(t, os.MkdirAll(filepath.Join(dir, "raw", "keep"), 0o755)) + require.NoError(t, os.MkdirAll(filepath.Join(dir, "wiki"), 0o755)) + require.NoError(t, os.Symlink(filepath.Join("..", "raw"), filepath.Join(dir, "wiki", "inwing"))) + require.NoError(t, os.WriteFile(filepath.Join(dir, "raw", "v.md"), []byte("untouched"), 0o644)) + require.NoError(t, os.Symlink(filepath.Join("raw", "keep"), filepath.Join(dir, "indir"))) + require.NoError(t, os.WriteFile(filepath.Join(dir, "wiki", "exists.md"), []byte("original"), 0o644)) + require.NoError(t, os.Symlink("nowhere.md", filepath.Join(dir, "wiki", "dangling.md"))) + b, err := Open(dir) + require.NoError(t, err) + defer func() { _ = b.Close() }() + + assert.ErrorIs(t, b.CreateRegular("wiki/inwing/facts/n.md", []byte("x")), ErrNotRegular) + _, err = os.Stat(filepath.Join(dir, "raw", "facts")) + assert.True(t, os.IsNotExist(err), "nothing created through the in-brain link") + assert.ErrorIs(t, b.CreateRegular("indir/../v.md", []byte("x")), ErrNotRegular) + got, _ := os.ReadFile(filepath.Join(dir, "raw", "v.md")) + assert.Equal(t, "untouched", string(got)) + + assert.ErrorIs(t, b.CreateRegular("wiki/exists.md", []byte("x")), fs.ErrExist) + got, _ = os.ReadFile(filepath.Join(dir, "wiki", "exists.md")) + assert.Equal(t, "original", string(got)) + assert.ErrorIs(t, b.CreateRegular("wiki/dangling.md", []byte("x")), fs.ErrExist) + _, err = os.Stat(filepath.Join(dir, "wiki", "nowhere.md")) + assert.True(t, os.IsNotExist(err), "nothing created at the dangling link's target") + + require.NoError(t, b.CreateRegular("wiki/new/facts/n.md", []byte("one")), "positive control: create with missing parents") + got, _ = os.ReadFile(filepath.Join(dir, "wiki", "new", "facts", "n.md")) + assert.Equal(t, "one", string(got)) +}