diff --git a/score/mw/com/test/bigdata/BUILD b/score/mw/com/test/bigdata/BUILD index 2948682bc..d22f50b74 100644 --- a/score/mw/com/test/bigdata/BUILD +++ b/score/mw/com/test/bigdata/BUILD @@ -16,6 +16,11 @@ load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_library") load("@score_baselibs//score/language/safecpp:toolchain_features.bzl", "COMPILER_WARNING_FEATURES") load("//score/mw/com/test:pkg_application.bzl", "pkg_application") +exports_files( + ["logging.json"], + visibility = ["//score/mw/com/test:__subpackages__"], +) + cc_binary( name = "bigdata", srcs = [ diff --git a/score/mw/com/test/com_api/BUILD b/score/mw/com/test/com_api/BUILD new file mode 100644 index 000000000..0e8696e4a --- /dev/null +++ b/score/mw/com/test/com_api/BUILD @@ -0,0 +1,44 @@ +# ******************************************************************************* +# 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("@rules_cc//cc:defs.bzl", "cc_library") +load("@rules_rust//rust:defs.bzl", "rust_library") +load("@score_baselibs//score/language/safecpp:toolchain_features.bzl", "COMPILER_WARNING_FEATURES") + +cc_library( + name = "bigdata_com_api_gen_cpp", + srcs = ["bigdata_com_api_gen.cpp"], + hdrs = ["bigdata_com_api_gen.h"], + features = COMPILER_WARNING_FEATURES, + implementation_deps = [ + "//score/mw/com/impl/rust/com-api/com-api-ffi-lola:registry_bridge_macro_cpp", + ], + deps = [ + "//score/mw/com/test/common_test_resources:bigdata_type", + ], + alwayslink = True, +) + +rust_library( + name = "bigdata_com_api_gen_rs", + srcs = ["bigdata_com_api_gen.rs"], + crate_name = "bigdata_com_api_gen", + features = ["link_std_cpp_lib"], + visibility = [ + "//score/mw/com/test/com_api:__subpackages__", + ], + deps = [ + ":bigdata_com_api_gen_cpp", + "//score/mw/com/impl/rust/com-api/com-api", + ], +) diff --git a/score/mw/com/test/com_api/bigdata_com_api_gen.cpp b/score/mw/com/test/com_api/bigdata_com_api_gen.cpp new file mode 100644 index 000000000..90b4b1d40 --- /dev/null +++ b/score/mw/com/test/com_api/bigdata_com_api_gen.cpp @@ -0,0 +1,27 @@ +/******************************************************************************* + * 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/mw/com/test/com_api/bigdata_com_api_gen.h" +#include "score/mw/com/impl/rust/com-api/com-api-ffi-lola/registry_bridge_macro.h" + +// Register the BigData interface with the com-api FFI bridge. +BEGIN_EXPORT_MW_COM_INTERFACE(BigDataInterface, + ::score::mw::com::test::BigDataProxy, + ::score::mw::com::test::BigDataSkeleton) +EXPORT_MW_COM_EVENT(::score::mw::com::test::MapApiLanesStamped, map_api_lanes_stamped_) +EXPORT_MW_COM_EVENT(::score::mw::com::test::DummyDataStamped, dummy_data_stamped_) +END_EXPORT_MW_COM_INTERFACE() + +// Export data types so that the Rust-side CommData::ID can resolve them. +EXPORT_MW_COM_TYPE(MapApiLanesStamped, ::score::mw::com::test::MapApiLanesStamped) +EXPORT_MW_COM_TYPE(DummyDataStamped, ::score::mw::com::test::DummyDataStamped) diff --git a/score/mw/com/test/com_api/bigdata_com_api_gen.h b/score/mw/com/test/com_api/bigdata_com_api_gen.h new file mode 100644 index 000000000..bc7dbd9ff --- /dev/null +++ b/score/mw/com/test/com_api/bigdata_com_api_gen.h @@ -0,0 +1,21 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ + +#ifndef SCORE_MW_COM_TEST_COM_API_BIGDATA_COM_API_GEN_H +#define SCORE_MW_COM_TEST_COM_API_BIGDATA_COM_API_GEN_H + +// Re-export the BigData interface types (BigDataProxy / BigDataSkeleton) that are +// already defined in big_datatype.h +#include "score/mw/com/test/common_test_resources/big_datatype.h" + +#endif // SCORE_MW_COM_TEST_COM_API_BIGDATA_COM_API_GEN_H diff --git a/score/mw/com/test/com_api/bigdata_com_api_gen.rs b/score/mw/com/test/com_api/bigdata_com_api_gen.rs new file mode 100644 index 000000000..ab76d5e97 --- /dev/null +++ b/score/mw/com/test/com_api/bigdata_com_api_gen.rs @@ -0,0 +1,108 @@ +/******************************************************************************** + * 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 + ********************************************************************************/ + +//! Generated bindings for the BigData interface using the com-api library. +//! +//! This file is the com-api counterpart of the old-API `bigdata_gen.rs`. It +//! defines the same large data types (`MapApiLanesStamped`, `DummyDataStamped`) +//! and wires them through the com-api `Interface` / `Consumer` / `Producer` +//! abstractions instead of the legacy `mw_com::import_interface!` macro. + +use com_api::{interface, CommData, ProviderInfo, Publisher, Reloc, Subscriber}; + +use core::fmt::Debug; + +#[repr(C)] +#[derive(Default, Reloc)] +pub struct StdTimestamp { + pub fractional_seconds: u32, + pub seconds: u32, + pub sync_status: u32, +} + +/// Opaque representation of `MapApiLaneBoundaryData` (empty struct in C++). +#[repr(C)] +#[derive(Default, Reloc)] +pub struct MapApiLaneBoundaryData { + _dummy: [u8; 1], +} + +/// Opaque representation of `MapApiLaneData`. +/// Using a single-byte placeholder; the C++ type is much larger. +/// This is sufficient because the test only verifies sample-count delivery. +#[repr(C)] +#[derive(Default, Reloc)] +pub struct MapApiLaneData { + _dummy: [u8; 1], +} + +/// Opaque representation of `LaneGroupData` (empty struct in C++). +#[repr(C)] +#[derive(Default, Reloc)] +pub struct LaneGroupData { + _dummy: [u8; 1], +} + +pub const MAX_LANES: usize = 16; + +/// Large data type sent over the `map_api_lanes_stamped` event. +#[repr(C)] +#[derive(Default, Reloc)] +pub struct MapApiLanesStamped { + pub time_stamp: StdTimestamp, + pub frame_id: [u8; 10], + pub projection_id: u32, + pub event_data_qualifier: u32, + pub lane_boundaries: [MapApiLaneBoundaryData; 10], + pub lanes: [MapApiLaneData; MAX_LANES], + pub lane_groups: [LaneGroupData; 10], + pub x: u32, + pub hash_value: usize, +} + +impl CommData for MapApiLanesStamped { + const ID: &'static str = "MapApiLanesStamped"; +} + +impl Debug for MapApiLanesStamped { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "MapApiLanesStamped {{ x: {} }}", self.x) + } +} + +/// Secondary event data type. +#[repr(C)] +#[derive(Default, Reloc)] +pub struct DummyDataStamped { + pub time_stamp: StdTimestamp, + pub x: u8, + pub hash_value: usize, +} + +impl CommData for DummyDataStamped { + const ID: &'static str = "DummyDataStamped"; +} + +impl Debug for DummyDataStamped { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "DummyDataStamped {{ x: {} }}", self.x) + } +} + +interface!( + interface BigData, { + Id = "BigDataInterface", + map_api_lanes_stamped_: Event, + dummy_data_stamped_: Event, + } +); diff --git a/score/mw/com/test/com_api/consumer_async_apis/BUILD b/score/mw/com/test/com_api/consumer_async_apis/BUILD new file mode 100644 index 000000000..05b38032b --- /dev/null +++ b/score/mw/com/test/com_api/consumer_async_apis/BUILD @@ -0,0 +1,46 @@ +# ******************************************************************************* +# 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("@rules_rust//rust:defs.bzl", "rust_binary") +load("//score/mw/com/test:pkg_application.bzl", "pkg_application") + +rust_binary( + name = "bigdata-consumer-async", + srcs = ["consumer_app.rs"], + features = ["link_std_cpp_lib"], + visibility = [ + "//score/mw/com/test/com_api:__subpackages__", + ], + deps = [ + "//score/mw/com/impl/rust/com-api/com-api", + "//score/mw/com/test/com_api:bigdata_com_api_gen_rs", + "@score_communication_crate_index//:clap", + "@score_communication_crate_index//:tokio", + ], +) + +pkg_application( + name = "bigdata-com-api-async-pkg", + app_name = "bigdata-com-api-async", + bin = [ + ":bigdata-consumer-async", + "//score/mw/com/test/com_api/producer_app:bigdata-producer", + ], + etc = [ + "//score/mw/com/test/com_api/etc:config", + "//score/mw/com/test/bigdata:logging.json", + ], + visibility = [ + "//score/mw/com/test/com_api:__subpackages__", + ], +) diff --git a/score/mw/com/test/com_api/consumer_async_apis/consumer_app.rs b/score/mw/com/test/com_api/consumer_async_apis/consumer_app.rs new file mode 100644 index 000000000..0dbd3b92e --- /dev/null +++ b/score/mw/com/test/com_api/consumer_async_apis/consumer_app.rs @@ -0,0 +1,123 @@ +/******************************************************************************** + * 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 + ********************************************************************************/ + +//! Consumer (proxy) binary for the BigData com-api SCT. +//! it use the async APIs for Service Discovery and Receive samples. +//! +//! # Usage +//! +//! ``` +//! bigdata-consumer -n +//! ``` +//! * `-n ` — number of samples to receive before exiting. +//! The consumer subscribes to the producer's `map_api_lanes_stamped_` output and +//! prints the `x` field of each received sample until it has received the specified number of samples, at which point it exits. + +use bigdata_com_api_gen::BigDataInterface; +use clap::Parser; +use com_api::{ + Builder, FindServiceSpecifier, InstanceSpecifier, LolaRuntimeBuilderImpl, Runtime, + RuntimeBuilder, SampleContainer, ServiceDiscovery, Subscriber, Subscription, +}; +use std::path::Path; + +const CONFIG_PATH: &str = "etc/config.json"; +const MAX_SAMPLES_PER_CALL: usize = 5; + +#[derive(Parser)] +struct Args { + /// Number of samples to receive before exiting + #[arg(short = 'n', required = true)] + num_cycles: usize, +} + +#[tokio::main] +async fn main() { + let args = Args::parse(); + let num_cycles = args.num_cycles; + + println!( + "[bigdata-consumer] Starting, will receive {} samples", + num_cycles + ); + + // Initialise the Lola runtime. + let mut runtime_builder = LolaRuntimeBuilderImpl::new(); + runtime_builder.load_config(Path::new(CONFIG_PATH)); + let runtime = runtime_builder + .build() + .expect("Failed to build Lola runtime"); + + let instance_specifier = InstanceSpecifier::new("/score/cp60/MapApiLanesStamped") + .expect("Invalid instance specifier"); + + let discovery = runtime + .find_service::(FindServiceSpecifier::Specific(instance_specifier)); + + // Await the producer to become available. + let instances = discovery + .get_available_instances_async() + .await + .expect("Failed to get available instances"); + + let builder = instances + .into_iter() + .next() + .expect("No service instances available"); + let consumer = builder.build().expect("Failed to build consumer"); + + // Subscribe with a slot buffer large enough for MAX_SAMPLES_PER_CALL. + let subscription = consumer + .map_api_lanes_stamped_ + .subscribe(MAX_SAMPLES_PER_CALL) + .expect("Failed to subscribe to map_api_lanes_stamped_"); + + let mut received_total: usize = 0; + let mut sample_buf = SampleContainer::new(MAX_SAMPLES_PER_CALL); + // `receive` awaits until at least `min_samples` (1) are available. + while received_total < num_cycles { + sample_buf = match subscription + .receive(sample_buf, 1, MAX_SAMPLES_PER_CALL) + .await + { + Ok(returned_buf) => { + let count = returned_buf.sample_count(); + if count > 0 { + let mut buf = returned_buf; + for _ in 0..count { + if let Some(sample) = buf.pop_front() { + println!("[bigdata-consumer] Received sample x={}", sample.x); + } + } + received_total += count; + println!( + "[bigdata-consumer] Progress: {}/{}", + received_total, num_cycles + ); + buf + } else { + returned_buf + } + } + Err(e) => { + eprintln!("[bigdata-consumer] Receive error: {:?}", e); + std::process::exit(1); + } + }; + } + + println!( + "[bigdata-consumer] Received all {} samples, exiting", + num_cycles + ); +} diff --git a/score/mw/com/test/com_api/consumer_async_apis/integration_test/BUILD b/score/mw/com/test/com_api/consumer_async_apis/integration_test/BUILD new file mode 100644 index 000000000..1083b4eda --- /dev/null +++ b/score/mw/com/test/com_api/consumer_async_apis/integration_test/BUILD @@ -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 +# ******************************************************************************* +load("@rules_pkg//pkg:tar.bzl", "pkg_tar") +load("//quality/integration_testing:integration_testing.bzl", "integration_test") + +pkg_tar( + name = "filesystem", + deps = [ + "//score/mw/com/test/com_api/consumer_async_apis:bigdata-com-api-async-pkg", + ], +) + +integration_test( + name = "test_com_api_async", + timeout = "moderate", + srcs = [ + "com_api_async_api_test.py", + ], + filesystem = ":filesystem", +) diff --git a/score/mw/com/test/com_api/consumer_async_apis/integration_test/com_api_async_api_test.py b/score/mw/com/test/com_api/consumer_async_apis/integration_test/com_api_async_api_test.py new file mode 100644 index 000000000..17e8c07df --- /dev/null +++ b/score/mw/com/test/com_api/consumer_async_apis/integration_test/com_api_async_api_test.py @@ -0,0 +1,19 @@ +# ******************************************************************************* +# 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 +# ******************************************************************************* + + +def test_bigdata_async_exchange(sut): + # Sender runs for 40 cycles, Receiver receives 25 cycles asynchronously + with sut.start_process("./bin/bigdata-producer -n 40", cwd="/opt/bigdata-com-api-async/") as sender_process: + with sut.start_process("./bin/bigdata-consumer-async -n 25", cwd="/opt/bigdata-com-api-async/") as receiver_process: + assert receiver_process.wait_for_exit(timeout=120) == 0 diff --git a/score/mw/com/test/com_api/consumer_sync_apis/BUILD b/score/mw/com/test/com_api/consumer_sync_apis/BUILD new file mode 100644 index 000000000..cc7133c40 --- /dev/null +++ b/score/mw/com/test/com_api/consumer_sync_apis/BUILD @@ -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("@rules_rust//rust:defs.bzl", "rust_binary", "rust_library") +load("//score/mw/com/test:pkg_application.bzl", "pkg_application") + +rust_binary( + name = "bigdata-consumer", + srcs = ["consumer_app.rs"], + features = ["link_std_cpp_lib"], + visibility = [ + "//score/mw/com/test/com_api:__subpackages__", + ], + deps = [ + "//score/mw/com/impl/rust/com-api/com-api", + "//score/mw/com/test/com_api:bigdata_com_api_gen_rs", + "@score_communication_crate_index//:clap", + ], +) + +pkg_application( + name = "bigdata-com-api-sync-pkg", + app_name = "bigdata-com-api-sync", + bin = [ + ":bigdata-consumer", + "//score/mw/com/test/com_api/producer_app:bigdata-producer", + ], + etc = [ + "//score/mw/com/test/com_api/etc:config", + "//score/mw/com/test/bigdata:logging.json", + ], + visibility = [ + "//score/mw/com/test/com_api:__subpackages__", + ], +) diff --git a/score/mw/com/test/com_api/consumer_sync_apis/consumer_app.rs b/score/mw/com/test/com_api/consumer_sync_apis/consumer_app.rs new file mode 100644 index 000000000..08267e4c4 --- /dev/null +++ b/score/mw/com/test/com_api/consumer_sync_apis/consumer_app.rs @@ -0,0 +1,128 @@ +/******************************************************************************** + * 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 + ********************************************************************************/ + +//! Consumer (proxy) binary for the BigData com-api SCT. +//! +//! # Usage +//! +//! ``` +//! bigdata-consumer -n +//! ``` +//! +//! * `-n ` — number of `MapApiLanesStamped` samples to receive +//! before exiting (required). +//! +//! The consumer retries service discovery until the producer is available, +//! then subscribes to `map_api_lanes_stamped_` and reads exactly `num_cycles` +//! samples before exiting with code 0. + +use bigdata_com_api_gen::BigDataInterface; +use clap::Parser; +use com_api::{ + Builder, FindServiceSpecifier, InstanceSpecifier, LolaRuntimeBuilderImpl, Runtime, + RuntimeBuilder, SampleContainer, ServiceDiscovery, Subscriber, Subscription, +}; +use std::path::Path; +use std::thread; +use std::time::Duration; + +const CONFIG_PATH: &str = "etc/config.json"; +const SERVICE_DISCOVERY_RETRY_MS: u64 = 500; +const MAX_SAMPLES_PER_CALL: usize = 5; + +#[derive(Parser)] +struct Args { + /// Number of samples to receive before exiting + #[arg(short = 'n', required = true)] + num_cycles: usize, +} + +fn main() { + let args = Args::parse(); + let num_cycles = args.num_cycles; + + println!( + "[bigdata-consumer] Starting, will receive {} samples", + num_cycles + ); + + // Initialise the Lola runtime. + let mut runtime_builder = LolaRuntimeBuilderImpl::new(); + runtime_builder.load_config(Path::new(CONFIG_PATH)); + let runtime = runtime_builder + .build() + .expect("Failed to build Lola runtime"); + + let instance_specifier = InstanceSpecifier::new("/score/cp60/MapApiLanesStamped") + .expect("Invalid instance specifier"); + let discovery = runtime + .find_service::(FindServiceSpecifier::Specific(instance_specifier)); + + // Retry until the producer has offered the service. + let consumer_builder = loop { + let instances = discovery + .get_available_instances() + .expect("Service discovery failed"); + if let Some(builder) = instances.into_iter().next() { + break builder; + } + println!("[bigdata-consumer] Service not yet available, retrying..."); + thread::sleep(Duration::from_millis(SERVICE_DISCOVERY_RETRY_MS)); + }; + + let consumer = consumer_builder.build().expect("Failed to build consumer"); + + let subscription = consumer + .map_api_lanes_stamped_ + .subscribe(MAX_SAMPLES_PER_CALL) + .expect("Failed to subscribe to map_api_lanes_stamped_"); + + println!( + "[bigdata-consumer] Subscribed, waiting for {} samples", + num_cycles + ); + + let mut received_total: usize = 0; + let mut sample_buf = SampleContainer::new(MAX_SAMPLES_PER_CALL); + + while received_total < num_cycles { + let want = (num_cycles - received_total).min(MAX_SAMPLES_PER_CALL); + match subscription.try_receive(&mut sample_buf, want) { + Ok(0) => { + // No data yet — yield briefly and retry. + thread::sleep(Duration::from_millis(1)); + } + Ok(n) => { + for _ in 0..n { + if let Some(sample) = sample_buf.pop_front() { + println!("[bigdata-consumer] Received sample x={}", sample.x); + } + } + received_total += n; + println!( + "[bigdata-consumer] Progress: {}/{}", + received_total, num_cycles + ); + } + Err(e) => { + eprintln!("[bigdata-consumer] Receive error: {:?}", e); + std::process::exit(1); + } + } + } + + println!( + "[bigdata-consumer] Received all {} samples, exiting", + num_cycles + ); +} diff --git a/score/mw/com/test/com_api/consumer_sync_apis/integration_test/BUILD b/score/mw/com/test/com_api/consumer_sync_apis/integration_test/BUILD new file mode 100644 index 000000000..33b640823 --- /dev/null +++ b/score/mw/com/test/com_api/consumer_sync_apis/integration_test/BUILD @@ -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 +# ******************************************************************************* +load("@rules_pkg//pkg:tar.bzl", "pkg_tar") +load("//quality/integration_testing:integration_testing.bzl", "integration_test") + +pkg_tar( + name = "filesystem", + deps = [ + "//score/mw/com/test/com_api/consumer_sync_apis:bigdata-com-api-sync-pkg", + ], +) + +integration_test( + name = "test_com_api_sync", + timeout = "moderate", + srcs = [ + "com_api_sync_api_test.py", + ], + filesystem = ":filesystem", +) diff --git a/score/mw/com/test/com_api/consumer_sync_apis/integration_test/com_api_sync_api_test.py b/score/mw/com/test/com_api/consumer_sync_apis/integration_test/com_api_sync_api_test.py new file mode 100644 index 000000000..a554bfd4c --- /dev/null +++ b/score/mw/com/test/com_api/consumer_sync_apis/integration_test/com_api_sync_api_test.py @@ -0,0 +1,19 @@ +# ******************************************************************************* +# 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 +# ******************************************************************************* + + +def test_bigdata_exchange(sut): + # Sender runs for 30 cycles, Receiver receives 25 cycles + with sut.start_process("./bin/bigdata-producer -n 30", cwd="/opt/bigdata-com-api-sync/") as sender_process: + with sut.start_process("./bin/bigdata-consumer -n 25", cwd="/opt/bigdata-com-api-sync/") as receiver_process: + assert receiver_process.wait_for_exit(timeout=120) == 0 diff --git a/score/mw/com/test/com_api/etc/BUILD b/score/mw/com/test/com_api/etc/BUILD new file mode 100644 index 000000000..206454775 --- /dev/null +++ b/score/mw/com/test/com_api/etc/BUILD @@ -0,0 +1,18 @@ +# ******************************************************************************* +# 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 +# ******************************************************************************* + +filegroup( + name = "config", + srcs = ["config.json"], + visibility = ["//:__subpackages__"], +) diff --git a/score/mw/com/test/com_api/etc/config.json b/score/mw/com/test/com_api/etc/config.json new file mode 100644 index 000000000..78b87e091 --- /dev/null +++ b/score/mw/com/test/com_api/etc/config.json @@ -0,0 +1,83 @@ +{ + "serviceTypes": [ + { + "serviceTypeName": "/score/adp/MapApiLanesStamped", + "version": { + "major": 1, + "minor": 0 + }, + "bindings": [ + { + "binding": "SHM", + "serviceId": 6432, + "events": [ + { + "eventName": "map_api_lanes_stamped", + "eventId": 1 + }, + { + "eventName": "dummy_data_stamped", + "eventId": 2 + } + ] + } + ] + }, + { + "serviceTypeName": "/score/adp/DummyServiceType", + "version": { + "major": 1, + "minor": 0 + }, + "bindings": [ + { + "binding": "SHM", + "serviceId": 6433, + "events": [ + ] + } + ] + } + ], + "serviceInstances": [ + { + "instanceSpecifier": "/score/cp60/MapApiLanesStamped", + "serviceTypeName": "/score/adp/MapApiLanesStamped", + "version": { + "major": 1, + "minor": 0 + }, + "instances": [ + { + "instanceId": 1, + "allowedConsumer": { + "QM": [ + 4002, + 0 + ] + }, + "allowedProvider": { + "QM": [ + 4001, + 0 + ] + }, + "asil-level": "QM", + "binding": "SHM", + "events": [ + { + "eventName": "map_api_lanes_stamped", + "numberOfSampleSlots": 10, + "maxSubscribers": 3 + }, + { + "eventName": "dummy_data_stamped", + "numberOfSampleSlots": 10, + "maxSubscribers": 3 + } + ] + } + ] + } + ] +} diff --git a/score/mw/com/test/com_api/producer_app/BUILD b/score/mw/com/test/com_api/producer_app/BUILD new file mode 100644 index 000000000..6304a0e41 --- /dev/null +++ b/score/mw/com/test/com_api/producer_app/BUILD @@ -0,0 +1,28 @@ +# ******************************************************************************* +# 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("@rules_rust//rust:defs.bzl", "rust_binary") + +rust_binary( + name = "bigdata-producer", + srcs = ["producer_app.rs"], + features = ["link_std_cpp_lib"], + visibility = [ + "//score/mw/com/test/com_api:__subpackages__", + ], + deps = [ + "//score/mw/com/impl/rust/com-api/com-api", + "//score/mw/com/test/com_api:bigdata_com_api_gen_rs", + "@score_communication_crate_index//:clap", + ], +) diff --git a/score/mw/com/test/com_api/producer_app/producer_app.rs b/score/mw/com/test/com_api/producer_app/producer_app.rs new file mode 100644 index 000000000..7b4e2e1b7 --- /dev/null +++ b/score/mw/com/test/com_api/producer_app/producer_app.rs @@ -0,0 +1,86 @@ +/******************************************************************************** + * 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 + ********************************************************************************/ + +//! Producer (skeleton) binary for the BigData com-api SCT. +//! +//! # Usage +//! +//! ``` +//! bigdata-producer [-n ] +//! ``` +//! * `-n ` — number of samples to send before exiting (default: 40). +//! +//! The producer sends incrementing `MapApiLanesStamped` samples until it has sent +//! `num_cycles` samples, then exits with code 0. +//! It sleeps for a short duration between sends. +use std::path::Path; +use std::thread; +use std::time::Duration; + +use bigdata_com_api_gen::{BigDataInterface, MapApiLanesStamped}; +use clap::Parser; +use com_api::{ + Builder, InstanceSpecifier, LolaRuntimeBuilderImpl, Producer, Publisher, Runtime, + RuntimeBuilder, SampleMaybeUninit, SampleMut, +}; + +const CONFIG_PATH: &str = "etc/config.json"; +const DEFAULT_CYCLES: u32 = 40; +const SERVICE_OFFER_DELAY_MS: u64 = 2000; +const SEND_INTERVAL_MS: u64 = 100; + +#[derive(Parser)] +struct Args { + /// Number of samples to send before exiting + #[arg(short = 'n', default_value_t = DEFAULT_CYCLES)] + num_cycles: u32, +} + +fn main() { + let args = Args::parse(); + let num_cycles = args.num_cycles; + + println!("[bigdata-producer] Starting with num_cycles={}", num_cycles); + + // Initialise the Lola runtime. + let mut runtime_builder = LolaRuntimeBuilderImpl::new(); + runtime_builder.load_config(Path::new(CONFIG_PATH)); + let runtime = runtime_builder + .build() + .expect("Failed to build Lola runtime"); + + // Create the producer and offer the service. + let instance_specifier = InstanceSpecifier::new("/score/cp60/MapApiLanesStamped") + .expect("Invalid instance specifier"); + // Sleep for a few seconds before offering the service to allow the consumer to start first and demonstrate service discovery retries. + thread::sleep(Duration::from_millis(SERVICE_OFFER_DELAY_MS)); + + let producer_builder = runtime.producer_builder::(instance_specifier); + let producer = producer_builder.build().expect("Failed to build producer"); + let offered = producer.offer().expect("Failed to offer service"); + + println!("[bigdata-producer] Service offered, starting send loop"); + for x in 0..num_cycles { + let uninit = offered + .map_api_lanes_stamped_ + .allocate() + .expect("Failed to allocate sample"); + let mut sample = MapApiLanesStamped::default(); + sample.x = x; + let ready = uninit.write(sample); + ready.send().expect("Failed to send sample"); + println!("[bigdata-producer] Sent sample x={}", x); + + thread::sleep(Duration::from_millis(SEND_INTERVAL_MS)); + } +}