Skip to content

Commit db58bfd

Browse files
committed
Added test cases for TestLifecycleApplicationIf
added test cases for lifecycle ipc alive security policy enforcement validation activation for dependency gated activation added test cases for failure diagnostics correlated added test cases for control IPC routing validation test cases for deadline monitore checkpoint IPC added test cases for validating timestamp consistency between lifecycle events and system time added test cases for run-target transitions remain synchronized with orchestrator added test cases for validating supervision and monitoring isolation across multiple Launch Manager instances test case added for invalid lifecycle configuration added test cases for baselibs requirements local review fixes
1 parent b2ae791 commit db58bfd

44 files changed

Lines changed: 3376 additions & 13 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

BUILD

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# *******************************************************************************
1313

1414
load("@score_docs_as_code//:docs.bzl", "docs")
15-
load("@score_tooling//:defs.bzl", "setup_starpls", "use_format_targets")
15+
load("@score_tooling//:defs.bzl", "copyright_checker", "setup_starpls", "use_format_targets")
1616

1717
# Docs-as-code
1818
docs(
@@ -44,6 +44,38 @@ setup_starpls(
4444
# Add target for formatting checks
4545
use_format_targets()
4646

47+
# Add copyright check/fix targets:
48+
# - //:copyright.check
49+
# - //:copyright.fix
50+
copyright_checker(
51+
name = "copyright",
52+
srcs = glob(
53+
["**/*"],
54+
exclude = [
55+
".git/**",
56+
".venv/**",
57+
"bazel-*/**",
58+
"**/*.png",
59+
"**/*.jpg",
60+
"**/*.jpeg",
61+
"**/*.gif",
62+
"**/*.svg",
63+
"**/*.pdf",
64+
"**/*.drawio",
65+
"**/*.ipynb",
66+
"**/*.bin",
67+
"**/*.hash",
68+
"**/*.zip",
69+
"**/*.tar",
70+
"**/*.tar.gz",
71+
"**/*.tgz",
72+
],
73+
),
74+
config = "@score_tooling//cr_checker/resources:config",
75+
template = "@score_tooling//cr_checker/resources:templates",
76+
visibility = ["//visibility:public"],
77+
)
78+
4779
exports_files([
4880
"MODULE.bazel",
4981
"pyproject.toml",

README.md

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,30 @@ To generate a full documentation of all integrated modules, run:
6161
bazel run //:docs_combo_experimental
6262
```
6363

64+
## Feature Integration Tests (FIT)
65+
66+
Use the Linux config for both Rust and C++ FIT flows:
67+
68+
```bash
69+
bazel test --config=linux-x86_64 //feature_integration_tests/test_cases:fit
70+
bazel test --config=linux-x86_64 //feature_integration_tests/test_cases:fit_rust
71+
bazel test --config=linux-x86_64 //feature_integration_tests/test_cases:fit_cpp
72+
```
73+
74+
Run only lifecycle application interface checks:
75+
76+
```bash
77+
bazel test --config=linux-x86_64 //feature_integration_tests/test_cases:fit_rust --test_arg=-k --test_arg=lifecycle_application_if
78+
bazel test --config=linux-x86_64 //feature_integration_tests/test_cases:fit_cpp --test_arg=-k --test_arg=lifecycle_application_if
79+
```
80+
81+
Build scenario binaries directly:
82+
83+
```bash
84+
bazel build --config=linux-x86_64 //feature_integration_tests/test_scenarios/rust:rust_test_scenarios
85+
bazel build --config=linux-x86_64 //feature_integration_tests/test_scenarios/cpp:cpp_test_scenarios
86+
```
87+
6488
## Operating system integrations
6589

6690
> [!NOTE]
@@ -71,7 +95,7 @@ bazel run //:docs_combo_experimental
7195
- [Elektrobit corbos Linux for Safety Applications](./images/ebclfsa_aarch64/README.md)
7296
- Linux x86_64
7397

74-
## Workspace support
98+
## Workspace support
7599

76100
You can obtain a complete S-CORE workspace, i.e. a git checkout of all modules from `known_good.json`, on the specific branches / commits, integrated into one Bazel build.
77101
This helps with cross-module development, debugging, and generally "trying out things".

feature_integration_tests/README.md

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,40 @@ bazel test --config=linux-x86_64 //feature_integration_tests/test_cases:fit
3232
To run specific test suites:
3333

3434
```sh
35-
bazel test //feature_integration_tests/test_cases:fit_rust
35+
bazel test --config=linux-x86_64 //feature_integration_tests/test_cases:fit_rust
3636
bazel test --config=linux-x86_64 //feature_integration_tests/test_cases:fit_cpp
3737
```
3838

39+
To run lifecycle-focused FIT tests only:
40+
41+
```sh
42+
bazel test --config=linux-x86_64 //feature_integration_tests/test_cases:fit_rust --test_arg=-k --test_arg=lifecycle
43+
bazel test --config=linux-x86_64 //feature_integration_tests/test_cases:fit_cpp --test_arg=-k --test_arg=lifecycle
44+
```
45+
46+
To run only the new lifecycle application interface requirement test:
47+
48+
```sh
49+
bazel test --config=linux-x86_64 //feature_integration_tests/test_cases:fit_rust --test_arg=-k --test_arg=lifecycle_application_if
50+
bazel test --config=linux-x86_64 //feature_integration_tests/test_cases:fit_cpp --test_arg=-k --test_arg=lifecycle_application_if
51+
```
52+
53+
To build scenario binaries directly:
54+
55+
```sh
56+
bazel build --config=linux-x86_64 //feature_integration_tests/test_scenarios/rust:rust_test_scenarios
57+
bazel build --config=linux-x86_64 //feature_integration_tests/test_scenarios/cpp:cpp_test_scenarios
58+
```
59+
60+
When running pytest directly with scenario pre-build enabled, use an explicit Bazel config:
61+
62+
```sh
63+
python3 -m pytest feature_integration_tests/test_cases/tests/lifecycle/ --build-scenarios --bazel-config=linux-x86_64 -q -v
64+
65+
# or via env var
66+
FIT_BAZEL_CONFIG=linux-x86_64 python3 -m pytest feature_integration_tests/test_cases/tests/lifecycle/ --build-scenarios -q -v
67+
```
68+
3969
### ITF Tests (QEMU-based)
4070

4171
ITF tests run on a QEMU target and require the `itf-qnx-x86_64` config:
@@ -49,7 +79,7 @@ bazel test --config=itf-qnx-x86_64 //feature_integration_tests/itf
4979
Test scenarios can be listed and run directly for debugging:
5080

5181
```sh
52-
bazel run //feature_integration_tests/test_scenarios/rust:rust_test_scenarios -- --list-scenarios
82+
bazel run --config=linux-x86_64 //feature_integration_tests/test_scenarios/rust:rust_test_scenarios -- --list-scenarios
5383
bazel run --config=linux-x86_64 //feature_integration_tests/test_scenarios/cpp:cpp_test_scenarios -- --list-scenarios
5484
```
5585

feature_integration_tests/test_cases/conftest.py

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@
1010
#
1111
# SPDX-License-Identifier: Apache-2.0
1212
# *******************************************************************************
13+
import os
14+
import subprocess
1315
from pathlib import Path
1416

1517
import pytest
16-
from testing_utils import BazelTools
1718

1819

1920
# Cmdline options
@@ -61,6 +62,12 @@ def pytest_addoption(parser):
6162
default=180.0,
6263
help="Build command timeout in seconds. Default: %(default)s",
6364
)
65+
parser.addoption(
66+
"--bazel-config",
67+
type=str,
68+
default=os.environ.get("FIT_BAZEL_CONFIG", "linux-x86_64"),
69+
help=('Bazel config used when --build-scenarios is enabled (default: env FIT_BAZEL_CONFIG or "linux-x86_64").'),
70+
)
6471
parser.addoption(
6572
"--default-execution-timeout",
6673
type=float,
@@ -70,6 +77,12 @@ def pytest_addoption(parser):
7077

7178

7279
# Hooks
80+
def pytest_configure(config: pytest.Config) -> None:
81+
"""Register custom markers used by FIT parametrization."""
82+
config.addinivalue_line("markers", "cpp: mark scenario execution for C++ target")
83+
config.addinivalue_line("markers", "rust: mark scenario execution for Rust target")
84+
85+
7386
def pytest_collection_modifyitems(items: list[pytest.Function]):
7487
for item in items:
7588
# Automatically mark tests parametrized with 'version' as 'cpp' or 'rust'.
@@ -88,18 +101,35 @@ def pytest_sessionstart(session):
88101
# Build scenarios.
89102
if session.config.getoption("--build-scenarios"):
90103
build_timeout = session.config.getoption("--build-scenarios-timeout")
104+
bazel_config = session.config.getoption("--bazel-config")
105+
106+
def _build_target(target_name: str) -> None:
107+
command = ["bazel", "build", f"--config={bazel_config}", target_name]
108+
result = subprocess.run(
109+
command,
110+
capture_output=True,
111+
text=True,
112+
check=False,
113+
timeout=build_timeout,
114+
)
115+
if result.returncode != 0:
116+
stderr_tail = "\n".join(result.stderr.strip().splitlines()[-40:])
117+
raise RuntimeError(
118+
"Failed to run build with pytest --build-scenarios.\n"
119+
f"Command: {' '.join(command)}\n"
120+
f"Return code: {result.returncode}\n"
121+
f"stderr (last lines):\n{stderr_tail}"
122+
)
91123

92124
# Build Rust test scenarios.
93-
print("Building Rust test scenarios executable...")
94-
rust_tools = BazelTools(option_prefix="rust", build_timeout=build_timeout)
125+
print(f"Building Rust test scenarios executable with --config={bazel_config}...")
95126
rust_target_name = session.config.getoption("--rust-target-name")
96-
rust_tools.build(rust_target_name)
127+
_build_target(rust_target_name)
97128

98129
# Build C++ test scenarios.
99-
print("Building C++ test scenarios executable...")
100-
cpp_tools = BazelTools(option_prefix="cpp", build_timeout=build_timeout)
130+
print(f"Building C++ test scenarios executable with --config={bazel_config}...")
101131
cpp_target_name = session.config.getoption("--cpp-target-name")
102-
cpp_tools.build(cpp_target_name)
132+
_build_target(cpp_target_name)
103133

104134
except Exception as e:
105135
pytest.exit(str(e), returncode=1)

feature_integration_tests/test_cases/requirements.txt.lock

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,28 @@ packaging==25.0 \
9191
pluggy==1.6.0 \
9292
--hash=sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3 \
9393
--hash=sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746
94+
psutil==7.2.2 \
95+
--hash=sha256:0746f5f8d406af344fd547f1c8daa5f5c33dbc293bb8d6a16d80b4bb88f59372 \
96+
--hash=sha256:076a2d2f923fd4821644f5ba89f059523da90dc9014e85f8e45a5774ca5bc6f9 \
97+
--hash=sha256:11fe5a4f613759764e79c65cf11ebdf26e33d6dd34336f8a337aa2996d71c841 \
98+
--hash=sha256:1a571f2330c966c62aeda00dd24620425d4b0cc86881c89861fbc04549e5dc63 \
99+
--hash=sha256:1a7b04c10f32cc88ab39cbf606e117fd74721c831c98a27dc04578deb0c16979 \
100+
--hash=sha256:1fa4ecf83bcdf6e6c8f4449aff98eefb5d0604bf88cb883d7da3d8d2d909546a \
101+
--hash=sha256:2edccc433cbfa046b980b0df0171cd25bcaeb3a68fe9022db0979e7aa74a826b \
102+
--hash=sha256:7b6d09433a10592ce39b13d7be5a54fbac1d1228ed29abc880fb23df7cb694c9 \
103+
--hash=sha256:8c233660f575a5a89e6d4cb65d9f938126312bca76d8fe087b947b3a1aaac9ee \
104+
--hash=sha256:917e891983ca3c1887b4ef36447b1e0873e70c933afc831c6b6da078ba474312 \
105+
--hash=sha256:ab486563df44c17f5173621c7b198955bd6b613fb87c71c161f827d3fb149a9b \
106+
--hash=sha256:ae0aefdd8796a7737eccea863f80f81e468a1e4cf14d926bd9b6f5f2d5f90ca9 \
107+
--hash=sha256:b0726cecd84f9474419d67252add4ac0cd9811b04d61123054b9fb6f57df6e9e \
108+
--hash=sha256:b58fabe35e80b264a4e3bb23e6b96f9e45a3df7fb7eed419ac0e5947c61e47cc \
109+
--hash=sha256:c7663d4e37f13e884d13994247449e9f8f574bc4655d509c3b95e9ec9e2b9dc1 \
110+
--hash=sha256:e452c464a02e7dc7822a05d25db4cde564444a67e58539a00f929c51eddda0cf \
111+
--hash=sha256:e78c8603dcd9a04c7364f1a3e670cea95d51ee865e4efb3556a3a63adef958ea \
112+
--hash=sha256:eb7e81434c8d223ec4a219b5fc1c47d0417b12be7ea866e24fb5ad6e84b3d988 \
113+
--hash=sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486 \
114+
--hash=sha256:eed63d3b4d62449571547b60578c5b2c4bcccc5387148db46e0c2313dad0ee00 \
115+
--hash=sha256:fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8
94116
pygments==2.19.2 \
95117
--hash=sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887 \
96118
--hash=sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# *******************************************************************************
2+
# Copyright (c) 2026 Contributors to the Eclipse Foundation
3+
#
4+
# See the NOTICE file(s) distributed with this work for additional
5+
# information regarding copyright ownership.
6+
#
7+
# This program and the accompanying materials are made available under the
8+
# terms of the Apache License Version 2.0 which is available at
9+
# https://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# SPDX-License-Identifier: Apache-2.0
12+
# *******************************************************************************
13+
14+
from typing import Any
15+
16+
import pytest
17+
from fit_scenario import FitScenario
18+
from test_properties import add_test_properties
19+
from testing_utils import LogContainer
20+
21+
pytestmark = pytest.mark.parametrize("version", ["rust", "cpp"], scope="class")
22+
23+
24+
@add_test_properties(
25+
partially_verifies=[
26+
"logic_arc_int__lifecycle__lifecycle_if",
27+
"feat_req__lifecycle__process_state_comm",
28+
],
29+
test_type="requirements-based",
30+
derivation_technique="requirements-analysis",
31+
)
32+
class TestLifecycleApplicationIf(FitScenario):
33+
"""Verify state reporting and daemon-gated signaling for lifecycle application interface."""
34+
35+
@pytest.fixture(scope="class")
36+
def scenario_name(self) -> str:
37+
return "lifecycle.application_if"
38+
39+
@pytest.fixture(scope="class", params=[True, False])
40+
def daemon_enabled(self, request: pytest.FixtureRequest) -> bool:
41+
return bool(request.param)
42+
43+
@pytest.fixture(scope="class")
44+
def test_config(self, daemon_enabled: bool) -> dict[str, Any]:
45+
return {
46+
"test": {
47+
"daemon_enabled": daemon_enabled,
48+
"signal_name": "SIGUSR1",
49+
}
50+
}
51+
52+
def test_application_state_is_reported(self, version: str, logs_info_level: LogContainer) -> None:
53+
"""Ensure the SCORE application publishes a lifecycle state report."""
54+
assert version in ("rust", "cpp")
55+
app_state_log = logs_info_level.find_log("component", value="score_application")
56+
assert app_state_log is not None, "Missing SCORE application state report log"
57+
assert app_state_log.state == "state_reported"
58+
assert app_state_log.api == "lifecycle_if"
59+
60+
def test_conditional_signal_path(
61+
self,
62+
version: str,
63+
daemon_enabled: bool,
64+
logs_info_level: LogContainer,
65+
) -> None:
66+
"""Verify signal dispatch behavior depends on daemon availability."""
67+
assert version in ("rust", "cpp")
68+
if daemon_enabled:
69+
daemon_log = logs_info_level.find_log("component", value="control_daemon")
70+
assert daemon_log is not None, "Missing control daemon running state log"
71+
assert daemon_log.state == "running"
72+
73+
dispatched = logs_info_level.find_log("event", value="signal_dispatched")
74+
assert dispatched is not None, "Expected signal_dispatched log when daemon is running"
75+
assert dispatched.condition == "daemon_running"
76+
assert dispatched.signal_name == "SIGUSR1"
77+
assert dispatched.target_process == "score_application"
78+
return
79+
80+
skipped = logs_info_level.find_log("event", value="signal_skipped")
81+
assert skipped is not None, "Expected signal_skipped log when daemon is not running"
82+
assert skipped.condition == "daemon_not_running"
83+
assert skipped.signal_name == "SIGUSR1"
84+
assert skipped.target_process == "score_application"

0 commit comments

Comments
 (0)