Skip to content

test(coverage): cover env_backup.c, env_config.c, and deepen db_rec.c recovery branches - #80

Closed
gburd wants to merge 3 commits into
masterfrom
agent/backup-config
Closed

test(coverage): cover env_backup.c, env_config.c, and deepen db_rec.c recovery branches#80
gburd wants to merge 3 commits into
masterfrom
agent/backup-config

Conversation

@gburd

@gburd gburd commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

Summary

Raises coverage of three cold libdb areas, all within the bounded
run_coverage.sh subset. No engine code changed; only tests + wiring.

File Before (subset) After (subset)
env/env_backup.c 0.0% line / 0.0% br 96.7% / 81.8%
env/env_config.c 3.2% line / 1.2% br 71.8% / 61.4%
db/db_rec.c 18.0% line / 13.2% br 27.1% / 18.0%
db/db_backup.c (bonus) callback path cold 43.0% / 29.6%

(env_config baseline in the full run was 27.0%/17.7%; the subset baseline is
lower because the subset ran no DB_CONFIG-heavy test. env007 now beats both.)

What and why

env_backup.c is only the four backup config setters/getters and the
callback setter/getter. backup.tcl drives hot backup through the
db_hotbackup utility, which calls DB_ENV->backup() with a NULL
backup_handle, so none of env_backup.c ran and the
backup->open/write/close callback branches of db/db_backup.c stayed cold.
New standalone driver test/backup/backup_direct.c calls those public
entry points directly (all four config enums, WRITE_DIRECT on+off, the
getters-before-alloc EINVAL branches, set/get_backup_callbacks), then runs
DB_ENV->backup()/dbbackup() with write callbacks installed.

env_config.c (__env_read_db_config + __config_scan/__config_parse)
was cold in the subset because no subset test wrote a many-directive
DB_CONFIG. The existing, comprehensive env007 already writes a DB_CONFIG
exercising set_cachesize/set_lg_*/set_lk_detect/set_flags/
add_data_dir/set_verbose/mutex_set_*/set_memory_*/… and confirms each
via getters. It was registered but never in the subset -- now wired into the
default COV_TESTS. (No new config001.tcl needed: env007 already does
exactly the requested many-directive parse + getter verification.)

db/db_rec.c branch coverage: __db_merge_recover, __db_pgno_recover,
__db_pg_trunc_recover (~330 lines) fire only when btree compaction /
page-truncation records are replayed, and no recd0NN test runs compaction
under recovery, so they were completely cold. New driver
test/db/recd_compact.c fills+sparsifies a small-page btree, runs
DB->compact(DB_FREE_SPACE) (logging merge/pgno/pg_trunc records), then
re-opens under DB_RECOVER_FATAL. Also added recd002:btree (split
recovery) and recd016:btree (catastrophic recovery) to COV_TESTS.

Both C drivers follow the existing XA/upgrade-driver pattern: self-clean their
home dir, run under a hard SIGALRM + timeout guard, so they cannot hang.
Gated behind a new COV_BACKUP=1 (default on).

Bounded-cost note

Deliberately did not add recd003/recd004/recd011/recd002:hash:
each is 7-8 min under coverage instrumentation for a <1% marginal db_rec gain.
The chosen set (recd002 ~65s, recd016 ~14s, recd_compact ~30s, env007 ~24s,
backup_direct ~5s) is where the ROI is.

Validation

Built with --coverage in the nix dev shell; every added test/driver run and
confirmed PASS under a timeout (drivers verified reliable on repeat runs).
Deltas above are measured before->after via lcov + rank_coverage.py.

Notes

  • No engine bug surfaced by the backup or compaction-recovery paths.
  • No coverage artifacts committed (build_unix/** is gitignored).

gburd added 3 commits July 29, 2026 08:38
The Tcl backup.tcl test drives hot backup only through the db_hotbackup
utility, which calls DB_ENV->backup() with a NULL backup_handle -- so
env/env_backup.c (the four backup config setters/getters and the backup
callback setter/getter) was never reached (0% line/branch), and the
backup->open/write/close callback branches of db/db_backup.c stayed cold.

Add test/backup/backup_direct.c (same standalone-driver shape as
test/xa/xa_direct.c): it calls set/get_backup_config for all four config
enums (READ_COUNT/READ_SLEEP/SIZE/WRITE_DIRECT, the last on and off to hit
both F_SET and F_CLR), the getters-before-alloc EINVAL branches, and
set/get_backup_callbacks, then runs DB_ENV->backup()/dbbackup() with write
callbacks installed so the callback copy path in db_backup.c executes.
Self-cleans its home dir and runs under a hard SIGALRM + timeout guard.

Lift (coverage subset): env_backup.c 0%->96.7% line / 0%->81.8% branch;
db_backup.c callback path 43.0% line / 29.6% branch.
Three recovery record handlers in db/db_rec.c -- __db_merge_recover,
__db_pgno_recover, __db_pg_trunc_recover (~330 lines) -- fire only when
btree compaction / page-truncation log records are replayed.  No recd0NN
test runs compaction under recovery, so all three were completely cold.

Add test/db/recd_compact.c: it fills a small-page btree, deletes a large
contiguous range to leave sparse/empty pages, runs DB->compact(DB_FREE_SPACE)
in a transaction (logging __db_merge / __db_pgno / __db_pg_trunc records),
then re-opens the environment under DB_RECOVER_FATAL so catastrophic recovery
replays the whole log from the start, driving the redo/forward-roll branches
of those handlers.  It verifies the database still opens and reads back after
recovery.  Same self-clean + hard-timeout shape as the XA/upgrade drivers.

Lift (coverage subset, combined with recd002:btree + recd016): db_rec.c
18%->~27% line, ~13%->~18% branch; merge/pgno/pg_trunc/relink no longer cold.
…vers into subset

Add to the default COV_TESTS: env007 (comprehensive DB_CONFIG parser test --
writes a DB_CONFIG with many directives and confirms values via getters,
exercising __env_read_db_config + __config_scan; was registered but never in
the subset), recd002:btree (split recovery) and recd016:btree (catastrophic
recovery) for db_rec.c branch coverage.

Add a COV_BACKUP block (default on, same gating shape as COV_XA_UPG) that runs
the two new standalone drivers: test/backup/run_backup_direct.sh and
test/db/run_recd_compact.sh.  Both self-clean and run under a hard timeout.

Document the new surface in README.md (COV_BACKUP table row + section).

Lift (coverage subset): env_config.c 3.2%->71.8% line / 1.2%->61.4% branch
(via env007); env_backup.c 0%->96.7%/81.8%; db_rec.c 18%->27.1% line /
13.2%->18.0% branch.
@github-actions

Copy link
Copy Markdown

Coccinelle convention checks

No new violations. ✅

Resolved since baseline (2) -- update dist/cocci/baseline.txt to lock these in.
rule_mutex_unbalanced|MUTEX_UNBALANCED|src/crypto/mersenne/mt19937db.c|return (ret);
rule_mutex_unbalanced|MUTEX_UNBALANCED|src/mp/mp_register.c|return (ret);

@github-actions

Copy link
Copy Markdown

ABI diff vs v5.3.31 (libabigail — authoritative)

Removed exported symbols (nm -D, _NNNN version suffix normalized)

None.


Advisory: libabigail/nm is the authoritative binary-ABI check; Coccinelle is complementary source-level early warning. See dist/cocci/README.md.

@gburd

gburd commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator Author

Superseded by rebased branch onto master (#78/#81); 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