blob: 58d700f1ccefe6db3403d11f7a886dcd200c1ff0 [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
Patrick Williams07e1d6f2016-09-08 15:54:09 -05009using verifyCallback_t = void(*)(sd_bus_message*);
10verifyCallback_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
31 while(1)
32 {
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
Patrick Williams5b485792016-08-02 07:35:14 -050036 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 {
53 std::cout << "Warning: No verification for "
54 << verifyTypeString << std::endl;
55 }
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;
151 m.append(t, true, false, 1.1);
152 verifyTypeString = "bbbd";
153
154 struct verify
155 {
156 static void op(sd_bus_message* m)
157 {
158 bool t1, t2, f1;
159 double d;
160 sd_bus_message_read(m, "bbbd", &t1, &t2, &f1, &d);
161 assert(t1);
162 assert(t2);
163 assert(!f1);
164 assert(d == 1.1);
165 }
166 };
167 verifyCallback = &verify::op;
168
169 b.call_noreply(m);
170 }
171
Patrick Williams1807fa42016-08-01 22:23:30 -0500172 // Test r-value string.
173 {
Patrick Williams7802c072016-09-02 15:20:22 -0500174 auto m = newMethodCall__test(b);
175 m.append("asdf"s);
Patrick Williams1807fa42016-08-01 22:23:30 -0500176 verifyTypeString = "s";
Patrick Williams07e1d6f2016-09-08 15:54:09 -0500177
178 struct verify
179 {
180 static void op(sd_bus_message* m)
181 {
182 const char* s = nullptr;
183 sd_bus_message_read_basic(m, 's', &s);
184 assert(0 == strcmp("asdf", s));
185 }
186 };
187 verifyCallback = &verify::op;
188
Patrick Williams5b485792016-08-02 07:35:14 -0500189 b.call_noreply(m);
Patrick Williams1807fa42016-08-01 22:23:30 -0500190 }
191
192 // Test multiple strings, various forms.
193 {
Patrick Williams7802c072016-09-02 15:20:22 -0500194 auto m = newMethodCall__test(b);
Patrick Williams1807fa42016-08-01 22:23:30 -0500195 auto str = "jkl;"s;
196 auto str2 = "JKL:"s;
Patrick Williams7802c072016-09-02 15:20:22 -0500197 m.append(1, "asdf", "ASDF"s, str,
198 std::move(str2), 5);
Patrick Williams1807fa42016-08-01 22:23:30 -0500199 verifyTypeString = "issssi";
Patrick Williams07e1d6f2016-09-08 15:54:09 -0500200
201 struct verify
202 {
203 static void op(sd_bus_message* m)
204 {
205 int32_t a = 0, b = 0;
206 const char *s0 = nullptr, *s1 = nullptr, *s2 = nullptr,
207 *s3 = nullptr;
208 sd_bus_message_read(m, "issssi", &a, &s0, &s1, &s2, &s3, &b);
209 assert(a == 1);
210 assert(b == 5);
211 assert(0 == strcmp("asdf", s0));
212 assert(0 == strcmp("ASDF", s1));
213 assert(0 == strcmp("jkl;", s2));
214 assert(0 == strcmp("JKL:", s3));
215 }
216 };
217 verifyCallback = &verify::op;
218
Patrick Williams5b485792016-08-02 07:35:14 -0500219 b.call_noreply(m);
Patrick Williams1807fa42016-08-01 22:23:30 -0500220 }
221
Patrick Williams930460c2016-07-20 17:52:55 -0500222 // Test vector.
223 {
224 auto m = newMethodCall__test(b);
225 std::vector<std::string> s{ "1", "2", "3"};
226 m.append(1, s, 2);
227 verifyTypeString = "iasi";
228
229 struct verify
230 {
231 static void op(sd_bus_message* m)
232 {
233 int32_t a = 0;
234 sd_bus_message_read(m, "i", &a);
235 assert(a == 1);
236
237 auto rc = sd_bus_message_enter_container(m,
238 SD_BUS_TYPE_ARRAY,
239 "s");
240 assert(0 <= rc);
241
242 const char* s = nullptr;
243 sd_bus_message_read_basic(m, 's', &s);
244 assert(0 == strcmp("1", s));
245 sd_bus_message_read_basic(m, 's', &s);
246 assert(0 == strcmp("2", s));
247 sd_bus_message_read_basic(m, 's', &s);
248 assert(0 == strcmp("3", s));
249 assert(1 == sd_bus_message_at_end(m, false));
250
251 sd_bus_message_exit_container(m);
252
253 sd_bus_message_read(m, "i", &a);
254 assert(a == 2);
255
256 }
257 };
258 verifyCallback = &verify::op;
259
260
261 b.call_noreply(m);
262 }
263
Patrick Williamsbbe0e432016-09-10 08:57:03 -0500264 // Test map.
265 {
266 auto m = newMethodCall__test(b);
267 std::map<std::string, int> s = { { "asdf", 3 }, { "jkl;", 4 } };
268 m.append(1, s, 2);
269 verifyTypeString = "ia{si}i";
270
271 struct verify
272 {
273 static void op(sd_bus_message* m)
274 {
275 int32_t a = 0;
276 sd_bus_message_read(m, "i", &a);
277 assert(a == 1);
278
279 auto rc = sd_bus_message_enter_container(m,
280 SD_BUS_TYPE_ARRAY,
281 "{si}");
282 assert(0 <= rc);
283
284 rc = sd_bus_message_enter_container(m,
285 SD_BUS_TYPE_DICT_ENTRY,
286 "si");
287 assert(0 <= rc);
288
289 const char* s = nullptr;
290 sd_bus_message_read_basic(m, 's', &s);
291 assert(0 == strcmp("asdf", s));
292 sd_bus_message_read_basic(m, 'i', &a);
293 assert(a == 3);
294
295 assert(1 == sd_bus_message_at_end(m, false));
296 sd_bus_message_exit_container(m);
297
298 rc = sd_bus_message_enter_container(m,
299 SD_BUS_TYPE_DICT_ENTRY,
300 "si");
301 assert(0 <= rc);
302
303 sd_bus_message_read_basic(m, 's', &s);
304 assert(0 == strcmp("jkl;", s));
305 sd_bus_message_read_basic(m, 'i', &a);
306 assert(a == 4);
307
308 assert(1 == sd_bus_message_at_end(m, false));
309 sd_bus_message_exit_container(m);
310
311 assert(1 == sd_bus_message_at_end(m, false));
312 sd_bus_message_exit_container(m);
313
314 sd_bus_message_read(m, "i", &a);
315 assert(a == 2);
316 }
317 };
318 verifyCallback = &verify::op;
319
320 b.call_noreply(m);
321 }
322
Patrick Williamsaa2f48a2016-09-10 14:23:34 -0500323 // Test tuple.
324 {
325 auto m = newMethodCall__test(b);
326 std::tuple<int, double, std::string> a{ 3, 4.1, "asdf" };
327 m.append(1, a, 2);
328 verifyTypeString = "i(ids)i";
329
330 struct verify
331 {
332 static void op(sd_bus_message* m)
333 {
334 int32_t a = 0;
335 double b = 0;
336 const char* c = nullptr;
337
338 sd_bus_message_read(m, "i", &a);
339 assert(a == 1);
340
341 auto rc = sd_bus_message_enter_container(m,
342 SD_BUS_TYPE_STRUCT,
343 "ids");
344 assert(0 <= rc);
345
346 sd_bus_message_read(m, "ids", &a, &b, &c);
347 assert(a == 3);
348 assert(b == 4.1);
349 assert(0 == strcmp(c, "asdf"));
350
351 sd_bus_message_exit_container(m);
352
353 sd_bus_message_read(m, "i", &a);
354 assert(a == 2);
355 }
356 };
357 verifyCallback = &verify::op;
358
359 b.call_noreply(m);
360 }
361
Patrick Williams75596782016-09-11 21:14:10 -0500362 // Test variant.
363 {
364 auto m = newMethodCall__test(b);
365 sdbusplus::message::variant<int, double> a1{3.1}, a2{4};
366 m.append(1, a1, a2, 2);
367 verifyTypeString = "ivvi";
368
369 struct verify
370 {
371 static void op(sd_bus_message* m)
372 {
373 int32_t a = 0;
374 double b = 0;
375
376 sd_bus_message_read(m, "i", &a);
377 assert(a == 1);
378
379 sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, "d");
380 sd_bus_message_read(m, "d", &b);
381 assert(b == 3.1);
382 sd_bus_message_exit_container(m);
383
384 sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, "i");
385 sd_bus_message_read(m, "i", &a);
386 assert(a == 4);
387 sd_bus_message_exit_container(m);
388
389 sd_bus_message_read(m, "i", &a);
390 assert(a == 2);
391 }
392 };
393 verifyCallback = &verify::op;
394
395 b.call_noreply(m);
396 }
397
398 // Test map-variant.
399 {
400 auto m = newMethodCall__test(b);
401 std::map<std::string, sdbusplus::message::variant<int, double>> a1 =
402 { { "asdf", 3 }, { "jkl;", 4.1 } };
403 m.append(1, a1, 2);
404 verifyTypeString = "ia{sv}i";
405
406 struct verify
407 {
408 static void op(sd_bus_message* m)
409 {
410 int32_t a = 0;
411 double b = 0;
412 const char* c = nullptr;
413
414 sd_bus_message_read(m, "i", &a);
415 assert(a == 1);
416
417 sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
418 sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv");
419 sd_bus_message_read(m, "s", &c);
420 assert(0 == strcmp("asdf", c));
421 sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, "i");
422 sd_bus_message_read(m, "i", &a);
423 assert(a == 3);
424 sd_bus_message_exit_container(m);
425 sd_bus_message_exit_container(m);
426 sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv");
427 sd_bus_message_read(m, "s", &c);
428 assert(0 == strcmp("jkl;", c));
429 sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, "d");
430 sd_bus_message_read(m, "d", &b);
431 assert(b == 4.1);
432 sd_bus_message_exit_container(m);
433 sd_bus_message_exit_container(m);
434 sd_bus_message_exit_container(m);
435
436 sd_bus_message_read(m, "i", &a);
437 assert(a == 2);
438 }
439 };
440 verifyCallback = &verify::op;
441
442 b.call_noreply(m);
443 }
444
Patrick Williams1807fa42016-08-01 22:23:30 -0500445 // Shutdown server.
Patrick Williams7802c072016-09-02 15:20:22 -0500446 {
447 auto m = b.new_method_call(SERVICE, "/", INTERFACE, QUIT_METHOD);
448 b.call_noreply(m);
449 }
Patrick Williams1807fa42016-08-01 22:23:30 -0500450}
451
452int main()
453{
Patrick Williams07e1d6f2016-09-08 15:54:09 -0500454
Patrick Williams1807fa42016-08-01 22:23:30 -0500455 // Initialize and start server thread.
456 pthread_t t;
457 {
Patrick Williams5b485792016-08-02 07:35:14 -0500458 auto b = serverInit();
459 pthread_create(&t, NULL, server, b.release());
Patrick Williams1807fa42016-08-01 22:23:30 -0500460 }
461
462 runTests();
463
464 // Wait for server thread to exit.
465 pthread_join(t, NULL);
466
467 return 0;
468}