xref: /openbmc/sdbusplus/test/message/read.cpp (revision 696fa72a)
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";
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 
70 auto newMethodCall__test(sdbusplus::bus::bus& b)
71 {
72     // Allocate a method-call message for INTERFACE,TEST_METHOD.
73     return b.new_method_call(SERVICE, "/", INTERFACE, TEST_METHOD);
74 }
75 
76 void runTests()
77 {
78     using namespace std::literals;
79 
80     auto b = sdbusplus::bus::new_default();
81 
82     // Test r-value int.
83     {
84         auto m = newMethodCall__test(b);
85         m.append(1);
86         verifyTypeString = "i";
87 
88         struct verify
89         {
90             static void op(sdbusplus::message::message& m)
91             {
92                 int32_t i = 0;
93                 m.read(i);
94                 assert(i == 1);
95             }
96         };
97         verifyCallback = &verify::op;
98 
99         b.call_noreply(m);
100     }
101     // Test l-value int.
102     {
103         auto m = newMethodCall__test(b);
104         int a = 1;
105         m.append(a, a);
106         verifyTypeString = "ii";
107 
108         struct verify
109         {
110             static void op(sdbusplus::message::message& m)
111             {
112                 int32_t a = 0, b = 0;
113                 m.read(a, b);
114                 assert(a == 1);
115                 assert(b == 1);
116             }
117         };
118         verifyCallback = &verify::op;
119 
120         b.call_noreply(m);
121     }
122 
123     // Test multiple ints.
124     {
125         auto m = newMethodCall__test(b);
126         m.append(1, 2, 3, 4, 5);
127         verifyTypeString = "iiiii";
128 
129         struct verify
130         {
131             static void op(sdbusplus::message::message& m)
132             {
133                 int32_t a = 0, b = 0, c = 0, d = 0, e = 0;
134                 m.read(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 
144         b.call_noreply(m);
145     }
146 
147     // Test r-value string.
148     {
149         auto m = newMethodCall__test(b);
150         m.append("asdf"s);
151         verifyTypeString = "s";
152 
153         struct verify
154         {
155             static void op(sdbusplus::message::message& m)
156             {
157                 const char* s = nullptr;
158                 m.read(s);
159                 assert(0 == strcmp("asdf", s));
160             }
161         };
162         verifyCallback = &verify::op;
163 
164         b.call_noreply(m);
165     }
166 
167     // Test multiple strings, various forms.
168     {
169         auto m = newMethodCall__test(b);
170         auto str = "jkl;"s;
171         auto str2 = "JKL:"s;
172         m.append(1, "asdf", "ASDF"s, str,
173                  std::move(str2), 5);
174         verifyTypeString = "issssi";
175 
176         struct verify
177         {
178             static void op(sdbusplus::message::message& m)
179             {
180                 int32_t a = 0, b = 0;
181                 std::string s0, s1, s2, s3;
182                 m.read(a, s0, s1, s2, s3, b);
183                 assert(a == 1);
184                 assert(b == 5);
185                 assert(s0 == "asdf"s);
186                 assert(s1 == "ASDF"s);
187                 assert(s2 == "jkl;"s);
188                 assert(s3 == "JKL:");
189             }
190         };
191         verifyCallback = &verify::op;
192 
193         b.call_noreply(m);
194     }
195 
196     // Test vector.
197     {
198         auto m = newMethodCall__test(b);
199         std::vector<std::string> s{ "1", "2", "3"};
200         m.append(1, s, 2);
201         verifyTypeString = "iasi";
202 
203         struct verify
204         {
205             static void op(sdbusplus::message::message& m)
206             {
207                 int32_t a = 0;
208                 std::vector<std::string> s;
209                 m.read(a, s);
210                 assert(a == 1);
211                 assert(s[0] == "1");
212                 assert(s[1] == "2");
213                 assert(s[2] == "3");
214                 decltype(s) s2 = { "1" , "2" , "3" };
215                 assert(s == s2);
216             }
217         };
218         verifyCallback = &verify::op;
219 
220         b.call_noreply(m);
221     }
222 
223     // Test map.
224     {
225         auto m = newMethodCall__test(b);
226         std::map<std::string, int> s = { { "asdf", 3 }, { "jkl;", 4 } };
227         m.append(1, s, 2);
228         verifyTypeString = "ia{si}i";
229 
230         struct verify
231         {
232             static void op(sdbusplus::message::message& m)
233             {
234                 int32_t a = 0, b = 0;
235                 std::map<std::string, int> s{};
236 
237                 m.read(a, s, b);
238                 assert(a == 1);
239                 assert(s.size() == 2);
240                 assert(s["asdf"] == 3);
241                 assert(s["jkl;"] == 4);
242                 assert(b == 2);
243             }
244         };
245         verifyCallback = &verify::op;
246 
247         b.call_noreply(m);
248     }
249 
250     // Test tuple.
251     {
252         auto m = newMethodCall__test(b);
253         std::tuple<int, double, std::string> a{ 3, 4.1, "asdf" };
254         m.append(1, a, 2);
255         verifyTypeString = "i(ids)i";
256 
257         struct verify
258         {
259             static void op(sdbusplus::message::message& m)
260             {
261                 int32_t a = 0, b = 0;
262                 std::tuple<int, double, std::string> c{};
263 
264                 m.read(a, c, b);
265                 assert(a == 1);
266                 assert(b == 2);
267                 assert(c == std::make_tuple(3, 4.1, "asdf"s));
268             }
269         };
270         verifyCallback = &verify::op;
271 
272         b.call_noreply(m);
273     }
274 
275     // Test variant.
276     {
277         auto m = newMethodCall__test(b);
278         sdbusplus::message::variant<int, double> a1{3.1}, a2{4};
279         m.append(1, a1, a2, 2);
280         verifyTypeString = "ivvi";
281 
282         struct verify
283         {
284             static void op(sdbusplus::message::message& m)
285             {
286                 int32_t a, b;
287                 sdbusplus::message::variant<int, double> a1{}, a2{};
288 
289                 m.read(a, a1, a2, b);
290                 assert(a == 1);
291                 assert(a1 == 3.1);
292                 assert(a2 == 4);
293                 assert(b == 2);
294             }
295         };
296         verifyCallback = &verify::op;
297 
298         b.call_noreply(m);
299     }
300 
301     // Test map-variant.
302     {
303         auto m = newMethodCall__test(b);
304         std::map<std::string, sdbusplus::message::variant<int, double>> a1 =
305                 { { "asdf", 3 }, { "jkl;", 4.1 } };
306         m.append(1, a1, 2);
307         verifyTypeString = "ia{sv}i";
308 
309         struct verify
310         {
311             static void op(sdbusplus::message::message& m)
312             {
313                 int32_t a = 0, b = 0;
314                 std::map<std::string,
315                          sdbusplus::message::variant<int, double>> a1{};
316 
317                 m.read(a, a1, b);
318                 assert(a == 1);
319                 assert(a1["asdf"] == 3);
320                 assert(a1["jkl;"] == 4.1);
321                 assert(b == 2);
322             }
323         };
324         verifyCallback = &verify::op;
325 
326         b.call_noreply(m);
327     }
328 
329 
330     // Shutdown server.
331     {
332         auto m = b.new_method_call(SERVICE, "/", INTERFACE, QUIT_METHOD);
333         b.call_noreply(m);
334     }
335 }
336 
337 int main()
338 {
339 
340     // Initialize and start server thread.
341     pthread_t t;
342     {
343         auto b = serverInit();
344         pthread_create(&t, NULL, server, b.release());
345     }
346 
347     runTests();
348 
349     // Wait for server thread to exit.
350     pthread_join(t, NULL);
351 
352     return 0;
353 }
354