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