blob: 656dc41a2f4d551893d8ca6d3260d4ff6aa25296 [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{
Krzysztof Grobelnyc8447d52022-01-05 13:21:37 +010021 struct UnpackError
Szymon Dompke6d83cf52021-10-19 16:31:29 +020022 {
Krzysztof Grobelnyc8447d52022-01-05 13:21:37 +010023 sdbusplus::UnpackErrorReason reason;
24 std::string property;
25 };
26
27 template <typename... Args>
28 std::optional<UnpackError> operator()(Args&&... args) const
29 {
30 std::optional<UnpackError> error;
31 unpackPropertiesNoThrow(
32 [&error](const sdbusplus::UnpackErrorReason reason,
33 const std::string& property) {
34 error.emplace(reason, property);
35 },
36 std::forward<Args>(args)...);
37 return error;
Szymon Dompke6d83cf52021-10-19 16:31:29 +020038 }
39};
40
41template <typename A, typename B>
42struct TestingTypes
43{
44 using SystemUnderTest = A;
45 using Container = B;
46};
47
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +020048using VariantType = std::variant<std::string, uint32_t, float, double>;
Szymon Dompke6d83cf52021-10-19 16:31:29 +020049using ContainerTypes = testing::Types<
50 TestingTypes<NonThrowingUnpack,
51 std::vector<std::pair<std::string, VariantType>>>,
Szymon Dompke6d83cf52021-10-19 16:31:29 +020052 TestingTypes<ThrowingUnpack,
Krzysztof Grobelnyc8447d52022-01-05 13:21:37 +010053 std::vector<std::pair<std::string, VariantType>>>>;
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +020054
55template <typename Exception, typename F>
56std::optional<Exception> captureException(F&& code)
57{
58 try
59 {
60 code();
61 }
62 catch (const Exception& e)
63 {
64 return e;
65 }
66
67 return std::nullopt;
68}
69
Szymon Dompke6d83cf52021-10-19 16:31:29 +020070template <typename Params>
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +020071struct UnpackPropertiesTest : public testing::Test
72{
73 void SetUp() override
74 {
75 using namespace std::string_literals;
76
77 data.insert(data.end(),
78 std::make_pair("Key-1"s, VariantType("string"s)));
79 data.insert(data.end(), std::make_pair("Key-2"s, VariantType(42.f)));
80 data.insert(data.end(), std::make_pair("Key-3"s, VariantType(15.)));
81 }
82
Szymon Dompke6d83cf52021-10-19 16:31:29 +020083 typename Params::Container data;
84 typename Params::SystemUnderTest unpackPropertiesCall;
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +020085};
86
87TYPED_TEST_SUITE(UnpackPropertiesTest, ContainerTypes);
88
89TYPED_TEST(UnpackPropertiesTest, returnsValueWhenKeyIsPresentAndTypeMatches)
90{
91 using namespace testing;
92
93 std::string val1;
94 float val2 = 0.f;
95 double val3 = 0.;
96
Szymon Dompke6d83cf52021-10-19 16:31:29 +020097 EXPECT_FALSE(this->unpackPropertiesCall(this->data, "Key-1", val1, "Key-2",
98 val2, "Key-3", val3));
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +020099
100 ASSERT_THAT(val1, Eq("string"));
101 ASSERT_THAT(val2, FloatEq(42.f));
102 ASSERT_THAT(val3, DoubleEq(15.));
103}
104
105TYPED_TEST(UnpackPropertiesTest,
Krzysztof Grobelnyc8447d52022-01-05 13:21:37 +0100106 unpackDoesntChangeOriginalDataWhenPassedAsNonConstReference)
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +0200107{
108 using namespace testing;
109
110 std::string val1, val2;
111
Szymon Dompke6d83cf52021-10-19 16:31:29 +0200112 EXPECT_FALSE(this->unpackPropertiesCall(this->data, "Key-1", val1));
113 EXPECT_FALSE(this->unpackPropertiesCall(this->data, "Key-1", val2));
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +0200114
115 ASSERT_THAT(val1, Eq("string"));
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +0200116 ASSERT_THAT(val2, Eq("string"));
117}
118
Krzysztof Grobelnyc8447d52022-01-05 13:21:37 +0100119TYPED_TEST(UnpackPropertiesTest, doesntReportMissingPropertyForOptional)
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +0200120{
121 using namespace testing;
122 using namespace std::string_literals;
123
Krzysztof Grobelnyc8447d52022-01-05 13:21:37 +0100124 std::optional<std::string> val1;
125 std::optional<std::string> val4;
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +0200126
Krzysztof Grobelnyc8447d52022-01-05 13:21:37 +0100127 EXPECT_FALSE(
128 this->unpackPropertiesCall(this->data, "Key-1", val1, "Key-4", val4));
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +0200129
130 ASSERT_THAT(val1, Eq("string"));
Krzysztof Grobelnyc8447d52022-01-05 13:21:37 +0100131 ASSERT_THAT(val4, Eq(std::nullopt));
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +0200132}
133
Krzysztof Grobelnyc8447d52022-01-05 13:21:37 +0100134TYPED_TEST(UnpackPropertiesTest, setPresentPointersOnSuccess)
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +0200135{
136 using namespace testing;
137 using namespace std::string_literals;
138
Krzysztof Grobelnyc8447d52022-01-05 13:21:37 +0100139 const std::string* val1 = nullptr;
140 const float* val2 = nullptr;
141 const double* val3 = nullptr;
142 const std::string* val4 = nullptr;
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +0200143
Krzysztof Grobelnyc8447d52022-01-05 13:21:37 +0100144 EXPECT_FALSE(this->unpackPropertiesCall(this->data, "Key-1", val1, "Key-2",
145 val2, "Key-3", val3, "Key-4",
146 val4));
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +0200147
Krzysztof Grobelnyc8447d52022-01-05 13:21:37 +0100148 ASSERT_TRUE(val1 && val2 && val3);
149 ASSERT_TRUE(!val4);
150
151 ASSERT_THAT(*val1, Eq("string"));
152 ASSERT_THAT(*val2, FloatEq(42.f));
153 ASSERT_THAT(*val3, DoubleEq(15.));
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +0200154}
155
Szymon Dompke6d83cf52021-10-19 16:31:29 +0200156template <typename Params>
157struct UnpackPropertiesThrowingTest : public UnpackPropertiesTest<Params>
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +0200158{};
159
Krzysztof Grobelnyc8447d52022-01-05 13:21:37 +0100160using ContainerTypesThrowing = testing::Types<TestingTypes<
161 ThrowingUnpack, std::vector<std::pair<std::string, VariantType>>>>;
Szymon Dompke6d83cf52021-10-19 16:31:29 +0200162
163TYPED_TEST_SUITE(UnpackPropertiesThrowingTest, ContainerTypesThrowing);
164
165TYPED_TEST(UnpackPropertiesThrowingTest, throwsErrorWhenKeyIsMissing)
166{
167 using namespace testing;
168
169 std::string val1;
170 float val2 = 0.f;
171 double val3 = 0.;
172
173 auto error = captureException<exception::UnpackPropertyError>([&] {
174 this->unpackPropertiesCall(this->data, "Key-1", val1, "Key-4", val2,
175 "Key-3", val3);
176 });
177
178 ASSERT_TRUE(error);
Krzysztof Grobelnyc8447d52022-01-05 13:21:37 +0100179 ASSERT_THAT(error->reason, Eq(UnpackErrorReason::missingProperty));
Szymon Dompke6d83cf52021-10-19 16:31:29 +0200180 ASSERT_THAT(error->propertyName, Eq("Key-4"));
181}
182
183TYPED_TEST(UnpackPropertiesThrowingTest, throwsErrorWhenTypeDoesntMatch)
184{
185 using namespace testing;
186
187 std::string val1;
188 std::string val2;
189 double val3 = 0.;
190
191 auto error = captureException<exception::UnpackPropertyError>([&] {
192 this->unpackPropertiesCall(this->data, "Key-1", val1, "Key-2", val2,
193 "Key-3", val3);
194 });
195
196 ASSERT_TRUE(error);
Krzysztof Grobelnyc8447d52022-01-05 13:21:37 +0100197 ASSERT_THAT(error->reason, Eq(UnpackErrorReason::wrongType));
198 ASSERT_THAT(error->propertyName, Eq("Key-2"));
199}
200
201TYPED_TEST(UnpackPropertiesThrowingTest, throwsErrorWhenOptionalTypeDoesntMatch)
202{
203 using namespace testing;
204
205 std::optional<std::string> val1;
206 std::optional<std::string> val2;
207
208 auto error = captureException<exception::UnpackPropertyError>([&] {
209 this->unpackPropertiesCall(this->data, "Key-1", val1, "Key-2", val2);
210 });
211
212 ASSERT_TRUE(error);
213 ASSERT_THAT(error->reason, Eq(UnpackErrorReason::wrongType));
Szymon Dompke6d83cf52021-10-19 16:31:29 +0200214 ASSERT_THAT(error->propertyName, Eq("Key-2"));
215}
216
217template <typename Params>
218struct UnpackPropertiesNonThrowingTest : public UnpackPropertiesTest<Params>
219{};
220
Krzysztof Grobelnyc8447d52022-01-05 13:21:37 +0100221using ContainerTypesNonThrowing = testing::Types<TestingTypes<
222 NonThrowingUnpack, std::vector<std::pair<std::string, VariantType>>>>;
Szymon Dompke6d83cf52021-10-19 16:31:29 +0200223
224TYPED_TEST_SUITE(UnpackPropertiesNonThrowingTest, ContainerTypesNonThrowing);
225
226TYPED_TEST(UnpackPropertiesNonThrowingTest, ErrorWhenKeyIsMissing)
227{
228 using namespace testing;
229
230 std::string val1;
231 float val2 = 0.f;
232 double val3 = 0.;
233
234 auto badProperty = this->unpackPropertiesCall(this->data, "Key-1", val1,
235 "Key-4", val2, "Key-3", val3);
236
237 ASSERT_TRUE(badProperty);
Krzysztof Grobelnyc8447d52022-01-05 13:21:37 +0100238 EXPECT_THAT(badProperty->reason, Eq(UnpackErrorReason::missingProperty));
239 EXPECT_THAT(badProperty->property, Eq("Key-4"));
Szymon Dompke6d83cf52021-10-19 16:31:29 +0200240}
241
242TYPED_TEST(UnpackPropertiesNonThrowingTest, ErrorWhenTypeDoesntMatch)
243{
244 using namespace testing;
245
246 std::string val1;
247 std::string val2;
248 double val3 = 0.;
249
250 auto badProperty = this->unpackPropertiesCall(this->data, "Key-1", val1,
251 "Key-2", val2, "Key-3", val3);
252
253 ASSERT_TRUE(badProperty);
Krzysztof Grobelnyc8447d52022-01-05 13:21:37 +0100254 EXPECT_THAT(badProperty->reason, Eq(UnpackErrorReason::wrongType));
255 EXPECT_THAT(badProperty->property, Eq("Key-2"));
256}
257
258TYPED_TEST(UnpackPropertiesNonThrowingTest, ErrorWhenOptionalTypeDoesntMatch)
259{
260 using namespace testing;
261
262 std::optional<std::string> val1;
263 std::optional<std::string> val2;
264
265 auto badProperty =
266 this->unpackPropertiesCall(this->data, "Key-1", val1, "Key-2", val2);
267
268 ASSERT_TRUE(badProperty);
269 EXPECT_THAT(badProperty->reason, Eq(UnpackErrorReason::wrongType));
270 EXPECT_THAT(badProperty->property, Eq("Key-2"));
Szymon Dompke6d83cf52021-10-19 16:31:29 +0200271}
272
273template <typename Params>
274struct UnpackPropertiesTest_ForVector : public UnpackPropertiesTest<Params>
275{};
276
277using ContainerTypesVector = testing::Types<
278 TestingTypes<NonThrowingUnpack,
279 std::vector<std::pair<std::string, VariantType>>>,
280 TestingTypes<ThrowingUnpack,
281 std::vector<std::pair<std::string, VariantType>>>>;
282
283TYPED_TEST_SUITE(UnpackPropertiesTest_ForVector, ContainerTypesVector);
284
285TYPED_TEST(UnpackPropertiesTest_ForVector, silentlyDiscardsDuplicatedKeyInData)
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +0200286{
287 using namespace testing;
288 using namespace std::string_literals;
289
290 std::string val1;
291 float val2 = 0.f;
292 double val3 = 0.;
293
294 this->data.insert(this->data.end(),
295 std::make_pair("Key-1"s, VariantType("string2"s)));
296
Szymon Dompke6d83cf52021-10-19 16:31:29 +0200297 EXPECT_FALSE(this->unpackPropertiesCall(this->data, "Key-1", val1, "Key-2",
298 val2, "Key-3", val3));
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +0200299
300 ASSERT_THAT(val1, Eq("string"));
301 ASSERT_THAT(val2, FloatEq(42.f));
302 ASSERT_THAT(val3, DoubleEq(15.));
303}
304
305} // namespace sdbusplus