1515 symmetry :
1616 name : MATLAB <-> Python symmetry tests
1717 runs-on : ubuntu-latest
18+ env :
19+ # Every comparison is expected to run here, so a comparison that could
20+ # not run FAILS instead of reporting green: a skipped Python symmetry
21+ # test fails (tests/symmetry/conftest.py), and the MATLAB stages fail
22+ # on any Incomplete result. Cases that cannot run in a given stage by
23+ # design are deselected by name in that stage. VH-Lab/NDR-python#34.
24+ NDR_SYMMETRY_CHECK_STRICT : " 1"
25+ # matbox resolves and downloads its MATLAB dependencies (e.g.
26+ # vhlab-toolbox-matlab) through the GitHub API. Give it the runner's
27+ # built-in token (auto-provided; no secret to configure) so those calls
28+ # are authenticated (5000 req/hr) instead of hitting the shared
29+ # unauthenticated limit (60 req/hr), which fails dependency install.
30+ # Same fix as NDR-matlab's test-symmetry.yml.
31+ GITHUB_TOKEN : ${{ github.token }}
1832
1933 steps :
2034 # -- Checkout both repos ----------------------------------------------
@@ -28,15 +42,29 @@ jobs:
2842 # Developers are expected to keep matching branch names across the
2943 # two repos when making cross-language changes. Falls back to main
3044 # when the matching branch does not exist in NDR-matlab.
45+ #
46+ # The choice is written to the job summary with its reason: a paired
47+ # change whose NDR-matlab branch was pushed AFTER this run started
48+ # resolves to main, and then fails in strict mode for want of the
49+ # MATLAB half -- push NDR-matlab first, or re-run once it exists.
3150 - name : Resolve NDR-matlab branch
3251 id : matlab-ref
3352 run : |
3453 BRANCH="${{ github.head_ref || github.ref_name }}"
3554 if git ls-remote --exit-code --heads https://github.com/VH-Lab/NDR-matlab.git "$BRANCH" >/dev/null 2>&1; then
36- echo "ref=$BRANCH" >> "$GITHUB_OUTPUT"
55+ REF="$BRANCH"
56+ WHY="NDR-matlab has a branch named \`$BRANCH\`, matching this run."
3757 else
38- echo "ref=main" >> "$GITHUB_OUTPUT"
58+ REF="main"
59+ WHY="NDR-matlab has no branch named \`$BRANCH\`, so this run falls back to \`main\`. If this is a paired change, push the NDR-matlab branch and re-run."
3960 fi
61+ echo "ref=$REF" >> "$GITHUB_OUTPUT"
62+ echo "NDR-matlab ref: $REF ($WHY)"
63+ {
64+ echo "### NDR-matlab checkout: \`$REF\`"
65+ echo
66+ echo "$WHY"
67+ } >> "$GITHUB_STEP_SUMMARY"
4068
4169 - name : Check out NDR-matlab (matching branch)
4270 uses : actions/checkout@v4
@@ -107,15 +135,29 @@ jobs:
107135 runner = TestRunner.withTextOutput("Verbosity", "Detailed");
108136 results = runner.run(suite);
109137
110- fprintf("\n=== MATLAB makeArtifacts: %d passed, %d failed ===\n", ...
111- nnz([results.Passed]), nnz([results.Failed]));
138+ fprintf("\n=== MATLAB makeArtifacts: %d passed, %d failed, %d incomplete ===\n", ...
139+ nnz([results.Passed]), nnz([results.Failed]), nnz([results.Incomplete]) );
112140 assert(all(~[results.Failed]), "MATLAB makeArtifacts failed")
113141
142+ % Incomplete = an assumption failed (a missing example file or
143+ % tool), so these artifacts were never made. Strict mode: fail.
144+ incomplete = results([results.Incomplete]);
145+ for k = 1:numel(incomplete)
146+ fprintf(2, "INCOMPLETE: %s\n", incomplete(k).Name);
147+ end
148+ assert(isempty(incomplete), ...
149+ "%d MATLAB makeArtifacts test(s) were Incomplete: their artifacts were never made.", ...
150+ numel(incomplete))
151+
114152 # -- Stage 2: Python readArtifacts (reads MATLAB artifacts) -----------
153+ # The pythonArtifacts cases cannot run yet -- Python makes those in
154+ # Stage 3 -- so they are deselected here rather than skipped (MATLAB
155+ # reads them in Stage 4). Every case left must run: under
156+ # NDR_SYMMETRY_CHECK_STRICT a skip fails.
115157 - name : " Stage 2: Python readArtifacts (reads MATLAB artifacts)"
116158 working-directory : NDR-python
117159 run : |
118- pytest tests/symmetry/read_artifacts/ -v --tb=short
160+ pytest tests/symmetry/read_artifacts/ -v --tb=short -k "not pythonArtifacts"
119161
120162 # -- Stage 3: Python makeArtifacts ------------------------------------
121163 - name : " Stage 3: Python makeArtifacts"
@@ -137,12 +179,36 @@ jobs:
137179 import matlab.unittest.TestRunner
138180
139181 suite = TestSuite.fromPackage("ndr.symmetry.readArtifacts", "IncludingSubpackages", true);
182+
183+ % KNOWN GAPS: MATLAB symmetry tests with no Python half, whose
184+ % pythonArtifacts case therefore cannot run. Deselected by name and
185+ % listed in the log, never left to come back Incomplete. Remove an
186+ % entry when its Python half lands.
187+ % readOmeZarr -- NDR-python has no OME-Zarr symmetry test yet.
188+ noPythonHalf = ["readOmeZarr"];
189+ gap = contains({suite.Name}, "SourceType=pythonArtifacts") & ...
190+ contains({suite.Name}, noPythonHalf);
191+ for k = find(gap)
192+ fprintf("Deselected (no Python half yet): %s\n", suite(k).Name);
193+ end
194+ suite = suite(~gap);
195+
140196 fprintf("\n=== MATLAB readArtifacts: %d test(s) ===\n", numel(suite));
141197 assert(~isempty(suite), "No MATLAB readArtifacts tests found.")
142198
143199 runner = TestRunner.withTextOutput("Verbosity", "Detailed");
144200 results = runner.run(suite);
145201
146- fprintf("\n=== MATLAB readArtifacts: %d passed, %d failed ===\n", ...
147- nnz([results.Passed]), nnz([results.Failed]));
202+ fprintf("\n=== MATLAB readArtifacts: %d passed, %d failed, %d incomplete ===\n", ...
203+ nnz([results.Passed]), nnz([results.Failed]), nnz([results.Incomplete]) );
148204 assert(all(~[results.Failed]), "MATLAB readArtifacts failed")
205+
206+ % Incomplete = the comparison did not run (the other suite's
207+ % artifacts were missing). Strict mode: fail.
208+ incomplete = results([results.Incomplete]);
209+ for k = 1:numel(incomplete)
210+ fprintf(2, "INCOMPLETE: %s\n", incomplete(k).Name);
211+ end
212+ assert(isempty(incomplete), ...
213+ "%d MATLAB readArtifacts test(s) were Incomplete: their comparison did not run.", ...
214+ numel(incomplete))
0 commit comments