blob: cb7b1227acced36ae057a3a31782d0853f4a6cf3 [file] [log] [blame]
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +02001#include <boost/container/flat_map.hpp>
2#include <sdbusplus/unpack_properties.hpp>
3
4#include <gmock/gmock.h>
5
6namespace sdbusplus
7{
8
Szymon Dompke6d83cf52021-10-19 16:31:29 +02009struct ThrowingUnpack
10{
11 template <typename... Args>
12 bool operator()(Args&&... args) const
13 {
14 unpackProperties(std::forward<Args>(args)...);
15 return false;
16 }
17};
18
19struct NonThrowingUnpack
20{
21 template <typename... Args>
22 std::optional<std::string> operator()(Args&&... args) const
23 {
24 return unpackPropertiesNoThrow(std::forward<Args>(args)...);
25 }
26};
27
28template <typename A, typename B>
29struct TestingTypes
30{
31 using SystemUnderTest = A;
32 using Container = B;
33};
34
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +020035using VariantType = std::variant<std::string, uint32_t, float, double>;
Szymon Dompke6d83cf52021-10-19 16:31:29 +020036using ContainerTypes = testing::Types<
37 TestingTypes<NonThrowingUnpack,
38 std::vector<std::pair<std::string, VariantType>>>,
39 TestingTypes<NonThrowingUnpack,
40 boost::container::flat_map<std::string, VariantType>>,
41 TestingTypes<NonThrowingUnpack, std::map<std::string, VariantType>>,
42 TestingTypes<ThrowingUnpack,
43 std::vector<std::pair<std::string, VariantType>>>,
44 TestingTypes<ThrowingUnpack,
45 boost::container::flat_map<std::string, VariantType>>,
46 TestingTypes<ThrowingUnpack, std::map<std::string, VariantType>>>;
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +020047
48template <typename Exception, typename F>
49std::optional<Exception> captureException(F&& code)
50{
51 try
52 {
53 code();
54 }
55 catch (const Exception& e)
56 {
57 return e;
58 }
59
60 return std::nullopt;
61}
62
Szymon Dompke6d83cf52021-10-19 16:31:29 +020063template <typename Params>
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +020064struct UnpackPropertiesTest : public testing::Test
65{
66 void SetUp() override
67 {
68 using namespace std::string_literals;
69
70 data.insert(data.end(),
71 std::make_pair("Key-1"s, VariantType("string"s)));
72 data.insert(data.end(), std::make_pair("Key-2"s, VariantType(42.f)));
73 data.insert(data.end(), std::make_pair("Key-3"s, VariantType(15.)));
74 }
75
Szymon Dompke6d83cf52021-10-19 16:31:29 +020076 typename Params::Container data;
77 typename Params::SystemUnderTest unpackPropertiesCall;
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +020078};
79
80TYPED_TEST_SUITE(UnpackPropertiesTest, ContainerTypes);
81
82TYPED_TEST(UnpackPropertiesTest, returnsValueWhenKeyIsPresentAndTypeMatches)
83{
84 using namespace testing;
85
86 std::string val1;
87 float val2 = 0.f;
88 double val3 = 0.;
89
Szymon Dompke6d83cf52021-10-19 16:31:29 +020090 EXPECT_FALSE(this->unpackPropertiesCall(this->data, "Key-1", val1, "Key-2",
91 val2, "Key-3", val3));
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +020092
93 ASSERT_THAT(val1, Eq("string"));
94 ASSERT_THAT(val2, FloatEq(42.f));
95 ASSERT_THAT(val3, DoubleEq(15.));
96}
97
98TYPED_TEST(UnpackPropertiesTest,
99 unpackChangesOriginalDataWhenPassedAsNonConstReference)
100{
101 using namespace testing;
102
103 std::string val1, val2;
104
Szymon Dompke6d83cf52021-10-19 16:31:29 +0200105 EXPECT_FALSE(this->unpackPropertiesCall(this->data, "Key-1", val1));
106 EXPECT_FALSE(this->unpackPropertiesCall(this->data, "Key-1", val2));
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +0200107
108 ASSERT_THAT(val1, Eq("string"));
109 ASSERT_THAT(val2, Not(Eq("string")));
110}
111
112TYPED_TEST(UnpackPropertiesTest,
113 unpackDoesntChangeOriginalDataWhenPassesAsConstReference)
114{
115 using namespace testing;
116
117 std::string val1, val2;
118
Szymon Dompke6d83cf52021-10-19 16:31:29 +0200119 EXPECT_FALSE(this->unpackPropertiesCall(Const(this->data), "Key-1", val1));
120 EXPECT_FALSE(this->unpackPropertiesCall(Const(this->data), "Key-1", val2));
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +0200121
122 ASSERT_THAT(val1, Eq("string"));
123 ASSERT_THAT(val2, Eq("string"));
124}
125
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +0200126TYPED_TEST(UnpackPropertiesTest,
127 returnsUndefinedValueForDuplicatedKeysWhenDataIsNonConstReference)
128{
129 using namespace testing;
130 using namespace std::string_literals;
131
132 std::string val1;
133 float val2 = 0.f;
134 double val3 = 0.;
135 std::string val4;
136
Szymon Dompke6d83cf52021-10-19 16:31:29 +0200137 EXPECT_FALSE(this->unpackPropertiesCall(this->data, "Key-1", val1, "Key-2",
138 val2, "Key-3", val3, "Key-1",
139 val4));
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +0200140
141 ASSERT_THAT(val1, Eq("string"));
142 ASSERT_THAT(val2, FloatEq(42.f));
143 ASSERT_THAT(val3, DoubleEq(15.));
144 ASSERT_THAT(val4, Not(Eq("string")));
145}
146
147TYPED_TEST(UnpackPropertiesTest,
148 returnsValueForDuplicatedKeysWhenDataIsConstReference)
149{
150 using namespace testing;
151 using namespace std::string_literals;
152
153 std::string val1;
154 float val2 = 0.f;
155 double val3 = 0.;
156 std::string val4;
157
Szymon Dompke6d83cf52021-10-19 16:31:29 +0200158 EXPECT_FALSE(this->unpackPropertiesCall(Const(this->data), "Key-1", val1,
159 "Key-2", val2, "Key-3", val3,
160 "Key-1", val4));
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +0200161
162 ASSERT_THAT(val1, Eq("string"));
163 ASSERT_THAT(val2, FloatEq(42.f));
164 ASSERT_THAT(val3, DoubleEq(15.));
165 ASSERT_THAT(val4, Eq("string"));
166}
167
Szymon Dompke6d83cf52021-10-19 16:31:29 +0200168template <typename Params>
169struct UnpackPropertiesThrowingTest : public UnpackPropertiesTest<Params>
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +0200170{};
171
Szymon Dompke6d83cf52021-10-19 16:31:29 +0200172using ContainerTypesThrowing = testing::Types<
173 TestingTypes<ThrowingUnpack,
174 std::vector<std::pair<std::string, VariantType>>>,
175 TestingTypes<ThrowingUnpack,
176 boost::container::flat_map<std::string, VariantType>>,
177 TestingTypes<ThrowingUnpack, std::map<std::string, VariantType>>>;
178
179TYPED_TEST_SUITE(UnpackPropertiesThrowingTest, ContainerTypesThrowing);
180
181TYPED_TEST(UnpackPropertiesThrowingTest, throwsErrorWhenKeyIsMissing)
182{
183 using namespace testing;
184
185 std::string val1;
186 float val2 = 0.f;
187 double val3 = 0.;
188
189 auto error = captureException<exception::UnpackPropertyError>([&] {
190 this->unpackPropertiesCall(this->data, "Key-1", val1, "Key-4", val2,
191 "Key-3", val3);
192 });
193
194 ASSERT_TRUE(error);
195 ASSERT_THAT(error->reason,
196 Eq(exception::UnpackPropertyError::reasonMissingProperty));
197 ASSERT_THAT(error->propertyName, Eq("Key-4"));
198}
199
200TYPED_TEST(UnpackPropertiesThrowingTest, throwsErrorWhenTypeDoesntMatch)
201{
202 using namespace testing;
203
204 std::string val1;
205 std::string val2;
206 double val3 = 0.;
207
208 auto error = captureException<exception::UnpackPropertyError>([&] {
209 this->unpackPropertiesCall(this->data, "Key-1", val1, "Key-2", val2,
210 "Key-3", val3);
211 });
212
213 ASSERT_TRUE(error);
214 ASSERT_THAT(error->reason,
215 Eq(exception::UnpackPropertyError::reasonTypeNotMatched));
216 ASSERT_THAT(error->propertyName, Eq("Key-2"));
217}
218
219template <typename Params>
220struct UnpackPropertiesNonThrowingTest : public UnpackPropertiesTest<Params>
221{};
222
223using ContainerTypesNonThrowing = testing::Types<
224 TestingTypes<NonThrowingUnpack,
225 std::vector<std::pair<std::string, VariantType>>>,
226 TestingTypes<NonThrowingUnpack,
227 boost::container::flat_map<std::string, VariantType>>,
228 TestingTypes<NonThrowingUnpack, std::map<std::string, VariantType>>>;
229
230TYPED_TEST_SUITE(UnpackPropertiesNonThrowingTest, ContainerTypesNonThrowing);
231
232TYPED_TEST(UnpackPropertiesNonThrowingTest, ErrorWhenKeyIsMissing)
233{
234 using namespace testing;
235
236 std::string val1;
237 float val2 = 0.f;
238 double val3 = 0.;
239
240 auto badProperty = this->unpackPropertiesCall(this->data, "Key-1", val1,
241 "Key-4", val2, "Key-3", val3);
242
243 ASSERT_TRUE(badProperty);
244 ASSERT_THAT(*badProperty, Eq("Key-4"));
245}
246
247TYPED_TEST(UnpackPropertiesNonThrowingTest, ErrorWhenTypeDoesntMatch)
248{
249 using namespace testing;
250
251 std::string val1;
252 std::string val2;
253 double val3 = 0.;
254
255 auto badProperty = this->unpackPropertiesCall(this->data, "Key-1", val1,
256 "Key-2", val2, "Key-3", val3);
257
258 ASSERT_TRUE(badProperty);
259 ASSERT_THAT(*badProperty, Eq("Key-2"));
260}
261
262template <typename Params>
263struct UnpackPropertiesTest_ForVector : public UnpackPropertiesTest<Params>
264{};
265
266using ContainerTypesVector = testing::Types<
267 TestingTypes<NonThrowingUnpack,
268 std::vector<std::pair<std::string, VariantType>>>,
269 TestingTypes<ThrowingUnpack,
270 std::vector<std::pair<std::string, VariantType>>>>;
271
272TYPED_TEST_SUITE(UnpackPropertiesTest_ForVector, ContainerTypesVector);
273
274TYPED_TEST(UnpackPropertiesTest_ForVector, silentlyDiscardsDuplicatedKeyInData)
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +0200275{
276 using namespace testing;
277 using namespace std::string_literals;
278
279 std::string val1;
280 float val2 = 0.f;
281 double val3 = 0.;
282
283 this->data.insert(this->data.end(),
284 std::make_pair("Key-1"s, VariantType("string2"s)));
285
Szymon Dompke6d83cf52021-10-19 16:31:29 +0200286 EXPECT_FALSE(this->unpackPropertiesCall(this->data, "Key-1", val1, "Key-2",
287 val2, "Key-3", val3));
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +0200288
289 ASSERT_THAT(val1, Eq("string"));
290 ASSERT_THAT(val2, FloatEq(42.f));
291 ASSERT_THAT(val3, DoubleEq(15.));
292}
293
294} // namespace sdbusplus