Skip to content

feat: add TimeDaemon CIT with pip hub infrastructure - #122

Open
gordon9901 wants to merge 14 commits into
eclipse-score:mainfrom
gordon9901:ecarx_time_daemon_cit
Open

feat: add TimeDaemon CIT with pip hub infrastructure#122
gordon9901 wants to merge 14 commits into
eclipse-score:mainfrom
gordon9901:ecarx_time_daemon_cit

Conversation

@gordon9901

@gordon9901 gordon9901 commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

This PR adds TimeDaemon component integration tests with pip hub infrastructure (part 1 of 3):

  • Add three independent pip hubs for TimeDaemon, TimeSlave, and MIT test suites
  • Add score_test_scenarios framework dependency with compatibility patch for score_baselibs 0.2.7
  • Add TimeDaemon CIT covering daemon lifecycle, control flow, IPC, SVT, and verification pipeline
  • Fix visibility for shm_ptp_engine and svt_handler to allow access from test scenarios

Part of #56

test QNX

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

License Check Results

🚀 The license check job ran with the Bazel command:

bazel run //:license-check

Status: ⚠️ Needs Review

Click to expand output
[License Check Output]
Extracting Bazel installation...
Starting local Bazel server (8.6.0) and connecting to it...
INFO: Invocation ID: a89e31ae-6b5b-4a25-a185-6879359ed506
Computing main repo mapping: 
Computing main repo mapping: 
Computing main repo mapping: 
WARNING: For repository 'platforms', the root module requires module version platforms@1.0.0, but got platforms@1.1.0 in the resolved dependency graph. Please update the version in your MODULE.bazel or set --check_direct_dependencies=off
WARNING: For repository 'score_platform', the root module requires module version score_platform@0.7.1, but got score_platform@0.7.2 in the resolved dependency graph. Please update the version in your MODULE.bazel or set --check_direct_dependencies=off
WARNING: For repository 'rules_oci', the root module requires module version rules_oci@2.2.7, but got rules_oci@2.3.0 in the resolved dependency graph. Please update the version in your MODULE.bazel or set --check_direct_dependencies=off
WARNING: For repository 'nlohmann_json', the root module requires module version nlohmann_json@3.11.3, but got nlohmann_json@3.12.0 in the resolved dependency graph. Please update the version in your MODULE.bazel or set --check_direct_dependencies=off
Computing main repo mapping: 
Computing main repo mapping: 
Computing main repo mapping: 
Computing main repo mapping: 
Computing main repo mapping: 
Computing main repo mapping: 
Loading: 
Loading: 3 packages loaded
Analyzing: target //:license-check (4 packages loaded, 0 targets configured)
Analyzing: target //:license-check (4 packages loaded, 0 targets configured)

Analyzing: target //:license-check (64 packages loaded, 10 targets configured)

Analyzing: target //:license-check (146 packages loaded, 2892 targets configured)

Analyzing: target //:license-check (160 packages loaded, 6243 targets configured)

Analyzing: target //:license-check (165 packages loaded, 9366 targets configured)

Analyzing: target //:license-check (165 packages loaded, 9366 targets configured)

Analyzing: target //:license-check (165 packages loaded, 9366 targets configured)

Analyzing: target //:license-check (175 packages loaded, 11305 targets configured)

Analyzing: target //:license-check (175 packages loaded, 11305 targets configured)

Analyzing: target //:license-check (175 packages loaded, 11305 targets configured)

INFO: Analyzed target //:license-check (177 packages loaded, 11555 targets configured).
[9 / 16] [Prepa] Creating source manifest for @@score_tooling+//dash/tool/formatters:dash_format_converter [for tool]
INFO: From Generating Dash formatted dependency file ...:
INFO: Successfully converted 2 packages from Cargo.lock to bazel-out/k8-fastbuild/bin/formatted.txt
[15 / 16] [Prepa] Building license.check.license_check.jar ()
INFO: Found 1 target...
Target //:license.check.license_check up-to-date:
  bazel-bin/license.check.license_check
  bazel-bin/license.check.license_check.jar
INFO: Elapsed time: 26.404s, Critical Path: 1.95s
INFO: 16 processes: 12 internal, 3 processwrapper-sandbox, 1 worker.
INFO: Build completed successfully, 16 total actions
INFO: Running command line: bazel-bin/license.check.license_check ./formatted.txt <args omitted>
usage: org.eclipse.dash.licenses.cli.Main [-batch <int>] [-cd <url>]
       [-confidence <int>] [-ef <url>] [-excludeSources <sources>] [-help] [-lic
       <url>] [-project <shortname>] [-repo <url>] [-review] [-summary <file>]
       [-timeout <seconds>] [-token <token>]

@github-actions

Copy link
Copy Markdown

The created documentation from the pull request is available at: docu-html

Comment thread score/time_daemon/src/ptp_machine/shm/details/BUILD Outdated
Comment thread score/tests/patches/score_test_scenarios_json_writer.patch Outdated
Comment thread score/time_daemon/tests/component_tests/tests/control_flow/test_ptp_divider.py Outdated
Comment thread score/time_daemon/tests/integration_tests/.gitkeep Outdated
Comment thread MODULE.bazel Outdated
Comment thread MODULE.bazel
Comment thread score/time_daemon/tests/integration_tests/requirements.txt Outdated
Comment thread score/time_daemon/tests/test_scenarios/cpp/src/main.cpp Outdated
Comment thread score/time_daemon/tests/integration_tests/conftest.py Outdated
Comment thread score/time_daemon/tests/test_scenarios/cpp/BUILD Outdated
Comment thread MODULE.bazel
psutil
pytest-metadata
pytest-env
testing-utils @ git+https://github.com/eclipse-score/testing_tools.git@a2f9cded3deb636f5dc800bf7a47131487119721

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add version tag as comment

Suggested change
testing-utils @ git+https://github.com/eclipse-score/testing_tools.git@a2f9cded3deb636f5dc800bf7a47131487119721
testing-utils @ git+https://github.com/eclipse-score/testing_tools.git@a2f9cded3deb636f5dc800bf7a47131487119721 # v0.3.0

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — added # v0.3.0 at end of line.

# via testing-utils
# WARNING: pip install will require the following package to be hashed.
# Consider using a hashable URL like https://github.com/jazzband/pip-tools/archive/SOMECOMMIT.zip
testing-utils @ git+https://github.com/eclipse-score/testing_tools.git@v0.3.0

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops - why is the hash here replaced by the version tag? Thought this is generated ...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, the lockfile had been manually edited and the requirements.update target was also broken (score_tooling//python_basics:requirements.txt was renamed to requirements.in after an upgrade). I fixed the BUILD reference and re-generated the lockfile with bazel run :requirements.update — it now keeps the commit hash from requirements.txt as expected.

Comment on lines +43 to +57
void run(const std::string& /*input*/) const final
{
// Phase 1: construct — calls all four subsystem factory functions
auto handler = score::td::CreateSvtTimebase();

// Phase 2: initialize — wires MessageBroker pub-sub topology
handler->Initialize();

// Phase 3: stop from kIdle — verifies graceful shutdown without starting async workers
handler->Stop();

TRACING_INFO(kTargetName,
std::pair{std::string{"lifecycle_initialize_ok"}, std::string{"true"}},
std::pair{std::string{"lifecycle_complete"}, std::string{"true"}});
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already tested in score/time_daemon/src/application/svt/svt_handler_integration_test.cpp

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, SvtHandlerTest.CreateAndDestroy already covers construct→Initialize→Stop. Removed the lifecycle CIT scenario.

Comment on lines +41 to +85
void run(const std::string& /*input*/) const final
{
auto publisher = score::td::CreateSvtPublisher("cit_ipc_pub");
auto receiver = score::td::CreateSvtReceiver();

if (!publisher->Init())
{
throw std::runtime_error{"SvtPublisher::Init() failed"};
}
if (!receiver->Init())
{
throw std::runtime_error{"SvtReceiver::Init() failed"};
}

score::td::PtpTimeInfo info{};
info.ptp_assumed_time = std::chrono::nanoseconds{1'000'000'000LL};
info.local_time = score::td::PtpTimeInfo::ReferenceClock::time_point{std::chrono::nanoseconds{500'000'000LL}};
info.rate_deviation = 0.0;
info.status = {true, false, false, false, true};
info.sync_fup_data.sequence_id = 42U;
info.sync_fup_data.precise_origin_timestamp = 1'000'000'000ULL;

publisher->OnMessage(info);

const auto result = receiver->Receive();
const bool read_ok = result.has_value();

bool ptp_time_ok = false;
bool status_ok = false;
bool seq_ok = false;

if (read_ok)
{
const auto& snap = result.value();
ptp_time_ok = snap.ptp_assumed_time == static_cast<uint64_t>(1'000'000'000LL);
status_ok = snap.status.is_synchronized && snap.status.is_correct;
seq_ok = snap.sync_fup_data.sequence_id == 42U;
}

TRACING_INFO(kTargetName,
std::pair{std::string{"read_succeeded"}, std::string{read_ok ? "true" : "false"}},
std::pair{std::string{"ptp_time_preserved"}, std::string{ptp_time_ok ? "true" : "false"}},
std::pair{std::string{"status_preserved"}, std::string{status_ok ? "true" : "false"}},
std::pair{std::string{"seq_id_preserved"}, std::string{seq_ok ? "true" : "false"}});
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also already tested: score/time_daemon/src/ipc/svt/common_factory_test.cpp

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acknowledged — FactoryImplTest.TestReadAndWrite already exercises the full publish→receive path with EXPECT_EQ full-struct comparison, which is stricter than the CIT version. Removed.

Comment on lines +46 to +82
{
auto ptp_machine = score::td::CreateGPTPStubMachine("cit_verif_ptp");
auto verifier = score::td::CreateSvtVerificationMachine("cit_verif");

std::promise<score::td::PtpTimeInfo> verified_promise;
auto verified_future = verified_promise.get_future();

// Wire PTP machine output into the verification pipeline.
ptp_machine->SetPublishCallback([&verifier](const score::td::PtpTimeInfo& data) {
verifier->OnMessage(data);
});

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

verifier->Init();

if (!ptp_machine->Init())
{
throw std::runtime_error{"GPTPStubMachine::Init() failed"};
}
ptp_machine->Start();

if (verified_future.wait_for(std::chrono::seconds(5)) != std::future_status::ready)
{
ptp_machine->Stop();
throw std::runtime_error{"Timed out waiting for verified PTP data through pipeline"};
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This kind of test makes sense, because it really combines multiple sub-components. Following remarks:

  1. We should use plain gtest for doing this. Makes error checking much easier and expressive, e.g. instead of having:
if (!ptp_machine->Init()) {
    throw std::runtime_error{"GPTPStubMachine::Init() failed"};
}

we'd have:

ASSERT_TRUE(ptp_machine->Init());

and no additional checks on Python side.

  1. A similar test like this could be achieved by instantiating the application svt_handler. Valery already added test code there (score/time_daemon/src/application/svt/svt_handler_integration_test.cpp) but that is commented out at the moment.

I really would use Python/ITF based tests only for testing a single - in this case the TimeDaemon - or multiple binaries working together.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed. I agree that in-process multi-object wiring belongs in gtest:

Ported the pipeline scenario to svt_verification_machine_pipeline_integration_test.cpp under src/verification_machine/svt/, using ASSERT_/EXPECT_ assertions instead of TRACING_INFO + Python-side checks.
Removed the CIT test_scenarios/cpp/ binary and the corresponding pytest targets. The CIT scaffolding (conftest.py, cit_scenario.py, requirements) is kept for future process-level tests (launching the real TimeDaemon binary), with a note in the README clarifying that CIT is reserved for single-/multi-binary scenarios.
Re (2): I didn't wire this through svt_handler because the existing svt_handler_integration_test is currently commented out in the BUILD and relies on a mocked libqgptp; the new gtest uses the real GPTPStubMachine + SvtVerificationMachine directly, which is the specific stub→verification path I wanted to cover. Happy to consolidate into svt_handler_integration_test once that is re-enabled — let me know if you'd prefer that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

4 participants