Checker struct.
Checker into a shared module was proposed and rejected -
a component that owns its own harness can be read and built alone.
Recorder, which demonstrates that the class template binds to any Output.Cpp_TextFinder_Entry is: a binary whose behavior is its startup sequence, its
exit codes, and its stream routing, none of which can be exercised without running it.
| Suite | Assertions | What it covers |
|---|---|---|
| Cmdline | 50 | Every default, both introducers, boolean case folding, last-occurrence-wins, /P accumulation, the five /p normalization rules, all six parse diagnostics, and the rendered help and option listings |
| Dirnav | 39 | Skip-list pruning including the root carve-out, /p selection with the dot-file rule, /s false, all four block forms, the /h gating, cannot open, LF, CRLF and bare CR splitting, BOM consumption, and the 10 MB limit at and just above the boundary |
| Output | 9 | The single LF terminator, the absence of CR, unchanged pass-through, and dispatch through Output& |
| Integration | 53 | The executable end to end: exit codes, stream routing, /H, the bare command line, the /v ordering, LF-only output, and all seven usage diagnostics |
*_UnitTest.ixx exporting one entry point, with a
*_TestDriver.cpp that runs it and maps the failure count to an exit status.
Recorder : public Output, which
exercises the same constraint the real sink satisfies and so demonstrates that the class
template binds to any Output. The Output suite redirects
std::cout's stream buffer to inspect the bytes written, which is the only way
to assert that no CR reaches the stream.
Checker struct.
struct Checker {
std::ostream& log;
int failures{0};
int total{0};
void expect(bool ok, std::string_view name) { record(ok, name); }
void equal(const std::string& actual, const std::string& expected, std::string_view name) {
const bool ok = actual == expected;
record(ok, name);
if (ok) return;
log << " expected: [" << expected << "]\n";
log << " actual: [" << actual << "]\n";
}
void record(bool ok, std::string_view name) {
++total;
if (!ok) ++failures;
log << (ok ? " PASS " : " FAIL ") << name << "\n";
}
};
equal follows a failure with the expected and actual strings in brackets,
which is what makes a whitespace difference visible. Two of the suites add a
visible helper that renders \n and \r as escapes,
since the CRLF failures of the first run looked identical to their expected text.
runCmdlineUnitTests, runDirnavUnitTests,
runOutputUnitTests - which keeps the modules free of a shared result type that
would collide when several are imported together. The driver is four lines of substance.
// Cpp_TextFinder_Cmdline_TestDriver.cpp - runs the Cpp_TextFinder_Cmdline unit tests
import std;
import Cpp_TextFinder_Cmdline_UnitTest;
int main() {
const int failures = runCmdlineUnitTests(std::cout);
std::cout << (failures == 0 ? "PASS\n" : "FAIL\n");
return failures == 0 ? 0 : 1;
}
Checker is duplicated across the four test modules. Factoring it into a
shared support module was proposed and would remove about seventy lines; the user rejected
it, asking that the checker stay duplicated per part, so the shared module was never
written. A component that owns its own harness can be read and built alone, which is worth
seventy lines in a project whose point is that each part is specified separately.
std::system with stdout
and stderr redirected to files read back in binary. Reading back in binary is what lets it
assert the LF rule at all, since a text-mode read would translate the bytes it is checking.
CMake passes the executable's path in through the
$<TARGET_FILE:Cpp_TextFinder> generator expression, and a command-line
argument overrides it, so a binary built elsewhere can be tested.
=== <name> === banner and a
--- <name>: exit status N (PASS|FAIL) --- line, then prints a summary and
returns the number of failed suites as its own exit code.
| Runner | What it does |
|---|---|
run_unit_tests.bat |
Runs the Cmdline, Dirnav, and Output drivers in turn |
run_integration_tests.bat |
Runs the integration driver; an argument overrides the executable under test |
run_demo.bat |
Runs the demonstration driver; two arguments override the executable and the demo root |
%~dp0, so any of the
three runs from any working directory. A suite that was never built is reported as
not built: with its path and counted as a failure rather than skipped
silently, which is the difference between a green run and a run that tested nothing. That
failure path was verified by pointing the integration script at a nonexistent executable.
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release when
build\CMakeCache.txt is absent, and cmake --build build in
either case. Deleting the whole build directory and running
run_unit_tests.bat therefore configures, builds, and runs the three suites
in one command.<io.h>, and a plain shell has no
include path for it - which is the failure the build record reports from its first
attempt, io.h: no include path set. A Developer Command Prompt already
carries what is needed. Otherwise the runner asks vswhere for the latest
installation with the C++ toolset and calls its vcvars64.bat, inside its
own setlocal so the change reaches nothing else. It prints the
installation path it used, and it says what to do when there is no
cl and no vswhere rather than failing with a compiler error a
reader has to interpret.run_unit_tests.bat stopped between its last suite and
its summary, and run_integration_tests.bat stopped between running the driver
and reporting its status. Both now hold once, last, through one :hold
subroutine. Setting TEXTFINDER_NO_PAUSE to a non-empty value suppresses it,
which is how the captures in Sections 4 and 5 are taken.
pause leaves
ERRORLEVEL untouched, which is worth stating because the opposite is widely
assumed and the integration runner's old placement would have corrupted its reported status
if it were true. Each runner returns its failure count explicitly in any case.
add_test, so
ctest runs them as a set. One environment note from the record is worth
keeping: ctest on this machine's PATH resolves to something that runs
cargo test, so CMake's own ctest.exe has to be called by full
path.
Cpp_TextFinder_Cmdline unit tests
PASS empty command line parses
PASS default /P is .
PASS default /p is empty
PASS default /r is .
PASS default /s is true
PASS default /h is true
PASS default /v is false
PASS default /H is false
PASS default /n is false
PASS default /L is false
PASS introducers / and - are equivalent
PASS boolean values fold case
PASS True is accepted
PASS last occurrence wins for /r
PASS /h and /H are distinct switches
PASS an argument beginning with an introducer is taken verbatim
PASS first /P replaces the default
PASS /P accumulates in argv order
PASS items are trimmed
PASS one leading dot is stripped
PASS empty items are discarded
PASS an all-whitespace list is empty
PASS duplicates are retained
PASS not a switch
PASS unrecognized switch
PASS over-long switch token
PASS bare introducer
PASS missing argument
PASS invalid boolean
PASS empty root path
PASS empty expression
PASS the introducer is reproduced as typed
PASS parsing stops at the first violation
PASS helpText begins with usageLine
PASS usage names the executable
PASS usageLine ends with a newline
PASS helpText ends with a newline
PASS help lists /P
PASS help lists /p
PASS help lists /r
PASS help lists /s
PASS help lists /h
PASS help lists /v
PASS help lists /H
PASS help lists /n
PASS help lists /L
PASS help describes the block layout of Spec_TextFinder.md §3.4
PASS help describes the bare command line of Spec_TextFinder.md §3.1
PASS option listing follows §5 order
PASS an empty /p list emits /p alone, ending no line in whitespace
50 of 50 passed
PASS
/p list emits /p alone,
ending no line in whitespace.
Cpp_TextFinder_Dirnav unit tests
PASS skip list prunes build/, and the NUL file is not searched
PASS /p selects by extension
PASS a dot-file's extension is its last dot-suffix
PASS /s false searches the root's own files only
PASS an empty skip list prunes nothing
PASS a root whose name is in the skip list is traversed, not pruned
PASS the same directory reached during traversal is still pruned
PASS /n and /L true give a path line and an indented number-and-text detail line
PASS /n false leaves the detail line carrying the text alone
PASS /L false leaves the detail line carrying the number alone
PASS with neither /n nor /L a block is its path line alone
PASS a block with no detail lines stops at the first match
PASS three matching lines yield three detail lines under one path line
PASS /h true emits nothing for a file that matched nothing
PASS /h false announces every file that produced no block, and only those
PASS /h true leaves the matching file's block and nothing else
PASS a file that matched is never announced - its block already names it
PASS /h false announces a file rejected by the NUL test
PASS a pruned directory is not announced
PASS an unopenable root draws an error announcement under /h true
PASS the default options report every selected file, the NUL file among them
PASS an empty file is not reported, having no line to match
PASS asking for the matched line reads the file again and adds a detail line
PASS CRLF terminates a line and is not part of it
PASS a bare CR terminates a line
PASS a leading BOM is not part of the first line
PASS a file above 10 MB draws an error announcement under /h true
PASS a file exactly at the limit is searched
PASS every examined file and every entered directory is counted
PASS a file the /p list excluded is not counted
PASS a directory holding no selected file is still counted
PASS under /s false no subdirectory is counted
PASS a pruned directory and its files are counted once the list no longer prunes it
PASS a root that is a regular file counts as a file, and neither noun is inflected
PASS a root that cannot be opened is counted as neither
PASS the counts are of the whole run, not of one root
PASS an entry reached under two roots counts once for each
PASS the summary is not gated on /h
PASS the no-content case counts the files it never opens
39 of 39 passed
PASS
/p list excluded is not
counted, a pruned directory is counted as neither, under /s false no
subdirectory is counted, an unopenable root is counted as neither. Two of the eleven test
properties no other assertion could reach - that the counts are of the whole run rather than
of one root, and that an entry reached under two roots counts once for each - by driving one
navigator over two roots the way the binary does. One more asserts
accessed 1 files, 0 directories verbatim, which pins the uninflected singular
§3.6 accepts rather than leaving a later reader to correct it.
Cpp_TextFinder_Output unit tests
PASS one call writes the text and a single LF
PASS each call is one line
PASS no CR reaches the stream
PASS the string is written unchanged, with nothing added but the terminator
PASS a path line and its detail line pass through with their own leading space
PASS an empty string still terminates a line
PASS UTF-8 bytes pass through untouched
PASS Cpp_TextFinder_Output implements the Output interface
PASS the override is reached through Output&
9 of 9 passed
PASS
/H and the bare command line write no
summary at all, which is the only way to test a rule about runs that do not traverse; and
one checks that the help text names the closing line. The other fourteen §3.6 touched
were already here and simply gained the line in their expected output - which is what
asserting exact stdout costs when the output grows, and what it buys.
Cpp_TextFinder integration tests
PASS a normal search exits 0
PASS one path line per matching file, the NUL file excluded
PASS a normal search writes nothing to stderr
PASS build/ is pruned by the default skip list
PASS a root named in the skip list is traversed, not pruned
PASS /n and /L true give a path line and an indented detail line
PASS /L false leaves the number alone on the detail line
PASS with neither /n nor /L a block is its path line, emitted once per file
PASS the default expression lists every selected file without reading it
PASS /p filters by extension
PASS /s false enters no subdirectory
PASS roots are traversed in the order given
PASS /h false announces every file that produced no block, and only those
PASS a file that matched is never announced - its block already names it
PASS /h true leaves the matching file's block and nothing else
PASS an unopenable root announces through the output component
PASS an unopenable root does not affect the exit code
PASS /H exits 0
PASS /H prints the help text
PASS help describes /h in its current terms
PASS help describes the block layout
PASS help describes the closing run summary
PASS help text carries LF only, being written after the sink configures stdout
PASS a bare command line exits 0
PASS a bare command line lists every default, with /v reading false
PASS a bare command line writes nothing to stderr
PASS /v lists the resolved options before the search output
PASS the search output follows the /v listing
PASS output carries LF only, on every platform
PASS the run summary is the last line a traversing run writes
PASS /H traverses nothing and writes no run summary
PASS a bare command line traverses nothing and writes no run summary
PASS not a switch diagnostic
PASS not a switch exits 1
PASS not a switch stdout
PASS unrecognized switch diagnostic
PASS unrecognized switch exits 1
PASS unrecognized switch stdout
PASS missing argument diagnostic
PASS missing argument exits 1
PASS missing argument stdout
PASS invalid boolean diagnostic
PASS invalid boolean exits 1
PASS invalid boolean stdout
PASS empty root path diagnostic
PASS empty root path exits 1
PASS empty root path stdout
PASS empty expression diagnostic
PASS empty expression exits 1
PASS empty expression stdout
PASS invalid regex diagnostic
PASS invalid regex exits 1
PASS invalid regex stdout
53 of 53 passed
PASS
/v listing precedes the search
output; and that a bare command line writes nothing to stderr.
Cpp_TextFinder_Output puts stdout into binary mode, but two outputs bypassed
that sink: the /H help text went to std::cout before the sink was
constructed, and the usage diagnostics go to std::cerr, which is never set to
binary. On Windows both arrived CRLF-translated.
/H, and §5.2 at the time
called the reason lines "fixed text, identical across implementations" - which CRLF on
Windows against LF on POSIX is not.
/H after Output construction, so the help text now carries LF and the
suite asserts it. The stderr half remains open by design, §3.4 leaving the stderr
terminator to the platform.
Cpp_TextFinder_Dirnav gained renderPath and a traversal gate to
satisfy it. No suite exercises either. Building such a name means an unpaired surrogate on
Windows or a non-UTF-8 byte sequence on POSIX, neither of which the existing fixtures
create, and the POSIX branch does not compile on the machine this build runs on. What the
136 assertions prove is that the new rendering produces byte-identical output to the call
it replaced for every ordinary name - the regression risk, and the reason they all still
pass - not that the substitution branch is correct. §6.2 asks the suites to check a
claim rather than let it be read, so that claim is currently unchecked.
# Prompts and Replies — Tests for Cpp_TextFinder
This file records the prompts and replies that produced the unit and integration test suites. The work that produced the code under test is recorded in [Prompts_Build_Cpp_TextFinder.md](Prompts_Build_Cpp_TextFinder.md).
---
## Turn 1
### User
> Create unit tests and test drivers for each Cpp_TextFinder part. Place in part directories. Create integration test and test driver. Place in Cpp_Spec_driven_Textfinder.
### Assistant
**Scope.** Wrote unit tests for the three library parts and left `Cpp_TextFinder_Entry` to the integration suite: Entry is a binary whose behavior is its startup sequence, exit codes, and stream routing, none of which can be exercised without running it.
**Harness.** Used no test framework. Spec_TextFinder.md §6 confines implementations to the standard library, so each test module carries a small `Checker` struct with `expect` and `equal`, counting assertions and printing only failures. Each unit-test module exports a single entry point returning a failure count — `runCmdlineUnitTests`, `runDirnavUnitTests`, `runOutputUnitTests` — which keeps the modules free of a shared result type that would collide when several are imported together.
**Files.** Eight, two per suite:
- [Cpp_TextFinder_Cmdline_UnitTest.ixx](Cpp_Spec_driven_Cmdline/src/Cpp_TextFinder_Cmdline_UnitTest.ixx) and its `_TestDriver.cpp` — defaults, both introducers, boolean case folding, last-occurrence-wins, `/P` accumulation, the five `/p` normalization rules, all eight parse diagnostics, and the rendered help and option listings.
- [Cpp_TextFinder_Dirnav_UnitTest.ixx](Cpp_Spec_driven_Dirnav/src/Cpp_TextFinder_Dirnav_UnitTest.ixx) and its driver — builds a temp tree and supplies its own `Recorder : public Output`, which also demonstrates that the class template binds to any `Output`. Covers skip-list pruning, `/p` selection including the dot-file rule, `/s false`, all four record forms, the `/h` gating, `cannot open`, LF, CRLF and bare CR line splitting, BOM consumption, and the 10 MB limit at and just above the boundary.
- [Cpp_TextFinder_Output_UnitTest.ixx](Cpp_Spec_driven_Output/src/Cpp_TextFinder_Output_UnitTest.ixx) and its driver — redirects `std::cout`'s stream buffer to inspect the bytes written, checking the single LF terminator, the absence of CR, unchanged pass-through, and dispatch through `Output&`.
- [Cpp_TextFinder_IntegrationTest.ixx](src/Cpp_TextFinder_IntegrationTest.ixx) and its driver, at the top of this folder — spawns the built executable through `std::system` with stdout and stderr redirected to files read back in binary, so Entry is covered end to end.
**Build.** Each component's `CMakeLists.txt` gained a `*_UnitTest` module library and a `*_TestDriver` executable; the top-level one gained `enable_testing()`, the integration targets, and an `add_test` for each suite. CMake passes the executable's path to the integration driver as `TEXTFINDER_EXE` through the `$<TARGET_FILE:Cpp_TextFinder>` generator expression, with a command-line argument able to override it.
**What the first run found.** The three unit suites passed. Eight integration assertions failed with expected and actual text that looked identical — a CRLF-against-LF difference. `Cpp_TextFinder_Output` puts stdout into binary mode, but two outputs bypass that sink: the `/H` help text goes to `std::cout` at step 2, before `Cpp_TextFinder_Output` is constructed at step 3, and the usage diagnostics go to `std::cerr`, which is never set to binary. On Windows both arrive CRLF-translated.
Whether that is a defect depends on how the specs are read. §3.4's terminator rule covers "every match record and every announcement," and neither of these is one. But §5.1 says every implementation prints "exactly this text" under `/H`, and §5.2 calls the reason lines "fixed text, identical across implementations" — which CRLF on Windows against LF on POSIX is not. Normalized line endings in the two affected comparisons and documented the reasoning at the helper, rather than change a specification that had not been asked about. Closing the gap would mean extending §3.4, setting file descriptor 2 to binary, and moving `/H` after Output construction.
After that change all four suites passed: 48, 19, 8, and 40 assertions, 115 in total.
**Two incidental notes.** The Dirnav and integration suites sort emitted lines before comparing, because §3.2 leaves the order of a directory's entries to the filesystem. And `ctest` on this machine's PATH resolves to something that runs `cargo test`, so CMake's own `ctest.exe` has to be called by full path.
Updated [Project_Tree.md](../Project_Tree.md) with the new sources and a legend for them, and flagged that the `Checker` struct is duplicated across the four test modules — factoring it into a shared support module would remove about seventy lines but would add a component that had not been asked for.
---
## Turn 2
### User
> run tests and show output
### Assistant
Ran the four drivers directly and then the whole suite through CMake's `ctest`:
```
Cpp_TextFinder_Cmdline unit tests
48 of 48 passed
PASS
Cpp_TextFinder_Dirnav unit tests
19 of 19 passed
PASS
Cpp_TextFinder_Output unit tests
8 of 8 passed
PASS
Cpp_TextFinder integration tests
40 of 40 passed
PASS
```
```
1/4 Test #1: IntegrationTest .................. Passed 4.09 sec
2/4 Test #2: Cmdline_UnitTest ................. Passed 0.05 sec
3/4 Test #3: Dirnav_UnitTest .................. Passed 0.11 sec
4/4 Test #4: Output_UnitTest .................. Passed 0.05 sec
100% tests passed, 0 tests failed out of 4
```
Noted that the drivers print only a summary on success and name assertions only when they fail, which is why a passing run is this terse; that the integration suite accounts for nearly all the runtime because each of its assertions spawns the executable, while the three in-process suites finish in about a fifth of a second combined; and that naming each assertion on a passing run would need a verbose mode on `Checker`.
---
## Turn 3
### User
> create Prompts_Cpp_Spec_driven_TextFinder_Tests. Include all the prompts and replies created to build and run tests
### Assistant
Created this file, [Prompts_Cpp_Spec_driven_TextFinder_Tests.md](Prompts_Cpp_Spec_driven_TextFinder_Tests.md), and added it to [Project_Tree.md](../Project_Tree.md). User prompts are quoted verbatim. Assistant replies are summarized from the actual responses; tool calls are noted as effects rather than transcribed.
---
## Turn 4
### User
> create batch file to run all unit tests. create batch file to run integration tests. Each run should announce the test and its return status
### Assistant
Created [run_unit_tests.bat](run_unit_tests.bat) and [run_integration_tests.bat](run_integration_tests.bat) at the top of this folder. Each brackets a suite with a `=== <name> ===` banner and a `--- <name>: exit status N (PASS|FAIL) ---` line, then prints a summary and returns the number of failed suites as its own exit code.
Both locate the build directory from their own path with `%~dp0`, so they run from any working directory. A driver that has not been built is reported as `not built:` with its path and counted as a failure rather than skipped silently. The integration script forwards an optional argument to the driver, so a binary built elsewhere can be tested.
Verified the failure path as well as the success path, by pointing the integration script at a nonexistent executable: it reported `exit status 1 (FAIL)` and the batch file exited 1.
---
## Turn 5
### User
> Create Testing src files that announce each test and its completion status for both unit and integration tests
### Assistant
First proposed a shared `Cpp_TextFinder_TestSupport` module holding one `Tester` class for all four suites, which would also have retired the duplicated `Checker` flagged in Turn 1. The user rejected it, asking instead that the checker stay duplicated per part, so that file was never written.
Changed the `Checker` in each of the four test modules instead: `expect` and `equal` now both delegate to a `record` helper that prints `PASS` or `FAIL` alongside the test name, and `equal` still follows a failure with the expected and actual strings. The batch files needed no change, since the announcements nest inside the banners they already print.
---
## Turn 6
### User
> run tests
### Assistant
Ran both batch files. All 115 assertions passed — 48 Cmdline, 19 Dirnav, 8 Output, 40 integration — and both scripts exited 0.
---
## Turn 7
### User
> run and show output
### Assistant
Reproduced the full run in the reply rather than only summarizing it, since command output reaches the assistant but not reliably the user's terminal.
---
## Test Output
`run_unit_tests.bat`:
```
Cpp_TextFinder unit tests
Build directory: ...\Cpp_Spec_driven_TextFinder\build
=== Cmdline unit tests ===
Cpp_TextFinder_Cmdline unit tests
PASS empty command line parses
PASS default /P is .
PASS default /p is empty
PASS default /r is .
PASS default /s is true
PASS default /h is true
PASS default /v is false
PASS default /H is false
PASS default /n is true
PASS default /L is true
PASS introducers / and - are equivalent
PASS boolean values fold case
PASS True is accepted
PASS last occurrence wins for /r
PASS /h and /H are distinct switches
PASS an argument beginning with an introducer is taken verbatim
PASS first /P replaces the default
PASS /P accumulates in argv order
PASS items are trimmed
PASS one leading dot is stripped
PASS empty items are discarded
PASS an all-whitespace list is empty
PASS duplicates are retained
PASS not a switch
PASS unrecognized switch
PASS over-long switch token
PASS bare introducer
PASS missing argument
PASS invalid boolean
PASS empty root path
PASS empty expression
PASS the introducer is reproduced as typed
PASS parsing stops at the first violation
PASS helpText begins with usageLine
PASS usage names the executable
PASS usageLine ends with a newline
PASS helpText ends with a newline
PASS help lists /P
PASS help lists /p
PASS help lists /r
PASS help lists /s
PASS help lists /h
PASS help lists /v
PASS help lists /H
PASS help lists /n
PASS help lists /L
PASS option listing follows §5 order
PASS an empty /p list keeps its trailing space
48 of 48 passed
PASS
--- Cmdline: exit status 0 (PASS) ---
=== Dirnav unit tests ===
Cpp_TextFinder_Dirnav unit tests
PASS skip list prunes build/, and the NUL file is not searched
PASS /p selects by extension
PASS a dot-file's extension is its last dot-suffix
PASS /s false searches the root's own files only
PASS an empty skip list prunes nothing
PASS default record carries path, line number, and text
PASS /n false omits the line number and its separator
PASS /L false omits the matched line and its separator
PASS both false leaves the path alone
PASS /h true emits no file announcement
PASS /h false announces a searched file
PASS /h false announces a file rejected by the NUL test
PASS a pruned directory is not announced
PASS an unopenable root draws an error announcement under /h true
PASS CRLF terminates a line and is not part of it
PASS a bare CR terminates a line
PASS a leading BOM is not part of the first line
PASS a file above 10 MB draws an error announcement under /h true
PASS a file exactly at the limit is searched
19 of 19 passed
PASS
--- Dirnav: exit status 0 (PASS) ---
=== Output unit tests ===
Cpp_TextFinder_Output unit tests
PASS one call writes the text and a single LF
PASS each call is one line
PASS no CR reaches the stream
PASS the string is written unchanged, with nothing added but the terminator
PASS an empty string still terminates a line
PASS UTF-8 bytes pass through untouched
PASS Cpp_TextFinder_Output implements the Output interface
PASS the override is reached through Output&
8 of 8 passed
PASS
--- Output: exit status 0 (PASS) ---
ALL UNIT TEST SUITES PASSED
```
`run_integration_tests.bat`:
```
Cpp_TextFinder integration tests
Build directory: ...\Cpp_Spec_driven_TextFinder\build
=== Integration tests ===
Cpp_TextFinder integration tests
PASS a normal search exits 0
PASS records name every matching file, the NUL file excluded
PASS a normal search writes nothing to stderr
PASS build/ is pruned by the default skip list
PASS the default record form carries all three fields
PASS /p filters by extension
PASS /s false enters no subdirectory
PASS roots are traversed in the order given
PASS /h false announces a searched file
PASS /h false announces a file rejected by the NUL test
PASS /h true suppresses file announcements
PASS an unopenable root announces through the output component
PASS an unopenable root does not affect the exit code
PASS /H exits 0
PASS /H prints the help text
PASS help describes /h in its current terms
PASS /v lists the resolved options before the records
PASS records follow the /v listing
PASS output carries LF only, on every platform
PASS not a switch diagnostic
PASS not a switch exits 1
PASS not a switch writes nothing to stdout
PASS unrecognized switch diagnostic
PASS unrecognized switch exits 1
PASS unrecognized switch writes nothing to stdout
PASS missing argument diagnostic
PASS missing argument exits 1
PASS missing argument writes nothing to stdout
PASS invalid boolean diagnostic
PASS invalid boolean exits 1
PASS invalid boolean writes nothing to stdout
PASS empty root path diagnostic
PASS empty root path exits 1
PASS empty root path writes nothing to stdout
PASS empty expression diagnostic
PASS empty expression exits 1
PASS empty expression writes nothing to stdout
PASS invalid regex diagnostic
PASS invalid regex exits 1
PASS invalid regex writes nothing to stdout
40 of 40 passed
PASS
--- Integration: exit status 0 (PASS) ---
ALL INTEGRATION TEST SUITES PASSED
```