-
Notifications
You must be signed in to change notification settings - Fork 33
added test cases for conditional launching #298
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
Saumya-R
wants to merge
4
commits into
eclipse-score:main
Choose a base branch
from
qorix-group:saumya_lifecycle_integration_test_1
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
50 changes: 50 additions & 0 deletions
50
feature_integration_tests/test_cases/lifecycle_scenario.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| # ******************************************************************************* | ||
| # Copyright (c) 2026 Contributors to the Eclipse Foundation | ||
| # | ||
| # See the NOTICE file(s) distributed with this work for additional | ||
| # information regarding copyright ownership. | ||
| # | ||
| # This program and the accompanying materials are made available under the | ||
| # terms of the Apache License Version 2.0 which is available at | ||
| # https://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # ******************************************************************************* | ||
| """ | ||
| Helpers and base scenario class for lifecycle feature integration tests. | ||
|
|
||
| ``LifecycleScenario`` is a ``FitScenario`` subclass that supplies the shared | ||
| ``temp_dir`` fixture so individual test classes do not have to duplicate it. | ||
| """ | ||
|
|
||
| from collections.abc import Generator | ||
| from pathlib import Path | ||
|
|
||
| import pytest | ||
| from fit_scenario import FitScenario, temp_dir_common | ||
|
|
||
|
|
||
| class LifecycleScenario(FitScenario): | ||
| """ | ||
| Base class for lifecycle feature integration tests. | ||
|
|
||
| Provides the ``temp_dir`` fixture shared by all lifecycle test classes. | ||
| """ | ||
|
|
||
| @pytest.fixture(scope="class") | ||
| def temp_dir( | ||
| self, | ||
| tmp_path_factory: pytest.TempPathFactory, | ||
| version: str, | ||
| ) -> Generator[Path, None, None]: | ||
| """ | ||
| Provide a temporary working directory for the lifecycle tests. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| tmp_path_factory : pytest.TempPathFactory | ||
| Built-in pytest factory for temporary directories. | ||
| version : str | ||
| Parametrized scenario version (``"rust"`` or ``"cpp"``). | ||
| """ | ||
| yield from temp_dir_common(tmp_path_factory, self.__class__.__name__, version) |
212 changes: 212 additions & 0 deletions
212
feature_integration_tests/test_cases/tests/lifecycle/test_conditional_launching.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,212 @@ | ||
| # ******************************************************************************* | ||
| # Copyright (c) 2026 Contributors to the Eclipse Foundation | ||
| # | ||
| # See the NOTICE file(s) distributed with this work for additional | ||
| # information regarding copyright ownership. | ||
| # | ||
| # This program and the accompanying materials are made available under the | ||
| # terms of the Apache License Version 2.0 which is available at | ||
| # https://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # ******************************************************************************* | ||
| """ | ||
| Feature integration tests for conditional launching. | ||
|
|
||
| Tests verify that the Launch Manager supports conditional process launching | ||
| based on various conditions including process state, environment variables, | ||
| paths, and dependencies. | ||
| """ | ||
|
|
||
| from pathlib import Path | ||
| from typing import Any | ||
|
|
||
| import pytest | ||
| from fit_scenario import ResultCode | ||
| from lifecycle_scenario import LifecycleScenario | ||
| from test_properties import add_test_properties | ||
| from testing_utils import LogContainer, ScenarioResult | ||
|
|
||
| pytestmark = pytest.mark.parametrize("version", ["rust", "cpp"], scope="class") | ||
|
|
||
|
|
||
| @add_test_properties( | ||
| partially_verifies=[ | ||
| "feat_req__lifecycle__waitfor_support", | ||
| "feat_req__lifecycle__cond_process_start", | ||
| "feat_req__lifecycle__total_wait_time_support", | ||
| "feat_req__lifecycle__polling_interval", | ||
| "feat_req__lifecycle__validate_conditions", | ||
| "feat_req__lifecycle__validation_conditions", | ||
| "feat_req__lifecycle__launcher_status_storage", | ||
| "feat_req__lifecycle__condition_check_method", | ||
| "feat_req__lifecycle__config_actions_cond", | ||
| "feat_req__lifecycle__path_condition_check", | ||
| "feat_req__lifecycle__env_variable_cond_check", | ||
| "feat_req__lifecycle__dependency_check", | ||
| "feat_req__lifecycle__check_dependency_exec", | ||
| "feat_req__lifecycle__define_swc_dependencies", | ||
| "feat_req__lifecycle__stop_sequence", | ||
| ], | ||
| test_type="requirements-based", | ||
| derivation_technique="requirements-analysis", | ||
| ) | ||
| class TestConditionalLaunching(LifecycleScenario): | ||
| """ | ||
| Verify conditional process launching support. | ||
|
|
||
| This test confirms that the Launch Manager can conditionally launch | ||
| processes based on various criteria and wait conditions. | ||
| """ | ||
|
|
||
| @pytest.fixture(scope="class") | ||
| def scenario_name(self) -> str: | ||
| return "lifecycle.conditional_launching" | ||
|
|
||
| @pytest.fixture(scope="class") | ||
| def test_config(self, temp_dir: Path) -> dict[str, Any]: | ||
| return { | ||
| "test": { | ||
| "test_duration_ms": 300, | ||
| "wait_conditions": ["path:/tmp/ready", "env:STARTUP_COMPLETE", "process:init_done"], | ||
| "polling_interval_ms": 173, | ||
| "timeout_ms": 6421, | ||
| } | ||
| } | ||
|
|
||
| def test_path_condition_check(self, results: ScenarioResult, logs_info_level: LogContainer, version: str) -> None: | ||
| """ | ||
| Verify that path-based condition checking works. | ||
| """ | ||
| assert results.return_code == ResultCode.SUCCESS | ||
|
|
||
| if version == "cpp": | ||
| assert "Checking path condition: /tmp/ready" in results.stdout, "Path condition not checked" | ||
| else: | ||
| path_logs = logs_info_level.get_logs(field="message", pattern="Checking path condition: /tmp/ready") | ||
| assert len(path_logs) > 0, "Path condition not checked" | ||
|
|
||
| def test_env_condition_check(self, results: ScenarioResult, logs_info_level: LogContainer, version: str) -> None: | ||
| """ | ||
| Verify that environment variable condition checking works. | ||
| """ | ||
| assert results.return_code == ResultCode.SUCCESS | ||
|
|
||
| if version == "cpp": | ||
| assert "Checking env condition: STARTUP_COMPLETE" in results.stdout, "Environment condition not checked" | ||
| else: | ||
| env_logs = logs_info_level.get_logs(field="message", pattern="Checking env condition: STARTUP_COMPLETE") | ||
| assert len(env_logs) > 0, "Environment condition not checked" | ||
|
|
||
| def test_process_condition_check( | ||
| self, results: ScenarioResult, logs_info_level: LogContainer, version: str | ||
| ) -> None: | ||
| """ | ||
| Verify that process state condition checking works. | ||
| """ | ||
| assert results.return_code == ResultCode.SUCCESS | ||
|
|
||
| if version == "cpp": | ||
| assert "Checking process condition: init_done" in results.stdout, "Process condition not checked" | ||
| else: | ||
| process_logs = logs_info_level.get_logs(field="message", pattern="Checking process condition: init_done") | ||
| assert len(process_logs) > 0, "Process condition not checked" | ||
|
|
||
| def test_polling_interval_configured( | ||
| self, results: ScenarioResult, logs_info_level: LogContainer, version: str | ||
| ) -> None: | ||
| """ | ||
| Verify that polling interval is configured correctly. | ||
| """ | ||
| assert results.return_code == ResultCode.SUCCESS | ||
|
|
||
| if version == "cpp": | ||
| assert "Polling interval: 173ms" in results.stdout, "Polling interval not configured" | ||
| else: | ||
| polling_logs = logs_info_level.get_logs(field="message", pattern="Polling interval: 173ms") | ||
| assert len(polling_logs) > 0, "Polling interval not configured" | ||
|
|
||
| def test_condition_timeout_configured( | ||
| self, results: ScenarioResult, logs_info_level: LogContainer, version: str | ||
| ) -> None: | ||
| """ | ||
| Verify that condition timeout is configured. | ||
| """ | ||
| assert results.return_code == ResultCode.SUCCESS | ||
|
|
||
| if version == "cpp": | ||
| assert "Condition timeout: 6421ms" in results.stdout, "Condition timeout not configured" | ||
| else: | ||
| timeout_logs = logs_info_level.get_logs(field="message", pattern="Condition timeout: 6421ms") | ||
| assert len(timeout_logs) > 0, "Condition timeout not configured" | ||
|
|
||
| def test_dependency_check(self, results: ScenarioResult, logs_info_level: LogContainer, version: str) -> None: | ||
| """ | ||
| Verify that dependency checking works. | ||
| """ | ||
| assert results.return_code == ResultCode.SUCCESS | ||
|
|
||
| if version == "cpp": | ||
| assert "All dependencies satisfied" in results.stdout, "Dependency check failed" | ||
| else: | ||
| dep_logs = logs_info_level.get_logs(field="message", value="All dependencies satisfied") | ||
| assert len(dep_logs) > 0, "Dependency check failed" | ||
|
Saumya-R marked this conversation as resolved.
|
||
|
|
||
|
|
||
| @add_test_properties( | ||
| partially_verifies=[ | ||
| "feat_req__lifecycle__validate_conditions", | ||
| "feat_req__lifecycle__validation_conditions", | ||
| ], | ||
| test_type="requirements-based", | ||
| derivation_technique="requirements-analysis", | ||
| ) | ||
| class TestInvalidConditionPrefix(LifecycleScenario): | ||
| """ | ||
| Verify that an unsupported wait-condition prefix is rejected. | ||
|
|
||
| The scenario implementation must reject any condition whose prefix is not | ||
| one of the known types (path, env, process). This test supplies a | ||
| deliberately invalid prefix to exercise that validation path and confirm | ||
| the error is propagated correctly. | ||
| """ | ||
|
|
||
| @pytest.fixture(scope="class") | ||
| def scenario_name(self) -> str: | ||
| return "lifecycle.conditional_launching" | ||
|
|
||
| @pytest.fixture(scope="class") | ||
| def test_config(self, temp_dir: Path) -> dict[str, Any]: | ||
| return { | ||
| "test": { | ||
| "test_duration_ms": 300, | ||
| # "badprefix" is intentionally not a recognised condition type. | ||
| # The scenario must reject it and exit with a non-zero return code. | ||
| "wait_conditions": ["badprefix:value"], | ||
| "polling_interval_ms": 50, | ||
| "timeout_ms": 5000, | ||
| } | ||
| } | ||
|
|
||
| def expect_command_failure(self, *args, **kwargs) -> bool: | ||
| """Tell the results fixture that a non-zero exit is expected here.""" | ||
| return True | ||
|
|
||
| def capture_stderr(self, *args, **kwargs) -> bool: | ||
| """Capture stderr so the rejection message can be asserted.""" | ||
| return True | ||
|
|
||
| def test_invalid_prefix_rejected(self, results: ScenarioResult, version: str) -> None: | ||
| """ | ||
| Verify that an unsupported wait-condition prefix causes scenario failure. | ||
|
|
||
| Both implementations must exit with a non-zero return code and surface | ||
| the rejection message so callers can identify the bad condition. | ||
| """ | ||
| assert results.return_code != ResultCode.SUCCESS, ( | ||
| f"Scenario should have failed for version={version} but exited successfully" | ||
| ) | ||
| assert results.stderr is not None, "Expected error output in stderr but got None" | ||
| assert "Unsupported wait condition prefix: badprefix:value" in results.stderr, ( | ||
| f"Rejection message not found in stderr for version={version}. stderr={results.stderr!r}" | ||
| ) | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.