blob: 89f6af0020f66f7df385cdd77a56dbe7dcd345a4 [file] [log] [blame]
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -07001#include <gtest/gtest.h>
2#include <gmock/gmock.h>
3#include <map>
Patrick Williams4fe85a32016-09-08 15:03:56 -05004#include <sdbusplus/message.hpp>
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -07005#include <sdbusplus/test/sdbus_mock.hpp>
Ed Tanous28dc36d2018-02-21 12:22:54 -08006#include <set>
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -07007#include <string>
8#include <systemd/sd-bus-protocol.h>
9#include <tuple>
10#include <unordered_map>
11#include <vector>
Patrick Williams4fe85a32016-09-08 15:03:56 -050012
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -070013namespace
Patrick Williams4fe85a32016-09-08 15:03:56 -050014{
Patrick Williams4fe85a32016-09-08 15:03:56 -050015
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -070016using testing::DoAll;
17using testing::Return;
18using testing::StrEq;
19
20ACTION_TEMPLATE(AssignReadVal, HAS_1_TEMPLATE_PARAMS(typename, T),
21 AND_1_VALUE_PARAMS(val))
22{
23 *static_cast<T *>(arg2) = val;
Patrick Williams4fe85a32016-09-08 15:03:56 -050024}
25
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -070026class ReadTest : public testing::Test
Patrick Williams4fe85a32016-09-08 15:03:56 -050027{
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -070028 protected:
29 testing::StrictMock<sdbusplus::SdBusMock> mock;
Patrick Williams4fe85a32016-09-08 15:03:56 -050030
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -070031 void SetUp() override
Patrick Williams4fe85a32016-09-08 15:03:56 -050032 {
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -070033 EXPECT_CALL(mock, sd_bus_message_new_method_call(testing::_, testing::_,
34 nullptr, nullptr,
35 nullptr, nullptr))
36 .WillRepeatedly(Return(0));
37 };
Patrick Williams4fe85a32016-09-08 15:03:56 -050038
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -070039 sdbusplus::message::message new_message()
40 {
41 return sdbusplus::get_mocked_new(&mock).new_method_call(
42 nullptr, nullptr, nullptr, nullptr);
43 }
44
45 template <typename T> void expect_basic(char type, T val)
46 {
47 EXPECT_CALL(mock, sd_bus_message_read_basic(nullptr, type, testing::_))
48 .WillOnce(DoAll(AssignReadVal<T>(val), Return(0)));
49 }
50
51 void expect_verify_type(char type, const char *contents, int ret)
52 {
53 EXPECT_CALL(mock,
54 sd_bus_message_verify_type(nullptr, type, StrEq(contents)))
55 .WillOnce(Return(ret));
56 }
57
58 void expect_at_end(bool complete, int ret)
59 {
60 EXPECT_CALL(mock, sd_bus_message_at_end(nullptr, complete))
61 .WillOnce(Return(ret));
62 }
63
William A. Kennington III60a72832018-06-26 14:31:15 -070064 void expect_skip(const char *contents)
65 {
66 EXPECT_CALL(mock, sd_bus_message_skip(nullptr, StrEq(contents)))
67 .WillOnce(Return(0));
68 }
69
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -070070 void expect_enter_container(char type, const char *contents)
71 {
72 EXPECT_CALL(mock, sd_bus_message_enter_container(nullptr, type,
73 StrEq(contents)))
74 .WillOnce(Return(0));
75 }
76
77 void expect_exit_container()
78 {
79 EXPECT_CALL(mock, sd_bus_message_exit_container(nullptr))
80 .WillOnce(Return(0));
81 }
82};
83
84TEST_F(ReadTest, Int)
85{
86 const int i = 1;
87 expect_basic<int>(SD_BUS_TYPE_INT32, i);
88 int ret;
89 new_message().read(ret);
90 EXPECT_EQ(i, ret);
91}
92
93TEST_F(ReadTest, Bool)
94{
95 const bool b = true;
96 expect_basic<int>(SD_BUS_TYPE_BOOLEAN, b);
97 bool ret;
98 new_message().read(ret);
99 EXPECT_EQ(b, ret);
100}
101
102TEST_F(ReadTest, Double)
103{
104 const double d = 1.1;
105 expect_basic<double>(SD_BUS_TYPE_DOUBLE, d);
106 double ret;
107 new_message().read(ret);
108 EXPECT_EQ(d, ret);
109}
110
111TEST_F(ReadTest, CString)
112{
113 const char *const s = "asdf";
114 expect_basic<const char *>(SD_BUS_TYPE_STRING, s);
115 const char *ret;
116 new_message().read(ret);
117 EXPECT_EQ(s, ret);
118}
119
120TEST_F(ReadTest, String)
121{
122 const char *const s = "fsda";
123 expect_basic<const char *>(SD_BUS_TYPE_STRING, s);
124 std::string ret;
125 new_message().read(ret);
126 // Pointer comparison here is intentional as we don't expect a copy
127 EXPECT_EQ(s, ret);
128}
129
130TEST_F(ReadTest, ObjectPath)
131{
132 const char *const s = "/fsda";
133 expect_basic<const char *>(SD_BUS_TYPE_OBJECT_PATH, s);
134 sdbusplus::message::object_path ret;
135 new_message().read(ret);
136 EXPECT_EQ(s, ret.str);
137}
138
139TEST_F(ReadTest, Signature)
140{
141 const char *const s = "{ii}";
142 expect_basic<const char *>(SD_BUS_TYPE_SIGNATURE, s);
143 sdbusplus::message::signature ret;
144 new_message().read(ret);
145 EXPECT_EQ(s, ret.str);
146}
147
148TEST_F(ReadTest, CombinedBasic)
149{
150 const double a = 2.2;
151 const char *const b = "ijkd";
152 const bool c = false;
153 const int d = 18;
154
155 {
156 testing::InSequence seq;
157 expect_basic<double>(SD_BUS_TYPE_DOUBLE, a);
158 expect_basic<const char *>(SD_BUS_TYPE_STRING, b);
159 expect_basic<int>(SD_BUS_TYPE_BOOLEAN, c);
160 expect_basic<int>(SD_BUS_TYPE_INT32, d);
161 }
162
163 double ret_a;
164 const char *ret_b;
165 bool ret_c;
166 int ret_d;
167 new_message().read(ret_a, ret_b, ret_c, ret_d);
168 EXPECT_EQ(a, ret_a);
169 EXPECT_EQ(b, ret_b);
170 EXPECT_EQ(c, ret_c);
171 EXPECT_EQ(d, ret_d);
172}
173
174TEST_F(ReadTest, Vector)
175{
176 const std::vector<int> vi{1, 2, 3, 4};
177
178 {
179 testing::InSequence seq;
180 expect_enter_container(SD_BUS_TYPE_ARRAY, "i");
181 for (const auto &i : vi)
Patrick Williams4fe85a32016-09-08 15:03:56 -0500182 {
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -0700183 expect_at_end(false, 0);
184 expect_basic<int>(SD_BUS_TYPE_INT32, i);
Patrick Williams4fe85a32016-09-08 15:03:56 -0500185 }
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -0700186 expect_at_end(false, 1);
187 expect_exit_container();
188 }
Patrick Williams4fe85a32016-09-08 15:03:56 -0500189
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -0700190 std::vector<int> ret_vi;
191 new_message().read(ret_vi);
192 EXPECT_EQ(vi, ret_vi);
193}
194
195TEST_F(ReadTest, Set)
196{
197 const std::set<std::string> ss{"one", "two", "eight"};
198
199 {
200 testing::InSequence seq;
201 expect_enter_container(SD_BUS_TYPE_ARRAY, "s");
202 for (const auto &s : ss)
Patrick Williams4fe85a32016-09-08 15:03:56 -0500203 {
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -0700204 expect_at_end(false, 0);
205 expect_basic<const char *>(SD_BUS_TYPE_STRING, s.c_str());
206 }
207 expect_at_end(false, 1);
208 expect_exit_container();
209 }
Patrick Williams4fe85a32016-09-08 15:03:56 -0500210
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -0700211 std::set<std::string> ret_ss;
212 new_message().read(ret_ss);
213 EXPECT_EQ(ss, ret_ss);
214}
215
216TEST_F(ReadTest, Map)
217{
218 const std::map<int, std::string> mis{
219 {1, "a"},
220 {2, "bc"},
221 {3, "def"},
222 {4, "ghij"},
223 };
224
225 {
226 testing::InSequence seq;
227 expect_enter_container(SD_BUS_TYPE_ARRAY, "{is}");
228 for (const auto &is : mis)
229 {
230 expect_at_end(false, 0);
231 expect_enter_container(SD_BUS_TYPE_DICT_ENTRY, "is");
232 expect_basic<int>(SD_BUS_TYPE_INT32, is.first);
233 expect_basic<const char *>(SD_BUS_TYPE_STRING, is.second.c_str());
234 expect_exit_container();
235 }
236 expect_at_end(false, 1);
237 expect_exit_container();
238 }
239
240 std::map<int, std::string> ret_mis;
241 new_message().read(ret_mis);
242 EXPECT_EQ(mis, ret_mis);
243}
244
245TEST_F(ReadTest, UnorderedMap)
246{
247 const std::unordered_map<int, std::string> mis{
248 {1, "a"},
249 {2, "bc"},
250 {3, "def"},
251 {4, "ghij"},
252 };
253
254 {
255 testing::InSequence seq;
256 expect_enter_container(SD_BUS_TYPE_ARRAY, "{is}");
257 for (const auto &is : mis)
258 {
259 expect_at_end(false, 0);
260 expect_enter_container(SD_BUS_TYPE_DICT_ENTRY, "is");
261 expect_basic<int>(SD_BUS_TYPE_INT32, is.first);
262 expect_basic<const char *>(SD_BUS_TYPE_STRING, is.second.c_str());
263 expect_exit_container();
264 }
265 expect_at_end(false, 1);
266 expect_exit_container();
267 }
268
269 std::unordered_map<int, std::string> ret_mis;
270 new_message().read(ret_mis);
271 EXPECT_EQ(mis, ret_mis);
272}
273
274TEST_F(ReadTest, Tuple)
275{
276 const std::tuple<int, std::string, bool> tisb{3, "hi", false};
277
278 {
279 testing::InSequence seq;
280 expect_enter_container(SD_BUS_TYPE_STRUCT, "isb");
281 expect_basic<int>(SD_BUS_TYPE_INT32, std::get<0>(tisb));
282 expect_basic<const char *>(SD_BUS_TYPE_STRING,
283 std::get<1>(tisb).c_str());
284 expect_basic<int>(SD_BUS_TYPE_BOOLEAN, std::get<2>(tisb));
285 expect_exit_container();
286 }
287
288 std::tuple<int, std::string, bool> ret_tisb;
289 new_message().read(ret_tisb);
290 EXPECT_EQ(tisb, ret_tisb);
291}
292
293TEST_F(ReadTest, Variant)
294{
295 const bool b1 = false;
296 const std::string s2{"asdf"};
297 const sdbusplus::message::variant<int, std::string, bool> v1{b1}, v2{s2};
298
299 {
300 testing::InSequence seq;
301 expect_verify_type(SD_BUS_TYPE_VARIANT, "i", false);
302 expect_verify_type(SD_BUS_TYPE_VARIANT, "s", false);
303 expect_verify_type(SD_BUS_TYPE_VARIANT, "b", true);
304 expect_enter_container(SD_BUS_TYPE_VARIANT, "b");
305 expect_basic<int>(SD_BUS_TYPE_BOOLEAN, b1);
306 expect_exit_container();
307 expect_verify_type(SD_BUS_TYPE_VARIANT, "i", false);
308 expect_verify_type(SD_BUS_TYPE_VARIANT, "s", true);
309 expect_enter_container(SD_BUS_TYPE_VARIANT, "s");
310 expect_basic<const char *>(SD_BUS_TYPE_STRING, s2.c_str());
311 expect_exit_container();
312 }
313
314 sdbusplus::message::variant<int, std::string, bool> ret_v1, ret_v2;
315 new_message().read(ret_v1, ret_v2);
316 EXPECT_EQ(v1, ret_v1);
317 EXPECT_EQ(v2, ret_v2);
318}
319
William A. Kennington III60a72832018-06-26 14:31:15 -0700320TEST_F(ReadTest, VariantSkipUnmatched)
321{
322 {
323 testing::InSequence seq;
324 expect_verify_type(SD_BUS_TYPE_VARIANT, "i", false);
325 expect_verify_type(SD_BUS_TYPE_VARIANT, "b", false);
326 expect_skip("v");
327 }
328 sdbusplus::message::variant<int, bool> ret;
329 new_message().read(ret);
330}
331
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -0700332TEST_F(ReadTest, LargeCombo)
333{
334 const std::vector<std::set<std::string>> vas{
335 {"a", "b", "c"},
336 {"d", "", "e"},
337 };
338 const std::map<std::string, sdbusplus::message::variant<int, double>> msv =
339 {{"a", 3.3}, {"b", 1}, {"c", 4.4}};
340
341 {
342 testing::InSequence seq;
343
344 expect_enter_container(SD_BUS_TYPE_ARRAY, "as");
345 for (const auto &as : vas)
346 {
347 expect_at_end(false, 0);
348 expect_enter_container(SD_BUS_TYPE_ARRAY, "s");
349 for (const auto &s : as)
Patrick Williams4fe85a32016-09-08 15:03:56 -0500350 {
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -0700351 expect_at_end(false, 0);
352 expect_basic<const char *>(SD_BUS_TYPE_STRING, s.c_str());
353 }
354 expect_at_end(false, 1);
355 expect_exit_container();
356 }
357 expect_at_end(false, 1);
358 expect_exit_container();
Patrick Williams4fe85a32016-09-08 15:03:56 -0500359
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -0700360 expect_enter_container(SD_BUS_TYPE_ARRAY, "{sv}");
361 for (const auto &sv : msv)
362 {
363 expect_at_end(false, 0);
364 expect_enter_container(SD_BUS_TYPE_DICT_ENTRY, "sv");
365 expect_basic<const char *>(SD_BUS_TYPE_STRING, sv.first.c_str());
366 if (sv.second.is<int>())
367 {
368 expect_verify_type(SD_BUS_TYPE_VARIANT, "i", true);
369 expect_enter_container(SD_BUS_TYPE_VARIANT, "i");
370 expect_basic<int>(SD_BUS_TYPE_INT32, sv.second.get<int>());
371 expect_exit_container();
Patrick Williams4fe85a32016-09-08 15:03:56 -0500372 }
373 else
374 {
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -0700375 expect_verify_type(SD_BUS_TYPE_VARIANT, "i", false);
376 expect_verify_type(SD_BUS_TYPE_VARIANT, "d", true);
377 expect_enter_container(SD_BUS_TYPE_VARIANT, "d");
378 expect_basic<double>(SD_BUS_TYPE_DOUBLE,
379 sv.second.get<double>());
380 expect_exit_container();
Patrick Williams4fe85a32016-09-08 15:03:56 -0500381 }
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -0700382 expect_exit_container();
Patrick Williams4fe85a32016-09-08 15:03:56 -0500383 }
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -0700384 expect_at_end(false, 1);
385 expect_exit_container();
Patrick Williams4fe85a32016-09-08 15:03:56 -0500386 }
Patrick Williams696e3152016-11-04 17:03:39 -0500387
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -0700388 std::vector<std::set<std::string>> ret_vas;
389 std::map<std::string, sdbusplus::message::variant<int, double>> ret_msv;
390 new_message().read(ret_vas, ret_msv);
391 EXPECT_EQ(vas, ret_vas);
392 EXPECT_EQ(msv, ret_msv);
Patrick Williams4fe85a32016-09-08 15:03:56 -0500393}
394
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -0700395} // namespace