Artifact c30799a77b40e43b2598c8350f6fec1cad67b6ca4ef8c2515f431a6889eaa7a6:
- File
internal/manifest/sparse_receive_proof_test.go
— part of check-in
[b38bf23f79]
at
2026-10-20 21:38:53
on branch feat/submanifest-reader
— perf(manifest): bound repair work by the linked batch (#455)
Propagate tags and apply scheduled leaf rechecks before each link transaction commits. Preserve sparse metadata repair, pretagged merge-parent rechecks, and rollback-safe retries. Tracked in #432. (user: [email protected], size: 4794) [annotate] [blame] [check-ins using] [more...]
package manifest import ( "context" "errors" "fmt" "testing" "time" "github.com/danmestas/go-libfossil/db" "github.com/danmestas/go-libfossil/internal/blob" "github.com/danmestas/go-libfossil/internal/content" "github.com/danmestas/go-libfossil/internal/deck" ) // Reusing one receive linker across transactions must not preserve an Outside // proof after a newly received artifact makes the omitted node structural. func TestSparseReceiveProofRefreshesAfterRawAliasArrival(t *testing.T) { f, rid, outside, _ := partialMetadataFixture(t) linker, err := NewReceiveLinker(f.r) if err != nil { t.Fatal(err) } data, err := content.Expand(f.r.DB(), rid) if err != nil { t.Fatal(err) } root, err := deck.Parse(data) if err != nil { t.Fatal(err) } receiveSparseProofDeck(t, f, linker, root) if _, err := linker.Finalize(context.Background()); err != nil { t.Fatal(err) } assertSparseRows(t, f, int64(rid), 1, 0, 1) if linker.state.guard.coneReferences != nil { t.Fatal("raw classification proof escaped its batch transaction") } receiveSparseProofDeck(t, f, linker, &deck.Deck{ D: time.Date(2026, 1, 3, 0, 0, 0, 0, time.UTC), U: deck.User("u"), T: []deck.TagCard{{Type: deck.TagSingleton, Name: "sym-required", UUID: outside}}, }) root.C = "later check-in with newly required gap" root.D = root.D.Add(time.Hour) child := receiveSparseProofDeck(t, f, linker, root) if _, err := linker.Finalize(context.Background()); err != nil { t.Fatal(err) } var n int if err := f.r.DB().QueryRow("SELECT count(*) FROM event WHERE objid=?", child).Scan(&n); err != nil { t.Fatal(err) } if n != 0 { t.Fatalf("newly required gap published %d metadata rows using stale proof", n) } } func TestSparseReceiveProofRecognizesNewOutsideNode(t *testing.T) { f, rid, _, _ := partialMetadataFixture(t) linker, err := NewReceiveLinker(f.r) if err != nil { t.Fatal(err) } if _, err := linker.Finalize(context.Background()); err != nil { t.Fatal(err) } data, err := content.Expand(f.r.DB(), rid) if err != nil { t.Fatal(err) } root, err := deck.Parse(data) if err != nil { t.Fatal(err) } root.C = "new outside node after first finalize" root.S[1].UUID = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" child := receiveSparseProofDeck(t, f, linker, root) if _, err := linker.Finalize(context.Background()); err != nil { t.Fatal(err) } assertSparseRows(t, f, child, 1, 0, 1) if linker.state.guard.coneReferences != nil { t.Fatal("finalize retained transaction-scoped raw proof") } } func TestSparseProofReusedWithinUnchangedTransaction(t *testing.T) { f, rid, _, _ := partialMetadataFixture(t) data, err := content.Expand(f.r.DB(), rid) if err != nil { t.Fatal(err) } d, err := deck.Parse(data) if err != nil { t.Fatal(err) } st := newLinkState(receiveCacheBytes) if err := f.r.WithTx(func(tx *db.Tx) error { ready, err := crosslinkPartialCheckin(context.Background(), tx, rid, d, st.guard, st.sched) if err != nil { return err } if !ready || st.guard.coneReferences == nil { t.Fatal("partial check-in did not load transaction proof") } proof := st.guard.coneReferences ready, err = crosslinkPartialCheckin(context.Background(), tx, rid, d, st.guard, st.sched) if !ready || st.guard.coneReferences != proof { t.Error("unchanged transaction did not reuse its proof") } return err }); err != nil { t.Fatal(err) } } func TestSparseReceiveProofClearedAfterBatchRollback(t *testing.T) { f, rid, _, _ := partialMetadataFixture(t) for i := 0; i < 768; i++ { f.storeBytes([]byte(fmt.Sprintf("ordinary receive payload %d", i))) } linker, err := NewReceiveLinker(f.r) if err != nil { t.Fatal(err) } if _, err := linker.Finalize(newPollCancelCtx(2)); !errors.Is(err, context.Canceled) { t.Fatalf("interrupted finalize = %v, want cancellation", err) } if linker.state.guard.coneReferences != nil { t.Fatal("rolled-back batch retained its raw proof") } var n int if err := f.r.DB().QueryRow("SELECT count(*) FROM event WHERE objid=?", rid).Scan(&n); err != nil { t.Fatal(err) } if n != 0 { t.Fatalf("interrupted finalize committed %d partial events", n) } if _, err := linker.Finalize(context.Background()); err != nil { t.Fatal(err) } assertSparseRows(t, f, int64(rid), 1, 0, 1) } func receiveSparseProofDeck(t *testing.T, f *treeFixture, linker *ReceiveLinker, d *deck.Deck) int64 { t.Helper() data, err := d.Marshal() if err != nil { t.Fatal(err) } var result int64 if err := linker.WithTx(f.r, func(tx *db.Tx) error { rid, uuid, err := blob.Store(tx, data) if err != nil { return err } result = int64(rid) return linker.LinkStored(context.Background(), tx, rid, uuid, data) }); err != nil { t.Fatal(err) } return result }