diff --git a/adbc_drivers_dev/make_checks.py b/adbc_drivers_dev/make_checks.py index eeb6899..a373fb3 100644 --- a/adbc_drivers_dev/make_checks.py +++ b/adbc_drivers_dev/make_checks.py @@ -67,12 +67,16 @@ def _read_linux_symbols_in_docker( ) -def check_linux_symbols(symbols: list[str], binary: Path, manylinux: str) -> None: +def check_linux_symbols( + symbols: list[str], binary: Path, manylinux: str, driver: str +) -> None: bad_symbols = [] + exported_symbols = set() for symbol in symbols: if " T " not in symbol: continue _, _, name = symbol.partition(" T ") + exported_symbols.add(name) if not name.startswith("Adbc"): bad_symbols.append(name) if bad_symbols: @@ -80,6 +84,16 @@ def check_linux_symbols(symbols: list[str], binary: Path, manylinux: str) -> Non f"{', '.join(bad_symbols[:3])}... ({len(bad_symbols)} symbols total) should not be exported from {binary}" ) + driver_init = f"AdbcDriver{driver.lower().capitalize()}Init" + missing_symbols = set() + for required_symbol in (driver_init, "AdbcDriverInit"): + if required_symbol not in exported_symbols: + missing_symbols.add(required_symbol) + if missing_symbols: + raise RuntimeError( + f"{', '.join(missing_symbols)} should be exported from {binary}" + ) + limits = { "manylinux2014": ("2.17", "3.4.19"), "manylinux_2_28": ("2.28", "3.4.32"), @@ -113,7 +127,7 @@ def _check_linux(make_env: MakeEnv, make_config: MakeConfig, binary: Path) -> No raise RuntimeError( "Cannot run Linux compatibility checks on non-Linux host without Docker" ) - check_linux_symbols(symbols, binary, make_config.manylinux) + check_linux_symbols(symbols, binary, make_config.manylinux, make_config.driver) def _check_macos(binary: Path) -> None: diff --git a/tests/test_make_checks.py b/tests/test_make_checks.py index 650ab38..73ab268 100644 --- a/tests/test_make_checks.py +++ b/tests/test_make_checks.py @@ -24,39 +24,86 @@ def test_check_linux_symbols_accepts_adbc_exports() -> None: [ "000000 T AdbcDatabaseNew", "000000 T AdbcConnectionInit", + "000000 T AdbcDriverInit", + "000000 T AdbcDriverMultiwordnameInit", " U external_symbol", "000000 B _cgo_runtime", ], Path("driver.so"), "manylinux2014", + "multiwordname", ) def test_check_linux_symbols_rejects_non_adbc_exports() -> None: with pytest.raises(RuntimeError, match="bad_symbol"): make_checks.check_linux_symbols( - ["000000 T AdbcDatabaseNew", "000000 T bad_symbol"], + [ + "000000 T AdbcDatabaseNew", + "000000 T AdbcDriverInit", + "000000 T AdbcDriverDriverInit", + "000000 T bad_symbol", + ], Path("driver.so"), "manylinux2014", + "driver", + ) + + +def test_check_linux_symbols_requires_driver_init() -> None: + with pytest.raises(RuntimeError, match="AdbcDriverMultiwordnameInit"): + make_checks.check_linux_symbols( + ["000000 T AdbcDriverInit", "000000 T AdbcDriverMultiWordNameInit"], + Path("libadbc_driver_multiwordname.so"), + "manylinux2014", + "multiwordname", + ) + + +def test_check_linux_symbols_requires_generic_driver_init() -> None: + with pytest.raises(RuntimeError, match="AdbcDriverInit"): + make_checks.check_linux_symbols( + ["000000 T AdbcDriverMultiwordnameInit"], + Path("libadbc_driver_multiwordname.so"), + "manylinux2014", + "multiwordname", ) def test_check_linux_symbols_enforces_manylinux_limits() -> None: with pytest.raises(RuntimeError, match="GLIBC_2.18"): make_checks.check_linux_symbols( - [" U function@GLIBC_2.18"], Path("driver.so"), "manylinux2014" + [ + "000000 T AdbcDriverInit", + "000000 T AdbcDriverDriverInit", + " U function@GLIBC_2.18", + ], + Path("driver.so"), + "manylinux2014", + "driver", ) make_checks.check_linux_symbols( - [" U function@GLIBC_2.28", " U function@GLIBCXX_3.4.32"], + [ + "000000 T AdbcDriverInit", + "000000 T AdbcDriverDriverInit", + " U function@GLIBC_2.28", + " U function@GLIBCXX_3.4.32", + ], Path("driver.so"), "manylinux_2_28", + "driver", ) def test_check_linux_symbols_rejects_unknown_policy() -> None: with pytest.raises(ValueError, match="Unsupported manylinux policy"): - make_checks.check_linux_symbols([], Path("driver.so"), "unknown") + make_checks.check_linux_symbols( + ["000000 T AdbcDriverInit", "000000 T AdbcDriverDriverInit"], + Path("driver.so"), + "unknown", + "driver", + ) def test_check_macos_rejects_new_deployment_target(