xref: /openbmc/sdbusplus/test/message/read.cpp (revision 930460c0)
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     // Shutdown server.
224     {
225         auto m = b.new_method_call(SERVICE, "/", INTERFACE, QUIT_METHOD);
226         b.call_noreply(m);
227     }
228 }
229 
230 int main()
231 {
232 
233     // Initialize and start server thread.
234     pthread_t t;
235     {
236         auto b = serverInit();
237         pthread_create(&t, NULL, server, b.release());
238     }
239 
240     runTests();
241 
242     // Wait for server thread to exit.
243     pthread_join(t, NULL);
244 
245     return 0;
246 }
247