blob: 62659de8a9bd494a95774155c75f70ca71abb6f8 [file] [log] [blame]
Vitaly Bukaa0305d32015-07-27 16:08:51 -07001// Copyright 2015 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 "buffet/dbus_conversion.h"
6
7#include <limits>
8#include <memory>
9#include <string>
10#include <vector>
11
12#include <base/guid.h>
13#include <base/rand_util.h>
14#include <base/values.h>
Alex Vakulenko41705852015-10-13 10:12:06 -070015#include <brillo/variant_dictionary.h>
Vitaly Bukaa0305d32015-07-27 16:08:51 -070016#include <gtest/gtest.h>
Vitaly Bukaea2f1e22015-08-20 15:35:19 -070017#include <weave/test/unittest_utils.h>
Vitaly Bukaa0305d32015-07-27 16:08:51 -070018
19namespace buffet {
20
21namespace {
22
Alex Vakulenko41705852015-10-13 10:12:06 -070023using brillo::Any;
24using brillo::VariantDictionary;
Vitaly Bukaea2f1e22015-08-20 15:35:19 -070025using weave::test::CreateDictionaryValue;
26using weave::test::IsEqualValue;
Vitaly Bukaa0305d32015-07-27 16:08:51 -070027
Alex Vakulenko41705852015-10-13 10:12:06 -070028brillo::VariantDictionary ToDBus(const base::DictionaryValue& object) {
Vitaly Bukaa0305d32015-07-27 16:08:51 -070029 return DictionaryToDBusVariantDictionary(object);
30}
31
32std::unique_ptr<base::DictionaryValue> FromDBus(
Alex Vakulenko41705852015-10-13 10:12:06 -070033 const brillo::VariantDictionary& object) {
34 brillo::ErrorPtr error;
Vitaly Bukaa0305d32015-07-27 16:08:51 -070035 auto result = DictionaryFromDBusVariantDictionary(object, &error);
36 EXPECT_TRUE(result || error);
37 return result;
38}
39
40std::unique_ptr<base::Value> CreateRandomValue(int children);
41std::unique_ptr<base::Value> CreateRandomValue(int children,
42 base::Value::Type type);
43
44const base::Value::Type kRandomTypes[] = {
45 base::Value::TYPE_BOOLEAN, base::Value::TYPE_INTEGER,
46 base::Value::TYPE_DOUBLE, base::Value::TYPE_STRING,
47 base::Value::TYPE_DICTIONARY, base::Value::TYPE_LIST,
48};
49
50const base::Value::Type kRandomTypesWithChildren[] = {
51 base::Value::TYPE_DICTIONARY, base::Value::TYPE_LIST,
52};
53
54base::Value::Type CreateRandomValueType(bool with_children) {
55 if (with_children) {
56 return kRandomTypesWithChildren[base::RandInt(
57 0, arraysize(kRandomTypesWithChildren) - 1)];
58 }
59 return kRandomTypes[base::RandInt(0, arraysize(kRandomTypes) - 1)];
60}
61
62std::unique_ptr<base::DictionaryValue> CreateRandomDictionary(int children) {
63 std::unique_ptr<base::DictionaryValue> result{new base::DictionaryValue};
64
65 while (children > 0) {
66 int sub_children = base::RandInt(1, children);
67 children -= sub_children;
68 result->Set(base::GenerateGUID(),
69 CreateRandomValue(sub_children).release());
70 }
71
72 return result;
73}
74
75std::unique_ptr<base::ListValue> CreateRandomList(int children) {
76 std::unique_ptr<base::ListValue> result{new base::ListValue};
77
78 base::Value::Type type = CreateRandomValueType(children > 0);
79 while (children > 0) {
80 size_t max_children =
81 (type != base::Value::TYPE_DICTIONARY && type != base::Value::TYPE_LIST)
82 ? 1
83 : children;
84 size_t sub_children = base::RandInt(1, max_children);
85 children -= sub_children;
86 result->Append(CreateRandomValue(sub_children, type).release());
87 }
88
89 return result;
90}
91
92std::unique_ptr<base::Value> CreateRandomValue(int children,
93 base::Value::Type type) {
94 CHECK_GE(children, 1);
95 switch (type) {
96 case base::Value::TYPE_INTEGER:
97 return std::unique_ptr<base::Value>{new base::FundamentalValue{
98 base::RandInt(std::numeric_limits<int>::min(),
99 std::numeric_limits<int>::max())}};
100 case base::Value::TYPE_DOUBLE:
101 return std::unique_ptr<base::Value>{
102 new base::FundamentalValue{base::RandDouble()}};
103 case base::Value::TYPE_STRING:
104 return std::unique_ptr<base::Value>{
105 new base::StringValue{base::GenerateGUID()}};
106 case base::Value::TYPE_DICTIONARY:
107 CHECK_GE(children, 1);
108 return CreateRandomDictionary(children - 1);
109 case base::Value::TYPE_LIST:
110 CHECK_GE(children, 1);
111 return CreateRandomList(children - 1);
112 default:
113 return std::unique_ptr<base::Value>{
114 new base::FundamentalValue{base::RandInt(0, 1) != 0}};
115 }
116}
117
118std::unique_ptr<base::Value> CreateRandomValue(int children) {
119 return CreateRandomValue(children, CreateRandomValueType(children > 0));
120}
121
122} // namespace
123
124TEST(DBusConversionTest, DictionaryToDBusVariantDictionary) {
125 EXPECT_EQ((VariantDictionary{{"bool", true}}),
126 ToDBus(*CreateDictionaryValue("{'bool': true}")));
127 EXPECT_EQ((VariantDictionary{{"int", 5}}),
128 ToDBus(*CreateDictionaryValue("{'int': 5}")));
129 EXPECT_EQ((VariantDictionary{{"double", 6.7}}),
130 ToDBus(*CreateDictionaryValue("{'double': 6.7}")));
131 EXPECT_EQ((VariantDictionary{{"string", std::string{"abc"}}}),
132 ToDBus(*CreateDictionaryValue("{'string': 'abc'}")));
133 EXPECT_EQ((VariantDictionary{{"object", VariantDictionary{{"bool", true}}}}),
134 ToDBus(*CreateDictionaryValue("{'object': {'bool': true}}")));
135 EXPECT_EQ((VariantDictionary{{"emptyList", std::vector<Any>{}}}),
136 ToDBus(*CreateDictionaryValue("{'emptyList': []}")));
137 EXPECT_EQ((VariantDictionary{{"intList", std::vector<int>{5}}}),
138 ToDBus(*CreateDictionaryValue("{'intList': [5]}")));
139 EXPECT_EQ((VariantDictionary{
140 {"intListList", std::vector<Any>{std::vector<int>{5},
141 std::vector<int>{6, 7}}}}),
142 ToDBus(*CreateDictionaryValue("{'intListList': [[5], [6, 7]]}")));
143 EXPECT_EQ((VariantDictionary{{"objList",
144 std::vector<VariantDictionary>{
145 {{"string", std::string{"abc"}}}}}}),
146 ToDBus(*CreateDictionaryValue("{'objList': [{'string': 'abc'}]}")));
147}
148
149TEST(DBusConversionTest, DictionaryFromDBusVariantDictionary) {
150 EXPECT_JSON_EQ("{'bool': true}", *FromDBus({{"bool", true}}));
151 EXPECT_JSON_EQ("{'int': 5}", *FromDBus({{"int", 5}}));
152 EXPECT_JSON_EQ("{'double': 6.7}", *FromDBus({{"double", 6.7}}));
153 EXPECT_JSON_EQ("{'string': 'abc'}",
154 *FromDBus({{"string", std::string{"abc"}}}));
155 EXPECT_JSON_EQ("{'object': {'bool': true}}",
156 *FromDBus({{"object", VariantDictionary{{"bool", true}}}}));
157 EXPECT_JSON_EQ("{'emptyList': []}",
158 *FromDBus({{"emptyList", std::vector<bool>{}}}));
159 EXPECT_JSON_EQ("{'intList': [5]}",
160 *FromDBus({{"intList", std::vector<int>{5}}}));
161 EXPECT_JSON_EQ(
162 "{'intListList': [[5], [6, 7]]}",
163 *FromDBus({{"intListList", std::vector<Any>{std::vector<int>{5},
164 std::vector<int>{6, 7}}}}));
165 EXPECT_JSON_EQ(
166 "{'objList': [{'string': 'abc'}]}",
167 *FromDBus({{"objList", std::vector<VariantDictionary>{
168 {{"string", std::string{"abc"}}}}}}));
169 EXPECT_JSON_EQ("{'int': 5}", *FromDBus({{"int", Any{Any{5}}}}));
170}
171
172TEST(DBusConversionTest, DictionaryFromDBusVariantDictionary_Errors) {
173 EXPECT_FALSE(FromDBus({{"cString", "abc"}}));
174 EXPECT_FALSE(FromDBus({{"float", 1.0f}}));
175 EXPECT_FALSE(FromDBus({{"listList", std::vector<std::vector<int>>{}}}));
176 EXPECT_FALSE(FromDBus({{"any", Any{}}}));
177 EXPECT_FALSE(FromDBus({{"null", nullptr}}));
178}
179
180TEST(DBusConversionTest, DBusRandomDictionaryConversion) {
181 auto dict = CreateRandomDictionary(10000);
182 auto varian_dict = ToDBus(*dict);
183 auto dict_restored = FromDBus(varian_dict);
184 EXPECT_PRED2(IsEqualValue, *dict, *dict_restored);
185}
186
187} // namespace buffet