Artifact dc21dfede26b96a8bec97225ac885b037ad44d8579ef33ecc54fe457beba06b0:
- File
internal/content/chain_bound_test.go
— part of check-in
[39f9ea4d8a]
at
2026-07-27 17:24:05
on branch trunk
— test(content): build the chain-bound fixture in one transaction (#182)
TestChainBoundBitesAtSameLength inserted its fixture a statement at a time: one blob row per chain node and one delta row per edge, across two arms sized maxDeltaChainDepth and maxDeltaChainDepth+1. At the current constant that is ~65k statements, each in its own implicit transaction and each paying a commit.
The chain is incidental setup; the subject of the test is the bound. But the setup cost dominated the runtime and was sensitive to how loaded the machine was, so on a contended runner it consumed the package's 120s budget and failed a PR that touched only CI YAML.
Wrap both loops in a single db.WithTx so the chain commits once. This follows buildBackwardChain in chain_depth_bench_test.go, which already builds its chain this way in the same package.
The assertions are untouched, byte for byte: the two walks must still agree at maxDeltaChainDepth and disagree one past it. Verified by mutation -- widening one walk's loop bound by a single node still fails the test with the same diagnostic it was written to produce.
Measured on this machine, three runs each, whole-package wall clock:
modernc before 19.7s / 25.0s / 7.1s after 1.19s / 1.36s / 0.80s ncruces before 3.5s / 10.0s / 7.5s after 1.27s / 1.59s / 1.13s
The spread collapsing matters more than the median: the old fixture's cost tracked machine load, which is what made it a timeout risk rather than merely slow.
Refs #179 (user: [email protected], size: 2545) [annotate] [blame] [check-ins using]
package content import ( "fmt" "testing" "github.com/danmestas/go-libfossil/db" libfossil "github.com/danmestas/go-libfossil/internal/fsltype" _ "github.com/danmestas/go-libfossil/internal/testdriver" ) // maxDeltaChainDepth's doc says both read-path walks stop after visiting that // many nodes. They reached the bound a node apart until the loop in // walkDeltaChain was rewritten to count nodes rather than iterations, which // meant a chain of exactly maxDeltaChainDepth+1 was unavailable to one walk // and complete to the other. Nothing else pins the two together: each has its // own loop, and a future edit to either can reintroduce the skew silently. func TestChainBoundBitesAtSameLength(t *testing.T) { for _, n := range []int{maxDeltaChainDepth, maxDeltaChainDepth + 1} { d := setupTestDB(t) // Build the whole chain under one commit. This fixture is incidental // to what the test asserts, but at maxDeltaChainDepth it is ~65k rows // across the two arms; a commit per row makes the runtime durability- // bound and pushed the package past its CI timeout. rids := make([]libfossil.FslID, n) if err := d.WithTx(func(tx *db.Tx) error { for i := 0; i < n; i++ { res, err := tx.Exec( "INSERT INTO blob(uuid, size, content, rcvid) VALUES(printf('%040d', ?), 42, x'00', 1)", i) if err != nil { return fmt.Errorf("insert blob %d: %w", i, err) } id, err := res.LastInsertId() if err != nil { return fmt.Errorf("LastInsertId for blob %d: %w", i, err) } rids[i] = libfossil.FslID(id) } // An acyclic chain grounded at its far end, so only the bound can // decide the outcome. for i := 0; i < n-1; i++ { if _, err := tx.Exec("INSERT INTO delta(rid, srcid) VALUES(?, ?)", rids[i], rids[i+1]); err != nil { return fmt.Errorf("insert delta %d: %w", i, err) } } return nil }); err != nil { t.Fatalf("build chain of %d nodes: %v", n, err) } available := IsAvailable(d, rids[0]) _, _, err := walkDeltaChain(d, rids[0], nil) walked := err == nil if available != walked { t.Errorf("chain of %d nodes: IsAvailable=%v but walkDeltaChain succeeded=%v; "+ "the two walks must reach maxDeltaChainDepth (%d) at the same length", n, available, walked, maxDeltaChainDepth) } if n == maxDeltaChainDepth && !available { t.Errorf("chain of exactly maxDeltaChainDepth (%d) nodes was rejected", n) } if n == maxDeltaChainDepth+1 && available { t.Errorf("chain of maxDeltaChainDepth+1 (%d) nodes was accepted", n) } } }