Skip to content

Commit b1fa276

Browse files
committed
refactor pytest markers and security plugins detection
1 parent d04aa4f commit b1fa276

19 files changed

Lines changed: 135 additions & 236 deletions

modules/01-operating-room/pyproject.toml

Lines changed: 0 additions & 9 deletions
This file was deleted.

modules/01-operating-room/tests/conftest.py

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,33 +25,27 @@
2525

2626

2727
def pytest_collection_modifyitems(config, items):
28-
"""Fail tests when prerequisites are missing instead of silently skipping."""
29-
fail_gui = pytest.mark.xfail(
28+
"""Skip tests when prerequisites are missing."""
29+
skip_gui = pytest.mark.skip(
3030
reason="No graphical display available (need DISPLAY or WAYLAND_DISPLAY)",
31-
strict=True,
32-
run=False,
3331
)
34-
fail_sec_artifacts = pytest.mark.xfail(
32+
skip_sec_artifacts = pytest.mark.skip(
3533
reason="Security artifacts not generated (run setup_security.py)",
36-
strict=True,
37-
run=False,
3834
)
39-
fail_sec_plugin = pytest.mark.xfail(
40-
reason="DDS Security plugin not fully installed "
41-
"(need libnddssecurity, OpenSSL, rti_license.dat)",
42-
strict=True,
43-
run=False,
35+
skip_sec_plugin = pytest.mark.skip(
36+
reason="DDS Security runtime probe failed",
4437
)
4538

4639
has_display = _has_display()
40+
module_items = [i for i in items if Path(i.fspath).is_relative_to(TESTS_DIR)]
4741

48-
for item in items:
42+
for item in module_items:
4943
if "gui" in item.keywords and not has_display:
50-
item.add_marker(fail_gui)
44+
item.add_marker(skip_gui)
5145
if "secure" in item.keywords and not _security_artifacts_exist():
52-
item.add_marker(fail_sec_artifacts)
46+
item.add_marker(skip_sec_artifacts)
5347
elif "secure" in item.keywords and not _security_plugin_available():
54-
item.add_marker(fail_sec_plugin)
48+
item.add_marker(skip_sec_plugin)
5549

5650

5751
@pytest.fixture(scope="session")

modules/01-operating-room/tests/module01_test_support.py

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import subprocess
2323
import sys
2424
import time
25+
from functools import lru_cache
2526
from pathlib import Path
2627

2728
# Make resource/python/ importable — the `scripts` package contains
@@ -33,6 +34,7 @@
3334
# Make src/ importable so tests can use generated Types module directly.
3435
sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "src"))
3536

37+
from scripts.security_utils import check_security
3638

3739
# ---------------------------------------------------------------------------
3840
# Path bootstrapping — mirror what the launch scripts do
@@ -67,28 +69,10 @@ def _security_artifacts_exist() -> bool:
6769
return any(domain_scope_dir.rglob("*.p7s"))
6870

6971

72+
@lru_cache(maxsize=1)
7073
def _security_plugin_available() -> bool:
71-
"""Return True when the DDS Security plugin is fully usable.
72-
73-
Requires:
74-
1. ``libnddssecurity`` shared library
75-
2. Bundled OpenSSL ``release/lib`` directory
76-
3. A valid ``rti_license.dat`` in NDDSHOME (Security Plugins are
77-
a licensed feature).
78-
"""
79-
nddshome = os.environ.get("NDDSHOME")
80-
if not nddshome:
81-
return False
82-
nddshome_path = Path(nddshome)
83-
has_plugin = bool(list(nddshome_path.glob("lib/*/libnddssecurity.*")))
84-
has_openssl = any(
85-
(arch / "release" / "lib").is_dir()
86-
for arch in nddshome_path.glob("third_party/openssl-*/*")
87-
)
88-
has_license = (nddshome_path / "rti_license.dat").is_file() and (
89-
(nddshome_path / "rti_license.dat").stat().st_size > 0
90-
)
91-
return has_plugin and has_openssl and has_license
74+
"""Return True when secure participant creation succeeds at runtime."""
75+
return check_security()
9276

9377

9478
# ---------------------------------------------------------------------------
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#
2+
# (c) 2026 Copyright, Real-Time Innovations, Inc. (RTI) All rights reserved.
3+
#
4+
# RTI grants Licensee a license to use, modify, compile, and create derivative
5+
# works of the software solely for use with RTI Connext DDS. Licensee may
6+
# redistribute copies of the software provided that all such copies are
7+
# subject to this license. The software is provided "as is", with no warranty
8+
# of any type, including any warranty for fitness for any purpose. RTI is
9+
# under no obligation to maintain or support the software. RTI shall not be
10+
# liable for any incidental or consequential damages arising out of the use or
11+
# inability to use the software.
12+
"""Build verification tests for Module 01.
13+
14+
Ensures the CMake build succeeds, expected binaries are produced,
15+
and the generated Python types are importable.
16+
"""
17+
18+
import sys
19+
from pathlib import Path
20+
21+
import pytest
22+
from module01_test_support import MODULE_DIR
23+
24+
sys.path.insert(0, str(MODULE_DIR.parent.parent / "resource" / "python"))
25+
from scripts import platform_setup
26+
27+
# ---------------------------------------------------------------------------
28+
# Build
29+
# ---------------------------------------------------------------------------
30+
31+
32+
class TestBuild:
33+
"""Validate that the project-level CMake build produced expected binaries."""
34+
35+
@pytest.mark.parametrize("binary", ["PatientSensor", "Orchestrator", "ArmController"])
36+
def test_binary_exists(self, binary: str):
37+
"""Compiled C++ binary exists and can be located."""
38+
exe = platform_setup.find_executable(binary)
39+
assert Path(exe).is_file(), f"Binary not found: {exe}"

modules/01-operating-room/tests/test_build_and_types.py

Lines changed: 0 additions & 170 deletions
This file was deleted.

modules/01-operating-room/tests/test_demo_flow.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ def test_vitals_flow_with_security(self, proc_manager_secure, dds_env_secure):
296296

297297

298298
@pytest.mark.secure
299+
@pytest.mark.gui
299300
class TestSecureAllApps:
300301
"""All C++ apps should launch successfully in secure mode."""
301302

modules/02-record-playback/pyproject.toml

Lines changed: 0 additions & 6 deletions
This file was deleted.

modules/02-record-playback/tests/conftest.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,13 @@
2525

2626

2727
def pytest_collection_modifyitems(config, items):
28-
"""Auto-skip all tests if Recording/Replay Service is not available."""
28+
"""Auto-skip @service-marked tests if Recording/Replay Service is not available."""
2929
if RECORDING_SERVICE and REPLAY_SERVICE:
3030
return
3131
skip = pytest.mark.skip(reason="RTI Recording/Replay Service not found in NDDSHOME/bin/")
3232
for item in items:
33-
item.add_marker(skip)
33+
if Path(item.fspath).is_relative_to(TESTS_DIR) and "service" in item.keywords:
34+
item.add_marker(skip)
3435

3536

3637
@pytest.fixture(scope="session")

modules/02-record-playback/tests/test_recording.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
)
2727

2828

29+
@pytest.mark.service
2930
@pytest.mark.slow
3031
class TestRecording:
3132
"""RTI Recording Service should capture data from running applications."""

modules/02-record-playback/tests/test_replay.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
SRC_DIR = MODULE_01_DIR / "src"
3434

3535

36+
@pytest.mark.service
3637
@pytest.mark.slow
3738
class TestReplay:
3839
"""RTI Replay Service should re-publish recorded data."""

0 commit comments

Comments
 (0)