From f69d84c3a00430e149a12215426e49c216dc4f35 Mon Sep 17 00:00:00 2001 From: Konrad Breitsprecher Date: Fri, 20 Dec 2024 18:05:23 +0100 Subject: [PATCH 1/2] dev: public API to get parameters from a participant dev: Hourglass storage for parameter values; integration tests fixup: Exclude unused demo; new license dev: User buffer for particiant parameters dev: GetParameter API user-provided buffer --- SilKit/IntegrationTests/CMakeLists.txt | 4 ++ .../IntegrationTests/Hourglass/MockCapi.cpp | 9 +++ .../IntegrationTests/Hourglass/MockCapi.hpp | 4 ++ .../IntegrationTests/ITest_GetParameter.cpp | 72 +++++++++++++++++++ SilKit/include/silkit/capi/Parameters.h | 29 ++++++++ SilKit/include/silkit/capi/Participant.h | 23 ++++++ SilKit/include/silkit/capi/SilKit.h | 1 + .../impl/participant/ParameterProvider.hpp | 66 +++++++++++++++++ .../detail/impl/participant/Participant.hpp | 13 ++++ .../silkit/participant/IParticipant.hpp | 5 ++ .../include/silkit/participant/parameters.hpp | 23 ++++++ SilKit/source/capi/CMakeLists.txt | 1 + SilKit/source/capi/CapiParticipant.cpp | 36 +++++++++- SilKit/source/capi/Test_CapiGetParameter.cpp | 60 ++++++++++++++++ .../core/internal/IParticipantInternal.hpp | 3 + .../core/mock/participant/MockParticipant.hpp | 5 ++ .../source/core/participant/Participant.hpp | 4 ++ .../core/participant/Participant_impl.hpp | 19 +++++ 18 files changed, 376 insertions(+), 1 deletion(-) create mode 100644 SilKit/IntegrationTests/ITest_GetParameter.cpp create mode 100644 SilKit/include/silkit/capi/Parameters.h create mode 100644 SilKit/include/silkit/detail/impl/participant/ParameterProvider.hpp create mode 100644 SilKit/include/silkit/participant/parameters.hpp create mode 100644 SilKit/source/capi/Test_CapiGetParameter.cpp diff --git a/SilKit/IntegrationTests/CMakeLists.txt b/SilKit/IntegrationTests/CMakeLists.txt index 634a56dce..84cea7e5a 100644 --- a/SilKit/IntegrationTests/CMakeLists.txt +++ b/SilKit/IntegrationTests/CMakeLists.txt @@ -114,6 +114,10 @@ add_silkit_test_to_executable(SilKitIntegrationTests SOURCES ITest_SimTask.cpp ) +add_silkit_test_to_executable(SilKitIntegrationTests + SOURCES ITest_GetParameter.cpp +) + add_silkit_test_to_executable(SilKitFunctionalTests SOURCES FTest_WallClockCoupling.cpp ) diff --git a/SilKit/IntegrationTests/Hourglass/MockCapi.cpp b/SilKit/IntegrationTests/Hourglass/MockCapi.cpp index 79237be50..c8940b3d1 100644 --- a/SilKit/IntegrationTests/Hourglass/MockCapi.cpp +++ b/SilKit/IntegrationTests/Hourglass/MockCapi.cpp @@ -769,6 +769,15 @@ extern "C" return globalCapi->SilKit_Participant_GetLogger(outLogger, participant); } + SilKit_ReturnCode SilKitCALL SilKit_Participant_GetParameter(char* outParameterValue, + size_t* inOutParameterValueSize, + SilKit_Parameter parameter, + SilKit_Participant* participant) + { + return globalCapi->SilKit_Participant_GetParameter(outParameterValue, inOutParameterValueSize, parameter, + participant); + } + // ParticipantConfiguration SilKit_ReturnCode SilKitCALL SilKit_ParticipantConfiguration_FromString( diff --git a/SilKit/IntegrationTests/Hourglass/MockCapi.hpp b/SilKit/IntegrationTests/Hourglass/MockCapi.hpp index 5242be8a4..cf69cc542 100644 --- a/SilKit/IntegrationTests/Hourglass/MockCapi.hpp +++ b/SilKit/IntegrationTests/Hourglass/MockCapi.hpp @@ -406,6 +406,10 @@ class MockCapi MOCK_METHOD(SilKit_ReturnCode, SilKit_Participant_GetLogger, (SilKit_Logger * *outLogger, SilKit_Participant* participant)); + + MOCK_METHOD(SilKit_ReturnCode, SilKit_Participant_GetParameter, + (char* outParameterValue, size_t* outParameterValueSize, SilKit_Parameter parameter, + SilKit_Participant* participant)); // ParticipantConfiguration diff --git a/SilKit/IntegrationTests/ITest_GetParameter.cpp b/SilKit/IntegrationTests/ITest_GetParameter.cpp new file mode 100644 index 000000000..23b8b119d --- /dev/null +++ b/SilKit/IntegrationTests/ITest_GetParameter.cpp @@ -0,0 +1,72 @@ +// SPDX-FileCopyrightText: 2023 Vector Informatik GmbH +// +// SPDX-License-Identifier: MIT + +#include +#include + +#include "gtest/gtest.h" +#include "silkit/vendor/CreateSilKitRegistry.hpp" +#include "silkit/SilKit.hpp" + +namespace { + +struct ITest_GetParameter : public testing::Test +{ + + void checkGetParameterValues(SilKit::IParticipant* participant, std::unordered_map expectedParameters) + { + for (auto it : expectedParameters) + { + std::string parameterValue = participant->GetParameter(it.first); + std::string expectedValue = it.second; + EXPECT_EQ(expectedValue, parameterValue); + } + } + + const std::string _registryUriAnyPort = "silkit://127.0.0.1:0"; +}; + +// Check that GetParameter return the values set via api +TEST_F(ITest_GetParameter, get_parameter_set_by_api) +{ + const std::string participantNameByApi = "P1"; + + auto emptyParticipantConfig = SilKit::Config::ParticipantConfigurationFromString(""); + + auto registry = SilKit::Vendor::Vector::CreateSilKitRegistry(emptyParticipantConfig); + auto registryUriByApi = registry->StartListening(_registryUriAnyPort); + + auto participant = SilKit::CreateParticipant(emptyParticipantConfig, participantNameByApi, registryUriByApi); + + checkGetParameterValues(participant.get(), {{SilKit::Parameter::ParticipantName, participantNameByApi}, + {SilKit::Parameter::RegistryUri, registryUriByApi}}); +} + +// Config values take precedence over api values +// Check that GetParameter actually return the config values if both are set +TEST_F(ITest_GetParameter, get_parameter_set_by_config) +{ + const std::string participantNameByApi = "P2"; + const std::string registryUriByApi = "silkit://127.0.0.42:0"; + + const std::string participantNameByConfig = "P1"; + + auto emptyParticipantConfig = SilKit::Config::ParticipantConfigurationFromString(""); + + auto registry = SilKit::Vendor::Vector::CreateSilKitRegistry(emptyParticipantConfig); + auto registryUriByConfig = registry->StartListening(_registryUriAnyPort); + + std::ostringstream ss; + ss << R"({ "ParticipantName": ")" << participantNameByConfig << R"(", "Middleware": { "RegistryUri": ")" + << registryUriByConfig << R"(" }})"; + auto participantConfig = SilKit::Config::ParticipantConfigurationFromString(ss.str()); + + auto participant = SilKit::CreateParticipant(participantConfig, participantNameByApi, registryUriByApi); + + checkGetParameterValues(participant.get(), {{SilKit::Parameter::ParticipantName, participantNameByConfig}, + {SilKit::Parameter::RegistryUri, registryUriByConfig}}); + +} + +} //end namespace diff --git a/SilKit/include/silkit/capi/Parameters.h b/SilKit/include/silkit/capi/Parameters.h new file mode 100644 index 000000000..06063b504 --- /dev/null +++ b/SilKit/include/silkit/capi/Parameters.h @@ -0,0 +1,29 @@ +// SPDX-FileCopyrightText: 2024 Vector Informatik GmbH +// +// SPDX-License-Identifier: MIT + +#pragma once +#include +#include "SilKitMacros.h" + +#pragma pack(push) +#pragma pack(8) + +SILKIT_BEGIN_DECLS + +/*! Internal parameter provider. */ +typedef struct SilKit_ParamterProvider SilKit_ParamterProvider; + +/*! A parameter set by an API call and/or the participant configuration. */ +typedef int16_t SilKit_Parameter; + +/*! An undefined parameter */ +#define SilKit_Parameter_Undefined ((SilKit_Parameter)0) +/*! The name of the participant */ +#define SilKit_Parameter_ParticipantName ((SilKit_Parameter)1) +/*! The registry URI */ +#define SilKit_Parameter_ReistryUri ((SilKit_Parameter)2) + +SILKIT_END_DECLS + +#pragma pack(pop) diff --git a/SilKit/include/silkit/capi/Participant.h b/SilKit/include/silkit/capi/Participant.h index 31283c542..d7b5f9974 100644 --- a/SilKit/include/silkit/capi/Participant.h +++ b/SilKit/include/silkit/capi/Participant.h @@ -8,6 +8,7 @@ #include "silkit/capi/SilKitMacros.h" #include "silkit/capi/Types.h" #include "silkit/capi/Logger.h" +#include "silkit/capi/Parameters.h" #pragma pack(push) #pragma pack(8) @@ -63,6 +64,28 @@ SilKitAPI SilKit_ReturnCode SilKitCALL SilKit_Participant_GetLogger(SilKit_Logge typedef SilKit_ReturnCode(SilKitFPTR* SilKit_Participant_GetLogger_t)(SilKit_Logger** outLogger, SilKit_Participant* participant); + +/*! \brief Retrieve a parameter from a participant. + * + * \param outParameterValue A buffer to copy the null-terminated parameter value to. + Passing a nullptr is valid and indicates a size-check via inOutParameterValueSize to allocate the buffer. + * \param inOutParameterValueSize The size of the parameter including null-termination. + * \param parameter The parameter to get. + * \param participant The participant to get the parameter from. + * + * Returns the current value of the given parameter. + * Useful for parameters that are passed to the participant via the API and the participant configuration. + */ +SilKitAPI SilKit_ReturnCode SilKitCALL SilKit_Participant_GetParameter(char* outParameterValue, + size_t* inOutParameterValueSize, + SilKit_Parameter parameter, + SilKit_Participant* participant); + +typedef SilKit_ReturnCode(SilKitFPTR* SilKit_Participant_GetParameter_t)(char* outParameterValue, + size_t* inOutParameterValueSize, + SilKit_Parameter parameter, + SilKit_Participant* participant); + SILKIT_END_DECLS #pragma pack(pop) diff --git a/SilKit/include/silkit/capi/SilKit.h b/SilKit/include/silkit/capi/SilKit.h index a210cd1bd..e7a980d1e 100644 --- a/SilKit/include/silkit/capi/SilKit.h +++ b/SilKit/include/silkit/capi/SilKit.h @@ -20,6 +20,7 @@ #include "silkit/capi/Version.h" #include "silkit/capi/NetworkSimulator.h" #include "silkit/capi/EventProducer.h" +#include "silkit/capi/Parameters.h" SILKIT_BEGIN_DECLS diff --git a/SilKit/include/silkit/detail/impl/participant/ParameterProvider.hpp b/SilKit/include/silkit/detail/impl/participant/ParameterProvider.hpp new file mode 100644 index 000000000..c3e07e061 --- /dev/null +++ b/SilKit/include/silkit/detail/impl/participant/ParameterProvider.hpp @@ -0,0 +1,66 @@ +// SPDX-FileCopyrightText: 2024 Vector Informatik GmbH +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include "silkit/capi/Parameters.h" + +namespace SilKit { +DETAIL_SILKIT_DETAIL_VN_NAMESPACE_BEGIN +namespace Impl { + +class ParameterProvider +{ +public: + inline ParameterProvider(); + + inline ~ParameterProvider() = default; + + inline auto GetParameter(SilKit_Participant* participant, Parameter parameter) -> std::string; + +}; + +} // namespace Impl +DETAIL_SILKIT_DETAIL_VN_NAMESPACE_CLOSE +} // namespace SilKit + + +// ================================================================================ +// Inline Implementations +// ================================================================================ + +#include "silkit/detail/impl/ThrowOnError.hpp" + +namespace SilKit { +DETAIL_SILKIT_DETAIL_VN_NAMESPACE_BEGIN +namespace Impl { + +ParameterProvider::ParameterProvider() +{ +} + +auto ParameterProvider::GetParameter(SilKit_Participant* participant, Parameter parameter) -> std::string +{ + std::vector buffer; + size_t size = 0; + SilKit_Parameter cParameter = static_cast(parameter); + { + const auto returnCode = SilKit_Participant_GetParameter(nullptr, &size, cParameter, participant); + ThrowOnError(returnCode); + } + while (size > buffer.size()) + { + buffer.resize(size); + const auto returnCode = SilKit_Participant_GetParameter(buffer.data(), &size, cParameter, participant); + ThrowOnError(returnCode); + } + buffer.resize(size); + + return std::string{buffer.data()}; +} + +} // namespace Impl +DETAIL_SILKIT_DETAIL_VN_NAMESPACE_CLOSE +} // namespace SilKit diff --git a/SilKit/include/silkit/detail/impl/participant/Participant.hpp b/SilKit/include/silkit/detail/impl/participant/Participant.hpp index a3ebada3c..869ec89e8 100644 --- a/SilKit/include/silkit/detail/impl/participant/Participant.hpp +++ b/SilKit/include/silkit/detail/impl/participant/Participant.hpp @@ -36,6 +36,8 @@ #include "silkit/detail/impl/netsim/NetworkSimulator.hpp" +#include "silkit/detail/impl/participant/ParameterProvider.hpp" + namespace SilKit { DETAIL_SILKIT_DETAIL_VN_NAMESPACE_BEGIN namespace Impl { @@ -83,6 +85,8 @@ class Participant : public SilKit::IParticipant inline auto GetLogger() -> SilKit::Services::Logging::ILogger* override; + inline auto GetParameter(SilKit::Parameter parameter) -> std::string override; + inline auto ExperimentalCreateNetworkSimulator() -> SilKit::Experimental::NetworkSimulation::INetworkSimulator*; inline auto ExperimentalCreateSystemController() @@ -124,6 +128,8 @@ class Participant : public SilKit::IParticipant std::unique_ptr _logger; std::unique_ptr _networkSimulator; + + std::unique_ptr _parameterProvider; }; } // namespace Impl @@ -143,6 +149,7 @@ Participant::Participant(SilKit_Participant* participant) : _participant{participant} { _logger = std::make_unique(_participant); + _parameterProvider = std::make_unique(); } Participant::~Participant() @@ -224,6 +231,12 @@ auto Participant::GetLogger() -> SilKit::Services::Logging::ILogger* return _logger.get(); } + +auto Participant::GetParameter(SilKit::Parameter parameter) -> std::string +{ + return _parameterProvider->GetParameter(_participant, parameter); +} + auto Participant::ExperimentalCreateSystemController() -> SilKit::Experimental::Services::Orchestration::ISystemController* { diff --git a/SilKit/include/silkit/participant/IParticipant.hpp b/SilKit/include/silkit/participant/IParticipant.hpp index c1e9516c7..3575c3a1e 100644 --- a/SilKit/include/silkit/participant/IParticipant.hpp +++ b/SilKit/include/silkit/participant/IParticipant.hpp @@ -18,6 +18,8 @@ #include "silkit/services/rpc/RpcSpec.hpp" #include "silkit/services/rpc/RpcDatatypes.hpp" +#include "silkit/participant/parameters.hpp" + namespace SilKit { /*! \brief Communication interface to be used by SIL Kit participants @@ -82,6 +84,9 @@ class IParticipant //! \brief Return the ILogger at this SIL Kit participant. virtual auto GetLogger() -> Services::Logging::ILogger* = 0; + + //! \brief Get a parameter set by an API call and/or the participant configuration. + virtual auto GetParameter(SilKit::Parameter parameter) -> std::string = 0; }; } // namespace SilKit diff --git a/SilKit/include/silkit/participant/parameters.hpp b/SilKit/include/silkit/participant/parameters.hpp new file mode 100644 index 000000000..e440c366c --- /dev/null +++ b/SilKit/include/silkit/participant/parameters.hpp @@ -0,0 +1,23 @@ +// SPDX-FileCopyrightText: 2024 Vector Informatik GmbH +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "silkit/capi/Parameters.h" + +namespace SilKit { + +// note: never reuse old numbers! +//! \brief Available parameters to query +enum class Parameter : SilKit_Parameter +{ + //! An undefined parameter + Undefined = SilKit_Parameter_Undefined, + //! The name of the participant + ParticipantName = SilKit_Parameter_ParticipantName, + //! The registry URI + RegistryUri = SilKit_Parameter_ReistryUri, +}; + +} // namespace SilKit diff --git a/SilKit/source/capi/CMakeLists.txt b/SilKit/source/capi/CMakeLists.txt index ca5a1e94b..2d3f5142c 100644 --- a/SilKit/source/capi/CMakeLists.txt +++ b/SilKit/source/capi/CMakeLists.txt @@ -48,4 +48,5 @@ add_silkit_test_to_executable(SilKitUnitTests SOURCES Test_CapiLin.cpp LIBS S_Si add_silkit_test_to_executable(SilKitUnitTests SOURCES Test_CapiSymbols.cpp LIBS S_SilKitImpl) add_silkit_test_to_executable(SilKitUnitTests SOURCES Test_CapiNetSim.cpp LIBS S_SilKitImpl I_SilKit_Core_Mock_Participant) add_silkit_test_to_executable(SilKitUnitTests SOURCES Test_CapiExceptions.cpp LIBS S_SilKitImpl) +add_silkit_test_to_executable(SilKitUnitTests SOURCES Test_CapiGetParameter.cpp LIBS S_SilKitImpl) diff --git a/SilKit/source/capi/CapiParticipant.cpp b/SilKit/source/capi/CapiParticipant.cpp index d5c11e542..2f8357528 100644 --- a/SilKit/source/capi/CapiParticipant.cpp +++ b/SilKit/source/capi/CapiParticipant.cpp @@ -11,6 +11,7 @@ #include "silkit/SilKit.hpp" #include "silkit/services/logging/ILogger.hpp" #include "silkit/services/orchestration/all.hpp" +#include "silkit/participant/parameters.hpp" #include "CapiImpl.hpp" #include "TypeConversion.hpp" @@ -20,7 +21,6 @@ #include #include - SilKit_ReturnCode SilKitCALL SilKit_Participant_Create(SilKit_Participant** outParticipant, SilKit_ParticipantConfiguration* participantConfiguration, const char* participantName, const char* registryUri) @@ -86,6 +86,40 @@ try } CAPI_CATCH_EXCEPTIONS +SilKit_ReturnCode SilKitCALL SilKit_Participant_GetParameter(char* outParameterValue, size_t* inOutParameterValueSize, + SilKit_Parameter parameter, + SilKit_Participant* participant) +try +{ + ASSERT_VALID_OUT_PARAMETER(inOutParameterValueSize); + ASSERT_VALID_POINTER_PARAMETER(participant); + + auto cppParticipant = reinterpret_cast(participant); + auto cppParameter = static_cast(parameter); + auto parameterValue = cppParticipant->GetParameter(cppParameter); + + // outParameterValue == nullptr indicates a size-check only, otherwise copy + if (outParameterValue != nullptr) + { + size_t sizeToCopy; + if (*inOutParameterValueSize >= parameterValue.size() + 1) + { + // Don't copy more than we actually have + sizeToCopy = parameterValue.size(); + } + else + { + // Don't copy more than the given size + sizeToCopy = *inOutParameterValueSize - 1; + } + parameterValue.copy(outParameterValue, sizeToCopy); + outParameterValue[sizeToCopy] = '\0'; + } + *inOutParameterValueSize = parameterValue.size() + 1; + return SilKit_ReturnCode_SUCCESS; +} +CAPI_CATCH_EXCEPTIONS + SilKit_ReturnCode SilKitCALL SilKit_ParticipantConfiguration_FromString( SilKit_ParticipantConfiguration** outParticipantConfiguration, const char* participantConfigurationString) diff --git a/SilKit/source/capi/Test_CapiGetParameter.cpp b/SilKit/source/capi/Test_CapiGetParameter.cpp new file mode 100644 index 000000000..d96dedda6 --- /dev/null +++ b/SilKit/source/capi/Test_CapiGetParameter.cpp @@ -0,0 +1,60 @@ +// SPDX-FileCopyrightText: 2024 Vector Informatik GmbH +// +// SPDX-License-Identifier: MIT +#include "gtest/gtest.h" +#include "gmock/gmock.h" +#include "silkit/capi/SilKit.h" + +#include "MockParticipant.hpp" + +namespace { + +using SilKit::Core::Tests::DummyParticipant; + +class MockParticipant : public SilKit::Core::Tests::DummyParticipant +{ +public: + MOCK_METHOD(std::string, GetParameter, (SilKit::Parameter /*parameter*/), (override)); +}; + +class Test_CapiGetParameter : public testing::Test +{ +public: + MockParticipant mockParticipant; + Test_CapiGetParameter() {} +}; + +TEST_F(Test_CapiGetParameter, getparameter_bad_params) +{ + SilKit_ReturnCode returnCode; + auto cMockParticipant = (SilKit_Participant*)&mockParticipant; + char* parameterValue{nullptr}; + size_t parameterSize; + + returnCode = + SilKit_Participant_GetParameter(nullptr, ¶meterSize, SilKit_Parameter_ParticipantName, cMockParticipant); + EXPECT_EQ(returnCode, SilKit_ReturnCode_SUCCESS); + + returnCode = + SilKit_Participant_GetParameter(parameterValue, nullptr, SilKit_Parameter_ParticipantName, cMockParticipant); + EXPECT_EQ(returnCode, SilKit_ReturnCode_BADPARAMETER); + + returnCode = + SilKit_Participant_GetParameter(parameterValue, ¶meterSize, SilKit_Parameter_ParticipantName, nullptr); + EXPECT_EQ(returnCode, SilKit_ReturnCode_BADPARAMETER); +} + +TEST_F(Test_CapiGetParameter, getparameter_function_mapping) +{ + SilKit_ReturnCode returnCode; + auto cMockParticipant = (SilKit_Participant*)&mockParticipant; + char* parameterValue{nullptr}; + size_t parameterSize; + + EXPECT_CALL(mockParticipant, GetParameter(SilKit::Parameter::ParticipantName)).Times(testing::Exactly(1)); + returnCode = SilKit_Participant_GetParameter(parameterValue, & parameterSize, SilKit_Parameter_ParticipantName, + cMockParticipant); + EXPECT_EQ(returnCode, SilKit_ReturnCode_SUCCESS); +} + +} // namespace diff --git a/SilKit/source/core/internal/IParticipantInternal.hpp b/SilKit/source/core/internal/IParticipantInternal.hpp index 3da426d3d..3a68e0a86 100644 --- a/SilKit/source/core/internal/IParticipantInternal.hpp +++ b/SilKit/source/core/internal/IParticipantInternal.hpp @@ -290,6 +290,9 @@ class IParticipantInternal : public IParticipant //! \brief Return the ILogger at this SIL Kit participant. virtual auto GetLogger() -> Services::Logging::ILogger* = 0; + //! \brief Get a parameter set by an API call and/or the participant configuration. + virtual auto GetParameter(Parameter parameter) -> std::string = 0; + //! \brief Return the LifecycleService at this SIL Kit participant. virtual auto GetLifecycleService() -> Services::Orchestration::ILifecycleService* = 0; diff --git a/SilKit/source/core/mock/participant/MockParticipant.hpp b/SilKit/source/core/mock/participant/MockParticipant.hpp index 611a852e0..24354e4bf 100644 --- a/SilKit/source/core/mock/participant/MockParticipant.hpp +++ b/SilKit/source/core/mock/participant/MockParticipant.hpp @@ -349,6 +349,11 @@ class DummyParticipant : public IParticipantInternal return &logger; } + auto GetParameter(Parameter /*parameter*/) -> std::string override + { + return ""; + } + void RegisterSimulator(Core::ISimulator*, std::string, Experimental::NetworkSimulation::SimulatedNetworkType) override { diff --git a/SilKit/source/core/participant/Participant.hpp b/SilKit/source/core/participant/Participant.hpp index 02b53a8ec..83fce27cd 100644 --- a/SilKit/source/core/participant/Participant.hpp +++ b/SilKit/source/core/participant/Participant.hpp @@ -15,6 +15,7 @@ #include "silkit/services/all.hpp" #include "silkit/services/logging/ILogger.hpp" +#include "silkit/participant/parameters.hpp" #include "ParticipantConfiguration.hpp" #include "ReplayScheduler.hpp" @@ -149,6 +150,9 @@ class Participant : public IParticipantInternal auto GetMetricsManager() -> IMetricsManager* override; auto GetLogger() -> Services::Logging::ILogger* override; + + auto GetParameter(Parameter parameter) -> std::string override; + auto CreateLifecycleService(Services::Orchestration::LifecycleConfiguration startConfiguration) -> Services::Orchestration::ILifecycleService* override; auto GetLifecycleService() -> Services::Orchestration::ILifecycleService* override; diff --git a/SilKit/source/core/participant/Participant_impl.hpp b/SilKit/source/core/participant/Participant_impl.hpp index 1c5bc9056..6ca17bdfe 100644 --- a/SilKit/source/core/participant/Participant_impl.hpp +++ b/SilKit/source/core/participant/Participant_impl.hpp @@ -1048,6 +1048,25 @@ auto Participant::GetLoggerInternal() -> Services::Logging::I return _logger.get(); } +template +auto Participant::GetParameter(Parameter parameter) -> std::string +{ + switch (parameter) + { + case Parameter::ParticipantName: + return GetParticipantName(); + break; + case Parameter::RegistryUri: + return GetRegistryUri(); + break; + case Parameter::Undefined: + break; + } + + throw SilKit::SilKitError("Unknown parameter."); +} + + template void Participant::SendMsg(const IServiceEndpoint* from, const Can::WireCanFrameEvent& msg) { From a44c8942e5f4c157043ec32a123fbed5e5547a09 Mon Sep 17 00:00:00 2001 From: Konrad Breitsprecher Date: Mon, 15 Sep 2025 14:58:52 +0200 Subject: [PATCH 2/2] Return void* and drop internal nul termination --- SilKit/IntegrationTests/Hourglass/MockCapi.cpp | 2 +- SilKit/IntegrationTests/Hourglass/MockCapi.hpp | 2 +- SilKit/include/silkit/capi/Participant.h | 4 ++-- .../detail/impl/participant/ParameterProvider.hpp | 8 +++++++- SilKit/source/capi/CapiParticipant.cpp | 11 +++++------ SilKit/source/capi/Test_CapiGetParameter.cpp | 7 +++++-- 6 files changed, 21 insertions(+), 13 deletions(-) diff --git a/SilKit/IntegrationTests/Hourglass/MockCapi.cpp b/SilKit/IntegrationTests/Hourglass/MockCapi.cpp index c8940b3d1..4c46720f8 100644 --- a/SilKit/IntegrationTests/Hourglass/MockCapi.cpp +++ b/SilKit/IntegrationTests/Hourglass/MockCapi.cpp @@ -769,7 +769,7 @@ extern "C" return globalCapi->SilKit_Participant_GetLogger(outLogger, participant); } - SilKit_ReturnCode SilKitCALL SilKit_Participant_GetParameter(char* outParameterValue, + SilKit_ReturnCode SilKitCALL SilKit_Participant_GetParameter(void* outParameterValue, size_t* inOutParameterValueSize, SilKit_Parameter parameter, SilKit_Participant* participant) diff --git a/SilKit/IntegrationTests/Hourglass/MockCapi.hpp b/SilKit/IntegrationTests/Hourglass/MockCapi.hpp index cf69cc542..42842afa4 100644 --- a/SilKit/IntegrationTests/Hourglass/MockCapi.hpp +++ b/SilKit/IntegrationTests/Hourglass/MockCapi.hpp @@ -408,7 +408,7 @@ class MockCapi (SilKit_Logger * *outLogger, SilKit_Participant* participant)); MOCK_METHOD(SilKit_ReturnCode, SilKit_Participant_GetParameter, - (char* outParameterValue, size_t* outParameterValueSize, SilKit_Parameter parameter, + (void* outParameterValue, size_t* outParameterValueSize, SilKit_Parameter parameter, SilKit_Participant* participant)); // ParticipantConfiguration diff --git a/SilKit/include/silkit/capi/Participant.h b/SilKit/include/silkit/capi/Participant.h index d7b5f9974..99e91ed23 100644 --- a/SilKit/include/silkit/capi/Participant.h +++ b/SilKit/include/silkit/capi/Participant.h @@ -76,12 +76,12 @@ typedef SilKit_ReturnCode(SilKitFPTR* SilKit_Participant_GetLogger_t)(SilKit_Log * Returns the current value of the given parameter. * Useful for parameters that are passed to the participant via the API and the participant configuration. */ -SilKitAPI SilKit_ReturnCode SilKitCALL SilKit_Participant_GetParameter(char* outParameterValue, +SilKitAPI SilKit_ReturnCode SilKitCALL SilKit_Participant_GetParameter(void* outParameterValue, size_t* inOutParameterValueSize, SilKit_Parameter parameter, SilKit_Participant* participant); -typedef SilKit_ReturnCode(SilKitFPTR* SilKit_Participant_GetParameter_t)(char* outParameterValue, +typedef SilKit_ReturnCode(SilKitFPTR* SilKit_Participant_GetParameter_t)(void* outParameterValue, size_t* inOutParameterValueSize, SilKit_Parameter parameter, SilKit_Participant* participant); diff --git a/SilKit/include/silkit/detail/impl/participant/ParameterProvider.hpp b/SilKit/include/silkit/detail/impl/participant/ParameterProvider.hpp index c3e07e061..8b2a8f52a 100644 --- a/SilKit/include/silkit/detail/impl/participant/ParameterProvider.hpp +++ b/SilKit/include/silkit/detail/impl/participant/ParameterProvider.hpp @@ -46,17 +46,23 @@ auto ParameterProvider::GetParameter(SilKit_Participant* participant, Parameter std::vector buffer; size_t size = 0; SilKit_Parameter cParameter = static_cast(parameter); + + // Query the size by passing nullptr for the outParameterValue { const auto returnCode = SilKit_Participant_GetParameter(nullptr, &size, cParameter, participant); ThrowOnError(returnCode); } + + // Loop as the size might changed intermediately while (size > buffer.size()) { buffer.resize(size); const auto returnCode = SilKit_Participant_GetParameter(buffer.data(), &size, cParameter, participant); ThrowOnError(returnCode); } - buffer.resize(size); + + // Value-initialized to nul + buffer.resize(size + 1); return std::string{buffer.data()}; } diff --git a/SilKit/source/capi/CapiParticipant.cpp b/SilKit/source/capi/CapiParticipant.cpp index 2f8357528..3e769e9db 100644 --- a/SilKit/source/capi/CapiParticipant.cpp +++ b/SilKit/source/capi/CapiParticipant.cpp @@ -86,7 +86,7 @@ try } CAPI_CATCH_EXCEPTIONS -SilKit_ReturnCode SilKitCALL SilKit_Participant_GetParameter(char* outParameterValue, size_t* inOutParameterValueSize, +SilKit_ReturnCode SilKitCALL SilKit_Participant_GetParameter(void* outParameterValue, size_t* inOutParameterValueSize, SilKit_Parameter parameter, SilKit_Participant* participant) try @@ -102,7 +102,7 @@ try if (outParameterValue != nullptr) { size_t sizeToCopy; - if (*inOutParameterValueSize >= parameterValue.size() + 1) + if (*inOutParameterValueSize > parameterValue.size()) { // Don't copy more than we actually have sizeToCopy = parameterValue.size(); @@ -110,12 +110,11 @@ try else { // Don't copy more than the given size - sizeToCopy = *inOutParameterValueSize - 1; + sizeToCopy = *inOutParameterValueSize; } - parameterValue.copy(outParameterValue, sizeToCopy); - outParameterValue[sizeToCopy] = '\0'; + parameterValue.copy(static_cast(outParameterValue), sizeToCopy); } - *inOutParameterValueSize = parameterValue.size() + 1; + *inOutParameterValueSize = parameterValue.size(); return SilKit_ReturnCode_SUCCESS; } CAPI_CATCH_EXCEPTIONS diff --git a/SilKit/source/capi/Test_CapiGetParameter.cpp b/SilKit/source/capi/Test_CapiGetParameter.cpp index d96dedda6..fa57079cc 100644 --- a/SilKit/source/capi/Test_CapiGetParameter.cpp +++ b/SilKit/source/capi/Test_CapiGetParameter.cpp @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2024 Vector Informatik GmbH // // SPDX-License-Identifier: MIT + #include "gtest/gtest.h" #include "gmock/gmock.h" #include "silkit/capi/SilKit.h" @@ -31,8 +32,10 @@ TEST_F(Test_CapiGetParameter, getparameter_bad_params) char* parameterValue{nullptr}; size_t parameterSize; - returnCode = - SilKit_Participant_GetParameter(nullptr, ¶meterSize, SilKit_Parameter_ParticipantName, cMockParticipant); + EXPECT_CALL(mockParticipant, GetParameter(SilKit::Parameter::ParticipantName)).Times(testing::Exactly(1)); + + returnCode = SilKit_Participant_GetParameter(nullptr, ¶meterSize, SilKit_Parameter_ParticipantName, + cMockParticipant); EXPECT_EQ(returnCode, SilKit_ReturnCode_SUCCESS); returnCode =