From 3f74f3d9e3793fe9f92a8714e591c9b6d0b3e12b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20Zim=C3=A1nyi?= Date: Tue, 8 Sep 2026 00:14:54 +0200 Subject: [PATCH 1/2] Project the surface MEOS publishes today MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The generated surface is the catalog's projection at MobilityDB 79a66f4576902b933481883443334c67edccf607. `geo_meos_supported` and `geom_meos_supported` leave it and `geo_meos_coverage` and `geom_meos_coverage` take their place, answering an `int` where the pair answered a `bool`: MEOS declares the two names in no header and `libmeos.so` defines neither symbol, so the wrappers naming them resolve nothing at load. The committed snapshot is what a consumer of this repository compiles, and the suite's own `EveryDeclaredEntryPointResolvesInTheLoadedMeos` reads the pair against the loaded library — `MEOS exports none of: geo_meos_supported, geom_meos_supported` is the failure a caller would otherwise meet as an `EntryPointNotFoundException` on the call itself. `GAP-LEDGER.md` follows the same two names into its nullability rows and records the commit it is derived from. The build takes 0 warnings and the suite passes 67 of 67 with none skipped. --- GAP-LEDGER.md | 6 +++--- MEOS.NET/Functions/Meos.Native.g.cs | 10 ++++------ MEOS.NET/Functions/Meos.meos_internal_geo.g.cs | 8 ++++---- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/GAP-LEDGER.md b/GAP-LEDGER.md index ca7d2a6..87c5b2c 100644 --- a/GAP-LEDGER.md +++ b/GAP-LEDGER.md @@ -10,7 +10,7 @@ A kind with no rows is a site the generators watch and that nothing reached in this run. It prints so that an empty class reads as a measurement rather than as a class nobody looked at. -Generated from `meos-idl.json` at MobilityDB `d64dcffecee20e939ab227a4dbf8943b551030f4` by `tools/codegen.py` +Generated from `meos-idl.json` at MobilityDB `79a66f4576902b933481883443334c67edccf607` by `tools/codegen.py` and `tools/objectgen.py`. Do not edit. @@ -911,7 +911,7 @@ and `tools/objectgen.py`. Do not edit. | geo_is_point_set | gs | | geo_is_unitary | gs | | geo_makeline_garray | gsarr | -| geo_meos_supported | gs | +| geo_meos_coverage | gs | | geo_num_geos | gs | | geo_num_points | gs | | geo_out | gs | @@ -977,7 +977,7 @@ and `tools/objectgen.py`. Do not edit. | geom_is_simple | gs | | geom_length | gs | | geom_max_distance2d | gs1, gs2 | -| geom_meos_supported | geom | +| geom_meos_coverage | geom | | geom_min_bounding_radius | geom, radius | | geom_oriented_envelope | gs | | geom_perimeter | gs | diff --git a/MEOS.NET/Functions/Meos.Native.g.cs b/MEOS.NET/Functions/Meos.Native.g.cs index fffe186..e2ad488 100644 --- a/MEOS.NET/Functions/Meos.Native.g.cs +++ b/MEOS.NET/Functions/Meos.Native.g.cs @@ -9233,9 +9233,8 @@ private static partial class Native [return: MarshalAs(UnmanagedType.U1)] internal static partial bool GeoIsPointSet(IntPtr gs); - [LibraryImport(DllPath, EntryPoint = "geo_meos_supported", StringMarshalling = StringMarshalling.Utf8)] - [return: MarshalAs(UnmanagedType.U1)] - internal static partial bool GeoMeosSupported(IntPtr gs); + [LibraryImport(DllPath, EntryPoint = "geo_meos_coverage", StringMarshalling = StringMarshalling.Utf8)] + internal static partial int GeoMeosCoverage(IntPtr gs); [LibraryImport(DllPath, EntryPoint = "geo_points_covered", StringMarshalling = StringMarshalling.Utf8)] internal static partial IntPtr GeoPointsCovered(IntPtr pts, IntPtr gs, [MarshalAs(UnmanagedType.U1)] bool covered); @@ -9276,9 +9275,8 @@ private static partial class Native [LibraryImport(DllPath, EntryPoint = "tpoint_linear_restrict_geom", StringMarshalling = StringMarshalling.Utf8)] internal static partial IntPtr TpointLinearRestrictGeom(IntPtr temp, IntPtr gs, [MarshalAs(UnmanagedType.U1)] bool atfunc); - [LibraryImport(DllPath, EntryPoint = "geom_meos_supported", StringMarshalling = StringMarshalling.Utf8)] - [return: MarshalAs(UnmanagedType.U1)] - internal static partial bool GeomMeosSupported(IntPtr geom); + [LibraryImport(DllPath, EntryPoint = "geom_meos_coverage", StringMarshalling = StringMarshalling.Utf8)] + internal static partial int GeomMeosCoverage(IntPtr geom); [LibraryImport(DllPath, EntryPoint = "stbox_nad", StringMarshalling = StringMarshalling.Utf8)] internal static partial double StboxNad(IntPtr box1, IntPtr box2); diff --git a/MEOS.NET/Functions/Meos.meos_internal_geo.g.cs b/MEOS.NET/Functions/Meos.meos_internal_geo.g.cs index 42de909..ec30694 100644 --- a/MEOS.NET/Functions/Meos.meos_internal_geo.g.cs +++ b/MEOS.NET/Functions/Meos.meos_internal_geo.g.cs @@ -267,8 +267,8 @@ public static bool GeoEveryPartBoundsArea(IntPtr gs) public static bool GeoIsPointSet(IntPtr gs) => SafeExecution(() => Native.GeoIsPointSet(gs)); - public static bool GeoMeosSupported(IntPtr gs) - => SafeExecution(() => Native.GeoMeosSupported(gs)); + public static int GeoMeosCoverage(IntPtr gs) + => SafeExecution(() => Native.GeoMeosCoverage(gs)); public static IntPtr GeoPointsCovered(IntPtr pts, IntPtr gs, bool covered) => SafeExecution(() => Native.GeoPointsCovered(pts, gs, covered)); @@ -306,8 +306,8 @@ public static IntPtr TpointLinearDistanceGeom(IntPtr temp, IntPtr gs) public static IntPtr TpointLinearRestrictGeom(IntPtr temp, IntPtr gs, bool atfunc) => SafeExecution(() => Native.TpointLinearRestrictGeom(temp, gs, atfunc)); - public static bool GeomMeosSupported(IntPtr geom) - => SafeExecution(() => Native.GeomMeosSupported(geom)); + public static int GeomMeosCoverage(IntPtr geom) + => SafeExecution(() => Native.GeomMeosCoverage(geom)); public static double StboxNad(IntPtr box1, IntPtr box2) => SafeExecution(() => Native.StboxNad(box1, box2)); From 6be7e5e0314d8b725d5a010fefe815aa7db96587 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20Zim=C3=A1nyi?= Date: Tue, 8 Sep 2026 00:06:55 +0200 Subject: [PATCH 2/2] Make a skipped test impossible to write MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `MEOS.NET.Tests/BannedSymbols.txt` names every construct MSTest offers for stopping a test from asserting — the `[Ignore]` attribute and the three `Assert.Inconclusive` overloads — and `RS0030` is an error in the test project, so each one fails the build rather than reaching a reviewer, a log or a count. A skipped test asserts nothing and reads as a pass in the conclusion, which is why the construct is refused at the compiler rather than tallied afterwards. Deleting a test is then the only remaining way to stop running it, and that leaves no skip behind. What moves is the total, so the workflow reads the run through `MobilityDB/MEOS-API/.github/actions/check-test-outcome` against a floor of 67: the same rules every other binding in the ecosystem is held to, from the one runnable definition, so the CI answer and the answer a developer gets by hand cannot differ. The run the floor is taken from collects the whole suite — the snapshot step above it narrows with `--filter` deliberately and no count is read from that one. Four refuters, each measured. `[Ignore("refuter")]` on a test takes `error RS0030: The symbol 'IgnoreAttribute' is banned in this project`, and `Assert.Inconclusive("refuter")` in a body takes the same error naming `Assert.Inconclusive(string?)`; both read `Build FAILED`. Against the suite's own log the guard reads `total=67 skipped=0 floor=67` and passes, while a floor of 68 is refused as a shrinking suite and a log whose summary carries `Skipped: 1` is refused as a skip. Without all four the pair would be configuration rather than enforcement. The suite passes 67 of 67 with none skipped, and the build takes 0 warnings. --- .github/workflows/ci.yml | 16 +++++++++++++++- MEOS.NET.Tests/BannedSymbols.txt | 14 ++++++++++++++ MEOS.NET.Tests/MEOS.NET.Tests.csproj | 15 +++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 MEOS.NET.Tests/BannedSymbols.txt diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9ce9679..4af2703 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -53,11 +53,25 @@ jobs: - name: Build solution run: dotnet build MEOS.NET.sln -c Release + # No --filter here: this run is the one the floor below is read from, so it + # collects the whole suite. The snapshot step above narrows deliberately and + # its result is not what any count is taken from. - name: Run tests - run: dotnet test MEOS.NET.sln -c Release --no-build + run: dotnet test MEOS.NET.sln -c Release --no-build 2>&1 | tee test.log env: LD_LIBRARY_PATH: ${{ steps.provision.outputs.libmeos-prefix }}/lib + # A skip is already impossible to WRITE — MEOS.NET.Tests/BannedSymbols.txt + # makes [Ignore] and Assert.Inconclusive compile errors. Deleting a test is + # the remaining way to stop running it, and that leaves no skip behind, so + # the total carries a floor. Raise it when the suite grows; lowering it is a + # deliberate act belonging to the commit that removes the tests. + - name: Refuse a skipped test and a shrinking suite + uses: MobilityDB/MEOS-API/.github/actions/check-test-outcome@master + with: + log: test.log + min-tests: "67" + - name: Smoke-test the FFI run: dotnet run --project ExampleApp/ExampleApp.csproj -c Release --no-build env: diff --git a/MEOS.NET.Tests/BannedSymbols.txt b/MEOS.NET.Tests/BannedSymbols.txt new file mode 100644 index 0000000..1dd9d7a --- /dev/null +++ b/MEOS.NET.Tests/BannedSymbols.txt @@ -0,0 +1,14 @@ +; Every way MSTest lets a test stop asserting while the run still reports success. +; BannedApiAnalyzers resolves each entry to a symbol and RS0030 is an ERROR here, so a +; skip does not reach a reviewer, a CI log or a floor — it fails to compile. +; +; A skipped test asserts nothing and reads as a pass in the conclusion, which is the +; whole reason the construct is banned rather than merely counted. Deleting a test is +; then the only remaining way to stop running it, and that moves the total, which the +; floor in the workflow refuses. +; +; Format: ;. +T:Microsoft.VisualStudio.TestTools.UnitTesting.IgnoreAttribute;A test that does not run asserts nothing. Fix or delete the test — the suite carries no skips. +M:Microsoft.VisualStudio.TestTools.UnitTesting.Assert.Inconclusive;Inconclusive reports as skipped and reads as a pass. Assert the real outcome, or delete the test. +M:Microsoft.VisualStudio.TestTools.UnitTesting.Assert.Inconclusive(System.String);Inconclusive reports as skipped and reads as a pass. Assert the real outcome, or delete the test. +M:Microsoft.VisualStudio.TestTools.UnitTesting.Assert.Inconclusive(System.String,System.Object[]);Inconclusive reports as skipped and reads as a pass. Assert the real outcome, or delete the test. diff --git a/MEOS.NET.Tests/MEOS.NET.Tests.csproj b/MEOS.NET.Tests/MEOS.NET.Tests.csproj index 482dde7..fee9a44 100644 --- a/MEOS.NET.Tests/MEOS.NET.Tests.csproj +++ b/MEOS.NET.Tests/MEOS.NET.Tests.csproj @@ -7,6 +7,12 @@ false true + + + $(WarningsAsErrors);RS0030 @@ -14,6 +20,15 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + +