From 6f8015e9986fd3bc550981344771d25c92f08213 Mon Sep 17 00:00:00 2001 From: soldier-sky Date: Wed, 15 Apr 2026 14:52:27 +0200 Subject: [PATCH 1/7] Add useGetIfAvailable/useSetIfAvailable to LoLa field deployment - Introduce dedicated LolaFieldInstanceDeployment class replacing the former LolaEventInstanceDeployment type alias, adding field-specific members use_get_if_available_ and use_set_if_available_. - Fix mw_com_config_schema.json: move useGetIfAvailable and useSetIfAvailable into the field "properties" object so they are correctly validated when additionalProperties is false. Issue: SWP-250429 --- score/mw/com/impl/configuration/BUILD | 5 +- .../lola_field_instance_deployment.cpp | 178 +++++++++++++++++- .../lola_field_instance_deployment.h | 71 ++++++- .../configuration/mw_com_config_schema.json | 28 ++- 4 files changed, 271 insertions(+), 11 deletions(-) diff --git a/score/mw/com/impl/configuration/BUILD b/score/mw/com/impl/configuration/BUILD index 381d94969..2dd8a2d53 100644 --- a/score/mw/com/impl/configuration/BUILD +++ b/score/mw/com/impl/configuration/BUILD @@ -203,7 +203,10 @@ cc_library( hdrs = ["lola_field_instance_deployment.h"], features = COMPILER_WARNING_FEATURES, tags = ["FFI"], - deps = [":lola_event_instance_deployment"], + deps = [ + ":lola_event_instance_deployment", + ":configuration_common_resources", + ], ) cc_library( diff --git a/score/mw/com/impl/configuration/lola_field_instance_deployment.cpp b/score/mw/com/impl/configuration/lola_field_instance_deployment.cpp index 964c2dc44..1b532669e 100644 --- a/score/mw/com/impl/configuration/lola_field_instance_deployment.cpp +++ b/score/mw/com/impl/configuration/lola_field_instance_deployment.cpp @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2025 Contributors to the Eclipse Foundation + * Copyright (c) 2026 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -11,3 +11,179 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ #include "score/mw/com/impl/configuration/lola_field_instance_deployment.h" + +#include "score/mw/com/impl/configuration/configuration_common_resources.h" + +#include "score/mw/log/logging.h" + +#include +#include + +namespace score::mw::com::impl +{ + +namespace +{ + +constexpr auto kNumberOfSampleSlotsKey = "numberOfSampleSlots"; +constexpr auto kSubscribersKey = "maxSubscribers"; +constexpr auto kMaxConcurrentAllocationsKey = "maxConcurrentAllocations"; +constexpr auto kEnforceMaxSamplesKey = "enforceMaxSamples"; +constexpr auto kNumberOfIpcTracingSlotsKey = "numberOfIpcTracingSlots"; +constexpr auto kUseGetIfAvailableKey = "useGetIfAvailable"; +constexpr auto kUseSetIfAvailableKey = "useSetIfAvailable"; +constexpr LolaFieldInstanceDeployment::TracingSlotSizeType kNumberOfIpcTracingSlotsDefault{0U}; + +} // namespace + +LolaFieldInstanceDeployment::LolaFieldInstanceDeployment(std::optional number_of_sample_slots, + std::optional max_subscribers, + std::optional max_concurrent_allocations, + const bool enforce_max_samples, + const TracingSlotSizeType number_of_tracing_slots, + const bool use_get_if_available, + const bool use_set_if_available) noexcept + : max_subscribers_{max_subscribers}, + max_concurrent_allocations_{max_concurrent_allocations}, + enforce_max_samples_{enforce_max_samples}, + use_get_if_available_{use_get_if_available}, + use_set_if_available_{use_set_if_available}, + number_of_sample_slots_{number_of_sample_slots}, + number_of_tracing_slots_{number_of_tracing_slots} +{ +} + +LolaFieldInstanceDeployment::LolaFieldInstanceDeployment(const score::json::Object& json_object) noexcept + : LolaFieldInstanceDeployment(LolaFieldInstanceDeployment::CreateFromJson(json_object)) +{ +} + +LolaFieldInstanceDeployment LolaFieldInstanceDeployment::CreateFromJson(const score::json::Object& json_object) noexcept +{ + + const auto serialization_version = GetValueFromJson(json_object, kSerializationVersionKey); + if (serialization_version != serializationVersion) + { + std::terminate(); + } + + const auto number_of_sample_slots = + GetOptionalValueFromJson(json_object, kNumberOfSampleSlotsKey); + const auto max_subscribers = GetOptionalValueFromJson(json_object, kSubscribersKey); + const auto max_concurrent_allocations = + GetOptionalValueFromJson(json_object, kMaxConcurrentAllocationsKey); + const auto enforce_max_samples = GetValueFromJson(json_object, kEnforceMaxSamplesKey); + const auto number_of_tracing_slots_opt = + GetOptionalValueFromJson(json_object, kNumberOfIpcTracingSlotsKey); + + auto number_of_tracing_slots = number_of_tracing_slots_opt.value_or(kNumberOfIpcTracingSlotsDefault); + + // getter and setters are optional fields. If not provided, we set them to false as default value. + const auto use_get_if_available = + GetOptionalValueFromJson(json_object, kUseGetIfAvailableKey).value_or(false); + const auto use_set_if_available = + GetOptionalValueFromJson(json_object, kUseSetIfAvailableKey).value_or(false); + + return LolaFieldInstanceDeployment(number_of_sample_slots, + max_subscribers, + max_concurrent_allocations, + enforce_max_samples, + number_of_tracing_slots, + use_get_if_available, + use_set_if_available); +} + +// Suppress "AUTOSAR C++14 A15-5-3" rule finding. This rule states: "The std::terminate() function shall not be called +// implicitly" +// false positive std::bad_optional_access. We check and early exit in case the optional is empty. +// coverity[autosar_cpp14_a15_5_3_violation] +score::json::Object LolaFieldInstanceDeployment::Serialize() const noexcept +{ + score::json::Object json_object{}; + if (number_of_sample_slots_.has_value()) + { + json_object[kNumberOfSampleSlotsKey] = score::json::Any{number_of_sample_slots_.value()}; + } + if (max_subscribers_.has_value()) + { + json_object[kSubscribersKey] = score::json::Any{max_subscribers_.value()}; + } + json_object[kSerializationVersionKey] = json::Any{serializationVersion}; + + if (max_concurrent_allocations_.has_value()) + { + json_object[kMaxConcurrentAllocationsKey] = score::json::Any{max_concurrent_allocations_.value()}; + } + + json_object[kEnforceMaxSamplesKey] = score::json::Any{enforce_max_samples_}; + + // We always turn of ipc tracing. I.e., serialize kNumberOfIpcTracingSlotsKey as false + json_object[kNumberOfIpcTracingSlotsKey] = static_cast(0U); + + json_object[kUseGetIfAvailableKey] = score::json::Any{use_get_if_available_}; + json_object[kUseSetIfAvailableKey] = score::json::Any{use_set_if_available_}; + + return json_object; +} + +// Suppress "AUTOSAR C++14 A15-5-3" rule finding. This rule states: "The std::terminate() function shall not be called +// implicitly" +// false positive std::bad_optional_access. We check and early exit in case the optional is empty. +// coverity[autosar_cpp14_a15_5_3_violation] +auto LolaFieldInstanceDeployment::GetNumberOfSampleSlots() const noexcept -> std::optional +{ + if (!number_of_sample_slots_.has_value()) + { + return {}; + } + + const auto intermediate = static_cast(number_of_sample_slots_.value()) + + static_cast(number_of_tracing_slots_); + if (intermediate > std::numeric_limits::max()) + { + ::score::mw::log::LogFatal("lola") + << "Number of sample slots + number of tracing slots exceeds sample slot limit. Terminating."; + SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(false); + } + return static_cast(intermediate); +} + +auto LolaFieldInstanceDeployment::GetNumberOfSampleSlotsExcludingTracingSlot() const noexcept + -> std::optional +{ + if (!number_of_sample_slots_.has_value()) + { + return {}; + } + return *number_of_sample_slots_; +} + +auto LolaFieldInstanceDeployment::GetNumberOfTracingSlots() const noexcept -> TracingSlotSizeType +{ + return number_of_tracing_slots_; +} + +void LolaFieldInstanceDeployment::SetNumberOfSampleSlots(SampleSlotCountType number_of_sample_slots) noexcept +{ + + number_of_sample_slots_ = number_of_sample_slots; +} + +bool operator==(const LolaFieldInstanceDeployment& lhs, const LolaFieldInstanceDeployment& rhs) noexcept +{ + const bool number_of_sample_slots_equal = (lhs.number_of_sample_slots_ == rhs.number_of_sample_slots_); + const bool number_of_tracing_slots_equal = (lhs.number_of_tracing_slots_ == rhs.number_of_tracing_slots_); + const bool max_subscribers_equal = (lhs.max_subscribers_ == rhs.max_subscribers_); + const bool max_concurrent_allocations_equal = (lhs.max_concurrent_allocations_ == rhs.max_concurrent_allocations_); + const bool enforce_max_samples_equal = (lhs.enforce_max_samples_ == rhs.enforce_max_samples_); + const bool use_get_if_available_equal = (lhs.use_get_if_available_ == rhs.use_get_if_available_); + const bool use_set_if_available_equal = (lhs.use_set_if_available_ == rhs.use_set_if_available_); + // Adding Brackets to the expression does not give additional value since only one logical operator is used which + // is independent of the execution order + // coverity[autosar_cpp14_a5_2_6_violation] + return (number_of_sample_slots_equal && number_of_tracing_slots_equal && max_subscribers_equal && + max_concurrent_allocations_equal && enforce_max_samples_equal && + use_get_if_available_equal && use_set_if_available_equal); +} + +} // namespace score::mw::com::impl diff --git a/score/mw/com/impl/configuration/lola_field_instance_deployment.h b/score/mw/com/impl/configuration/lola_field_instance_deployment.h index 8e8d98e0a..1b80d071f 100644 --- a/score/mw/com/impl/configuration/lola_field_instance_deployment.h +++ b/score/mw/com/impl/configuration/lola_field_instance_deployment.h @@ -13,12 +13,79 @@ #ifndef SCORE_MW_COM_IMPL_CONFIGURATION_LOLA_FIELD_INSTANCE_DEPLOYMENT_H #define SCORE_MW_COM_IMPL_CONFIGURATION_LOLA_FIELD_INSTANCE_DEPLOYMENT_H -#include "score/mw/com/impl/configuration/lola_event_instance_deployment.h" +#include "score/json/json_parser.h" + +#include + +#include +#include +#include namespace score::mw::com::impl { -using LolaFieldInstanceDeployment = LolaEventInstanceDeployment; +class LolaFieldInstanceDeployment +{ + public: + using SampleSlotCountType = std::uint16_t; + using SubscriberCountType = std::uint8_t; + using TracingSlotSizeType = std::uint8_t; + + explicit LolaFieldInstanceDeployment(std::optional number_of_sample_slots, + std::optional max_subscribers, + std::optional max_concurrent_allocations, + const bool enforce_max_samples, + const TracingSlotSizeType number_of_tracing_slots, + const bool use_get_if_available, + const bool use_set_if_available) noexcept; + + explicit LolaFieldInstanceDeployment(const score::json::Object& json_object) noexcept; + + static LolaFieldInstanceDeployment CreateFromJson(const score::json::Object& json_object) noexcept; + + score::json::Object Serialize() const noexcept; + + void SetNumberOfSampleSlots(SampleSlotCountType number_of_sample_slots) noexcept; + + [[nodiscard]] std::optional GetNumberOfSampleSlots() const noexcept; + [[nodiscard]] std::optional GetNumberOfSampleSlotsExcludingTracingSlot() const noexcept; + + [[nodiscard]] TracingSlotSizeType GetNumberOfTracingSlots() const noexcept; + + /// \brief max subscribers slots is only relevant/required on skeleton side. On the proxy side it is irrelevant. + /// Therefore, it is optional! + // Note the struct is not compliant to POD type containing non-POD member. + // The struct is used as a config storage obtained by performing the parsing json object. + // Public access is more convenient to reach the following members of the struct. + // coverity[autosar_cpp14_m11_0_1_violation] + std::optional max_subscribers_; + // coverity[autosar_cpp14_m11_0_1_violation] + std::optional max_concurrent_allocations_; + // coverity[autosar_cpp14_m11_0_1_violation] + bool enforce_max_samples_; + // coverity[autosar_cpp14_m11_0_1_violation] + bool use_get_if_available_{false}; + // coverity[autosar_cpp14_m11_0_1_violation] + bool use_set_if_available_{false}; + + // False positive, variable is used outside of the file. + // coverity[autosar_cpp14_a0_1_1_violation : FALSE] + constexpr static std::uint32_t serializationVersion = 1U; + + friend bool operator==(const LolaFieldInstanceDeployment& lhs, const LolaFieldInstanceDeployment& rhs) noexcept; + + private: + /// \brief number of sample slots is only relevant/required on skeleton side, where slots get allocated. On the + /// proxy side it is irrelevant. Therefore, it is optional! + std::optional number_of_sample_slots_; + // Non-zero values greater than one for this parameter only make sense on the skeleton side. For the proxy it is + // just important if the tracing is enabled or not, i.e., if this variable is zero or non-zero. + TracingSlotSizeType number_of_tracing_slots_; + +}; + +bool operator==(const LolaFieldInstanceDeployment& lhs, const LolaFieldInstanceDeployment& rhs) noexcept; + } // namespace score::mw::com::impl diff --git a/score/mw/com/impl/configuration/mw_com_config_schema.json b/score/mw/com/impl/configuration/mw_com_config_schema.json index a8da3fe74..31b5e251e 100644 --- a/score/mw/com/impl/configuration/mw_com_config_schema.json +++ b/score/mw/com/impl/configuration/mw_com_config_schema.json @@ -50,14 +50,15 @@ "title": "Type of binding", "type": "string", "enum": [ - "SHM" + "SHM", + "SOME/IP" ], "description": "Binding technology" }, "serviceId": { "type": "integer", "title": "Service Id", - "description": "Binding technology specific service id, it might be 16 or 64 bit. For LoLa/Shm we have 16 bit values." + "description": "Binding technology specific service id, it might be 16 or 64 bit. For LoLa/Shm and SOME/IP we have 16 bit values." }, "events": { "type": "array", @@ -81,7 +82,7 @@ "eventId": { "type": "integer", "title": "Service Event Id", - "description": "Binding technology specific event id. LoLa supports 8 bit." + "description": "Binding technology specific event id. LoLa supports 8 bit, while SOME/IP supports 15 bit." } } } @@ -108,7 +109,7 @@ "fieldId": { "type": "integer", "title": "Service Field Id", - "description": "Binding technology specific field id. LoLa supports 8 bit." + "description": "Binding technology specific field id. LoLa supports 8 bit, while SOME/IP supports 15 bit." }, "Get": { "type": "boolean", @@ -143,7 +144,7 @@ }, "methodId": { "type": "integer", - "description": "Binding technology specific method id. LoLa supports 8 bit." + "description": "Binding technology specific method id. LoLa supports 8 bit, while SOME/IP supports 15 bit." } } } @@ -173,7 +174,7 @@ "instanceSpecifier": { "type": "string", "title": "Service Instance Specifier", - "description": "Represents the InstanceSpecifier value. This is itself an AUTOSAR short-name-path (representing a port prototype of a software component instance). For comfort reasons, we allow also the usage of abbreviated short-name-paths (short-name-paths with a number of components starting from root being removed) in case they are still unique within an executable (this json/configuration is a per executable config!). From AUTOSAR concept perspective an executable contains a 'root sw-component', which itself can be a nested composition of AdaptiveApplicationSwComponentTypes). Because of this 'compositing feature' it could be the case, that the direct short-name of a port prototype isn’t unique within the composition making up the executable. In reality however the port names are 95% unique and forcing the usage of lengthy short-name-paths can be annoying! So this translates to the following rules:\n1. A config file with two “instanceSpecifiers”, where one is only a trailing substring of the other is INVALID!\n2. If user code makes a resolve/lookup providing an 'instanceSpecifier' in the form of an abbreviated short-name-path, which turns out NOT being unique with respect to the config, this is a hard programming/configuration fault, which shall lead to an abort." + "description": "Represents the InstanceSpecifier value. This is itself an AUTOSAR short-name-path (representing a port prototype of a software component instance). For comfort reasons, we allow also the usage of abbreviated short-name-paths (short-name-paths with a number of components starting from root being removed) in case they are still unique within an executable (this json/configuration is a per executable config!). From AUTOSAR concept perspective an executable contains a 'root sw-component', which itself can be a nested composition of AdaptiveApplicationSwComponentTypes). Because of this 'compositing feature' it could be the case, that the direct short-name of a port prototype isn\u2019t unique within the composition making up the executable. In reality however the port names are 95% unique and forcing the usage of lengthy short-name-paths can be annoying! So this translates to the following rules:\n1. A config file with two \u201cinstanceSpecifiers\u201d, where one is only a trailing substring of the other is INVALID!\n2. If user code makes a resolve/lookup providing an 'instanceSpecifier' in the form of an abbreviated short-name-path, which turns out NOT being unique with respect to the config, this is a hard programming/configuration fault, which shall lead to an abort." }, "serviceTypeName": { "type": "string", @@ -214,7 +215,8 @@ "binding": { "type": "string", "enum": [ - "SHM" + "SHM", + "SOME/IP" ], "title": "Binding", "description": "Binding technology" @@ -387,6 +389,18 @@ "default": 0, "minimum": 0, "maximum": 255 + }, + "useGetIfAvailable": { + "type": "boolean", + "title": "Use Field Getter If Available", + "description": "When true, the getter for this field will be used if the service type declares one.", + "default": false + }, + "useSetIfAvailable": { + "type": "boolean", + "title": "Use Field Setter If Available", + "description": "When true, the setter for this field will be used if the service type declares one.", + "default": false } } } From 6a83ef64dd62ca840489da568317b7f4fbd9e5c5 Mon Sep 17 00:00:00 2001 From: soldier-sky Date: Wed, 15 Apr 2026 15:24:37 +0200 Subject: [PATCH 2/7] Update config parser to read useGetIfAvailable/useSetIfAvailable - Update config_parser.cpp to read optional field values useGetIfAvailable/useSetIfAvailable - Fix existing unit test of loloa field instance deployment. Issue: SWP-250429 --- score/mw/com/impl/configuration/BUILD | 2 +- score/mw/com/impl/configuration/config_parser.cpp | 10 +++++++++- .../lola_field_instance_deployment.cpp | 4 ++-- .../lola_field_instance_deployment.h | 2 -- .../lola_field_instance_deployment_test.cpp | 12 +++++++++--- .../test/configuration_test_resources.cpp | 15 ++++++++++++--- .../test/configuration_test_resources.h | 4 +++- 7 files changed, 36 insertions(+), 13 deletions(-) diff --git a/score/mw/com/impl/configuration/BUILD b/score/mw/com/impl/configuration/BUILD index 2dd8a2d53..4a7b1d284 100644 --- a/score/mw/com/impl/configuration/BUILD +++ b/score/mw/com/impl/configuration/BUILD @@ -204,8 +204,8 @@ cc_library( features = COMPILER_WARNING_FEATURES, tags = ["FFI"], deps = [ - ":lola_event_instance_deployment", ":configuration_common_resources", + ":lola_event_instance_deployment", ], ) diff --git a/score/mw/com/impl/configuration/config_parser.cpp b/score/mw/com/impl/configuration/config_parser.cpp index 3c0db69cd..19411c83f 100644 --- a/score/mw/com/impl/configuration/config_parser.cpp +++ b/score/mw/com/impl/configuration/config_parser.cpp @@ -81,6 +81,8 @@ constexpr auto kFieldNumberOfSampleSlotsKey = "numberOfSampleSlots"sv; constexpr auto kFieldMaxSubscribersKey = "maxSubscribers"sv; constexpr auto kFieldEnforceMaxSamplesKey = "enforceMaxSamples"sv; constexpr auto kFieldMaxConcurrentAllocationsKey = "maxConcurrentAllocations"sv; +constexpr auto kFieldUseGetIfAvailableKey = "useGetIfAvailable"sv; +constexpr auto kFieldUseSetIfAvailableKey = "useSetIfAvailable"sv; constexpr auto kLolaShmSizeKey = "shm-size"sv; constexpr auto kLolaControlAsilBShmSizeKey = "control-asil-b-shm-size"sv; constexpr auto kLolaControlQmShmSizeKey = "control-qm-shm-size"sv; @@ -491,12 +493,18 @@ auto ParseLolaFieldInstanceDeployment(const score::json::Object& json_map, LolaS const auto number_of_tracing_slots = deployment_parser.RetrieveJsonElement(kNumberOfIpcTracingSlotsKey) .value_or(kNumberOfIpcTracingSlotsDefault); + const auto use_get_if_available = + deployment_parser.RetrieveJsonElement(kFieldUseGetIfAvailableKey).value_or(false); + const auto use_set_if_available = + deployment_parser.RetrieveJsonElement(kFieldUseSetIfAvailableKey).value_or(false); auto field_deployment = LolaFieldInstanceDeployment(number_of_sample_slots, max_subscribers, kMaxConcurrentAllocationsDefault, enforce_max_samples, - number_of_tracing_slots); + number_of_tracing_slots, + use_get_if_available, + use_set_if_available); const auto emplace_result = service.fields_.emplace(std::piecewise_construct, std::forward_as_tuple(std::move(field_name_value)), std::forward_as_tuple(field_deployment)); diff --git a/score/mw/com/impl/configuration/lola_field_instance_deployment.cpp b/score/mw/com/impl/configuration/lola_field_instance_deployment.cpp index 1b532669e..ef13e7071 100644 --- a/score/mw/com/impl/configuration/lola_field_instance_deployment.cpp +++ b/score/mw/com/impl/configuration/lola_field_instance_deployment.cpp @@ -182,8 +182,8 @@ bool operator==(const LolaFieldInstanceDeployment& lhs, const LolaFieldInstanceD // is independent of the execution order // coverity[autosar_cpp14_a5_2_6_violation] return (number_of_sample_slots_equal && number_of_tracing_slots_equal && max_subscribers_equal && - max_concurrent_allocations_equal && enforce_max_samples_equal && - use_get_if_available_equal && use_set_if_available_equal); + max_concurrent_allocations_equal && enforce_max_samples_equal && use_get_if_available_equal && + use_set_if_available_equal); } } // namespace score::mw::com::impl diff --git a/score/mw/com/impl/configuration/lola_field_instance_deployment.h b/score/mw/com/impl/configuration/lola_field_instance_deployment.h index 1b80d071f..ba7ae1b49 100644 --- a/score/mw/com/impl/configuration/lola_field_instance_deployment.h +++ b/score/mw/com/impl/configuration/lola_field_instance_deployment.h @@ -81,12 +81,10 @@ class LolaFieldInstanceDeployment // Non-zero values greater than one for this parameter only make sense on the skeleton side. For the proxy it is // just important if the tracing is enabled or not, i.e., if this variable is zero or non-zero. TracingSlotSizeType number_of_tracing_slots_; - }; bool operator==(const LolaFieldInstanceDeployment& lhs, const LolaFieldInstanceDeployment& rhs) noexcept; - } // namespace score::mw::com::impl #endif // SCORE_MW_COM_IMPL_CONFIGURATION_LOLA_FIELD_INSTANCE_DEPLOYMENT_H diff --git a/score/mw/com/impl/configuration/lola_field_instance_deployment_test.cpp b/score/mw/com/impl/configuration/lola_field_instance_deployment_test.cpp index da2375a23..8eab545e0 100644 --- a/score/mw/com/impl/configuration/lola_field_instance_deployment_test.cpp +++ b/score/mw/com/impl/configuration/lola_field_instance_deployment_test.cpp @@ -39,9 +39,15 @@ TEST_F(LolaFieldInstanceDeploymentFixture, CanCreateFromSerializedObjectWithoutO const std::optional max_subscribers{13}; const std::optional max_concurrent_allocations{}; const bool enforce_max_samples{true}; - - const LolaFieldInstanceDeployment unit{ - MakeLolaFieldInstanceDeployment(max_samples, max_subscribers, max_concurrent_allocations, enforce_max_samples)}; + const auto use_get_if_available{false}; + const auto use_set_if_available{false}; + + const LolaFieldInstanceDeployment unit{MakeLolaFieldInstanceDeployment(max_samples, + max_subscribers, + max_concurrent_allocations, + enforce_max_samples, + use_get_if_available, + use_set_if_available)}; const auto serialized_unit{unit.Serialize()}; diff --git a/score/mw/com/impl/configuration/test/configuration_test_resources.cpp b/score/mw/com/impl/configuration/test/configuration_test_resources.cpp index 0f29a54bc..9b90b347a 100644 --- a/score/mw/com/impl/configuration/test/configuration_test_resources.cpp +++ b/score/mw/com/impl/configuration/test/configuration_test_resources.cpp @@ -49,10 +49,17 @@ LolaFieldInstanceDeployment MakeLolaFieldInstanceDeployment( const std::optional max_subscribers, const std::optional max_concurrent_allocations, bool enforce_max_samples, - std::uint8_t number_of_tracing_slots) noexcept + std::uint8_t number_of_tracing_slots, + const bool use_get_if_available, + const bool use_set_if_available) noexcept { - const LolaFieldInstanceDeployment unit{ - max_samples, max_subscribers, max_concurrent_allocations, enforce_max_samples, number_of_tracing_slots}; + const LolaFieldInstanceDeployment unit{max_samples, + max_subscribers, + max_concurrent_allocations, + enforce_max_samples, + number_of_tracing_slots, + use_get_if_available, + use_set_if_available}; return unit; } @@ -154,6 +161,8 @@ void ConfigurationStructsFixture::ExpectLolaFieldInstanceDeploymentObjectsEqual( EXPECT_EQ(lhs.max_concurrent_allocations_, rhs.max_concurrent_allocations_); EXPECT_EQ(lhs.enforce_max_samples_, rhs.enforce_max_samples_); EXPECT_EQ(lhs.GetNumberOfSampleSlotsExcludingTracingSlot(), rhs.GetNumberOfSampleSlotsExcludingTracingSlot()); + EXPECT_EQ(lhs.use_get_if_available_, rhs.use_get_if_available_); + EXPECT_EQ(lhs.use_set_if_available_, rhs.use_set_if_available_); } void ConfigurationStructsFixture::ExpectLolaMethodInstanceDeploymentObjectsEqual( diff --git a/score/mw/com/impl/configuration/test/configuration_test_resources.h b/score/mw/com/impl/configuration/test/configuration_test_resources.h index 787b7d680..a20c81f03 100644 --- a/score/mw/com/impl/configuration/test/configuration_test_resources.h +++ b/score/mw/com/impl/configuration/test/configuration_test_resources.h @@ -52,7 +52,9 @@ LolaFieldInstanceDeployment MakeLolaFieldInstanceDeployment( const std::optional max_subscribers = 13U, const std::optional max_concurrent_allocations = 14U, const bool enforce_max_samples = true, - std::uint8_t number_of_tracing_slots = 1U) noexcept; + std::uint8_t number_of_tracing_slots = 1U, + const bool use_get_if_available = false, + const bool use_set_if_available = false) noexcept; LolaMethodInstanceDeployment MakeDefaultLolaMethodInstanceDeployment() noexcept; From 18752510c478c1f6bf81cb5d290e438dd3518638 Mon Sep 17 00:00:00 2001 From: soldier-sky Date: Thu, 16 Apr 2026 13:37:39 +0200 Subject: [PATCH 3/7] Adapt existing tests to support fields with optional setter/getter Update existing tests which refer LolaFieldInstanceDeployment to support additional optional useGetIfAvailable and useSetIfAvailable Issue: SWP-250429 --- .../com/impl/bindings/lola/skeleton_test.cpp | 4 +- .../lola/test/proxy_component_test.cpp | 2 +- .../lola/test/skeleton_component_test.cpp | 2 +- .../lola/test/skeleton_test_resources.h | 4 +- .../impl/configuration/configuration_test.cpp | 5 ++- .../lola_service_instance_deployment_test.cpp | 4 +- ...proxy_event_field_binding_factory_test.cpp | 2 +- ...n_service_element_binding_factory_test.cpp | 8 ++-- .../dummy_instance_identifier_builder.cpp | 3 +- .../test/dummy_instance_identifier_builder.h | 2 +- .../configuration/tracing_filter_config.cpp | 39 +++++++++++-------- .../tracing_filter_config_test.cpp | 9 ++++- .../tracing/skeleton_event_tracing_test.cpp | 2 +- 13 files changed, 51 insertions(+), 35 deletions(-) diff --git a/score/mw/com/impl/bindings/lola/skeleton_test.cpp b/score/mw/com/impl/bindings/lola/skeleton_test.cpp index 2b5f18209..0ea96cdfb 100644 --- a/score/mw/com/impl/bindings/lola/skeleton_test.cpp +++ b/score/mw/com/impl/bindings/lola/skeleton_test.cpp @@ -1167,9 +1167,9 @@ TEST_P(SkeletonRegisterParamaterisedFixture, ValidEventMetaInfoExistAfterEventIs fields_.emplace(test::kDumbEventName, dumb_event); lola_field_inst_depls.push_back( - {test::kFooEventName, LolaFieldInstanceDeployment{number_of_slots, 10U, 1U, true, 0}}); + {test::kFooEventName, LolaFieldInstanceDeployment{number_of_slots, 10U, 1U, true, 0, false, false}}); lola_field_inst_depls.push_back( - {test::kDumbEventName, LolaFieldInstanceDeployment{number_of_slots, 10U, 1U, true, 0}}); + {test::kDumbEventName, LolaFieldInstanceDeployment{number_of_slots, 10U, 1U, true, 0, false, false}}); } ServiceInstanceDeployment service_instance_deployment{ test::kFooService, diff --git a/score/mw/com/impl/bindings/lola/test/proxy_component_test.cpp b/score/mw/com/impl/bindings/lola/test/proxy_component_test.cpp index b8d7b7719..98e8e353d 100644 --- a/score/mw/com/impl/bindings/lola/test/proxy_component_test.cpp +++ b/score/mw/com/impl/bindings/lola/test/proxy_component_test.cpp @@ -111,7 +111,7 @@ class ProxyWithRealMemFixture : public ::testing::Test LolaServiceInstanceDeployment lola_service_instance_deployment{ LolaServiceInstanceId{kElementFqId.instance_id_}, {{kEventName, LolaEventInstanceDeployment{10U, 10U, 2U, true, 0}}, - {kNonProvidedEventName, LolaFieldInstanceDeployment{10U, 10U, 2U, true, 0}}}}; + {kNonProvidedEventName, LolaEventInstanceDeployment{10U, 10U, 2U, true, 0}}}}; LolaServiceTypeDeployment lola_service_type_deployment{ kElementFqId.service_id_, {{kEventName, LolaEventId{kElementFqId.element_id_}}, diff --git a/score/mw/com/impl/bindings/lola/test/skeleton_component_test.cpp b/score/mw/com/impl/bindings/lola/test/skeleton_component_test.cpp index 0148099c6..9c93b00b2 100644 --- a/score/mw/com/impl/bindings/lola/test/skeleton_component_test.cpp +++ b/score/mw/com/impl/bindings/lola/test/skeleton_component_test.cpp @@ -187,7 +187,7 @@ class SkeletonComponentTestFixture : public ::testing::Test {test::kFooEventName, LolaEventInstanceDeployment{kNumberOfSlots, 10U, 1U, true, 0}}); fields_.emplace(test::kFooFieldName, mock_field_binding_); lola_field_instance_deployments_.push_back( - {test::kFooFieldName, LolaEventInstanceDeployment{kNumberOfSlots, 10U, 1U, true, 0}}); + {test::kFooFieldName, LolaFieldInstanceDeployment{kNumberOfSlots, 10U, 1U, true, 0, false, false}}); service_instance_deployment_ = std::make_unique( test::kFooService, CreateLolaServiceInstanceDeployment(test::kDefaultLolaInstanceId, diff --git a/score/mw/com/impl/bindings/lola/test/skeleton_test_resources.h b/score/mw/com/impl/bindings/lola/test/skeleton_test_resources.h index 64252e9f3..33a6a59a9 100644 --- a/score/mw/com/impl/bindings/lola/test/skeleton_test_resources.h +++ b/score/mw/com/impl/bindings/lola/test/skeleton_test_resources.h @@ -239,7 +239,7 @@ static const ServiceInstanceDeployment kValidInstanceDeploymentWithField{ CreateLolaServiceInstanceDeployment( kDefaultLolaInstanceId, {}, - {{test::kFooEventName, LolaFieldInstanceDeployment{test::kMaxSlots, 10U, 1U, true, 0}}}, + {{test::kFooEventName, LolaFieldInstanceDeployment{test::kMaxSlots, 10U, 1U, true, 0, false, false}}}, {}, {}, {}, @@ -284,7 +284,7 @@ static const ServiceInstanceDeployment kValidAsilInstanceDeploymentWithField{ CreateLolaServiceInstanceDeployment( kDefaultLolaInstanceId, {}, - {{test::kFooEventName, LolaFieldInstanceDeployment{test::kMaxSlots, 10U, 1U, true, 0}}}, + {{test::kFooEventName, LolaFieldInstanceDeployment{test::kMaxSlots, 10U, 1U, true, 0, false, false}}}, {}, {}, {}, diff --git a/score/mw/com/impl/configuration/configuration_test.cpp b/score/mw/com/impl/configuration/configuration_test.cpp index ba1a21209..a1e6eaf4a 100644 --- a/score/mw/com/impl/configuration/configuration_test.cpp +++ b/score/mw/com/impl/configuration/configuration_test.cpp @@ -184,8 +184,9 @@ TEST_F(ConfigurationFixture, ConfigIsCorrectlyParsedFromFile) const std::vector allowed_provider_ids_b{15}; const LolaEventInstanceDeployment lola_event_instance{event_max_samples, event_max_subscribers, 1U, true, 0}; - const LolaFieldInstanceDeployment lola_field_instance{field_max_samples, field_max_subscribers, 1U, true, 7}; - const LolaMethodInstanceDeployment lola_method_instance{method_queue_size, true}; + const LolaFieldInstanceDeployment lola_field_instance{ + field_max_samples, field_max_subscribers, 1U, true, 7, false, false}; + const LolaMethodInstanceDeployment lola_method_instance{method_queue_size}; const LolaServiceInstanceDeployment::EventInstanceMapping instance_events{ {instance_event_name, lola_event_instance}}; diff --git a/score/mw/com/impl/configuration/lola_service_instance_deployment_test.cpp b/score/mw/com/impl/configuration/lola_service_instance_deployment_test.cpp index 9d02846c9..e8a1dd5f8 100644 --- a/score/mw/com/impl/configuration/lola_service_instance_deployment_test.cpp +++ b/score/mw/com/impl/configuration/lola_service_instance_deployment_test.cpp @@ -122,7 +122,7 @@ TEST(LolaServiceInstanceDeployment, ContainsEventReturnsFalseIfEventMissing) TEST(LolaServiceInstanceDeployment, ContainsFieldReturnsTrueIfEventPresent) { LolaServiceInstanceDeployment unit{LolaServiceInstanceId{LolaServiceInstanceId{2U}}}; - auto temp = MakeDefaultLolaEventInstanceDeployment(); + auto temp = MakeLolaFieldInstanceDeployment(); unit.fields_.emplace(std::make_pair("abc", temp)); EXPECT_TRUE(unit.ContainsField("abc")); } @@ -130,7 +130,7 @@ TEST(LolaServiceInstanceDeployment, ContainsFieldReturnsTrueIfEventPresent) TEST(LolaServiceInstanceDeployment, ContainsFieldReturnsFalseIfEventMissing) { LolaServiceInstanceDeployment unit{LolaServiceInstanceId{2U}}; - auto temp = MakeDefaultLolaEventInstanceDeployment(); + auto temp = MakeLolaFieldInstanceDeployment(); unit.fields_.emplace(std::make_pair("abc", temp)); EXPECT_FALSE(unit.ContainsField("def")); } diff --git a/score/mw/com/impl/plumbing/proxy_event_field_binding_factory_test.cpp b/score/mw/com/impl/plumbing/proxy_event_field_binding_factory_test.cpp index 5e61cec99..3a5a21e8d 100644 --- a/score/mw/com/impl/plumbing/proxy_event_field_binding_factory_test.cpp +++ b/score/mw/com/impl/plumbing/proxy_event_field_binding_factory_test.cpp @@ -56,7 +56,7 @@ const LolaServiceInstanceDeployment kLolaServiceInstanceDeployment{ LolaServiceInstanceId{kInstanceId}, {{kDummyEventName, LolaEventInstanceDeployment{{1U}, {3U}, 1U, true, 0}}, {kDummyGenericProxyEventName, LolaEventInstanceDeployment{{1U}, {3U}, 1U, true, 0}}}, - {{kDummyFieldName, LolaFieldInstanceDeployment{{1U}, {3U}, 1U, true, 0}}}}; + {{kDummyFieldName, LolaFieldInstanceDeployment{{1U}, {3U}, 1U, true, 0, false, false}}}}; const LolaServiceTypeDeployment kLolaServiceTypeDeployment{ kServiceId, {{kDummyEventName, kDummyEventId}, {kDummyGenericProxyEventName, kDummyGenericProxyId}}, diff --git a/score/mw/com/impl/plumbing/skeleton_service_element_binding_factory_test.cpp b/score/mw/com/impl/plumbing/skeleton_service_element_binding_factory_test.cpp index 37207dd89..8c619a90a 100644 --- a/score/mw/com/impl/plumbing/skeleton_service_element_binding_factory_test.cpp +++ b/score/mw/com/impl/plumbing/skeleton_service_element_binding_factory_test.cpp @@ -45,7 +45,7 @@ const auto kInstanceSpecifier = InstanceSpecifier::Create(std::string{"/my_dummy const LolaServiceInstanceDeployment kLolaServiceInstanceDeployment{ LolaServiceInstanceId{kInstanceId}, {{kDummyEventName, LolaEventInstanceDeployment{{1U}, {3U}, 1U, true, 0U}}}, - {{kDummyFieldName, LolaFieldInstanceDeployment{{1U}, {3U}, 1U, true, 0U}}}}; + {{kDummyFieldName, LolaFieldInstanceDeployment{{1U}, {3U}, 1U, true, 0U, false, false}}}}; const LolaServiceTypeDeployment kLolaServiceTypeDeployment{kServiceId, {{kDummyEventName, kDummyEventId}}, {{kDummyFieldName, kDummyFieldId}}}; @@ -227,7 +227,7 @@ TEST_P(SkeletonServiceElementBindingFactoryParamaterisedDeathTest, const LolaServiceInstanceDeployment lola_service_instance_deployment_with_invalid_names{ LolaServiceInstanceId{kInstanceId}, {{incorrect_event_name, LolaEventInstanceDeployment{{1U}, {3U}, 1U, true, 0U}}}, - {{incorrect_field_name, LolaFieldInstanceDeployment{{1U}, {3U}, 1U, true, 0U}}}}; + {{incorrect_field_name, LolaFieldInstanceDeployment{{1U}, {3U}, 1U, true, 0U, false, false}}}}; ConfigurationStore config_store_with_invalid_service_element_names{ kInstanceSpecifier, @@ -255,7 +255,7 @@ TEST_P(SkeletonServiceElementBindingFactoryParamaterisedDeathTest, const LolaServiceInstanceDeployment lola_service_instance_deployment_without_event_sample_slots{ LolaServiceInstanceId{kInstanceId}, {{kDummyEventName, LolaEventInstanceDeployment{{}, {3U}, 1U, true, 0U}}}, - {{kDummyFieldName, LolaFieldInstanceDeployment{{}, {3U}, 1U, true, 0U}}}}; + {{kDummyFieldName, LolaFieldInstanceDeployment{{}, {3U}, 1U, true, 0U, false, false}}}}; ConfigurationStore config_store_with_invalid_service_element_names{ kInstanceSpecifier, @@ -284,7 +284,7 @@ TEST_P(SkeletonServiceElementBindingFactoryParamaterisedDeathTest, const LolaServiceInstanceDeployment lola_service_instance_deployment_without_max_subscribers{ LolaServiceInstanceId{kInstanceId}, {{kDummyEventName, LolaEventInstanceDeployment{{1U}, {}, 1U, true, 0U}}}, - {{kDummyFieldName, LolaFieldInstanceDeployment{{2U}, {}, 1U, true, 0U}}}}; + {{kDummyFieldName, LolaFieldInstanceDeployment{{2U}, {}, 1U, true, 0U, false, false}}}}; ConfigurationStore config_store_with_invalid_service_element_names{ kInstanceSpecifier, diff --git a/score/mw/com/impl/test/dummy_instance_identifier_builder.cpp b/score/mw/com/impl/test/dummy_instance_identifier_builder.cpp index e649266a8..a134dddc1 100644 --- a/score/mw/com/impl/test/dummy_instance_identifier_builder.cpp +++ b/score/mw/com/impl/test/dummy_instance_identifier_builder.cpp @@ -48,7 +48,8 @@ InstanceIdentifier DummyInstanceIdentifierBuilder::CreateValidLolaInstanceIdenti InstanceIdentifier DummyInstanceIdentifierBuilder::CreateValidLolaInstanceIdentifierWithField() { - return CreateValidLolaInstanceIdentifierWithField({{"test_field", LolaFieldInstanceDeployment{1, 1, 1, true, 0}}}); + return CreateValidLolaInstanceIdentifierWithField( + {{"test_field", LolaFieldInstanceDeployment{1, 1, 1, true, 0, false, false}}}); } InstanceIdentifier DummyInstanceIdentifierBuilder::CreateValidLolaInstanceIdentifierWithEvent( diff --git a/score/mw/com/impl/test/dummy_instance_identifier_builder.h b/score/mw/com/impl/test/dummy_instance_identifier_builder.h index 5a7c3fba6..2599d791f 100644 --- a/score/mw/com/impl/test/dummy_instance_identifier_builder.h +++ b/score/mw/com/impl/test/dummy_instance_identifier_builder.h @@ -37,7 +37,7 @@ class DummyInstanceIdentifierBuilder const LolaServiceInstanceDeployment::EventInstanceMapping& events); InstanceIdentifier CreateValidLolaInstanceIdentifierWithField(); InstanceIdentifier CreateValidLolaInstanceIdentifierWithField( - const LolaServiceInstanceDeployment::EventInstanceMapping& events); + const LolaServiceInstanceDeployment::FieldInstanceMapping& fields); InstanceIdentifier CreateLolaInstanceIdentifierWithoutInstanceId(); InstanceIdentifier CreateLolaInstanceIdentifierWithoutTypeDeployment(); InstanceIdentifier CreateBlankBindingInstanceIdentifier(); diff --git a/score/mw/com/impl/tracing/configuration/tracing_filter_config.cpp b/score/mw/com/impl/tracing/configuration/tracing_filter_config.cpp index 7deec0178..1e010aa94 100644 --- a/score/mw/com/impl/tracing/configuration/tracing_filter_config.cpp +++ b/score/mw/com/impl/tracing/configuration/tracing_filter_config.cpp @@ -228,15 +228,33 @@ std::size_t FindNumberOfTracingSlots( std::terminate(); } - const auto& service_instance_map = [service_element_type, &lola_service_instance_deployment]() { - if (service_element_type == ServiceElementType::EVENT) + const auto service_element_name = service_element.service_element_name.data(); + + LolaEventInstanceDeployment::TracingSlotSizeType slots_per_tracing_point{0U}; + if (service_element_type == ServiceElementType::EVENT) + { + const auto it = lola_service_instance_deployment->events_.find(service_element_name); + if (it == lola_service_instance_deployment->events_.end()) { - return lola_service_instance_deployment->events_; + score::mw::log::LogFatal("lola") + << "Requested service element (" << service_element << ") does not exist."; + std::terminate(); } - if (service_element_type == ServiceElementType::FIELD) + slots_per_tracing_point = it->second.GetNumberOfTracingSlots(); + } + else if (service_element_type == ServiceElementType::FIELD) + { + const auto it = lola_service_instance_deployment->fields_.find(service_element_name); + if (it == lola_service_instance_deployment->fields_.end()) { - return lola_service_instance_deployment->fields_; + score::mw::log::LogFatal("lola") + << "Requested service element (" << service_element << ") does not exist."; + std::terminate(); } + slots_per_tracing_point = it->second.GetNumberOfTracingSlots(); + } + else + { // LCOV_EXCL_START Defensive programming. // This function is only used internally and only ever called with EVENT or FIELD ServiceElementType, // thus the following lines can never be reached. @@ -244,18 +262,7 @@ std::size_t FindNumberOfTracingSlots( << "Lola: invalid service element (" << service_element_type << ") provided."; std::terminate(); // LCOV_EXCL_STOP - }(); - - const auto service_element_name = service_element.service_element_name.data(); - const auto service_element_name_it = service_instance_map.find(service_element_name); - - if (service_element_name_it == service_instance_map.end()) - { - score::mw::log::LogFatal("lola") - << "Requested service element (" << service_element << ") does not exist."; - std::terminate(); } - const auto slots_per_tracing_point = service_element_name_it->second.GetNumberOfTracingSlots(); number_of_needed_traceing_slots += slots_per_tracing_point; } diff --git a/score/mw/com/impl/tracing/configuration/tracing_filter_config_test.cpp b/score/mw/com/impl/tracing/configuration/tracing_filter_config_test.cpp index f751ac411..f462ab740 100644 --- a/score/mw/com/impl/tracing/configuration/tracing_filter_config_test.cpp +++ b/score/mw/com/impl/tracing/configuration/tracing_filter_config_test.cpp @@ -581,7 +581,14 @@ class ConfigurationFixture : public ::testing::Test Instance MakeLolaServiceInstanceDeployment(std::optional number_of_sample_slots, const TracingSlotSizeType number_of_tracing_slots) { - return Instance(number_of_sample_slots, 1U, 1U, false, number_of_tracing_slots); + if constexpr (std::is_same::value) + { + return Instance(number_of_sample_slots, 1U, 1U, false, number_of_tracing_slots, false, false); + } + else + { + return Instance(number_of_sample_slots, 1U, 1U, false, number_of_tracing_slots); + } } InstanceSpecifier MakeInstanceSpecifier(std::string_view instance_specifier_sv) diff --git a/score/mw/com/impl/tracing/skeleton_event_tracing_test.cpp b/score/mw/com/impl/tracing/skeleton_event_tracing_test.cpp index 2bedf01e5..4231c529f 100644 --- a/score/mw/com/impl/tracing/skeleton_event_tracing_test.cpp +++ b/score/mw/com/impl/tracing/skeleton_event_tracing_test.cpp @@ -51,7 +51,7 @@ const std::string kDummyFieldName{"my_dummy_field"}; const LolaServiceInstanceDeployment kLolaServiceInstanceDeploymentWithEventAndField{ LolaServiceInstanceId{1U}, {{kDummyEventName, LolaEventInstanceDeployment{10U, 10U, 2U, true, 0}}}, - {{kDummyFieldName, LolaFieldInstanceDeployment{10U, 10U, 2U, true, 0}}} + {{kDummyFieldName, LolaFieldInstanceDeployment{10U, 10U, 2U, true, 0, false, false}}} }; const LolaServiceTypeDeployment kLolaServiceTypeDeploymentWithEventAndField{2U, From 5204e0281417f75b8b1305e76e995ae640a799c5 Mon Sep 17 00:00:00 2001 From: soldier-sky Date: Thu, 16 Apr 2026 17:17:42 +0200 Subject: [PATCH 4/7] Add unit tests to verify optional setter and getter field values - Add tests to verfiy behaviour of option field values useGetIfAvailable/useSetIfAvailable Issue: SWP-250429 --- .../impl/configuration/config_parser_test.cpp | 256 ++++++++++++++++++ .../lola_field_instance_deployment_test.cpp | 133 ++++++++- 2 files changed, 376 insertions(+), 13 deletions(-) diff --git a/score/mw/com/impl/configuration/config_parser_test.cpp b/score/mw/com/impl/configuration/config_parser_test.cpp index afe5af94d..b30cdacfc 100644 --- a/score/mw/com/impl/configuration/config_parser_test.cpp +++ b/score/mw/com/impl/configuration/config_parser_test.cpp @@ -2105,6 +2105,262 @@ TEST(ConfigParser, LolaFieldOptionalEnforceMaxSamples) EXPECT_EQ(deploymentInfo.fields_.at("CurrentTemperatureFrontLeft").enforce_max_samples_, false); } +TEST(ConfigParser, LolaFieldUseGetIfAvailableSetToTrue) +{ + // Given a JSON with optional attribute `useGetIfAvailable` set to true for a field + auto j2 = R"( + { + "serviceTypes": [ + { + "serviceTypeName": "/score/ncar/services/TirePressureService", + "version": { + "major": 12, + "minor": 34 + }, + "bindings": [ + { + "binding": "SHM", + "serviceId": 1234, + "fields": [ + { + "fieldName": "CurrentTemperatureFrontLeft", + "fieldId": 20 + } + ] + } + ] + } + ], + "serviceInstances": [ + { + "instanceSpecifier": "abc/abc/TirePressurePort", + "serviceTypeName": "/score/ncar/services/TirePressureService", + "version": { + "major": 12, + "minor": 34 + }, + "instances": [ + { + "instanceId": 1234, + "asil-level": "QM", + "binding": "SHM", + "events": [], + "fields": [ + { + "fieldName": "CurrentTemperatureFrontLeft", + "numberOfSampleSlots": 50, + "maxSubscribers": 5, + "useGetIfAvailable": true + } + ] + } + ] + } + ] + } +)"_json; + const auto config = score::mw::com::impl::configuration::Parse(std::move(j2)); + + const auto deployment = + config.GetServiceInstances().at(InstanceSpecifier::Create(std::string{"abc/abc/TirePressurePort"}).value()); + + const auto deploymentInfo = std::get(deployment.bindingInfo_); + EXPECT_TRUE(deploymentInfo.fields_.at("CurrentTemperatureFrontLeft").use_get_if_available_); + EXPECT_FALSE(deploymentInfo.fields_.at("CurrentTemperatureFrontLeft").use_set_if_available_); +} + +TEST(ConfigParser, LolaFieldUseSetIfAvailableSetToTrue) +{ + // Given a JSON with optional attribute `useSetIfAvailable` set to true for a field + auto j2 = R"( + { + "serviceTypes": [ + { + "serviceTypeName": "/score/ncar/services/TirePressureService", + "version": { + "major": 12, + "minor": 34 + }, + "bindings": [ + { + "binding": "SHM", + "serviceId": 1234, + "fields": [ + { + "fieldName": "CurrentTemperatureFrontLeft", + "fieldId": 20 + } + ] + } + ] + } + ], + "serviceInstances": [ + { + "instanceSpecifier": "abc/abc/TirePressurePort", + "serviceTypeName": "/score/ncar/services/TirePressureService", + "version": { + "major": 12, + "minor": 34 + }, + "instances": [ + { + "instanceId": 1234, + "asil-level": "QM", + "binding": "SHM", + "events": [], + "fields": [ + { + "fieldName": "CurrentTemperatureFrontLeft", + "numberOfSampleSlots": 50, + "maxSubscribers": 5, + "useSetIfAvailable": true + } + ] + } + ] + } + ] + } +)"_json; + const auto config = score::mw::com::impl::configuration::Parse(std::move(j2)); + + const auto deployment = + config.GetServiceInstances().at(InstanceSpecifier::Create(std::string{"abc/abc/TirePressurePort"}).value()); + + const auto deploymentInfo = std::get(deployment.bindingInfo_); + EXPECT_FALSE(deploymentInfo.fields_.at("CurrentTemperatureFrontLeft").use_get_if_available_); + EXPECT_TRUE(deploymentInfo.fields_.at("CurrentTemperatureFrontLeft").use_set_if_available_); +} + +TEST(ConfigParser, LolaFieldOmittingBothFlagsDefaultsBothToFalse) +{ + // Given a JSON for a field without `useGetIfAvailable` or `useSetIfAvailable` + auto j2 = R"( + { + "serviceTypes": [ + { + "serviceTypeName": "/score/ncar/services/TirePressureService", + "version": { + "major": 12, + "minor": 34 + }, + "bindings": [ + { + "binding": "SHM", + "serviceId": 1234, + "fields": [ + { + "fieldName": "CurrentTemperatureFrontLeft", + "fieldId": 20 + } + ] + } + ] + } + ], + "serviceInstances": [ + { + "instanceSpecifier": "abc/abc/TirePressurePort", + "serviceTypeName": "/score/ncar/services/TirePressureService", + "version": { + "major": 12, + "minor": 34 + }, + "instances": [ + { + "instanceId": 1234, + "asil-level": "QM", + "binding": "SHM", + "events": [], + "fields": [ + { + "fieldName": "CurrentTemperatureFrontLeft", + "numberOfSampleSlots": 50, + "maxSubscribers": 5 + } + ] + } + ] + } + ] + } +)"_json; + const auto config = score::mw::com::impl::configuration::Parse(std::move(j2)); + + const auto deployment = + config.GetServiceInstances().at(InstanceSpecifier::Create(std::string{"abc/abc/TirePressurePort"}).value()); + + const auto deploymentInfo = std::get(deployment.bindingInfo_); + EXPECT_FALSE(deploymentInfo.fields_.at("CurrentTemperatureFrontLeft").use_get_if_available_); + EXPECT_FALSE(deploymentInfo.fields_.at("CurrentTemperatureFrontLeft").use_set_if_available_); +} + +TEST(ConfigParser, LolaFieldBothFlagsSetToTrue) +{ + // Given a JSON with both `useGetIfAvailable` and `useSetIfAvailable` set to true for a field + auto j2 = R"( + { + "serviceTypes": [ + { + "serviceTypeName": "/score/ncar/services/TirePressureService", + "version": { + "major": 12, + "minor": 34 + }, + "bindings": [ + { + "binding": "SHM", + "serviceId": 1234, + "fields": [ + { + "fieldName": "CurrentTemperatureFrontLeft", + "fieldId": 20 + } + ] + } + ] + } + ], + "serviceInstances": [ + { + "instanceSpecifier": "abc/abc/TirePressurePort", + "serviceTypeName": "/score/ncar/services/TirePressureService", + "version": { + "major": 12, + "minor": 34 + }, + "instances": [ + { + "instanceId": 1234, + "asil-level": "QM", + "binding": "SHM", + "events": [], + "fields": [ + { + "fieldName": "CurrentTemperatureFrontLeft", + "numberOfSampleSlots": 50, + "maxSubscribers": 5, + "useGetIfAvailable": true, + "useSetIfAvailable": true + } + ] + } + ] + } + ] + } +)"_json; + const auto config = score::mw::com::impl::configuration::Parse(std::move(j2)); + + const auto deployment = + config.GetServiceInstances().at(InstanceSpecifier::Create(std::string{"abc/abc/TirePressurePort"}).value()); + + const auto deploymentInfo = std::get(deployment.bindingInfo_); + EXPECT_TRUE(deploymentInfo.fields_.at("CurrentTemperatureFrontLeft").use_get_if_available_); + EXPECT_TRUE(deploymentInfo.fields_.at("CurrentTemperatureFrontLeft").use_set_if_available_); +} + TEST(ConfigParser, EmptyServiceTypes) { // Given a JSON with necessary attribute `serviceTypes` being empty (which is allowed) diff --git a/score/mw/com/impl/configuration/lola_field_instance_deployment_test.cpp b/score/mw/com/impl/configuration/lola_field_instance_deployment_test.cpp index 8eab545e0..36d3f6520 100644 --- a/score/mw/com/impl/configuration/lola_field_instance_deployment_test.cpp +++ b/score/mw/com/impl/configuration/lola_field_instance_deployment_test.cpp @@ -22,6 +22,15 @@ namespace { using LolaFieldInstanceDeploymentFixture = ConfigurationStructsFixture; + +namespace +{ +constexpr std::uint16_t kMaxSamples{12U}; +constexpr std::uint8_t kMaxSubscribers{13U}; +constexpr std::uint8_t kMaxConcurrentAllocations{14U}; +constexpr bool kEnforceMaxSamples{true}; +constexpr std::uint8_t kNumberOfTracingSlots{1U}; +} // namespace TEST_F(LolaFieldInstanceDeploymentFixture, CanCreateFromSerializedObjectWithOptionals) { const LolaFieldInstanceDeployment unit{MakeLolaFieldInstanceDeployment()}; @@ -35,19 +44,17 @@ TEST_F(LolaFieldInstanceDeploymentFixture, CanCreateFromSerializedObjectWithOpti TEST_F(LolaFieldInstanceDeploymentFixture, CanCreateFromSerializedObjectWithoutOptionals) { - const std::uint16_t max_samples{12}; - const std::optional max_subscribers{13}; - const std::optional max_concurrent_allocations{}; - const bool enforce_max_samples{true}; - const auto use_get_if_available{false}; - const auto use_set_if_available{false}; - - const LolaFieldInstanceDeployment unit{MakeLolaFieldInstanceDeployment(max_samples, - max_subscribers, - max_concurrent_allocations, - enforce_max_samples, - use_get_if_available, - use_set_if_available)}; + + const std::optional kNoMaxConcurrentAllocations{}; + constexpr std::uint8_t kNoTracingSlots{0U}; + + const LolaFieldInstanceDeployment unit{MakeLolaFieldInstanceDeployment(kMaxSamples, + kMaxSubscribers, + kNoMaxConcurrentAllocations, + kEnforceMaxSamples, + kNoTracingSlots, + /*use_get*/ false, + /*use_set*/ false)}; const auto serialized_unit{unit.Serialize()}; @@ -56,6 +63,106 @@ TEST_F(LolaFieldInstanceDeploymentFixture, CanCreateFromSerializedObjectWithoutO ExpectLolaFieldInstanceDeploymentObjectsEqual(reconstructed_unit, unit); } +TEST_F(LolaFieldInstanceDeploymentFixture, UseGetIfAvailableIsTrueAfterRoundTripSerialisation) +{ + // Given a field deployment with use_get_if_available set to true + const LolaFieldInstanceDeployment unit{MakeLolaFieldInstanceDeployment(kMaxSamples, + kMaxSubscribers, + kMaxConcurrentAllocations, + kEnforceMaxSamples, + kNumberOfTracingSlots, + /*use_get*/ true, + /*use_set*/ false)}; + + // When serialising and deserialising + const auto serialized_unit{unit.Serialize()}; + const LolaFieldInstanceDeployment reconstructed_unit{serialized_unit}; + + // Then use_get_if_available is preserved and use_set_if_available is unaffected + EXPECT_TRUE(reconstructed_unit.use_get_if_available_); + EXPECT_FALSE(reconstructed_unit.use_set_if_available_); +} + +TEST_F(LolaFieldInstanceDeploymentFixture, UseSetIfAvailableIsTrueAfterRoundTripSerialisation) +{ + // Given a field deployment with use_set_if_available set to true + const LolaFieldInstanceDeployment unit{MakeLolaFieldInstanceDeployment(kMaxSamples, + kMaxSubscribers, + kMaxConcurrentAllocations, + kEnforceMaxSamples, + kNumberOfTracingSlots, + /*use_get*/ false, + /*use_set*/ true)}; + + // When serialising and deserialising + const auto serialized_unit{unit.Serialize()}; + const LolaFieldInstanceDeployment reconstructed_unit{serialized_unit}; + + // Then use_set_if_available is preserved and use_get_if_available is unaffected + EXPECT_FALSE(reconstructed_unit.use_get_if_available_); + EXPECT_TRUE(reconstructed_unit.use_set_if_available_); +} + +TEST_F(LolaFieldInstanceDeploymentFixture, BothFlagsDefaultToFalseAfterRoundTripSerialisation) +{ + // Given a field deployment constructed without specifying the new boolean flags + const LolaFieldInstanceDeployment unit{MakeLolaFieldInstanceDeployment()}; + + // When serialising and deserialising + const auto serialized_unit{unit.Serialize()}; + const LolaFieldInstanceDeployment reconstructed_unit{serialized_unit}; + + // Then both flags default to false + EXPECT_FALSE(reconstructed_unit.use_get_if_available_); + EXPECT_FALSE(reconstructed_unit.use_set_if_available_); +} + +TEST_F(LolaFieldInstanceDeploymentFixture, UseGetAndUseSetFlagsAreIndependentOfEachOther) +{ + // Given four deployments covering all flag combinations + const LolaFieldInstanceDeployment both_false{MakeLolaFieldInstanceDeployment(kMaxSamples, + kMaxSubscribers, + kMaxConcurrentAllocations, + kEnforceMaxSamples, + kNumberOfTracingSlots, + false, + false)}; + const LolaFieldInstanceDeployment get_only{MakeLolaFieldInstanceDeployment(kMaxSamples, + kMaxSubscribers, + kMaxConcurrentAllocations, + kEnforceMaxSamples, + kNumberOfTracingSlots, + true, + false)}; + const LolaFieldInstanceDeployment set_only{MakeLolaFieldInstanceDeployment(kMaxSamples, + kMaxSubscribers, + kMaxConcurrentAllocations, + kEnforceMaxSamples, + kNumberOfTracingSlots, + false, + true)}; + const LolaFieldInstanceDeployment both_true{MakeLolaFieldInstanceDeployment(kMaxSamples, + kMaxSubscribers, + kMaxConcurrentAllocations, + kEnforceMaxSamples, + kNumberOfTracingSlots, + true, + true)}; + + // Then each combination holds exactly the values set, independently + EXPECT_FALSE(both_false.use_get_if_available_); + EXPECT_FALSE(both_false.use_set_if_available_); + + EXPECT_TRUE(get_only.use_get_if_available_); + EXPECT_FALSE(get_only.use_set_if_available_); + + EXPECT_FALSE(set_only.use_get_if_available_); + EXPECT_TRUE(set_only.use_set_if_available_); + + EXPECT_TRUE(both_true.use_get_if_available_); + EXPECT_TRUE(both_true.use_set_if_available_); +} + TEST(LolaFieldInstanceDeploymentDeathTest, CreatingFromSerializedObjectWithMismatchedSerializationVersionTerminates) { const LolaFieldInstanceDeployment unit{MakeLolaFieldInstanceDeployment()}; From 5752204670f0d4f2cc125c4514b40898820c4b8a Mon Sep 17 00:00:00 2001 From: soldier-sky Date: Fri, 17 Apr 2026 09:15:17 +0200 Subject: [PATCH 5/7] Update configuration documentation - Update ReadMe and UML diagram to refelct updated changes optional field values useGetIfAvailable/useSetIfAvailable Issue: SWP-250429 --- .../design/configuration/structural_view.puml | 26 +++++++++++++++---- score/mw/com/impl/configuration/README.md | 10 ++++++- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/score/mw/com/design/configuration/structural_view.puml b/score/mw/com/design/configuration/structural_view.puml index f2f7a21bb..eeab4a947 100644 --- a/score/mw/com/design/configuration/structural_view.puml +++ b/score/mw/com/design/configuration/structural_view.puml @@ -54,11 +54,27 @@ package "configuration" { } class "score::mw::com::impl::LolaFieldInstanceDeployment" { - + max_samples_: std::uint16_t - + max_subscribers_: std::uint8_t - + enforce_max_samples_ : score::cpp::optional - + is_set_configured: bool - + is_get_configured: bool + {static} + constexpr serializationVersion : std::uint32_t + + max_subscribers_ : std::optional + + max_concurrent_allocations_ : std::optional + + enforce_max_samples_ : bool + + use_get_if_available_ : bool + + use_set_if_available_ : bool + - number_of_sample_slots_ : std::optional + - number_of_tracing_slots_ : TracingSlotSizeType + __ + + LolaFieldInstanceDeployment(number_of_sample_slots : std::optional, max_subscribers : std::optional, max_concurrent_allocations : std::optional, enforce_max_samples : bool, number_of_tracing_slots : TracingSlotSizeType, use_get_if_available : bool, use_set_if_available : bool) noexcept + {static} + CreateFromJson(json_object : const score::json::Object&) : LolaFieldInstanceDeployment + + Serialize() const : score::json::Object + + SetNumberOfSampleSlots(number_of_sample_slots : SampleSlotCountType) noexcept : void + + GetNumberOfSampleSlots() const noexcept : std::optional + + GetNumberOfSampleSlotsExcludingTracingSlot() const noexcept : std::optional + + GetNumberOfTracingSlots() const noexcept : TracingSlotSizeType + -- + Type Aliases: + using SampleSlotCountType as std::uint16_t + using SubscriberCountType as std::uint8_t + using TracingSlotSizeType as std::uint8_t } class "score::mw::com::impl::LolaMethodInstanceDeployment" { diff --git a/score/mw/com/impl/configuration/README.md b/score/mw/com/impl/configuration/README.md index b92501783..780853428 100644 --- a/score/mw/com/impl/configuration/README.md +++ b/score/mw/com/impl/configuration/README.md @@ -355,7 +355,7 @@ Within the `service-instance` json object, there are further binding independent - `events` - `fields` -the `event` and `field` json objects, which are the items in the corresponding arrays are property-wise identical. +the event and field json objects share most configuration properties, but fields have two additional optional properties (useGetIfAvailable, useSetIfAvailable) not present on events. Additionally, there is the following constraint: For each event or field enlisted in the `events` and `fields` arrays on the [service-type->bindings](#bindings) level of the `service-type` a `service-instance` is based on, a corresponding instance specific event or field object has to exist. @@ -434,6 +434,12 @@ The properties of a field or an event object on the instance level are: tracing are different and the tracing subsystem has to explicitly know, how many slots/samples it is allowed to access in parallel at most. Furthermore, setting the value of `numberOfIpcTracingSlots` to 0 or not configuring it all, explicitly means, that tracing for this event or field is disabled. +- `useGetIfAvailable`: (optional, field only, default `false`) - When `true`, the getter for this field will be + used if the service type declares a getter. This is a consumer/proxy side configuration hint. On the provider + (skeleton) side this setting has no effect. +- `useSetIfAvailable`: (optional, field only, default `false`) - When `true`, the setter for this field will be + used if the service type declares a setter. This is a consumer/proxy side configuration hint. On the provider + (skeleton) side this setting has no effect. ###### methods within an instance @@ -599,3 +605,5 @@ is being used, whether a property is mandatory or optional or irrelevant, the fo | _serviceInstances.instances.events.maxSubscribers_
_serviceInstances.instances.fields.maxSubscribers_ | required | - | | | _serviceInstances.instances.events.enforceMaxSamples_
_serviceInstances.instances.fields.enforceMaxSamples_ | optional | - | if not given on skeleton side, defaults to true | | _serviceInstances.instances.events.numberOfIpcTracingSlots_
_serviceInstances.instances.fields.numberOfIpcTracingSlots_ | optional | - | if not given on skeleton side, defaults to 0, which means tracing for this event is disabled. | +| _serviceInstances.instances.fields.useGetIfAvailable_ | - | optional | if not given, defaults to false. Signals that the field getter should be used when the service type declares one. | +| _serviceInstances.instances.fields.useSetIfAvailable_ | - | optional | if not given, defaults to false. Signals that the field setter should be used when the service type declares one. | From c6cafcb857761ca1151b216dc2c9b38b19c0c835 Mon Sep 17 00:00:00 2001 From: soldier-sky Date: Tue, 28 Apr 2026 13:27:54 +0200 Subject: [PATCH 6/7] Optimize unit tests and update the field configuration default option - Remove the redundant unit tests and update the exsiting test for default field setter/getter value - Update the default values of useGetIfAvailable/useSetIfAvailable from default false to true - Update the plant UML diagram to retain only necessary information Issue: SWP-250429 --- .../design/configuration/structural_view.puml | 5 -- .../com/impl/configuration/config_parser.cpp | 10 ++- .../impl/configuration/config_parser_test.cpp | 18 +++- .../configuration/example/mw_com_config.json | 4 +- .../lola_field_instance_deployment.h | 4 +- .../lola_field_instance_deployment_test.cpp | 82 +++++++------------ .../lola_service_instance_deployment_test.cpp | 4 +- .../configuration/mw_com_config_schema.json | 8 +- 8 files changed, 64 insertions(+), 71 deletions(-) diff --git a/score/mw/com/design/configuration/structural_view.puml b/score/mw/com/design/configuration/structural_view.puml index eeab4a947..e65bf84be 100644 --- a/score/mw/com/design/configuration/structural_view.puml +++ b/score/mw/com/design/configuration/structural_view.puml @@ -63,13 +63,8 @@ package "configuration" { - number_of_sample_slots_ : std::optional - number_of_tracing_slots_ : TracingSlotSizeType __ - + LolaFieldInstanceDeployment(number_of_sample_slots : std::optional, max_subscribers : std::optional, max_concurrent_allocations : std::optional, enforce_max_samples : bool, number_of_tracing_slots : TracingSlotSizeType, use_get_if_available : bool, use_set_if_available : bool) noexcept {static} + CreateFromJson(json_object : const score::json::Object&) : LolaFieldInstanceDeployment + Serialize() const : score::json::Object - + SetNumberOfSampleSlots(number_of_sample_slots : SampleSlotCountType) noexcept : void - + GetNumberOfSampleSlots() const noexcept : std::optional - + GetNumberOfSampleSlotsExcludingTracingSlot() const noexcept : std::optional - + GetNumberOfTracingSlots() const noexcept : TracingSlotSizeType -- Type Aliases: using SampleSlotCountType as std::uint16_t diff --git a/score/mw/com/impl/configuration/config_parser.cpp b/score/mw/com/impl/configuration/config_parser.cpp index 19411c83f..e499bce2f 100644 --- a/score/mw/com/impl/configuration/config_parser.cpp +++ b/score/mw/com/impl/configuration/config_parser.cpp @@ -83,6 +83,8 @@ constexpr auto kFieldEnforceMaxSamplesKey = "enforceMaxSamples"sv; constexpr auto kFieldMaxConcurrentAllocationsKey = "maxConcurrentAllocations"sv; constexpr auto kFieldUseGetIfAvailableKey = "useGetIfAvailable"sv; constexpr auto kFieldUseSetIfAvailableKey = "useSetIfAvailable"sv; +constexpr auto kFieldUseGetIfAvailableDefault = false; +constexpr auto kFieldUseSetIfAvailableDefault = false; constexpr auto kLolaShmSizeKey = "shm-size"sv; constexpr auto kLolaControlAsilBShmSizeKey = "control-asil-b-shm-size"sv; constexpr auto kLolaControlQmShmSizeKey = "control-qm-shm-size"sv; @@ -493,10 +495,10 @@ auto ParseLolaFieldInstanceDeployment(const score::json::Object& json_map, LolaS const auto number_of_tracing_slots = deployment_parser.RetrieveJsonElement(kNumberOfIpcTracingSlotsKey) .value_or(kNumberOfIpcTracingSlotsDefault); - const auto use_get_if_available = - deployment_parser.RetrieveJsonElement(kFieldUseGetIfAvailableKey).value_or(false); - const auto use_set_if_available = - deployment_parser.RetrieveJsonElement(kFieldUseSetIfAvailableKey).value_or(false); + const auto use_get_if_available = deployment_parser.RetrieveJsonElement(kFieldUseGetIfAvailableKey) + .value_or(kFieldUseGetIfAvailableDefault); + const auto use_set_if_available = deployment_parser.RetrieveJsonElement(kFieldUseSetIfAvailableKey) + .value_or(kFieldUseSetIfAvailableDefault); auto field_deployment = LolaFieldInstanceDeployment(number_of_sample_slots, max_subscribers, diff --git a/score/mw/com/impl/configuration/config_parser_test.cpp b/score/mw/com/impl/configuration/config_parser_test.cpp index b30cdacfc..4bef07ef0 100644 --- a/score/mw/com/impl/configuration/config_parser_test.cpp +++ b/score/mw/com/impl/configuration/config_parser_test.cpp @@ -116,8 +116,8 @@ TEST_F(ConfigParserFixture, ParseExampleJson) EXPECT_EQ(secondDeploymentInfo.fields_.at("CurrentTemperatureFrontLeft").max_subscribers_.value(), 6); EXPECT_EQ(secondDeploymentInfo.fields_.at("CurrentTemperatureFrontLeft").enforce_max_samples_, true); EXPECT_EQ(secondDeploymentInfo.fields_.at("CurrentTemperatureFrontLeft").max_concurrent_allocations_.value(), 1); - ASSERT_TRUE(secondDeploymentInfo.methods_.at("SetPressure").enabled_.has_value()); - EXPECT_TRUE(secondDeploymentInfo.methods_.at("SetPressure").enabled_.value()); + EXPECT_FALSE(secondDeploymentInfo.fields_.at("CurrentTemperatureFrontLeft").use_get_if_available_); + EXPECT_FALSE(secondDeploymentInfo.fields_.at("CurrentTemperatureFrontLeft").use_set_if_available_); const auto service_deployment = config.GetServiceTypes().at(deployments.service_); const auto* const lola_service_type_deployment = @@ -2159,12 +2159,16 @@ TEST(ConfigParser, LolaFieldUseGetIfAvailableSetToTrue) ] } )"_json; + + // When parsing the JSON const auto config = score::mw::com::impl::configuration::Parse(std::move(j2)); const auto deployment = config.GetServiceInstances().at(InstanceSpecifier::Create(std::string{"abc/abc/TirePressurePort"}).value()); const auto deploymentInfo = std::get(deployment.bindingInfo_); + + // Then use_get_if_available_ is true and use_set_if_available_ defaults to false EXPECT_TRUE(deploymentInfo.fields_.at("CurrentTemperatureFrontLeft").use_get_if_available_); EXPECT_FALSE(deploymentInfo.fields_.at("CurrentTemperatureFrontLeft").use_set_if_available_); } @@ -2223,12 +2227,16 @@ TEST(ConfigParser, LolaFieldUseSetIfAvailableSetToTrue) ] } )"_json; + + // When parsing the JSON const auto config = score::mw::com::impl::configuration::Parse(std::move(j2)); const auto deployment = config.GetServiceInstances().at(InstanceSpecifier::Create(std::string{"abc/abc/TirePressurePort"}).value()); const auto deploymentInfo = std::get(deployment.bindingInfo_); + + // Then use_set_if_available_ is true and use_get_if_available_ defaults to false EXPECT_FALSE(deploymentInfo.fields_.at("CurrentTemperatureFrontLeft").use_get_if_available_); EXPECT_TRUE(deploymentInfo.fields_.at("CurrentTemperatureFrontLeft").use_set_if_available_); } @@ -2286,12 +2294,16 @@ TEST(ConfigParser, LolaFieldOmittingBothFlagsDefaultsBothToFalse) ] } )"_json; + + // When parsing the JSON const auto config = score::mw::com::impl::configuration::Parse(std::move(j2)); const auto deployment = config.GetServiceInstances().at(InstanceSpecifier::Create(std::string{"abc/abc/TirePressurePort"}).value()); const auto deploymentInfo = std::get(deployment.bindingInfo_); + + // Then both flags default to false EXPECT_FALSE(deploymentInfo.fields_.at("CurrentTemperatureFrontLeft").use_get_if_available_); EXPECT_FALSE(deploymentInfo.fields_.at("CurrentTemperatureFrontLeft").use_set_if_available_); } @@ -2357,6 +2369,8 @@ TEST(ConfigParser, LolaFieldBothFlagsSetToTrue) config.GetServiceInstances().at(InstanceSpecifier::Create(std::string{"abc/abc/TirePressurePort"}).value()); const auto deploymentInfo = std::get(deployment.bindingInfo_); + + // Then both flags are true EXPECT_TRUE(deploymentInfo.fields_.at("CurrentTemperatureFrontLeft").use_get_if_available_); EXPECT_TRUE(deploymentInfo.fields_.at("CurrentTemperatureFrontLeft").use_set_if_available_); } diff --git a/score/mw/com/impl/configuration/example/mw_com_config.json b/score/mw/com/impl/configuration/example/mw_com_config.json index 4333747bf..f69347e64 100644 --- a/score/mw/com/impl/configuration/example/mw_com_config.json +++ b/score/mw/com/impl/configuration/example/mw_com_config.json @@ -61,7 +61,9 @@ "fieldName": "CurrentTemperatureFrontLeft", "numberOfSampleSlots": 60, "maxSubscribers": 6, - "numberOfIpcTracingSlots": 7 + "numberOfIpcTracingSlots": 7, + "useGetIfAvailable": false, + "useSetIfAvailable": false } ], "methods": [ diff --git a/score/mw/com/impl/configuration/lola_field_instance_deployment.h b/score/mw/com/impl/configuration/lola_field_instance_deployment.h index ba7ae1b49..f6722295b 100644 --- a/score/mw/com/impl/configuration/lola_field_instance_deployment.h +++ b/score/mw/com/impl/configuration/lola_field_instance_deployment.h @@ -64,9 +64,9 @@ class LolaFieldInstanceDeployment // coverity[autosar_cpp14_m11_0_1_violation] bool enforce_max_samples_; // coverity[autosar_cpp14_m11_0_1_violation] - bool use_get_if_available_{false}; + bool use_get_if_available_; // coverity[autosar_cpp14_m11_0_1_violation] - bool use_set_if_available_{false}; + bool use_set_if_available_; // False positive, variable is used outside of the file. // coverity[autosar_cpp14_a0_1_1_violation : FALSE] diff --git a/score/mw/com/impl/configuration/lola_field_instance_deployment_test.cpp b/score/mw/com/impl/configuration/lola_field_instance_deployment_test.cpp index 36d3f6520..326416ec1 100644 --- a/score/mw/com/impl/configuration/lola_field_instance_deployment_test.cpp +++ b/score/mw/com/impl/configuration/lola_field_instance_deployment_test.cpp @@ -66,41 +66,45 @@ TEST_F(LolaFieldInstanceDeploymentFixture, CanCreateFromSerializedObjectWithoutO TEST_F(LolaFieldInstanceDeploymentFixture, UseGetIfAvailableIsTrueAfterRoundTripSerialisation) { // Given a field deployment with use_get_if_available set to true + constexpr bool kUseGetIfAvailable{true}; + constexpr bool kUseSetIfAvailable{false}; const LolaFieldInstanceDeployment unit{MakeLolaFieldInstanceDeployment(kMaxSamples, kMaxSubscribers, kMaxConcurrentAllocations, kEnforceMaxSamples, kNumberOfTracingSlots, - /*use_get*/ true, - /*use_set*/ false)}; + kUseGetIfAvailable, + kUseSetIfAvailable)}; // When serialising and deserialising const auto serialized_unit{unit.Serialize()}; const LolaFieldInstanceDeployment reconstructed_unit{serialized_unit}; // Then use_get_if_available is preserved and use_set_if_available is unaffected - EXPECT_TRUE(reconstructed_unit.use_get_if_available_); - EXPECT_FALSE(reconstructed_unit.use_set_if_available_); + EXPECT_EQ(reconstructed_unit.use_get_if_available_, kUseGetIfAvailable); + EXPECT_EQ(reconstructed_unit.use_set_if_available_, kUseSetIfAvailable); } TEST_F(LolaFieldInstanceDeploymentFixture, UseSetIfAvailableIsTrueAfterRoundTripSerialisation) { // Given a field deployment with use_set_if_available set to true + constexpr bool kUseGetIfAvailable{false}; + constexpr bool kUseSetIfAvailable{true}; const LolaFieldInstanceDeployment unit{MakeLolaFieldInstanceDeployment(kMaxSamples, kMaxSubscribers, kMaxConcurrentAllocations, kEnforceMaxSamples, kNumberOfTracingSlots, - /*use_get*/ false, - /*use_set*/ true)}; + kUseGetIfAvailable, + kUseSetIfAvailable)}; // When serialising and deserialising const auto serialized_unit{unit.Serialize()}; const LolaFieldInstanceDeployment reconstructed_unit{serialized_unit}; // Then use_set_if_available is preserved and use_get_if_available is unaffected - EXPECT_FALSE(reconstructed_unit.use_get_if_available_); - EXPECT_TRUE(reconstructed_unit.use_set_if_available_); + EXPECT_EQ(reconstructed_unit.use_get_if_available_, kUseGetIfAvailable); + EXPECT_EQ(reconstructed_unit.use_set_if_available_, kUseSetIfAvailable); } TEST_F(LolaFieldInstanceDeploymentFixture, BothFlagsDefaultToFalseAfterRoundTripSerialisation) @@ -117,50 +121,26 @@ TEST_F(LolaFieldInstanceDeploymentFixture, BothFlagsDefaultToFalseAfterRoundTrip EXPECT_FALSE(reconstructed_unit.use_set_if_available_); } -TEST_F(LolaFieldInstanceDeploymentFixture, UseGetAndUseSetFlagsAreIndependentOfEachOther) +TEST_F(LolaFieldInstanceDeploymentFixture, BothFlagsSetToTrueAfterRoundTripSerialisation) { - // Given four deployments covering all flag combinations - const LolaFieldInstanceDeployment both_false{MakeLolaFieldInstanceDeployment(kMaxSamples, - kMaxSubscribers, - kMaxConcurrentAllocations, - kEnforceMaxSamples, - kNumberOfTracingSlots, - false, - false)}; - const LolaFieldInstanceDeployment get_only{MakeLolaFieldInstanceDeployment(kMaxSamples, - kMaxSubscribers, - kMaxConcurrentAllocations, - kEnforceMaxSamples, - kNumberOfTracingSlots, - true, - false)}; - const LolaFieldInstanceDeployment set_only{MakeLolaFieldInstanceDeployment(kMaxSamples, - kMaxSubscribers, - kMaxConcurrentAllocations, - kEnforceMaxSamples, - kNumberOfTracingSlots, - false, - true)}; - const LolaFieldInstanceDeployment both_true{MakeLolaFieldInstanceDeployment(kMaxSamples, - kMaxSubscribers, - kMaxConcurrentAllocations, - kEnforceMaxSamples, - kNumberOfTracingSlots, - true, - true)}; - - // Then each combination holds exactly the values set, independently - EXPECT_FALSE(both_false.use_get_if_available_); - EXPECT_FALSE(both_false.use_set_if_available_); - - EXPECT_TRUE(get_only.use_get_if_available_); - EXPECT_FALSE(get_only.use_set_if_available_); - - EXPECT_FALSE(set_only.use_get_if_available_); - EXPECT_TRUE(set_only.use_set_if_available_); - - EXPECT_TRUE(both_true.use_get_if_available_); - EXPECT_TRUE(both_true.use_set_if_available_); + // Given a field deployment with both flags set to true + constexpr bool kUseGetIfAvailable{true}; + constexpr bool kUseSetIfAvailable{true}; + const LolaFieldInstanceDeployment unit{MakeLolaFieldInstanceDeployment(kMaxSamples, + kMaxSubscribers, + kMaxConcurrentAllocations, + kEnforceMaxSamples, + kNumberOfTracingSlots, + kUseGetIfAvailable, + kUseSetIfAvailable)}; + + // When serialising and deserialising + const auto serialized_unit{unit.Serialize()}; + const LolaFieldInstanceDeployment reconstructed_unit{serialized_unit}; + + // Then both flags are preserved as true + EXPECT_EQ(reconstructed_unit.use_get_if_available_, kUseGetIfAvailable); + EXPECT_EQ(reconstructed_unit.use_set_if_available_, kUseSetIfAvailable); } TEST(LolaFieldInstanceDeploymentDeathTest, CreatingFromSerializedObjectWithMismatchedSerializationVersionTerminates) diff --git a/score/mw/com/impl/configuration/lola_service_instance_deployment_test.cpp b/score/mw/com/impl/configuration/lola_service_instance_deployment_test.cpp index e8a1dd5f8..3cebb1399 100644 --- a/score/mw/com/impl/configuration/lola_service_instance_deployment_test.cpp +++ b/score/mw/com/impl/configuration/lola_service_instance_deployment_test.cpp @@ -119,7 +119,7 @@ TEST(LolaServiceInstanceDeployment, ContainsEventReturnsFalseIfEventMissing) EXPECT_FALSE(unit.ContainsEvent("def")); } -TEST(LolaServiceInstanceDeployment, ContainsFieldReturnsTrueIfEventPresent) +TEST(LolaServiceInstanceDeployment, ContainsFieldReturnsTrueIfFieldPresent) { LolaServiceInstanceDeployment unit{LolaServiceInstanceId{LolaServiceInstanceId{2U}}}; auto temp = MakeLolaFieldInstanceDeployment(); @@ -127,7 +127,7 @@ TEST(LolaServiceInstanceDeployment, ContainsFieldReturnsTrueIfEventPresent) EXPECT_TRUE(unit.ContainsField("abc")); } -TEST(LolaServiceInstanceDeployment, ContainsFieldReturnsFalseIfEventMissing) +TEST(LolaServiceInstanceDeployment, ContainsFieldReturnsFalseIfFieldMissing) { LolaServiceInstanceDeployment unit{LolaServiceInstanceId{2U}}; auto temp = MakeLolaFieldInstanceDeployment(); diff --git a/score/mw/com/impl/configuration/mw_com_config_schema.json b/score/mw/com/impl/configuration/mw_com_config_schema.json index 31b5e251e..6eb190dbb 100644 --- a/score/mw/com/impl/configuration/mw_com_config_schema.json +++ b/score/mw/com/impl/configuration/mw_com_config_schema.json @@ -393,14 +393,14 @@ "useGetIfAvailable": { "type": "boolean", "title": "Use Field Getter If Available", - "description": "When true, the getter for this field will be used if the service type declares one.", - "default": false + "description": "When true, the getter for this field will be used if the service type declares one in the C++ service interface. Applicable for proxy/consumer side.", + "default": true }, "useSetIfAvailable": { "type": "boolean", "title": "Use Field Setter If Available", - "description": "When true, the setter for this field will be used if the service type declares one.", - "default": false + "description": "When true, the setter for this field will be used if the service type declares one in the C++ service interface. Applicable for proxy/consumer side.", + "default": true } } } From eef72751d70514556753bed2a13a666cf0ca8b10 Mon Sep 17 00:00:00 2001 From: Sahithi Nukala Date: Mon, 11 May 2026 14:09:23 +0200 Subject: [PATCH 7/7] Use composition in LolaFieldInstanceDeployment instead of duplicating LolaEventInstanceDeployment members - Delegate GetNumberOfSampleSlots(), GetNumberOfTracingSlots(), and SetNumberOfSampleSlots() to the inner lola_event_instance_deployment_ member - Delegate CreateFromJson() event parsing and Serialize() event part to LolaEventInstanceDeployment - Add a non-template GetSkeletonEventProperties() overload in skeleton_service_element_binding_factory_impl.h that delegates to the event deployment overload - Update all call sites: config_parser.cpp, configuration_test_resources.cpp, and all affected test files --- .../com/impl/bindings/lola/skeleton_test.cpp | 8 +- .../lola/test/skeleton_component_test.cpp | 3 +- .../lola/test/skeleton_test_resources.h | 6 +- .../com/impl/configuration/config_parser.cpp | 15 +-- .../impl/configuration/config_parser_test.cpp | 21 +++- .../impl/configuration/configuration_test.cpp | 4 +- .../lola_field_instance_deployment.cpp | 117 +++--------------- .../lola_field_instance_deployment.h | 24 +--- .../configuration/mw_com_config_schema.json | 18 ++- .../test/configuration_test_resources.cpp | 16 +-- ...proxy_event_field_binding_factory_test.cpp | 3 +- ...ton_service_element_binding_factory_impl.h | 10 ++ ...n_service_element_binding_factory_test.cpp | 12 +- .../dummy_instance_identifier_builder.cpp | 2 +- .../tracing_filter_config_test.cpp | 4 +- .../tracing/skeleton_event_tracing_test.cpp | 2 +- 16 files changed, 94 insertions(+), 171 deletions(-) diff --git a/score/mw/com/impl/bindings/lola/skeleton_test.cpp b/score/mw/com/impl/bindings/lola/skeleton_test.cpp index 0ea96cdfb..24805dbd4 100644 --- a/score/mw/com/impl/bindings/lola/skeleton_test.cpp +++ b/score/mw/com/impl/bindings/lola/skeleton_test.cpp @@ -1167,9 +1167,13 @@ TEST_P(SkeletonRegisterParamaterisedFixture, ValidEventMetaInfoExistAfterEventIs fields_.emplace(test::kDumbEventName, dumb_event); lola_field_inst_depls.push_back( - {test::kFooEventName, LolaFieldInstanceDeployment{number_of_slots, 10U, 1U, true, 0, false, false}}); + {test::kFooEventName, + LolaFieldInstanceDeployment{ + LolaEventInstanceDeployment{number_of_slots, 10U, 1U, true, 0}, false, false}}); lola_field_inst_depls.push_back( - {test::kDumbEventName, LolaFieldInstanceDeployment{number_of_slots, 10U, 1U, true, 0, false, false}}); + {test::kDumbEventName, + LolaFieldInstanceDeployment{ + LolaEventInstanceDeployment{number_of_slots, 10U, 1U, true, 0}, false, false}}); } ServiceInstanceDeployment service_instance_deployment{ test::kFooService, diff --git a/score/mw/com/impl/bindings/lola/test/skeleton_component_test.cpp b/score/mw/com/impl/bindings/lola/test/skeleton_component_test.cpp index 9c93b00b2..fd7b81199 100644 --- a/score/mw/com/impl/bindings/lola/test/skeleton_component_test.cpp +++ b/score/mw/com/impl/bindings/lola/test/skeleton_component_test.cpp @@ -187,7 +187,8 @@ class SkeletonComponentTestFixture : public ::testing::Test {test::kFooEventName, LolaEventInstanceDeployment{kNumberOfSlots, 10U, 1U, true, 0}}); fields_.emplace(test::kFooFieldName, mock_field_binding_); lola_field_instance_deployments_.push_back( - {test::kFooFieldName, LolaFieldInstanceDeployment{kNumberOfSlots, 10U, 1U, true, 0, false, false}}); + {test::kFooFieldName, + LolaFieldInstanceDeployment{LolaEventInstanceDeployment{kNumberOfSlots, 10U, 1U, true, 0}, false, false}}); service_instance_deployment_ = std::make_unique( test::kFooService, CreateLolaServiceInstanceDeployment(test::kDefaultLolaInstanceId, diff --git a/score/mw/com/impl/bindings/lola/test/skeleton_test_resources.h b/score/mw/com/impl/bindings/lola/test/skeleton_test_resources.h index 33a6a59a9..9138ff66e 100644 --- a/score/mw/com/impl/bindings/lola/test/skeleton_test_resources.h +++ b/score/mw/com/impl/bindings/lola/test/skeleton_test_resources.h @@ -239,7 +239,8 @@ static const ServiceInstanceDeployment kValidInstanceDeploymentWithField{ CreateLolaServiceInstanceDeployment( kDefaultLolaInstanceId, {}, - {{test::kFooEventName, LolaFieldInstanceDeployment{test::kMaxSlots, 10U, 1U, true, 0, false, false}}}, + {{test::kFooEventName, + LolaFieldInstanceDeployment{LolaEventInstanceDeployment{test::kMaxSlots, 10U, 1U, true, 0}, false, false}}}, {}, {}, {}, @@ -284,7 +285,8 @@ static const ServiceInstanceDeployment kValidAsilInstanceDeploymentWithField{ CreateLolaServiceInstanceDeployment( kDefaultLolaInstanceId, {}, - {{test::kFooEventName, LolaFieldInstanceDeployment{test::kMaxSlots, 10U, 1U, true, 0, false, false}}}, + {{test::kFooEventName, + LolaFieldInstanceDeployment{LolaEventInstanceDeployment{test::kMaxSlots, 10U, 1U, true, 0}, false, false}}}, {}, {}, {}, diff --git a/score/mw/com/impl/configuration/config_parser.cpp b/score/mw/com/impl/configuration/config_parser.cpp index e499bce2f..f4684d5b1 100644 --- a/score/mw/com/impl/configuration/config_parser.cpp +++ b/score/mw/com/impl/configuration/config_parser.cpp @@ -500,13 +500,14 @@ auto ParseLolaFieldInstanceDeployment(const score::json::Object& json_map, LolaS const auto use_set_if_available = deployment_parser.RetrieveJsonElement(kFieldUseSetIfAvailableKey) .value_or(kFieldUseSetIfAvailableDefault); - auto field_deployment = LolaFieldInstanceDeployment(number_of_sample_slots, - max_subscribers, - kMaxConcurrentAllocationsDefault, - enforce_max_samples, - number_of_tracing_slots, - use_get_if_available, - use_set_if_available); + auto field_deployment = + LolaFieldInstanceDeployment(LolaEventInstanceDeployment(number_of_sample_slots, + max_subscribers, + kMaxConcurrentAllocationsDefault, + enforce_max_samples, + number_of_tracing_slots), + use_get_if_available, + use_set_if_available); const auto emplace_result = service.fields_.emplace(std::piecewise_construct, std::forward_as_tuple(std::move(field_name_value)), std::forward_as_tuple(field_deployment)); diff --git a/score/mw/com/impl/configuration/config_parser_test.cpp b/score/mw/com/impl/configuration/config_parser_test.cpp index 4bef07ef0..9ef86e584 100644 --- a/score/mw/com/impl/configuration/config_parser_test.cpp +++ b/score/mw/com/impl/configuration/config_parser_test.cpp @@ -113,11 +113,19 @@ TEST_F(ConfigParserFixture, ParseExampleJson) EXPECT_EQ(secondDeploymentInfo.fields_.at("CurrentTemperatureFrontLeft").GetNumberOfTracingSlots(), 7); EXPECT_EQ(secondDeploymentInfo.fields_.at("CurrentTemperatureFrontLeft").GetNumberOfSampleSlots().value(), 60 + 7); - EXPECT_EQ(secondDeploymentInfo.fields_.at("CurrentTemperatureFrontLeft").max_subscribers_.value(), 6); - EXPECT_EQ(secondDeploymentInfo.fields_.at("CurrentTemperatureFrontLeft").enforce_max_samples_, true); - EXPECT_EQ(secondDeploymentInfo.fields_.at("CurrentTemperatureFrontLeft").max_concurrent_allocations_.value(), 1); + EXPECT_EQ(secondDeploymentInfo.fields_.at("CurrentTemperatureFrontLeft") + .lola_event_instance_deployment_.max_subscribers_.value(), + 6); + EXPECT_EQ(secondDeploymentInfo.fields_.at("CurrentTemperatureFrontLeft") + .lola_event_instance_deployment_.enforce_max_samples_, + true); + EXPECT_EQ(secondDeploymentInfo.fields_.at("CurrentTemperatureFrontLeft") + .lola_event_instance_deployment_.max_concurrent_allocations_.value(), + 1); EXPECT_FALSE(secondDeploymentInfo.fields_.at("CurrentTemperatureFrontLeft").use_get_if_available_); EXPECT_FALSE(secondDeploymentInfo.fields_.at("CurrentTemperatureFrontLeft").use_set_if_available_); + ASSERT_TRUE(secondDeploymentInfo.methods_.at("SetPressure").enabled_.has_value()); + EXPECT_TRUE(secondDeploymentInfo.methods_.at("SetPressure").enabled_.value()); const auto service_deployment = config.GetServiceTypes().at(deployments.service_); const auto* const lola_service_type_deployment = @@ -1735,7 +1743,8 @@ TEST(ConfigParser, NoFieldMaxSubscribersLeavesValueOptional) const auto deploymentInfo = std::get(deployment.bindingInfo_); // That the max_subscribers_ in the field has no value - EXPECT_FALSE(deploymentInfo.fields_.at("CurrentTemperatureFrontLeft").max_subscribers_.has_value()); + EXPECT_FALSE(deploymentInfo.fields_.at("CurrentTemperatureFrontLeft") + .lola_event_instance_deployment_.max_subscribers_.has_value()); } TEST(ConfigParser, NoSHMInstanceIdLeavesValueOptional) @@ -2102,7 +2111,9 @@ TEST(ConfigParser, LolaFieldOptionalEnforceMaxSamples) config.GetServiceInstances().at(InstanceSpecifier::Create(std::string{"abc/abc/TirePressurePort"}).value()); const auto deploymentInfo = std::get(deployment.bindingInfo_); - EXPECT_EQ(deploymentInfo.fields_.at("CurrentTemperatureFrontLeft").enforce_max_samples_, false); + EXPECT_EQ( + deploymentInfo.fields_.at("CurrentTemperatureFrontLeft").lola_event_instance_deployment_.enforce_max_samples_, + false); } TEST(ConfigParser, LolaFieldUseGetIfAvailableSetToTrue) diff --git a/score/mw/com/impl/configuration/configuration_test.cpp b/score/mw/com/impl/configuration/configuration_test.cpp index a1e6eaf4a..e324a75fd 100644 --- a/score/mw/com/impl/configuration/configuration_test.cpp +++ b/score/mw/com/impl/configuration/configuration_test.cpp @@ -185,8 +185,8 @@ TEST_F(ConfigurationFixture, ConfigIsCorrectlyParsedFromFile) const LolaEventInstanceDeployment lola_event_instance{event_max_samples, event_max_subscribers, 1U, true, 0}; const LolaFieldInstanceDeployment lola_field_instance{ - field_max_samples, field_max_subscribers, 1U, true, 7, false, false}; - const LolaMethodInstanceDeployment lola_method_instance{method_queue_size}; + LolaEventInstanceDeployment{field_max_samples, field_max_subscribers, 1U, true, 7}, false, false}; + const LolaMethodInstanceDeployment lola_method_instance{method_queue_size, true}; const LolaServiceInstanceDeployment::EventInstanceMapping instance_events{ {instance_event_name, lola_event_instance}}; diff --git a/score/mw/com/impl/configuration/lola_field_instance_deployment.cpp b/score/mw/com/impl/configuration/lola_field_instance_deployment.cpp index ef13e7071..49dc259fe 100644 --- a/score/mw/com/impl/configuration/lola_field_instance_deployment.cpp +++ b/score/mw/com/impl/configuration/lola_field_instance_deployment.cpp @@ -13,11 +13,10 @@ #include "score/mw/com/impl/configuration/lola_field_instance_deployment.h" #include "score/mw/com/impl/configuration/configuration_common_resources.h" - -#include "score/mw/log/logging.h" +#include "score/mw/com/impl/configuration/lola_event_instance_deployment.h" #include -#include +#include namespace score::mw::com::impl { @@ -25,31 +24,17 @@ namespace score::mw::com::impl namespace { -constexpr auto kNumberOfSampleSlotsKey = "numberOfSampleSlots"; -constexpr auto kSubscribersKey = "maxSubscribers"; -constexpr auto kMaxConcurrentAllocationsKey = "maxConcurrentAllocations"; -constexpr auto kEnforceMaxSamplesKey = "enforceMaxSamples"; -constexpr auto kNumberOfIpcTracingSlotsKey = "numberOfIpcTracingSlots"; constexpr auto kUseGetIfAvailableKey = "useGetIfAvailable"; constexpr auto kUseSetIfAvailableKey = "useSetIfAvailable"; -constexpr LolaFieldInstanceDeployment::TracingSlotSizeType kNumberOfIpcTracingSlotsDefault{0U}; } // namespace -LolaFieldInstanceDeployment::LolaFieldInstanceDeployment(std::optional number_of_sample_slots, - std::optional max_subscribers, - std::optional max_concurrent_allocations, - const bool enforce_max_samples, - const TracingSlotSizeType number_of_tracing_slots, +LolaFieldInstanceDeployment::LolaFieldInstanceDeployment(LolaEventInstanceDeployment event_deployment, const bool use_get_if_available, const bool use_set_if_available) noexcept - : max_subscribers_{max_subscribers}, - max_concurrent_allocations_{max_concurrent_allocations}, - enforce_max_samples_{enforce_max_samples}, + : lola_event_instance_deployment_{std::move(event_deployment)}, use_get_if_available_{use_get_if_available}, - use_set_if_available_{use_set_if_available}, - number_of_sample_slots_{number_of_sample_slots}, - number_of_tracing_slots_{number_of_tracing_slots} + use_set_if_available_{use_set_if_available} { } @@ -60,23 +45,8 @@ LolaFieldInstanceDeployment::LolaFieldInstanceDeployment(const score::json::Obje LolaFieldInstanceDeployment LolaFieldInstanceDeployment::CreateFromJson(const score::json::Object& json_object) noexcept { - - const auto serialization_version = GetValueFromJson(json_object, kSerializationVersionKey); - if (serialization_version != serializationVersion) - { - std::terminate(); - } - - const auto number_of_sample_slots = - GetOptionalValueFromJson(json_object, kNumberOfSampleSlotsKey); - const auto max_subscribers = GetOptionalValueFromJson(json_object, kSubscribersKey); - const auto max_concurrent_allocations = - GetOptionalValueFromJson(json_object, kMaxConcurrentAllocationsKey); - const auto enforce_max_samples = GetValueFromJson(json_object, kEnforceMaxSamplesKey); - const auto number_of_tracing_slots_opt = - GetOptionalValueFromJson(json_object, kNumberOfIpcTracingSlotsKey); - - auto number_of_tracing_slots = number_of_tracing_slots_opt.value_or(kNumberOfIpcTracingSlotsDefault); + // Delegate event-specific parsing to LolaEventInstanceDeployment (which also checks serialization version). + auto event_deployment = LolaEventInstanceDeployment::CreateFromJson(json_object); // getter and setters are optional fields. If not provided, we set them to false as default value. const auto use_get_if_available = @@ -84,41 +54,12 @@ LolaFieldInstanceDeployment LolaFieldInstanceDeployment::CreateFromJson(const sc const auto use_set_if_available = GetOptionalValueFromJson(json_object, kUseSetIfAvailableKey).value_or(false); - return LolaFieldInstanceDeployment(number_of_sample_slots, - max_subscribers, - max_concurrent_allocations, - enforce_max_samples, - number_of_tracing_slots, - use_get_if_available, - use_set_if_available); + return LolaFieldInstanceDeployment(std::move(event_deployment), use_get_if_available, use_set_if_available); } -// Suppress "AUTOSAR C++14 A15-5-3" rule finding. This rule states: "The std::terminate() function shall not be called -// implicitly" -// false positive std::bad_optional_access. We check and early exit in case the optional is empty. -// coverity[autosar_cpp14_a15_5_3_violation] score::json::Object LolaFieldInstanceDeployment::Serialize() const noexcept { - score::json::Object json_object{}; - if (number_of_sample_slots_.has_value()) - { - json_object[kNumberOfSampleSlotsKey] = score::json::Any{number_of_sample_slots_.value()}; - } - if (max_subscribers_.has_value()) - { - json_object[kSubscribersKey] = score::json::Any{max_subscribers_.value()}; - } - json_object[kSerializationVersionKey] = json::Any{serializationVersion}; - - if (max_concurrent_allocations_.has_value()) - { - json_object[kMaxConcurrentAllocationsKey] = score::json::Any{max_concurrent_allocations_.value()}; - } - - json_object[kEnforceMaxSamplesKey] = score::json::Any{enforce_max_samples_}; - - // We always turn of ipc tracing. I.e., serialize kNumberOfIpcTracingSlotsKey as false - json_object[kNumberOfIpcTracingSlotsKey] = static_cast(0U); + auto json_object = lola_event_instance_deployment_.Serialize(); json_object[kUseGetIfAvailableKey] = score::json::Any{use_get_if_available_}; json_object[kUseSetIfAvailableKey] = score::json::Any{use_set_if_available_}; @@ -126,64 +67,36 @@ score::json::Object LolaFieldInstanceDeployment::Serialize() const noexcept return json_object; } -// Suppress "AUTOSAR C++14 A15-5-3" rule finding. This rule states: "The std::terminate() function shall not be called -// implicitly" -// false positive std::bad_optional_access. We check and early exit in case the optional is empty. -// coverity[autosar_cpp14_a15_5_3_violation] auto LolaFieldInstanceDeployment::GetNumberOfSampleSlots() const noexcept -> std::optional { - if (!number_of_sample_slots_.has_value()) - { - return {}; - } - - const auto intermediate = static_cast(number_of_sample_slots_.value()) + - static_cast(number_of_tracing_slots_); - if (intermediate > std::numeric_limits::max()) - { - ::score::mw::log::LogFatal("lola") - << "Number of sample slots + number of tracing slots exceeds sample slot limit. Terminating."; - SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(false); - } - return static_cast(intermediate); + return lola_event_instance_deployment_.GetNumberOfSampleSlots(); } auto LolaFieldInstanceDeployment::GetNumberOfSampleSlotsExcludingTracingSlot() const noexcept -> std::optional { - if (!number_of_sample_slots_.has_value()) - { - return {}; - } - return *number_of_sample_slots_; + return lola_event_instance_deployment_.GetNumberOfSampleSlotsExcludingTracingSlot(); } auto LolaFieldInstanceDeployment::GetNumberOfTracingSlots() const noexcept -> TracingSlotSizeType { - return number_of_tracing_slots_; + return lola_event_instance_deployment_.GetNumberOfTracingSlots(); } void LolaFieldInstanceDeployment::SetNumberOfSampleSlots(SampleSlotCountType number_of_sample_slots) noexcept { - - number_of_sample_slots_ = number_of_sample_slots; + lola_event_instance_deployment_.SetNumberOfSampleSlots(number_of_sample_slots); } bool operator==(const LolaFieldInstanceDeployment& lhs, const LolaFieldInstanceDeployment& rhs) noexcept { - const bool number_of_sample_slots_equal = (lhs.number_of_sample_slots_ == rhs.number_of_sample_slots_); - const bool number_of_tracing_slots_equal = (lhs.number_of_tracing_slots_ == rhs.number_of_tracing_slots_); - const bool max_subscribers_equal = (lhs.max_subscribers_ == rhs.max_subscribers_); - const bool max_concurrent_allocations_equal = (lhs.max_concurrent_allocations_ == rhs.max_concurrent_allocations_); - const bool enforce_max_samples_equal = (lhs.enforce_max_samples_ == rhs.enforce_max_samples_); const bool use_get_if_available_equal = (lhs.use_get_if_available_ == rhs.use_get_if_available_); const bool use_set_if_available_equal = (lhs.use_set_if_available_ == rhs.use_set_if_available_); // Adding Brackets to the expression does not give additional value since only one logical operator is used which // is independent of the execution order // coverity[autosar_cpp14_a5_2_6_violation] - return (number_of_sample_slots_equal && number_of_tracing_slots_equal && max_subscribers_equal && - max_concurrent_allocations_equal && enforce_max_samples_equal && use_get_if_available_equal && - use_set_if_available_equal); + return ((lhs.lola_event_instance_deployment_ == rhs.lola_event_instance_deployment_) && + use_get_if_available_equal && use_set_if_available_equal); } } // namespace score::mw::com::impl diff --git a/score/mw/com/impl/configuration/lola_field_instance_deployment.h b/score/mw/com/impl/configuration/lola_field_instance_deployment.h index f6722295b..b25107711 100644 --- a/score/mw/com/impl/configuration/lola_field_instance_deployment.h +++ b/score/mw/com/impl/configuration/lola_field_instance_deployment.h @@ -14,12 +14,12 @@ #define SCORE_MW_COM_IMPL_CONFIGURATION_LOLA_FIELD_INSTANCE_DEPLOYMENT_H #include "score/json/json_parser.h" +#include "score/mw/com/impl/configuration/lola_event_instance_deployment.h" #include #include #include -#include namespace score::mw::com::impl { @@ -31,11 +31,7 @@ class LolaFieldInstanceDeployment using SubscriberCountType = std::uint8_t; using TracingSlotSizeType = std::uint8_t; - explicit LolaFieldInstanceDeployment(std::optional number_of_sample_slots, - std::optional max_subscribers, - std::optional max_concurrent_allocations, - const bool enforce_max_samples, - const TracingSlotSizeType number_of_tracing_slots, + explicit LolaFieldInstanceDeployment(LolaEventInstanceDeployment event_deployment, const bool use_get_if_available, const bool use_set_if_available) noexcept; @@ -52,17 +48,11 @@ class LolaFieldInstanceDeployment [[nodiscard]] TracingSlotSizeType GetNumberOfTracingSlots() const noexcept; - /// \brief max subscribers slots is only relevant/required on skeleton side. On the proxy side it is irrelevant. - /// Therefore, it is optional! // Note the struct is not compliant to POD type containing non-POD member. // The struct is used as a config storage obtained by performing the parsing json object. // Public access is more convenient to reach the following members of the struct. // coverity[autosar_cpp14_m11_0_1_violation] - std::optional max_subscribers_; - // coverity[autosar_cpp14_m11_0_1_violation] - std::optional max_concurrent_allocations_; - // coverity[autosar_cpp14_m11_0_1_violation] - bool enforce_max_samples_; + LolaEventInstanceDeployment lola_event_instance_deployment_; // coverity[autosar_cpp14_m11_0_1_violation] bool use_get_if_available_; // coverity[autosar_cpp14_m11_0_1_violation] @@ -73,14 +63,6 @@ class LolaFieldInstanceDeployment constexpr static std::uint32_t serializationVersion = 1U; friend bool operator==(const LolaFieldInstanceDeployment& lhs, const LolaFieldInstanceDeployment& rhs) noexcept; - - private: - /// \brief number of sample slots is only relevant/required on skeleton side, where slots get allocated. On the - /// proxy side it is irrelevant. Therefore, it is optional! - std::optional number_of_sample_slots_; - // Non-zero values greater than one for this parameter only make sense on the skeleton side. For the proxy it is - // just important if the tracing is enabled or not, i.e., if this variable is zero or non-zero. - TracingSlotSizeType number_of_tracing_slots_; }; bool operator==(const LolaFieldInstanceDeployment& lhs, const LolaFieldInstanceDeployment& rhs) noexcept; diff --git a/score/mw/com/impl/configuration/mw_com_config_schema.json b/score/mw/com/impl/configuration/mw_com_config_schema.json index 6eb190dbb..0f99d7b6f 100644 --- a/score/mw/com/impl/configuration/mw_com_config_schema.json +++ b/score/mw/com/impl/configuration/mw_com_config_schema.json @@ -50,15 +50,14 @@ "title": "Type of binding", "type": "string", "enum": [ - "SHM", - "SOME/IP" + "SHM" ], "description": "Binding technology" }, "serviceId": { "type": "integer", "title": "Service Id", - "description": "Binding technology specific service id, it might be 16 or 64 bit. For LoLa/Shm and SOME/IP we have 16 bit values." + "description": "Binding technology specific service id, it might be 16 or 64 bit. For LoLa/Shm we have 16 bit values." }, "events": { "type": "array", @@ -82,7 +81,7 @@ "eventId": { "type": "integer", "title": "Service Event Id", - "description": "Binding technology specific event id. LoLa supports 8 bit, while SOME/IP supports 15 bit." + "description": "Binding technology specific event id. LoLa supports 8 bit." } } } @@ -109,7 +108,7 @@ "fieldId": { "type": "integer", "title": "Service Field Id", - "description": "Binding technology specific field id. LoLa supports 8 bit, while SOME/IP supports 15 bit." + "description": "Binding technology specific field id. LoLa supports 8 bit." }, "Get": { "type": "boolean", @@ -144,7 +143,7 @@ }, "methodId": { "type": "integer", - "description": "Binding technology specific method id. LoLa supports 8 bit, while SOME/IP supports 15 bit." + "description": "Binding technology specific method id. LoLa supports 8 bit." } } } @@ -215,8 +214,7 @@ "binding": { "type": "string", "enum": [ - "SHM", - "SOME/IP" + "SHM" ], "title": "Binding", "description": "Binding technology" @@ -394,13 +392,13 @@ "type": "boolean", "title": "Use Field Getter If Available", "description": "When true, the getter for this field will be used if the service type declares one in the C++ service interface. Applicable for proxy/consumer side.", - "default": true + "default": false }, "useSetIfAvailable": { "type": "boolean", "title": "Use Field Setter If Available", "description": "When true, the setter for this field will be used if the service type declares one in the C++ service interface. Applicable for proxy/consumer side.", - "default": true + "default": false } } } diff --git a/score/mw/com/impl/configuration/test/configuration_test_resources.cpp b/score/mw/com/impl/configuration/test/configuration_test_resources.cpp index 9b90b347a..03de4419c 100644 --- a/score/mw/com/impl/configuration/test/configuration_test_resources.cpp +++ b/score/mw/com/impl/configuration/test/configuration_test_resources.cpp @@ -53,13 +53,9 @@ LolaFieldInstanceDeployment MakeLolaFieldInstanceDeployment( const bool use_get_if_available, const bool use_set_if_available) noexcept { - const LolaFieldInstanceDeployment unit{max_samples, - max_subscribers, - max_concurrent_allocations, - enforce_max_samples, - number_of_tracing_slots, - use_get_if_available, - use_set_if_available}; + const LolaEventInstanceDeployment event_deployment{ + max_samples, max_subscribers, max_concurrent_allocations, enforce_max_samples, number_of_tracing_slots}; + const LolaFieldInstanceDeployment unit{event_deployment, use_get_if_available, use_set_if_available}; return unit; } @@ -157,10 +153,8 @@ void ConfigurationStructsFixture::ExpectLolaFieldInstanceDeploymentObjectsEqual( const LolaFieldInstanceDeployment& lhs, const LolaFieldInstanceDeployment& rhs) const noexcept { - EXPECT_EQ(lhs.max_subscribers_, rhs.max_subscribers_); - EXPECT_EQ(lhs.max_concurrent_allocations_, rhs.max_concurrent_allocations_); - EXPECT_EQ(lhs.enforce_max_samples_, rhs.enforce_max_samples_); - EXPECT_EQ(lhs.GetNumberOfSampleSlotsExcludingTracingSlot(), rhs.GetNumberOfSampleSlotsExcludingTracingSlot()); + ExpectLolaEventInstanceDeploymentObjectsEqual(lhs.lola_event_instance_deployment_, + rhs.lola_event_instance_deployment_); EXPECT_EQ(lhs.use_get_if_available_, rhs.use_get_if_available_); EXPECT_EQ(lhs.use_set_if_available_, rhs.use_set_if_available_); } diff --git a/score/mw/com/impl/plumbing/proxy_event_field_binding_factory_test.cpp b/score/mw/com/impl/plumbing/proxy_event_field_binding_factory_test.cpp index 3a5a21e8d..0ffe9e4b1 100644 --- a/score/mw/com/impl/plumbing/proxy_event_field_binding_factory_test.cpp +++ b/score/mw/com/impl/plumbing/proxy_event_field_binding_factory_test.cpp @@ -56,7 +56,8 @@ const LolaServiceInstanceDeployment kLolaServiceInstanceDeployment{ LolaServiceInstanceId{kInstanceId}, {{kDummyEventName, LolaEventInstanceDeployment{{1U}, {3U}, 1U, true, 0}}, {kDummyGenericProxyEventName, LolaEventInstanceDeployment{{1U}, {3U}, 1U, true, 0}}}, - {{kDummyFieldName, LolaFieldInstanceDeployment{{1U}, {3U}, 1U, true, 0, false, false}}}}; + {{kDummyFieldName, + LolaFieldInstanceDeployment{LolaEventInstanceDeployment{{1U}, {3U}, 1U, true, 0}, false, false}}}}; const LolaServiceTypeDeployment kLolaServiceTypeDeployment{ kServiceId, {{kDummyEventName, kDummyEventId}, {kDummyGenericProxyEventName, kDummyGenericProxyId}}, diff --git a/score/mw/com/impl/plumbing/skeleton_service_element_binding_factory_impl.h b/score/mw/com/impl/plumbing/skeleton_service_element_binding_factory_impl.h index f3bc69910..d16255fbc 100644 --- a/score/mw/com/impl/plumbing/skeleton_service_element_binding_factory_impl.h +++ b/score/mw/com/impl/plumbing/skeleton_service_element_binding_factory_impl.h @@ -43,6 +43,16 @@ namespace score::mw::com::impl namespace detail { +template +lola::SkeletonEventProperties GetSkeletonEventProperties( + const LolaServiceElementInstanceDeployment& lola_service_element_instance_deployment); + +inline lola::SkeletonEventProperties GetSkeletonEventProperties( + const LolaFieldInstanceDeployment& lola_service_element_instance_deployment) +{ + return GetSkeletonEventProperties(lola_service_element_instance_deployment.lola_event_instance_deployment_); +} + template lola::SkeletonEventProperties GetSkeletonEventProperties( const LolaServiceElementInstanceDeployment& lola_service_element_instance_deployment) diff --git a/score/mw/com/impl/plumbing/skeleton_service_element_binding_factory_test.cpp b/score/mw/com/impl/plumbing/skeleton_service_element_binding_factory_test.cpp index 8c619a90a..5e2e37fbf 100644 --- a/score/mw/com/impl/plumbing/skeleton_service_element_binding_factory_test.cpp +++ b/score/mw/com/impl/plumbing/skeleton_service_element_binding_factory_test.cpp @@ -45,7 +45,8 @@ const auto kInstanceSpecifier = InstanceSpecifier::Create(std::string{"/my_dummy const LolaServiceInstanceDeployment kLolaServiceInstanceDeployment{ LolaServiceInstanceId{kInstanceId}, {{kDummyEventName, LolaEventInstanceDeployment{{1U}, {3U}, 1U, true, 0U}}}, - {{kDummyFieldName, LolaFieldInstanceDeployment{{1U}, {3U}, 1U, true, 0U, false, false}}}}; + {{kDummyFieldName, + LolaFieldInstanceDeployment{LolaEventInstanceDeployment{{1U}, {3U}, 1U, true, 0U}, false, false}}}}; const LolaServiceTypeDeployment kLolaServiceTypeDeployment{kServiceId, {{kDummyEventName, kDummyEventId}}, {{kDummyFieldName, kDummyFieldId}}}; @@ -227,7 +228,8 @@ TEST_P(SkeletonServiceElementBindingFactoryParamaterisedDeathTest, const LolaServiceInstanceDeployment lola_service_instance_deployment_with_invalid_names{ LolaServiceInstanceId{kInstanceId}, {{incorrect_event_name, LolaEventInstanceDeployment{{1U}, {3U}, 1U, true, 0U}}}, - {{incorrect_field_name, LolaFieldInstanceDeployment{{1U}, {3U}, 1U, true, 0U, false, false}}}}; + {{incorrect_field_name, + LolaFieldInstanceDeployment{LolaEventInstanceDeployment{{1U}, {3U}, 1U, true, 0U}, false, false}}}}; ConfigurationStore config_store_with_invalid_service_element_names{ kInstanceSpecifier, @@ -255,7 +257,8 @@ TEST_P(SkeletonServiceElementBindingFactoryParamaterisedDeathTest, const LolaServiceInstanceDeployment lola_service_instance_deployment_without_event_sample_slots{ LolaServiceInstanceId{kInstanceId}, {{kDummyEventName, LolaEventInstanceDeployment{{}, {3U}, 1U, true, 0U}}}, - {{kDummyFieldName, LolaFieldInstanceDeployment{{}, {3U}, 1U, true, 0U, false, false}}}}; + {{kDummyFieldName, + LolaFieldInstanceDeployment{LolaEventInstanceDeployment{{}, {3U}, 1U, true, 0U}, false, false}}}}; ConfigurationStore config_store_with_invalid_service_element_names{ kInstanceSpecifier, @@ -284,7 +287,8 @@ TEST_P(SkeletonServiceElementBindingFactoryParamaterisedDeathTest, const LolaServiceInstanceDeployment lola_service_instance_deployment_without_max_subscribers{ LolaServiceInstanceId{kInstanceId}, {{kDummyEventName, LolaEventInstanceDeployment{{1U}, {}, 1U, true, 0U}}}, - {{kDummyFieldName, LolaFieldInstanceDeployment{{2U}, {}, 1U, true, 0U, false, false}}}}; + {{kDummyFieldName, + LolaFieldInstanceDeployment{LolaEventInstanceDeployment{{2U}, {}, 1U, true, 0U}, false, false}}}}; ConfigurationStore config_store_with_invalid_service_element_names{ kInstanceSpecifier, diff --git a/score/mw/com/impl/test/dummy_instance_identifier_builder.cpp b/score/mw/com/impl/test/dummy_instance_identifier_builder.cpp index a134dddc1..a828ba7c4 100644 --- a/score/mw/com/impl/test/dummy_instance_identifier_builder.cpp +++ b/score/mw/com/impl/test/dummy_instance_identifier_builder.cpp @@ -49,7 +49,7 @@ InstanceIdentifier DummyInstanceIdentifierBuilder::CreateValidLolaInstanceIdenti InstanceIdentifier DummyInstanceIdentifierBuilder::CreateValidLolaInstanceIdentifierWithField() { return CreateValidLolaInstanceIdentifierWithField( - {{"test_field", LolaFieldInstanceDeployment{1, 1, 1, true, 0, false, false}}}); + {{"test_field", LolaFieldInstanceDeployment{LolaEventInstanceDeployment{1, 1, 1, true, 0}, false, false}}}); } InstanceIdentifier DummyInstanceIdentifierBuilder::CreateValidLolaInstanceIdentifierWithEvent( diff --git a/score/mw/com/impl/tracing/configuration/tracing_filter_config_test.cpp b/score/mw/com/impl/tracing/configuration/tracing_filter_config_test.cpp index f462ab740..07279134f 100644 --- a/score/mw/com/impl/tracing/configuration/tracing_filter_config_test.cpp +++ b/score/mw/com/impl/tracing/configuration/tracing_filter_config_test.cpp @@ -583,7 +583,9 @@ class ConfigurationFixture : public ::testing::Test { if constexpr (std::is_same::value) { - return Instance(number_of_sample_slots, 1U, 1U, false, number_of_tracing_slots, false, false); + return Instance(LolaEventInstanceDeployment(number_of_sample_slots, 1U, 1U, false, number_of_tracing_slots), + false, + false); } else { diff --git a/score/mw/com/impl/tracing/skeleton_event_tracing_test.cpp b/score/mw/com/impl/tracing/skeleton_event_tracing_test.cpp index 4231c529f..3fe8e0b53 100644 --- a/score/mw/com/impl/tracing/skeleton_event_tracing_test.cpp +++ b/score/mw/com/impl/tracing/skeleton_event_tracing_test.cpp @@ -51,7 +51,7 @@ const std::string kDummyFieldName{"my_dummy_field"}; const LolaServiceInstanceDeployment kLolaServiceInstanceDeploymentWithEventAndField{ LolaServiceInstanceId{1U}, {{kDummyEventName, LolaEventInstanceDeployment{10U, 10U, 2U, true, 0}}}, - {{kDummyFieldName, LolaFieldInstanceDeployment{10U, 10U, 2U, true, 0, false, false}}} + {{kDummyFieldName, LolaFieldInstanceDeployment{LolaEventInstanceDeployment{10U, 10U, 2U, true, 0}, false, false}}} }; const LolaServiceTypeDeployment kLolaServiceTypeDeploymentWithEventAndField{2U,