Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .clang-tidy
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# *******************************************************************************
# 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
# *******************************************************************************
# Local clang-tidy overrides for the score_time module.
#
# The S-CORE baseline from @score_cpp_policies//clang_tidy:.clang-tidy is
# applied first; settings here are layered on top per clang-tidy's standard
# merge rules. Only module-specific suppressions belong here — do not remove
# baseline checks.

# Only analyze headers inside the score/ source tree. Without this,
# clang-tidy picks up warnings from externally provided headers
# (e.g. toolchain redacted_dates.h) that we cannot fix.
HeaderFilterRegex: 'score/'

# Suppress the builtin-macro-redefined diagnostic emitted by the LLVM
# toolchain's redacted_dates.h (which redefines __DATE__/__TIME__ for
# deterministic builds). This is injected by the toolchain via -include
# and is not user code, so suppressing it here is appropriate.
Checks: >-
-clang-diagnostic-builtin-macro-redefined
2 changes: 2 additions & 0 deletions BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,7 @@ exports_files(
[
# Used by the @score_tooling coverage reporter to locate the workspace root.
"MODULE.bazel",
# Local clang-tidy overrides, layered on top of the S-CORE baseline.
".clang-tidy",
],
)
22 changes: 21 additions & 1 deletion MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,27 @@ pip.parse(
python_version = PYTHON_VERSION,
requirements_lock = "//third_party/codeql:requirements_lock.txt",
)
use_repo(pip, "codeql_coding_standards_pip_hub")

# To regenerate the lock file after editing requirements.txt:
# bazel run //score/time_daemon/tests/component_tests:requirements.update
pip.parse(
hub_name = "pip_time_daemon_venv",
python_version = PYTHON_VERSION,
requirements_lock = "//score/time_daemon/tests/component_tests:requirements.txt.lock",
)
use_repo(pip, "codeql_coding_standards_pip_hub", "pip_time_daemon_venv")

bazel_dep(name = "rules_cc", version = "0.2.17", dev_dependency = True)
Comment thread
gordon9901 marked this conversation as resolved.

## Component Integration Test framework

bazel_dep(name = "score_test_scenarios", version = "0.4.1", dev_dependency = True)
git_override(
module_name = "score_test_scenarios",
Comment thread
gordon9901 marked this conversation as resolved.
commit = "fec712d490ff5d46fae91332bafac4777b300026", # tag v0.4.1
remote = "https://github.com/eclipse-score/testing_tools.git",
)

## Integration Test Framework dependencies

bazel_dep(name = "score_itf", version = "0.5.0")
Expand Down
5 changes: 4 additions & 1 deletion MODULE.bazel.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion score/time_daemon/src/application/svt/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ load("@score_baselibs//score/language/safecpp:toolchain_features.bzl", "COMPILER
"svt_handler.h",
],
features = COMPILER_WARNING_FEATURES,
visibility = ["//score/time_daemon/src/application:__pkg__"],
visibility = [
"//score/time_daemon/src/application:__pkg__",
],
deps = [
"//score/time_daemon/src/application:timebase_handler",
"//score/time_daemon/src/application/job_runner",
Expand Down
16 changes: 16 additions & 0 deletions score/time_daemon/src/verification_machine/svt/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ cc_unit_test_suites_for_host_and_qnx(
name = "unit_test_suite",
cc_unit_tests = [
":svt_verification_machine_test",
":svt_verification_machine_pipeline_integration_test",
],
test_suites_from_sub_packages = ["//score/time_daemon/src/verification_machine/svt/validators:unit_test_suite"],
visibility = ["//score/time_daemon:__subpackages__"],
Expand All @@ -76,3 +77,18 @@ cc_test(
"@score_baselibs//score/mw/log:console_only_backend",
],
)

cc_test(
name = "svt_verification_machine_pipeline_integration_test",
srcs = [
"svt_verification_machine_pipeline_integration_test.cpp",
],
deps = [
"//score/time_daemon/src/common/data_types:ptp_time_info",
"//score/time_daemon/src/ptp_machine/stub:gptp_stub_machine",
"//score/time_daemon/src/verification_machine/svt:svt_verification_machine",
"@googletest//:gtest",
"@googletest//:gtest_main",
"@score_baselibs//score/mw/log:console_only_backend",
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/********************************************************************************
* 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
********************************************************************************/
#include "score/time_daemon/src/common/data_types/ptp_time_info.h"
#include "score/time_daemon/src/ptp_machine/stub/factory.h"
#include "score/time_daemon/src/verification_machine/svt/factory.h"

#include <gtest/gtest.h>

#include <chrono>
#include <future>

namespace score
{
namespace td
{

// Verifies that PtpTimeInfo published by GPTPStubMachine flows correctly through
// SvtVerificationMachine (SynchronizationValidator -> TimeoutValidator -> TimeJumpsValidator)
// and emerges with the expected status fields intact.
class VerificationPipelineIntegrationTest : public ::testing::Test
{
protected:
void SetUp() override
{
ptp_machine_ = CreateGPTPStubMachine("verif_pipeline_ptp");
verifier_ = CreateSvtVerificationMachine("verif_pipeline");

// Wire PTP machine output into the verification pipeline.
ptp_machine_->SetPublishCallback([this](const PtpTimeInfo& data) {
verifier_->OnMessage(data);
});

// Capture the first data point that exits the verification pipeline.
verifier_->SetPublishCallback([this](const PtpTimeInfo& data) {
try
{
verified_promise_.set_value(data);
}
catch (const std::future_error&)
{
// Capture only the first verified data point.
}
});
}

void TearDown() override
{
ptp_machine_->Stop();
}

std::shared_ptr<GPTPStubMachine> ptp_machine_;
std::shared_ptr<SvtVerificationMachine> verifier_;
std::promise<PtpTimeInfo> verified_promise_;
};

TEST_F(VerificationPipelineIntegrationTest, DataFlowsThroughPipeline)
{
ASSERT_TRUE(verifier_->Init());
ASSERT_TRUE(ptp_machine_->Init());
ptp_machine_->Start();

auto verified_future = verified_promise_.get_future();
ASSERT_EQ(verified_future.wait_for(std::chrono::seconds(5)), std::future_status::ready);

const auto data = verified_future.get();

// The stub always produces synchronized/correct data on its first publish;
// all three validators must let it through without flagging an anomaly.
EXPECT_TRUE(data.status.is_synchronized);
EXPECT_TRUE(data.status.is_correct);
EXPECT_FALSE(data.status.is_timeout);
EXPECT_FALSE(data.status.is_time_jump_future);
EXPECT_FALSE(data.status.is_time_jump_past);
EXPECT_GT(data.ptp_assumed_time.count(), 0);
}

} // namespace td
} // namespace score
45 changes: 45 additions & 0 deletions score/time_daemon/tests/component_tests/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# *******************************************************************************
# 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
# *******************************************************************************

load("@pip_time_daemon_venv//:requirements.bzl", "all_requirements")
load("@rules_python//python:pip.bzl", "compile_pip_requirements")
load("@score_tooling//python_basics:defs.bzl", "score_virtualenv")

# To regenerate requirements.txt.lock after editing requirements.txt, run:
# bazel run //score/time_daemon/tests/component_tests:requirements.update
compile_pip_requirements(
name = "requirements",
srcs = [
"requirements.txt",
"@score_tooling//python_basics:requirements.in",
],
requirements_txt = "requirements.txt.lock",
tags = ["manual"],
)

score_virtualenv(
name = "python_tc_venv",
reqs = all_requirements,
venv_name = ".python_tc_venv",
)

# NOTE: The time_daemon_cit pytest target is intentionally absent.
#
# Previous CIT scenarios (lifecycle, shm_roundtrip, pipeline) exercised
# component-internal behaviour inside a single process — those belong in
# gtest-based unit/component integration tests under src/.
#
# The CIT framework (Python driver + test_scenarios binary) is reserved
# for testing the TimeDaemon as an external binary, with true IPC between
# processes. Re-enable score_py_pytest here once a real process-level
# integration scenario is added.
73 changes: 73 additions & 0 deletions score/time_daemon/tests/component_tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<!-- ----------------------------------------------------------------------------
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
----------------------------------------------------------------------------- -->

# TimeDaemon Component Integration Tests (CIT)

## Scope

Component integration tests verify the TimeDaemon running as an **external
process** — its startup, runtime behaviour, IPC interfaces, and shutdown —
exercised from outside the binary. They are NOT a replacement for unit tests or
for in-process component integration tests.

| Layer | Tool | Where it lives | What it covers |
|-------|------|----------------|----------------|
| Unit | gtest / gmock | `score/time_daemon/src/**/*_test.cpp` | Individual classes, white-box |
| Component integration (in-process) | gtest / gmock | `score/time_daemon/src/**/*_integration_test.cpp` | Multiple production objects wired together inside one process (e.g. GPTPStubMachine → SvtVerificationMachine) |
| **CIT (this layer)** | **pytest + scenario binary** | `score/time_daemon/tests/component_tests/` | **TimeDaemon running as a real binary, single- or multi-process interaction** |
| Module integration | pytest + ITF | `score/tests/module_integration_tests/` | TimeSlave ↔ TimeDaemon across components |
| System | pytest + ITF + QEMU / Docker | `score/tests/gptp_pipeline/` | Multi-binary end-to-end across OS targets |

**Rule of thumb** — if a scenario can be written by instantiating production
objects directly and linking them with gtest (i.e. everything happens inside one
test process), it belongs in the gtest layer under `src/`. CIT is reserved for
tests that must launch the real TimeDaemon executable (or multiple binaries) and
interact with it from outside, via its real IPC/SHM interfaces.

## Architecture

```
pytest (Python) test runner, assertions, reporting
▼ subprocess + structured-log parsing
scenario / daemon binary real TimeDaemon (or helper) process
▼ IPC / SHM / command line
TimeDaemon production code running in its own process
```

- Python side lives under `tests/` and subclasses `testing_utils.Scenario`
(see `tests/cit_scenario.py`).
- Each pytest class declares a `scenario_name` fixture that selects which
scenario/binary to run; results come back as exit code + structured log lines
parsed by `testing_utils.LogContainer`.
- The `conftest.py` provides CLI options for building and running C++ scenario
binaries (e.g. `--cpp-target-name`, `--build-scenarios`).

## Status

The Python driver scaffolding (`conftest.py`, `cit_scenario.py`, `result_code.py`,
requirements, virtualenv) is in place. Active CIT scenarios will be added here
once the TimeDaemon binary can be launched standalone for process-level
integration testing.

In-process multi-module integration scenarios live in gtest under `src/` (e.g.
`svt_verification_machine_pipeline_integration_test.cpp`).

## Running

When scenario targets exist, run with:

```bash
bazel test //score/time_daemon/tests/component_tests:<target_name>
```
Loading
Loading