From 84a9bdb49aee240d24b99582d233b42eb2c40601 Mon Sep 17 00:00:00 2001 From: XuPeng-SH Date: Wed, 21 Oct 2026 03:42:19 +0800 Subject: [PATCH 1/2] fix(ci): locate native libraries in coverage test executables --- .github/workflows/check-action-file.yaml | 3 ++ .github/workflows/coverage-ut.yaml | 2 +- scripts/test_coverage_native_runtime.py | 61 ++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 scripts/test_coverage_native_runtime.py diff --git a/.github/workflows/check-action-file.yaml b/.github/workflows/check-action-file.yaml index f76b18e..3f33d2c 100644 --- a/.github/workflows/check-action-file.yaml +++ b/.github/workflows/check-action-file.yaml @@ -16,6 +16,7 @@ on: - 'actions/upload-artifact-with-retry/state-machine.schema.json' - 'scripts/select_coverage_artifacts.py' - 'scripts/test_select_coverage_artifacts.py' + - 'scripts/test_coverage_native_runtime.py' - 'scripts/test_merge_trigger_tke_subject.py' - 'scripts/compact_coverage_profile.go' - 'scripts/compact_coverage_profile_test.go' @@ -83,6 +84,8 @@ jobs: scripts/compact_coverage_profile_test.go - name: Test coverage artifact generation selection run: python3 scripts/test_select_coverage_artifacts.py -v + - name: Test coverage native runtime paths + run: python3 scripts/test_coverage_native_runtime.py -v - name: Test TKE merge subject identity contract run: python3 scripts/test_merge_trigger_tke_subject.py -v - name: Test SCA license scope selection diff --git a/.github/workflows/coverage-ut.yaml b/.github/workflows/coverage-ut.yaml index 3ae558d..be572f0 100644 --- a/.github/workflows/coverage-ut.yaml +++ b/.github/workflows/coverage-ut.yaml @@ -350,7 +350,7 @@ jobs: (( phase_status == 0 )) || exit "${phase_status}" thirdparties_install_dir="$GITHUB_WORKSPACE/thirdparties/install" cgo_cflags="-I${GITHUB_WORKSPACE}/cgo -I${thirdparties_install_dir}/include" - cgo_ldflags="-L${GITHUB_WORKSPACE}/cgo -lmo -L${thirdparties_install_dir}/lib -lusearch_c -Wl,-rpath,${thirdparties_install_dir}/lib -lm" + cgo_ldflags="-L${GITHUB_WORKSPACE}/cgo -lmo -Wl,-rpath,${GITHUB_WORKSPACE}/cgo -L${thirdparties_install_dir}/lib -lusearch_c -Wl,-rpath,${thirdparties_install_dir}/lib -lm" # Keep the same all-package coverage scope and external storage # coverage as main. Save the verbose JSON report as an artifact diff --git a/scripts/test_coverage_native_runtime.py b/scripts/test_coverage_native_runtime.py new file mode 100644 index 0000000..1f84c28 --- /dev/null +++ b/scripts/test_coverage_native_runtime.py @@ -0,0 +1,61 @@ +import os +from pathlib import Path +import re +import shlex +import subprocess +import tempfile +import unittest + + +class CoverageNativeRuntimeTest(unittest.TestCase): + def test_coverage_native_runtime_paths(self): + """Coverage executables must load both native locations without ambient LD paths.""" + temporary = tempfile.TemporaryDirectory() + self.addCleanup(temporary.cleanup) + tmp_path = Path(temporary.name) + workspace = tmp_path / "workspace" + cgo = workspace / "cgo" + thirdparty = workspace / "thirdparties" / "install" / "lib" + cgo.mkdir(parents=True) + thirdparty.mkdir(parents=True) + env = os.environ.copy() + env.pop("LD_LIBRARY_PATH", None) + env["GITHUB_WORKSPACE"] = str(workspace) + workflow = (Path(__file__).parents[1] / ".github/workflows/coverage-ut.yaml").read_text() + assignments = re.findall( + r"^ (?:thirdparties_install_dir|cgo_ldflags)=.*$", workflow, re.MULTILINE + ) + assert len(assignments) == 2 + flags = subprocess.check_output( + ["bash", "-eu", "-c", "\n".join(assignments) + '\nprintf "%s" "$cgo_ldflags"'], + env=env, + text=True, + ) + for name, directory, value in [("mo", cgo, 19), ("usearch_c", thirdparty, 23)]: + source = tmp_path / f"{name}.c" + source.write_text(f"int {name}_probe(void) {{ return {value}; }}\n") + subprocess.run( + ["cc", "-fPIC", "-shared", str(source), "-o", str(directory / f"lib{name}.so")], + check=True, + ) + source = tmp_path / "main.c" + source.write_text( + "int mo_probe(void); int usearch_c_probe(void);\n" + "int main(void) { return mo_probe() + usearch_c_probe() == 42 ? 0 : 1; }\n" + ) + for name, link_flags in [ + ("complete", flags), + ("missing_cgo_runtime_path", flags.replace(f"-Wl,-rpath,{cgo} ", "")), + ]: + binary = tmp_path / name + subprocess.run(["cc", str(source), *shlex.split(link_flags), "-o", str(binary)], check=True) + result = subprocess.run([str(binary)], cwd=tmp_path, env=env, capture_output=True, text=True) + if name == "complete": + assert result.returncode == 0, result.stderr + else: + assert result.returncode != 0 + assert "libmo.so" in result.stderr + + +if __name__ == "__main__": + unittest.main() From 430fe1fd42c1d40cdefeb5f246b7128eb9f5d327 Mon Sep 17 00:00:00 2001 From: XuPeng-SH Date: Wed, 21 Oct 2026 05:56:33 +0800 Subject: [PATCH 2/2] fix(coverage): include nightly native runtime path --- .github/workflows/robot.yaml | 2 +- scripts/test_coverage_native_runtime.py | 78 +++++++++++++++++-------- 2 files changed, 55 insertions(+), 25 deletions(-) diff --git a/.github/workflows/robot.yaml b/.github/workflows/robot.yaml index 771af4d..01b21af 100644 --- a/.github/workflows/robot.yaml +++ b/.github/workflows/robot.yaml @@ -172,7 +172,7 @@ jobs: test_scope=$(go list ./... | grep -v 'driver\|engine/aoe\|engine/memEngine\|pkg/catalog') make clean && make config && make cgo CGO_CFLAGS="-I${GITHUB_WORKSPACE}/matrixone/cgo" - CGO_LDFLAGS="-L${GITHUB_WORKSPACE}/matrixone/cgo -lmo" + CGO_LDFLAGS="-L${GITHUB_WORKSPACE}/matrixone/cgo -lmo -Wl,-rpath,${GITHUB_WORKSPACE}/matrixone/cgo" THIRDPARTIES_DIR=$GITHUB_WORKSPACE/matrixone/thirdparties THIRDPARTIES_INSTALL_DIR=$THIRDPARTIES_DIR/install if [ -d $THIRDPARTIES_DIR ] ; then diff --git a/scripts/test_coverage_native_runtime.py b/scripts/test_coverage_native_runtime.py index 1f84c28..84fc59b 100644 --- a/scripts/test_coverage_native_runtime.py +++ b/scripts/test_coverage_native_runtime.py @@ -14,23 +14,13 @@ def test_coverage_native_runtime_paths(self): self.addCleanup(temporary.cleanup) tmp_path = Path(temporary.name) workspace = tmp_path / "workspace" - cgo = workspace / "cgo" - thirdparty = workspace / "thirdparties" / "install" / "lib" + repository = workspace / "matrixone" + cgo = repository / "cgo" + thirdparty = repository / "thirdparties" / "install" / "lib" cgo.mkdir(parents=True) thirdparty.mkdir(parents=True) env = os.environ.copy() env.pop("LD_LIBRARY_PATH", None) - env["GITHUB_WORKSPACE"] = str(workspace) - workflow = (Path(__file__).parents[1] / ".github/workflows/coverage-ut.yaml").read_text() - assignments = re.findall( - r"^ (?:thirdparties_install_dir|cgo_ldflags)=.*$", workflow, re.MULTILINE - ) - assert len(assignments) == 2 - flags = subprocess.check_output( - ["bash", "-eu", "-c", "\n".join(assignments) + '\nprintf "%s" "$cgo_ldflags"'], - env=env, - text=True, - ) for name, directory, value in [("mo", cgo, 19), ("usearch_c", thirdparty, 23)]: source = tmp_path / f"{name}.c" source.write_text(f"int {name}_probe(void) {{ return {value}; }}\n") @@ -43,18 +33,58 @@ def test_coverage_native_runtime_paths(self): "int mo_probe(void); int usearch_c_probe(void);\n" "int main(void) { return mo_probe() + usearch_c_probe() == 42 ? 0 : 1; }\n" ) - for name, link_flags in [ - ("complete", flags), - ("missing_cgo_runtime_path", flags.replace(f"-Wl,-rpath,{cgo} ", "")), + for workflow_name, workspace_root, variables, assignment_count, result_variable in [ + ("coverage-ut.yaml", repository, "thirdparties_install_dir|cgo_ldflags", 2, "cgo_ldflags"), + ( + "robot.yaml", + workspace, + "CGO_LDFLAGS|THIRDPARTIES_DIR|THIRDPARTIES_INSTALL_DIR", + 4, + "CGO_LDFLAGS", + ), ]: - binary = tmp_path / name - subprocess.run(["cc", str(source), *shlex.split(link_flags), "-o", str(binary)], check=True) - result = subprocess.run([str(binary)], cwd=tmp_path, env=env, capture_output=True, text=True) - if name == "complete": - assert result.returncode == 0, result.stderr - else: - assert result.returncode != 0 - assert "libmo.so" in result.stderr + with self.subTest(workflow=workflow_name): + env["GITHUB_WORKSPACE"] = str(workspace_root) + workflow = (Path(__file__).parents[1] / ".github/workflows" / workflow_name).read_text() + assignments = re.findall(r"^ +(?:" + variables + r")=.*$", workflow, re.MULTILINE) + self.assertEqual(len(assignments), assignment_count) + flags = subprocess.check_output( + [ + "bash", + "-eu", + "-c", + "\n".join(assignments) + '\nprintf "%s" "$' + result_variable + '"', + ], + env=env, + text=True, + ) + for name, link_flags, missing_library in [ + ("complete", flags, None), + ("missing_cgo_runtime_path", flags.replace(f"-Wl,-rpath,{cgo}", ""), "libmo.so"), + ( + "missing_thirdparty_runtime_path", + flags.replace(f"-Wl,-rpath,{thirdparty}", ""), + "libusearch_c.so", + ), + ]: + with self.subTest(workflow=workflow_name, runtime_path=name): + if missing_library is not None: + self.assertNotEqual(link_flags, flags, "negative control must remove its rpath") + binary = tmp_path / (workflow_name + "-" + name) + # The real Go cgo package supplies -lusearch_c even when + # the nightly workflow leaves it out of CGO_LDFLAGS. + subprocess.run( + ["cc", str(source), *shlex.split(link_flags), "-lusearch_c", "-o", str(binary)], + check=True, + ) + result = subprocess.run( + [str(binary)], cwd=tmp_path, env=env, capture_output=True, text=True + ) + if missing_library is None: + self.assertEqual(result.returncode, 0, result.stderr) + else: + self.assertNotEqual(result.returncode, 0) + self.assertIn(missing_library, result.stderr) if __name__ == "__main__":