blob: 7782f02625764f2c65b799ce4134dc35ccfba5a5 [file] [log] [blame]
Patrick Williams1807fa42016-08-01 22:23:30 -05001#include <iostream>
Patrick Williams1807fa42016-08-01 22:23:30 -05002#include <cassert>
Patrick Williams7802c072016-09-02 15:20:22 -05003#include <sdbusplus/message.hpp>
Patrick Williams5b485792016-08-02 07:35:14 -05004#include <sdbusplus/bus.hpp>
Patrick Williams1807fa42016-08-01 22:23:30 -05005
6// Global to share the dbus type string between client and server.
7static std::string verifyTypeString;
8
Andrew Geissler072da3e2018-01-18 07:21:42 -08009using verifyCallback_t = void (*)(sd_bus_message*);
Patrick Williams07e1d6f2016-09-08 15:54:09 -050010verifyCallback_t verifyCallback = nullptr;
11
Patrick Williams24fb2962016-11-04 17:08:59 -050012static constexpr auto SERVICE = "sdbusplus.test.message.append";
Patrick Williams1807fa42016-08-01 22:23:30 -050013static constexpr auto INTERFACE = SERVICE;
14static constexpr auto TEST_METHOD = "test";
15static constexpr auto QUIT_METHOD = "quit";
16
17// Open up the sdbus and claim SERVICE name.
Patrick Williams5b485792016-08-02 07:35:14 -050018auto serverInit()
Patrick Williams1807fa42016-08-01 22:23:30 -050019{
Patrick Williams5b485792016-08-02 07:35:14 -050020 auto b = sdbusplus::bus::new_default();
21 b.request_name(SERVICE);
22
23 return std::move(b);
Patrick Williams1807fa42016-08-01 22:23:30 -050024}
25
26// Thread to run the dbus server.
27void* server(void* b)
28{
Patrick Williams5b485792016-08-02 07:35:14 -050029 auto bus = sdbusplus::bus::bus(reinterpret_cast<sdbusplus::bus::busp_t>(b));
Patrick Williams1807fa42016-08-01 22:23:30 -050030
Andrew Geissler072da3e2018-01-18 07:21:42 -080031 while (1)
Patrick Williams1807fa42016-08-01 22:23:30 -050032 {
33 // Wait for messages.
Patrick Williams13b97c52016-09-09 09:36:55 -050034 auto m = bus.process().release();
Patrick Williams1807fa42016-08-01 22:23:30 -050035
Andrew Geissler072da3e2018-01-18 07:21:42 -080036 if (m == nullptr)
Patrick Williams1807fa42016-08-01 22:23:30 -050037 {
Patrick Williams5b485792016-08-02 07:35:14 -050038 bus.wait();
Patrick Williams1807fa42016-08-01 22:23:30 -050039 continue;
40 }
41
42 if (sd_bus_message_is_method_call(m, INTERFACE, TEST_METHOD))
43 {
44 // Verify the message type matches what the test expects.
Patrick Williams1807fa42016-08-01 22:23:30 -050045 assert(verifyTypeString == sd_bus_message_get_signature(m, true));
Patrick Williams07e1d6f2016-09-08 15:54:09 -050046 if (verifyCallback)
47 {
48 verifyCallback(m);
49 verifyCallback = nullptr;
50 }
51 else
52 {
Andrew Geissler072da3e2018-01-18 07:21:42 -080053 std::cout << "Warning: No verification for " << verifyTypeString
54 << std::endl;
Patrick Williams07e1d6f2016-09-08 15:54:09 -050055 }
Patrick Williams1807fa42016-08-01 22:23:30 -050056 // Reply to client.
57 sd_bus_reply_method_return(m, nullptr);
58 }
59 else if (sd_bus_message_is_method_call(m, INTERFACE, QUIT_METHOD))
60 {
61 // Reply and exit.
62 sd_bus_reply_method_return(m, nullptr);
63 break;
64 }
65 }
Patrick Williams696e3152016-11-04 17:03:39 -050066
67 return nullptr;
Patrick Williams1807fa42016-08-01 22:23:30 -050068}
69
Patrick Williams7802c072016-09-02 15:20:22 -050070auto newMethodCall__test(sdbusplus::bus::bus& b)
Patrick Williams1807fa42016-08-01 22:23:30 -050071{
72 // Allocate a method-call message for INTERFACE,TEST_METHOD.
Patrick Williams7802c072016-09-02 15:20:22 -050073 return b.new_method_call(SERVICE, "/", INTERFACE, TEST_METHOD);
Patrick Williams1807fa42016-08-01 22:23:30 -050074}
75
76void runTests()
77{
78 using namespace std::literals;
79
Patrick Williams5b485792016-08-02 07:35:14 -050080 auto b = sdbusplus::bus::new_default();
Patrick Williams1807fa42016-08-01 22:23:30 -050081
82 // Test r-value int.
83 {
Patrick Williams7802c072016-09-02 15:20:22 -050084 auto m = newMethodCall__test(b);
85 m.append(1);
Patrick Williams1807fa42016-08-01 22:23:30 -050086 verifyTypeString = "i";
Patrick Williams07e1d6f2016-09-08 15:54:09 -050087
88 struct verify
89 {
90 static void op(sd_bus_message* m)
91 {
92 int32_t i = 0;
93 sd_bus_message_read_basic(m, 'i', &i);
94 assert(i == 1);
95 }
96 };
97 verifyCallback = &verify::op;
98
Patrick Williams5b485792016-08-02 07:35:14 -050099 b.call_noreply(m);
Patrick Williams1807fa42016-08-01 22:23:30 -0500100 }
Patrick Williams1807fa42016-08-01 22:23:30 -0500101 // Test l-value int.
102 {
Patrick Williams7802c072016-09-02 15:20:22 -0500103 auto m = newMethodCall__test(b);
Patrick Williams1807fa42016-08-01 22:23:30 -0500104 int a = 1;
Patrick Williams7802c072016-09-02 15:20:22 -0500105 m.append(a, a);
Patrick Williams1807fa42016-08-01 22:23:30 -0500106 verifyTypeString = "ii";
Patrick Williams07e1d6f2016-09-08 15:54:09 -0500107
108 struct verify
109 {
110 static void op(sd_bus_message* m)
111 {
112 int32_t a = 0, b = 0;
113 sd_bus_message_read(m, "ii", &a, &b);
114 assert(a == 1);
115 assert(b == 1);
116 }
117 };
118 verifyCallback = &verify::op;
119
Patrick Williams5b485792016-08-02 07:35:14 -0500120 b.call_noreply(m);
Patrick Williams1807fa42016-08-01 22:23:30 -0500121 }
122
123 // Test multiple ints.
124 {
Patrick Williams7802c072016-09-02 15:20:22 -0500125 auto m = newMethodCall__test(b);
126 m.append(1, 2, 3, 4, 5);
Patrick Williams1807fa42016-08-01 22:23:30 -0500127 verifyTypeString = "iiiii";
Patrick Williams07e1d6f2016-09-08 15:54:09 -0500128
129 struct verify
130 {
131 static void op(sd_bus_message* m)
132 {
133 int32_t a = 0, b = 0, c = 0, d = 0, e = 0;
134 sd_bus_message_read(m, "iiiii", &a, &b, &c, &d, &e);
135 assert(a == 1);
136 assert(b == 2);
137 assert(c == 3);
138 assert(d == 4);
139 assert(e == 5);
140 }
141 };
142 verifyCallback = &verify::op;
143
Patrick Williams5b485792016-08-02 07:35:14 -0500144 b.call_noreply(m);
Patrick Williams1807fa42016-08-01 22:23:30 -0500145 }
146
Patrick Williams9e3b51e2016-10-18 07:47:29 -0500147 // Test double and bool.
148 {
149 auto m = newMethodCall__test(b);
150 bool t = true;
Patrick Williamsb760a992016-11-28 11:26:55 -0600151 bool f = false;
152 bool f2 = false;
153 m.append(t, true, f, std::move(f2), false, 1.1);
154 verifyTypeString = "bbbbbd";
Patrick Williams9e3b51e2016-10-18 07:47:29 -0500155
156 struct verify
157 {
158 static void op(sd_bus_message* m)
159 {
Patrick Williamsb760a992016-11-28 11:26:55 -0600160 bool t1, t2, f1, f2, f3;
Patrick Williams9e3b51e2016-10-18 07:47:29 -0500161 double d;
Patrick Williamsb760a992016-11-28 11:26:55 -0600162 sd_bus_message_read(m, "bbbbbd", &t1, &t2, &f1, &f2, &f3, &d);
Patrick Williams9e3b51e2016-10-18 07:47:29 -0500163 assert(t1);
164 assert(t2);
165 assert(!f1);
Patrick Williamsb760a992016-11-28 11:26:55 -0600166 assert(!f2);
167 assert(!f3);
Patrick Williams9e3b51e2016-10-18 07:47:29 -0500168 assert(d == 1.1);
169 }
170 };
171 verifyCallback = &verify::op;
172
173 b.call_noreply(m);
174 }
175
Patrick Williams1807fa42016-08-01 22:23:30 -0500176 // Test r-value string.
177 {
Patrick Williams7802c072016-09-02 15:20:22 -0500178 auto m = newMethodCall__test(b);
179 m.append("asdf"s);
Patrick Williams1807fa42016-08-01 22:23:30 -0500180 verifyTypeString = "s";
Patrick Williams07e1d6f2016-09-08 15:54:09 -0500181
182 struct verify
183 {
184 static void op(sd_bus_message* m)
185 {
186 const char* s = nullptr;
187 sd_bus_message_read_basic(m, 's', &s);
188 assert(0 == strcmp("asdf", s));
189 }
190 };
191 verifyCallback = &verify::op;
192
Patrick Williams5b485792016-08-02 07:35:14 -0500193 b.call_noreply(m);
Patrick Williams1807fa42016-08-01 22:23:30 -0500194 }
195
Patrick Williams16e17532017-02-15 10:23:22 -0600196 // Test const string owned by const struct. openbmc/openbmc#1025
197 {
198 struct
199 {
200 const char* foo;
201
202 void insert(sdbusplus::message::message& m)
203 {
204 m.append(foo);
205 }
206 } s;
207
208 auto m = newMethodCall__test(b);
209 s.foo = "1234";
210 s.insert(m);
211
212 verifyTypeString = "s";
213
214 struct verify
215 {
216 static void op(sd_bus_message* m)
217 {
218 const char* s = nullptr;
219 sd_bus_message_read_basic(m, 's', &s);
220 assert(0 == strcmp("1234", s));
221 }
222 };
223 verifyCallback = &verify::op;
224
225 b.call_noreply(m);
226 }
227
Patrick Williams1807fa42016-08-01 22:23:30 -0500228 // Test multiple strings, various forms.
229 {
Patrick Williams7802c072016-09-02 15:20:22 -0500230 auto m = newMethodCall__test(b);
Patrick Williams1807fa42016-08-01 22:23:30 -0500231 auto str = "jkl;"s;
232 auto str2 = "JKL:"s;
Patrick Williams16e17532017-02-15 10:23:22 -0600233 const char* str3 = "1234";
234 const char* const str4 = "5678";
235 const auto str5 = "!@#$";
Andrew Geissler072da3e2018-01-18 07:21:42 -0800236 m.append(1, "asdf", "ASDF"s, str, std::move(str2), str3, str4, str5, 5);
Patrick Williams16e17532017-02-15 10:23:22 -0600237 verifyTypeString = "isssssssi";
Patrick Williams07e1d6f2016-09-08 15:54:09 -0500238
239 struct verify
240 {
241 static void op(sd_bus_message* m)
242 {
243 int32_t a = 0, b = 0;
244 const char *s0 = nullptr, *s1 = nullptr, *s2 = nullptr,
Patrick Williams16e17532017-02-15 10:23:22 -0600245 *s3 = nullptr, *s4 = nullptr, *s5 = nullptr,
246 *s6 = nullptr;
Andrew Geissler072da3e2018-01-18 07:21:42 -0800247 sd_bus_message_read(m, "isssssssi", &a, &s0, &s1, &s2, &s3, &s4,
248 &s5, &s6, &b);
Patrick Williams07e1d6f2016-09-08 15:54:09 -0500249 assert(a == 1);
250 assert(b == 5);
251 assert(0 == strcmp("asdf", s0));
252 assert(0 == strcmp("ASDF", s1));
253 assert(0 == strcmp("jkl;", s2));
254 assert(0 == strcmp("JKL:", s3));
Patrick Williams16e17532017-02-15 10:23:22 -0600255 assert(0 == strcmp("1234", s4));
256 assert(0 == strcmp("5678", s5));
257 assert(0 == strcmp("!@#$", s6));
258 assert(b == 5);
Patrick Williams07e1d6f2016-09-08 15:54:09 -0500259 }
260 };
261 verifyCallback = &verify::op;
262
Patrick Williams5b485792016-08-02 07:35:14 -0500263 b.call_noreply(m);
Patrick Williams1807fa42016-08-01 22:23:30 -0500264 }
265
Patrick Williamsfd3c4622017-01-06 16:11:47 -0600266 // Test object_path and signature.
267 {
268 auto m = newMethodCall__test(b);
269 auto o = sdbusplus::message::object_path("/asdf");
270 auto s = sdbusplus::message::signature("iii");
271 m.append(1, o, s, 4);
272 verifyTypeString = "iogi";
273
274 struct verify
275 {
276 static void op(sd_bus_message* m)
277 {
278 int32_t a = 0, b = 0;
279 const char *s0 = nullptr, *s1 = nullptr;
280 sd_bus_message_read(m, "iogi", &a, &s0, &s1, &b);
281 assert(a == 1);
282 assert(b == 4);
283 assert(0 == strcmp("/asdf", s0));
284 assert(0 == strcmp("iii", s1));
Patrick Williamsfd3c4622017-01-06 16:11:47 -0600285 }
286 };
287 verifyCallback = &verify::op;
288
289 b.call_noreply(m);
290 }
291
Patrick Williams930460c2016-07-20 17:52:55 -0500292 // Test vector.
293 {
294 auto m = newMethodCall__test(b);
Andrew Geissler072da3e2018-01-18 07:21:42 -0800295 std::vector<std::string> s{"1", "2", "3"};
Patrick Williams930460c2016-07-20 17:52:55 -0500296 m.append(1, s, 2);
297 verifyTypeString = "iasi";
298
299 struct verify
300 {
301 static void op(sd_bus_message* m)
302 {
303 int32_t a = 0;
304 sd_bus_message_read(m, "i", &a);
305 assert(a == 1);
306
Andrew Geissler072da3e2018-01-18 07:21:42 -0800307 auto rc =
308 sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
Patrick Williams930460c2016-07-20 17:52:55 -0500309 assert(0 <= rc);
310
311 const char* s = nullptr;
312 sd_bus_message_read_basic(m, 's', &s);
313 assert(0 == strcmp("1", s));
314 sd_bus_message_read_basic(m, 's', &s);
315 assert(0 == strcmp("2", s));
316 sd_bus_message_read_basic(m, 's', &s);
317 assert(0 == strcmp("3", s));
318 assert(1 == sd_bus_message_at_end(m, false));
319
320 sd_bus_message_exit_container(m);
321
322 sd_bus_message_read(m, "i", &a);
323 assert(a == 2);
Patrick Williams930460c2016-07-20 17:52:55 -0500324 }
325 };
326 verifyCallback = &verify::op;
327
Patrick Williams930460c2016-07-20 17:52:55 -0500328 b.call_noreply(m);
329 }
330
Patrick Williamsbbe0e432016-09-10 08:57:03 -0500331 // Test map.
332 {
333 auto m = newMethodCall__test(b);
Andrew Geissler072da3e2018-01-18 07:21:42 -0800334 std::map<std::string, int> s = {{"asdf", 3}, {"jkl;", 4}};
Patrick Williamsbbe0e432016-09-10 08:57:03 -0500335 m.append(1, s, 2);
336 verifyTypeString = "ia{si}i";
337
338 struct verify
339 {
340 static void op(sd_bus_message* m)
341 {
342 int32_t a = 0;
343 sd_bus_message_read(m, "i", &a);
344 assert(a == 1);
345
Andrew Geissler072da3e2018-01-18 07:21:42 -0800346 auto rc = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY,
Patrick Williamsbbe0e432016-09-10 08:57:03 -0500347 "{si}");
348 assert(0 <= rc);
349
Andrew Geissler072da3e2018-01-18 07:21:42 -0800350 rc = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY,
Patrick Williamsbbe0e432016-09-10 08:57:03 -0500351 "si");
352 assert(0 <= rc);
353
354 const char* s = nullptr;
355 sd_bus_message_read_basic(m, 's', &s);
356 assert(0 == strcmp("asdf", s));
357 sd_bus_message_read_basic(m, 'i', &a);
358 assert(a == 3);
359
360 assert(1 == sd_bus_message_at_end(m, false));
361 sd_bus_message_exit_container(m);
362
Andrew Geissler072da3e2018-01-18 07:21:42 -0800363 rc = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY,
Patrick Williamsbbe0e432016-09-10 08:57:03 -0500364 "si");
365 assert(0 <= rc);
366
367 sd_bus_message_read_basic(m, 's', &s);
368 assert(0 == strcmp("jkl;", s));
369 sd_bus_message_read_basic(m, 'i', &a);
370 assert(a == 4);
371
372 assert(1 == sd_bus_message_at_end(m, false));
373 sd_bus_message_exit_container(m);
374
375 assert(1 == sd_bus_message_at_end(m, false));
376 sd_bus_message_exit_container(m);
377
378 sd_bus_message_read(m, "i", &a);
379 assert(a == 2);
380 }
381 };
382 verifyCallback = &verify::op;
383
384 b.call_noreply(m);
385 }
386
Patrick Williamsaa2f48a2016-09-10 14:23:34 -0500387 // Test tuple.
388 {
389 auto m = newMethodCall__test(b);
Andrew Geissler072da3e2018-01-18 07:21:42 -0800390 std::tuple<int, double, std::string> a{3, 4.1, "asdf"};
Patrick Williamsaa2f48a2016-09-10 14:23:34 -0500391 m.append(1, a, 2);
392 verifyTypeString = "i(ids)i";
393
394 struct verify
395 {
396 static void op(sd_bus_message* m)
397 {
398 int32_t a = 0;
399 double b = 0;
400 const char* c = nullptr;
401
402 sd_bus_message_read(m, "i", &a);
403 assert(a == 1);
404
Andrew Geissler072da3e2018-01-18 07:21:42 -0800405 auto rc = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT,
Patrick Williamsaa2f48a2016-09-10 14:23:34 -0500406 "ids");
407 assert(0 <= rc);
408
409 sd_bus_message_read(m, "ids", &a, &b, &c);
410 assert(a == 3);
411 assert(b == 4.1);
412 assert(0 == strcmp(c, "asdf"));
413
414 sd_bus_message_exit_container(m);
415
416 sd_bus_message_read(m, "i", &a);
417 assert(a == 2);
418 }
419 };
420 verifyCallback = &verify::op;
421
422 b.call_noreply(m);
423 }
424
Patrick Williams75596782016-09-11 21:14:10 -0500425 // Test variant.
426 {
427 auto m = newMethodCall__test(b);
428 sdbusplus::message::variant<int, double> a1{3.1}, a2{4};
429 m.append(1, a1, a2, 2);
430 verifyTypeString = "ivvi";
431
432 struct verify
433 {
434 static void op(sd_bus_message* m)
435 {
436 int32_t a = 0;
437 double b = 0;
438
439 sd_bus_message_read(m, "i", &a);
440 assert(a == 1);
441
442 sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, "d");
443 sd_bus_message_read(m, "d", &b);
444 assert(b == 3.1);
445 sd_bus_message_exit_container(m);
446
447 sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, "i");
448 sd_bus_message_read(m, "i", &a);
449 assert(a == 4);
450 sd_bus_message_exit_container(m);
451
452 sd_bus_message_read(m, "i", &a);
453 assert(a == 2);
454 }
455 };
456 verifyCallback = &verify::op;
457
458 b.call_noreply(m);
459 }
460
461 // Test map-variant.
462 {
463 auto m = newMethodCall__test(b);
Andrew Geissler072da3e2018-01-18 07:21:42 -0800464 std::map<std::string, sdbusplus::message::variant<int, double>> a1 = {
465 {"asdf", 3}, {"jkl;", 4.1}};
Patrick Williams75596782016-09-11 21:14:10 -0500466 m.append(1, a1, 2);
467 verifyTypeString = "ia{sv}i";
468
469 struct verify
470 {
471 static void op(sd_bus_message* m)
472 {
473 int32_t a = 0;
474 double b = 0;
475 const char* c = nullptr;
476
477 sd_bus_message_read(m, "i", &a);
478 assert(a == 1);
479
480 sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
481 sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv");
482 sd_bus_message_read(m, "s", &c);
483 assert(0 == strcmp("asdf", c));
484 sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, "i");
485 sd_bus_message_read(m, "i", &a);
486 assert(a == 3);
487 sd_bus_message_exit_container(m);
488 sd_bus_message_exit_container(m);
489 sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv");
490 sd_bus_message_read(m, "s", &c);
491 assert(0 == strcmp("jkl;", c));
492 sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, "d");
493 sd_bus_message_read(m, "d", &b);
494 assert(b == 4.1);
495 sd_bus_message_exit_container(m);
496 sd_bus_message_exit_container(m);
497 sd_bus_message_exit_container(m);
498
499 sd_bus_message_read(m, "i", &a);
500 assert(a == 2);
501 }
502 };
503 verifyCallback = &verify::op;
504
505 b.call_noreply(m);
506 }
507
Patrick Williams1807fa42016-08-01 22:23:30 -0500508 // Shutdown server.
Patrick Williams7802c072016-09-02 15:20:22 -0500509 {
510 auto m = b.new_method_call(SERVICE, "/", INTERFACE, QUIT_METHOD);
511 b.call_noreply(m);
512 }
Patrick Williams1807fa42016-08-01 22:23:30 -0500513}
514
515int main()
516{
Patrick Williams07e1d6f2016-09-08 15:54:09 -0500517
Patrick Williams1807fa42016-08-01 22:23:30 -0500518 // Initialize and start server thread.
519 pthread_t t;
520 {
Patrick Williams5b485792016-08-02 07:35:14 -0500521 auto b = serverInit();
522 pthread_create(&t, NULL, server, b.release());
Patrick Williams1807fa42016-08-01 22:23:30 -0500523 }
524
525 runTests();
526
527 // Wait for server thread to exit.
528 pthread_join(t, NULL);
529
530 return 0;
531}