Enhance self-validation tests for DotNet, C++, and VHDL generation - #37
Conversation
…generation Extends ApiMark.Tool's --validate self-test suite beyond version/help smoke tests to exercise the real generator pipelines: - RunDotNetGenerationTest runs DotNetGenerator against the tool's own already-built assembly and XML doc file. - RunCppGenerationTest runs CppGenerator against a tiny embedded sample header, and is recorded as Skipped (not Failed) when clang cannot be located, so users validating only DotNet/VHDL are never forced to install clang or blocked by its absence. - RunVhdlGenerationTest runs VhdlGenerator against a tiny embedded sample entity (VHDL parsing has no external tool dependency). Refactored ClangAstParser.FindClangExecutable into a non-throwing TryFindClangExecutable, shared by a new public ClangDiscovery.IsAvailable helper so the self-test's skip gate uses identical discovery logic to actual parsing. Hardened the macOS xcrun discovery option to probe 'xcrun -find clang' rather than assuming success unconditionally, preventing a false 'available' result on machines without Xcode Command Line Tools (found during change-review). Validation.Run's summary now reports a 'Skipped: N' line; skipped tests never count toward failures or the exit code. Updated design, reqstream, verification, user-guide docs, and .reviewmark.yaml (added ClangDiscovery.cs/ClangDiscoveryTests.cs to the ApiMark-Cpp-ClangAstParser review-set, per formal-review finding). Verified: ApiMark.Tool.Tests 94/94 passing (including the clang-unavailable skip path); full solution builds clean; formal reviews (gpt-5.4-mini) of ApiMark-Cpp-ClangAstParser, ApiMark-Tool-SelfTest, and ApiMark-Tool-SelfTest-Validation review-sets passed with one addressed finding; built-in change-review passed with one addressed finding (xcrun probe). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Second-round change-review found two issues in TryProbeXcrunClang (added in the previous commit to fix a false-'available' xcrun result): - stderr was redirected but never drained, risking a pipe-buffer deadlock if 'xcrun -find clang' wrote enough to stderr while this method blocked reading only stdout. Fixed by reading stdout/stderr concurrently via ReadToEndAsync, matching the existing RunProcess pattern used elsewhere in this file. - No timeout was applied to WaitForExit, so a hung/slow xcrun (e.g. a first-run license prompt) could block this synchronous pre-flight check indefinitely. Added a bounded 5-second timeout with a best-effort process kill on timeout. Verified: full solution builds clean; ApiMark.Tool.Tests 94/94 passing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Route the DotNet/C++/VHDL functional self-validation generator calls through a silent, log-capturing child Context instead of the outer validation context, so DotNetGenerator/CppGenerator/VhdlGenerator's own informational WriteLine output (e.g. 'Parsing assembly: ...', 'Found N types...') no longer interleaves with the pass/fail transcript. Matches the existing pattern used by the version/help self-tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add ApiMark_EnforceDocs to the --validate self-test suite: exercises the real VhdlGenerator.CheckDocumentationCoverage pipeline (the same API Program.RunToolLogic calls for --enforce-docs) against an embedded VHDL sample with one documented and one deliberately undocumented port, verifying the undocumented port is detected and the documented one is not. VHDL is used since it needs no external tool dependency, so this test always runs regardless of clang availability. Update design/verification/reqstream docs and ValidationTests.cs for the new 6th self-test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add RunDotNetEnforceDocsTest and RunCppEnforceDocsTest alongside the renamed RunVhdlEnforceDocsTest, giving --validate parity between generation and enforcement self-tests for all three supported languages. Update design, verification, and reqstream docs to match the new 8-test suite. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR expands ApiMark.Tool’s in-process --validate self-test suite so it exercises the real DotNet, C++, and VHDL generation and documentation-coverage enforcement pipelines end-to-end, while handling clang-unavailable environments by marking C++ tests as skipped (NotExecuted) instead of failing.
Changes:
- Added functional generation self-tests for DotNet, C++, and VHDL, plus enforce-docs self-tests for the same generators, with generator output routed into silent/log-capturing child contexts.
- Introduced
ApiMark.Cpp.CppAst.ClangDiscoveryand refactored clang discovery to support a non-throwing availability probe; improved macOSxcrundiscovery by probingxcrun -find clang. - Updated test assertions, documentation, and requirements/verification artifacts to reflect the expanded (8-test) validation suite and skipped-test reporting.
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| test/ApiMark.Tool.Tests/SelfTest/ValidationTests.cs | Updates expected results count to 8 and adds assertions around functional/enforcement test names and skipped reporting. |
| test/ApiMark.Cpp.Tests/ClangDiscoveryTests.cs | Adds unit coverage for ClangDiscovery.IsAvailable behavior. |
| src/ApiMark.Tool/SelfTest/Validation.cs | Extends validation to run generation + enforcement tests and prints a skipped count. |
| src/ApiMark.Tool/SelfTest/Validation.DotNet.cs | Adds DotNet generator functional self-test. |
| src/ApiMark.Tool/SelfTest/Validation.Cpp.cs | Adds C++ generator functional self-test with clang gating (skip). |
| src/ApiMark.Tool/SelfTest/Validation.Vhdl.cs | Adds VHDL generator functional self-test. |
| src/ApiMark.Tool/SelfTest/Validation.EnforceDocs.DotNet.cs | Adds DotNet enforce-docs functional self-test against the tool’s own assembly/XML docs. |
| src/ApiMark.Tool/SelfTest/Validation.EnforceDocs.Cpp.cs | Adds C++ enforce-docs functional self-test with clang gating (skip). |
| src/ApiMark.Tool/SelfTest/Validation.EnforceDocs.Vhdl.cs | Adds VHDL enforce-docs functional self-test with embedded sample source. |
| src/ApiMark.Cpp/CppAst/ClangDiscovery.cs | Introduces a public helper to preflight clang availability using shared discovery logic. |
| src/ApiMark.Cpp/CppAst/ClangAstParser.cs | Refactors discovery to a non-throwing helper and adds an xcrun probe with timeout/kill handling. |
| docs/verification/api-mark-tool/self-test/validation.md | Updates verification plan/criteria to reflect expanded validation coverage and skipped tests. |
| docs/verification/api-mark-tool/self-test.md | Updates self-test verification summary (but currently has inconsistencies noted in review comments). |
| docs/verification/api-mark-cpp/clang-ast-parser.md | Documents ClangDiscovery verification and its relationship to clang discovery. |
| docs/user_guide/faq.md | Updates FAQ to describe expanded validation and C++ skip behavior. |
| docs/user_guide/cli.md | Updates CLI docs for --validate/--results and skipped-count reporting (with a wording mismatch noted). |
| docs/reqstream/api-mark-tool/self-test/validation.yaml | Adds requirements entries covering new generation/enforcement tests, skipping logic, and output suppression. |
| docs/reqstream/api-mark-tool/self-test.yaml | Links new validation requirements into the self-test requirement set. |
| docs/design/api-mark-tool/self-test/validation.md | Updates design documentation to reflect expanded test suite and clang gating. |
| .reviewmark.yaml | Assigns new clang discovery source/test files to the appropriate review group. |
Suppressed comments (5)
docs/verification/api-mark-tool/self-test.md:36
- The scenario description still says ExitCode=0 only when "both internal self-tests" pass, but validation now runs additional self-tests and permits skips (e.g., clang unavailable). The scenario text should match the current behavior and the test it references.
**Self-validation with valid context exits zero**: Verifies that
`Validation.Run` completes with `ExitCode = 0` when both internal self-tests
pass. Tested by `Validation_Run_WithValidContext_ExitsZero`.
docs/verification/api-mark-tool/self-test.md:41
- This section says the TRX file contains "all five" results and refers to a single C++ test, but validation now writes 8 results and includes both C++ generation and enforcement tests.
`.trx` path, the file is created and contains `"TestRun"` and all five
self-test results, including the C++ test's `Passed` or `NotExecuted`
outcome. Tested by `Validation_Run_WithResultsTrxFile_CreatesTrxFile`.
docs/verification/api-mark-tool/self-test.md:45
- This section says the XML results file contains "all five" results, but validation now writes 8 results.
`.xml` path, the file is created and contains all five self-test results.
Tested by `Validation_Run_WithResultsXmlFile_CreatesXmlFile`.
docs/verification/api-mark-tool/self-test.md:29
- Acceptance criteria refers to a single "C++ functional test", but validation now has two clang-gated C++ tests (generation and enforce-docs).
- The C++ functional test is recorded as skipped (`TestOutcome.NotExecuted`),
not failed, when clang cannot be located, and does not set `ExitCode` to 1.
docs/verification/api-mark-tool/self-test.md:58
- This scenario is described as checking only generation test names, but the referenced test also asserts the enforce-docs test names. The scenario text should match what the test actually checks.
**Output mentions all three functional generation test names**: Verifies
that the log output contains `"ApiMark_DotNetGeneration"`,
`"ApiMark_CppGeneration"`, and `"ApiMark_VhdlGeneration"`. Tested by
`Validation_Run_WritesFunctionalGenerationTestResults`.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| - Output mentions `ApiMark_VersionDisplay`, `ApiMark_HelpDisplay`, | ||
| `ApiMark_DotNetGeneration`, `ApiMark_CppGeneration`, and | ||
| `ApiMark_VhdlGeneration`. |
| Verifies that forcing clang discovery to fail (by pointing | ||
| `APIMARK_CLANG_PATH` at a nonexistent path) records `ApiMark_CppGeneration` | ||
| with `TestOutcome.NotExecuted` and leaves `context.ExitCode` at `0`. Tested | ||
| by `Validation_Run_CppGenerationSkippedWhenClangUnavailable`. |
| format) or an `.xml` file path (JUnit-compatible XML). The summary output includes | ||
| `Total Tests`, `Passed`, `Skipped`, and `Failed` counts. The exit code is non-zero if | ||
| any validation test fails; skipped tests (such as the C++ check when clang is |
| `test/ApiMark.Cpp.Tests/ClangDiscoveryTests.cs`. It shares the exact discovery logic used by | ||
| `ClangAstParser.Parse` (via the internal `TryFindClangExecutable` helper), so its return value | ||
| always matches whether `Parse` would succeed or throw for the same inputs. |
| catch (Exception ex) when (ex is InvalidOperationException or System.ComponentModel.Win32Exception) | ||
| { | ||
| return false; | ||
| } |
| /// Validates that Validation.Run produces output mentioning all three functional | ||
| /// generation test names. |
This pull request significantly expands the self-validation suite for ApiMarkTool, ensuring that the tool's real DotNet, C++, and VHDL documentation generators and enforcement pipelines are exercised end-to-end during validation. It adds new functional and enforcement tests, robustly handles environments lacking clang, and updates the documentation and requirements to reflect these features. The changes also improve test reporting by distinguishing skipped tests and suppressing generator output during validation.
Self-Validation Enhancements
Clang Availability and Skipped Tests
ApiMark.Cpp.CppAst.ClangDiscoveryhelper. When clang is not found, these tests are recorded as skipped (not failed) and do not set a non-zero exit code. [1] [2] [3] [4] [5] Ffdbf4c8L19R19, [6] [7]Documentation and Requirements Updates
ClangDiscovery. [1] [2]Test Ownership and Coverage
.reviewmark.yamlfile is updated to assign new source and test files (ClangDiscovery.cs,ClangDiscoveryTests.cs) to the correct review group, ensuring proper code ownership and review coverage.