blob: 8e0e5588c204308c388aec9f7f182dc22bc462c3 [file] [log] [blame]
Patrick Venture95269db2018-08-31 09:19:17 -07001#include <systemd/sd-bus-protocol.h>
2
Patrick Williams7802c072016-09-02 15:20:22 -05003#include <sdbusplus/message.hpp>
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -07004#include <sdbusplus/test/sdbus_mock.hpp>
Patrick Williams127b8ab2020-05-21 15:24:19 -05005
6#include <array>
7#include <map>
Ed Tanous28dc36d2018-02-21 12:22:54 -08008#include <set>
Patrick Williamsb7329a92022-04-28 09:57:23 -05009#include <span>
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -070010#include <string>
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -070011#include <tuple>
12#include <unordered_map>
Patrick Williamsb98bdc62020-06-16 16:15:40 -050013#include <unordered_set>
William A. Kennington III4274c112018-11-26 09:50:13 -080014#include <variant>
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -070015#include <vector>
Patrick Williams1807fa42016-08-01 22:23:30 -050016
Patrick Venture95269db2018-08-31 09:19:17 -070017#include <gmock/gmock.h>
18#include <gtest/gtest.h>
19
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -070020namespace
Patrick Williams1807fa42016-08-01 22:23:30 -050021{
Patrick Williams5b485792016-08-02 07:35:14 -050022
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -070023using testing::Eq;
24using testing::MatcherCast;
25using testing::Pointee;
26using testing::Return;
27using testing::SafeMatcherCast;
28using testing::StrEq;
29
Ed Tanous640a7d52023-01-04 13:17:55 -080030MATCHER_P(iovec_equal, match_string, "")
31{
32 const char* start = std::bit_cast<char*>(arg->iov_base);
33 return std::string(start, arg->iov_len) == match_string;
34}
35
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -070036class AppendTest : public testing::Test
37{
38 protected:
39 testing::StrictMock<sdbusplus::SdBusMock> mock;
40
41 void SetUp() override
42 {
43 EXPECT_CALL(mock, sd_bus_message_new_method_call(testing::_, testing::_,
44 nullptr, nullptr,
45 nullptr, nullptr))
46 .WillRepeatedly(Return(0));
Ed Tanouscb2fbeb2023-01-06 13:16:19 -080047 }
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -070048
Patrick Williams10d7aa12021-11-19 11:36:18 -060049 sdbusplus::message_t new_message()
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -070050 {
51 return sdbusplus::get_mocked_new(&mock).new_method_call(
52 nullptr, nullptr, nullptr, nullptr);
53 }
54
Patrick Venture2b238af2018-08-31 12:45:01 -070055 template <typename T>
56 void expect_basic(char type, T val)
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -070057 {
William A. Kennington IIIe0d69652018-08-31 13:09:47 -070058 EXPECT_CALL(mock, sd_bus_message_append_basic(
59 nullptr, type,
60 MatcherCast<const void*>(
61 SafeMatcherCast<const T*>(Pointee(Eq(val))))))
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -070062 .WillOnce(Return(0));
63 }
64
William A. Kennington IIIe0d69652018-08-31 13:09:47 -070065 void expect_basic_string(char type, const char* str)
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -070066 {
67 EXPECT_CALL(mock, sd_bus_message_append_basic(
68 nullptr, type,
William A. Kennington IIIe0d69652018-08-31 13:09:47 -070069 MatcherCast<const void*>(
70 SafeMatcherCast<const char*>(StrEq(str)))))
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -070071 .WillOnce(Return(0));
72 }
Ed Tanous640a7d52023-01-04 13:17:55 -080073 void expect_basic_string_iovec(const char* str, size_t size)
74 {
75 std::string tmp = {str, size};
76 EXPECT_CALL(mock, sd_bus_message_append_string_iovec(
77 nullptr, iovec_equal(tmp), 1))
78 .WillOnce(Return(0));
79 }
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -070080
William A. Kennington IIIe0d69652018-08-31 13:09:47 -070081 void expect_open_container(char type, const char* contents)
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -070082 {
83 EXPECT_CALL(
84 mock, sd_bus_message_open_container(nullptr, type, StrEq(contents)))
85 .WillOnce(Return(0));
86 }
87
88 void expect_close_container()
89 {
90 EXPECT_CALL(mock, sd_bus_message_close_container(nullptr))
91 .WillOnce(Return(0));
92 }
Ed Tanous242677a2024-03-27 17:56:21 -070093
94 static int on_array_append(sd_bus_message*, char, const void*, size_t)
95 {
96 return 0;
97 }
98
99 void expect_append_array(char type, size_t sz)
100 {
101 EXPECT_CALL(mock,
102 sd_bus_message_append_array(nullptr, type, testing::_, sz))
103 .WillOnce(testing::Invoke(on_array_append));
104 }
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700105};
106
107TEST_F(AppendTest, RValueInt)
108{
Patrick Williamsb7329a92022-04-28 09:57:23 -0500109 static_assert(
110 sdbusplus::message::details::can_append_multiple_v<decltype(1)>);
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700111 expect_basic<int>(SD_BUS_TYPE_INT32, 1);
112 new_message().append(1);
Patrick Williams1807fa42016-08-01 22:23:30 -0500113}
114
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700115TEST_F(AppendTest, LValueInt)
Patrick Williams1807fa42016-08-01 22:23:30 -0500116{
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700117 const int a = 1;
Patrick Williamsb7329a92022-04-28 09:57:23 -0500118 static_assert(
119 sdbusplus::message::details::can_append_multiple_v<decltype(a)>);
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700120 expect_basic<int>(SD_BUS_TYPE_INT32, a);
121 new_message().append(a);
122}
Patrick Williams1807fa42016-08-01 22:23:30 -0500123
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700124TEST_F(AppendTest, XValueInt)
125{
126 int a = 1;
127 expect_basic<int>(SD_BUS_TYPE_INT32, a);
128 new_message().append(std::move(a));
129}
130
131TEST_F(AppendTest, RValueBool)
132{
133 expect_basic<int>(SD_BUS_TYPE_BOOLEAN, true);
134 new_message().append(true);
135}
136
137TEST_F(AppendTest, LValueBool)
138{
139 const bool a = false;
140 expect_basic<int>(SD_BUS_TYPE_BOOLEAN, false);
141 new_message().append(a);
142}
143
144TEST_F(AppendTest, XValueBool)
145{
146 bool a = false;
147 expect_basic<int>(SD_BUS_TYPE_BOOLEAN, false);
148 new_message().append(std::move(a));
149}
150
151TEST_F(AppendTest, RValueDouble)
152{
153 expect_basic<double>(SD_BUS_TYPE_DOUBLE, 1.1);
154 new_message().append(1.1);
155}
156
157TEST_F(AppendTest, LValueDouble)
158{
159 const double a = 1.1;
160 expect_basic<double>(SD_BUS_TYPE_DOUBLE, a);
161 new_message().append(a);
162}
163
164TEST_F(AppendTest, XValueDouble)
165{
166 double a = 1.1;
167 expect_basic<double>(SD_BUS_TYPE_DOUBLE, a);
168 new_message().append(std::move(a));
169}
170
171TEST_F(AppendTest, RValueCString)
172{
173 expect_basic_string(SD_BUS_TYPE_STRING, "asdf");
174 new_message().append("asdf");
175}
176
177TEST_F(AppendTest, LValueCString)
178{
William A. Kennington IIIe0d69652018-08-31 13:09:47 -0700179 const char* const s = "asdf";
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700180 expect_basic_string(SD_BUS_TYPE_STRING, s);
181 new_message().append(s);
182}
183
184TEST_F(AppendTest, XValueCString)
185{
William A. Kennington IIIe0d69652018-08-31 13:09:47 -0700186 const char* s = "asdf";
Patrick Williamsb7329a92022-04-28 09:57:23 -0500187 static_assert(
188 sdbusplus::message::details::can_append_multiple_v<decltype(s)>);
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700189 expect_basic_string(SD_BUS_TYPE_STRING, s);
190 new_message().append(std::move(s));
191}
192
193TEST_F(AppendTest, RValueString)
194{
195 expect_basic_string(SD_BUS_TYPE_STRING, "asdf");
196 new_message().append(std::string{"asdf"});
197}
198
199TEST_F(AppendTest, LValueString)
200{
201 std::string s{"asdf"};
Patrick Williamsb7329a92022-04-28 09:57:23 -0500202 static_assert(
203 !sdbusplus::message::details::can_append_multiple_v<decltype(s)>);
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700204 expect_basic_string(SD_BUS_TYPE_STRING, s.c_str());
205 new_message().append(s);
206}
207
208TEST_F(AppendTest, XValueString)
209{
210 std::string s{"asdf"};
211 expect_basic_string(SD_BUS_TYPE_STRING, s.c_str());
212 new_message().append(std::move(s));
213}
214
Ed Tanous640a7d52023-01-04 13:17:55 -0800215TEST_F(AppendTest, LValueStringView)
216{
217 std::string_view s{"asdf"};
218 expect_basic_string_iovec(s.data(), s.size());
219 new_message().append(s);
220}
221
222TEST_F(AppendTest, RValueStringView)
223{
224 std::string_view s{"asdf"};
225 expect_basic_string_iovec(s.data(), s.size());
226 new_message().append(std::string_view{"asdf"});
227}
228
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700229TEST_F(AppendTest, ObjectPath)
230{
231 sdbusplus::message::object_path o{"/asdf"};
232 expect_basic_string(SD_BUS_TYPE_OBJECT_PATH, o.str.c_str());
233 new_message().append(o);
234}
235
236TEST_F(AppendTest, Signature)
237{
238 sdbusplus::message::signature g{"ii"};
239 expect_basic_string(SD_BUS_TYPE_SIGNATURE, g.str.c_str());
240 new_message().append(g);
241}
242
243TEST_F(AppendTest, CombinedBasic)
244{
245 const int c = 3;
246 const std::string s1{"fdsa"};
William A. Kennington IIIe0d69652018-08-31 13:09:47 -0700247 const char* const s2 = "asdf";
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700248
Patrick Williams1807fa42016-08-01 22:23:30 -0500249 {
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700250 testing::InSequence seq;
251 expect_basic<int>(SD_BUS_TYPE_INT32, 1);
252 expect_basic<double>(SD_BUS_TYPE_DOUBLE, 2.2);
253 expect_basic<int>(SD_BUS_TYPE_INT32, c);
254 expect_basic_string(SD_BUS_TYPE_STRING, s1.c_str());
255 expect_basic<int>(SD_BUS_TYPE_BOOLEAN, false);
256 expect_basic_string(SD_BUS_TYPE_STRING, s2);
257 }
258 new_message().append(1, 2.2, c, s1, false, s2);
259}
Patrick Williams1807fa42016-08-01 22:23:30 -0500260
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700261TEST_F(AppendTest, Array)
262{
263 const std::array<double, 4> a{1.1, 2.2, 3.3, 4.4};
Patrick Williamsb7329a92022-04-28 09:57:23 -0500264 static_assert(
265 !sdbusplus::message::details::can_append_multiple_v<decltype(a)>);
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700266
267 {
Ed Tanous242677a2024-03-27 17:56:21 -0700268 expect_append_array(SD_BUS_TYPE_DOUBLE, a.size() * sizeof(double));
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700269 }
270 new_message().append(a);
271}
Patrick Williams1807fa42016-08-01 22:23:30 -0500272
Patrick Williamsb7329a92022-04-28 09:57:23 -0500273TEST_F(AppendTest, Span)
274{
275 const std::array<double, 4> a{1.1, 2.2, 3.3, 4.4};
276 auto s = std::span{a};
277 static_assert(
278 !sdbusplus::message::details::can_append_multiple_v<decltype(s)>);
279
280 {
Ed Tanous242677a2024-03-27 17:56:21 -0700281 expect_append_array(SD_BUS_TYPE_DOUBLE, a.size() * sizeof(double));
Patrick Williamsb7329a92022-04-28 09:57:23 -0500282 }
283 new_message().append(s);
284}
285
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700286TEST_F(AppendTest, Vector)
287{
Ed Tanousf4265a72024-03-04 21:07:05 -0800288 const std::vector<std::string> v{"a", "b", "c", "d"};
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700289
290 {
291 testing::InSequence seq;
Ed Tanousf4265a72024-03-04 21:07:05 -0800292 expect_open_container(SD_BUS_TYPE_ARRAY, "s");
William A. Kennington IIIe0d69652018-08-31 13:09:47 -0700293 for (const auto& i : v)
Patrick Williams1807fa42016-08-01 22:23:30 -0500294 {
Ed Tanousf4265a72024-03-04 21:07:05 -0800295 expect_basic_string(SD_BUS_TYPE_STRING, i.c_str());
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700296 }
297 expect_close_container();
298 }
299 new_message().append(v);
300}
301
Ed Tanous242677a2024-03-27 17:56:21 -0700302TEST_F(AppendTest, VectorIntegral)
303{
304 const std::vector<int32_t> v{1, 2, 3, 4};
305 expect_append_array(SD_BUS_TYPE_INT32, v.size() * sizeof(int32_t));
306 new_message().append(v);
307}
308
309TEST_F(AppendTest, VectorNestIntegral)
310{
311 const std::vector<std::array<int32_t, 3>> v{
312 {1, 2, 3}, {3, 4, 5}, {6, 7, 8}};
313
314 {
315 testing::InSequence seq;
316 expect_open_container(SD_BUS_TYPE_ARRAY, "ai");
317 for (long unsigned int i = 0; i < v.size(); i++)
318 {
319 expect_append_array(SD_BUS_TYPE_INT32,
320 v[i].size() * sizeof(int32_t));
321 }
322 expect_close_container();
323 }
324 new_message().append(v);
325}
326
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700327TEST_F(AppendTest, Set)
328{
329 const std::set<std::string> s{"one", "two", "eight"};
330
331 {
332 testing::InSequence seq;
333 expect_open_container(SD_BUS_TYPE_ARRAY, "s");
William A. Kennington IIIe0d69652018-08-31 13:09:47 -0700334 for (const auto& i : s)
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700335 {
336 expect_basic_string(SD_BUS_TYPE_STRING, i.c_str());
337 }
338 expect_close_container();
339 }
340 new_message().append(s);
341}
342
Patrick Williamsb98bdc62020-06-16 16:15:40 -0500343TEST_F(AppendTest, UnorderedSet)
344{
345 const std::unordered_set<std::string> s{"one", "two", "eight"};
346
347 {
348 testing::InSequence seq;
349 expect_open_container(SD_BUS_TYPE_ARRAY, "s");
350 for (const auto& i : s)
351 {
352 expect_basic_string(SD_BUS_TYPE_STRING, i.c_str());
353 }
354 expect_close_container();
355 }
356 new_message().append(s);
357}
358
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700359TEST_F(AppendTest, Map)
360{
361 const std::map<int, std::string> m{
362 {1, "a"},
363 {2, "bc"},
364 {3, "def"},
365 {4, "ghij"},
366 };
367
368 {
369 testing::InSequence seq;
370 expect_open_container(SD_BUS_TYPE_ARRAY, "{is}");
William A. Kennington IIIe0d69652018-08-31 13:09:47 -0700371 for (const auto& i : m)
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700372 {
373 expect_open_container(SD_BUS_TYPE_DICT_ENTRY, "is");
374 expect_basic<int>(SD_BUS_TYPE_INT32, i.first);
375 expect_basic_string(SD_BUS_TYPE_STRING, i.second.c_str());
376 expect_close_container();
377 }
378 expect_close_container();
379 }
380 new_message().append(m);
381}
382
383TEST_F(AppendTest, UnorderedMap)
384{
385 const std::unordered_map<int, bool> m{
386 {1, false},
387 {2, true},
388 {3, true},
389 {4, false},
390 };
391
392 {
393 testing::InSequence seq;
394 expect_open_container(SD_BUS_TYPE_ARRAY, "{ib}");
William A. Kennington IIIe0d69652018-08-31 13:09:47 -0700395 for (const auto& i : m)
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700396 {
397 expect_open_container(SD_BUS_TYPE_DICT_ENTRY, "ib");
398 expect_basic<int>(SD_BUS_TYPE_INT32, i.first);
399 expect_basic<int>(SD_BUS_TYPE_BOOLEAN, i.second);
400 expect_close_container();
401 }
402 expect_close_container();
403 }
404 new_message().append(m);
405}
406
407TEST_F(AppendTest, Tuple)
408{
409 const std::tuple<int, std::string, bool> t{5, "asdf", false};
410
411 {
412 testing::InSequence seq;
413 expect_open_container(SD_BUS_TYPE_STRUCT, "isb");
414 expect_basic<int>(SD_BUS_TYPE_INT32, std::get<0>(t));
415 expect_basic_string(SD_BUS_TYPE_STRING, std::get<1>(t).c_str());
416 expect_basic<int>(SD_BUS_TYPE_BOOLEAN, std::get<2>(t));
417 expect_close_container();
418 }
419 new_message().append(t);
420}
421
422TEST_F(AppendTest, Variant)
423{
424 const bool b1 = false;
425 const std::string s2{"asdf"};
William A. Kennington III4274c112018-11-26 09:50:13 -0800426 const std::variant<int, std::string, bool> v1{b1}, v2{s2};
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700427
428 {
429 testing::InSequence seq;
430 expect_open_container(SD_BUS_TYPE_VARIANT, "b");
431 expect_basic<int>(SD_BUS_TYPE_BOOLEAN, b1);
432 expect_close_container();
433 expect_open_container(SD_BUS_TYPE_VARIANT, "s");
434 expect_basic_string(SD_BUS_TYPE_STRING, s2.c_str());
435 expect_close_container();
436 }
437 new_message().append(v1, v2);
438}
439
440TEST_F(AppendTest, LargeCombo)
441{
442 std::vector<std::array<std::string, 3>> vas{{"a", "b", "c"},
443 {"d", "", "e"}};
William A. Kennington III4274c112018-11-26 09:50:13 -0800444 std::map<std::string, std::variant<int, double>> msv = {
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700445 {"a", 3.3}, {"b", 1}, {"c", 4.4}};
446
447 {
448 testing::InSequence seq;
449
450 expect_open_container(SD_BUS_TYPE_ARRAY, "as");
William A. Kennington IIIe0d69652018-08-31 13:09:47 -0700451 for (const auto& as : vas)
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700452 {
453 expect_open_container(SD_BUS_TYPE_ARRAY, "s");
William A. Kennington IIIe0d69652018-08-31 13:09:47 -0700454 for (const auto& s : as)
Patrick Williams07e1d6f2016-09-08 15:54:09 -0500455 {
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700456 expect_basic_string(SD_BUS_TYPE_STRING, s.c_str());
457 }
458 expect_close_container();
459 }
460 expect_close_container();
461
462 expect_open_container(SD_BUS_TYPE_ARRAY, "{sv}");
William A. Kennington IIIe0d69652018-08-31 13:09:47 -0700463 for (const auto& sv : msv)
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700464 {
465 expect_open_container(SD_BUS_TYPE_DICT_ENTRY, "sv");
466 expect_basic_string(SD_BUS_TYPE_STRING, sv.first.c_str());
William A. Kennington III4274c112018-11-26 09:50:13 -0800467 if (std::holds_alternative<int>(sv.second))
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700468 {
469 expect_open_container(SD_BUS_TYPE_VARIANT, "i");
William A. Kennington III4274c112018-11-26 09:50:13 -0800470 expect_basic<int>(SD_BUS_TYPE_INT32, std::get<int>(sv.second));
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700471 expect_close_container();
Patrick Williams07e1d6f2016-09-08 15:54:09 -0500472 }
473 else
474 {
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700475 expect_open_container(SD_BUS_TYPE_VARIANT, "d");
476 expect_basic<double>(SD_BUS_TYPE_DOUBLE,
William A. Kennington III4274c112018-11-26 09:50:13 -0800477 std::get<double>(sv.second));
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700478 expect_close_container();
Patrick Williams07e1d6f2016-09-08 15:54:09 -0500479 }
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700480 expect_close_container();
Patrick Williams1807fa42016-08-01 22:23:30 -0500481 }
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700482 expect_close_container();
Patrick Williams1807fa42016-08-01 22:23:30 -0500483 }
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700484 new_message().append(vas, msv);
Patrick Williams1807fa42016-08-01 22:23:30 -0500485}
486
William A. Kennington IIIa1e9e2a2018-06-23 13:33:25 -0700487} // namespace