1 // Copyright 2014 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <brillo/dbus/data_serialization.h>
6
7 #include <limits>
8
9 #include <base/files/scoped_file.h>
10 #include <brillo/variant_dictionary.h>
11 #include <gtest/gtest.h>
12
13 #include "brillo/dbus/test.pb.h"
14
15 using base::ScopedFD;
16 using dbus::Message;
17 using dbus::MessageReader;
18 using dbus::MessageWriter;
19 using dbus::ObjectPath;
20 using dbus::Response;
21
22 namespace brillo {
23 namespace dbus_utils {
24
TEST(DBusUtils,Supported_BasicTypes)25 TEST(DBusUtils, Supported_BasicTypes) {
26 EXPECT_TRUE(IsTypeSupported<bool>::value);
27 EXPECT_TRUE(IsTypeSupported<uint8_t>::value);
28 EXPECT_TRUE(IsTypeSupported<int16_t>::value);
29 EXPECT_TRUE(IsTypeSupported<uint16_t>::value);
30 EXPECT_TRUE(IsTypeSupported<int32_t>::value);
31 EXPECT_TRUE(IsTypeSupported<uint32_t>::value);
32 EXPECT_TRUE(IsTypeSupported<int64_t>::value);
33 EXPECT_TRUE(IsTypeSupported<uint64_t>::value);
34 EXPECT_TRUE(IsTypeSupported<double>::value);
35 EXPECT_TRUE(IsTypeSupported<std::string>::value);
36 EXPECT_TRUE(IsTypeSupported<ObjectPath>::value);
37 EXPECT_TRUE(IsTypeSupported<ScopedFD>::value);
38 EXPECT_TRUE(IsTypeSupported<Any>::value);
39 EXPECT_TRUE(IsTypeSupported<google::protobuf::MessageLite>::value);
40 EXPECT_TRUE(IsTypeSupported<dbus_utils_test::TestMessage>::value);
41 }
42
TEST(DBusUtils,Unsupported_BasicTypes)43 TEST(DBusUtils, Unsupported_BasicTypes) {
44 EXPECT_FALSE(IsTypeSupported<char>::value);
45 EXPECT_FALSE(IsTypeSupported<float>::value);
46 }
47
TEST(DBusUtils,Supported_ComplexTypes)48 TEST(DBusUtils, Supported_ComplexTypes) {
49 EXPECT_TRUE(IsTypeSupported<std::vector<bool>>::value);
50 EXPECT_TRUE(IsTypeSupported<std::vector<uint8_t>>::value);
51 EXPECT_TRUE((IsTypeSupported<std::pair<int16_t, double>>::value));
52 EXPECT_TRUE(
53 (IsTypeSupported<std::map<uint16_t, std::vector<int64_t>>>::value));
54 EXPECT_TRUE((IsTypeSupported<std::tuple<bool, double, int32_t>>::value));
55 EXPECT_TRUE(
56 IsTypeSupported<std::vector<dbus_utils_test::TestMessage>>::value);
57 }
58
TEST(DBusUtils,Unsupported_ComplexTypes)59 TEST(DBusUtils, Unsupported_ComplexTypes) {
60 EXPECT_FALSE(IsTypeSupported<std::vector<char>>::value);
61 EXPECT_FALSE((IsTypeSupported<std::pair<int16_t, float>>::value));
62 EXPECT_FALSE((IsTypeSupported<std::pair<char, int32_t>>::value));
63 EXPECT_FALSE((IsTypeSupported<std::map<int16_t, float>>::value));
64 EXPECT_FALSE((IsTypeSupported<std::map<char, int32_t>>::value));
65 EXPECT_FALSE((IsTypeSupported<std::tuple<bool, char, int32_t>>::value));
66 }
67
TEST(DBusUtils,Supported_TypeSet)68 TEST(DBusUtils, Supported_TypeSet) {
69 EXPECT_TRUE((IsTypeSupported<int32_t, double, std::string>::value));
70 EXPECT_TRUE((IsTypeSupported<bool, std::vector<int32_t>, uint8_t>::value));
71 }
72
TEST(DBusUtils,Unupported_TypeSet)73 TEST(DBusUtils, Unupported_TypeSet) {
74 EXPECT_FALSE((IsTypeSupported<int32_t, double, std::string, char>::value));
75 EXPECT_FALSE(
76 (IsTypeSupported<bool, std::pair<std::vector<float>, uint8_t>>::value));
77 EXPECT_FALSE((IsTypeSupported<char, double, std::string, int16_t>::value));
78 EXPECT_FALSE((IsTypeSupported<char, std::vector<float>, float>::value));
79 }
80
TEST(DBusUtils,Signatures_BasicTypes)81 TEST(DBusUtils, Signatures_BasicTypes) {
82 EXPECT_EQ("b", GetDBusSignature<bool>());
83 EXPECT_EQ("y", GetDBusSignature<uint8_t>());
84 EXPECT_EQ("n", GetDBusSignature<int16_t>());
85 EXPECT_EQ("q", GetDBusSignature<uint16_t>());
86 EXPECT_EQ("i", GetDBusSignature<int32_t>());
87 EXPECT_EQ("u", GetDBusSignature<uint32_t>());
88 EXPECT_EQ("x", GetDBusSignature<int64_t>());
89 EXPECT_EQ("t", GetDBusSignature<uint64_t>());
90 EXPECT_EQ("d", GetDBusSignature<double>());
91 EXPECT_EQ("s", GetDBusSignature<std::string>());
92 EXPECT_EQ("o", GetDBusSignature<ObjectPath>());
93 EXPECT_EQ("h", GetDBusSignature<ScopedFD>());
94 EXPECT_EQ("v", GetDBusSignature<Any>());
95 }
96
TEST(DBusUtils,Signatures_Arrays)97 TEST(DBusUtils, Signatures_Arrays) {
98 EXPECT_EQ("ab", GetDBusSignature<std::vector<bool>>());
99 EXPECT_EQ("ay", GetDBusSignature<std::vector<uint8_t>>());
100 EXPECT_EQ("an", GetDBusSignature<std::vector<int16_t>>());
101 EXPECT_EQ("aq", GetDBusSignature<std::vector<uint16_t>>());
102 EXPECT_EQ("ai", GetDBusSignature<std::vector<int32_t>>());
103 EXPECT_EQ("au", GetDBusSignature<std::vector<uint32_t>>());
104 EXPECT_EQ("ax", GetDBusSignature<std::vector<int64_t>>());
105 EXPECT_EQ("at", GetDBusSignature<std::vector<uint64_t>>());
106 EXPECT_EQ("ad", GetDBusSignature<std::vector<double>>());
107 EXPECT_EQ("as", GetDBusSignature<std::vector<std::string>>());
108 EXPECT_EQ("ao", GetDBusSignature<std::vector<ObjectPath>>());
109 EXPECT_EQ("ah", GetDBusSignature<std::vector<ScopedFD>>());
110 EXPECT_EQ("av", GetDBusSignature<std::vector<Any>>());
111 EXPECT_EQ("a(is)",
112 (GetDBusSignature<std::vector<std::pair<int, std::string>>>()));
113 EXPECT_EQ("aad", GetDBusSignature<std::vector<std::vector<double>>>());
114 }
115
TEST(DBusUtils,Signatures_Maps)116 TEST(DBusUtils, Signatures_Maps) {
117 EXPECT_EQ("a{sb}", (GetDBusSignature<std::map<std::string, bool>>()));
118 EXPECT_EQ("a{ss}", (GetDBusSignature<std::map<std::string, std::string>>()));
119 EXPECT_EQ("a{sv}", (GetDBusSignature<std::map<std::string, Any>>()));
120 EXPECT_EQ("a{id}", (GetDBusSignature<std::map<int, double>>()));
121 EXPECT_EQ(
122 "a{ia{ss}}",
123 (GetDBusSignature<std::map<int, std::map<std::string, std::string>>>()));
124 }
125
TEST(DBusUtils,Signatures_Pairs)126 TEST(DBusUtils, Signatures_Pairs) {
127 EXPECT_EQ("(sb)", (GetDBusSignature<std::pair<std::string, bool>>()));
128 EXPECT_EQ("(sv)", (GetDBusSignature<std::pair<std::string, Any>>()));
129 EXPECT_EQ("(id)", (GetDBusSignature<std::pair<int, double>>()));
130 }
131
TEST(DBusUtils,Signatures_Tuples)132 TEST(DBusUtils, Signatures_Tuples) {
133 EXPECT_EQ("(i)", (GetDBusSignature<std::tuple<int>>()));
134 EXPECT_EQ("(sv)", (GetDBusSignature<std::tuple<std::string, Any>>()));
135 EXPECT_EQ("(id(si))",
136 (GetDBusSignature<
137 std::tuple<int, double, std::tuple<std::string, int>>>()));
138 }
139
TEST(DBusUtils,Signatures_Protobufs)140 TEST(DBusUtils, Signatures_Protobufs) {
141 EXPECT_EQ("ay", (GetDBusSignature<google::protobuf::MessageLite>()));
142 EXPECT_EQ("ay", (GetDBusSignature<dbus_utils_test::TestMessage>()));
143 }
144
145 // Test that a byte can be properly written and read. We only have this
146 // test for byte, as repeating this for other basic types is too redundant.
TEST(DBusUtils,AppendAndPopByte)147 TEST(DBusUtils, AppendAndPopByte) {
148 std::unique_ptr<Response> message = Response::CreateEmpty();
149 MessageWriter writer(message.get());
150 AppendValueToWriter(&writer, uint8_t{123});
151 EXPECT_EQ("y", message->GetSignature());
152
153 MessageReader reader(message.get());
154 EXPECT_TRUE(reader.HasMoreData()); // Should have data to read.
155 EXPECT_EQ(Message::BYTE, reader.GetDataType());
156
157 bool bool_value = false;
158 // Should fail as the type is not bool here.
159 EXPECT_FALSE(PopValueFromReader(&reader, &bool_value));
160
161 uint8_t byte_value = 0;
162 EXPECT_TRUE(PopValueFromReader(&reader, &byte_value));
163 EXPECT_EQ(123, byte_value); // Should match with the input.
164 EXPECT_FALSE(reader.HasMoreData()); // Should not have more data to read.
165
166 // Try to get another byte. Should fail.
167 EXPECT_FALSE(PopValueFromReader(&reader, &byte_value));
168 }
169
170 // Check all basic types can be properly written and read.
TEST(DBusUtils,AppendAndPopBasicDataTypes)171 TEST(DBusUtils, AppendAndPopBasicDataTypes) {
172 std::unique_ptr<Response> message = Response::CreateEmpty();
173 MessageWriter writer(message.get());
174
175 // Append 0, true, 2, 3, 4, 5, 6, 7, 8.0, "string", "/object/path".
176 AppendValueToWriter(&writer, uint8_t{0});
177 AppendValueToWriter(&writer, bool{true});
178 AppendValueToWriter(&writer, int16_t{2});
179 AppendValueToWriter(&writer, uint16_t{3});
180 AppendValueToWriter(&writer, int32_t{4});
181 AppendValueToWriter(&writer, uint32_t{5});
182 AppendValueToWriter(&writer, int64_t{6});
183 AppendValueToWriter(&writer, uint64_t{7});
184 AppendValueToWriter(&writer, double{8.0});
185 AppendValueToWriter(&writer, std::string{"string"});
186 AppendValueToWriter(&writer, ObjectPath{"/object/path"});
187
188 EXPECT_EQ("ybnqiuxtdso", message->GetSignature());
189
190 uint8_t byte_value = 0;
191 bool bool_value = false;
192 int16_t int16_value = 0;
193 uint16_t uint16_value = 0;
194 int32_t int32_value = 0;
195 uint32_t uint32_value = 0;
196 int64_t int64_value = 0;
197 uint64_t uint64_value = 0;
198 double double_value = 0;
199 std::string string_value;
200 ObjectPath object_path_value;
201
202 MessageReader reader(message.get());
203 EXPECT_TRUE(reader.HasMoreData());
204 EXPECT_TRUE(PopValueFromReader(&reader, &byte_value));
205 EXPECT_TRUE(PopValueFromReader(&reader, &bool_value));
206 EXPECT_TRUE(PopValueFromReader(&reader, &int16_value));
207 EXPECT_TRUE(PopValueFromReader(&reader, &uint16_value));
208 EXPECT_TRUE(PopValueFromReader(&reader, &int32_value));
209 EXPECT_TRUE(PopValueFromReader(&reader, &uint32_value));
210 EXPECT_TRUE(PopValueFromReader(&reader, &int64_value));
211 EXPECT_TRUE(PopValueFromReader(&reader, &uint64_value));
212 EXPECT_TRUE(PopValueFromReader(&reader, &double_value));
213 EXPECT_TRUE(PopValueFromReader(&reader, &string_value));
214 EXPECT_TRUE(PopValueFromReader(&reader, &object_path_value));
215 EXPECT_FALSE(reader.HasMoreData());
216
217 // 0, true, 2, 3, 4, 5, 6, 7, 8, "string", "/object/path" should be returned.
218 EXPECT_EQ(0, byte_value);
219 EXPECT_TRUE(bool_value);
220 EXPECT_EQ(2, int16_value);
221 EXPECT_EQ(3U, uint16_value);
222 EXPECT_EQ(4, int32_value);
223 EXPECT_EQ(5U, uint32_value);
224 EXPECT_EQ(6, int64_value);
225 EXPECT_EQ(7U, uint64_value);
226 EXPECT_DOUBLE_EQ(8.0, double_value);
227 EXPECT_EQ("string", string_value);
228 EXPECT_EQ(ObjectPath{"/object/path"}, object_path_value);
229 }
230
231 // Check all basic types can be properly written and read.
TEST(DBusUtils,AppendAndPopFileDescriptor)232 TEST(DBusUtils, AppendAndPopFileDescriptor) {
233 if (!dbus::IsDBusTypeUnixFdSupported()) {
234 LOG(WARNING) << "FD passing is not supported";
235 return;
236 }
237
238 std::unique_ptr<Response> message = Response::CreateEmpty();
239 MessageWriter writer(message.get());
240
241 // Append stdout.
242 ScopedFD temp(1);
243 // Descriptor should not be valid until checked.
244 EXPECT_FALSE(temp.is_valid());
245 // NB: thread IO requirements not relevant for unit tests.
246 temp.CheckValidity();
247 EXPECT_TRUE(temp.is_valid());
248 AppendValueToWriter(&writer, temp);
249
250 EXPECT_EQ("h", message->GetSignature());
251
252 ScopedFD fd_value;
253
254 MessageReader reader(message.get());
255 EXPECT_TRUE(reader.HasMoreData());
256 EXPECT_TRUE(PopValueFromReader(&reader, &fd_value));
257 EXPECT_FALSE(reader.HasMoreData());
258 // Descriptor is automatically checked for validity as part of
259 // PopValueFromReader() call.
260 EXPECT_TRUE(fd_value.is_valid());
261 }
262
263 // Check all variant types can be properly written and read.
TEST(DBusUtils,AppendAndPopVariantDataTypes)264 TEST(DBusUtils, AppendAndPopVariantDataTypes) {
265 std::unique_ptr<Response> message = Response::CreateEmpty();
266 MessageWriter writer(message.get());
267
268 // Append 10, false, 12, 13, 14, 15, 16, 17, 18.5, "data", "/obj/path".
269 AppendValueToWriterAsVariant(&writer, uint8_t{10});
270 AppendValueToWriterAsVariant(&writer, bool{false});
271 AppendValueToWriterAsVariant(&writer, int16_t{12});
272 AppendValueToWriterAsVariant(&writer, uint16_t{13});
273 AppendValueToWriterAsVariant(&writer, int32_t{14});
274 AppendValueToWriterAsVariant(&writer, uint32_t{15});
275 AppendValueToWriterAsVariant(&writer, int64_t{16});
276 AppendValueToWriterAsVariant(&writer, uint64_t{17});
277 AppendValueToWriterAsVariant(&writer, double{18.5});
278 AppendValueToWriterAsVariant(&writer, std::string{"data"});
279 AppendValueToWriterAsVariant(&writer, ObjectPath{"/obj/path"});
280 AppendValueToWriterAsVariant(&writer, Any{17});
281 AppendValueToWriterAsVariant(&writer,
282 Any{std::vector<std::vector<int>>{{6, 7}}});
283
284 EXPECT_EQ("vvvvvvvvvvvvv", message->GetSignature());
285
286 uint8_t byte_value = 0;
287 bool bool_value = true;
288 int16_t int16_value = 0;
289 uint16_t uint16_value = 0;
290 int32_t int32_value = 0;
291 uint32_t uint32_value = 0;
292 int64_t int64_value = 0;
293 uint64_t uint64_value = 0;
294 double double_value = 0;
295 std::string string_value;
296 ObjectPath object_path_value;
297 Any any_value;
298 Any any_vector_vector;
299
300 MessageReader reader(message.get());
301 EXPECT_TRUE(reader.HasMoreData());
302 EXPECT_TRUE(PopVariantValueFromReader(&reader, &byte_value));
303 EXPECT_TRUE(PopVariantValueFromReader(&reader, &bool_value));
304 EXPECT_TRUE(PopVariantValueFromReader(&reader, &int16_value));
305 EXPECT_TRUE(PopVariantValueFromReader(&reader, &uint16_value));
306 EXPECT_TRUE(PopVariantValueFromReader(&reader, &int32_value));
307 EXPECT_TRUE(PopVariantValueFromReader(&reader, &uint32_value));
308 EXPECT_TRUE(PopVariantValueFromReader(&reader, &int64_value));
309 EXPECT_TRUE(PopVariantValueFromReader(&reader, &uint64_value));
310 EXPECT_TRUE(PopVariantValueFromReader(&reader, &double_value));
311 EXPECT_TRUE(PopVariantValueFromReader(&reader, &string_value));
312 EXPECT_TRUE(PopVariantValueFromReader(&reader, &object_path_value));
313 EXPECT_TRUE(PopVariantValueFromReader(&reader, &any_value));
314 // Not implemented.
315 EXPECT_FALSE(PopVariantValueFromReader(&reader, &any_vector_vector));
316 EXPECT_FALSE(reader.HasMoreData());
317
318 EXPECT_EQ(10, byte_value);
319 EXPECT_FALSE(bool_value);
320 EXPECT_EQ(12, int16_value);
321 EXPECT_EQ(13U, uint16_value);
322 EXPECT_EQ(14, int32_value);
323 EXPECT_EQ(15U, uint32_value);
324 EXPECT_EQ(16, int64_value);
325 EXPECT_EQ(17U, uint64_value);
326 EXPECT_DOUBLE_EQ(18.5, double_value);
327 EXPECT_EQ("data", string_value);
328 EXPECT_EQ(ObjectPath{"/obj/path"}, object_path_value);
329 EXPECT_EQ(17, any_value.Get<int>());
330 EXPECT_TRUE(any_vector_vector.IsEmpty());
331 }
332
TEST(DBusUtils,AppendAndPopBasicAny)333 TEST(DBusUtils, AppendAndPopBasicAny) {
334 std::unique_ptr<Response> message = Response::CreateEmpty();
335 MessageWriter writer(message.get());
336
337 // Append 10, true, 12, 13, 14, 15, 16, 17, 18.5, "data", "/obj/path".
338 AppendValueToWriter(&writer, Any(uint8_t{10}));
339 AppendValueToWriter(&writer, Any(bool{true}));
340 AppendValueToWriter(&writer, Any(int16_t{12}));
341 AppendValueToWriter(&writer, Any(uint16_t{13}));
342 AppendValueToWriter(&writer, Any(int32_t{14}));
343 AppendValueToWriter(&writer, Any(uint32_t{15}));
344 AppendValueToWriter(&writer, Any(int64_t{16}));
345 AppendValueToWriter(&writer, Any(uint64_t{17}));
346 AppendValueToWriter(&writer, Any(double{18.5}));
347 AppendValueToWriter(&writer, Any(std::string{"data"}));
348 AppendValueToWriter(&writer, Any(ObjectPath{"/obj/path"}));
349 EXPECT_EQ("vvvvvvvvvvv", message->GetSignature());
350
351 Any byte_value;
352 Any bool_value;
353 Any int16_value;
354 Any uint16_value;
355 Any int32_value;
356 Any uint32_value;
357 Any int64_value;
358 Any uint64_value;
359 Any double_value;
360 Any string_value;
361 Any object_path_value;
362
363 MessageReader reader(message.get());
364 EXPECT_TRUE(reader.HasMoreData());
365 EXPECT_TRUE(PopValueFromReader(&reader, &byte_value));
366 EXPECT_TRUE(PopValueFromReader(&reader, &bool_value));
367 EXPECT_TRUE(PopValueFromReader(&reader, &int16_value));
368 EXPECT_TRUE(PopValueFromReader(&reader, &uint16_value));
369 EXPECT_TRUE(PopValueFromReader(&reader, &int32_value));
370 EXPECT_TRUE(PopValueFromReader(&reader, &uint32_value));
371 EXPECT_TRUE(PopValueFromReader(&reader, &int64_value));
372 EXPECT_TRUE(PopValueFromReader(&reader, &uint64_value));
373 EXPECT_TRUE(PopValueFromReader(&reader, &double_value));
374 EXPECT_TRUE(PopValueFromReader(&reader, &string_value));
375 EXPECT_TRUE(PopValueFromReader(&reader, &object_path_value));
376 EXPECT_FALSE(reader.HasMoreData());
377
378 // Must be: 10, true, 12, 13, 14, 15, 16, 17, 18.5, "data", "/obj/path".
379 EXPECT_EQ(10, byte_value.Get<uint8_t>());
380 EXPECT_TRUE(bool_value.Get<bool>());
381 EXPECT_EQ(12, int16_value.Get<int16_t>());
382 EXPECT_EQ(13U, uint16_value.Get<uint16_t>());
383 EXPECT_EQ(14, int32_value.Get<int32_t>());
384 EXPECT_EQ(15U, uint32_value.Get<uint32_t>());
385 EXPECT_EQ(16, int64_value.Get<int64_t>());
386 EXPECT_EQ(17U, uint64_value.Get<uint64_t>());
387 EXPECT_DOUBLE_EQ(18.5, double_value.Get<double>());
388 EXPECT_EQ("data", string_value.Get<std::string>());
389 EXPECT_EQ(ObjectPath{"/obj/path"}, object_path_value.Get<ObjectPath>());
390 }
391
TEST(DBusUtils,ArrayOfBytes)392 TEST(DBusUtils, ArrayOfBytes) {
393 std::unique_ptr<Response> message = Response::CreateEmpty();
394 MessageWriter writer(message.get());
395 std::vector<uint8_t> bytes{1, 2, 3};
396 AppendValueToWriter(&writer, bytes);
397
398 EXPECT_EQ("ay", message->GetSignature());
399
400 MessageReader reader(message.get());
401 std::vector<uint8_t> bytes_out;
402 EXPECT_TRUE(PopValueFromReader(&reader, &bytes_out));
403 EXPECT_FALSE(reader.HasMoreData());
404 EXPECT_EQ(bytes, bytes_out);
405 }
406
TEST(DBusUtils,ArrayOfBytes_Empty)407 TEST(DBusUtils, ArrayOfBytes_Empty) {
408 std::unique_ptr<Response> message = Response::CreateEmpty();
409 MessageWriter writer(message.get());
410 std::vector<uint8_t> bytes;
411 AppendValueToWriter(&writer, bytes);
412
413 EXPECT_EQ("ay", message->GetSignature());
414
415 MessageReader reader(message.get());
416 std::vector<uint8_t> bytes_out;
417 EXPECT_TRUE(PopValueFromReader(&reader, &bytes_out));
418 EXPECT_FALSE(reader.HasMoreData());
419 EXPECT_EQ(bytes, bytes_out);
420 }
421
TEST(DBusUtils,ArrayOfStrings)422 TEST(DBusUtils, ArrayOfStrings) {
423 std::unique_ptr<Response> message = Response::CreateEmpty();
424 MessageWriter writer(message.get());
425 std::vector<std::string> strings{"foo", "bar", "baz"};
426 AppendValueToWriter(&writer, strings);
427
428 EXPECT_EQ("as", message->GetSignature());
429
430 MessageReader reader(message.get());
431 std::vector<std::string> strings_out;
432 EXPECT_TRUE(PopValueFromReader(&reader, &strings_out));
433 EXPECT_FALSE(reader.HasMoreData());
434 EXPECT_EQ(strings, strings_out);
435 }
436
TEST(DBusUtils,ArrayOfInt64)437 TEST(DBusUtils, ArrayOfInt64) {
438 std::unique_ptr<Response> message = Response::CreateEmpty();
439 MessageWriter writer(message.get());
440 std::vector<int64_t> values{-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5,
441 std::numeric_limits<int64_t>::min(),
442 std::numeric_limits<int64_t>::max()};
443 AppendValueToWriter(&writer, values);
444
445 EXPECT_EQ("ax", message->GetSignature());
446
447 MessageReader reader(message.get());
448 std::vector<int64_t> values_out;
449 EXPECT_TRUE(PopValueFromReader(&reader, &values_out));
450 EXPECT_FALSE(reader.HasMoreData());
451 EXPECT_EQ(values, values_out);
452 }
453
TEST(DBusUtils,ArrayOfObjectPaths)454 TEST(DBusUtils, ArrayOfObjectPaths) {
455 std::unique_ptr<Response> message = Response::CreateEmpty();
456 MessageWriter writer(message.get());
457 std::vector<ObjectPath> object_paths{
458 ObjectPath("/object/path/1"),
459 ObjectPath("/object/path/2"),
460 ObjectPath("/object/path/3"),
461 };
462 AppendValueToWriter(&writer, object_paths);
463
464 EXPECT_EQ("ao", message->GetSignature());
465
466 MessageReader reader(message.get());
467 std::vector<ObjectPath> object_paths_out;
468 EXPECT_TRUE(PopValueFromReader(&reader, &object_paths_out));
469 EXPECT_FALSE(reader.HasMoreData());
470 EXPECT_EQ(object_paths, object_paths_out);
471 }
472
TEST(DBusUtils,ArraysAsVariant)473 TEST(DBusUtils, ArraysAsVariant) {
474 std::unique_ptr<Response> message = Response::CreateEmpty();
475 MessageWriter writer(message.get());
476 std::vector<int> int_array{1, 2, 3};
477 std::vector<std::string> str_array{"foo", "bar", "baz"};
478 std::vector<double> dbl_array_empty{};
479 std::map<std::string, std::string> dict_ss{{"k1", "v1"}, {"k2", "v2"}};
480 VariantDictionary dict_sv{{"k1", 1}, {"k2", "v2"}};
481 AppendValueToWriterAsVariant(&writer, int_array);
482 AppendValueToWriterAsVariant(&writer, str_array);
483 AppendValueToWriterAsVariant(&writer, dbl_array_empty);
484 AppendValueToWriterAsVariant(&writer, dict_ss);
485 AppendValueToWriterAsVariant(&writer, dict_sv);
486
487 EXPECT_EQ("vvvvv", message->GetSignature());
488
489 Any int_array_out;
490 Any str_array_out;
491 Any dbl_array_out;
492 Any dict_ss_out;
493 Any dict_sv_out;
494
495 MessageReader reader(message.get());
496 EXPECT_TRUE(PopValueFromReader(&reader, &int_array_out));
497 EXPECT_TRUE(PopValueFromReader(&reader, &str_array_out));
498 EXPECT_TRUE(PopValueFromReader(&reader, &dbl_array_out));
499 EXPECT_TRUE(PopValueFromReader(&reader, &dict_ss_out));
500 EXPECT_TRUE(PopValueFromReader(&reader, &dict_sv_out));
501 EXPECT_FALSE(reader.HasMoreData());
502
503 EXPECT_EQ(int_array, int_array_out.Get<std::vector<int>>());
504 EXPECT_EQ(str_array, str_array_out.Get<std::vector<std::string>>());
505 EXPECT_EQ(dbl_array_empty, dbl_array_out.Get<std::vector<double>>());
506 EXPECT_EQ(dict_ss, (dict_ss_out.Get<std::map<std::string, std::string>>()));
507 EXPECT_EQ(dict_sv["k1"].Get<int>(),
508 dict_sv_out.Get<VariantDictionary>().at("k1").Get<int>());
509 EXPECT_EQ(dict_sv["k2"].Get<const char*>(),
510 dict_sv_out.Get<VariantDictionary>().at("k2").Get<std::string>());
511 }
512
TEST(DBusUtils,VariantDictionary)513 TEST(DBusUtils, VariantDictionary) {
514 std::unique_ptr<Response> message = Response::CreateEmpty();
515 MessageWriter writer(message.get());
516 VariantDictionary values{
517 {"key1", uint8_t{10}},
518 {"key2", bool{true}},
519 {"key3", int16_t{12}},
520 {"key4", uint16_t{13}},
521 {"key5", int32_t{14}},
522 {"key6", uint32_t{15}},
523 {"key7", int64_t{16}},
524 {"key8", uint64_t{17}},
525 {"key9", double{18.5}},
526 {"keyA", std::string{"data"}},
527 {"keyB", ObjectPath{"/obj/path"}},
528 };
529 AppendValueToWriter(&writer, values);
530
531 EXPECT_EQ("a{sv}", message->GetSignature());
532
533 MessageReader reader(message.get());
534 VariantDictionary values_out;
535 EXPECT_TRUE(PopValueFromReader(&reader, &values_out));
536 EXPECT_FALSE(reader.HasMoreData());
537 EXPECT_EQ(values.size(), values_out.size());
538 EXPECT_EQ(values["key1"].Get<uint8_t>(), values_out["key1"].Get<uint8_t>());
539 EXPECT_EQ(values["key2"].Get<bool>(), values_out["key2"].Get<bool>());
540 EXPECT_EQ(values["key3"].Get<int16_t>(), values_out["key3"].Get<int16_t>());
541 EXPECT_EQ(values["key4"].Get<uint16_t>(), values_out["key4"].Get<uint16_t>());
542 EXPECT_EQ(values["key5"].Get<int32_t>(), values_out["key5"].Get<int32_t>());
543 EXPECT_EQ(values["key6"].Get<uint32_t>(), values_out["key6"].Get<uint32_t>());
544 EXPECT_EQ(values["key7"].Get<int64_t>(), values_out["key7"].Get<int64_t>());
545 EXPECT_EQ(values["key8"].Get<uint64_t>(), values_out["key8"].Get<uint64_t>());
546 EXPECT_EQ(values["key9"].Get<double>(), values_out["key9"].Get<double>());
547 EXPECT_EQ(values["keyA"].Get<std::string>(),
548 values_out["keyA"].Get<std::string>());
549 EXPECT_EQ(values["keyB"].Get<ObjectPath>(),
550 values_out["keyB"].Get<ObjectPath>());
551 }
552
TEST(DBusUtils,StringToStringMap)553 TEST(DBusUtils, StringToStringMap) {
554 std::unique_ptr<Response> message = Response::CreateEmpty();
555 MessageWriter writer(message.get());
556 std::map<std::string, std::string> values{
557 {"key1", "value1"},
558 {"key2", "value2"},
559 {"key3", "value3"},
560 {"key4", "value4"},
561 {"key5", "value5"},
562 };
563 AppendValueToWriter(&writer, values);
564
565 EXPECT_EQ("a{ss}", message->GetSignature());
566
567 MessageReader reader(message.get());
568 std::map<std::string, std::string> values_out;
569 EXPECT_TRUE(PopValueFromReader(&reader, &values_out));
570 EXPECT_FALSE(reader.HasMoreData());
571 EXPECT_EQ(values, values_out);
572 }
573
TEST(DBusUtils,Pair)574 TEST(DBusUtils, Pair) {
575 std::unique_ptr<Response> message = Response::CreateEmpty();
576 MessageWriter writer(message.get());
577 std::pair<std::string, int> struct1{"value2", 3};
578 AppendValueToWriter(&writer, struct1);
579 std::pair<int, std::pair<int, int>> struct2{1, {2, 3}};
580 AppendValueToWriter(&writer, struct2);
581
582 EXPECT_EQ("(si)(i(ii))", message->GetSignature());
583
584 std::pair<std::string, int> struct1_out;
585 std::pair<int, std::pair<int, int>> struct2_out;
586
587 MessageReader reader(message.get());
588 EXPECT_TRUE(PopValueFromReader(&reader, &struct1_out));
589 EXPECT_TRUE(PopValueFromReader(&reader, &struct2_out));
590 EXPECT_FALSE(reader.HasMoreData());
591 EXPECT_EQ(struct1, struct1_out);
592 EXPECT_EQ(struct2, struct2_out);
593 }
594
TEST(DBusUtils,Tuple)595 TEST(DBusUtils, Tuple) {
596 std::unique_ptr<Response> message = Response::CreateEmpty();
597 MessageWriter writer(message.get());
598 std::tuple<std::string, int> struct1{"value2", 3};
599 AppendValueToWriter(&writer, struct1);
600 std::tuple<int, std::string, std::vector<std::pair<int, int>>> struct2{
601 1, "a", {{2, 3}}
602 };
603 AppendValueToWriter(&writer, struct2);
604
605 EXPECT_EQ("(si)(isa(ii))", message->GetSignature());
606
607 std::tuple<std::string, int> struct1_out;
608 std::tuple<int, std::string, std::vector<std::pair<int, int>>> struct2_out;
609
610 MessageReader reader(message.get());
611 EXPECT_TRUE(PopValueFromReader(&reader, &struct1_out));
612 EXPECT_TRUE(PopValueFromReader(&reader, &struct2_out));
613 EXPECT_FALSE(reader.HasMoreData());
614 EXPECT_EQ(struct1, struct1_out);
615 EXPECT_EQ(struct2, struct2_out);
616 }
617
TEST(DBusUtils,ReinterpretVariant)618 TEST(DBusUtils, ReinterpretVariant) {
619 std::unique_ptr<Response> message = Response::CreateEmpty();
620 MessageWriter writer(message.get());
621 std::vector<std::string> str_array{"foo", "bar", "baz"};
622 std::map<std::string, std::string> dict_ss{{"k1", "v1"}, {"k2", "v2"}};
623 VariantDictionary dict_sv{{"k1", "v1"}, {"k2", "v2"}};
624 AppendValueToWriterAsVariant(&writer, 123);
625 AppendValueToWriterAsVariant(&writer, str_array);
626 AppendValueToWriterAsVariant(&writer, 1.7);
627 AppendValueToWriterAsVariant(&writer, dict_ss);
628 AppendValueToWriter(&writer, dict_sv);
629
630 EXPECT_EQ("vvvva{sv}", message->GetSignature());
631
632 int int_out = 0;
633 std::vector<std::string> str_array_out;
634 double dbl_out = 0.0;
635 std::map<std::string, std::string> dict_ss_out;
636 std::map<std::string, std::string> dict_ss_out2;
637
638 MessageReader reader(message.get());
639 EXPECT_TRUE(PopValueFromReader(&reader, &int_out));
640 EXPECT_TRUE(PopValueFromReader(&reader, &str_array_out));
641 EXPECT_TRUE(PopValueFromReader(&reader, &dbl_out));
642 EXPECT_TRUE(PopValueFromReader(&reader, &dict_ss_out));
643 EXPECT_TRUE(PopValueFromReader(&reader,
644 &dict_ss_out2)); // Read "a{sv}" as "a{ss}".
645 EXPECT_FALSE(reader.HasMoreData());
646
647 EXPECT_EQ(123, int_out);
648 EXPECT_EQ(str_array, str_array_out);
649 EXPECT_DOUBLE_EQ(1.7, dbl_out);
650 EXPECT_EQ(dict_ss, dict_ss_out);
651 EXPECT_EQ(dict_ss, dict_ss_out2);
652 }
653
654 // Test handling of custom data types.
655 struct Person {
656 std::string first_name;
657 std::string last_name;
658 int age;
659 // Provide == operator so we can easily compare arrays of Person.
operator ==brillo::dbus_utils::Person660 bool operator==(const Person& rhs) const {
661 return first_name == rhs.first_name && last_name == rhs.last_name &&
662 age == rhs.age;
663 }
664 };
665
666 // Overload AppendValueToWriter() for "Person" structure.
AppendValueToWriter(dbus::MessageWriter * writer,const Person & value)667 void AppendValueToWriter(dbus::MessageWriter* writer, const Person& value) {
668 dbus::MessageWriter struct_writer(nullptr);
669 writer->OpenStruct(&struct_writer);
670 AppendValueToWriter(&struct_writer, value.first_name);
671 AppendValueToWriter(&struct_writer, value.last_name);
672 AppendValueToWriter(&struct_writer, value.age);
673 writer->CloseContainer(&struct_writer);
674 }
675
676 // Overload PopValueFromReader() for "Person" structure.
PopValueFromReader(dbus::MessageReader * reader,Person * value)677 bool PopValueFromReader(dbus::MessageReader* reader, Person* value) {
678 dbus::MessageReader variant_reader(nullptr);
679 dbus::MessageReader struct_reader(nullptr);
680 if (!details::DescendIntoVariantIfPresent(&reader, &variant_reader) ||
681 !reader->PopStruct(&struct_reader))
682 return false;
683 return PopValueFromReader(&struct_reader, &value->first_name) &&
684 PopValueFromReader(&struct_reader, &value->last_name) &&
685 PopValueFromReader(&struct_reader, &value->age);
686 }
687
688 // Specialize DBusType<T> for "Person" structure.
689 template<>
690 struct DBusType<Person> {
GetSignaturebrillo::dbus_utils::DBusType691 inline static std::string GetSignature() {
692 return GetStructDBusSignature<std::string, std::string, int>();
693 }
Writebrillo::dbus_utils::DBusType694 inline static void Write(dbus::MessageWriter* writer, const Person& value) {
695 AppendValueToWriter(writer, value);
696 }
Readbrillo::dbus_utils::DBusType697 inline static bool Read(dbus::MessageReader* reader, Person* value) {
698 return PopValueFromReader(reader, value);
699 }
700 };
701
TEST(DBusUtils,CustomStruct)702 TEST(DBusUtils, CustomStruct) {
703 std::unique_ptr<Response> message = Response::CreateEmpty();
704 MessageWriter writer(message.get());
705 std::vector<Person> people{{"John", "Doe", 32}, {"Jane", "Smith", 48}};
706 AppendValueToWriter(&writer, people);
707 AppendValueToWriterAsVariant(&writer, people);
708 AppendValueToWriterAsVariant(&writer, people);
709
710 EXPECT_EQ("a(ssi)vv", message->GetSignature());
711
712 std::vector<Person> people_out1;
713 std::vector<Person> people_out2;
714 std::vector<Person> people_out3;
715
716 MessageReader reader(message.get());
717 EXPECT_TRUE(PopValueFromReader(&reader, &people_out1));
718 EXPECT_TRUE(PopValueFromReader(&reader, &people_out2));
719 EXPECT_TRUE(PopVariantValueFromReader(&reader, &people_out3));
720 EXPECT_FALSE(reader.HasMoreData());
721
722 EXPECT_EQ(people, people_out1);
723 EXPECT_EQ(people, people_out2);
724 EXPECT_EQ(people, people_out3);
725 }
726
TEST(DBusUtils,CustomStructInComplexTypes)727 TEST(DBusUtils, CustomStructInComplexTypes) {
728 std::unique_ptr<Response> message = Response::CreateEmpty();
729 MessageWriter writer(message.get());
730 std::vector<Person> people{{"John", "Doe", 32}, {"Jane", "Smith", 48}};
731 std::vector<std::map<int, Person>> data{
732 {
733 {1, Person{"John", "Doe", 32}},
734 {2, Person{"Jane", "Smith", 48}},
735 }
736 };
737 AppendValueToWriter(&writer, data);
738
739 EXPECT_EQ("aa{i(ssi)}", message->GetSignature());
740
741 std::vector<std::map<int, Person>> data_out;
742
743 MessageReader reader(message.get());
744 EXPECT_TRUE(PopValueFromReader(&reader, &data_out));
745 EXPECT_FALSE(reader.HasMoreData());
746
747 EXPECT_EQ(data, data_out);
748 }
749
TEST(DBusUtils,EmptyVariant)750 TEST(DBusUtils, EmptyVariant) {
751 std::unique_ptr<Response> message = Response::CreateEmpty();
752 MessageWriter writer(message.get());
753 EXPECT_DEATH(AppendValueToWriter(&writer, Any{}),
754 "Must not be called on an empty Any");
755 }
756
TEST(DBusUtils,IncompatibleVariant)757 TEST(DBusUtils, IncompatibleVariant) {
758 std::unique_ptr<Response> message = Response::CreateEmpty();
759 MessageWriter writer(message.get());
760 EXPECT_DEATH(AppendValueToWriter(&writer, Any{2.2f}),
761 "Type 'float' is not supported by D-Bus");
762 }
763
TEST(DBusUtils,Protobuf)764 TEST(DBusUtils, Protobuf) {
765 std::unique_ptr<Response> message = Response::CreateEmpty();
766 MessageWriter writer(message.get());
767
768 dbus_utils_test::TestMessage test_message;
769 test_message.set_foo(123);
770 test_message.set_bar("abcd");
771
772 AppendValueToWriter(&writer, test_message);
773
774 EXPECT_EQ("ay", message->GetSignature());
775
776 dbus_utils_test::TestMessage test_message_out;
777
778 MessageReader reader(message.get());
779 EXPECT_TRUE(PopValueFromReader(&reader, &test_message_out));
780 EXPECT_FALSE(reader.HasMoreData());
781
782 EXPECT_EQ(123, test_message_out.foo());
783 EXPECT_EQ("abcd", test_message_out.bar());
784 }
785
786 } // namespace dbus_utils
787 } // namespace brillo
788