refactor(test): simplify GlobalsGuard and TempDir, and test the harness - #122
Conversation
Make Globals::VERSION and Globals::PROGRAM static. They are compile-time constants identical in every instance, so they are not per-object state; as non-static const members they deleted Globals' copy-assignment operator. GlobalsGuard's destructor can now restore global state with one whole-struct assignment instead of enumerating 33 fields, which a newly added Globals field could silently escape and leak into an unrelated test file. Every existing use goes through .data(), unchanged on a static const std::string. Drop the std::vector<char> copy in TempDir: C++17's non-const std::string::data() lets mkdtemp mutate the template in place. Add tests/unit/src/test_harness.cpp, covering TempDir creation, uniqueness, recursive removal and path joining; GlobalsGuard scalar/container restoration and verbosity silencing; write_tmp_vcf output parsing under htslib; and the make_fasta, make_ctgVariants and alloc_reach_offs builders. A defect in the scaffolding now fails in its own file rather than somebody else's. Closes #119
Closes #128. add_var() defaults every parameter after phase_set, so make_ctgVariants() passing var.supercluster in the eleventh position bound it to rec_idx once #116 inserted the three provenance parameters mid-signature, and supercluster silently took its -1 default. Both are int, so it compiled clean under -Wall -Wextra. var_desc gains rec_idx, alt_idx and ploidy fields (defaults -1, -1, 0) and all four are now passed explicitly, so tests can exercise the new per-variant vectors. The new fields are appended rather than inserted, so positional brace-initialization of var_desc keeps binding to the same members. MakeCtgVariants.ProvenanceFieldsReachTheirOwnVectors gives each of the five trailing fields a distinct value, so a future positional shift fails a test instead of passing silently. Also corrects var_desc::qual's doc comment, which claimed add_var() clamps it to g.max_qual: that holds for var_qual only, not gt_qual (#135). No behavior change in src/variant.cpp.
3ecbb74 to
faa9207
Compare
|
Claude Opus 5 🤖: Rebased onto RebaseNo conflicts. #128 —
|
Note
Authorship: the content below was drafted by Claude Opus 5 (an AI coding agent) and
filed via
ghunder @TimD1-bot, a bot account operated by @TimD1. It reflects theagent's analysis, not a statement authored by @TimD1.
Closes #119. Part of #45; follow-up to #118, which landed the unit-test harness.
Three cleanups to the unit-test scaffolding, done before the per-module test PRs build much on top of it.
1.
Globals::VERSION/PROGRAMare now staticVERSIONandPROGRAMare compile-time constants identical in everyGlobalsinstance, so they were never per-object state — but as non-staticconstmembers they deleted the implicitly-generated copy-assignment operator. Making themstatic const std::string(declared insrc/globals.h, defined insrc/globals.cpp) restores copy-assignment.Every existing use goes through
.data(), which is unchanged on astatic const std::string, so there are no call-site edits:src/globals.cpp(print_version,print_usage),src/print.cpp(write_params), and theWARN/INFO/ERRORmacros insrc/defs.h.2.
GlobalsGuardno longer enumerates fieldsWith
Globalscopy-assignable, the destructor collapses from a 33-field assignment list tog = this->saved;. The public interface is unchanged —GlobalsGuard guard;at the top of a test behaves exactly as before.The point is that a newly added
Globalsfield can no longer silently escape restoration. Previously it would leak into the next test, and because gtest orders suites across translation units by link order, the resulting failure could surface in an unrelated test file.3.
TempDirdrops thevector<char>copymkdtempmutates its argument, which used to require copying the template through astd::vector<char>. Non-conststd::string::data()is available in C++17 and the build already uses-std=c++17, somkdtemp(tmpl.data())works directly. The_XXXXXXsuffix is untouched —mkdtemprequires exactly six trailingXcharacters.4.
tests/unit/src/test_harness.cppThe scaffolding itself had no committed test, so a defect in it surfaced inside somebody else's test file. Eleven new cases, one gtest suite per helper:
TempDirCreatesWritableTempDirDistinctPathsTempDirRemovesRecursivelyTempDirPathJoinpath(name)ispath() + "/" + name, with no doubled separatorGlobalsGuardRestoresScalarg.sv_thresholdis restored at scope exitGlobalsGuardRestoresContainerg.filters, which a field-by-field restore is likeliest to missGlobalsGuardSilencesVerbosityg.verbosity == 0inside the guard's scopeWriteTmpVcfParsesUnderHtslibparse_variants, the helper's entire contractMakeFastaSequenceReadableMakeCtgVariantsRoundtripAllocReachOffsSizeAndInitMATS*(max(x,o+e)+1)*(qlen+tlen-1)entries, all-2test_harness.ois added toOBJSintests/unit/build/Makefile; the existing pattern rule needs no change.Verification
cd tests/unit/build && make— builds clean (the one warning,dist.cpp:1070unused parameterthread2, predates this branch)../test_vcfdist—22 tests from 9 test suites ran./[ PASSED ] 22 tests., up from 11.cd src && make clean && make— linksvcfdist;./vcfdist --versionprintsvcfdist v3.0.0-b0, exercising both static members through.data().cd src && doxygen Doxyfile 2>&1 | grep -i warning— silent.cd tests && pytest—3 passed.