1 #include <iostream> 2 #include <cassert> 3 #include <sdbusplus/message.hpp> 4 #include <sdbusplus/bus.hpp> 5 6 // Global to share the dbus type string between client and server. 7 static std::string verifyTypeString; 8 9 using verifyCallback_t = void(*)(sdbusplus::message::message&); 10 verifyCallback_t verifyCallback = nullptr; 11 12 static constexpr auto SERVICE = "sdbusplus.test.message.read"; 13 static constexpr auto INTERFACE = SERVICE; 14 static constexpr auto TEST_METHOD = "test"; 15 static constexpr auto QUIT_METHOD = "quit"; 16 17 // Open up the sdbus and claim SERVICE name. 18 auto serverInit() 19 { 20 auto b = sdbusplus::bus::new_default(); 21 b.request_name(SERVICE); 22 23 return std::move(b); 24 } 25 26 // Thread to run the dbus server. 27 void* server(void* b) 28 { 29 auto bus = sdbusplus::bus::bus(reinterpret_cast<sdbusplus::bus::busp_t>(b)); 30 31 while(1) 32 { 33 // Wait for messages. 34 auto m = bus.process(); 35 36 if(!m) 37 { 38 bus.wait(); 39 continue; 40 } 41 42 if (m.is_method_call(INTERFACE, TEST_METHOD)) 43 { 44 // Verify the message type matches what the test expects. 45 assert(verifyTypeString == m.get_signature()); 46 47 if (verifyCallback) 48 { 49 50 verifyCallback(m); 51 verifyCallback = nullptr; 52 } 53 else 54 { 55 std::cout << "Warning: No verification for " 56 << verifyTypeString << std::endl; 57 } 58 // Reply to client. 59 sd_bus_reply_method_return(m.release(), nullptr); 60 } 61 else if (m.is_method_call(INTERFACE, QUIT_METHOD)) 62 { 63 // Reply and exit. 64 sd_bus_reply_method_return(m.release(), nullptr); 65 break; 66 } 67 } 68 69 return nullptr; 70 } 71 72 auto newMethodCall__test(sdbusplus::bus::bus& b) 73 { 74 // Allocate a method-call message for INTERFACE,TEST_METHOD. 75 return b.new_method_call(SERVICE, "/", INTERFACE, TEST_METHOD); 76 } 77 78 void runTests() 79 { 80 using namespace std::literals; 81 82 auto b = sdbusplus::bus::new_default(); 83 84 // Test r-value int. 85 { 86 auto m = newMethodCall__test(b); 87 m.append(1); 88 verifyTypeString = "i"; 89 90 struct verify 91 { 92 static void op(sdbusplus::message::message& m) 93 { 94 int32_t i = 0; 95 m.read(i); 96 assert(i == 1); 97 } 98 }; 99 verifyCallback = &verify::op; 100 101 b.call_noreply(m); 102 } 103 // Test l-value int. 104 { 105 auto m = newMethodCall__test(b); 106 int a = 1; 107 m.append(a, a); 108 verifyTypeString = "ii"; 109 110 struct verify 111 { 112 static void op(sdbusplus::message::message& m) 113 { 114 int32_t a = 0, b = 0; 115 m.read(a, b); 116 assert(a == 1); 117 assert(b == 1); 118 } 119 }; 120 verifyCallback = &verify::op; 121 122 b.call_noreply(m); 123 } 124 125 // Test multiple ints. 126 { 127 auto m = newMethodCall__test(b); 128 m.append(1, 2, 3, 4, 5); 129 verifyTypeString = "iiiii"; 130 131 struct verify 132 { 133 static void op(sdbusplus::message::message& m) 134 { 135 int32_t a = 0, b = 0, c = 0, d = 0, e = 0; 136 m.read(a,b,c,d,e); 137 assert(a == 1); 138 assert(b == 2); 139 assert(c == 3); 140 assert(d == 4); 141 assert(e == 5); 142 } 143 }; 144 verifyCallback = &verify::op; 145 146 b.call_noreply(m); 147 } 148 149 // Test double and bool. 150 { 151 auto m = newMethodCall__test(b); 152 bool t = true; 153 bool f = false; 154 bool f2 = false; 155 m.append(t, true, f, std::move(f2), false, 1.1); 156 verifyTypeString = "bbbbbd"; 157 158 struct verify 159 { 160 static void op(sdbusplus::message::message& m) 161 { 162 bool t1, t2, f1, f2, f3; 163 double d; 164 m.read(t1, t2, f1, f2, f3, d); 165 assert(t1); 166 assert(t2); 167 assert(!f1); 168 assert(!f2); 169 assert(!f3); 170 assert(d == 1.1); 171 } 172 }; 173 verifyCallback = &verify::op; 174 175 b.call_noreply(m); 176 } 177 178 // Test r-value string. 179 { 180 auto m = newMethodCall__test(b); 181 m.append("asdf"s); 182 verifyTypeString = "s"; 183 184 struct verify 185 { 186 static void op(sdbusplus::message::message& m) 187 { 188 const char* s = nullptr; 189 m.read(s); 190 assert(0 == strcmp("asdf", s)); 191 } 192 }; 193 verifyCallback = &verify::op; 194 195 b.call_noreply(m); 196 } 197 198 // Test multiple strings, various forms. 199 { 200 auto m = newMethodCall__test(b); 201 auto str = "jkl;"s; 202 auto str2 = "JKL:"s; 203 m.append(1, "asdf", "ASDF"s, str, 204 std::move(str2), 5); 205 verifyTypeString = "issssi"; 206 207 struct verify 208 { 209 static void op(sdbusplus::message::message& m) 210 { 211 int32_t a = 0, b = 0; 212 std::string s0, s1, s2, s3; 213 m.read(a, s0, s1, s2, s3, b); 214 assert(a == 1); 215 assert(b == 5); 216 assert(s0 == "asdf"s); 217 assert(s1 == "ASDF"s); 218 assert(s2 == "jkl;"s); 219 assert(s3 == "JKL:"); 220 } 221 }; 222 verifyCallback = &verify::op; 223 224 b.call_noreply(m); 225 } 226 227 // Test object_path and signature. 228 { 229 auto m = newMethodCall__test(b); 230 auto o = sdbusplus::message::object_path("/asdf"); 231 auto s = sdbusplus::message::signature("iii"); 232 m.append(1, o, s, 4); 233 verifyTypeString = "iogi"; 234 235 struct verify 236 { 237 static void op(sdbusplus::message::message& m) 238 { 239 int32_t a = 0, b = 0; 240 sdbusplus::message::object_path o; 241 sdbusplus::message::signature s; 242 m.read(a, o, s, b); 243 assert(a == 1); 244 assert(b == 4); 245 assert(std::string(o) == "/asdf"s); 246 assert(std::string(s) == "iii"s); 247 } 248 }; 249 verifyCallback = &verify::op; 250 251 b.call_noreply(m); 252 } 253 254 255 // Test vector. 256 { 257 auto m = newMethodCall__test(b); 258 std::vector<std::string> s{ "1", "2", "3"}; 259 m.append(1, s, 2); 260 verifyTypeString = "iasi"; 261 262 struct verify 263 { 264 static void op(sdbusplus::message::message& m) 265 { 266 int32_t a = 0; 267 std::vector<std::string> s; 268 m.read(a, s); 269 assert(a == 1); 270 assert(s[0] == "1"); 271 assert(s[1] == "2"); 272 assert(s[2] == "3"); 273 decltype(s) s2 = { "1" , "2" , "3" }; 274 assert(s == s2); 275 } 276 }; 277 verifyCallback = &verify::op; 278 279 b.call_noreply(m); 280 } 281 282 // Test map. 283 { 284 auto m = newMethodCall__test(b); 285 std::map<std::string, int> s = { { "asdf", 3 }, { "jkl;", 4 } }; 286 m.append(1, s, 2); 287 verifyTypeString = "ia{si}i"; 288 289 struct verify 290 { 291 static void op(sdbusplus::message::message& m) 292 { 293 int32_t a = 0, b = 0; 294 std::map<std::string, int> s{}; 295 296 m.read(a, s, b); 297 assert(a == 1); 298 assert(s.size() == 2); 299 assert(s["asdf"] == 3); 300 assert(s["jkl;"] == 4); 301 assert(b == 2); 302 } 303 }; 304 verifyCallback = &verify::op; 305 306 b.call_noreply(m); 307 } 308 309 // Test tuple. 310 { 311 auto m = newMethodCall__test(b); 312 std::tuple<int, double, std::string> a{ 3, 4.1, "asdf" }; 313 m.append(1, a, 2); 314 verifyTypeString = "i(ids)i"; 315 316 struct verify 317 { 318 static void op(sdbusplus::message::message& m) 319 { 320 int32_t a = 0, b = 0; 321 std::tuple<int, double, std::string> c{}; 322 323 m.read(a, c, b); 324 assert(a == 1); 325 assert(b == 2); 326 assert(c == std::make_tuple(3, 4.1, "asdf"s)); 327 } 328 }; 329 verifyCallback = &verify::op; 330 331 b.call_noreply(m); 332 } 333 334 // Test variant. 335 { 336 auto m = newMethodCall__test(b); 337 sdbusplus::message::variant<int, double> a1{3.1}, a2{4}; 338 m.append(1, a1, a2, 2); 339 verifyTypeString = "ivvi"; 340 341 struct verify 342 { 343 static void op(sdbusplus::message::message& m) 344 { 345 int32_t a, b; 346 sdbusplus::message::variant<int, double> a1{}, a2{}; 347 348 m.read(a, a1, a2, b); 349 assert(a == 1); 350 assert(a1 == 3.1); 351 assert(a2 == 4); 352 assert(b == 2); 353 } 354 }; 355 verifyCallback = &verify::op; 356 357 b.call_noreply(m); 358 } 359 360 // Test variant with missing/wrong type. 361 { 362 auto m = newMethodCall__test(b); 363 sdbusplus::message::variant<uint64_t, double> a1{3.1}, a2{uint64_t(4)}; 364 m.append(1, a1, a2, 2); 365 verifyTypeString = "ivvi"; 366 367 struct verify 368 { 369 static void op(sdbusplus::message::message& m) 370 { 371 int32_t a, b; 372 sdbusplus::message::variant<uint8_t, double> a1{}, a2{}; 373 374 m.read(a, a1, a2, b); 375 assert(a == 1); 376 assert(a1 == 3.1); 377 assert(a2 == uint8_t()); 378 assert(b == 2); 379 } 380 }; 381 verifyCallback = &verify::op; 382 383 b.call_noreply(m); 384 } 385 386 // Test map-variant. 387 { 388 auto m = newMethodCall__test(b); 389 std::map<std::string, sdbusplus::message::variant<int, double>> a1 = 390 { { "asdf", 3 }, { "jkl;", 4.1 } }; 391 m.append(1, a1, 2); 392 verifyTypeString = "ia{sv}i"; 393 394 struct verify 395 { 396 static void op(sdbusplus::message::message& m) 397 { 398 int32_t a = 0, b = 0; 399 std::map<std::string, 400 sdbusplus::message::variant<int, double>> a1{}; 401 402 m.read(a, a1, b); 403 assert(a == 1); 404 assert(a1["asdf"] == 3); 405 assert(a1["jkl;"] == 4.1); 406 assert(b == 2); 407 } 408 }; 409 verifyCallback = &verify::op; 410 411 b.call_noreply(m); 412 } 413 414 415 // Shutdown server. 416 { 417 auto m = b.new_method_call(SERVICE, "/", INTERFACE, QUIT_METHOD); 418 b.call_noreply(m); 419 } 420 } 421 422 int main() 423 { 424 425 // Initialize and start server thread. 426 pthread_t t; 427 { 428 auto b = serverInit(); 429 pthread_create(&t, NULL, server, b.release()); 430 } 431 432 runTests(); 433 434 // Wait for server thread to exit. 435 pthread_join(t, NULL); 436 437 return 0; 438 } 439