blob: 90fb0fce6b09d36695008b583df87f9c0e5ad3ce [file] [log] [blame]
Patrick Williams4fe85a32016-09-08 15:03:56 -05001#include <iostream>
2#include <cassert>
3#include <sdbusplus/message.hpp>
4#include <sdbusplus/bus.hpp>
Ed Tanous28dc36d2018-02-21 12:22:54 -08005#include <unordered_map>
6#include <set>
Patrick Williams4fe85a32016-09-08 15:03:56 -05007
William A. Kennington III48697812018-06-19 18:35:38 -07008// Make sure even in non-debug mode we use asserts
9#define TEST_ASSERT(n) \
10 do \
11 { \
12 if (!(n)) \
13 { \
14 fprintf(stderr, "%s:%d %s: Assertion `%s` failed\n", __FILE__, \
15 __LINE__, __func__, #n); \
16 abort(); \
17 } \
18 } while (0)
19
Patrick Williams4fe85a32016-09-08 15:03:56 -050020// Global to share the dbus type string between client and server.
21static std::string verifyTypeString;
22
Andrew Geissler072da3e2018-01-18 07:21:42 -080023using verifyCallback_t = void (*)(sdbusplus::message::message&);
Patrick Williams4fe85a32016-09-08 15:03:56 -050024verifyCallback_t verifyCallback = nullptr;
25
Patrick Williams24fb2962016-11-04 17:08:59 -050026static constexpr auto SERVICE = "sdbusplus.test.message.read";
Patrick Williams4fe85a32016-09-08 15:03:56 -050027static constexpr auto INTERFACE = SERVICE;
28static constexpr auto TEST_METHOD = "test";
29static constexpr auto QUIT_METHOD = "quit";
30
31// Open up the sdbus and claim SERVICE name.
32auto serverInit()
33{
34 auto b = sdbusplus::bus::new_default();
35 b.request_name(SERVICE);
36
37 return std::move(b);
38}
39
40// Thread to run the dbus server.
41void* server(void* b)
42{
William A. Kennington IIIb5645502018-06-19 18:36:41 -070043 auto bus = sdbusplus::bus::bus(reinterpret_cast<sdbusplus::bus::busp_t>(b),
44 std::false_type());
Patrick Williams4fe85a32016-09-08 15:03:56 -050045
Andrew Geissler072da3e2018-01-18 07:21:42 -080046 while (1)
Patrick Williams4fe85a32016-09-08 15:03:56 -050047 {
48 // Wait for messages.
49 auto m = bus.process();
50
Andrew Geissler072da3e2018-01-18 07:21:42 -080051 if (!m)
Patrick Williams4fe85a32016-09-08 15:03:56 -050052 {
53 bus.wait();
54 continue;
55 }
56
57 if (m.is_method_call(INTERFACE, TEST_METHOD))
58 {
59 // Verify the message type matches what the test expects.
William A. Kennington III48697812018-06-19 18:35:38 -070060 TEST_ASSERT(verifyTypeString == m.get_signature());
Patrick Williams4fe85a32016-09-08 15:03:56 -050061
62 if (verifyCallback)
63 {
64
65 verifyCallback(m);
66 verifyCallback = nullptr;
67 }
68 else
69 {
Andrew Geissler072da3e2018-01-18 07:21:42 -080070 std::cout << "Warning: No verification for " << verifyTypeString
71 << std::endl;
Patrick Williams4fe85a32016-09-08 15:03:56 -050072 }
73 // Reply to client.
William A. Kennington IIIb5645502018-06-19 18:36:41 -070074 auto sd_m = m.release();
75 sd_bus_reply_method_return(sd_m, nullptr);
76 sd_bus_message_unref(sd_m);
Patrick Williams4fe85a32016-09-08 15:03:56 -050077 }
78 else if (m.is_method_call(INTERFACE, QUIT_METHOD))
79 {
80 // Reply and exit.
William A. Kennington IIIb5645502018-06-19 18:36:41 -070081 auto sd_m = m.release();
82 sd_bus_reply_method_return(sd_m, nullptr);
83 sd_bus_message_unref(sd_m);
Patrick Williams4fe85a32016-09-08 15:03:56 -050084 break;
85 }
86 }
Patrick Williams696e3152016-11-04 17:03:39 -050087
88 return nullptr;
Patrick Williams4fe85a32016-09-08 15:03:56 -050089}
90
91auto newMethodCall__test(sdbusplus::bus::bus& b)
92{
93 // Allocate a method-call message for INTERFACE,TEST_METHOD.
94 return b.new_method_call(SERVICE, "/", INTERFACE, TEST_METHOD);
95}
96
97void runTests()
98{
99 using namespace std::literals;
100
101 auto b = sdbusplus::bus::new_default();
102
103 // Test r-value int.
104 {
105 auto m = newMethodCall__test(b);
106 m.append(1);
107 verifyTypeString = "i";
108
109 struct verify
110 {
111 static void op(sdbusplus::message::message& m)
112 {
113 int32_t i = 0;
114 m.read(i);
William A. Kennington III48697812018-06-19 18:35:38 -0700115 TEST_ASSERT(i == 1);
Patrick Williams4fe85a32016-09-08 15:03:56 -0500116 }
117 };
118 verifyCallback = &verify::op;
119
120 b.call_noreply(m);
121 }
122 // Test l-value int.
123 {
124 auto m = newMethodCall__test(b);
125 int a = 1;
126 m.append(a, a);
127 verifyTypeString = "ii";
128
129 struct verify
130 {
131 static void op(sdbusplus::message::message& m)
132 {
133 int32_t a = 0, b = 0;
134 m.read(a, b);
William A. Kennington III48697812018-06-19 18:35:38 -0700135 TEST_ASSERT(a == 1);
136 TEST_ASSERT(b == 1);
Patrick Williams4fe85a32016-09-08 15:03:56 -0500137 }
138 };
139 verifyCallback = &verify::op;
140
141 b.call_noreply(m);
142 }
143
144 // Test multiple ints.
145 {
146 auto m = newMethodCall__test(b);
147 m.append(1, 2, 3, 4, 5);
148 verifyTypeString = "iiiii";
149
150 struct verify
151 {
152 static void op(sdbusplus::message::message& m)
153 {
154 int32_t a = 0, b = 0, c = 0, d = 0, e = 0;
Andrew Geissler072da3e2018-01-18 07:21:42 -0800155 m.read(a, b, c, d, e);
William A. Kennington III48697812018-06-19 18:35:38 -0700156 TEST_ASSERT(a == 1);
157 TEST_ASSERT(b == 2);
158 TEST_ASSERT(c == 3);
159 TEST_ASSERT(d == 4);
160 TEST_ASSERT(e == 5);
Patrick Williams4fe85a32016-09-08 15:03:56 -0500161 }
162 };
163 verifyCallback = &verify::op;
164
165 b.call_noreply(m);
166 }
167
Patrick Williams9e3b51e2016-10-18 07:47:29 -0500168 // Test double and bool.
169 {
170 auto m = newMethodCall__test(b);
171 bool t = true;
Patrick Williamsb760a992016-11-28 11:26:55 -0600172 bool f = false;
173 bool f2 = false;
174 m.append(t, true, f, std::move(f2), false, 1.1);
175 verifyTypeString = "bbbbbd";
Patrick Williams9e3b51e2016-10-18 07:47:29 -0500176
177 struct verify
178 {
179 static void op(sdbusplus::message::message& m)
180 {
Patrick Williamsb760a992016-11-28 11:26:55 -0600181 bool t1, t2, f1, f2, f3;
Patrick Williams9e3b51e2016-10-18 07:47:29 -0500182 double d;
Patrick Williamsb760a992016-11-28 11:26:55 -0600183 m.read(t1, t2, f1, f2, f3, d);
William A. Kennington III48697812018-06-19 18:35:38 -0700184 TEST_ASSERT(t1);
185 TEST_ASSERT(t2);
186 TEST_ASSERT(!f1);
187 TEST_ASSERT(!f2);
188 TEST_ASSERT(!f3);
189 TEST_ASSERT(d == 1.1);
Patrick Williams9e3b51e2016-10-18 07:47:29 -0500190 }
191 };
192 verifyCallback = &verify::op;
193
194 b.call_noreply(m);
195 }
196
Patrick Williams4fe85a32016-09-08 15:03:56 -0500197 // Test r-value string.
198 {
199 auto m = newMethodCall__test(b);
200 m.append("asdf"s);
201 verifyTypeString = "s";
202
203 struct verify
204 {
205 static void op(sdbusplus::message::message& m)
206 {
207 const char* s = nullptr;
208 m.read(s);
William A. Kennington III48697812018-06-19 18:35:38 -0700209 TEST_ASSERT(0 == strcmp("asdf", s));
Patrick Williams4fe85a32016-09-08 15:03:56 -0500210 }
211 };
212 verifyCallback = &verify::op;
213
214 b.call_noreply(m);
215 }
216
217 // Test multiple strings, various forms.
218 {
219 auto m = newMethodCall__test(b);
220 auto str = "jkl;"s;
221 auto str2 = "JKL:"s;
Andrew Geissler072da3e2018-01-18 07:21:42 -0800222 m.append(1, "asdf", "ASDF"s, str, std::move(str2), 5);
Patrick Williams4fe85a32016-09-08 15:03:56 -0500223 verifyTypeString = "issssi";
224
225 struct verify
226 {
227 static void op(sdbusplus::message::message& m)
228 {
229 int32_t a = 0, b = 0;
230 std::string s0, s1, s2, s3;
231 m.read(a, s0, s1, s2, s3, b);
William A. Kennington III48697812018-06-19 18:35:38 -0700232 TEST_ASSERT(a == 1);
233 TEST_ASSERT(b == 5);
234 TEST_ASSERT(s0 == "asdf"s);
235 TEST_ASSERT(s1 == "ASDF"s);
236 TEST_ASSERT(s2 == "jkl;"s);
237 TEST_ASSERT(s3 == "JKL:");
Patrick Williams4fe85a32016-09-08 15:03:56 -0500238 }
239 };
240 verifyCallback = &verify::op;
241
242 b.call_noreply(m);
243 }
244
Patrick Williams572a8ea2017-01-06 16:23:14 -0600245 // Test object_path and signature.
246 {
247 auto m = newMethodCall__test(b);
248 auto o = sdbusplus::message::object_path("/asdf");
249 auto s = sdbusplus::message::signature("iii");
250 m.append(1, o, s, 4);
251 verifyTypeString = "iogi";
252
253 struct verify
254 {
255 static void op(sdbusplus::message::message& m)
256 {
257 int32_t a = 0, b = 0;
258 sdbusplus::message::object_path o;
259 sdbusplus::message::signature s;
260 m.read(a, o, s, b);
William A. Kennington III48697812018-06-19 18:35:38 -0700261 TEST_ASSERT(a == 1);
262 TEST_ASSERT(b == 4);
263 TEST_ASSERT(std::string(o) == "/asdf"s);
264 TEST_ASSERT(std::string(s) == "iii"s);
Patrick Williams572a8ea2017-01-06 16:23:14 -0600265 }
266 };
267 verifyCallback = &verify::op;
268
269 b.call_noreply(m);
270 }
271
Patrick Williams930460c2016-07-20 17:52:55 -0500272 // Test vector.
273 {
274 auto m = newMethodCall__test(b);
Andrew Geissler072da3e2018-01-18 07:21:42 -0800275 std::vector<std::string> s{"1", "2", "3"};
Patrick Williams930460c2016-07-20 17:52:55 -0500276 m.append(1, s, 2);
277 verifyTypeString = "iasi";
278
279 struct verify
280 {
281 static void op(sdbusplus::message::message& m)
282 {
283 int32_t a = 0;
284 std::vector<std::string> s;
285 m.read(a, s);
William A. Kennington III48697812018-06-19 18:35:38 -0700286 TEST_ASSERT(a == 1);
287 TEST_ASSERT(s[0] == "1");
288 TEST_ASSERT(s[1] == "2");
289 TEST_ASSERT(s[2] == "3");
Andrew Geissler072da3e2018-01-18 07:21:42 -0800290 decltype(s) s2 = {"1", "2", "3"};
William A. Kennington III48697812018-06-19 18:35:38 -0700291 TEST_ASSERT(s == s2);
Patrick Williams930460c2016-07-20 17:52:55 -0500292 }
293 };
294 verifyCallback = &verify::op;
295
296 b.call_noreply(m);
297 }
298
Patrick Williamsbbe0e432016-09-10 08:57:03 -0500299 // Test map.
300 {
301 auto m = newMethodCall__test(b);
Andrew Geissler072da3e2018-01-18 07:21:42 -0800302 std::map<std::string, int> s = {{"asdf", 3}, {"jkl;", 4}};
Patrick Williamsbbe0e432016-09-10 08:57:03 -0500303 m.append(1, s, 2);
304 verifyTypeString = "ia{si}i";
305
306 struct verify
307 {
308 static void op(sdbusplus::message::message& m)
309 {
310 int32_t a = 0, b = 0;
311 std::map<std::string, int> s{};
312
313 m.read(a, s, b);
William A. Kennington III48697812018-06-19 18:35:38 -0700314 TEST_ASSERT(a == 1);
315 TEST_ASSERT(s.size() == 2);
316 TEST_ASSERT(s["asdf"] == 3);
317 TEST_ASSERT(s["jkl;"] == 4);
318 TEST_ASSERT(b == 2);
Patrick Williamsbbe0e432016-09-10 08:57:03 -0500319 }
320 };
321 verifyCallback = &verify::op;
322
323 b.call_noreply(m);
324 }
325
Ed Tanous28dc36d2018-02-21 12:22:54 -0800326 // Test unordered_map.
327 {
328 auto m = newMethodCall__test(b);
329 std::unordered_map<std::string, int> s = {{"asdf", 3}, {"jkl;", 4}};
330 m.append(1, s, 2);
331 verifyTypeString = "ia{si}i";
332
333 struct verify
334 {
335 static void op(sdbusplus::message::message& m)
336 {
337 int32_t a = 0, b = 0;
338 std::unordered_map<std::string, int> s{};
339
340 m.read(a, s, b);
William A. Kennington III48697812018-06-19 18:35:38 -0700341 TEST_ASSERT(a == 1);
342 TEST_ASSERT(s.size() == 2);
343 TEST_ASSERT(s["asdf"] == 3);
344 TEST_ASSERT(s["jkl;"] == 4);
345 TEST_ASSERT(b == 2);
Ed Tanous28dc36d2018-02-21 12:22:54 -0800346 }
347 };
348 verifyCallback = &verify::op;
349
350 b.call_noreply(m);
351 }
352
353 // Test set.
354 {
355 auto m = newMethodCall__test(b);
356 std::set<std::string> s = {{"asdf"}, {"jkl;"}};
357 m.append(1, s, 2);
358 verifyTypeString = "iasi";
359
360 struct verify
361 {
362 static void op(sdbusplus::message::message& m)
363 {
364 int32_t a = 0, b = 0;
365 std::set<std::string> s{};
366
367 m.read(a, s, b);
William A. Kennington III48697812018-06-19 18:35:38 -0700368 TEST_ASSERT(a == 1);
369 TEST_ASSERT(s.size() == 2);
370 TEST_ASSERT(s.find("asdf") != s.end());
371 TEST_ASSERT(s.find("jkl;") != s.end());
372 TEST_ASSERT(b == 2);
Ed Tanous28dc36d2018-02-21 12:22:54 -0800373 }
374 };
375 verifyCallback = &verify::op;
376
377 b.call_noreply(m);
378 }
379
Patrick Williamsaa2f48a2016-09-10 14:23:34 -0500380 // Test tuple.
381 {
382 auto m = newMethodCall__test(b);
Andrew Geissler072da3e2018-01-18 07:21:42 -0800383 std::tuple<int, double, std::string> a{3, 4.1, "asdf"};
Patrick Williamsaa2f48a2016-09-10 14:23:34 -0500384 m.append(1, a, 2);
385 verifyTypeString = "i(ids)i";
Patrick Williamsbbe0e432016-09-10 08:57:03 -0500386
Patrick Williamsaa2f48a2016-09-10 14:23:34 -0500387 struct verify
388 {
389 static void op(sdbusplus::message::message& m)
390 {
391 int32_t a = 0, b = 0;
392 std::tuple<int, double, std::string> c{};
393
394 m.read(a, c, b);
William A. Kennington III48697812018-06-19 18:35:38 -0700395 TEST_ASSERT(a == 1);
396 TEST_ASSERT(b == 2);
397 TEST_ASSERT(c == std::make_tuple(3, 4.1, "asdf"s));
Patrick Williamsaa2f48a2016-09-10 14:23:34 -0500398 }
399 };
400 verifyCallback = &verify::op;
401
402 b.call_noreply(m);
403 }
Patrick Williamsbbe0e432016-09-10 08:57:03 -0500404
Patrick Williams75596782016-09-11 21:14:10 -0500405 // Test variant.
406 {
407 auto m = newMethodCall__test(b);
408 sdbusplus::message::variant<int, double> a1{3.1}, a2{4};
409 m.append(1, a1, a2, 2);
410 verifyTypeString = "ivvi";
411
412 struct verify
413 {
414 static void op(sdbusplus::message::message& m)
415 {
416 int32_t a, b;
417 sdbusplus::message::variant<int, double> a1{}, a2{};
418
419 m.read(a, a1, a2, b);
William A. Kennington III48697812018-06-19 18:35:38 -0700420 TEST_ASSERT(a == 1);
421 TEST_ASSERT(a1 == 3.1);
422 TEST_ASSERT(a2 == 4);
423 TEST_ASSERT(b == 2);
Patrick Williams75596782016-09-11 21:14:10 -0500424 }
425 };
426 verifyCallback = &verify::op;
427
428 b.call_noreply(m);
429 }
430
Patrick Williamsf101ee22016-11-04 17:44:04 -0500431 // Test variant with missing/wrong type.
432 {
433 auto m = newMethodCall__test(b);
434 sdbusplus::message::variant<uint64_t, double> a1{3.1}, a2{uint64_t(4)};
435 m.append(1, a1, a2, 2);
436 verifyTypeString = "ivvi";
437
438 struct verify
439 {
440 static void op(sdbusplus::message::message& m)
441 {
442 int32_t a, b;
443 sdbusplus::message::variant<uint8_t, double> a1{}, a2{};
444
445 m.read(a, a1, a2, b);
William A. Kennington III48697812018-06-19 18:35:38 -0700446 TEST_ASSERT(a == 1);
447 TEST_ASSERT(a1 == 3.1);
448 TEST_ASSERT(a2 == uint8_t());
449 TEST_ASSERT(b == 2);
Patrick Williamsf101ee22016-11-04 17:44:04 -0500450 }
451 };
452 verifyCallback = &verify::op;
453
454 b.call_noreply(m);
455 }
456
Patrick Williams75596782016-09-11 21:14:10 -0500457 // Test map-variant.
458 {
459 auto m = newMethodCall__test(b);
Andrew Geissler072da3e2018-01-18 07:21:42 -0800460 std::map<std::string, sdbusplus::message::variant<int, double>> a1 = {
461 {"asdf", 3}, {"jkl;", 4.1}};
Patrick Williams75596782016-09-11 21:14:10 -0500462 m.append(1, a1, 2);
463 verifyTypeString = "ia{sv}i";
464
465 struct verify
466 {
467 static void op(sdbusplus::message::message& m)
468 {
469 int32_t a = 0, b = 0;
Andrew Geissler072da3e2018-01-18 07:21:42 -0800470 std::map<std::string, sdbusplus::message::variant<int, double>>
471 a1{};
Patrick Williams75596782016-09-11 21:14:10 -0500472
473 m.read(a, a1, b);
William A. Kennington III48697812018-06-19 18:35:38 -0700474 TEST_ASSERT(a == 1);
475 TEST_ASSERT(a1["asdf"] == 3);
476 TEST_ASSERT(a1["jkl;"] == 4.1);
477 TEST_ASSERT(b == 2);
Patrick Williams75596782016-09-11 21:14:10 -0500478 }
479 };
480 verifyCallback = &verify::op;
481
482 b.call_noreply(m);
483 }
484
Patrick Williams4fe85a32016-09-08 15:03:56 -0500485 // Shutdown server.
486 {
487 auto m = b.new_method_call(SERVICE, "/", INTERFACE, QUIT_METHOD);
488 b.call_noreply(m);
489 }
490}
491
492int main()
493{
494
495 // Initialize and start server thread.
496 pthread_t t;
497 {
498 auto b = serverInit();
499 pthread_create(&t, NULL, server, b.release());
500 }
501
502 runTests();
503
504 // Wait for server thread to exit.
505 pthread_join(t, NULL);
506
507 return 0;
508}