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