Skip to content

Commit 5e6e75a

Browse files
mw/com: disambiguate proxy field test ctor with WithTestTag
1 parent 16bdf51 commit 5e6e75a

7 files changed

Lines changed: 93 additions & 31 deletions

File tree

score/mw/com/impl/field_tags.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ struct is_tag_enabled : std::conjunction<contains_type<TargetTag, Tags...>, std:
4949
{
5050
};
5151

52+
/// \brief Marker used as a disambiguator on test-only ctors to keep them distinct from production overloads.
53+
/// Lives in detail to signal "not part of the public API"; tests reach into the detail namespace knowingly.
54+
struct WithTestTag
55+
{
56+
};
57+
5258
} // namespace detail
5359

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

score/mw/com/impl/mocking/proxy_event_mock_test.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,27 @@ class ProxyEventFieldMockFixture : public ::testing::Test
4545
using ProxyEventFieldMock = typename T::ProxyEventFieldMock;
4646

4747
ProxyEventFieldMockFixture()
48+
: unit_{[this] {
49+
if constexpr (detail::is_proxy_field_v<ProxyEventField>)
50+
{
51+
return ProxyEventField{proxy_base_,
52+
kDummyEventFieldName,
53+
detail::WithTestTag{},
54+
std::unique_ptr<ProxyEventBinding<TestSampleType>>{nullptr}};
55+
}
56+
else
57+
{
58+
return ProxyEventField{
59+
proxy_base_, kDummyEventFieldName, std::unique_ptr<ProxyEventBinding<TestSampleType>>{nullptr}};
60+
}
61+
}()}
4862
{
4963
unit_.InjectMock(proxy_service_element_mock_);
5064
}
5165

5266
ProxyEventFieldMock proxy_service_element_mock_{};
5367
ProxyBase proxy_base_{nullptr, MakeFakeHandle(1U)};
54-
ProxyEventField unit_{proxy_base_,
55-
kDummyEventFieldName,
56-
std::unique_ptr<ProxyEventBinding<TestSampleType>>{nullptr}};
68+
ProxyEventField unit_;
5769
};
5870

5971
struct ProxyEventStruct

score/mw/com/impl/proxy_event_base_test.cpp

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,21 @@ using namespace ::testing;
4040

4141
using TestEventOrFieldType = std::uint16_t;
4242

43+
/// Constructs a service element (ProxyEvent / GenericProxyEvent / ProxyField) for testing, inserting the
44+
/// detail::WithTestTag disambiguator when the target type is a ProxyField.
45+
template <typename ServiceElementType, typename ProxyT, typename Binding>
46+
auto MakeServiceElementForTest(ProxyT& proxy, const char* name, Binding binding)
47+
{
48+
if constexpr (detail::is_proxy_field_v<ServiceElementType>)
49+
{
50+
return std::make_unique<ServiceElementType>(proxy, name, detail::WithTestTag{}, std::move(binding));
51+
}
52+
else
53+
{
54+
return std::make_unique<ServiceElementType>(proxy, name, std::move(binding));
55+
}
56+
}
57+
4358
const ServiceTypeDeployment kEmptyTypeDeployment{score::cpp::blank{}};
4459
const ServiceIdentifierType kFooservice{make_ServiceIdentifierType("foo")};
4560
const auto kInstanceSpecifier = InstanceSpecifier::Create(std::string{"/dummy_instance_specifier"}).value();
@@ -73,8 +88,8 @@ class ProxyEventBaseFixture : public ::testing::Test
7388
auto mock_service_element_binding_ptr = std::make_unique<MockServiceElementType>();
7489
mock_service_element_binding_ = mock_service_element_binding_ptr.get();
7590

76-
service_element_ =
77-
std::make_unique<ServiceElementType>(empty_proxy_, kEventName, std::move(mock_service_element_binding_ptr));
91+
service_element_ = MakeServiceElementForTest<ServiceElementType>(
92+
empty_proxy_, kEventName, std::move(mock_service_element_binding_ptr));
7893

7994
ON_CALL(*mock_service_element_binding_, SetReceiveHandler(_)).WillByDefault(Return(score::Result<void>{}));
8095
}
@@ -164,8 +179,9 @@ TYPED_TEST(ProxyEventBaseCreationFixture, CreatingServiceElementWithValidEventBi
164179
make_HandleType(make_InstanceIdentifier(kEmptyInstanceDeployment, kEmptyTypeDeployment)));
165180

166181
// When creating a ProxyEvent with a valid binding
167-
auto service_element = std::make_unique<typename ProxyEventBaseCreationFixture<TypeParam>::ServiceElementType>(
168-
dummy_proxy, kEventName, std::move(valid_proxy_event_binding));
182+
auto service_element =
183+
MakeServiceElementForTest<typename ProxyEventBaseCreationFixture<TypeParam>::ServiceElementType>(
184+
dummy_proxy, kEventName, std::move(valid_proxy_event_binding));
169185

170186
// Then the proxy should report that all bindings are valid
171187
EXPECT_TRUE(dummy_proxy.AreBindingsValid());
@@ -178,10 +194,11 @@ TYPED_TEST(ProxyEventBaseCreationFixture, CreatingServiceElementWithInvalidEvent
178194
make_HandleType(make_InstanceIdentifier(kEmptyInstanceDeployment, kEmptyTypeDeployment)));
179195

180196
// When creating a ProxyEvent with an invalid binding
181-
auto service_element = std::make_unique<typename ProxyEventBaseCreationFixture<TypeParam>::ServiceElementType>(
182-
dummy_proxy,
183-
kEventName,
184-
std::unique_ptr<typename ProxyEventBaseCreationFixture<TypeParam>::MockServiceElementType>(nullptr));
197+
auto service_element =
198+
MakeServiceElementForTest<typename ProxyEventBaseCreationFixture<TypeParam>::ServiceElementType>(
199+
dummy_proxy,
200+
kEventName,
201+
std::unique_ptr<typename ProxyEventBaseCreationFixture<TypeParam>::MockServiceElementType>(nullptr));
185202

186203
// Then the proxy should report that all bindings are not valid
187204
EXPECT_FALSE(dummy_proxy.AreBindingsValid());
@@ -197,8 +214,9 @@ TYPED_TEST(ProxyEventBaseCreationFixture, CreatingServiceElementWithInvalidProxy
197214
make_HandleType(make_InstanceIdentifier(kEmptyInstanceDeployment, kEmptyTypeDeployment)));
198215

199216
// When creating a ProxyEvent with a valid binding
200-
auto service_element = std::make_unique<typename ProxyEventBaseCreationFixture<TypeParam>::ServiceElementType>(
201-
dummy_proxy, kEventName, std::move(valid_proxy_event_binding));
217+
auto service_element =
218+
MakeServiceElementForTest<typename ProxyEventBaseCreationFixture<TypeParam>::ServiceElementType>(
219+
dummy_proxy, kEventName, std::move(valid_proxy_event_binding));
202220

203221
// Then the proxy should report that all bindings are not valid
204222
EXPECT_FALSE(dummy_proxy.AreBindingsValid());
@@ -223,8 +241,9 @@ TYPED_TEST(ProxyEventBaseCreationFixture,
223241
make_HandleType(make_InstanceIdentifier(kEmptyInstanceDeployment, kEmptyTypeDeployment)));
224242

225243
// When creating a ProxyEvent with a valid binding
226-
auto service_element = std::make_unique<typename ProxyEventBaseCreationFixture<TypeParam>::ServiceElementType>(
227-
dummy_proxy, kEventName, std::move(valid_proxy_event_binding));
244+
auto service_element =
245+
MakeServiceElementForTest<typename ProxyEventBaseCreationFixture<TypeParam>::ServiceElementType>(
246+
dummy_proxy, kEventName, std::move(valid_proxy_event_binding));
228247
}
229248

230249
TYPED_TEST(ProxyEventBaseCreationFixture,
@@ -243,10 +262,10 @@ TYPED_TEST(ProxyEventBaseCreationFixture,
243262
make_HandleType(make_InstanceIdentifier(kEmptyInstanceDeployment, kEmptyTypeDeployment)));
244263

245264
// When creating a ProxyEvent with an invalid binding
246-
auto service_element = std::make_unique<typename ProxyEventBaseCreationFixture<TypeParam>::ServiceElementType>(
247-
dummy_proxy,
248-
kEventName,
249-
std::unique_ptr<typename ProxyEventBaseCreationFixture<TypeParam>::MockServiceElementType>(nullptr));
265+
using ServiceElementType = typename ProxyEventBaseCreationFixture<TypeParam>::ServiceElementType;
266+
using MockServiceElementType = typename ProxyEventBaseCreationFixture<TypeParam>::MockServiceElementType;
267+
auto service_element = MakeServiceElementForTest<ServiceElementType>(
268+
dummy_proxy, kEventName, std::unique_ptr<MockServiceElementType>(nullptr));
250269
}
251270

252271
TYPED_TEST(ProxyEventBaseUnsubscribeFixture, CallingUnsubscribeWhileSubscribedCallsUnsubscribeOnBinding)
@@ -357,8 +376,8 @@ class AServiceElement : public ::testing::Test
357376
auto mock_service_element_binding_ptr = std::make_unique<MockServiceElementType>();
358377
mock_service_element_binding_ = mock_service_element_binding_ptr.get();
359378

360-
service_element_ =
361-
std::make_unique<ServiceElementType>(empty_proxy_, kEventName, std::move(mock_service_element_binding_ptr));
379+
service_element_ = MakeServiceElementForTest<ServiceElementType>(
380+
empty_proxy_, kEventName, std::move(mock_service_element_binding_ptr));
362381
ASSERT_NE(service_element_, nullptr);
363382

364383
ON_CALL(*mock_service_element_binding_, SetReceiveHandler(_)).WillByDefault(Return(score::Result<void>{}));

score/mw/com/impl/proxy_event_test.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,17 @@ class ProxyEventFixture : public ::testing::Test
106106
make_HandleType(make_InstanceIdentifier(kEmptyInstanceDeployment, kEmptyTypeDeployment))},
107107
mock_proxy_event_ptr_{std::make_unique<MockProxyEventType>()},
108108
mock_proxy_event_{*mock_proxy_event_ptr_},
109-
proxy_event_{empty_proxy_, kEventName, std::move(mock_proxy_event_ptr_)}
109+
proxy_event_{[this] {
110+
if constexpr (detail::is_proxy_field_v<ProxyEventType>)
111+
{
112+
return ProxyEventType{
113+
empty_proxy_, kEventName, detail::WithTestTag{}, std::move(mock_proxy_event_ptr_)};
114+
}
115+
else
116+
{
117+
return ProxyEventType{empty_proxy_, kEventName, std::move(mock_proxy_event_ptr_)};
118+
}
119+
}()}
110120
{
111121
}
112122

score/mw/com/impl/proxy_field.h

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,25 @@ namespace score::mw::com::impl
4343
template <typename FieldType, typename... Tags>
4444
class ProxyFieldAttorney;
4545

46+
template <typename SampleDataType, typename... Tags>
47+
class ProxyField;
48+
49+
namespace detail
50+
{
51+
52+
template <typename T>
53+
struct is_proxy_field : std::false_type
54+
{
55+
};
56+
template <typename FieldType, typename... Tags>
57+
struct is_proxy_field<ProxyField<FieldType, Tags...>> : std::true_type
58+
{
59+
};
60+
template <typename T>
61+
constexpr bool is_proxy_field_v = is_proxy_field<T>::value;
62+
63+
} // namespace detail
64+
4665
/// \brief This is the user-visible class of a field that is part of a proxy. It delegates all functionality to
4766
/// ProxyEvent.
4867
///
@@ -67,11 +86,11 @@ class ProxyField final : public ProxyFieldBase
6786
public:
6887
using FieldType = SampleDataType;
6988

70-
/// Testing ctor: bindings are passed in directly (used with mock bindings). The event binding is required
71-
/// (no default) to disambiguate this overload from the production ctors when called as `{proxy, field_name}`.
72-
/// Method bindings default to nullptr; passing nullptr means the corresponding ProxyMethod is not built.
89+
/// Testing ctor: bindings are passed in directly (used with mock bindings). Disambiguated from the production
90+
/// ctors via the detail::WithTestTag marker, required as the 3rd argument. Bindings default to nullptr;
7391
ProxyField(ProxyBase& proxy_base,
7492
const std::string_view field_name,
93+
detail::WithTestTag,
7594
std::unique_ptr<ProxyEventBinding<FieldType>> event_binding = nullptr,
7695
std::unique_ptr<ProxyMethodBinding> get_method_binding = nullptr,
7796
std::unique_ptr<ProxyMethodBinding> set_method_binding = nullptr)

score/mw/com/impl/proxy_field_base.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ namespace score::mw::com::impl
3030
class ProxyFieldBase
3131
{
3232
public:
33+
/// \param proxy_event_base_dispatch May be nullptr when the field has no notifier tag.
3334
ProxyFieldBase(ProxyBase& proxy_base, std::string_view field_name, ProxyEventBase* proxy_event_base_dispatch)
3435
: proxy_base_{proxy_base}, proxy_event_base_dispatch_{proxy_event_base_dispatch}, field_name_{field_name}
3536
{
36-
SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(proxy_event_base_dispatch != nullptr);
3737
}
3838

3939
/// \brief A ProxyFieldBase shall not be copyable

score/mw/com/test/common_test_resources/test_interface.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,7 @@ class TestInterface : public T::Base
2828
public:
2929
using T::Base::Base;
3030

31-
typename T::template Field<std::int32_t,
32-
score::mw::com::WithGetter,
33-
score::mw::com::WithSetter,
34-
score::mw::com::WithNotifier>
35-
test_field{*this, "test_field"};
31+
typename T::template Field<std::int32_t, score::mw::com::WithNotifier> test_field{*this, "test_field"};
3632
};
3733

3834
} // namespace score::mw::com::test

0 commit comments

Comments
 (0)