diff --git a/flink-processor/docs/parity-status.md b/flink-processor/docs/parity-status.md index bf2650e..ffe002e 100644 --- a/flink-processor/docs/parity-status.md +++ b/flink-processor/docs/parity-status.md @@ -41,3 +41,16 @@ For comparability with the SQL-surface bindings, the facade is also matched agai - Addressable distinct C symbols: **1335**; bound by JMEOS: **1065**; exposed by the facade: **939** (88.2% of the JMEOS-bindable SQL surface). +## 5. Runtime symbol resolution + +Every facade method delegates to a libmeos symbol of the same name. Against a libmeos built with the extended modules (`-DCBUFFER=ON -DNPOINT=ON -DPOSE=ON -DRGEO=ON`), **2152 of 2160** facade methods resolve to an exported symbol. The following require a libmeos built from current MEOS sources: + +- `geog_from_binary` +- `nad_stbox_trgeo` +- `tcbuffer_from_mfjson` +- `tfloat_avg_value` +- `tnpoint_from_mfjson` +- `trgeo_points` +- `trgeo_rotation` +- `trgeo_segments` + diff --git a/flink-processor/src/test/java/org/mobilitydb/flink/meos/MeosFacadeSmokeTest.java b/flink-processor/src/test/java/org/mobilitydb/flink/meos/MeosFacadeSmokeTest.java index 93165d7..b116f65 100644 --- a/flink-processor/src/test/java/org/mobilitydb/flink/meos/MeosFacadeSmokeTest.java +++ b/flink-processor/src/test/java/org/mobilitydb/flink/meos/MeosFacadeSmokeTest.java @@ -40,6 +40,14 @@ void coreTbox() { assertTrue(MeosOpsTBox.tbox_out(tbox, 6).contains("TBOX")); } + @Test + void coreIntspan() { + Pointer span = MeosOpsIntSpan.intspan_in("[1, 5)"); + assertNotNull(span); + String out = MeosOpsIntSpan.intspan_out(span); + assertTrue(out.contains("1") && out.contains("5")); + } + @Test void geoStbox() { Pointer stbox = MeosOpsSTBox.stbox_in("STBOX X((1,1),(2,2))"); @@ -75,5 +83,6 @@ void pose() { Pointer pose = MeosOpsFreePose.pose_in("Pose(Point(1 1), 0.5)"); assertNotNull(pose); assertNotNull(MeosOpsFreePose.pose_out(pose, 6)); + assertEquals(0.5, MeosOpsFreePose.pose_rotation(pose), 1e-9); } } diff --git a/flink-processor/tools/parity/parity_audit.py b/flink-processor/tools/parity/parity_audit.py index 7548738..5596e59 100644 --- a/flink-processor/tools/parity/parity_audit.py +++ b/flink-processor/tools/parity/parity_audit.py @@ -69,6 +69,11 @@ def facade_methods(d): return syms +def libmeos_symbols(path): + out = subprocess.run(["nm", "-D", path], capture_output=True, text=True).stdout + return {line.split()[-1] for line in out.splitlines() if line.strip()} + + def public_surface(inc): fam, allpub = {}, set() for h in PUBLIC_HEADERS: @@ -106,10 +111,14 @@ def main(): ap.add_argument("--facade", default=os.path.join(here, "src/main/java/org/mobilitydb/flink/meos")) ap.add_argument("--mdb-sql", default="/home/esteban/src/MobilityDB/mobilitydb/sql") ap.add_argument("--out", default=os.path.join(here, "docs", "parity-status.md")) + ap.add_argument("--libmeos", default=None, + help="path to a built libmeos.so; cross-checks that every facade method " + "resolves to an exported symbol (runtime resolution check)") a = ap.parse_args() jm = jmeos_symbols(a.jar) - fa = facade_methods(a.facade) & jm + fa_all = facade_methods(a.facade) + fa = fa_all & jm pub, fam = public_surface(a.meos_include) bindable = pub & jm covered = bindable & fa @@ -178,6 +187,21 @@ def main(): f"exposed by the facade: **{sql_cov}** " f"({pct(sql_cov, sql_bindable):.1f}% of the JMEOS-bindable SQL surface).\n") + if a.libmeos: + libsyms = libmeos_symbols(a.libmeos) + resolved = fa_all & libsyms + unresolved = sorted(fa_all - libsyms) + L.append("## 5. Runtime symbol resolution\n") + L.append("Every facade method delegates to a libmeos symbol of the same name. Against a " + "libmeos built with the extended modules (`-DCBUFFER=ON -DNPOINT=ON -DPOSE=ON " + "-DRGEO=ON`), " + f"**{len(resolved)} of {len(fa_all)}** facade methods resolve to an exported " + "symbol. The following require a libmeos built from current MEOS sources:\n") + L.append(("\n".join(f"- `{n}`" for n in unresolved) if unresolved + else "- (none — all facade methods resolve)") + "\n") + print(f"libmeos resolution: {len(resolved)}/{len(fa_all)} " + f"({len(unresolved)} unresolved)") + md = "\n".join(L) + "\n" os.makedirs(os.path.dirname(a.out), exist_ok=True) open(a.out, "w").write(md)