From b9ed353cacd3e73cce13d325e602a67d6a74b5ee Mon Sep 17 00:00:00 2001 From: Sahithi Nukala Date: Tue, 21 Apr 2026 11:20:05 +0200 Subject: [PATCH] mw/com: Add method configuration support to SOME/IP - Extend the SOME/IP configuration to support method deployment alongside existing events and fields. - This includes new SomeIpMethodInstanceDeployment class, SomeIpServiceTypeDeployment struct, new SOME/IP ID type aliases (event, field, method, service), updated BUILD targets, parser logic for method parsing, and documentation updates. - All related tests have been updated to reflect the new functionality, including updating the stale TerminateOnParsingSomeIP test now that SOME/IP configuration parsing is fully implemented. --- score/mw/com/design/configuration/README.md | 16 +- .../design/configuration/structural_view.puml | 22 +- score/mw/com/impl/configuration/BUILD | 61 +++ score/mw/com/impl/configuration/README.md | 7 +- .../com/impl/configuration/config_parser.cpp | 365 +++++++++++++++--- .../impl/configuration/config_parser_test.cpp | 8 +- .../configuration/mw_com_config_schema.json | 2 + .../configuration/service_type_deployment.cpp | 6 + .../configuration/service_type_deployment.h | 7 +- .../impl/configuration/someip_event_id.cpp | 13 + .../com/impl/configuration/someip_event_id.h | 25 ++ .../impl/configuration/someip_field_id.cpp | 13 + .../com/impl/configuration/someip_field_id.h | 25 ++ .../impl/configuration/someip_method_id.cpp | 13 + .../com/impl/configuration/someip_method_id.h | 25 ++ .../someip_method_instance_deployment.cpp | 58 +++ .../someip_method_instance_deployment.h | 82 ++++ .../impl/configuration/someip_service_id.cpp | 13 + .../impl/configuration/someip_service_id.h | 25 ++ .../someip_service_instance_deployment.cpp | 5 +- .../someip_service_instance_deployment.h | 12 +- .../someip_service_type_deployment.cpp | 13 + .../someip_service_type_deployment.h | 39 ++ .../test/configuration_test_resources.cpp | 35 +- .../test/configuration_test_resources.h | 9 + 25 files changed, 834 insertions(+), 65 deletions(-) create mode 100644 score/mw/com/impl/configuration/someip_event_id.cpp create mode 100644 score/mw/com/impl/configuration/someip_event_id.h create mode 100644 score/mw/com/impl/configuration/someip_field_id.cpp create mode 100644 score/mw/com/impl/configuration/someip_field_id.h create mode 100644 score/mw/com/impl/configuration/someip_method_id.cpp create mode 100644 score/mw/com/impl/configuration/someip_method_id.h create mode 100644 score/mw/com/impl/configuration/someip_method_instance_deployment.cpp create mode 100644 score/mw/com/impl/configuration/someip_method_instance_deployment.h create mode 100644 score/mw/com/impl/configuration/someip_service_id.cpp create mode 100644 score/mw/com/impl/configuration/someip_service_id.h create mode 100644 score/mw/com/impl/configuration/someip_service_type_deployment.cpp create mode 100644 score/mw/com/impl/configuration/someip_service_type_deployment.h diff --git a/score/mw/com/design/configuration/README.md b/score/mw/com/design/configuration/README.md index 1187bb6f2..4a31b47ec 100644 --- a/score/mw/com/design/configuration/README.md +++ b/score/mw/com/design/configuration/README.md @@ -129,7 +129,13 @@ An example of such a mapping is shown here: "eventId": 633 } ], - "fields": [] + "fields": [], + "methods": [ + { + "methodName": "SetPressure", + "methodId": 40 + } + ] }, { "binding": "SHM", @@ -153,7 +159,13 @@ An example of such a mapping is shown here: { "instanceId": 1234, "asil-level": "QM", - "binding": "SOME/IP" + "binding": "SOME/IP", + "methods": [ + { + "methodName": "SetPressure", + "queueSize": 1 + } + ] }, { "instanceId": 62, diff --git a/score/mw/com/design/configuration/structural_view.puml b/score/mw/com/design/configuration/structural_view.puml index 9579a38cd..f526349ea 100644 --- a/score/mw/com/design/configuration/structural_view.puml +++ b/score/mw/com/design/configuration/structural_view.puml @@ -27,8 +27,25 @@ package "configuration" { } class "score::mw::com::impl::SomeIpServiceInstanceDeployment" { - + instanceId: score::cpp::optional const - + ToString() const : std::string + + instance_id_: score::cpp::optional + + events_ : std::unordered_map + + fields_ : std::unordered_map + + methods_ : std::unordered_map + + SomeIpServiceInstanceDeployment(instance_id : score::cpp::optional, events : EventInstanceMapping, fields : FieldInstanceMapping, methods : MethodInstanceMapping) + + Serialize() const : score::json::Object + } + + class "score::mw::com::impl::SomeIpMethodInstanceDeployment" { + {static} + constexpr serializationVersion : std::uint8_t + + queue_size_: std::optional + __ + + SomeIpMethodInstanceDeployment(queue_size : std::optional) + + SomeIpMethodInstanceDeployment(json_object : const score::json::Object&) + {static} + CreateFromJson(json_object : const score::json::Object&) : SomeIpMethodInstanceDeployment + + Serialize() const : score::json::Object + -- + Type Aliases: + using QueueSize as std::uint8_t } class "score::mw::com::impl::LolaServiceInstanceDeployment" { @@ -228,6 +245,7 @@ class "score::mw::com::impl::Runtime" { "score::mw::com::impl::LolaServiceInstanceDeployment" *-- "score::mw::com::impl::LolaEventInstanceDeployment" : 0..1 "score::mw::com::impl::LolaServiceInstanceDeployment" *-- "score::mw::com::impl::LolaFieldInstanceDeployment" : 0..1 "score::mw::com::impl::LolaServiceInstanceDeployment" *-- "score::mw::com::impl::LolaMethodInstanceDeployment" : 0..1 +"score::mw::com::impl::SomeIpServiceInstanceDeployment" *-- "score::mw::com::impl::SomeIpMethodInstanceDeployment" : 0..1 "score::mw::com::impl::Configuration" *-- "score::mw::com::ServiceIdentifierType" "score::mw::com::impl::Configuration" *-- "score::mw::com::impl::ServiceInstanceDeployment" "score::mw::com::impl::Configuration" *-- "GlobalConfiguration" diff --git a/score/mw/com/impl/configuration/BUILD b/score/mw/com/impl/configuration/BUILD index 5f3533474..e12509d64 100644 --- a/score/mw/com/impl/configuration/BUILD +++ b/score/mw/com/impl/configuration/BUILD @@ -50,6 +50,7 @@ cc_library( ":lola_service_instance_deployment", ":quality_type", ":service_type_deployment", + ":someip_method_instance_deployment", ":someip_service_instance_deployment", "@score_logging//score/mw/log", ], @@ -195,6 +196,39 @@ cc_library( tags = ["FFI"], ) +cc_library( + name = "someip_event_id", + srcs = ["someip_event_id.cpp"], + hdrs = ["someip_event_id.h"], + features = COMPILER_WARNING_FEATURES, + tags = ["FFI"], +) + +cc_library( + name = "someip_field_id", + srcs = ["someip_field_id.cpp"], + hdrs = ["someip_field_id.h"], + features = COMPILER_WARNING_FEATURES, + tags = ["FFI"], + deps = [":someip_event_id"], +) + +cc_library( + name = "someip_method_id", + srcs = ["someip_method_id.cpp"], + hdrs = ["someip_method_id.h"], + features = COMPILER_WARNING_FEATURES, + tags = ["FFI"], +) + +cc_library( + name = "someip_service_id", + srcs = ["someip_service_id.cpp"], + hdrs = ["someip_service_id.h"], + features = COMPILER_WARNING_FEATURES, + tags = ["FFI"], +) + cc_library( name = "lola_field_instance_deployment", srcs = ["lola_field_instance_deployment.cpp"], @@ -222,6 +256,15 @@ cc_library( deps = ["@score_baselibs//score/json"], ) +cc_library( + name = "someip_method_instance_deployment", + srcs = ["someip_method_instance_deployment.cpp"], + hdrs = ["someip_method_instance_deployment.h"], + features = COMPILER_WARNING_FEATURES, + tags = ["FFI"], + deps = ["@score_baselibs//score/json"], +) + cc_library( name = "lola_service_instance_deployment", srcs = ["lola_service_instance_deployment.cpp"], @@ -257,6 +300,21 @@ cc_library( ], ) +cc_library( + name = "someip_service_type_deployment", + srcs = ["someip_service_type_deployment.cpp"], + hdrs = ["someip_service_type_deployment.h"], + features = COMPILER_WARNING_FEATURES, + tags = ["FFI"], + deps = [ + ":binding_service_type_deployment", + ":someip_event_id", + ":someip_field_id", + ":someip_method_id", + ":someip_service_id", + ], +) + cc_library( name = "lola_service_instance_id", srcs = ["lola_service_instance_id.cpp"], @@ -336,6 +394,7 @@ cc_library( deps = [ ":configuration_common_resources", ":lola_service_type_deployment", + ":someip_service_type_deployment", "@score_baselibs//score/json", "@score_baselibs//score/language/futurecpp", ], @@ -364,6 +423,7 @@ cc_library( ":configuration_common_resources", ":someip_event_instance_deployment", ":someip_field_instance_deployment", + ":someip_method_instance_deployment", ":someip_service_instance_id", "@score_baselibs//score/json", "@score_baselibs//score/language/futurecpp", @@ -429,6 +489,7 @@ cc_library( ":service_type_deployment", ":service_version_type", ":shm_size_calc_mode", + ":someip_method_instance_deployment", ":someip_service_instance_deployment", ], ) diff --git a/score/mw/com/impl/configuration/README.md b/score/mw/com/impl/configuration/README.md index efe772ca0..38f382d34 100644 --- a/score/mw/com/impl/configuration/README.md +++ b/score/mw/com/impl/configuration/README.md @@ -94,8 +94,9 @@ support cross-ECU communication. However, the `service-type` on which the `service-instance` is based on, needs to support the technical transport mechanism (`binding`) and needs to configure the instance `independent` parts of the binding. -Currently, the only supported binding is the shared-memory binding, which is represented as `SHM` in the json. -The other binding `SOME/IP`, which the schema allows, is only a placeholder right now. +Currently, the fully functional end-to-end binding is the shared-memory binding, which is represented as `SHM` in the json. +The `SOME/IP` binding configuration layer (schema, parsing, and deployment classes) is also implemented and supported in the json. +However, the `SOME/IP` transport layer implementation is still pending. In the corresponding snippet from our example configuration: "bindings": [ @@ -593,3 +594,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.methods.methodName_ | required | required | | +| _serviceInstances.instances.methods.queueSize_ | optional | - | if not given on skeleton side, defaults to 1. Currently only queue sizes of 1 are supported. | diff --git a/score/mw/com/impl/configuration/config_parser.cpp b/score/mw/com/impl/configuration/config_parser.cpp index 11bd15564..b679c6614 100644 --- a/score/mw/com/impl/configuration/config_parser.cpp +++ b/score/mw/com/impl/configuration/config_parser.cpp @@ -16,6 +16,12 @@ #include "score/mw/com/impl/configuration/lola_service_instance_deployment.h" #include "score/mw/com/impl/configuration/quality_type.h" #include "score/mw/com/impl/configuration/service_type_deployment.h" +#include "score/mw/com/impl/configuration/someip_event_id.h" +#include "score/mw/com/impl/configuration/someip_field_id.h" +#include "score/mw/com/impl/configuration/someip_method_id.h" +#include "score/mw/com/impl/configuration/someip_service_id.h" +#include "score/mw/com/impl/configuration/someip_service_instance_deployment.h" +#include "score/mw/com/impl/configuration/someip_service_type_deployment.h" #include "score/mw/com/impl/configuration/tracing_configuration.h" #include "score/mw/com/impl/instance_specifier.h" #include "score/mw/com/impl/service_element_type.h" @@ -531,6 +537,57 @@ auto ParseLolaMethodInstanceDeployment(const score::json::Object& json_map, Lola } } +// See Note 1 +// coverity[autosar_cpp14_a15_5_3_violation] +auto ParseSomeIpMethodInstanceDeployment(const score::json::Object& json_map, SomeIpServiceInstanceDeployment& service) + -> void +{ + const auto& methods = json_map.find(kMethodsKey.data()); + if (methods == json_map.cend()) + { + return; + } + + const auto methods_list_result = methods->second.As(); + SCORE_LANGUAGE_FUTURECPP_PRECONDITION_PRD_MESSAGE(methods_list_result.has_value(), + "Configuration corrupted, check with json schema"); + const auto& methods_list = methods_list_result.value().get(); + for (const auto& method : methods_list) + { + const auto method_casted = method.As(); + SCORE_LANGUAGE_FUTURECPP_PRECONDITION_PRD_MESSAGE(method_casted.has_value(), + "Configuration corrupted, check with json schema"); + const auto& method_object = method_casted.value().get(); + const auto& method_name = GetValueFromJson(method_object, kMethodNameKey); + const std::optional queue_size = + GetOptionalValueFromJson(method_object, kMethodQueueSizeKey); + const SomeIpMethodInstanceDeployment method_deployment{queue_size}; + + const auto emplace_result = service.methods_.emplace( + std::piecewise_construct, std::forward_as_tuple(method_name), std::forward_as_tuple(method_deployment)); + SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD_MESSAGE(emplace_result.second, "Could not emplace element in map"); + } +} + +auto ParseSomeIpServiceInstanceDeployment(const score::json::Object& json_map) -> SomeIpServiceInstanceDeployment +{ + SomeIpServiceInstanceDeployment service{}; + + const auto& instance_id = json_map.find(kInstanceIdKey.data()); + if (instance_id != json_map.cend()) + { + const auto instance_id_casted = instance_id->second.As(); + SCORE_LANGUAGE_FUTURECPP_PRECONDITION_PRD_MESSAGE(instance_id_casted.has_value(), + "Configuration corrupted, check with json schema"); + const auto instance_id_value = instance_id_casted.value(); + service.instance_id_ = SomeIpServiceInstanceId{instance_id_value}; + } + + ParseSomeIpMethodInstanceDeployment(json_map, service); + + return service; +} + // See Note 1 // coverity[autosar_cpp14_a15_5_3_violation] auto ParseServiceElementTracingEnabled(const score::json::Object& json_map, @@ -701,8 +758,11 @@ auto ParseServiceInstanceDeployments(const score::json::Object& json_map, const auto& bindingValue = bindingValue_result.value().get(); if (bindingValue == kSomeIpBinding) { - score::mw::log::LogFatal("lola") << "Provided SOME/IP binding, which can not be parsed."; - SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(false); + // Return Value not needed in this context + score::cpp::ignore = deployments.emplace_back(service, + ParseSomeIpServiceInstanceDeployment(deployment_map), + asil_level.value(), + instance_specifier); } else if (bindingValue == kShmBinding) { @@ -919,6 +979,210 @@ auto ParseLolaMethodTypeDeployments(const score::json::Object& json_map, LolaSer return true; } +auto ParseSomeIpMethodTypeDeployments(const score::json::Object& json_map, SomeIpServiceTypeDeployment& service) -> bool +{ + const auto& methods = json_map.find(kMethodsKey.data()); + if (methods == json_map.cend()) + { + return false; + } + + auto methods_list_result = methods->second.As(); + SCORE_LANGUAGE_FUTURECPP_PRECONDITION_PRD_MESSAGE(methods_list_result.has_value(), + "Configuration corrupted, check with json schema"); + const auto& methods_list = methods_list_result.value().get(); + for (const auto& method : methods_list) + { + const auto& method_object_casted = method.As(); + SCORE_LANGUAGE_FUTURECPP_PRECONDITION_PRD_MESSAGE(method_object_casted.has_value(), + "Configuration corrupted, check with json schema"); + const auto& method_object = method_object_casted.value().get(); + const auto& method_name = method_object.find(kMethodNameKey.data()); + const auto& method_id = method_object.find(kMethodIdKey.data()); + + SCORE_LANGUAGE_FUTURECPP_PRECONDITION_PRD_MESSAGE( + (method_name != method_object.cend()) && (method_id != method_object.cend()), + "Configuration corrupted, check with json schema"); + + const auto method_name_casted = method_name->second.As(); + SCORE_LANGUAGE_FUTURECPP_PRECONDITION_PRD_MESSAGE(method_name_casted.has_value(), + "Configuration corrupted, check with json schema"); + const auto method_id_casted = method_id->second.As(); + SCORE_LANGUAGE_FUTURECPP_PRECONDITION_PRD_MESSAGE(method_id_casted.has_value(), + "Configuration corrupted, check with json schema"); + const auto result = service.methods_.emplace(std::piecewise_construct, + std::forward_as_tuple(method_name_casted.value().get()), + std::forward_as_tuple(method_id_casted.value())); + + if (result.second != true) + { + score::mw::log::LogFatal("someip") << "A method was configured twice."; + SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(false); + } + } + return true; +} + +// See Note 1 +// coverity[autosar_cpp14_a15_5_3_violation] +auto ParseSomeIpEventTypeDeployments(const score::json::Object& json_map, SomeIpServiceTypeDeployment& service) -> bool +{ + const auto& events = json_map.find(kEventsKey.data()); + if (events == json_map.cend()) + { + return false; + } + auto events_list_result = events->second.As(); + SCORE_LANGUAGE_FUTURECPP_PRECONDITION_PRD_MESSAGE(events_list_result.has_value(), + "Configuration corrupted, check with json schema"); + const auto& events_list = events_list_result.value().get(); + for (const auto& event : events_list) + { + const auto event_obj = event.As(); + SCORE_LANGUAGE_FUTURECPP_PRECONDITION_PRD_MESSAGE(event_obj.has_value(), + "Configuration corrupted, check with json schema"); + const auto& event_object = event_obj.value().get(); + const auto& event_name = event_object.find(kEventNameKey.data()); + const auto& event_id = event_object.find(kEventIdKey.data()); + + SCORE_LANGUAGE_FUTURECPP_PRECONDITION_PRD_MESSAGE( + (event_name != event_object.cend()) && (event_id != event_object.cend()), + "Configuration corrupted, check with json schema"); + + const auto event_name_casted = event_name->second.As(); + SCORE_LANGUAGE_FUTURECPP_PRECONDITION_PRD_MESSAGE(event_name_casted.has_value(), + "Configuration corrupted, check with json schema"); + const auto event_id_casted = event_id->second.As(); + SCORE_LANGUAGE_FUTURECPP_PRECONDITION_PRD_MESSAGE(event_id_casted.has_value(), + "Configuration corrupted, check with json schema"); + const auto result = service.events_.emplace(std::piecewise_construct, + std::forward_as_tuple(event_name_casted.value().get()), + std::forward_as_tuple(event_id_casted.value())); + + if (result.second != true) + { + score::mw::log::LogFatal("someip") << "An event was configured twice."; + SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(false); + } + } + return true; +} + +// See Note 1 +// coverity[autosar_cpp14_a15_5_3_violation] +auto ParseSomeIpFieldTypeDeployments(const score::json::Object& json_map, SomeIpServiceTypeDeployment& service) -> bool +{ + const auto& fields = json_map.find(kFieldsKey.data()); + if (fields == json_map.cend()) + { + return false; + } + + auto fields_list_result = fields->second.As(); + SCORE_LANGUAGE_FUTURECPP_PRECONDITION_PRD_MESSAGE(fields_list_result.has_value(), + "Configuration corrupted, check with json schema"); + const auto& fields_list = fields_list_result.value().get(); + for (const auto& field : fields_list) + { + auto field_obj = field.As(); + SCORE_LANGUAGE_FUTURECPP_PRECONDITION_PRD_MESSAGE(field_obj.has_value(), + "Configuration corrupted, check with json schema"); + const auto& field_object = field_obj.value().get(); + const auto& field_name = field_object.find(kFieldNameKey.data()); + const auto& field_id = field_object.find(kFieldIdKey.data()); + + SCORE_LANGUAGE_FUTURECPP_PRECONDITION_PRD_MESSAGE( + (field_name != field_object.cend()) && (field_id != field_object.cend()), + "Configuration corrupted, check with json schema"); + + const auto field_name_casted = field_name->second.As(); + SCORE_LANGUAGE_FUTURECPP_PRECONDITION_PRD_MESSAGE(field_name_casted.has_value(), + "Configuration corrupted, check with json schema"); + const auto field_id_casted = field_id->second.As(); + SCORE_LANGUAGE_FUTURECPP_PRECONDITION_PRD_MESSAGE(field_id_casted.has_value(), + "Configuration corrupted, check with json schema"); + const auto result = service.fields_.emplace(std::piecewise_construct, + std::forward_as_tuple(field_name_casted.value().get()), + std::forward_as_tuple(field_id_casted.value())); + + if (result.second != true) + { + score::mw::log::LogFatal("someip") << "A field was configured twice."; + SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(false); + } + } + return true; +} + +auto AreSomeIpEventFieldAndMethodIdsUnique(const SomeIpServiceTypeDeployment& someip_service_type_deployment) -> bool +{ + const auto& events = someip_service_type_deployment.events_; + const auto& fields = someip_service_type_deployment.fields_; + const auto& methods = someip_service_type_deployment.methods_; + + static_assert(std::is_same::value, + "EventId and FieldId should have the same underlying type."); + static_assert(std::is_same::value, + "EventId and MethodId should have the same underlying type."); + std::set ids{}; + + for (const auto& event : events) + { + const auto result = ids.insert(event.second); + if (!result.second) + { + return false; + } + } + + for (const auto& field : fields) + { + const auto result = ids.insert(field.second); + if (!result.second) + { + return false; + } + } + + for (const auto& method : methods) + { + const auto result = ids.insert(method.second); + if (!result.second) + { + return false; + } + } + return true; +} + +// See Note 1 +// coverity[autosar_cpp14_a15_5_3_violation] +auto ParseSomeIpServiceTypeDeployments(const score::json::Object& json_map) -> SomeIpServiceTypeDeployment +{ + const auto& service_id = json_map.find(kServiceIdKey.data()); + SCORE_LANGUAGE_FUTURECPP_PRECONDITION_PRD_MESSAGE(service_id != json_map.cend(), + "Configuration corrupted, check with json schema"); + + const auto service_id_casted = service_id->second.As(); + SCORE_LANGUAGE_FUTURECPP_PRECONDITION_PRD_MESSAGE(service_id_casted.has_value(), + "Configuration corrupted, check with json schema"); + SomeIpServiceTypeDeployment someip{service_id_casted.value()}; + const bool events_exist = ParseSomeIpEventTypeDeployments(json_map, someip); + const bool fields_exist = ParseSomeIpFieldTypeDeployments(json_map, someip); + const bool methods_exist = ParseSomeIpMethodTypeDeployments(json_map, someip); + if (!events_exist && !fields_exist && !methods_exist) + { + score::mw::log::LogFatal("someip") << "Configuration should contain at least one event, field, or method."; + SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(false); + } + if (!AreSomeIpEventFieldAndMethodIdsUnique(someip)) + { + score::mw::log::LogFatal("someip") << "Configuration cannot contain duplicate eventId, fieldId, or methodId."; + SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(false); + } + return someip; +} + auto AreEventFieldAndMethodIdsUnique(const LolaServiceTypeDeployment& lola_service_type_deployment) -> bool { const auto& events = lola_service_type_deployment.events_; @@ -1021,7 +1285,8 @@ auto ParseServiceTypeDeployment(const score::json::Object& json_map) -> ServiceT } else if (value == kSomeIpBinding) { - // we skip this, because we don't support SOME/IP right now. + SomeIpServiceTypeDeployment someip_deployment = ParseSomeIpServiceTypeDeployments(binding_map); + return ServiceTypeDeployment{someip_deployment}; } else { @@ -1323,62 +1588,66 @@ void CrosscheckServiceInstancesToTypes(const Configuration& config) << "), which is not configured. This is invalid, terminating"; SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(false); } - // check, that binding in service type and service instance are equal. Since currently ServiceTypeDeployment - // only supports LolaServiceTypeDeployment, everything else than LolaServiceInstanceDeployment is an error. - // LCOV_EXCL_BR_START: Defensive programming: Parse() currently terminates if the ServiceInstanceDeployment - // contains anything other than a Lola binding. Therefore, it's impossible to reach this point without - // a LolaServiceInstanceDeployment. - if (!std::holds_alternative(service_instance.second.bindingInfo_)) - { - // LCOV_EXCL_BR_STOP - // LCOV_EXCL_START defensive programming: Parse() currently terminates if the ServiceInstanceDeployment - // contains anything other than a Lola binding. Therefore, it's impossible to reach this point without - // a LolaServiceInstanceDeployment. - ::score::mw::log::LogFatal("lola") - << "Service instance " << service_instance.first - << "refers to an not yet supported binding. This is invalid, terminating"; - SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(false); - // LCOV_EXCL_STOP - } - if (!std::holds_alternative(foundServiceType->second.binding_info_)) - { - ::score::mw::log::LogFatal("lola") - << "Service type " << service_instance.second.service_.ToString() - << "refers to an not yet supported binding. This is invalid, terminating"; - SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(false); - } - // check, that for each service-element-name in the instance deployment, there exists a corresponding - // service-element-name in the type deployment - const auto& serviceInstanceDeployment = - std::get(service_instance.second.bindingInfo_); - for (const auto& eventInstanceElement : serviceInstanceDeployment.events_) + + if (std::holds_alternative(service_instance.second.bindingInfo_)) { - const auto& serviceTypeDeployment = - std::get(foundServiceType->second.binding_info_); - const auto search = serviceTypeDeployment.events_.find(eventInstanceElement.first); - if (search == serviceTypeDeployment.events_.cend()) + if (!std::holds_alternative(foundServiceType->second.binding_info_)) { ::score::mw::log::LogFatal("lola") - << "Service instance " << service_instance.first << "event" << eventInstanceElement.first - << "refers to an event, which doesn't exist in the referenced service type (" - << service_instance.second.service_.ToString() << "). This is invalid, terminating"; + << "Service type " << service_instance.second.service_.ToString() + << "refers to an not yet supported binding. This is invalid, terminating"; SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(false); } + // check, that for each service-element-name in the instance deployment, there exists a corresponding + // service-element-name in the type deployment + const auto& serviceInstanceDeployment = + std::get(service_instance.second.bindingInfo_); + for (const auto& eventInstanceElement : serviceInstanceDeployment.events_) + { + const auto& serviceTypeDeployment = + std::get(foundServiceType->second.binding_info_); + const auto search = serviceTypeDeployment.events_.find(eventInstanceElement.first); + if (search == serviceTypeDeployment.events_.cend()) + { + ::score::mw::log::LogFatal("lola") + << "Service instance " << service_instance.first << "event" << eventInstanceElement.first + << "refers to an event, which doesn't exist in the referenced service type (" + << service_instance.second.service_.ToString() << "). This is invalid, terminating"; + SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(false); + } + } + for (const auto& fieldInstanceElement : serviceInstanceDeployment.fields_) + { + const auto& serviceTypeDeployment = + std::get(foundServiceType->second.binding_info_); + const auto search = serviceTypeDeployment.fields_.find(fieldInstanceElement.first); + if (search == serviceTypeDeployment.fields_.cend()) + { + ::score::mw::log::LogFatal("lola") + << "Service instance " << service_instance.first << "field" << fieldInstanceElement.first + << "refers to a field, which doesn't exist in the referenced service type (" + << service_instance.second.service_.ToString() << "). This is invalid, terminating"; + SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(false); + } + } } - for (const auto& fieldInstanceElement : serviceInstanceDeployment.fields_) + else if (std::holds_alternative(service_instance.second.bindingInfo_)) { - const auto& serviceTypeDeployment = - std::get(foundServiceType->second.binding_info_); - const auto search = serviceTypeDeployment.fields_.find(fieldInstanceElement.first); - if (search == serviceTypeDeployment.fields_.cend()) + if (!std::holds_alternative(foundServiceType->second.binding_info_)) { - ::score::mw::log::LogFatal("lola") - << "Service instance " << service_instance.first << "field" << fieldInstanceElement.first - << "refers to a field, which doesn't exist in the referenced service type (" - << service_instance.second.service_.ToString() << "). This is invalid, terminating"; + ::score::mw::log::LogFatal("someip") + << "Service type " << service_instance.second.service_.ToString() + << "refers to an not yet supported binding. This is invalid, terminating"; SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(false); } } + else + { + ::score::mw::log::LogFatal("lola") + << "Service instance " << service_instance.first + << "refers to an not yet supported binding. This is invalid, terminating"; + SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(false); + } } } diff --git a/score/mw/com/impl/configuration/config_parser_test.cpp b/score/mw/com/impl/configuration/config_parser_test.cpp index 9ada2b143..b13321830 100644 --- a/score/mw/com/impl/configuration/config_parser_test.cpp +++ b/score/mw/com/impl/configuration/config_parser_test.cpp @@ -2475,7 +2475,7 @@ TEST(ConfigParser, InvalidQualityTypeForAllowedConsumersWillDie) SCORE_LANGUAGE_FUTURECPP_EXPECT_CONTRACT_VIOLATED(score::mw::com::impl::configuration::Parse(std::move(j2))); } -TEST(ConfigParser, TerminateOnParsingSomeIP) +TEST(ConfigParser, SuccessfullyParseSomeIP) { // Give a SOME/IP binding configuration auto config_with_some_ip_binding = R"( @@ -2524,10 +2524,8 @@ TEST(ConfigParser, TerminateOnParsingSomeIP) const score::json::JsonParser json_parser_obj; auto json = json_parser_obj.FromBuffer(config_with_some_ip_binding); - // When parsing such a configuration - // Fail and abort - SCORE_LANGUAGE_FUTURECPP_EXPECT_CONTRACT_VIOLATED( - score::mw::com::impl::configuration::Parse(std::move(json).value())); + // When parsing such a configuration, it should succeed (SOME/IP config parsing is now implemented) + EXPECT_NO_FATAL_FAILURE(score::mw::com::impl::configuration::Parse(std::move(json).value())); } class ShmSizeCalcMode : public ::testing::TestWithParam> 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 00fe1e343..61945a937 100644 --- a/score/mw/com/impl/configuration/mw_com_config_schema.json +++ b/score/mw/com/impl/configuration/mw_com_config_schema.json @@ -128,6 +128,7 @@ }, "methods": { "type": "array", + "title": "Service Methods", "description": "optional (serviceType may have no methods) binding specific method configurations of this serviceType.", "items": { "type": "object", @@ -395,6 +396,7 @@ }, "methods": { "type": "array", + "title": "Method Bindings", "description": "(optional) Binding technology specific configuration of methods within this instance", "items": { "type": "object", diff --git a/score/mw/com/impl/configuration/service_type_deployment.cpp b/score/mw/com/impl/configuration/service_type_deployment.cpp index c89829131..376de6cb7 100644 --- a/score/mw/com/impl/configuration/service_type_deployment.cpp +++ b/score/mw/com/impl/configuration/service_type_deployment.cpp @@ -71,6 +71,9 @@ std::string ToHashStringImpl(const ServiceTypeDeployment::BindingInformation& bi [](const LolaServiceTypeDeployment& service_type_deployment) noexcept -> std::string_view { return service_type_deployment.ToHashString(); }, + [](const SomeIpServiceTypeDeployment& service_type_deployment) noexcept -> std::string_view { + return service_type_deployment.ToHashString(); + }, // FP: only one statement in this line // coverity[autosar_cpp14_a7_1_7_violation] [](const score::cpp::blank&) noexcept -> std::string_view { @@ -125,6 +128,9 @@ score::json::Object ServiceTypeDeployment::Serialize() const noexcept [&json_object](const LolaServiceTypeDeployment& deployment) { json_object[kBindingInfoKey] = deployment.Serialize(); }, + [&json_object](const SomeIpServiceTypeDeployment& deployment) { + json_object[kBindingInfoKey] = deployment.Serialize(); + }, [](const score::cpp::blank&) noexcept {}); std::visit(visitor, binding_info_); diff --git a/score/mw/com/impl/configuration/service_type_deployment.h b/score/mw/com/impl/configuration/service_type_deployment.h index c509f6c60..0073168b9 100644 --- a/score/mw/com/impl/configuration/service_type_deployment.h +++ b/score/mw/com/impl/configuration/service_type_deployment.h @@ -14,10 +14,12 @@ #define SCORE_MW_COM_IMPL_CONFIGURATION_SERVICE_TYPE_DEPLOYMENT_H #include "score/mw/com/impl/configuration/lola_service_type_deployment.h" +#include "score/mw/com/impl/configuration/someip_service_type_deployment.h" #include "score/json/json_parser.h" #include "score/mw/log/logging.h" +#include #include #include #include @@ -30,7 +32,7 @@ namespace score::mw::com::impl class ServiceTypeDeployment { public: - using BindingInformation = std::variant; + using BindingInformation = std::variant; explicit ServiceTypeDeployment(const score::json::Object& json_object) noexcept; @@ -54,7 +56,8 @@ class ServiceTypeDeployment */ // Variable is used in a test case -> so this line is tested and prepared for easier reuse // coverity[autosar_cpp14_a0_1_1_violation] - constexpr static std::size_t hashStringSize{LolaServiceTypeDeployment::hashStringSize + 1U}; + constexpr static std::size_t hashStringSize{ + std::max(LolaServiceTypeDeployment::hashStringSize, SomeIpServiceTypeDeployment::hashStringSize) + 1U}; constexpr static std::uint32_t serializationVersion = 1U; diff --git a/score/mw/com/impl/configuration/someip_event_id.cpp b/score/mw/com/impl/configuration/someip_event_id.cpp new file mode 100644 index 000000000..1a9acb2db --- /dev/null +++ b/score/mw/com/impl/configuration/someip_event_id.cpp @@ -0,0 +1,13 @@ +/******************************************************************************** + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "score/mw/com/impl/configuration/someip_event_id.h" diff --git a/score/mw/com/impl/configuration/someip_event_id.h b/score/mw/com/impl/configuration/someip_event_id.h new file mode 100644 index 000000000..eb84fda6d --- /dev/null +++ b/score/mw/com/impl/configuration/someip_event_id.h @@ -0,0 +1,25 @@ +/******************************************************************************** + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#ifndef SCORE_MW_COM_IMPL_CONFIGURATION_SOMEIP_EVENT_ID_H +#define SCORE_MW_COM_IMPL_CONFIGURATION_SOMEIP_EVENT_ID_H + +#include + +namespace score::mw::com::impl +{ + +using SomeIpEventId = std::uint16_t; + +} // namespace score::mw::com::impl + +#endif // SCORE_MW_COM_IMPL_CONFIGURATION_SOMEIP_EVENT_ID_H diff --git a/score/mw/com/impl/configuration/someip_field_id.cpp b/score/mw/com/impl/configuration/someip_field_id.cpp new file mode 100644 index 000000000..a651064c6 --- /dev/null +++ b/score/mw/com/impl/configuration/someip_field_id.cpp @@ -0,0 +1,13 @@ +/******************************************************************************** + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "score/mw/com/impl/configuration/someip_field_id.h" diff --git a/score/mw/com/impl/configuration/someip_field_id.h b/score/mw/com/impl/configuration/someip_field_id.h new file mode 100644 index 000000000..8ad858a6d --- /dev/null +++ b/score/mw/com/impl/configuration/someip_field_id.h @@ -0,0 +1,25 @@ +/******************************************************************************** + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#ifndef SCORE_MW_COM_IMPL_CONFIGURATION_SOMEIP_FIELD_ID_H +#define SCORE_MW_COM_IMPL_CONFIGURATION_SOMEIP_FIELD_ID_H + +#include "score/mw/com/impl/configuration/someip_event_id.h" + +namespace score::mw::com::impl +{ + +using SomeIpFieldId = SomeIpEventId; + +} // namespace score::mw::com::impl + +#endif // SCORE_MW_COM_IMPL_CONFIGURATION_SOMEIP_FIELD_ID_H diff --git a/score/mw/com/impl/configuration/someip_method_id.cpp b/score/mw/com/impl/configuration/someip_method_id.cpp new file mode 100644 index 000000000..7a5ac5535 --- /dev/null +++ b/score/mw/com/impl/configuration/someip_method_id.cpp @@ -0,0 +1,13 @@ +/******************************************************************************** + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "score/mw/com/impl/configuration/someip_method_id.h" diff --git a/score/mw/com/impl/configuration/someip_method_id.h b/score/mw/com/impl/configuration/someip_method_id.h new file mode 100644 index 000000000..429eb584d --- /dev/null +++ b/score/mw/com/impl/configuration/someip_method_id.h @@ -0,0 +1,25 @@ +/******************************************************************************** + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#ifndef SCORE_MW_COM_IMPL_CONFIGURATION_SOMEIP_METHOD_ID_H +#define SCORE_MW_COM_IMPL_CONFIGURATION_SOMEIP_METHOD_ID_H + +#include + +namespace score::mw::com::impl +{ + +using SomeIpMethodId = std::uint16_t; + +} // namespace score::mw::com::impl + +#endif // SCORE_MW_COM_IMPL_CONFIGURATION_SOMEIP_METHOD_ID_H diff --git a/score/mw/com/impl/configuration/someip_method_instance_deployment.cpp b/score/mw/com/impl/configuration/someip_method_instance_deployment.cpp new file mode 100644 index 000000000..0c5c357b2 --- /dev/null +++ b/score/mw/com/impl/configuration/someip_method_instance_deployment.cpp @@ -0,0 +1,58 @@ +/******************************************************************************** + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "score/mw/com/impl/configuration/someip_method_instance_deployment.h" + +#include +#include + +namespace score::mw::com::impl +{ + +namespace +{ +using std::string_view_literals::operator""sv; +constexpr auto kQueueSizeKey = "queueSize"sv; +} // namespace + +SomeIpMethodInstanceDeployment::SomeIpMethodInstanceDeployment(std::optional queue_size) + : queue_size_{queue_size} +{ +} + +SomeIpMethodInstanceDeployment::SomeIpMethodInstanceDeployment( + const score::json::Object& serialized_someip_method_instance_deployment) +{ + const auto queue_size_iter = serialized_someip_method_instance_deployment.find(kQueueSizeKey.data()); + if (queue_size_iter != serialized_someip_method_instance_deployment.cend()) + { + queue_size_ = queue_size_iter->second.As().value(); + } +} + +SomeIpMethodInstanceDeployment SomeIpMethodInstanceDeployment::CreateFromJson( + const score::json::Object& serialized_someip_method_instance_deployment) +{ + return SomeIpMethodInstanceDeployment{serialized_someip_method_instance_deployment}; +} + +score::json::Object SomeIpMethodInstanceDeployment::Serialize() const +{ + score::json::Object result; + if (queue_size_.has_value()) + { + result[kQueueSizeKey.data()] = score::json::Any{queue_size_.value()}; + } + return result; +} + +} // namespace score::mw::com::impl diff --git a/score/mw/com/impl/configuration/someip_method_instance_deployment.h b/score/mw/com/impl/configuration/someip_method_instance_deployment.h new file mode 100644 index 000000000..5fcc7e173 --- /dev/null +++ b/score/mw/com/impl/configuration/someip_method_instance_deployment.h @@ -0,0 +1,82 @@ +/******************************************************************************** + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#ifndef SCORE_MW_COM_IMPL_CONFIGURATION_SOMEIP_METHOD_INSTANCE_DEPLOYMENT_H +#define SCORE_MW_COM_IMPL_CONFIGURATION_SOMEIP_METHOD_INSTANCE_DEPLOYMENT_H + +#include "score/json/json_parser.h" + +#include +#include + +namespace score::mw::com::impl +{ + +/** + * @brief Represents instance-specific deployment configuration for a someip method. + * + * This class encapsulates deployment parameters for a specific method instance within + * a service instance. + * + * The class provides JSON serialization capabilities. Deserialization is handled through + * the constructor and CreateFromJson factory method. + */ +class SomeIpMethodInstanceDeployment +{ + public: + using QueueSize = std::uint8_t; + + /** + * @brief Construct SomeIpMethodInstanceDeployment with optional queue size, because SomeIpMethodInstanceDeployment + * for a consumer will have a value while one for a provider will not. + * @param queue_size The maximum number of pending method requests that can be queued. + */ + explicit SomeIpMethodInstanceDeployment(std::optional queue_size); + + explicit SomeIpMethodInstanceDeployment(const score::json::Object& serialized_someip_method_instance_deployment); + + static SomeIpMethodInstanceDeployment CreateFromJson( + const score::json::Object& serialized_someip_method_instance_deployment); + + /** + * @brief Serializes the deployment configuration to a JSON object. + * @return A JSON object representing the method instance deployment. + */ + score::json::Object Serialize() const; + + /** + * @brief Version number of the serialization format. + * + * This constant is used to track the version of the serialization format for + * backward compatibility. If the format changes in future versions, this number + * should be incremented. + */ + // Finding States that: A project shall not contain instances of non-volatile variables being given values that are + // not subsequently used. + // Since the goal of the serializationVersion is to be used in the future, we decide to ignore this warning. + // coverity[autosar_cpp14_a0_1_1_violation] + constexpr static std::uint8_t serializationVersion{1U}; + + /** + * @brief The maximum number of method requests that can be queued on the server side. + */ + std::optional queue_size_{std::nullopt}; +}; + +inline bool operator==(const SomeIpMethodInstanceDeployment& lhs, const SomeIpMethodInstanceDeployment& rhs) noexcept +{ + return lhs.queue_size_ == rhs.queue_size_; +} + +} // namespace score::mw::com::impl + +#endif // SCORE_MW_COM_IMPL_CONFIGURATION_SOMEIP_METHOD_INSTANCE_DEPLOYMENT_H diff --git a/score/mw/com/impl/configuration/someip_service_id.cpp b/score/mw/com/impl/configuration/someip_service_id.cpp new file mode 100644 index 000000000..562948914 --- /dev/null +++ b/score/mw/com/impl/configuration/someip_service_id.cpp @@ -0,0 +1,13 @@ +/******************************************************************************** + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "score/mw/com/impl/configuration/someip_service_id.h" diff --git a/score/mw/com/impl/configuration/someip_service_id.h b/score/mw/com/impl/configuration/someip_service_id.h new file mode 100644 index 000000000..f7750e7ef --- /dev/null +++ b/score/mw/com/impl/configuration/someip_service_id.h @@ -0,0 +1,25 @@ +/******************************************************************************** + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#ifndef SCORE_MW_COM_IMPL_CONFIGURATION_SOMEIP_SERVICE_ID_H +#define SCORE_MW_COM_IMPL_CONFIGURATION_SOMEIP_SERVICE_ID_H + +#include + +namespace score::mw::com::impl +{ + +using SomeIpServiceId = std::uint16_t; + +} // namespace score::mw::com::impl + +#endif // SCORE_MW_COM_IMPL_CONFIGURATION_SOMEIP_SERVICE_ID_H diff --git a/score/mw/com/impl/configuration/someip_service_instance_deployment.cpp b/score/mw/com/impl/configuration/someip_service_instance_deployment.cpp index bedafc943..e7275f273 100644 --- a/score/mw/com/impl/configuration/someip_service_instance_deployment.cpp +++ b/score/mw/com/impl/configuration/someip_service_instance_deployment.cpp @@ -32,6 +32,7 @@ constexpr auto kSerializationVersionKeySerInstDepl = "serializationVersion"; constexpr auto kInstanceIdKeySerInstDepl = "instanceId"; constexpr auto kEventsKeySerInstDepl = "events"; constexpr auto kFieldsKeySerInstDepl = "fields"; +constexpr auto kMethodsKeySerInstDepl = "methods"; } // namespace @@ -71,7 +72,8 @@ SomeIpServiceInstanceDeployment::SomeIpServiceInstanceDeployment(const score::js : SomeIpServiceInstanceDeployment{ {}, ConvertJsonToServiceElementMap(json_object, kEventsKeySerInstDepl), - ConvertJsonToServiceElementMap(json_object, kFieldsKeySerInstDepl)} + ConvertJsonToServiceElementMap(json_object, kFieldsKeySerInstDepl), + ConvertJsonToServiceElementMap(json_object, kMethodsKeySerInstDepl)} { const auto instance_id_it = json_object.find(kInstanceIdKeySerInstDepl); if (instance_id_it != json_object.end()) @@ -99,6 +101,7 @@ score::json::Object SomeIpServiceInstanceDeployment::Serialize() const noexcept json_object[kEventsKeySerInstDepl] = ConvertServiceElementMapToJson(events_); json_object[kFieldsKeySerInstDepl] = ConvertServiceElementMapToJson(fields_); + json_object[kMethodsKeySerInstDepl] = ConvertServiceElementMapToJson(methods_); return json_object; } diff --git a/score/mw/com/impl/configuration/someip_service_instance_deployment.h b/score/mw/com/impl/configuration/someip_service_instance_deployment.h index e9aed6820..78f45108f 100644 --- a/score/mw/com/impl/configuration/someip_service_instance_deployment.h +++ b/score/mw/com/impl/configuration/someip_service_instance_deployment.h @@ -15,6 +15,7 @@ #include "score/mw/com/impl/configuration/someip_event_instance_deployment.h" #include "score/mw/com/impl/configuration/someip_field_instance_deployment.h" +#include "score/mw/com/impl/configuration/someip_method_instance_deployment.h" #include "score/mw/com/impl/configuration/someip_service_instance_id.h" #include "score/json/json_parser.h" @@ -34,12 +35,17 @@ class SomeIpServiceInstanceDeployment public: using EventInstanceMapping = std::unordered_map; using FieldInstanceMapping = std::unordered_map; + using MethodInstanceMapping = std::unordered_map; explicit SomeIpServiceInstanceDeployment(const score::json::Object& json_object) noexcept; explicit SomeIpServiceInstanceDeployment(score::cpp::optional instance_id = {}, EventInstanceMapping events = {}, - FieldInstanceMapping fields = {}) - : instance_id_{instance_id}, events_{std::move(events)}, fields_{std::move(fields)} + FieldInstanceMapping fields = {}, + MethodInstanceMapping methods = {}) + : instance_id_{instance_id}, + events_{std::move(events)}, + fields_{std::move(fields)}, + methods_{std::move(methods)} { } @@ -54,6 +60,8 @@ class SomeIpServiceInstanceDeployment EventInstanceMapping events_; // key = event name // coverity[autosar_cpp14_m11_0_1_violation] FieldInstanceMapping fields_; // key = field name + // coverity[autosar_cpp14_m11_0_1_violation] + MethodInstanceMapping methods_; // key = method name score::json::Object Serialize() const noexcept; }; diff --git a/score/mw/com/impl/configuration/someip_service_type_deployment.cpp b/score/mw/com/impl/configuration/someip_service_type_deployment.cpp new file mode 100644 index 000000000..8bdec6920 --- /dev/null +++ b/score/mw/com/impl/configuration/someip_service_type_deployment.cpp @@ -0,0 +1,13 @@ +/******************************************************************************** + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "score/mw/com/impl/configuration/someip_service_type_deployment.h" diff --git a/score/mw/com/impl/configuration/someip_service_type_deployment.h b/score/mw/com/impl/configuration/someip_service_type_deployment.h new file mode 100644 index 000000000..4faa87c11 --- /dev/null +++ b/score/mw/com/impl/configuration/someip_service_type_deployment.h @@ -0,0 +1,39 @@ +/******************************************************************************** + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#ifndef SCORE_MW_COM_IMPL_CONFIGURATION_SOMEIP_SERVICE_TYPE_DEPLOYMENT_H +#define SCORE_MW_COM_IMPL_CONFIGURATION_SOMEIP_SERVICE_TYPE_DEPLOYMENT_H + +#include "score/mw/com/impl/configuration/binding_service_type_deployment.h" +#include "score/mw/com/impl/configuration/someip_event_id.h" +#include "score/mw/com/impl/configuration/someip_field_id.h" +#include "score/mw/com/impl/configuration/someip_method_id.h" +#include "score/mw/com/impl/configuration/someip_service_id.h" + +namespace score::mw::com::impl +{ + +// NOLINTBEGIN +// A distinct struct (not a type alias) is required so that SomeIpServiceTypeDeployment and LolaServiceTypeDeployment +// are different types in std::variant, even though both instantiate BindingServiceTypeDeployment with the same +// underlying integer types (all are uint16_t aliases). +struct SomeIpServiceTypeDeployment + : BindingServiceTypeDeployment +{ + using BindingServiceTypeDeployment:: + BindingServiceTypeDeployment; +}; +// NOLINTEND + +} // namespace score::mw::com::impl + +#endif // SCORE_MW_COM_IMPL_CONFIGURATION_SOMEIP_SERVICE_TYPE_DEPLOYMENT_H 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 7a2d28660..d64632e42 100644 --- a/score/mw/com/impl/configuration/test/configuration_test_resources.cpp +++ b/score/mw/com/impl/configuration/test/configuration_test_resources.cpp @@ -111,6 +111,18 @@ LolaServiceInstanceDeployment MakeLolaServiceInstanceDeployment( return unit; } +SomeIpMethodInstanceDeployment MakeDefaultSomeIpMethodInstanceDeployment() noexcept +{ + return SomeIpMethodInstanceDeployment{std::nullopt}; +} + +SomeIpMethodInstanceDeployment MakeSomeIpMethodInstanceDeployment( + const std::optional queue_size) noexcept +{ + const SomeIpMethodInstanceDeployment unit{queue_size}; + return unit; +} + SomeIpServiceInstanceDeployment MakeSomeIpServiceInstanceDeployment( const score::cpp::optional instance_id) noexcept { @@ -120,13 +132,19 @@ SomeIpServiceInstanceDeployment MakeSomeIpServiceInstanceDeployment( const SomeIpFieldInstanceDeployment field_instance_deployment_1{}; const SomeIpFieldInstanceDeployment field_instance_deployment_2{}; + const SomeIpMethodInstanceDeployment method_instance_deployment_1{MakeSomeIpMethodInstanceDeployment(20U)}; + const SomeIpMethodInstanceDeployment method_instance_deployment_2{MakeSomeIpMethodInstanceDeployment(21U)}; + const SomeIpServiceInstanceDeployment::EventInstanceMapping events{{kDummyEventName1, event_instance_deployment_1}, {kDummyEventName2, event_instance_deployment_2}}; const SomeIpServiceInstanceDeployment::FieldInstanceMapping fields{{kDummyFieldName1, field_instance_deployment_1}, {kDummyFieldName2, field_instance_deployment_2}}; - return SomeIpServiceInstanceDeployment(instance_id, events, fields); + const SomeIpServiceInstanceDeployment::MethodInstanceMapping methods{ + {kDummyMethodName1, method_instance_deployment_1}, {kDummyMethodName2, method_instance_deployment_2}}; + + return SomeIpServiceInstanceDeployment(instance_id, events, fields, methods); } LolaServiceTypeDeployment MakeLolaServiceTypeDeployment(const std::uint16_t service_id) noexcept @@ -193,6 +211,13 @@ void ConfigurationStructsFixture::ExpectSomeIpFieldInstanceDeploymentObjectsEqua { } +void ConfigurationStructsFixture::ExpectSomeIpMethodInstanceDeploymentObjectsEqual( + const SomeIpMethodInstanceDeployment& lhs, + const SomeIpMethodInstanceDeployment& rhs) const noexcept +{ + EXPECT_EQ(lhs.queue_size_, rhs.queue_size_); +} + void ConfigurationStructsFixture::ExpectLolaServiceInstanceDeploymentObjectsEqual( const LolaServiceInstanceDeployment& lhs, const LolaServiceInstanceDeployment& rhs) const noexcept @@ -278,6 +303,14 @@ void ConfigurationStructsFixture::ExpectSomeIpServiceInstanceDeploymentObjectsEq ASSERT_NE(rhs_it, rhs.fields_.end()); ExpectSomeIpFieldInstanceDeploymentObjectsEqual(lhs_it.second, rhs_it->second); } + + ASSERT_EQ(lhs.methods_.size(), rhs.methods_.size()); + for (const auto& lhs_it : lhs.methods_) + { + auto rhs_it = rhs.methods_.find(lhs_it.first); + ASSERT_NE(rhs_it, rhs.methods_.end()); + ExpectSomeIpMethodInstanceDeploymentObjectsEqual(lhs_it.second, rhs_it->second); + } } void ConfigurationStructsFixture::ExpectServiceInstanceDeploymentObjectsEqual( 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 a85cf8522..cfeb41e40 100644 --- a/score/mw/com/impl/configuration/test/configuration_test_resources.h +++ b/score/mw/com/impl/configuration/test/configuration_test_resources.h @@ -28,6 +28,7 @@ #include "score/mw/com/impl/configuration/service_type_deployment.h" #include "score/mw/com/impl/configuration/someip_event_instance_deployment.h" #include "score/mw/com/impl/configuration/someip_field_instance_deployment.h" +#include "score/mw/com/impl/configuration/someip_method_instance_deployment.h" #include "score/mw/com/impl/configuration/someip_service_instance_id.h" #include @@ -68,6 +69,11 @@ LolaServiceInstanceDeployment MakeLolaServiceInstanceDeployment( const score::cpp::optional control_asil_b_memory_size = 3000U, const score::cpp::optional control_qm_memory_size = 4000U) noexcept; +SomeIpMethodInstanceDeployment MakeDefaultSomeIpMethodInstanceDeployment() noexcept; + +SomeIpMethodInstanceDeployment MakeSomeIpMethodInstanceDeployment( + const std::optional queue_size = 10U) noexcept; + SomeIpServiceInstanceDeployment MakeSomeIpServiceInstanceDeployment( const score::cpp::optional instance_id = 22U) noexcept; @@ -91,6 +97,9 @@ class ConfigurationStructsFixture : public ::testing::Test void ExpectSomeIpFieldInstanceDeploymentObjectsEqual(const SomeIpFieldInstanceDeployment& lhs, const SomeIpFieldInstanceDeployment& rhs) const noexcept; + void ExpectSomeIpMethodInstanceDeploymentObjectsEqual(const SomeIpMethodInstanceDeployment& lhs, + const SomeIpMethodInstanceDeployment& rhs) const noexcept; + void ExpectLolaServiceInstanceDeploymentObjectsEqual(const LolaServiceInstanceDeployment& lhs, const LolaServiceInstanceDeployment& rhs) const noexcept;