1 #include <systemd/sd-bus-protocol.h>
2
3 #include <sdbusplus/exception.hpp>
4 #include <sdbusplus/message.hpp>
5 #include <sdbusplus/test/sdbus_mock.hpp>
6
7 #include <cerrno>
8 #include <map>
9 #include <set>
10 #include <string>
11 #include <tuple>
12 #include <unordered_map>
13 #include <unordered_set>
14 #include <variant>
15 #include <vector>
16
17 #include <gmock/gmock.h>
18 #include <gtest/gtest.h>
19
20 namespace
21 {
22
23 using testing::DoAll;
24 using testing::Return;
25 using testing::StrEq;
26
ACTION_TEMPLATE(AssignReadVal,HAS_1_TEMPLATE_PARAMS (typename,T),AND_1_VALUE_PARAMS (val))27 ACTION_TEMPLATE(AssignReadVal, HAS_1_TEMPLATE_PARAMS(typename, T),
28 AND_1_VALUE_PARAMS(val))
29 {
30 *static_cast<T*>(arg2) = val;
31 }
32
33 class ReadTest : public testing::Test
34 {
35 protected:
36 testing::StrictMock<sdbusplus::SdBusMock> mock;
37
SetUp()38 void SetUp() override
39 {
40 EXPECT_CALL(mock, sd_bus_message_new_method_call(testing::_, testing::_,
41 nullptr, nullptr,
42 nullptr, nullptr))
43 .WillRepeatedly(Return(0));
44 }
45
new_message()46 sdbusplus::message_t new_message()
47 {
48 return sdbusplus::get_mocked_new(&mock).new_method_call(
49 nullptr, nullptr, nullptr, nullptr);
50 }
51
expect_basic_error(char type,int ret)52 void expect_basic_error(char type, int ret)
53 {
54 EXPECT_CALL(mock, sd_bus_message_read_basic(nullptr, type, testing::_))
55 .WillOnce(Return(ret));
56 }
57
58 template <typename T>
expect_basic(char type,T val)59 void expect_basic(char type, T val)
60 {
61 EXPECT_CALL(mock, sd_bus_message_read_basic(nullptr, type, testing::_))
62 .WillOnce(DoAll(AssignReadVal<T>(val), Return(0)));
63 }
64
expect_verify_type(char type,const char * contents,int ret)65 void expect_verify_type(char type, const char* contents, int ret)
66 {
67 EXPECT_CALL(mock,
68 sd_bus_message_verify_type(nullptr, type, StrEq(contents)))
69 .WillOnce(Return(ret));
70 }
71
expect_at_end(bool complete,int ret)72 void expect_at_end(bool complete, int ret)
73 {
74 EXPECT_CALL(mock, sd_bus_message_at_end(nullptr, complete))
75 .WillOnce(Return(ret));
76 }
77
expect_skip(const char * contents,int ret=0)78 void expect_skip(const char* contents, int ret = 0)
79 {
80 EXPECT_CALL(mock, sd_bus_message_skip(nullptr, StrEq(contents)))
81 .WillOnce(Return(ret));
82 }
83
expect_enter_container(char type,const char * contents,int ret=0)84 void expect_enter_container(char type, const char* contents, int ret = 0)
85 {
86 EXPECT_CALL(mock, sd_bus_message_enter_container(nullptr, type,
87 StrEq(contents)))
88 .WillOnce(Return(ret));
89 }
90
expect_exit_container(int ret=0)91 void expect_exit_container(int ret = 0)
92 {
93 EXPECT_CALL(mock, sd_bus_message_exit_container(nullptr))
94 .WillOnce(Return(ret));
95 }
96 };
97
TEST_F(ReadTest,Int)98 TEST_F(ReadTest, Int)
99 {
100 const int i = 1;
101 expect_basic<int>(SD_BUS_TYPE_INT32, i);
102 int ret;
103 new_message().read(ret);
104 EXPECT_EQ(i, ret);
105 }
106
TEST_F(ReadTest,Bool)107 TEST_F(ReadTest, Bool)
108 {
109 const bool b = true;
110 expect_basic<int>(SD_BUS_TYPE_BOOLEAN, b);
111 bool ret;
112 new_message().read(ret);
113 EXPECT_EQ(b, ret);
114 }
115
TEST_F(ReadTest,Double)116 TEST_F(ReadTest, Double)
117 {
118 const double d = 1.1;
119 expect_basic<double>(SD_BUS_TYPE_DOUBLE, d);
120 double ret;
121 new_message().read(ret);
122 EXPECT_EQ(d, ret);
123 }
124
TEST_F(ReadTest,CString)125 TEST_F(ReadTest, CString)
126 {
127 const char* const s = "asdf";
128 expect_basic<const char*>(SD_BUS_TYPE_STRING, s);
129 const char* ret;
130 new_message().read(ret);
131 EXPECT_EQ(s, ret);
132 }
133
TEST_F(ReadTest,String)134 TEST_F(ReadTest, String)
135 {
136 const char* const s = "fsda";
137 expect_basic<const char*>(SD_BUS_TYPE_STRING, s);
138 std::string ret;
139 new_message().read(ret);
140 // Pointer comparison here is intentional as we don't expect a copy
141 EXPECT_EQ(s, ret);
142 }
143
TEST_F(ReadTest,ObjectPath)144 TEST_F(ReadTest, ObjectPath)
145 {
146 const char* const s = "/fsda";
147 expect_basic<const char*>(SD_BUS_TYPE_OBJECT_PATH, s);
148 sdbusplus::message::object_path ret;
149 new_message().read(ret);
150 EXPECT_EQ(s, ret.str);
151 }
152
TEST_F(ReadTest,Signature)153 TEST_F(ReadTest, Signature)
154 {
155 const char* const s = "{ii}";
156 expect_basic<const char*>(SD_BUS_TYPE_SIGNATURE, s);
157 sdbusplus::message::signature ret;
158 new_message().read(ret);
159 EXPECT_EQ(s, ret.str);
160 }
161
TEST_F(ReadTest,UnixFd)162 TEST_F(ReadTest, UnixFd)
163 {
164 const int fd = 42;
165 expect_basic<int>(SD_BUS_TYPE_UNIX_FD, fd);
166 sdbusplus::message::unix_fd ret;
167 new_message().read(ret);
168 EXPECT_EQ(fd, ret);
169 }
170
TEST_F(ReadTest,CombinedBasic)171 TEST_F(ReadTest, CombinedBasic)
172 {
173 const double a = 2.2;
174 const char* const b = "ijkd";
175 const bool c = false;
176 const int d = 18;
177
178 {
179 testing::InSequence seq;
180 expect_basic<double>(SD_BUS_TYPE_DOUBLE, a);
181 expect_basic<const char*>(SD_BUS_TYPE_STRING, b);
182 expect_basic<int>(SD_BUS_TYPE_BOOLEAN, c);
183 expect_basic<int>(SD_BUS_TYPE_INT32, d);
184 }
185
186 double ret_a;
187 const char* ret_b;
188 bool ret_c;
189 int ret_d;
190 new_message().read(ret_a, ret_b, ret_c, ret_d);
191 EXPECT_EQ(a, ret_a);
192 EXPECT_EQ(b, ret_b);
193 EXPECT_EQ(c, ret_c);
194 EXPECT_EQ(d, ret_d);
195 }
196
TEST_F(ReadTest,BasicError)197 TEST_F(ReadTest, BasicError)
198 {
199 expect_basic_error(SD_BUS_TYPE_INT32, -EINVAL);
200 int ret;
201 EXPECT_THROW(new_message().read(ret), sdbusplus::exception::SdBusError);
202 }
203
TEST_F(ReadTest,BasicStringError)204 TEST_F(ReadTest, BasicStringError)
205 {
206 expect_basic_error(SD_BUS_TYPE_STRING, -EINVAL);
207 std::string ret;
208 EXPECT_THROW(new_message().read(ret), sdbusplus::exception::SdBusError);
209 }
210
TEST_F(ReadTest,BasicStringWrapperError)211 TEST_F(ReadTest, BasicStringWrapperError)
212 {
213 expect_basic_error(SD_BUS_TYPE_SIGNATURE, -EINVAL);
214 sdbusplus::message::signature ret;
215 EXPECT_THROW(new_message().read(ret), sdbusplus::exception::SdBusError);
216 }
217
TEST_F(ReadTest,BasicBoolError)218 TEST_F(ReadTest, BasicBoolError)
219 {
220 expect_basic_error(SD_BUS_TYPE_BOOLEAN, -EINVAL);
221 bool ret;
222 EXPECT_THROW(new_message().read(ret), sdbusplus::exception::SdBusError);
223 }
224
TEST_F(ReadTest,Vector)225 TEST_F(ReadTest, Vector)
226 {
227 const std::vector<int> vi{1, 2, 3, 4};
228
229 {
230 testing::InSequence seq;
231 expect_enter_container(SD_BUS_TYPE_ARRAY, "i");
232 for (const auto& i : vi)
233 {
234 expect_at_end(false, 0);
235 expect_basic<int>(SD_BUS_TYPE_INT32, i);
236 }
237 expect_at_end(false, 1);
238 expect_exit_container();
239 }
240
241 std::vector<int> ret_vi;
242 new_message().read(ret_vi);
243 EXPECT_EQ(vi, ret_vi);
244 }
245
TEST_F(ReadTest,VectorEnterError)246 TEST_F(ReadTest, VectorEnterError)
247 {
248 {
249 testing::InSequence seq;
250 expect_enter_container(SD_BUS_TYPE_ARRAY, "i", -EINVAL);
251 }
252
253 std::vector<int> ret;
254 EXPECT_THROW(new_message().read(ret), sdbusplus::exception::SdBusError);
255 }
256
TEST_F(ReadTest,VectorIterError)257 TEST_F(ReadTest, VectorIterError)
258 {
259 {
260 testing::InSequence seq;
261 expect_enter_container(SD_BUS_TYPE_ARRAY, "i");
262 expect_at_end(false, 0);
263 expect_basic<int>(SD_BUS_TYPE_INT32, 1);
264 expect_at_end(false, -EINVAL);
265 }
266
267 std::vector<int> ret;
268 EXPECT_THROW(new_message().read(ret), sdbusplus::exception::SdBusError);
269 }
270
TEST_F(ReadTest,VectorExitError)271 TEST_F(ReadTest, VectorExitError)
272 {
273 {
274 testing::InSequence seq;
275 expect_enter_container(SD_BUS_TYPE_ARRAY, "i");
276 expect_at_end(false, 0);
277 expect_basic<int>(SD_BUS_TYPE_INT32, 1);
278 expect_at_end(false, 0);
279 expect_basic<int>(SD_BUS_TYPE_INT32, 2);
280 expect_at_end(false, 1);
281 expect_exit_container(-EINVAL);
282 }
283
284 std::vector<int> ret;
285 EXPECT_THROW(new_message().read(ret), sdbusplus::exception::SdBusError);
286 }
287
TEST_F(ReadTest,Set)288 TEST_F(ReadTest, Set)
289 {
290 const std::set<std::string> ss{"one", "two", "eight"};
291
292 {
293 testing::InSequence seq;
294 expect_enter_container(SD_BUS_TYPE_ARRAY, "s");
295 for (const auto& s : ss)
296 {
297 expect_at_end(false, 0);
298 expect_basic<const char*>(SD_BUS_TYPE_STRING, s.c_str());
299 }
300 expect_at_end(false, 1);
301 expect_exit_container();
302 }
303
304 std::set<std::string> ret_ss;
305 new_message().read(ret_ss);
306 EXPECT_EQ(ss, ret_ss);
307 }
308
TEST_F(ReadTest,UnorderedSet)309 TEST_F(ReadTest, UnorderedSet)
310 {
311 const std::unordered_set<std::string> ss{"one", "two", "eight"};
312
313 {
314 testing::InSequence seq;
315 expect_enter_container(SD_BUS_TYPE_ARRAY, "s");
316 for (const auto& s : ss)
317 {
318 expect_at_end(false, 0);
319 expect_basic<const char*>(SD_BUS_TYPE_STRING, s.c_str());
320 }
321 expect_at_end(false, 1);
322 expect_exit_container();
323 }
324
325 std::unordered_set<std::string> ret_ss;
326 new_message().read(ret_ss);
327 EXPECT_EQ(ss, ret_ss);
328 }
329
TEST_F(ReadTest,Map)330 TEST_F(ReadTest, Map)
331 {
332 const std::map<int, std::string> mis{
333 {1, "a"},
334 {2, "bc"},
335 {3, "def"},
336 {4, "ghij"},
337 };
338
339 {
340 testing::InSequence seq;
341 expect_enter_container(SD_BUS_TYPE_ARRAY, "{is}");
342 for (const auto& is : mis)
343 {
344 expect_at_end(false, 0);
345 expect_enter_container(SD_BUS_TYPE_DICT_ENTRY, "is");
346 expect_basic<int>(SD_BUS_TYPE_INT32, is.first);
347 expect_basic<const char*>(SD_BUS_TYPE_STRING, is.second.c_str());
348 expect_exit_container();
349 }
350 expect_at_end(false, 1);
351 expect_exit_container();
352 }
353
354 std::map<int, std::string> ret_mis;
355 new_message().read(ret_mis);
356 EXPECT_EQ(mis, ret_mis);
357 }
358
TEST_F(ReadTest,MapEnterError)359 TEST_F(ReadTest, MapEnterError)
360 {
361 {
362 testing::InSequence seq;
363 expect_enter_container(SD_BUS_TYPE_ARRAY, "{si}", -EINVAL);
364 }
365
366 std::map<std::string, int> ret;
367 EXPECT_THROW(new_message().read(ret), sdbusplus::exception::SdBusError);
368 }
369
TEST_F(ReadTest,MapEntryEnterError)370 TEST_F(ReadTest, MapEntryEnterError)
371 {
372 {
373 testing::InSequence seq;
374 expect_enter_container(SD_BUS_TYPE_ARRAY, "{si}");
375 expect_at_end(false, 0);
376 expect_enter_container(SD_BUS_TYPE_DICT_ENTRY, "si", -EINVAL);
377 }
378
379 std::map<std::string, int> ret;
380 EXPECT_THROW(new_message().read(ret), sdbusplus::exception::SdBusError);
381 }
382
TEST_F(ReadTest,MapEntryExitError)383 TEST_F(ReadTest, MapEntryExitError)
384 {
385 {
386 testing::InSequence seq;
387 expect_enter_container(SD_BUS_TYPE_ARRAY, "{si}");
388 expect_at_end(false, 0);
389 expect_enter_container(SD_BUS_TYPE_DICT_ENTRY, "si");
390 expect_basic<const char*>(SD_BUS_TYPE_STRING, "ab");
391 expect_basic<int>(SD_BUS_TYPE_INT32, 1);
392 expect_exit_container(-EINVAL);
393 }
394
395 std::map<std::string, int> ret;
396 EXPECT_THROW(new_message().read(ret), sdbusplus::exception::SdBusError);
397 }
398
TEST_F(ReadTest,MapIterError)399 TEST_F(ReadTest, MapIterError)
400 {
401 {
402 testing::InSequence seq;
403 expect_enter_container(SD_BUS_TYPE_ARRAY, "{si}");
404 expect_at_end(false, 0);
405 expect_enter_container(SD_BUS_TYPE_DICT_ENTRY, "si");
406 expect_basic<const char*>(SD_BUS_TYPE_STRING, "ab");
407 expect_basic<int>(SD_BUS_TYPE_INT32, 1);
408 expect_exit_container();
409 expect_at_end(false, -EINVAL);
410 }
411
412 std::map<std::string, int> ret;
413 EXPECT_THROW(new_message().read(ret), sdbusplus::exception::SdBusError);
414 }
415
TEST_F(ReadTest,MapExitError)416 TEST_F(ReadTest, MapExitError)
417 {
418 {
419 testing::InSequence seq;
420 expect_enter_container(SD_BUS_TYPE_ARRAY, "{si}");
421 expect_at_end(false, 0);
422 expect_enter_container(SD_BUS_TYPE_DICT_ENTRY, "si");
423 expect_basic<const char*>(SD_BUS_TYPE_STRING, "ab");
424 expect_basic<int>(SD_BUS_TYPE_INT32, 1);
425 expect_exit_container();
426 expect_at_end(false, 1);
427 expect_exit_container(-EINVAL);
428 }
429
430 std::map<std::string, int> ret;
431 EXPECT_THROW(new_message().read(ret), sdbusplus::exception::SdBusError);
432 }
433
TEST_F(ReadTest,UnorderedMap)434 TEST_F(ReadTest, UnorderedMap)
435 {
436 const std::unordered_map<int, std::string> mis{
437 {1, "a"},
438 {2, "bc"},
439 {3, "def"},
440 {4, "ghij"},
441 };
442
443 {
444 testing::InSequence seq;
445 expect_enter_container(SD_BUS_TYPE_ARRAY, "{is}");
446 for (const auto& is : mis)
447 {
448 expect_at_end(false, 0);
449 expect_enter_container(SD_BUS_TYPE_DICT_ENTRY, "is");
450 expect_basic<int>(SD_BUS_TYPE_INT32, is.first);
451 expect_basic<const char*>(SD_BUS_TYPE_STRING, is.second.c_str());
452 expect_exit_container();
453 }
454 expect_at_end(false, 1);
455 expect_exit_container();
456 }
457
458 std::unordered_map<int, std::string> ret_mis;
459 new_message().read(ret_mis);
460 EXPECT_EQ(mis, ret_mis);
461 }
462
TEST_F(ReadTest,Tuple)463 TEST_F(ReadTest, Tuple)
464 {
465 const std::tuple<int, std::string, bool> tisb{3, "hi", false};
466
467 {
468 testing::InSequence seq;
469 expect_enter_container(SD_BUS_TYPE_STRUCT, "isb");
470 expect_basic<int>(SD_BUS_TYPE_INT32, std::get<0>(tisb));
471 expect_basic<const char*>(SD_BUS_TYPE_STRING,
472 std::get<1>(tisb).c_str());
473 expect_basic<int>(SD_BUS_TYPE_BOOLEAN, std::get<2>(tisb));
474 expect_exit_container();
475 }
476
477 std::tuple<int, std::string, bool> ret_tisb;
478 new_message().read(ret_tisb);
479 EXPECT_EQ(tisb, ret_tisb);
480 }
481
TEST_F(ReadTest,TupleEnterError)482 TEST_F(ReadTest, TupleEnterError)
483 {
484 {
485 testing::InSequence seq;
486 expect_enter_container(SD_BUS_TYPE_STRUCT, "bis", -EINVAL);
487 }
488
489 std::tuple<bool, int, std::string> ret;
490 EXPECT_THROW(new_message().read(ret), sdbusplus::exception::SdBusError);
491 }
492
TEST_F(ReadTest,TupleExitError)493 TEST_F(ReadTest, TupleExitError)
494 {
495 {
496 testing::InSequence seq;
497 expect_enter_container(SD_BUS_TYPE_STRUCT, "bis");
498 expect_basic<int>(SD_BUS_TYPE_BOOLEAN, false);
499 expect_basic<int>(SD_BUS_TYPE_INT32, 1);
500 expect_basic<const char*>(SD_BUS_TYPE_STRING, "ab");
501 expect_exit_container(-EINVAL);
502 }
503
504 std::tuple<bool, int, std::string> ret;
505 EXPECT_THROW(new_message().read(ret), sdbusplus::exception::SdBusError);
506 }
507
TEST_F(ReadTest,Variant)508 TEST_F(ReadTest, Variant)
509 {
510 const bool b1 = false;
511 const std::string s2{"asdf"};
512 const std::variant<int, std::string, bool> v1{b1}, v2{s2};
513
514 {
515 testing::InSequence seq;
516 expect_verify_type(SD_BUS_TYPE_VARIANT, "i", false);
517 expect_verify_type(SD_BUS_TYPE_VARIANT, "s", false);
518 expect_verify_type(SD_BUS_TYPE_VARIANT, "b", true);
519 expect_enter_container(SD_BUS_TYPE_VARIANT, "b");
520 expect_basic<int>(SD_BUS_TYPE_BOOLEAN, b1);
521 expect_exit_container();
522 expect_verify_type(SD_BUS_TYPE_VARIANT, "i", false);
523 expect_verify_type(SD_BUS_TYPE_VARIANT, "s", true);
524 expect_enter_container(SD_BUS_TYPE_VARIANT, "s");
525 expect_basic<const char*>(SD_BUS_TYPE_STRING, s2.c_str());
526 expect_exit_container();
527 }
528
529 std::variant<int, std::string, bool> ret_v1, ret_v2;
530 new_message().read(ret_v1, ret_v2);
531 EXPECT_EQ(v1, ret_v1);
532 EXPECT_EQ(v2, ret_v2);
533 }
534
TEST_F(ReadTest,VariantVerifyError)535 TEST_F(ReadTest, VariantVerifyError)
536 {
537 {
538 testing::InSequence seq;
539 expect_verify_type(SD_BUS_TYPE_VARIANT, "i", -EINVAL);
540 }
541
542 std::variant<int, bool> ret;
543 EXPECT_THROW(new_message().read(ret), sdbusplus::exception::SdBusError);
544 }
545
TEST_F(ReadTest,VariantSkipUnmatched)546 TEST_F(ReadTest, VariantSkipUnmatched)
547 {
548 {
549 testing::InSequence seq;
550 expect_verify_type(SD_BUS_TYPE_VARIANT, "i", false);
551 expect_verify_type(SD_BUS_TYPE_VARIANT, "b", false);
552 expect_skip("v");
553 }
554
555 std::variant<int, bool> ret;
556 new_message().read(ret);
557 }
558
TEST_F(ReadTest,VariantSkipError)559 TEST_F(ReadTest, VariantSkipError)
560 {
561 {
562 testing::InSequence seq;
563 expect_verify_type(SD_BUS_TYPE_VARIANT, "i", false);
564 expect_verify_type(SD_BUS_TYPE_VARIANT, "b", false);
565 expect_skip("v", -EINVAL);
566 }
567
568 std::variant<int, bool> ret;
569 EXPECT_THROW(new_message().read(ret), sdbusplus::exception::SdBusError);
570 }
571
TEST_F(ReadTest,VariantEnterError)572 TEST_F(ReadTest, VariantEnterError)
573 {
574 {
575 testing::InSequence seq;
576 expect_verify_type(SD_BUS_TYPE_VARIANT, "i", true);
577 expect_enter_container(SD_BUS_TYPE_VARIANT, "i", -EINVAL);
578 }
579
580 std::variant<int, bool> ret;
581 EXPECT_THROW(new_message().read(ret), sdbusplus::exception::SdBusError);
582 }
583
TEST_F(ReadTest,VariantExitError)584 TEST_F(ReadTest, VariantExitError)
585 {
586 {
587 testing::InSequence seq;
588 expect_verify_type(SD_BUS_TYPE_VARIANT, "i", true);
589 expect_enter_container(SD_BUS_TYPE_VARIANT, "i");
590 expect_basic<int>(SD_BUS_TYPE_INT32, 10);
591 expect_exit_container(-EINVAL);
592 }
593
594 std::variant<int, bool> ret;
595 EXPECT_THROW(new_message().read(ret), sdbusplus::exception::SdBusError);
596 }
597
TEST_F(ReadTest,LargeCombo)598 TEST_F(ReadTest, LargeCombo)
599 {
600 const std::vector<std::set<std::string>> vas{
601 {"a", "b", "c"},
602 {"d", "", "e"},
603 };
604 const std::map<std::string, std::variant<int, double>> msv = {
605 {"a", 3.3}, {"b", 1}, {"c", 4.4}};
606
607 {
608 testing::InSequence seq;
609
610 expect_enter_container(SD_BUS_TYPE_ARRAY, "as");
611 for (const auto& as : vas)
612 {
613 expect_at_end(false, 0);
614 expect_enter_container(SD_BUS_TYPE_ARRAY, "s");
615 for (const auto& s : as)
616 {
617 expect_at_end(false, 0);
618 expect_basic<const char*>(SD_BUS_TYPE_STRING, s.c_str());
619 }
620 expect_at_end(false, 1);
621 expect_exit_container();
622 }
623 expect_at_end(false, 1);
624 expect_exit_container();
625
626 expect_enter_container(SD_BUS_TYPE_ARRAY, "{sv}");
627 for (const auto& sv : msv)
628 {
629 expect_at_end(false, 0);
630 expect_enter_container(SD_BUS_TYPE_DICT_ENTRY, "sv");
631 expect_basic<const char*>(SD_BUS_TYPE_STRING, sv.first.c_str());
632 if (std::holds_alternative<int>(sv.second))
633 {
634 expect_verify_type(SD_BUS_TYPE_VARIANT, "i", true);
635 expect_enter_container(SD_BUS_TYPE_VARIANT, "i");
636 expect_basic<int>(SD_BUS_TYPE_INT32, std::get<int>(sv.second));
637 expect_exit_container();
638 }
639 else
640 {
641 expect_verify_type(SD_BUS_TYPE_VARIANT, "i", false);
642 expect_verify_type(SD_BUS_TYPE_VARIANT, "d", true);
643 expect_enter_container(SD_BUS_TYPE_VARIANT, "d");
644 expect_basic<double>(SD_BUS_TYPE_DOUBLE,
645 std::get<double>(sv.second));
646 expect_exit_container();
647 }
648 expect_exit_container();
649 }
650 expect_at_end(false, 1);
651 expect_exit_container();
652 }
653
654 std::vector<std::set<std::string>> ret_vas;
655 std::map<std::string, std::variant<int, double>> ret_msv;
656 new_message().read(ret_vas, ret_msv);
657 EXPECT_EQ(vas, ret_vas);
658 EXPECT_EQ(msv, ret_msv);
659 }
660
661 // Unpack tests.
662 // Since unpack uses read, we're mostly just testing the compilation.
663 // Duplicate a few tests from Read using 'unpack'.
664
TEST_F(ReadTest,UnpackSingleVector)665 TEST_F(ReadTest, UnpackSingleVector)
666 {
667 const std::vector<int> vi{1, 2, 3, 4};
668
669 {
670 testing::InSequence seq;
671 expect_enter_container(SD_BUS_TYPE_ARRAY, "i");
672 for (const auto& i : vi)
673 {
674 expect_at_end(false, 0);
675 expect_basic<int>(SD_BUS_TYPE_INT32, i);
676 }
677 expect_at_end(false, 1);
678 expect_exit_container();
679 }
680
681 auto ret_vi = new_message().unpack<std::vector<int>>();
682 EXPECT_EQ(vi, ret_vi);
683 }
684
TEST_F(ReadTest,UnpackMultiple)685 TEST_F(ReadTest, UnpackMultiple)
686 {
687 const std::tuple<int, std::string, bool> tisb{3, "hi", false};
688
689 {
690 testing::InSequence seq;
691 expect_basic<int>(SD_BUS_TYPE_INT32, std::get<0>(tisb));
692 expect_basic<const char*>(SD_BUS_TYPE_STRING,
693 std::get<1>(tisb).c_str());
694 expect_basic<int>(SD_BUS_TYPE_BOOLEAN, std::get<2>(tisb));
695 }
696
697 auto ret_tisb = new_message().unpack<int, std::string, bool>();
698 EXPECT_EQ(tisb, ret_tisb);
699 }
700
TEST_F(ReadTest,UnpackStructuredBinding)701 TEST_F(ReadTest, UnpackStructuredBinding)
702 {
703 const std::tuple<int, std::string, bool> tisb{3, "hi", false};
704
705 {
706 testing::InSequence seq;
707 expect_basic<int>(SD_BUS_TYPE_INT32, std::get<0>(tisb));
708 expect_basic<const char*>(SD_BUS_TYPE_STRING,
709 std::get<1>(tisb).c_str());
710 expect_basic<int>(SD_BUS_TYPE_BOOLEAN, std::get<2>(tisb));
711 }
712
713 auto [ret_ti, ret_ts,
714 ret_tb] = new_message().unpack<int, std::string, bool>();
715 EXPECT_EQ(tisb, std::make_tuple(ret_ti, ret_ts, ret_tb));
716 }
717
TEST_F(ReadTest,UnpackVoid)718 TEST_F(ReadTest, UnpackVoid)
719 {
720 new_message().unpack<>();
721 new_message().unpack<void>();
722 }
723
724 } // namespace
725