You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
823 lines
30 KiB
823 lines
30 KiB
// Copyright 2014 The Chromium OS Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include <brillo/dbus/data_serialization.h>
|
|
|
|
#include <limits>
|
|
#include <tuple>
|
|
|
|
#include <base/files/scoped_file.h>
|
|
#include <brillo/variant_dictionary.h>
|
|
#include <gtest/gtest.h>
|
|
|
|
#include "brillo/dbus/test.pb.h"
|
|
|
|
using dbus::Message;
|
|
using dbus::MessageReader;
|
|
using dbus::MessageWriter;
|
|
using dbus::ObjectPath;
|
|
using dbus::Response;
|
|
|
|
namespace brillo {
|
|
namespace dbus_utils {
|
|
|
|
TEST(DBusUtils, Supported_BasicTypes) {
|
|
EXPECT_TRUE(IsTypeSupported<bool>::value);
|
|
EXPECT_TRUE(IsTypeSupported<uint8_t>::value);
|
|
EXPECT_TRUE(IsTypeSupported<int16_t>::value);
|
|
EXPECT_TRUE(IsTypeSupported<uint16_t>::value);
|
|
EXPECT_TRUE(IsTypeSupported<int32_t>::value);
|
|
EXPECT_TRUE(IsTypeSupported<uint32_t>::value);
|
|
EXPECT_TRUE(IsTypeSupported<int64_t>::value);
|
|
EXPECT_TRUE(IsTypeSupported<uint64_t>::value);
|
|
EXPECT_TRUE(IsTypeSupported<double>::value);
|
|
EXPECT_TRUE(IsTypeSupported<std::string>::value);
|
|
EXPECT_TRUE(IsTypeSupported<ObjectPath>::value);
|
|
EXPECT_TRUE(IsTypeSupported<FileDescriptor>::value);
|
|
EXPECT_TRUE(IsTypeSupported<base::ScopedFD>::value);
|
|
EXPECT_TRUE(IsTypeSupported<Any>::value);
|
|
EXPECT_TRUE(IsTypeSupported<google::protobuf::MessageLite>::value);
|
|
EXPECT_TRUE(IsTypeSupported<dbus_utils_test::TestMessage>::value);
|
|
}
|
|
|
|
TEST(DBusUtils, Unsupported_BasicTypes) {
|
|
EXPECT_FALSE(IsTypeSupported<char>::value);
|
|
EXPECT_FALSE(IsTypeSupported<float>::value);
|
|
}
|
|
|
|
TEST(DBusUtils, Supported_ComplexTypes) {
|
|
EXPECT_TRUE(IsTypeSupported<std::vector<bool>>::value);
|
|
EXPECT_TRUE(IsTypeSupported<std::vector<uint8_t>>::value);
|
|
EXPECT_TRUE((IsTypeSupported<std::pair<int16_t, double>>::value));
|
|
EXPECT_TRUE(
|
|
(IsTypeSupported<std::map<uint16_t, std::vector<int64_t>>>::value));
|
|
EXPECT_TRUE((IsTypeSupported<std::tuple<bool, double, int32_t>>::value));
|
|
EXPECT_TRUE(
|
|
IsTypeSupported<std::vector<dbus_utils_test::TestMessage>>::value);
|
|
}
|
|
|
|
TEST(DBusUtils, Unsupported_ComplexTypes) {
|
|
EXPECT_FALSE(IsTypeSupported<std::vector<char>>::value);
|
|
EXPECT_FALSE((IsTypeSupported<std::pair<int16_t, float>>::value));
|
|
EXPECT_FALSE((IsTypeSupported<std::pair<char, int32_t>>::value));
|
|
EXPECT_FALSE((IsTypeSupported<std::map<int16_t, float>>::value));
|
|
EXPECT_FALSE((IsTypeSupported<std::map<char, int32_t>>::value));
|
|
EXPECT_FALSE((IsTypeSupported<std::tuple<bool, char, int32_t>>::value));
|
|
}
|
|
|
|
TEST(DBusUtils, Supported_TypeSet) {
|
|
EXPECT_TRUE((IsTypeSupported<int32_t, double, std::string>::value));
|
|
EXPECT_TRUE((IsTypeSupported<bool, std::vector<int32_t>, uint8_t>::value));
|
|
}
|
|
|
|
TEST(DBusUtils, Unupported_TypeSet) {
|
|
EXPECT_FALSE((IsTypeSupported<int32_t, double, std::string, char>::value));
|
|
EXPECT_FALSE(
|
|
(IsTypeSupported<bool, std::pair<std::vector<float>, uint8_t>>::value));
|
|
EXPECT_FALSE((IsTypeSupported<char, double, std::string, int16_t>::value));
|
|
EXPECT_FALSE((IsTypeSupported<char, std::vector<float>, float>::value));
|
|
}
|
|
|
|
TEST(DBusUtils, Signatures_BasicTypes) {
|
|
EXPECT_EQ("b", GetDBusSignature<bool>());
|
|
EXPECT_EQ("y", GetDBusSignature<uint8_t>());
|
|
EXPECT_EQ("n", GetDBusSignature<int16_t>());
|
|
EXPECT_EQ("q", GetDBusSignature<uint16_t>());
|
|
EXPECT_EQ("i", GetDBusSignature<int32_t>());
|
|
EXPECT_EQ("u", GetDBusSignature<uint32_t>());
|
|
EXPECT_EQ("x", GetDBusSignature<int64_t>());
|
|
EXPECT_EQ("t", GetDBusSignature<uint64_t>());
|
|
EXPECT_EQ("d", GetDBusSignature<double>());
|
|
EXPECT_EQ("s", GetDBusSignature<std::string>());
|
|
EXPECT_EQ("o", GetDBusSignature<ObjectPath>());
|
|
EXPECT_EQ("h", GetDBusSignature<FileDescriptor>());
|
|
EXPECT_EQ("h", GetDBusSignature<base::ScopedFD>());
|
|
EXPECT_EQ("v", GetDBusSignature<Any>());
|
|
}
|
|
|
|
TEST(DBusUtils, Signatures_Arrays) {
|
|
EXPECT_EQ("ab", GetDBusSignature<std::vector<bool>>());
|
|
EXPECT_EQ("ay", GetDBusSignature<std::vector<uint8_t>>());
|
|
EXPECT_EQ("an", GetDBusSignature<std::vector<int16_t>>());
|
|
EXPECT_EQ("aq", GetDBusSignature<std::vector<uint16_t>>());
|
|
EXPECT_EQ("ai", GetDBusSignature<std::vector<int32_t>>());
|
|
EXPECT_EQ("au", GetDBusSignature<std::vector<uint32_t>>());
|
|
EXPECT_EQ("ax", GetDBusSignature<std::vector<int64_t>>());
|
|
EXPECT_EQ("at", GetDBusSignature<std::vector<uint64_t>>());
|
|
EXPECT_EQ("ad", GetDBusSignature<std::vector<double>>());
|
|
EXPECT_EQ("as", GetDBusSignature<std::vector<std::string>>());
|
|
EXPECT_EQ("ao", GetDBusSignature<std::vector<ObjectPath>>());
|
|
EXPECT_EQ("ah", GetDBusSignature<std::vector<FileDescriptor>>());
|
|
EXPECT_EQ("ah", GetDBusSignature<std::vector<base::ScopedFD>>());
|
|
EXPECT_EQ("av", GetDBusSignature<std::vector<Any>>());
|
|
EXPECT_EQ("a(is)",
|
|
(GetDBusSignature<std::vector<std::pair<int, std::string>>>()));
|
|
EXPECT_EQ("aad", GetDBusSignature<std::vector<std::vector<double>>>());
|
|
}
|
|
|
|
TEST(DBusUtils, Signatures_Maps) {
|
|
EXPECT_EQ("a{sb}", (GetDBusSignature<std::map<std::string, bool>>()));
|
|
EXPECT_EQ("a{ss}", (GetDBusSignature<std::map<std::string, std::string>>()));
|
|
EXPECT_EQ("a{sv}", (GetDBusSignature<std::map<std::string, Any>>()));
|
|
EXPECT_EQ("a{id}", (GetDBusSignature<std::map<int, double>>()));
|
|
EXPECT_EQ(
|
|
"a{ia{ss}}",
|
|
(GetDBusSignature<std::map<int, std::map<std::string, std::string>>>()));
|
|
}
|
|
|
|
TEST(DBusUtils, Signatures_Pairs) {
|
|
EXPECT_EQ("(sb)", (GetDBusSignature<std::pair<std::string, bool>>()));
|
|
EXPECT_EQ("(sv)", (GetDBusSignature<std::pair<std::string, Any>>()));
|
|
EXPECT_EQ("(id)", (GetDBusSignature<std::pair<int, double>>()));
|
|
}
|
|
|
|
TEST(DBusUtils, Signatures_Tuples) {
|
|
EXPECT_EQ("(i)", (GetDBusSignature<std::tuple<int>>()));
|
|
EXPECT_EQ("(sv)", (GetDBusSignature<std::tuple<std::string, Any>>()));
|
|
EXPECT_EQ("(id(si))",
|
|
(GetDBusSignature<
|
|
std::tuple<int, double, std::tuple<std::string, int>>>()));
|
|
}
|
|
|
|
TEST(DBusUtils, Signatures_Protobufs) {
|
|
EXPECT_EQ("ay", (GetDBusSignature<google::protobuf::MessageLite>()));
|
|
EXPECT_EQ("ay", (GetDBusSignature<dbus_utils_test::TestMessage>()));
|
|
}
|
|
|
|
// Test that a byte can be properly written and read. We only have this
|
|
// test for byte, as repeating this for other basic types is too redundant.
|
|
TEST(DBusUtils, AppendAndPopByte) {
|
|
std::unique_ptr<Response> message = Response::CreateEmpty();
|
|
MessageWriter writer(message.get());
|
|
AppendValueToWriter(&writer, uint8_t{123});
|
|
EXPECT_EQ("y", message->GetSignature());
|
|
|
|
MessageReader reader(message.get());
|
|
EXPECT_TRUE(reader.HasMoreData()); // Should have data to read.
|
|
EXPECT_EQ(Message::BYTE, reader.GetDataType());
|
|
|
|
bool bool_value = false;
|
|
// Should fail as the type is not bool here.
|
|
EXPECT_FALSE(PopValueFromReader(&reader, &bool_value));
|
|
|
|
uint8_t byte_value = 0;
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &byte_value));
|
|
EXPECT_EQ(123, byte_value); // Should match with the input.
|
|
EXPECT_FALSE(reader.HasMoreData()); // Should not have more data to read.
|
|
|
|
// Try to get another byte. Should fail.
|
|
EXPECT_FALSE(PopValueFromReader(&reader, &byte_value));
|
|
}
|
|
|
|
// Check all basic types can be properly written and read.
|
|
TEST(DBusUtils, AppendAndPopBasicDataTypes) {
|
|
std::unique_ptr<Response> message = Response::CreateEmpty();
|
|
MessageWriter writer(message.get());
|
|
|
|
// Append 0, true, 2, 3, 4, 5, 6, 7, 8.0, "string", "/object/path".
|
|
AppendValueToWriter(&writer, uint8_t{0});
|
|
AppendValueToWriter(&writer, bool{true});
|
|
AppendValueToWriter(&writer, int16_t{2});
|
|
AppendValueToWriter(&writer, uint16_t{3});
|
|
AppendValueToWriter(&writer, int32_t{4});
|
|
AppendValueToWriter(&writer, uint32_t{5});
|
|
AppendValueToWriter(&writer, int64_t{6});
|
|
AppendValueToWriter(&writer, uint64_t{7});
|
|
AppendValueToWriter(&writer, double{8.0});
|
|
AppendValueToWriter(&writer, std::string{"string"});
|
|
AppendValueToWriter(&writer, ObjectPath{"/object/path"});
|
|
|
|
EXPECT_EQ("ybnqiuxtdso", message->GetSignature());
|
|
|
|
uint8_t byte_value = 0;
|
|
bool bool_value = false;
|
|
int16_t int16_value = 0;
|
|
uint16_t uint16_value = 0;
|
|
int32_t int32_value = 0;
|
|
uint32_t uint32_value = 0;
|
|
int64_t int64_value = 0;
|
|
uint64_t uint64_value = 0;
|
|
double double_value = 0;
|
|
std::string string_value;
|
|
ObjectPath object_path_value;
|
|
|
|
MessageReader reader(message.get());
|
|
EXPECT_TRUE(reader.HasMoreData());
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &byte_value));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &bool_value));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &int16_value));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &uint16_value));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &int32_value));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &uint32_value));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &int64_value));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &uint64_value));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &double_value));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &string_value));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &object_path_value));
|
|
EXPECT_FALSE(reader.HasMoreData());
|
|
|
|
// 0, true, 2, 3, 4, 5, 6, 7, 8, "string", "/object/path" should be returned.
|
|
EXPECT_EQ(0, byte_value);
|
|
EXPECT_TRUE(bool_value);
|
|
EXPECT_EQ(2, int16_value);
|
|
EXPECT_EQ(3U, uint16_value);
|
|
EXPECT_EQ(4, int32_value);
|
|
EXPECT_EQ(5U, uint32_value);
|
|
EXPECT_EQ(6, int64_value);
|
|
EXPECT_EQ(7U, uint64_value);
|
|
EXPECT_DOUBLE_EQ(8.0, double_value);
|
|
EXPECT_EQ("string", string_value);
|
|
EXPECT_EQ(ObjectPath{"/object/path"}, object_path_value);
|
|
}
|
|
|
|
// Check all basic types can be properly written and read.
|
|
TEST(DBusUtils, AppendAndPopFileDescriptor) {
|
|
if (!dbus::IsDBusTypeUnixFdSupported()) {
|
|
LOG(WARNING) << "FD passing is not supported";
|
|
return;
|
|
}
|
|
|
|
std::unique_ptr<Response> message = Response::CreateEmpty();
|
|
MessageWriter writer(message.get());
|
|
|
|
// Append stdout.
|
|
FileDescriptor temp = 1;
|
|
AppendValueToWriter(&writer, temp);
|
|
|
|
EXPECT_EQ("h", message->GetSignature());
|
|
|
|
base::ScopedFD fd_value;
|
|
|
|
MessageReader reader(message.get());
|
|
EXPECT_TRUE(reader.HasMoreData());
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &fd_value));
|
|
EXPECT_FALSE(reader.HasMoreData());
|
|
EXPECT_TRUE(fd_value.is_valid());
|
|
}
|
|
|
|
// Check all variant types can be properly written and read.
|
|
TEST(DBusUtils, AppendAndPopVariantDataTypes) {
|
|
std::unique_ptr<Response> message = Response::CreateEmpty();
|
|
MessageWriter writer(message.get());
|
|
|
|
// Append 10, false, 12, 13, 14, 15, 16, 17, 18.5, "data", "/obj/path".
|
|
AppendValueToWriterAsVariant(&writer, uint8_t{10});
|
|
AppendValueToWriterAsVariant(&writer, bool{false});
|
|
AppendValueToWriterAsVariant(&writer, int16_t{12});
|
|
AppendValueToWriterAsVariant(&writer, uint16_t{13});
|
|
AppendValueToWriterAsVariant(&writer, int32_t{14});
|
|
AppendValueToWriterAsVariant(&writer, uint32_t{15});
|
|
AppendValueToWriterAsVariant(&writer, int64_t{16});
|
|
AppendValueToWriterAsVariant(&writer, uint64_t{17});
|
|
AppendValueToWriterAsVariant(&writer, double{18.5});
|
|
AppendValueToWriterAsVariant(&writer, std::string{"data"});
|
|
AppendValueToWriterAsVariant(&writer, ObjectPath{"/obj/path"});
|
|
AppendValueToWriterAsVariant(&writer, Any{17});
|
|
AppendValueToWriterAsVariant(&writer,
|
|
Any{std::vector<std::vector<int>>{{6, 7}}});
|
|
|
|
EXPECT_EQ("vvvvvvvvvvvvv", message->GetSignature());
|
|
|
|
uint8_t byte_value = 0;
|
|
bool bool_value = true;
|
|
int16_t int16_value = 0;
|
|
uint16_t uint16_value = 0;
|
|
int32_t int32_value = 0;
|
|
uint32_t uint32_value = 0;
|
|
int64_t int64_value = 0;
|
|
uint64_t uint64_value = 0;
|
|
double double_value = 0;
|
|
std::string string_value;
|
|
ObjectPath object_path_value;
|
|
Any any_value;
|
|
Any any_vector_vector;
|
|
|
|
MessageReader reader(message.get());
|
|
EXPECT_TRUE(reader.HasMoreData());
|
|
EXPECT_TRUE(PopVariantValueFromReader(&reader, &byte_value));
|
|
EXPECT_TRUE(PopVariantValueFromReader(&reader, &bool_value));
|
|
EXPECT_TRUE(PopVariantValueFromReader(&reader, &int16_value));
|
|
EXPECT_TRUE(PopVariantValueFromReader(&reader, &uint16_value));
|
|
EXPECT_TRUE(PopVariantValueFromReader(&reader, &int32_value));
|
|
EXPECT_TRUE(PopVariantValueFromReader(&reader, &uint32_value));
|
|
EXPECT_TRUE(PopVariantValueFromReader(&reader, &int64_value));
|
|
EXPECT_TRUE(PopVariantValueFromReader(&reader, &uint64_value));
|
|
EXPECT_TRUE(PopVariantValueFromReader(&reader, &double_value));
|
|
EXPECT_TRUE(PopVariantValueFromReader(&reader, &string_value));
|
|
EXPECT_TRUE(PopVariantValueFromReader(&reader, &object_path_value));
|
|
EXPECT_TRUE(PopVariantValueFromReader(&reader, &any_value));
|
|
// Not implemented.
|
|
EXPECT_FALSE(PopVariantValueFromReader(&reader, &any_vector_vector));
|
|
EXPECT_FALSE(reader.HasMoreData());
|
|
|
|
EXPECT_EQ(10, byte_value);
|
|
EXPECT_FALSE(bool_value);
|
|
EXPECT_EQ(12, int16_value);
|
|
EXPECT_EQ(13U, uint16_value);
|
|
EXPECT_EQ(14, int32_value);
|
|
EXPECT_EQ(15U, uint32_value);
|
|
EXPECT_EQ(16, int64_value);
|
|
EXPECT_EQ(17U, uint64_value);
|
|
EXPECT_DOUBLE_EQ(18.5, double_value);
|
|
EXPECT_EQ("data", string_value);
|
|
EXPECT_EQ(ObjectPath{"/obj/path"}, object_path_value);
|
|
EXPECT_EQ(17, any_value.Get<int>());
|
|
EXPECT_TRUE(any_vector_vector.IsEmpty());
|
|
}
|
|
|
|
TEST(DBusUtils, AppendAndPopBasicAny) {
|
|
std::unique_ptr<Response> message = Response::CreateEmpty();
|
|
MessageWriter writer(message.get());
|
|
|
|
// Append 10, true, 12, 13, 14, 15, 16, 17, 18.5, "data", "/obj/path".
|
|
AppendValueToWriter(&writer, Any(uint8_t{10}));
|
|
AppendValueToWriter(&writer, Any(bool{true}));
|
|
AppendValueToWriter(&writer, Any(int16_t{12}));
|
|
AppendValueToWriter(&writer, Any(uint16_t{13}));
|
|
AppendValueToWriter(&writer, Any(int32_t{14}));
|
|
AppendValueToWriter(&writer, Any(uint32_t{15}));
|
|
AppendValueToWriter(&writer, Any(int64_t{16}));
|
|
AppendValueToWriter(&writer, Any(uint64_t{17}));
|
|
AppendValueToWriter(&writer, Any(double{18.5}));
|
|
AppendValueToWriter(&writer, Any(std::string{"data"}));
|
|
AppendValueToWriter(&writer, Any(ObjectPath{"/obj/path"}));
|
|
EXPECT_EQ("vvvvvvvvvvv", message->GetSignature());
|
|
|
|
Any byte_value;
|
|
Any bool_value;
|
|
Any int16_value;
|
|
Any uint16_value;
|
|
Any int32_value;
|
|
Any uint32_value;
|
|
Any int64_value;
|
|
Any uint64_value;
|
|
Any double_value;
|
|
Any string_value;
|
|
Any object_path_value;
|
|
|
|
MessageReader reader(message.get());
|
|
EXPECT_TRUE(reader.HasMoreData());
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &byte_value));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &bool_value));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &int16_value));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &uint16_value));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &int32_value));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &uint32_value));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &int64_value));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &uint64_value));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &double_value));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &string_value));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &object_path_value));
|
|
EXPECT_FALSE(reader.HasMoreData());
|
|
|
|
// Must be: 10, true, 12, 13, 14, 15, 16, 17, 18.5, "data", "/obj/path".
|
|
EXPECT_EQ(10, byte_value.Get<uint8_t>());
|
|
EXPECT_TRUE(bool_value.Get<bool>());
|
|
EXPECT_EQ(12, int16_value.Get<int16_t>());
|
|
EXPECT_EQ(13U, uint16_value.Get<uint16_t>());
|
|
EXPECT_EQ(14, int32_value.Get<int32_t>());
|
|
EXPECT_EQ(15U, uint32_value.Get<uint32_t>());
|
|
EXPECT_EQ(16, int64_value.Get<int64_t>());
|
|
EXPECT_EQ(17U, uint64_value.Get<uint64_t>());
|
|
EXPECT_DOUBLE_EQ(18.5, double_value.Get<double>());
|
|
EXPECT_EQ("data", string_value.Get<std::string>());
|
|
EXPECT_EQ(ObjectPath{"/obj/path"}, object_path_value.Get<ObjectPath>());
|
|
}
|
|
|
|
TEST(DBusUtils, ArrayOfBytes) {
|
|
std::unique_ptr<Response> message = Response::CreateEmpty();
|
|
MessageWriter writer(message.get());
|
|
std::vector<uint8_t> bytes{1, 2, 3};
|
|
AppendValueToWriter(&writer, bytes);
|
|
|
|
EXPECT_EQ("ay", message->GetSignature());
|
|
|
|
MessageReader reader(message.get());
|
|
std::vector<uint8_t> bytes_out;
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &bytes_out));
|
|
EXPECT_FALSE(reader.HasMoreData());
|
|
EXPECT_EQ(bytes, bytes_out);
|
|
}
|
|
|
|
TEST(DBusUtils, ArrayOfBytes_Empty) {
|
|
std::unique_ptr<Response> message = Response::CreateEmpty();
|
|
MessageWriter writer(message.get());
|
|
std::vector<uint8_t> bytes;
|
|
AppendValueToWriter(&writer, bytes);
|
|
|
|
EXPECT_EQ("ay", message->GetSignature());
|
|
|
|
MessageReader reader(message.get());
|
|
std::vector<uint8_t> bytes_out;
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &bytes_out));
|
|
EXPECT_FALSE(reader.HasMoreData());
|
|
EXPECT_EQ(bytes, bytes_out);
|
|
}
|
|
|
|
TEST(DBusUtils, ArrayOfStrings) {
|
|
std::unique_ptr<Response> message = Response::CreateEmpty();
|
|
MessageWriter writer(message.get());
|
|
std::vector<std::string> strings{"foo", "bar", "baz"};
|
|
AppendValueToWriter(&writer, strings);
|
|
|
|
EXPECT_EQ("as", message->GetSignature());
|
|
|
|
MessageReader reader(message.get());
|
|
std::vector<std::string> strings_out;
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &strings_out));
|
|
EXPECT_FALSE(reader.HasMoreData());
|
|
EXPECT_EQ(strings, strings_out);
|
|
}
|
|
|
|
TEST(DBusUtils, ArrayOfInt64) {
|
|
std::unique_ptr<Response> message = Response::CreateEmpty();
|
|
MessageWriter writer(message.get());
|
|
std::vector<int64_t> values{-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5,
|
|
std::numeric_limits<int64_t>::min(),
|
|
std::numeric_limits<int64_t>::max()};
|
|
AppendValueToWriter(&writer, values);
|
|
|
|
EXPECT_EQ("ax", message->GetSignature());
|
|
|
|
MessageReader reader(message.get());
|
|
std::vector<int64_t> values_out;
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &values_out));
|
|
EXPECT_FALSE(reader.HasMoreData());
|
|
EXPECT_EQ(values, values_out);
|
|
}
|
|
|
|
TEST(DBusUtils, ArrayOfObjectPaths) {
|
|
std::unique_ptr<Response> message = Response::CreateEmpty();
|
|
MessageWriter writer(message.get());
|
|
std::vector<ObjectPath> object_paths{
|
|
ObjectPath("/object/path/1"),
|
|
ObjectPath("/object/path/2"),
|
|
ObjectPath("/object/path/3"),
|
|
};
|
|
AppendValueToWriter(&writer, object_paths);
|
|
|
|
EXPECT_EQ("ao", message->GetSignature());
|
|
|
|
MessageReader reader(message.get());
|
|
std::vector<ObjectPath> object_paths_out;
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &object_paths_out));
|
|
EXPECT_FALSE(reader.HasMoreData());
|
|
EXPECT_EQ(object_paths, object_paths_out);
|
|
}
|
|
|
|
TEST(DBusUtils, ArraysAsVariant) {
|
|
std::unique_ptr<Response> message = Response::CreateEmpty();
|
|
MessageWriter writer(message.get());
|
|
std::vector<int> int_array{1, 2, 3};
|
|
std::vector<std::string> str_array{"foo", "bar", "baz"};
|
|
std::vector<double> dbl_array_empty{};
|
|
std::map<std::string, std::string> dict_ss{{"k1", "v1"}, {"k2", "v2"}};
|
|
VariantDictionary dict_sv{{"k1", 1}, {"k2", "v2"}};
|
|
using ComplexStructArray =
|
|
std::vector<std::tuple<uint32_t, bool, std::vector<uint8_t>>>;
|
|
ComplexStructArray complex_struct_array{
|
|
{123, true, {0xaa, 0xbb, 0xcc}},
|
|
{456, false, {0xdd}},
|
|
{789, false, {}},
|
|
};
|
|
AppendValueToWriterAsVariant(&writer, int_array);
|
|
AppendValueToWriterAsVariant(&writer, str_array);
|
|
AppendValueToWriterAsVariant(&writer, dbl_array_empty);
|
|
AppendValueToWriterAsVariant(&writer, dict_ss);
|
|
AppendValueToWriterAsVariant(&writer, dict_sv);
|
|
AppendValueToWriterAsVariant(&writer, complex_struct_array);
|
|
|
|
EXPECT_EQ("vvvvvv", message->GetSignature());
|
|
|
|
Any int_array_out;
|
|
Any str_array_out;
|
|
Any dbl_array_out;
|
|
Any dict_ss_out;
|
|
Any dict_sv_out;
|
|
Any complex_struct_array_out;
|
|
|
|
MessageReader reader(message.get());
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &int_array_out));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &str_array_out));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &dbl_array_out));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &dict_ss_out));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &dict_sv_out));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &complex_struct_array_out));
|
|
EXPECT_FALSE(reader.HasMoreData());
|
|
|
|
EXPECT_EQ(int_array, int_array_out.Get<std::vector<int>>());
|
|
EXPECT_EQ(str_array, str_array_out.Get<std::vector<std::string>>());
|
|
EXPECT_EQ(dbl_array_empty, dbl_array_out.Get<std::vector<double>>());
|
|
EXPECT_EQ(dict_ss, (dict_ss_out.Get<std::map<std::string, std::string>>()));
|
|
EXPECT_EQ(dict_sv["k1"].Get<int>(),
|
|
dict_sv_out.Get<VariantDictionary>().at("k1").Get<int>());
|
|
EXPECT_EQ(dict_sv["k2"].Get<const char*>(),
|
|
dict_sv_out.Get<VariantDictionary>().at("k2").Get<std::string>());
|
|
EXPECT_EQ(complex_struct_array,
|
|
complex_struct_array_out.Get<ComplexStructArray>());
|
|
}
|
|
|
|
TEST(DBusUtils, StructsAsVariant) {
|
|
std::unique_ptr<Response> message = Response::CreateEmpty();
|
|
MessageWriter writer(message.get());
|
|
VariantDictionary dict_sv{{"k1", 1}, {"k2", "v2"}};
|
|
std::tuple<uint32_t, VariantDictionary> u32_dict_sv_struct =
|
|
std::make_tuple(1, dict_sv);
|
|
AppendValueToWriterAsVariant(&writer, u32_dict_sv_struct);
|
|
|
|
EXPECT_EQ("v", message->GetSignature());
|
|
|
|
Any u32_dict_sv_struct_out_any;
|
|
|
|
MessageReader reader(message.get());
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &u32_dict_sv_struct_out_any));
|
|
EXPECT_FALSE(reader.HasMoreData());
|
|
|
|
auto u32_dict_sv_struct_out =
|
|
u32_dict_sv_struct_out_any.Get<std::tuple<uint32_t, VariantDictionary>>();
|
|
EXPECT_EQ(std::get<0>(u32_dict_sv_struct),
|
|
std::get<0>(u32_dict_sv_struct_out));
|
|
VariantDictionary dict_sv_out = std::get<1>(u32_dict_sv_struct_out);
|
|
EXPECT_EQ(dict_sv.size(), dict_sv_out.size());
|
|
EXPECT_EQ(dict_sv["k1"].Get<int>(), dict_sv_out["k1"].Get<int>());
|
|
EXPECT_EQ(dict_sv["k2"].Get<const char*>(),
|
|
dict_sv_out["k2"].Get<std::string>());
|
|
}
|
|
|
|
TEST(DBusUtils, VariantDictionary) {
|
|
std::unique_ptr<Response> message = Response::CreateEmpty();
|
|
MessageWriter writer(message.get());
|
|
VariantDictionary values{
|
|
{"key1", uint8_t{10}},
|
|
{"key2", bool{true}},
|
|
{"key3", int16_t{12}},
|
|
{"key4", uint16_t{13}},
|
|
{"key5", int32_t{14}},
|
|
{"key6", uint32_t{15}},
|
|
{"key7", int64_t{16}},
|
|
{"key8", uint64_t{17}},
|
|
{"key9", double{18.5}},
|
|
{"keyA", std::string{"data"}},
|
|
{"keyB", ObjectPath{"/obj/path"}},
|
|
};
|
|
AppendValueToWriter(&writer, values);
|
|
|
|
EXPECT_EQ("a{sv}", message->GetSignature());
|
|
|
|
MessageReader reader(message.get());
|
|
VariantDictionary values_out;
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &values_out));
|
|
EXPECT_FALSE(reader.HasMoreData());
|
|
EXPECT_EQ(values.size(), values_out.size());
|
|
EXPECT_EQ(values["key1"].Get<uint8_t>(), values_out["key1"].Get<uint8_t>());
|
|
EXPECT_EQ(values["key2"].Get<bool>(), values_out["key2"].Get<bool>());
|
|
EXPECT_EQ(values["key3"].Get<int16_t>(), values_out["key3"].Get<int16_t>());
|
|
EXPECT_EQ(values["key4"].Get<uint16_t>(), values_out["key4"].Get<uint16_t>());
|
|
EXPECT_EQ(values["key5"].Get<int32_t>(), values_out["key5"].Get<int32_t>());
|
|
EXPECT_EQ(values["key6"].Get<uint32_t>(), values_out["key6"].Get<uint32_t>());
|
|
EXPECT_EQ(values["key7"].Get<int64_t>(), values_out["key7"].Get<int64_t>());
|
|
EXPECT_EQ(values["key8"].Get<uint64_t>(), values_out["key8"].Get<uint64_t>());
|
|
EXPECT_EQ(values["key9"].Get<double>(), values_out["key9"].Get<double>());
|
|
EXPECT_EQ(values["keyA"].Get<std::string>(),
|
|
values_out["keyA"].Get<std::string>());
|
|
EXPECT_EQ(values["keyB"].Get<ObjectPath>(),
|
|
values_out["keyB"].Get<ObjectPath>());
|
|
}
|
|
|
|
TEST(DBusUtils, StringToStringMap) {
|
|
std::unique_ptr<Response> message = Response::CreateEmpty();
|
|
MessageWriter writer(message.get());
|
|
std::map<std::string, std::string> values{
|
|
{"key1", "value1"},
|
|
{"key2", "value2"},
|
|
{"key3", "value3"},
|
|
{"key4", "value4"},
|
|
{"key5", "value5"},
|
|
};
|
|
AppendValueToWriter(&writer, values);
|
|
|
|
EXPECT_EQ("a{ss}", message->GetSignature());
|
|
|
|
MessageReader reader(message.get());
|
|
std::map<std::string, std::string> values_out;
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &values_out));
|
|
EXPECT_FALSE(reader.HasMoreData());
|
|
EXPECT_EQ(values, values_out);
|
|
}
|
|
|
|
TEST(DBusUtils, Pair) {
|
|
std::unique_ptr<Response> message = Response::CreateEmpty();
|
|
MessageWriter writer(message.get());
|
|
std::pair<std::string, int> struct1{"value2", 3};
|
|
AppendValueToWriter(&writer, struct1);
|
|
std::pair<int, std::pair<int, int>> struct2{1, {2, 3}};
|
|
AppendValueToWriter(&writer, struct2);
|
|
|
|
EXPECT_EQ("(si)(i(ii))", message->GetSignature());
|
|
|
|
std::pair<std::string, int> struct1_out;
|
|
std::pair<int, std::pair<int, int>> struct2_out;
|
|
|
|
MessageReader reader(message.get());
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &struct1_out));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &struct2_out));
|
|
EXPECT_FALSE(reader.HasMoreData());
|
|
EXPECT_EQ(struct1, struct1_out);
|
|
EXPECT_EQ(struct2, struct2_out);
|
|
}
|
|
|
|
TEST(DBusUtils, Tuple) {
|
|
std::unique_ptr<Response> message = Response::CreateEmpty();
|
|
MessageWriter writer(message.get());
|
|
std::tuple<std::string, int> struct1{"value2", 3};
|
|
AppendValueToWriter(&writer, struct1);
|
|
std::tuple<int, std::string, std::vector<std::pair<int, int>>> struct2{
|
|
1, "a", {{2, 3}}
|
|
};
|
|
AppendValueToWriter(&writer, struct2);
|
|
|
|
EXPECT_EQ("(si)(isa(ii))", message->GetSignature());
|
|
|
|
std::tuple<std::string, int> struct1_out;
|
|
std::tuple<int, std::string, std::vector<std::pair<int, int>>> struct2_out;
|
|
|
|
MessageReader reader(message.get());
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &struct1_out));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &struct2_out));
|
|
EXPECT_FALSE(reader.HasMoreData());
|
|
EXPECT_EQ(struct1, struct1_out);
|
|
EXPECT_EQ(struct2, struct2_out);
|
|
}
|
|
|
|
TEST(DBusUtils, ReinterpretVariant) {
|
|
std::unique_ptr<Response> message = Response::CreateEmpty();
|
|
MessageWriter writer(message.get());
|
|
std::vector<std::string> str_array{"foo", "bar", "baz"};
|
|
std::map<std::string, std::string> dict_ss{{"k1", "v1"}, {"k2", "v2"}};
|
|
VariantDictionary dict_sv{{"k1", "v1"}, {"k2", "v2"}};
|
|
AppendValueToWriterAsVariant(&writer, 123);
|
|
AppendValueToWriterAsVariant(&writer, str_array);
|
|
AppendValueToWriterAsVariant(&writer, 1.7);
|
|
AppendValueToWriterAsVariant(&writer, dict_ss);
|
|
AppendValueToWriter(&writer, dict_sv);
|
|
|
|
EXPECT_EQ("vvvva{sv}", message->GetSignature());
|
|
|
|
int int_out = 0;
|
|
std::vector<std::string> str_array_out;
|
|
double dbl_out = 0.0;
|
|
std::map<std::string, std::string> dict_ss_out;
|
|
std::map<std::string, std::string> dict_ss_out2;
|
|
|
|
MessageReader reader(message.get());
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &int_out));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &str_array_out));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &dbl_out));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &dict_ss_out));
|
|
EXPECT_TRUE(PopValueFromReader(&reader,
|
|
&dict_ss_out2)); // Read "a{sv}" as "a{ss}".
|
|
EXPECT_FALSE(reader.HasMoreData());
|
|
|
|
EXPECT_EQ(123, int_out);
|
|
EXPECT_EQ(str_array, str_array_out);
|
|
EXPECT_DOUBLE_EQ(1.7, dbl_out);
|
|
EXPECT_EQ(dict_ss, dict_ss_out);
|
|
EXPECT_EQ(dict_ss, dict_ss_out2);
|
|
}
|
|
|
|
// Test handling of custom data types.
|
|
struct Person {
|
|
std::string first_name;
|
|
std::string last_name;
|
|
int age;
|
|
// Provide == operator so we can easily compare arrays of Person.
|
|
bool operator==(const Person& rhs) const {
|
|
return first_name == rhs.first_name && last_name == rhs.last_name &&
|
|
age == rhs.age;
|
|
}
|
|
};
|
|
|
|
// Overload AppendValueToWriter() for "Person" structure.
|
|
void AppendValueToWriter(dbus::MessageWriter* writer, const Person& value) {
|
|
dbus::MessageWriter struct_writer(nullptr);
|
|
writer->OpenStruct(&struct_writer);
|
|
AppendValueToWriter(&struct_writer, value.first_name);
|
|
AppendValueToWriter(&struct_writer, value.last_name);
|
|
AppendValueToWriter(&struct_writer, value.age);
|
|
writer->CloseContainer(&struct_writer);
|
|
}
|
|
|
|
// Overload PopValueFromReader() for "Person" structure.
|
|
bool PopValueFromReader(dbus::MessageReader* reader, Person* value) {
|
|
dbus::MessageReader variant_reader(nullptr);
|
|
dbus::MessageReader struct_reader(nullptr);
|
|
if (!details::DescendIntoVariantIfPresent(&reader, &variant_reader) ||
|
|
!reader->PopStruct(&struct_reader))
|
|
return false;
|
|
return PopValueFromReader(&struct_reader, &value->first_name) &&
|
|
PopValueFromReader(&struct_reader, &value->last_name) &&
|
|
PopValueFromReader(&struct_reader, &value->age);
|
|
}
|
|
|
|
// Specialize DBusType<T> for "Person" structure.
|
|
template<>
|
|
struct DBusType<Person> {
|
|
inline static std::string GetSignature() {
|
|
return GetStructDBusSignature<std::string, std::string, int>();
|
|
}
|
|
inline static void Write(dbus::MessageWriter* writer, const Person& value) {
|
|
AppendValueToWriter(writer, value);
|
|
}
|
|
inline static bool Read(dbus::MessageReader* reader, Person* value) {
|
|
return PopValueFromReader(reader, value);
|
|
}
|
|
};
|
|
|
|
TEST(DBusUtils, CustomStruct) {
|
|
std::unique_ptr<Response> message = Response::CreateEmpty();
|
|
MessageWriter writer(message.get());
|
|
std::vector<Person> people{{"John", "Doe", 32}, {"Jane", "Smith", 48}};
|
|
AppendValueToWriter(&writer, people);
|
|
AppendValueToWriterAsVariant(&writer, people);
|
|
AppendValueToWriterAsVariant(&writer, people);
|
|
|
|
EXPECT_EQ("a(ssi)vv", message->GetSignature());
|
|
|
|
std::vector<Person> people_out1;
|
|
std::vector<Person> people_out2;
|
|
std::vector<Person> people_out3;
|
|
|
|
MessageReader reader(message.get());
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &people_out1));
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &people_out2));
|
|
EXPECT_TRUE(PopVariantValueFromReader(&reader, &people_out3));
|
|
EXPECT_FALSE(reader.HasMoreData());
|
|
|
|
EXPECT_EQ(people, people_out1);
|
|
EXPECT_EQ(people, people_out2);
|
|
EXPECT_EQ(people, people_out3);
|
|
}
|
|
|
|
TEST(DBusUtils, CustomStructInComplexTypes) {
|
|
std::unique_ptr<Response> message = Response::CreateEmpty();
|
|
MessageWriter writer(message.get());
|
|
std::vector<Person> people{{"John", "Doe", 32}, {"Jane", "Smith", 48}};
|
|
std::vector<std::map<int, Person>> data{
|
|
{
|
|
{1, Person{"John", "Doe", 32}},
|
|
{2, Person{"Jane", "Smith", 48}},
|
|
}
|
|
};
|
|
AppendValueToWriter(&writer, data);
|
|
|
|
EXPECT_EQ("aa{i(ssi)}", message->GetSignature());
|
|
|
|
std::vector<std::map<int, Person>> data_out;
|
|
|
|
MessageReader reader(message.get());
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &data_out));
|
|
EXPECT_FALSE(reader.HasMoreData());
|
|
|
|
EXPECT_EQ(data, data_out);
|
|
}
|
|
|
|
TEST(DBusUtils, EmptyVariant) {
|
|
std::unique_ptr<Response> message = Response::CreateEmpty();
|
|
MessageWriter writer(message.get());
|
|
EXPECT_DEATH(AppendValueToWriter(&writer, Any{}),
|
|
"Must not be called on an empty Any");
|
|
}
|
|
|
|
TEST(DBusUtils, IncompatibleVariant) {
|
|
std::unique_ptr<Response> message = Response::CreateEmpty();
|
|
MessageWriter writer(message.get());
|
|
EXPECT_DEATH(AppendValueToWriter(&writer, Any{2.2f}),
|
|
"Type 'float' is not supported by D-Bus");
|
|
}
|
|
|
|
TEST(DBusUtils, Protobuf) {
|
|
std::unique_ptr<Response> message = Response::CreateEmpty();
|
|
MessageWriter writer(message.get());
|
|
|
|
dbus_utils_test::TestMessage test_message;
|
|
test_message.set_foo(123);
|
|
test_message.set_bar("abcd");
|
|
|
|
AppendValueToWriter(&writer, test_message);
|
|
|
|
EXPECT_EQ("ay", message->GetSignature());
|
|
|
|
dbus_utils_test::TestMessage test_message_out;
|
|
|
|
MessageReader reader(message.get());
|
|
EXPECT_TRUE(PopValueFromReader(&reader, &test_message_out));
|
|
EXPECT_FALSE(reader.HasMoreData());
|
|
|
|
EXPECT_EQ(123, test_message_out.foo());
|
|
EXPECT_EQ("abcd", test_message_out.bar());
|
|
}
|
|
|
|
} // namespace dbus_utils
|
|
} // namespace brillo
|