Skip to content

Add integration tests for LoLa/mw::com feature in ITF#21

Draft
Subramanian-K812 wants to merge 11 commits into
mainfrom
Subramanian-K812_add_communication_feature_integration_tests
Draft

Add integration tests for LoLa/mw::com feature in ITF#21
Subramanian-K812 wants to merge 11 commits into
mainfrom
Subramanian-K812_add_communication_feature_integration_tests

Conversation

@Subramanian-K812

@Subramanian-K812 Subramanian-K812 commented Jul 16, 2026

Copy link
Copy Markdown

Add communication (LoLa / mw::com) integration tests to ITF

Summary

Adds an ITF test suite for the communication module (LoLa / mw::com).

The suite drives its own two-process scenario —
showcases/standalone/comm_fit: fit_sender + fit_receiver, built on the
same public com_api Rust crate com-api-example uses — as two real OS
processes communicating over real shared memory.

The tests assert on data the consumer actually observes — delivery, ordering,
and value-integrity of a sequence number the sender encodes in the payload —
rather than on log strings the application prints about its own
configuration, so a regression in the middleware is what breaks them.

The suite runs under the existing //feature_integration_tests/itf:itf
target on both the Linux (Docker) and QNX (QEMU) configs.

What's added

File Purpose
showcases/standalone/comm_fit/fit_sender.rs Producer: offers the VehicleInterface service instance, publishes left_tire samples carrying a monotonically increasing sequence number.
showcases/standalone/comm_fit/fit_receiver.rs Consumer: discovers the service (with retry, so start order doesn't matter), subscribes, and prints one line per received sample for the ITF to assert on.
showcases/standalone/comm_fit/BUILD Builds fit_sender/fit_receiver and bundles them for deployment.
showcases/BUILD Deploys the comm_fit bundle into the reference image alongside com-api-example.
patches/communication/002-expose-com-api-gen.patch Exposes com-api-gen (the generated VehicleInterface) outside //score/mw/com, so fit_sender/fit_receiver can depend on it.
bazel_common/score_modules_target_sw.MODULE.bazel Adds the patch above to the score_communication git_override.
known_good.json Same patch entry, kept aligned with the generated MODULE.bazel (required by the known_good_correct CI check).
feature_integration_tests/itf/test_communication.py The test cases (see coverage table below).
feature_integration_tests/itf/comm_helpers.py Exchange helpers and output oracles (CommResult, ordering/integrity checks, deployment-config and ASIL-B ACL scenario helpers).
feature_integration_tests/itf/test_properties.py Fallback-safe wrapper around attribute_plugin.add_test_properties, mirroring feature_integration_tests/test_cases/test_properties.py (verified identical).
feature_integration_tests/itf/BUILD Adds the new sources to the itf target and activates the requirement-traceability plugin (-p attribute_plugin + @score_tooling//python_basics/score_pytest:attribute_plugin dep).

Test coverage

Test Verifies (requirement IDs) Oracle
test_fit_binaries_are_deployed — (deployment smoke check) fit_sender/fit_receiver binaries present on the target image.
test_event_exchange_delivers_data event_type, producer_consumer, interfaces, data_driven_arch, service_discovery Consumer discovers the service (as a separate OS process from the producer), receives samples, exits cleanly.
test_received_samples_are_ordered_and_intact data_corruption, data_reordering Received sequence numbers are non-decreasing and every value is one the sender actually sent (never a garbled value).
test_deployment_config_is_read_from_runtime_path depl_config_runtime SHM binding / service identity are read at runtime from an explicit -s <path> manifest, not compiled in.
test_late_joining_consumer_receives_data stateless_communication, producer_consumer A consumer subscribing 3s after the producer started still binds and receives valid samples from the SHM ring buffer.
test_missing_config_file_fails_deterministically depl_config_runtime Missing manifest → deterministic failure bounded by a shell timeout, never reaches service discovery.
test_truncated_config_fails_deterministically depl_config_runtime Syntactically invalid JSON → same deterministic-failure contract (observed: process aborts, RECV_EXIT=134).
test_schema_invalid_config_fails_deterministically depl_config_runtime Well-formed JSON missing the required schema structure → same contract.
test_mixed_criticality_acl_isolation asil, acl_for_consumer, acl_for_producer, acl_per_service_instance ASIL-B provider offers to one allowed UID; a concurrently-running excluded UID is denied and cannot affect the allowed consumer's stream. (Runs on Linux; skipped on QNX — see Limitations.)

Requirement IDs are the published feat_req__com__* identifiers, attached via
@add_test_properties(partially_verifies=[...]) so they are emitted into the
JUnit XML <properties> — the same traceability convention used by the
persistency FIT cases under feature_integration_tests/test_cases.

The negative-config tests (missing/truncated/schema_invalid) and the ACL
isolation test each run against a dedicated instance specifier that no other
test offers, so they cannot observe another test's leftover shared-memory
state (the QEMU target is session-scoped and persists across the whole test
file, unlike the Docker plugin's fresh-container-per-test model).

Limitations

  • ASIL-B ACL isolation on QNX. allowedConsumer enforcement is a
    shared-memory ACL keyed on the consumer's real UID, so exercising it needs a
    consumer running under a UID excluded from the allow-list (setpriv on
    Linux, on -u <uid> on QNX). On QNX, LoLa's MessagePassingService
    endpoint registration itself requires privilege, so a consumer launched
    under a lower-privilege UID aborts at message-passing setup before
    reaching the shared-memory ACL check. The denial therefore cannot be
    attributed to the ACL on QNX, so the test skips there; it runs on Linux,
    where an unprivileged UID can still bring up its endpoint and so reaches the
    ACL check the assertions rely on.

Verification

  • QNX 8.0 under QEMU (--config=qnx-x86_64): confirmed 8 passed, 1
    skipped
    across multiple runs (test_mixed_criticality_acl_isolation
    skips for the reason under Limitations).
  • Linux under Docker (--config=linux-x86_64, what CI's "Linux — Build &
    Integration Test" job runs): confirmed 9 passed
  • Requirement-traceability properties confirmed present in the generated
    JUnit XML (bazel-testlogs/.../itf/test.xml)

@PiotrKorkus PiotrKorkus left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

did you try to use scenario framework for apps implementation? Any blockers?

then discovers the service and receives samples over the config-declared
SHM binding.
"""
staged = "/tmp/comm_fit_runtime_manifest.json"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

there is still default mw_com_config.json and its identical to yours

prove modified config works

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed: manifest instance name now mutated and verified against non‑existent entry.

// Sequence number was encoded in the payload by fit_sender;
// the sample derefs to the generated Tire type.
let pressure = sample.pressure;
println!("FIT_RECV seq={}", pressure as i64);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

When passed f32 and casted into i64 it will saturate, NaN -> 0.
Improve test to assert each received seq.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed: raw f32 printed via Display; NaN/inf now visible instead of casted integer.

produced (0 .. send_cycles-1). A corrupted payload would decode to a value
outside that range.
"""
return all(0 <= s < send_cycles for s in seq)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

check the expected next value, sequence as whole. Not just range

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed: merged into strict samples_are_sequential_and_intact (range + step check).

Comment on lines +149 to +150
assert not result.found_service, "consumer proceeded past config load to service discovery"
assert not result.received_samples, "consumer proceeded to receive samples despite bad config"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

can we get more strict assertions what was the reason of exit? There might be dozens of reasons behind crash, excluding just 2 of them in test is not sufficient

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed: split into deterministic missing‑config exit (1) vs malformed‑config abort (134).

let discovery = runtime.find_service::<VehicleInterface>(FindServiceSpecifier::Specific(service_id.clone()));
if let Ok(instances) = discovery.get_available_instances() {
if let Some(builder) = instances.into_iter().next() {
return builder.build().ok();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

.ok() hides denied proxy build error without diagnostic, we should be verbose

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed: denied‑proxy error now matched and logged; ACL test asserts marker presence.

Comment thread showcases/standalone/comm_fit/BUILD Outdated
":fit_sender",
":fit_receiver",
],
package_dir = "standalone",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

why needed?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed: removed unused package_dir


def is_non_decreasing(seq: list[int]) -> bool:
"""No reordering: each received sequence number is >= the previous one."""
return all(b >= a for a, b in zip(seq, seq[1:]))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

shall we tolerate equals? dupes are not expected or?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed.

Comment on lines +36 to +37
"comm_helpers.py",
"test_communication.py",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

extract to separate group, this will mix in the future.
Gather all groups under all_tests

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed: new communication_tests filegroup created

Comment thread feature_integration_tests/itf/BUILD Outdated
Comment on lines +102 to +103
"@score_tooling//python_basics/score_pytest:attribute_plugin",
],

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

attr plugin should be used from itf not tooling

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed: switched to proper py_itf_plugin wrapper

@Subramanian-K812

Copy link
Copy Markdown
Author

did you try to use scenario framework for apps implementation? Any blockers?

Yes, have the checked the scenario framework. It only supports single-process runs via one Rust binary. Communication tests need cross-process proof — ACL enforcement by real UIDs, late-join semantics, service discovery — which the framework can’t handle.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants