Repository navigation
Read the arguments a wrapper gathers into a C array as one operand #463
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
| name: tests | |
| # Dogfoods the reusable provision-meos composite action, the single step every | |
| # binding uses to obtain the MEOS artifacts from one pinned MobilityDB commit. | |
| # The action builds and installs all-families libmeos (incl. pgPointCloud via | |
| # PGDG PG17) and derives output/meos-idl.json from the installed, self-contained | |
| # headers, then the pytest suite (type recovery + struct layout + portable | |
| # alias parity) runs against that catalog — the same catalog correctness signal | |
| # master had before, now produced by the shared action and FFI-accurate. | |
| on: | |
| pull_request: | |
| push: | |
| branches: [master] | |
| workflow_dispatch: | |
| jobs: | |
| tests: | |
| name: Build libmeos + regenerate catalog + pytest | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| # Build + install all-families libmeos and derive the catalog from the | |
| # installed headers — the exact step a native/FFI binding runs. | |
| - name: Provision the MEOS catalog and libmeos | |
| id: provision | |
| uses: ./.github/actions/provision-meos | |
| with: | |
| mobilitydb-ref: master | |
| build-libmeos: "true" | |
| - name: Assert libmeos.so is installed and print the family summary | |
| run: | | |
| test -f "${{ steps.provision.outputs.libmeos-prefix }}/lib/libmeos.so" | |
| echo "libmeos installed at ${{ steps.provision.outputs.libmeos-prefix }}/lib/libmeos.so" | |
| echo "----- cmake family summary -----" | |
| grep -E 'Including|Excluding' "$RUNNER_TEMP/cmake-configure.log" || true | |
| - name: Install pytest | |
| run: pip install pytest | |
| # PyMEOS is the object-model parity oracle. The audit reads its | |
| # factory.py and degrades to `oracle-unavailable` without it, so the two | |
| # parity gates assert nothing until it is on disk. | |
| - name: Check out the PyMEOS oracle | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: MobilityDB/PyMEOS | |
| path: _pymeos | |
| # The action wrote output/meos-idl.json at the repo root, exactly where | |
| # the suite loads it from; assert the advertised path and run the tests. | |
| # | |
| # Every environment variable here is a precondition some test guards on, | |
| # and a guard that fails makes the test SKIP: it asserts nothing and the | |
| # job still reports success. This job already had the material for all of | |
| # them and named none, so 11 of 268 tests never ran. | |
| # | |
| # MDB_SRC_ROOT the MobilityDB checkout the catalog came from; the | |
| # drift gates read meos_catalog.c and meos_error.h. | |
| # MEOS_LIBRARY_PATH the libmeos just built; the ctypes engine suite | |
| # decodes, invokes and round-trips against it. | |
| # MEOS_INCLUDE_DIR the installed headers; the vendored-provenance test | |
| # splits them by owner. | |
| # PYMEOS_FACTORY the parity oracle checked out above. | |
| # | |
| # Each is asserted before the run, so a moved path fails the job here | |
| # rather than turning into a silent skip. | |
| - name: Run the test suite | |
| env: | |
| MDB_SRC_ROOT: ${{ steps.provision.outputs.mobilitydb-src }} | |
| MEOS_LIBRARY_PATH: ${{ steps.provision.outputs.libmeos-prefix }}/lib/libmeos.so | |
| MEOS_INCLUDE_DIR: ${{ steps.provision.outputs.libmeos-prefix }}/include | |
| PYMEOS_FACTORY: ${{ github.workspace }}/_pymeos/pymeos/factory.py | |
| run: | | |
| set -o pipefail | |
| test -s "${{ steps.provision.outputs.catalog-path }}" | |
| test -f "$MDB_SRC_ROOT/meos/src/temporal/meos_catalog.c" | |
| test -f "$MEOS_LIBRARY_PATH" | |
| test -f "$MEOS_INCLUDE_DIR/meos.h" | |
| test -f "$PYMEOS_FACTORY" | |
| python3 -m pytest tests/ -v -rs | tee "$RUNNER_TEMP/pytest.log" | |
| # A skipped test is indistinguishable from a passing one in the job's | |
| # conclusion, which is how the eleven went unnoticed. Every precondition | |
| # is supplied and asserted above, so a skip now means a guard reads a | |
| # condition this job no longer satisfies — a defect, not a circumstance. | |
| # | |
| # The floor is the second half, and it guards what the skip count cannot | |
| # see: a test the run never collects is reported nowhere, so removing one | |
| # leaves the skip count at zero while coverage leaves. Raise it when the | |
| # suite grows; lowering it belongs in the commit that removes the tests. | |
| # Run the script from this checkout rather than through the action, which | |
| # would fetch master: a pull request must be checked by the rules it | |
| # carries, or a change to them is not exercised until after it merges. | |
| # Consumers use the action; this repository owns the rules. | |
| - name: Refuse a skip, and a suite that shrank | |
| run: tools/check-test-outcome.py "$RUNNER_TEMP/pytest.log" --min-tests 547 | |
| # The rules earn their place by refusing a log that carries what they | |
| # name. Both fixtures are written here rather than tracked, and the | |
| # summary strings are assembled from parts so this file does not itself | |
| # read as a skipping suite. | |
| - name: Prove the check can fail | |
| run: | | |
| set -e | |
| SK="skip""ped" | |
| printf '===== 257 passed, 11 %s in 13.58s =====\n' "$SK" > "$RUNNER_TEMP/fx-skip.log" | |
| if tools/check-test-outcome.py "$RUNNER_TEMP/fx-skip.log" --min-tests 268; then | |
| echo "::error::the check passed a log reporting skips and a shrunken suite" | |
| exit 1 | |
| fi | |
| printf '===== 267 passed in 13.58s =====\n' > "$RUNNER_TEMP/fx-shrank.log" | |
| if tools/check-test-outcome.py "$RUNNER_TEMP/fx-shrank.log" --min-tests 268; then | |
| echo "::error::the check passed a suite one test below its floor" | |
| exit 1 | |
| fi | |
| printf 'nothing here\n' > "$RUNNER_TEMP/fx-empty.log" | |
| if tools/check-test-outcome.py "$RUNNER_TEMP/fx-empty.log" --min-tests 268; then | |
| echo "::error::the check passed a log carrying no summary at all" | |
| exit 1 | |
| fi | |
| # The Go dialect, which MobilityAPI tees. It carries no counts of its | |
| # own: the totals are the tally of the result lines `go test -v` | |
| # writes, subtests included. The positive control comes first, so a | |
| # regex that matched nothing would fail here rather than read as a | |
| # clean log below. | |
| { | |
| printf -- '--- PASS: TestOne (0.01s)\n' | |
| printf -- ' --- PASS: TestOne/case (0.00s)\n' | |
| printf -- '--- PASS: TestTwo (0.00s)\n' | |
| } > "$RUNNER_TEMP/fx-go-ok.log" | |
| if ! tools/check-test-outcome.py "$RUNNER_TEMP/fx-go-ok.log" --min-tests 3; then | |
| echo "::error::the check refused a Go log that satisfies both rules" | |
| exit 1 | |
| fi | |
| { | |
| cat "$RUNNER_TEMP/fx-go-ok.log" | |
| printf -- '--- SK''IP: TestThree (0.00s)\n' | |
| } > "$RUNNER_TEMP/fx-go-skip.log" | |
| if tools/check-test-outcome.py "$RUNNER_TEMP/fx-go-skip.log" --min-tests 3; then | |
| echo "::error::the check passed a Go log reporting a skip" | |
| exit 1 | |
| fi | |
| if tools/check-test-outcome.py "$RUNNER_TEMP/fx-go-ok.log" --min-tests 4; then | |
| echo "::error::the check passed a Go suite below its floor" | |
| exit 1 | |
| fi | |
| printf 'ok \tgithub.com/x/y\t0.42s\n' > "$RUNNER_TEMP/fx-go-quiet.log" | |
| if tools/check-test-outcome.py "$RUNNER_TEMP/fx-go-quiet.log" --min-tests 3; then | |
| echo "::error::the check passed a Go log written without -v, which carries no counts" | |
| exit 1 | |
| fi | |
| # The VSTest dialect, which MEOS.NET tees. An assembly holding no | |
| # test at all writes no summary and exits 0, so the log it leaves is | |
| # the thing to refuse. | |
| printf 'Passed! - Failed: 0, Passed: 38, Skip''ped: 0, Total: 38, Duration: 182 ms - A.dll (net8.0)\n' \ | |
| > "$RUNNER_TEMP/fx-vstest-ok.log" | |
| if ! tools/check-test-outcome.py "$RUNNER_TEMP/fx-vstest-ok.log" --min-tests 38; then | |
| echo "::error::the check refused a VSTest log that satisfies both rules" | |
| exit 1 | |
| fi | |
| if tools/check-test-outcome.py "$RUNNER_TEMP/fx-vstest-ok.log" --min-tests 39; then | |
| echo "::error::the check passed a VSTest suite below its floor" | |
| exit 1 | |
| fi | |
| printf 'Failed! - Failed: 0, Passed: 36, Skip''ped: 2, Total: 38, Duration: 190 ms - A.dll (net8.0)\n' \ | |
| > "$RUNNER_TEMP/fx-vstest-skip.log" | |
| if tools/check-test-outcome.py "$RUNNER_TEMP/fx-vstest-skip.log" --min-tests 38; then | |
| echo "::error::the check passed a VSTest log reporting skips" | |
| exit 1 | |
| fi | |
| printf 'No test is available in /src/A.dll. Make sure that test discoverer & executors are registered.\n' \ | |
| > "$RUNNER_TEMP/fx-vstest-empty.log" | |
| if tools/check-test-outcome.py "$RUNNER_TEMP/fx-vstest-empty.log" --min-tests 1; then | |
| echo "::error::the check passed a VSTest run over an assembly holding no test" | |
| exit 1 | |
| fi | |
| # The Catch2 dialect, which the DuckDB test runner writes and a | |
| # MobilityDuck suite tees. The passing form's test-case count | |
| # EXCLUDES the skipped cases, so the floor is read off the sum. | |
| printf 'All tests passed (2695 assertions in 102 test cases)\n' \ | |
| > "$RUNNER_TEMP/fx-catch-ok.log" | |
| if ! tools/check-test-outcome.py "$RUNNER_TEMP/fx-catch-ok.log" --min-tests 102; then | |
| echo "::error::the check refused a Catch2 log that satisfies both rules" | |
| exit 1 | |
| fi | |
| if tools/check-test-outcome.py "$RUNNER_TEMP/fx-catch-ok.log" --min-tests 103; then | |
| echo "::error::the check passed a Catch2 suite below its floor" | |
| exit 1 | |
| fi | |
| printf 'All tests passed (3 skip''ped tests, 2695 assertions in 99 test cases)\n' \ | |
| > "$RUNNER_TEMP/fx-catch-skip.log" | |
| if tools/check-test-outcome.py "$RUNNER_TEMP/fx-catch-skip.log" --min-tests 102; then | |
| echo "::error::the check passed a Catch2 log reporting skipped tests" | |
| exit 1 | |
| fi | |
| # The failure table carries `101 passed`, which the pytest pattern | |
| # matches too; reading it as pytest would report 101 as the total. | |
| printf 'test cases: 102 | 101 passed | 1 failed\n' \ | |
| > "$RUNNER_TEMP/fx-catch-table.log" | |
| if tools/check-test-outcome.py "$RUNNER_TEMP/fx-catch-table.log" --min-tests 102 \ | |
| | grep -q 'pytest'; then | |
| echo "::error::the check read a Catch2 failure table as pytest" | |
| exit 1 | |
| fi | |
| echo "the check refuses a skip, a shrunken suite, and a log with no summary, in every dialect it reads" | |
| - name: Upload meos-idl.json as artefact | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: meos-idl | |
| path: output/meos-idl.json | |
| if-no-files-found: error |