xref: /openbmc/sdbusplus/test/message/read.cpp (revision 4fe85a30)
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     // Shutdown server.
197     {
198         auto m = b.new_method_call(SERVICE, "/", INTERFACE, QUIT_METHOD);
199         b.call_noreply(m);
200     }
201 }
202 
203 int main()
204 {
205 
206     // Initialize and start server thread.
207     pthread_t t;
208     {
209         auto b = serverInit();
210         pthread_create(&t, NULL, server, b.release());
211     }
212 
213     runTests();
214 
215     // Wait for server thread to exit.
216     pthread_join(t, NULL);
217 
218     return 0;
219 }
220