Skip to content

test(coverage): wire recd group into COV_RECD block for *_rec.c branch coverage - #87

Closed
gburd wants to merge 1 commit into
masterfrom
agent/recd-branches
Closed

test(coverage): wire recd group into COV_RECD block for *_rec.c branch coverage#87
gburd wants to merge 1 commit into
masterfrom
agent/recd-branches

Conversation

@gburd

@gburd gburd commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

What

Adds a COV_RECD block (default on) to test/coverage/run_coverage.sh that
drives the recd recovery-record test group driver-per-test, raising
BRANCH coverage of the four *_rec.c recovery-handler files — the biggest
remaining cold branch surface in the tree.

The __xxx_recover handlers each have redo / undo / abort / do-nothing
branches. op_recover (testutils.tcl) crashes the env at every log-record
boundary and replays recovery forward (redo) and backward (undo/abort)
exactly the cold branches. The subset previously ran only recd001/002/016
on btree, so the hash and queue handlers were at 0% and most
btree/db redo/undo branches were cold.

Results (recd-driven branch %, gcc --coverage, -O0)

file before after
db/db_rec.c 14.6% (467) 16.4% (523)
btree/bt_rec.c 12.3% (290) 21.6% (512)
hash/hash_rec.c 0% (0) 24.2% (501)
qam/qam_rec.c 0% (0) 45.5% (261)

Validated end-to-end via run_coverage.sh (COV_RECD=1, EXITCODE=0): all
26 recd runs PASS, each well inside its 300s per-test timeout (slowest is
recd004 at ~84s). Whole block ~10 min.

The curated set (coverage-per-minute)

Driver-per-test (each in its own tclsh — several recd tests use conflicting
globals, e.g. recd006 sets kvals as a scalar while recd010 uses it as an
array, so they cannot share one interpreter; each also spawns recdscript.tcl
subprocesses that need orphan cleanup):

  • recd002 (splits) × btree/hash/queue/recno
  • recd005 (file-id reuse) × btree/hash/queue/recno
  • recd006 (nested txn) × btree/hash, recd013 (cursor adjust) × btree/hash
  • recd004 big-key→internal, recd008 deep/many-child, recd009 recnum,
    recd010 off-page-dup splits, recd014 queueext (the only thing that
    reaches __qam_delext_recover), recd016 checksum, recd017 crypto,
    recd018 checkpoint/commit, recd019 txn-id wrap, recd020 dirs,
    recd022 aborted-prepared page-alloc, recd023 reverse split,
    recd024 streaming partial-put overflow, recd025 TXN_BULK.

recd001/002/016 removed from COV_TESTS (superseded by the driver-per-test
block, which is more robust than the shared-tclsh loop).

Deliberately excluded (too slow for the marginal branches, -O0)

  • recd001 (~6.5 min/method): the rest of the set already covers its per-op
    redo/undo branches — dropping it entirely moved the totals by ~1 branch.
  • recd003 (~7.3 min, dup): does not unlock the still-cold
    __bam_root/irep/rcuradj or __db_ovref handlers (they need scenarios no
    bounded recd test reaches), so its 7 min buy only a few adjacent branches.
  • recd015 (~4.6 min): prepared-txn branches already hit by recd002/recd022.
  • recd007 (~4.3 min): db_rec create/rename branches already covered by the
    recd_compact + upgrade drivers already in the subset.

Recovery correctness

No bug surfaced — all forward+backward replays across every access method
verified clean (that is the good outcome; a redo/undo bug would have failed
op_recover's post-recovery verify).

Follow-up (not in this PR)

Still-cold handlers that need scenarios no bounded recd test reaches:
__bam_root_recover, __bam_irep_recover, __bam_rcuradj_recover,
__db_ovref_recover, __db_cksum_recover. These would need a targeted C
recovery driver (like the existing recd_compact one) rather than a Tcl test.

The per-operation recovery handlers (__xxx_recover: redo/undo/abort/
do-nothing branches) in db/db_rec.c (3189 br), hash/hash_rec.c (2069),
btree/bt_rec.c (2366) and qam/qam_rec.c (574) were the biggest cold
BRANCH surface. The subset ran only recd001/002/016 on btree, leaving
the hash and queue handlers at 0% and most btree/db redo/undo branches
cold.

Add a COV_RECD block (default on) that drives the recd group
driver-per-test (each in its own tclsh, per-test timeout, recdscript.tcl
orphan cleanup) -- recd tests use conflicting globals (recd006 kvals
scalar vs recd010 array) so they cannot share one interpreter. The set
is curated for coverage-per-minute across every access method each test
supports; whole block ~10 min, every test PASSes well inside a 300s
timeout.

Recd-driven branch % (measured, gcc --coverage, -O0):
  db/db_rec.c    14.6 -> 16.4
  btree/bt_rec.c 12.3 -> 21.6
  hash/hash_rec.c 0   -> 24.2
  qam/qam_rec.c   0   -> 45.5

recd001/002/016 removed from COV_TESTS (superseded by the driver-per-test
block; recd001 was 6.5 min and added ~1 branch over the rest). recd003/
007/015 deliberately excluded: too slow under -O0 for the marginal
branches they add (recd003 does not unlock the still-cold __bam_root/
irep/rcuradj or __db_ovref handlers). No recovery-correctness bug
surfaced: all forward+backward replays verified clean.
@gburd

gburd commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator Author

Superseded by coverage/recd-branches-final (rebased onto master with #84/#88; COV_RECD block preserved, recd001/002/016 correctly removed from COV_TESTS in favor of the driver-per-test block). Reopening.

@gburd gburd closed this Jul 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant