blob: 1b6ae84eb7f020dcbf57f20e04fe88f74629a2c1 [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
64 void expect_enter_container(char type, const char *contents)
65 {
66 EXPECT_CALL(mock, sd_bus_message_enter_container(nullptr, type,
67 StrEq(contents)))
68 .WillOnce(Return(0));
69 }
70
71 void expect_exit_container()
72 {
73 EXPECT_CALL(mock, sd_bus_message_exit_container(nullptr))
74 .WillOnce(Return(0));
75 }
76};
77
78TEST_F(ReadTest, Int)
79{
80 const int i = 1;
81 expect_basic<int>(SD_BUS_TYPE_INT32, i);
82 int ret;
83 new_message().read(ret);
84 EXPECT_EQ(i, ret);
85}
86
87TEST_F(ReadTest, Bool)
88{
89 const bool b = true;
90 expect_basic<int>(SD_BUS_TYPE_BOOLEAN, b);
91 bool ret;
92 new_message().read(ret);
93 EXPECT_EQ(b, ret);
94}
95
96TEST_F(ReadTest, Double)
97{
98 const double d = 1.1;
99 expect_basic<double>(SD_BUS_TYPE_DOUBLE, d);
100 double ret;
101 new_message().read(ret);
102 EXPECT_EQ(d, ret);
103}
104
105TEST_F(ReadTest, CString)
106{
107 const char *const s = "asdf";
108 expect_basic<const char *>(SD_BUS_TYPE_STRING, s);
109 const char *ret;
110 new_message().read(ret);
111 EXPECT_EQ(s, ret);
112}
113
114TEST_F(ReadTest, String)
115{
116 const char *const s = "fsda";
117 expect_basic<const char *>(SD_BUS_TYPE_STRING, s);
118 std::string ret;
119 new_message().read(ret);
120 // Pointer comparison here is intentional as we don't expect a copy
121 EXPECT_EQ(s, ret);
122}
123
124TEST_F(ReadTest, ObjectPath)
125{
126 const char *const s = "/fsda";
127 expect_basic<const char *>(SD_BUS_TYPE_OBJECT_PATH, s);
128 sdbusplus::message::object_path ret;
129 new_message().read(ret);
130 EXPECT_EQ(s, ret.str);
131}
132
133TEST_F(ReadTest, Signature)
134{
135 const char *const s = "{ii}";
136 expect_basic<const char *>(SD_BUS_TYPE_SIGNATURE, s);
137 sdbusplus::message::signature ret;
138 new_message().read(ret);
139 EXPECT_EQ(s, ret.str);
140}
141
142TEST_F(ReadTest, CombinedBasic)
143{
144 const double a = 2.2;
145 const char *const b = "ijkd";
146 const bool c = false;
147 const int d = 18;
148
149 {
150 testing::InSequence seq;
151 expect_basic<double>(SD_BUS_TYPE_DOUBLE, a);
152 expect_basic<const char *>(SD_BUS_TYPE_STRING, b);
153 expect_basic<int>(SD_BUS_TYPE_BOOLEAN, c);
154 expect_basic<int>(SD_BUS_TYPE_INT32, d);
155 }
156
157 double ret_a;
158 const char *ret_b;
159 bool ret_c;
160 int ret_d;
161 new_message().read(ret_a, ret_b, ret_c, ret_d);
162 EXPECT_EQ(a, ret_a);
163 EXPECT_EQ(b, ret_b);
164 EXPECT_EQ(c, ret_c);
165 EXPECT_EQ(d, ret_d);
166}
167
168TEST_F(ReadTest, Vector)
169{
170 const std::vector<int> vi{1, 2, 3, 4};
171
172 {
173 testing::InSequence seq;
174 expect_enter_container(SD_BUS_TYPE_ARRAY, "i");
175 for (const auto &i : vi)
Patrick Williams4fe85a32016-09-08 15:03:56 -0500176 {
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -0700177 expect_at_end(false, 0);
178 expect_basic<int>(SD_BUS_TYPE_INT32, i);
Patrick Williams4fe85a32016-09-08 15:03:56 -0500179 }
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -0700180 expect_at_end(false, 1);
181 expect_exit_container();
182 }
Patrick Williams4fe85a32016-09-08 15:03:56 -0500183
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -0700184 std::vector<int> ret_vi;
185 new_message().read(ret_vi);
186 EXPECT_EQ(vi, ret_vi);
187}
188
189TEST_F(ReadTest, Set)
190{
191 const std::set<std::string> ss{"one", "two", "eight"};
192
193 {
194 testing::InSequence seq;
195 expect_enter_container(SD_BUS_TYPE_ARRAY, "s");
196 for (const auto &s : ss)
Patrick Williams4fe85a32016-09-08 15:03:56 -0500197 {
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -0700198 expect_at_end(false, 0);
199 expect_basic<const char *>(SD_BUS_TYPE_STRING, s.c_str());
200 }
201 expect_at_end(false, 1);
202 expect_exit_container();
203 }
Patrick Williams4fe85a32016-09-08 15:03:56 -0500204
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -0700205 std::set<std::string> ret_ss;
206 new_message().read(ret_ss);
207 EXPECT_EQ(ss, ret_ss);
208}
209
210TEST_F(ReadTest, Map)
211{
212 const std::map<int, std::string> mis{
213 {1, "a"},
214 {2, "bc"},
215 {3, "def"},
216 {4, "ghij"},
217 };
218
219 {
220 testing::InSequence seq;
221 expect_enter_container(SD_BUS_TYPE_ARRAY, "{is}");
222 for (const auto &is : mis)
223 {
224 expect_at_end(false, 0);
225 expect_enter_container(SD_BUS_TYPE_DICT_ENTRY, "is");
226 expect_basic<int>(SD_BUS_TYPE_INT32, is.first);
227 expect_basic<const char *>(SD_BUS_TYPE_STRING, is.second.c_str());
228 expect_exit_container();
229 }
230 expect_at_end(false, 1);
231 expect_exit_container();
232 }
233
234 std::map<int, std::string> ret_mis;
235 new_message().read(ret_mis);
236 EXPECT_EQ(mis, ret_mis);
237}
238
239TEST_F(ReadTest, UnorderedMap)
240{
241 const std::unordered_map<int, std::string> mis{
242 {1, "a"},
243 {2, "bc"},
244 {3, "def"},
245 {4, "ghij"},
246 };
247
248 {
249 testing::InSequence seq;
250 expect_enter_container(SD_BUS_TYPE_ARRAY, "{is}");
251 for (const auto &is : mis)
252 {
253 expect_at_end(false, 0);
254 expect_enter_container(SD_BUS_TYPE_DICT_ENTRY, "is");
255 expect_basic<int>(SD_BUS_TYPE_INT32, is.first);
256 expect_basic<const char *>(SD_BUS_TYPE_STRING, is.second.c_str());
257 expect_exit_container();
258 }
259 expect_at_end(false, 1);
260 expect_exit_container();
261 }
262
263 std::unordered_map<int, std::string> ret_mis;
264 new_message().read(ret_mis);
265 EXPECT_EQ(mis, ret_mis);
266}
267
268TEST_F(ReadTest, Tuple)
269{
270 const std::tuple<int, std::string, bool> tisb{3, "hi", false};
271
272 {
273 testing::InSequence seq;
274 expect_enter_container(SD_BUS_TYPE_STRUCT, "isb");
275 expect_basic<int>(SD_BUS_TYPE_INT32, std::get<0>(tisb));
276 expect_basic<const char *>(SD_BUS_TYPE_STRING,
277 std::get<1>(tisb).c_str());
278 expect_basic<int>(SD_BUS_TYPE_BOOLEAN, std::get<2>(tisb));
279 expect_exit_container();
280 }
281
282 std::tuple<int, std::string, bool> ret_tisb;
283 new_message().read(ret_tisb);
284 EXPECT_EQ(tisb, ret_tisb);
285}
286
287TEST_F(ReadTest, Variant)
288{
289 const bool b1 = false;
290 const std::string s2{"asdf"};
291 const sdbusplus::message::variant<int, std::string, bool> v1{b1}, v2{s2};
292
293 {
294 testing::InSequence seq;
295 expect_verify_type(SD_BUS_TYPE_VARIANT, "i", false);
296 expect_verify_type(SD_BUS_TYPE_VARIANT, "s", false);
297 expect_verify_type(SD_BUS_TYPE_VARIANT, "b", true);
298 expect_enter_container(SD_BUS_TYPE_VARIANT, "b");
299 expect_basic<int>(SD_BUS_TYPE_BOOLEAN, b1);
300 expect_exit_container();
301 expect_verify_type(SD_BUS_TYPE_VARIANT, "i", false);
302 expect_verify_type(SD_BUS_TYPE_VARIANT, "s", true);
303 expect_enter_container(SD_BUS_TYPE_VARIANT, "s");
304 expect_basic<const char *>(SD_BUS_TYPE_STRING, s2.c_str());
305 expect_exit_container();
306 }
307
308 sdbusplus::message::variant<int, std::string, bool> ret_v1, ret_v2;
309 new_message().read(ret_v1, ret_v2);
310 EXPECT_EQ(v1, ret_v1);
311 EXPECT_EQ(v2, ret_v2);
312}
313
314TEST_F(ReadTest, LargeCombo)
315{
316 const std::vector<std::set<std::string>> vas{
317 {"a", "b", "c"},
318 {"d", "", "e"},
319 };
320 const std::map<std::string, sdbusplus::message::variant<int, double>> msv =
321 {{"a", 3.3}, {"b", 1}, {"c", 4.4}};
322
323 {
324 testing::InSequence seq;
325
326 expect_enter_container(SD_BUS_TYPE_ARRAY, "as");
327 for (const auto &as : vas)
328 {
329 expect_at_end(false, 0);
330 expect_enter_container(SD_BUS_TYPE_ARRAY, "s");
331 for (const auto &s : as)
Patrick Williams4fe85a32016-09-08 15:03:56 -0500332 {
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -0700333 expect_at_end(false, 0);
334 expect_basic<const char *>(SD_BUS_TYPE_STRING, s.c_str());
335 }
336 expect_at_end(false, 1);
337 expect_exit_container();
338 }
339 expect_at_end(false, 1);
340 expect_exit_container();
Patrick Williams4fe85a32016-09-08 15:03:56 -0500341
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -0700342 expect_enter_container(SD_BUS_TYPE_ARRAY, "{sv}");
343 for (const auto &sv : msv)
344 {
345 expect_at_end(false, 0);
346 expect_enter_container(SD_BUS_TYPE_DICT_ENTRY, "sv");
347 expect_basic<const char *>(SD_BUS_TYPE_STRING, sv.first.c_str());
348 if (sv.second.is<int>())
349 {
350 expect_verify_type(SD_BUS_TYPE_VARIANT, "i", true);
351 expect_enter_container(SD_BUS_TYPE_VARIANT, "i");
352 expect_basic<int>(SD_BUS_TYPE_INT32, sv.second.get<int>());
353 expect_exit_container();
Patrick Williams4fe85a32016-09-08 15:03:56 -0500354 }
355 else
356 {
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -0700357 expect_verify_type(SD_BUS_TYPE_VARIANT, "i", false);
358 expect_verify_type(SD_BUS_TYPE_VARIANT, "d", true);
359 expect_enter_container(SD_BUS_TYPE_VARIANT, "d");
360 expect_basic<double>(SD_BUS_TYPE_DOUBLE,
361 sv.second.get<double>());
362 expect_exit_container();
Patrick Williams4fe85a32016-09-08 15:03:56 -0500363 }
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -0700364 expect_exit_container();
Patrick Williams4fe85a32016-09-08 15:03:56 -0500365 }
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -0700366 expect_at_end(false, 1);
367 expect_exit_container();
Patrick Williams4fe85a32016-09-08 15:03:56 -0500368 }
Patrick Williams696e3152016-11-04 17:03:39 -0500369
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -0700370 std::vector<std::set<std::string>> ret_vas;
371 std::map<std::string, sdbusplus::message::variant<int, double>> ret_msv;
372 new_message().read(ret_vas, ret_msv);
373 EXPECT_EQ(vas, ret_vas);
374 EXPECT_EQ(msv, ret_msv);
Patrick Williams4fe85a32016-09-08 15:03:56 -0500375}
376
William A. Kennington IIIb4b4fa12018-06-25 17:20:06 -0700377} // namespace