Repository navigation
Cover the fourth test leg, and watch the SymPy snapshot for drift (#746 items 35, 73) - #1038
Merged
Merged
Conversation
…ems 35, 73) Item 35: three of the four test legs report coverage and the C++ one reports none. It cannot report the same measurement -- the library reaches those tests as a Native AOT shared object, the published artefact holds no managed assembly, and ctest runs a native binary rather than a host the VSTest collector can attach to. What it does have is the C++ wrapper in AngouriMath.CPP.Importing, which nothing measured: the Linux job now builds it with --coverage and uploads a gcovr Cobertura report under the `cpp` flag, filtered to the wrapper so that neither googletest nor the test file inflates it. The step fails on an empty report rather than uploading one. Docs/Contributing/Coverage.md says what each flag covers and why this one is not the kernel. Item 73: the SymPy comparison is a hand-taken snapshot against one version and cannot tell you it has gone stale. A weekly job re-runs the 80 SymPy probes against whatever pip installs that day and fails when the version or any answer has moved from the committed baseline, uploading the new answers so re-taking the snapshot is a copy. Only the SymPy half runs here; the half that asks this library the same questions is not in this repository, and Maxima and SageMath are not touched, because nothing measures them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bjumi5K7fg8yx6UK1mZTQd
v5 of codecov-action takes `files`, not `file`. Given `file` it warns about an unexpected input, ignores the path and searches the workspace instead: on the C++ leg that search found 96 reports, the whole of googletest and of /usr/include/c++/13 among them, so the flag carried everything the gcovr filter exists to exclude. `disable_search` and `plugins: noop` hold it to the report gcovr wrote. CSharpTest.yml has the same input and the same consequence, so it is corrected here too; its search is left alone, not having been measured. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bjumi5K7fg8yx6UK1mZTQd
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two CI gaps from #746, independent of each other.
Item 35 — coverage for the C++ leg
The roadmap says "three of the four legs report coverage;
CPPTest.ymlhas no coverage step and no codecov flag". Measured against the workflow files, that is exactly right:CSharpTest.yml/p:CollectCoverage=trueand--collect:"XPlat Code Coverage"csharpFSharpTest.yml--collect:"XPlat Code Coverage"fsharpInteractiveTest.yml--collect:"XPlat Code Coverage"interactiveCPPTest.ymlThe other three legs' measurement cannot be made here, and the reason decides what to do instead.
AngouriMath.CPP.ExportingsetsPublishAot; publishing it with-p:NativeLib=Shared -p:SelfContained=trueleavesAngouriMath.CPP.Importing/out-x64holding one shared object and a symbol file — noAngouriMath.dll, noAngouriMath.CPP.Exporting.dll— and the tests are a native binary run byctest, not a test host. So there is nodotnet testfor the collector to attach to and no managed assembly in the artefact for it to instrument. Copying a step fromCSharpTest.ymlwould upload an empty report under a flag claiming this leg was covered.That is a statement about that route, not a proof that no route exists, and the doc says so in those words.
What is genuinely uncovered and genuinely coverable is the C++ itself.
Sources/Wrappers/AngouriMath.CPP.Importingis the handle cache, the error-code translation and the exception boundary every C++ caller passes through, and no managed test can see a defect in it. The Linux job in the matrix now configures cmake with--coverage -O0 -g, runs the same 24 tests, and reports withgcovrfiltered to the wrapper.Measured in CI, on the Linux job of this PR's own run (24 of 24 tests passing):
with
ErrorCode.cpp,ErrorCode.handAmgouriMathException.hthe least covered -- the error path is where these tests do not go.A defect this found in the existing legs
The first push went green while uploading the opposite of that report.
codecov/codecov-action@v5does not takefile; given it, the action logs "Unexpected input(s) 'file'", ignores the path and searches the workspace instead. That search found 96 coverage files -- the whole of googletest and of/usr/include/c++/13-- so thecppflag would have carried everything the filter exists to exclude.Corrected to
files, plusdisable_search: trueandplugins: noop, and re-measured on the next push:Found 1 coverage files to report,coverage-cpp.xml.CSharpTest.ymlhas the samefile:input and therefore the same consequence -- thecsharpflag has never been made from thecoverage.opencover.xmlit names. That is a one-word fix and it is in this PR; its search is left alone, not having been measured.The filter matters: unfiltered, the report is 6,773 lines of mostly vendored googletest, and it includes
RunTests.cppat 100% because that is the thing being run. And the step fails on an empty report (grep -q 'lines-valid="[1-9]') rather than letting gcovr's well-formed nothing go green under acppflag.New
Sources/AngouriMath/Docs/Contributing/Coverage.mdsays what each of the four flags covers, socppis not read as the kernel. It is not linked fromAGENTS.md's Where things are written down table — that file is owned by another change in flight; the row is owed.Roadmap wording. Item 35's Remaining line should stop implying a fourth leg of the same kind. Suggested: "Four legs run tests and all four now report coverage, but not of the same thing:
csharp,fsharpandinteractiveare managed coverage throughdotnet test, andcppis gcov over the C++ wrapper, because the C++ leg carries no managed assembly into CI. Managed coverage through the Native AOT export path is not collected by any route tried."Item 73 — the SymPy comparison goes stale on its own
The comparison is 80 probes over 23 areas, taken by hand against SymPy 1.14.0, published in
Docs/Usage/Comparison.md(#1030). A snapshot cannot tell you it has gone out of date.New
SymPyParity.yml, weekly plusworkflow_dispatch: install the newest SymPy (unpinned on purpose — pinning would make it agree with the baseline for ever), re-run the 80 probes, and compare with.github/sympy-parity/sympy-baseline.json. It fails when the version or any answer has moved, prints awas/is nowtable into the job summary, and uploads today's answers so re-taking the snapshot is a file copy plus a re-run of the harness. Same shape as the corpus gate: a committed baseline that fails when a verdict moves, rather than a number in a log that expires.A version bump with no answer moving still fails, deliberately: the published page names the version it measured, and a version it does not name is a version it did not measure. That is roughly two or three failures a year.
What it deliberately does not do.
The probe set is vendored to
.github/sympy-parity/probes.json(the SymPy column only) beside the workflow, since it is CI data rather than a test project. The committed baseline was regenerated locally and reproduces the published harness snapshot on all 80 rows; two consecutive runs at 1.14.0 differ on 0 of 80, and the one floating-point row is 15 digits out of mpmath.What ran, and what cannot run yet
Observed on this PR, not inferred from the YAML:
C++ Test— all three operating systemsPreparing tests, instrumented for coverage,Coverage of the C++ wrapperandSend to codecoveach green,100% tests passed, 0 tests failed out of 24SymPy parity watch—Paritysympy 1.14.0installed on Python 3.14.7,80 probes run, 0 answers moved, exit 0The parity job passing on a GitHub runner is also the determinism evidence: 80 answers taken on a different machine, a different Python and a different CPU match the committed baseline exactly.
CPPTest.ymlhas no path filter, so it fires on any PR.SymPyParity.yml'sscheduletrigger cannot fire until the workflow is on the default branch — a GitHub rule, not a defect — so what can be observed before merge is theworkflow_dispatchand the path-filteredpull_requesttrigger, and the latter is what ran here. Its path filters carry no leading./, which is the defect that silencedBenchmark.ymlfor ninety-eight PRs andCPPBuild.ymlfor its whole existence (#775). It is the repository's firstscheduletrigger.What is not claimed: that codecov ingested the
cppreport. The upload step reports success and the CLI names the one file it sent, but codecov's public API returns no commits and no flags for this repository at all — including the three that already exist — so there is nothing to read back from that side.