-
Notifications
You must be signed in to change notification settings - Fork 85
Config validation extraction #615
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
becf279
dcb25f1
aaac7d6
ea0b304
6de4790
bd1d4bd
521fc16
ee8654b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,164 @@ | ||
| /******************************************************************************** | ||
| * Copyright (c) 2026 Contributors to the Eclipse Foundation | ||
| * | ||
| * See the NOTICE file(s) distributed with this work for additional | ||
| * information regarding copyright ownership. | ||
| * | ||
| * This program and the accompanying materials are made available under the | ||
| * terms of the Apache License Version 2.0 which is available at | ||
| * https://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| ********************************************************************************/ | ||
| #include "score/mw/com/impl/configuration/config_validate.h" | ||
|
|
||
| #include "score/mw/com/impl/configuration/lola_event_id.h" | ||
| #include "score/mw/com/impl/configuration/lola_field_id.h" | ||
| #include "score/mw/com/impl/configuration/lola_method_id.h" | ||
| #include "score/mw/com/impl/configuration/lola_service_instance_deployment.h" | ||
|
|
||
| #include <set> | ||
| #include <type_traits> | ||
| #include <variant> | ||
|
|
||
| namespace score::mw::com::impl::configuration | ||
| { | ||
|
|
||
| void ValidateServiceTypeHasElements(const LolaServiceTypeDeployment& deployment) | ||
| { | ||
| if (deployment.events_.empty() && deployment.fields_.empty() && deployment.methods_.empty()) | ||
| { | ||
| score::mw::log::LogFatal("lola") << "Configuration should contain at least one event, field, or method."; | ||
| SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(false); | ||
| } | ||
| } | ||
|
|
||
| void ValidateUniqueServiceElementIds(const LolaServiceTypeDeployment& deployment) | ||
| { | ||
| static_assert(std::is_same<LolaEventId, LolaFieldId>::value, | ||
| "EventId and FieldId should have the same underlying type."); | ||
| static_assert(std::is_same<LolaEventId, LolaMethodId>::value, | ||
| "EventId and MethodId should have the same underlying type."); | ||
| std::set<LolaEventId> ids{}; | ||
|
|
||
| for (const auto& event : deployment.events_) | ||
| { | ||
| if (!ids.insert(event.second).second) | ||
| { | ||
| score::mw::log::LogFatal("lola") << "Configuration cannot contain duplicate eventId, fieldId, or methodId."; | ||
| SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(false); | ||
| } | ||
| } | ||
|
|
||
| for (const auto& field : deployment.fields_) | ||
| { | ||
| if (!ids.insert(field.second).second) | ||
| { | ||
| score::mw::log::LogFatal("lola") << "Configuration cannot contain duplicate eventId, fieldId, or methodId."; | ||
| SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(false); | ||
| } | ||
| } | ||
|
|
||
| for (const auto& method : deployment.methods_) | ||
| { | ||
| if (!ids.insert(method.second).second) | ||
| { | ||
| score::mw::log::LogFatal("lola") << "Configuration cannot contain duplicate eventId, fieldId, or methodId."; | ||
| SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(false); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| InstanceSpecifier CreateValidInstanceSpecifier(std::string instance_specifier_name) | ||
| { | ||
| auto result = InstanceSpecifier::Create(std::move(instance_specifier_name)); | ||
| if (!result.has_value()) | ||
| { | ||
| score::mw::log::LogFatal("lola") << "Invalid InstanceSpecifier."; | ||
| SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(false); | ||
| } | ||
| return result.value(); | ||
| } | ||
|
|
||
| void CrosscheckAsilLevels(const Configuration& config) | ||
| { | ||
| for (const auto& service_instance : config.GetServiceInstances()) | ||
| { | ||
| if ((service_instance.second.asilLevel_ == QualityType::kASIL_B) && | ||
| (config.GetGlobalConfiguration().GetProcessAsilLevel() != QualityType::kASIL_B)) | ||
| { | ||
| ::score::mw::log::LogFatal("lola") | ||
| << "Service instance has a higher ASIL than the process. This is invalid, terminating"; | ||
| SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(false); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // coverity[autosar_cpp14_a15_5_3_violation] | ||
| void CrosscheckServiceInstancesToTypes(const Configuration& config) | ||
| { | ||
| for (const auto& service_instance : config.GetServiceInstances()) | ||
| { | ||
| const auto foundServiceType = config.GetServiceTypes().find(service_instance.second.service_); | ||
| if (foundServiceType == config.GetServiceTypes().cend()) | ||
| { | ||
| ::score::mw::log::LogFatal("lola") | ||
| << "Service instance " << service_instance.first << "refers to a service type (" | ||
| << service_instance.second.service_.ToString() | ||
| << "), which is not configured. This is invalid, terminating"; | ||
| SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(false); | ||
| } | ||
| // 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<LolaServiceInstanceDeployment>(service_instance.second.bindingInfo_)) | ||
| { | ||
| // LCOV_EXCL_BR_STOP | ||
| // LCOV_EXCL_START defensive programming | ||
| ::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<LolaServiceTypeDeployment>(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); | ||
| } | ||
| const auto& serviceInstanceDeployment = | ||
| std::get<LolaServiceInstanceDeployment>(service_instance.second.bindingInfo_); | ||
| for (const auto& eventInstanceElement : serviceInstanceDeployment.events_) | ||
| { | ||
| const auto& serviceTypeDeployment = | ||
| std::get<LolaServiceTypeDeployment>(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<LolaServiceTypeDeployment>(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); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| } // namespace score::mw::com::impl::configuration |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| /******************************************************************************** | ||
| * Copyright (c) 2026 Contributors to the Eclipse Foundation | ||
| * | ||
| * See the NOTICE file(s) distributed with this work for additional | ||
| * information regarding copyright ownership. | ||
| * | ||
| * This program and the accompanying materials are made available under the | ||
| * terms of the Apache License Version 2.0 which is available at | ||
| * https://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| ********************************************************************************/ | ||
| #ifndef SCORE_MW_COM_IMPL_CONFIGURATION_CONFIG_VALIDATE_H | ||
| #define SCORE_MW_COM_IMPL_CONFIGURATION_CONFIG_VALIDATE_H | ||
|
|
||
| #include "score/mw/com/impl/configuration/configuration.h" | ||
| #include "score/mw/com/impl/configuration/lola_service_type_deployment.h" | ||
| #include "score/mw/com/impl/instance_specifier.h" | ||
|
|
||
| #include "score/mw/log/logging.h" | ||
|
|
||
| #include <score/assert.hpp> | ||
|
|
||
| #include <string> | ||
| #include <string_view> | ||
| #include <utility> | ||
| #include <vector> | ||
|
|
||
| namespace score::mw::com::impl::configuration | ||
| { | ||
|
|
||
| template <typename Map, typename Key, typename Value> | ||
| void EmplaceOrFatal(Map& map, Key&& key, Value&& value, std::string_view element_description) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function is local to This statement is also true for all other extractions that are done in later commits.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function will mostly be also used for the flatbuffer parser, that's why I put it in the common config_validate.h If you suggest adding these files directly to the 'configuration_json_parsing_strategy' lib directly instead of making it as a separate common lib 'config_validate' that to be used later with 'configuration_flatbuffer_parsing_strategy' I would see it okay. Or did I missunderstood something? |
||
| { | ||
| const auto result = map.emplace(std::forward<Key>(key), std::forward<Value>(value)); | ||
| if (!result.second) | ||
| { | ||
| score::mw::log::LogFatal("lola") << element_description << " was configured twice."; | ||
| SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(false); | ||
| } | ||
| } | ||
|
|
||
| void ValidateServiceTypeHasElements(const LolaServiceTypeDeployment& deployment); | ||
| void ValidateUniqueServiceElementIds(const LolaServiceTypeDeployment& deployment); | ||
| InstanceSpecifier CreateValidInstanceSpecifier(std::string instance_specifier_name); | ||
|
|
||
| template <typename Container> | ||
| void ValidateSingleDeployment(const Container& deployments, const ServiceIdentifierType& service_identifier) | ||
| { | ||
| if (deployments.size() != 1U) | ||
| { | ||
| score::mw::log::LogFatal("lola") << "More or less then one deployment for " << service_identifier.ToString() | ||
| << ". Multi-Binding support right now not supported"; | ||
| SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(false); | ||
| } | ||
| } | ||
|
|
||
| void CrosscheckAsilLevels(const Configuration& config); | ||
| void CrosscheckServiceInstancesToTypes(const Configuration& config); | ||
|
|
||
| } // namespace score::mw::com::impl::configuration | ||
|
|
||
| #endif // SCORE_MW_COM_IMPL_CONFIGURATION_CONFIG_VALIDATE_H | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its not a bug - its a feature :)
There have been use cases in the past, where an empty service was used. We see no reason why an empty service (e.g. as marker via the service discovery) shall not be allowed.
Can you maybe elaborate a bit, why you think this is a bug?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the original code you can see the in config_parser.cpp the error message description as following:
score::mw::log::LogFatal("lola") << "Configuration should contain at least one event, field, or method.";That's why I considered it as an unintended bug.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we consider it as a feature then we shall remove the check at all. What do you suggest?