diff --git a/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/conftest.py b/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/conftest.py index 54d457a31..86e3d14df 100644 --- a/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/conftest.py +++ b/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/conftest.py @@ -15,7 +15,7 @@ import socket import struct import threading -from unittest.mock import MagicMock +from unittest.mock import MagicMock, patch import pytest @@ -388,6 +388,13 @@ def unregister_service(self, service_id: int, instance_id: int): ] +@pytest.fixture(autouse=True) +def _mock_get_ext(): + """Ensure the native-extension guard passes in all tests by default.""" + with patch("jumpstarter_driver_someip.driver.get_ext", return_value=object()): + yield + + @pytest.fixture def stateful_osip(): """Provide a fresh StatefulOsipClient instance.""" diff --git a/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/driver.py b/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/driver.py index 53f48f623..b78b79ad7 100755 --- a/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/driver.py +++ b/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/driver.py @@ -7,6 +7,10 @@ from opensomeip import ClientConfig, TransportMode from opensomeip import SomeIpClient as OsipClient +try: + from opensomeip._bridge import get_ext +except ImportError: + get_ext = lambda: None # noqa: E731 from opensomeip.message import Message from opensomeip.sd import SdConfig, ServiceInstance from opensomeip.transport import Endpoint @@ -91,6 +95,18 @@ def __post_init__(self): raise ValueError( f"Invalid transport_mode: {self.transport_mode!r}. Must be 'TCP' or 'UDP'." ) + + if get_ext() is None: + raise RuntimeError( + "opensomeip C++ extension (_opensomeip) is not available. " + "The SOME/IP driver requires the native extension for network I/O. " + "On macOS, rebuild with the system compiler: " + "CC=/usr/bin/clang CXX=/usr/bin/clang++ " + "pip install --no-cache-dir --force-reinstall --no-binary=opensomeip opensomeip. " + "On other platforms, reinstall opensomeip and ensure the C++ " + "build toolchain is available." + ) + mode = TransportMode.TCP if transport_upper == "TCP" else TransportMode.UDP local_ep = Endpoint(self.host, self.port) diff --git a/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/driver_test.py b/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/driver_test.py index 755fcf1a5..8e36a3416 100644 --- a/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/driver_test.py +++ b/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/driver_test.py @@ -345,6 +345,12 @@ def test_someip_invalid_port_type(): SomeIp(host="127.0.0.1", port="not_a_port") # ty: ignore[invalid-argument-type] +@patch("jumpstarter_driver_someip.driver.get_ext", return_value=None) +def test_someip_raises_when_native_extension_unavailable(_mock_get_ext): + with pytest.raises(RuntimeError, match=r"_opensomeip.*not available"): + SomeIp(host="127.0.0.1", port=30490) + + @patch("jumpstarter_driver_someip.driver.OsipClient") def test_someip_invalid_transport_mode(mock_osip_cls): mock_osip_cls.return_value = _make_mock_osip_client()