Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions score/mw/com/impl/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ cc_library(
":proxy_event",
":proxy_event_binding",
":proxy_field_base",
"//score/mw/com/impl/methods:proxy_method",
"//score/mw/com/impl/mocking:i_proxy_event",
"//score/mw/com/impl/plumbing:field",
"@score_baselibs//score/language/futurecpp",
Expand Down Expand Up @@ -964,6 +965,7 @@ cc_gtest_unit_test(
deps = [
":impl",
":runtime_mock",
"//score/mw/com/impl/mocking:proxy_event_mock",
"//score/mw/com/impl/plumbing:proxy_field_binding_factory_mock",
"//score/mw/com/impl/test:binding_factory_resources",
"//score/mw/com/impl/test:proxy_resources",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@
namespace score::mw::com::impl
{

template <typename, bool, bool, bool>
class ProxyField;

/// \brief Partial specialization of ProxyMethod for function signatures with arguments and non-void return
/// \tparam ReturnType return type of the method
/// \tparam ArgTypes argument types of the method
Expand All @@ -51,6 +54,16 @@ class ProxyMethod<ReturnType(ArgTypes...)> final : public ProxyMethodBase
// coverity[autosar_cpp14_a11_3_1_violation]
friend class ProxyMethodView;

friend class ProxyField<ReturnType, true, true, true>;
friend class ProxyField<ReturnType, true, true, false>;
friend class ProxyField<ReturnType, false, true, false>;
friend class ProxyField<ReturnType, false, true, true>;

// Empty struct that is used to make the non-registering ctor only accessible to ProxyField (as it is a friend).
struct FieldOnlyConstructorEnabler
{
};

public:
ProxyMethod(ProxyBase& proxy_base, std::string_view method_name) noexcept
: ProxyMethodBase(
Expand Down Expand Up @@ -85,6 +98,26 @@ class ProxyMethod<ReturnType(ArgTypes...)> final : public ProxyMethodBase
}
}

/// \brief Ctor for ProxyMethod that is used by ProxyField for the "dispatch method" of a field-setter. This method
/// does not register the method in the ProxyBase's method map, since registration in the correct field map is done
/// by ProxyField ctor. This is achieved by the FieldOnlyConstructorEnabler tag type, which makes clear, that this
/// ctor should only be used by ProxyField (this is enforced by FieldOnlyConstructorEnabler only visible to
/// ProxyField due to it being a friend).
ProxyMethod(ProxyBase& proxy_base,
std::unique_ptr<ProxyMethodBinding> proxy_method_binding,
std::string_view method_name,
FieldOnlyConstructorEnabler) noexcept
: ProxyMethodBase(proxy_base, std::move(proxy_method_binding), method_name),
are_in_arg_ptrs_active_(kCallQueueSize)
{
auto proxy_base_view = ProxyBaseView{proxy_base};
if (binding_ == nullptr)
{
proxy_base_view.MarkServiceElementBindingInvalid();
return;
}
}

~ProxyMethod() final = default;

/// \brief A ProxyMethod shall not be copyable.
Expand Down
31 changes: 31 additions & 0 deletions score/mw/com/impl/methods/proxy_method_with_return_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
namespace score::mw::com::impl
{

template <typename, bool, bool, bool>
class ProxyField;

/// \brief Partial specialization of ProxyMethod for function signatures with no arguments and non-void return
/// \tparam ReturnType return type of the method
template <typename ReturnType>
Expand All @@ -45,6 +48,15 @@ class ProxyMethod<ReturnType()> final : public ProxyMethodBase
// This enables us to hide unnecessary internals from the end-user.
// coverity[autosar_cpp14_a11_3_1_violation]
friend class ProxyMethodView;
friend class ProxyField<ReturnType, true, true, true>;
friend class ProxyField<ReturnType, true, false, false>;
friend class ProxyField<ReturnType, true, true, false>;
friend class ProxyField<ReturnType, true, false, true>;

// Empty struct that is used to make the non-registering ctor only accessible to ProxyField (as it is a friend).
struct FieldOnlyConstructorEnabler
{
};

public:
ProxyMethod(ProxyBase& proxy_base, std::string_view method_name) noexcept
Expand Down Expand Up @@ -77,6 +89,25 @@ class ProxyMethod<ReturnType()> final : public ProxyMethodBase
}
}

/// \brief Ctor for ProxyMethod that is used by ProxyField for the "dispatch method" of a field-getter. This method
/// does not register the method in the ProxyBase's method map, since registration in the correct field map is done
/// by ProxyField ctor. This is achieved by the FieldOnlyConstructorEnabler tag type, which makes clear, that this
/// ctor should only be used by ProxyField (this is enforced by FieldOnlyConstructorEnabler only visible to
/// ProxyField due to it being a friend).
ProxyMethod(ProxyBase& proxy_base,
std::unique_ptr<ProxyMethodBinding> proxy_method_binding,
std::string_view method_name,
FieldOnlyConstructorEnabler) noexcept
: ProxyMethodBase(proxy_base, std::move(proxy_method_binding), method_name)
{
auto proxy_base_view = ProxyBaseView{proxy_base};
if (binding_ == nullptr)
{
proxy_base_view.MarkServiceElementBindingInvalid();
return;
}
}

~ProxyMethod() final = default;

/// \brief A ProxyMethod shall not be copyable.
Expand Down
11 changes: 8 additions & 3 deletions score/mw/com/impl/mocking/proxy_event_mock_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ namespace score::mw::com::impl
{
namespace
{

using TestSampleType = std::uint32_t;

auto kDummyEventFieldName = "MyDummyEventField";
Expand All @@ -46,7 +45,14 @@ class ProxyEventFieldMockFixture : public ::testing::Test

ProxyEventFieldMockFixture()
{
unit_.InjectMock(proxy_service_element_mock_);
if constexpr (std::is_same_v<ProxyEventField, ProxyEvent<TestSampleType>>)
{
unit_.InjectMock(proxy_service_element_mock_);
}
else
{
unit_.InjectEventMock(proxy_service_element_mock_);
}
}

ProxyEventFieldMock proxy_service_element_mock_{};
Expand Down Expand Up @@ -273,6 +279,5 @@ TYPED_TEST(ProxyEventFieldMockFixture, GetNewSamplesReturnsErrorWhenMockReturnsE
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error(), error_code);
}

} // namespace
} // namespace score::mw::com::impl
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ TEST_F(ProxyWrapperTestClassCreateFixture, CallingFunctionsOnMockProxyDispatches
auto& proxy_field_mock = std::get<0>(fields_tuple).mock;
proxy.some_event.InjectMock(proxy_event_mock);
proxy.some_event_2.InjectMock(proxy_event_mock_2);
proxy.some_field.InjectMock(proxy_field_mock);
proxy.some_field.InjectEventMock(proxy_field_mock);

// Expecting that OfferService will be called on the Proxy mock and Unsubscribe on the event and field mocks
EXPECT_CALL(proxy_event_mock, Unsubscribe());
Expand Down Expand Up @@ -254,7 +254,7 @@ TEST_F(ProxyWrapperTestClassFieldsOnlyCreateFixture, CallingFunctionsOnMockProxy
// and given a mocked proxy was created
auto proxy = ProxyWrapperClassTestView<FieldOnlyProxy>::Create(fields_tuple);
auto& proxy_field_mock = (std::get<0>(fields_tuple).mock);
proxy.some_field.InjectMock(proxy_field_mock);
proxy.some_field.InjectEventMock(proxy_field_mock);

// Expecting that Unsubscribe is called on the field
EXPECT_CALL(proxy_field_mock, Unsubscribe());
Expand Down
1 change: 1 addition & 0 deletions score/mw/com/impl/plumbing/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ cc_library(
tags = ["FFI"],
deps = [
":i_proxy_field_binding_factory",
":proxy_method_binding_factory",
":proxy_service_element_binding_factory_impl",
"@score_baselibs//score/language/futurecpp",
],
Expand Down
15 changes: 15 additions & 0 deletions score/mw/com/impl/plumbing/i_proxy_field_binding_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#define SCORE_MW_COM_IMPL_PLUMBING_I_PROXY_FIELD_BINDING_FACTORY_H

#include "score/mw/com/impl/instance_identifier.h"
#include "score/mw/com/impl/methods/proxy_method_binding.h"
#include "score/mw/com/impl/proxy_base.h"
#include "score/mw/com/impl/proxy_event_binding.h"

Expand Down Expand Up @@ -45,6 +46,20 @@ class IProxyFieldBindingFactory
/// \return An instance of ProxyEventBinding or nullptr in case of an error.
virtual auto CreateEventBinding(ProxyBase& parent, const std::string_view field_name) noexcept
-> std::unique_ptr<ProxyEventBinding<SampleType>> = 0;

///
/// @param parent
/// @param field_name
/// @return
virtual auto CreateGetMethodBinding(ProxyBase& parent, const std::string_view field_name) noexcept
-> std::unique_ptr<ProxyMethodBinding> = 0;

///
/// @param parent
/// @param field_name
/// @return
virtual auto CreateSetMethodBinding(ProxyBase& parent, const std::string_view field_name) noexcept
-> std::unique_ptr<ProxyMethodBinding> = 0;
};
} // namespace score::mw::com::impl

Expand Down
13 changes: 13 additions & 0 deletions score/mw/com/impl/plumbing/proxy_field_binding_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#ifndef SCORE_MW_COM_IMPL_PLUMBING_PROXY_FIELD_BINDING_FACTORY_H
#define SCORE_MW_COM_IMPL_PLUMBING_PROXY_FIELD_BINDING_FACTORY_H

#include "score/mw/com/impl/methods/proxy_method_binding.h"
#include "score/mw/com/impl/plumbing/i_proxy_field_binding_factory.h"
#include "score/mw/com/impl/plumbing/proxy_field_binding_factory_impl.h"
#include "score/mw/com/impl/proxy_base.h"
Expand All @@ -39,6 +40,18 @@ class ProxyFieldBindingFactory final
return instance().CreateEventBinding(parent, field_name);
}

static std::unique_ptr<ProxyMethodBinding> CreateGetMethodBinding(ProxyBase& parent,
std::string_view field_name) noexcept
{
return instance().CreateGetMethodBinding(parent, field_name);
}

static std::unique_ptr<ProxyMethodBinding> CreateSetMethodBinding(ProxyBase& parent,
std::string_view field_name) noexcept
{
return instance().CreateSetMethodBinding(parent, field_name);
}

/// \brief Inject a mock IProxyFieldBindingFactory. If a mock is injected, then all calls on
/// ProxyFieldBindingFactory will be dispatched to the mock.
static void InjectMockBinding(IProxyFieldBindingFactory<SampleType>* const mock) noexcept
Expand Down
40 changes: 36 additions & 4 deletions score/mw/com/impl/plumbing/proxy_field_binding_factory_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,25 @@
#ifndef SCORE_MW_COM_IMPL_PLUMBING_PROXY_FIELD_BINDING_FACTORY_IMPL_H
#define SCORE_MW_COM_IMPL_PLUMBING_PROXY_FIELD_BINDING_FACTORY_IMPL_H

#include "score/mw/com/impl/bindings/lola/element_fq_id.h"
#include "score/mw/com/impl/bindings/lola/proxy_event.h"
#include "score/mw/com/impl/plumbing/i_proxy_field_binding_factory.h"
#include "score/mw/com/impl/plumbing/proxy_method_binding_factory.h"
#include "score/mw/com/impl/plumbing/proxy_service_element_binding_factory_impl.h"
#include "score/mw/com/impl/proxy_base.h"
#include "score/mw/com/impl/proxy_event_binding.h"

#include <score/overload.hpp>

#include <memory>
#include <string_view>

namespace score::mw::com::impl
{

namespace detail
{
constexpr char kGetMethodName[] = "Get";
constexpr char kSetMethodName[] = "Set";
} // namespace detail

/// \brief Factory class that dispatches calls to the appropriate binding based on binding information in the
/// deployment configuration.
template <typename SampleType>
Expand All @@ -42,11 +46,17 @@ class ProxyFieldBindingFactoryImpl final : public IProxyFieldBindingFactory<Samp
std::unique_ptr<ProxyEventBinding<SampleType>> CreateEventBinding(
ProxyBase& parent,
const std::string_view field_name) noexcept override;

std::unique_ptr<ProxyMethodBinding> CreateGetMethodBinding(ProxyBase& parent,
const std::string_view field_name) noexcept override;

std::unique_ptr<ProxyMethodBinding> CreateSetMethodBinding(ProxyBase& parent,
const std::string_view field_name) noexcept override;
};

template <typename SampleType>
// Suppress "AUTOSAR C++14 A15-5-3" rule finding. This rule states: "The std::terminate() function shall
// not be called implicitly.". std::visit Throws std::bad_variant_access if
// not be called implicitly". std::visit Throws std::bad_variant_access if
// as-variant(vars_i).valueless_by_exception() is true for any variant vars_i in vars. The variant may only become
// valueless if an exception is thrown during different stages. Since we don't throw exceptions, it's not possible
// that the variant can return true from valueless_by_exception and therefore not possible that std::visit throws
Expand All @@ -62,6 +72,28 @@ inline std::unique_ptr<ProxyEventBinding<SampleType>> ProxyFieldBindingFactoryIm
ServiceElementType::FIELD>(parent, field_name);
}

template <typename SampleType>
inline std::unique_ptr<ProxyMethodBinding> ProxyFieldBindingFactoryImpl<SampleType>::CreateGetMethodBinding(
ProxyBase& parent,
const std::string_view field_name) noexcept
{
// \todo: when the extension in methods are there, where we have an additional method-type enum (get/set/normal
// method) this call needs to be updated -> method name shoud then be field name and get/set is distinguished by the
// additional enum
return ProxyMethodBindingFactory<SampleType()>::Create(
parent.GetHandle(), ProxyBaseView{parent}.GetBinding(), detail::kGetMethodName);
}

template <typename SampleType>
inline std::unique_ptr<ProxyMethodBinding> ProxyFieldBindingFactoryImpl<SampleType>::CreateSetMethodBinding(
ProxyBase& parent,
const std::string_view field_name) noexcept
{
// \todo: see above.
return ProxyMethodBindingFactory<SampleType(SampleType)>::Create(
parent.GetHandle(), ProxyBaseView{parent}.GetBinding(), detail::kSetMethodName);
}

} // namespace score::mw::com::impl

#endif // SCORE_MW_COM_IMPL_PLUMBING_PROXY_FIELD_BINDING_FACTORY_IMPL_H
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ class ProxyFieldBindingFactoryMock : public IProxyFieldBindingFactory<SampleType
CreateEventBinding,
(ProxyBase&, std::string_view),
(noexcept, override));
MOCK_METHOD(std::unique_ptr<ProxyMethodBinding>,
CreateGetMethodBinding,
(ProxyBase&, std::string_view),
(noexcept, override));
MOCK_METHOD(std::unique_ptr<ProxyMethodBinding>,
CreateSetMethodBinding,
(ProxyBase&, std::string_view),
(noexcept, override));
};

} // namespace score::mw::com::impl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,25 +35,27 @@
namespace score::mw::com::impl
{

template <typename ProxyServiceElementBinding, typename ProxyServiceElement, ServiceElementType element_type>
template <typename ProxyServiceElementBindingInterface,
typename ProxyServiceElementBinding,
ServiceElementType element_type>
// "AUTOSAR C++14 A15-5-3" triggered by std::bad_variant_access.
// Additionally the variant might be valueless_by_exception, which would also cause a std::bad_variant_access, this
// Additionally, the variant might be valueless_by_exception, which would also cause a std::bad_variant_access, this
// can only happen if any of the variants throw exception during construction. Since we do not throw exceptions,
// this can not happen, and therefore it is not possible for std::visit to throw an exception.
//
// The return type of the template function does not depend on the type of parameters.
//
//
// "AUTOSAR C++14 A8-2-1" This is not a safetey issue. The rationall only outlines code style improvements, which would
// "AUTOSAR C++14 A8-2-1" This is not a safety issue. The rational only outlines code style improvements, which would
// not be present here.
//
// coverity[autosar_cpp14_a15_5_3_violation]
// coverity[autosar_cpp14_a8_2_1_violation]
std::unique_ptr<ProxyServiceElementBinding> CreateProxyServiceElement(
std::unique_ptr<ProxyServiceElementBindingInterface> CreateProxyServiceElement(
ProxyBase& parent,
const std::string_view service_element_name) noexcept
{
using ReturnType = std::unique_ptr<ProxyServiceElementBinding>;
using ReturnType = std::unique_ptr<ProxyServiceElementBindingInterface>;

const HandleType& handle = parent.GetHandle();
const auto& type_deployment = handle.GetServiceTypeDeployment();
Expand All @@ -64,23 +66,23 @@ std::unique_ptr<ProxyServiceElementBinding> CreateProxyServiceElement(
if (lola_parent == nullptr)
{
score::mw::log::LogError("lola") << "Proxy service element could not be created because parent proxy "
"binding is a nullptr.";
"binding is a nullptr.";
return nullptr;
}

const auto instance_id = handle.GetInstanceId();
const auto* const lola_service_instance_id =
std::get_if<LolaServiceInstanceId>(&(instance_id.binding_info_));
SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD_MESSAGE(lola_service_instance_id != nullptr,
"ServiceInstanceId does not contain lola binding.");
"ServiceInstanceId does not contain lola binding.");

const auto lola_service_element_id =
GetServiceElementId<element_type>(lola_type_deployment, std::string{service_element_name});
const lola::ElementFqId element_fq_id{lola_type_deployment.service_id_,
lola_service_element_id,
lola_service_instance_id->GetId(),
element_type};
return std::make_unique<ProxyServiceElement>(*lola_parent, element_fq_id, service_element_name);
return std::make_unique<ProxyServiceElementBinding>(*lola_parent, element_fq_id, service_element_name);
},
[](const score::cpp::blank&) noexcept -> ReturnType {
return nullptr;
Expand Down
Loading
Loading