xref: /openbmc/sdbusplus/test/message/read.cpp (revision 2b0bdd6e)
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