xref: /openbmc/sdbusplus/test/message/append.cpp (revision 95269dbc)
1 #include <systemd/sd-bus-protocol.h>
2 
3 #include <array>
4 #include <map>
5 #include <sdbusplus/message.hpp>
6 #include <sdbusplus/test/sdbus_mock.hpp>
7 #include <set>
8 #include <string>
9 #include <tuple>
10 #include <unordered_map>
11 #include <vector>
12 
13 #include <gmock/gmock.h>
14 #include <gtest/gtest.h>
15 
16 namespace
17 {
18 
19 using testing::Eq;
20 using testing::MatcherCast;
21 using testing::Pointee;
22 using testing::Return;
23 using testing::SafeMatcherCast;
24 using testing::StrEq;
25 
26 class AppendTest : public testing::Test
27 {
28   protected:
29     testing::StrictMock<sdbusplus::SdBusMock> mock;
30 
31     void SetUp() override
32     {
33         EXPECT_CALL(mock, sd_bus_message_new_method_call(testing::_, testing::_,
34                                                          nullptr, nullptr,
35                                                          nullptr, nullptr))
36             .WillRepeatedly(Return(0));
37     };
38 
39     sdbusplus::message::message new_message()
40     {
41         return sdbusplus::get_mocked_new(&mock).new_method_call(
42             nullptr, nullptr, nullptr, nullptr);
43     }
44 
45     template <typename T> void expect_basic(char type, T val)
46     {
47         EXPECT_CALL(mock,
48                     sd_bus_message_append_basic(
49                         nullptr, type,
50                         MatcherCast<const void *>(
51                             SafeMatcherCast<const T *>(Pointee(Eq(val))))))
52             .WillOnce(Return(0));
53     }
54 
55     void expect_basic_string(char type, const char *str)
56     {
57         EXPECT_CALL(mock, sd_bus_message_append_basic(
58                               nullptr, type,
59                               MatcherCast<const void *>(
60                                   SafeMatcherCast<const char *>(StrEq(str)))))
61             .WillOnce(Return(0));
62     }
63 
64     void expect_open_container(char type, const char *contents)
65     {
66         EXPECT_CALL(
67             mock, sd_bus_message_open_container(nullptr, type, StrEq(contents)))
68             .WillOnce(Return(0));
69     }
70 
71     void expect_close_container()
72     {
73         EXPECT_CALL(mock, sd_bus_message_close_container(nullptr))
74             .WillOnce(Return(0));
75     }
76 };
77 
78 TEST_F(AppendTest, RValueInt)
79 {
80     expect_basic<int>(SD_BUS_TYPE_INT32, 1);
81     new_message().append(1);
82 }
83 
84 TEST_F(AppendTest, LValueInt)
85 {
86     const int a = 1;
87     expect_basic<int>(SD_BUS_TYPE_INT32, a);
88     new_message().append(a);
89 }
90 
91 TEST_F(AppendTest, XValueInt)
92 {
93     int a = 1;
94     expect_basic<int>(SD_BUS_TYPE_INT32, a);
95     new_message().append(std::move(a));
96 }
97 
98 TEST_F(AppendTest, RValueBool)
99 {
100     expect_basic<int>(SD_BUS_TYPE_BOOLEAN, true);
101     new_message().append(true);
102 }
103 
104 TEST_F(AppendTest, LValueBool)
105 {
106     const bool a = false;
107     expect_basic<int>(SD_BUS_TYPE_BOOLEAN, false);
108     new_message().append(a);
109 }
110 
111 TEST_F(AppendTest, XValueBool)
112 {
113     bool a = false;
114     expect_basic<int>(SD_BUS_TYPE_BOOLEAN, false);
115     new_message().append(std::move(a));
116 }
117 
118 TEST_F(AppendTest, RValueDouble)
119 {
120     expect_basic<double>(SD_BUS_TYPE_DOUBLE, 1.1);
121     new_message().append(1.1);
122 }
123 
124 TEST_F(AppendTest, LValueDouble)
125 {
126     const double a = 1.1;
127     expect_basic<double>(SD_BUS_TYPE_DOUBLE, a);
128     new_message().append(a);
129 }
130 
131 TEST_F(AppendTest, XValueDouble)
132 {
133     double a = 1.1;
134     expect_basic<double>(SD_BUS_TYPE_DOUBLE, a);
135     new_message().append(std::move(a));
136 }
137 
138 TEST_F(AppendTest, RValueCString)
139 {
140     expect_basic_string(SD_BUS_TYPE_STRING, "asdf");
141     new_message().append("asdf");
142 }
143 
144 TEST_F(AppendTest, LValueCString)
145 {
146     const char *const s = "asdf";
147     expect_basic_string(SD_BUS_TYPE_STRING, s);
148     new_message().append(s);
149 }
150 
151 TEST_F(AppendTest, XValueCString)
152 {
153     const char *s = "asdf";
154     expect_basic_string(SD_BUS_TYPE_STRING, s);
155     new_message().append(std::move(s));
156 }
157 
158 TEST_F(AppendTest, RValueString)
159 {
160     expect_basic_string(SD_BUS_TYPE_STRING, "asdf");
161     new_message().append(std::string{"asdf"});
162 }
163 
164 TEST_F(AppendTest, LValueString)
165 {
166     std::string s{"asdf"};
167     expect_basic_string(SD_BUS_TYPE_STRING, s.c_str());
168     new_message().append(s);
169 }
170 
171 TEST_F(AppendTest, XValueString)
172 {
173     std::string s{"asdf"};
174     expect_basic_string(SD_BUS_TYPE_STRING, s.c_str());
175     new_message().append(std::move(s));
176 }
177 
178 TEST_F(AppendTest, ObjectPath)
179 {
180     sdbusplus::message::object_path o{"/asdf"};
181     expect_basic_string(SD_BUS_TYPE_OBJECT_PATH, o.str.c_str());
182     new_message().append(o);
183 }
184 
185 TEST_F(AppendTest, Signature)
186 {
187     sdbusplus::message::signature g{"ii"};
188     expect_basic_string(SD_BUS_TYPE_SIGNATURE, g.str.c_str());
189     new_message().append(g);
190 }
191 
192 TEST_F(AppendTest, CombinedBasic)
193 {
194     const int c = 3;
195     const std::string s1{"fdsa"};
196     const char *const s2 = "asdf";
197 
198     {
199         testing::InSequence seq;
200         expect_basic<int>(SD_BUS_TYPE_INT32, 1);
201         expect_basic<double>(SD_BUS_TYPE_DOUBLE, 2.2);
202         expect_basic<int>(SD_BUS_TYPE_INT32, c);
203         expect_basic_string(SD_BUS_TYPE_STRING, s1.c_str());
204         expect_basic<int>(SD_BUS_TYPE_BOOLEAN, false);
205         expect_basic_string(SD_BUS_TYPE_STRING, s2);
206     }
207     new_message().append(1, 2.2, c, s1, false, s2);
208 }
209 
210 TEST_F(AppendTest, Array)
211 {
212     const std::array<double, 4> a{1.1, 2.2, 3.3, 4.4};
213 
214     {
215         testing::InSequence seq;
216         expect_open_container(SD_BUS_TYPE_ARRAY, "d");
217         for (const auto &i : a)
218         {
219             expect_basic<double>(SD_BUS_TYPE_DOUBLE, i);
220         }
221         expect_close_container();
222     }
223     new_message().append(a);
224 }
225 
226 TEST_F(AppendTest, Vector)
227 {
228     const std::vector<int> v{1, 2, 3, 4};
229 
230     {
231         testing::InSequence seq;
232         expect_open_container(SD_BUS_TYPE_ARRAY, "i");
233         for (const auto &i : v)
234         {
235             expect_basic<int>(SD_BUS_TYPE_INT32, i);
236         }
237         expect_close_container();
238     }
239     new_message().append(v);
240 }
241 
242 TEST_F(AppendTest, Set)
243 {
244     const std::set<std::string> s{"one", "two", "eight"};
245 
246     {
247         testing::InSequence seq;
248         expect_open_container(SD_BUS_TYPE_ARRAY, "s");
249         for (const auto &i : s)
250         {
251             expect_basic_string(SD_BUS_TYPE_STRING, i.c_str());
252         }
253         expect_close_container();
254     }
255     new_message().append(s);
256 }
257 
258 TEST_F(AppendTest, Map)
259 {
260     const std::map<int, std::string> m{
261         {1, "a"},
262         {2, "bc"},
263         {3, "def"},
264         {4, "ghij"},
265     };
266 
267     {
268         testing::InSequence seq;
269         expect_open_container(SD_BUS_TYPE_ARRAY, "{is}");
270         for (const auto &i : m)
271         {
272             expect_open_container(SD_BUS_TYPE_DICT_ENTRY, "is");
273             expect_basic<int>(SD_BUS_TYPE_INT32, i.first);
274             expect_basic_string(SD_BUS_TYPE_STRING, i.second.c_str());
275             expect_close_container();
276         }
277         expect_close_container();
278     }
279     new_message().append(m);
280 }
281 
282 TEST_F(AppendTest, UnorderedMap)
283 {
284     const std::unordered_map<int, bool> m{
285         {1, false},
286         {2, true},
287         {3, true},
288         {4, false},
289     };
290 
291     {
292         testing::InSequence seq;
293         expect_open_container(SD_BUS_TYPE_ARRAY, "{ib}");
294         for (const auto &i : m)
295         {
296             expect_open_container(SD_BUS_TYPE_DICT_ENTRY, "ib");
297             expect_basic<int>(SD_BUS_TYPE_INT32, i.first);
298             expect_basic<int>(SD_BUS_TYPE_BOOLEAN, i.second);
299             expect_close_container();
300         }
301         expect_close_container();
302     }
303     new_message().append(m);
304 }
305 
306 TEST_F(AppendTest, Tuple)
307 {
308     const std::tuple<int, std::string, bool> t{5, "asdf", false};
309 
310     {
311         testing::InSequence seq;
312         expect_open_container(SD_BUS_TYPE_STRUCT, "isb");
313         expect_basic<int>(SD_BUS_TYPE_INT32, std::get<0>(t));
314         expect_basic_string(SD_BUS_TYPE_STRING, std::get<1>(t).c_str());
315         expect_basic<int>(SD_BUS_TYPE_BOOLEAN, std::get<2>(t));
316         expect_close_container();
317     }
318     new_message().append(t);
319 }
320 
321 TEST_F(AppendTest, Variant)
322 {
323     const bool b1 = false;
324     const std::string s2{"asdf"};
325     const sdbusplus::message::variant<int, std::string, bool> v1{b1}, v2{s2};
326 
327     {
328         testing::InSequence seq;
329         expect_open_container(SD_BUS_TYPE_VARIANT, "b");
330         expect_basic<int>(SD_BUS_TYPE_BOOLEAN, b1);
331         expect_close_container();
332         expect_open_container(SD_BUS_TYPE_VARIANT, "s");
333         expect_basic_string(SD_BUS_TYPE_STRING, s2.c_str());
334         expect_close_container();
335     }
336     new_message().append(v1, v2);
337 }
338 
339 TEST_F(AppendTest, LargeCombo)
340 {
341     std::vector<std::array<std::string, 3>> vas{{"a", "b", "c"},
342                                                 {"d", "", "e"}};
343     std::map<std::string, sdbusplus::message::variant<int, double>> msv = {
344         {"a", 3.3}, {"b", 1}, {"c", 4.4}};
345 
346     {
347         testing::InSequence seq;
348 
349         expect_open_container(SD_BUS_TYPE_ARRAY, "as");
350         for (const auto &as : vas)
351         {
352             expect_open_container(SD_BUS_TYPE_ARRAY, "s");
353             for (const auto &s : as)
354             {
355                 expect_basic_string(SD_BUS_TYPE_STRING, s.c_str());
356             }
357             expect_close_container();
358         }
359         expect_close_container();
360 
361         expect_open_container(SD_BUS_TYPE_ARRAY, "{sv}");
362         for (const auto &sv : msv)
363         {
364             expect_open_container(SD_BUS_TYPE_DICT_ENTRY, "sv");
365             expect_basic_string(SD_BUS_TYPE_STRING, sv.first.c_str());
366             if (sv.second.is<int>())
367             {
368                 expect_open_container(SD_BUS_TYPE_VARIANT, "i");
369                 expect_basic<int>(SD_BUS_TYPE_INT32, sv.second.get<int>());
370                 expect_close_container();
371             }
372             else
373             {
374                 expect_open_container(SD_BUS_TYPE_VARIANT, "d");
375                 expect_basic<double>(SD_BUS_TYPE_DOUBLE,
376                                      sv.second.get<double>());
377                 expect_close_container();
378             }
379             expect_close_container();
380         }
381         expect_close_container();
382     }
383     new_message().append(vas, msv);
384 }
385 
386 } // namespace
387