Skip to content

Enhance self-validation tests for DotNet, C++, and VHDL generation - #37

Merged
Malcolmnixon merged 5 commits into
mainfrom
feature/functional-self-validation
Aug 13, 2026
Merged

Malcolmnixon merged 5 commits into
mainfrom
feature/functional-self-validation

Conversation

@Malcolmnixon

Copy link
Copy Markdown
Member

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

  • The validation suite now runs functional generation tests for DotNet, C++, and VHDL generators, verifying that each generator produces expected Markdown output from embedded sample sources. [1] [2] [3] [4]
  • Enforcement tests for documentation coverage are added for all three generators, checking that undocumented items are correctly detected and that documented items are not falsely flagged. [1] [2] [3] [4]
  • All generator invocations during validation are run in silent, log-capturing child contexts to keep the validation transcript clean. [1] [2] [3]

Clang Availability and Skipped Tests

  • The C++ generation and enforcement tests are gated on clang availability, using the new ApiMark.Cpp.CppAst.ClangDiscovery helper. 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]
  • The validation summary now includes a "Skipped: N" count for visibility in CI and operator logs. [1] [2] [3]

Documentation and Requirements Updates

  • User and FAQ documentation now describe the expanded validation coverage, the handling of skipped C++ tests, and the updated test result summary. (Ffdbf4c8L19R19, [1] [2]
  • Requirements and verification documents are updated to reflect the new tests, their gating/skipping logic, and the use of ClangDiscovery. [1] [2]

Test Ownership and Coverage

  • The .reviewmark.yaml file 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.

Malcolm Nixon and others added 5 commits August 12, 2026 18:22
…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>
Copilot AI lite review requested due to automatic review settings August 13, 2026 03:51
@Malcolmnixon
Malcolmnixon merged commit 040eded into main Aug 13, 2026
16 checks passed
@Malcolmnixon
Malcolmnixon deleted the feature/functional-self-validation branch August 13, 2026 03:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.ClangDiscovery and refactored clang discovery to support a non-throwing availability probe; improved macOS xcrun discovery by probing xcrun -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.

Comment on lines +25 to +27
- 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`.
Comment thread docs/user_guide/cli.md
Comment on lines +53 to +55
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
Comment on lines +72 to +74
`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.
Comment on lines +391 to +394
catch (Exception ex) when (ex is InvalidOperationException or System.ComponentModel.Win32Exception)
{
return false;
}
Comment on lines +182 to +183
/// Validates that Validation.Run produces output mentioning all three functional
/// generation test names.
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.

2 participants