blob: 4d0b90a2758c94cb8820b90e597160d22a38da8a [file] [log] [blame]
Alex Vakulenko66ec2922014-06-17 15:30:22 -07001// 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
Alex Deymof6cbe322014-11-10 19:55:35 -08005#include "buffet/commands/schema_utils.h"
6
Alex Vakulenko66ec2922014-06-17 15:30:22 -07007#include <memory>
8#include <string>
9#include <vector>
10
Alex Vakulenko66ec2922014-06-17 15:30:22 -070011#include <base/values.h>
Alex Vakulenko576c9792014-09-22 16:49:45 -070012#include <chromeos/variant_dictionary.h>
Alex Vakulenko66ec2922014-06-17 15:30:22 -070013#include <gtest/gtest.h>
14
15#include "buffet/commands/object_schema.h"
16#include "buffet/commands/prop_types.h"
17#include "buffet/commands/prop_values.h"
Alex Vakulenkoa32d83a2014-09-19 15:05:24 -070018#include "buffet/commands/schema_constants.h"
Alex Vakulenko6201d2d2014-07-16 14:46:48 -070019#include "buffet/commands/unittest_utils.h"
Alex Vakulenko66ec2922014-06-17 15:30:22 -070020
Alex Vakulenkoa32d83a2014-09-19 15:05:24 -070021using buffet::unittests::CreateDictionaryValue;
Alex Vakulenko6201d2d2014-07-16 14:46:48 -070022using buffet::unittests::CreateValue;
23using buffet::unittests::ValueToString;
Alex Vakulenko576c9792014-09-22 16:49:45 -070024using chromeos::VariantDictionary;
Alex Vakulenko66ec2922014-06-17 15:30:22 -070025
26TEST(CommandSchemaUtils, TypedValueToJson_Scalar) {
27 EXPECT_EQ("true",
28 ValueToString(buffet::TypedValueToJson(true, nullptr).get()));
29 EXPECT_EQ("false",
30 ValueToString(buffet::TypedValueToJson(false, nullptr).get()));
31
32 EXPECT_EQ("0", ValueToString(buffet::TypedValueToJson(0, nullptr).get()));
33 EXPECT_EQ("-10", ValueToString(buffet::TypedValueToJson(-10, nullptr).get()));
34 EXPECT_EQ("20", ValueToString(buffet::TypedValueToJson(20, nullptr).get()));
35
36 EXPECT_EQ("0.0", ValueToString(buffet::TypedValueToJson(0.0, nullptr).get()));
37 EXPECT_EQ("1.2", ValueToString(buffet::TypedValueToJson(1.2, nullptr).get()));
38
39 EXPECT_EQ("'abc'",
40 ValueToString(buffet::TypedValueToJson(std::string("abc"),
41 nullptr).get()));
42
43 std::vector<bool> bool_array{true, false};
44 EXPECT_EQ("[true,false]",
45 ValueToString(buffet::TypedValueToJson(bool_array, nullptr).get()));
46
47 std::vector<int> int_array{1, 2, 5};
48 EXPECT_EQ("[1,2,5]",
49 ValueToString(buffet::TypedValueToJson(int_array, nullptr).get()));
50
51 std::vector<double> dbl_array{1.1, 2.2};
52 EXPECT_EQ("[1.1,2.2]",
53 ValueToString(buffet::TypedValueToJson(dbl_array, nullptr).get()));
54
55 std::vector<std::string> str_array{"a", "bc"};
56 EXPECT_EQ("['a','bc']",
57 ValueToString(buffet::TypedValueToJson(str_array, nullptr).get()));
58}
59
60TEST(CommandSchemaUtils, TypedValueToJson_Object) {
61 buffet::IntPropType int_type;
62 buffet::native_types::Object object;
63
Alex Vakulenko157ccaa2014-09-19 14:59:34 -070064 object.insert(std::make_pair("width", int_type.CreateValue(640, nullptr)));
65 object.insert(std::make_pair("height", int_type.CreateValue(480, nullptr)));
Alex Vakulenko66ec2922014-06-17 15:30:22 -070066 EXPECT_EQ("{'height':480,'width':640}",
67 ValueToString(buffet::TypedValueToJson(object, nullptr).get()));
68}
69
70TEST(CommandSchemaUtils, TypedValueFromJson_Bool) {
71 bool value;
72
73 EXPECT_TRUE(buffet::TypedValueFromJson(CreateValue("true").get(), nullptr,
74 &value, nullptr));
75 EXPECT_TRUE(value);
76
77 EXPECT_TRUE(buffet::TypedValueFromJson(CreateValue("false").get(), nullptr,
78 &value, nullptr));
79 EXPECT_FALSE(value);
80
Alex Vakulenko5f472062014-08-14 17:54:04 -070081 chromeos::ErrorPtr error;
Alex Vakulenko66ec2922014-06-17 15:30:22 -070082 EXPECT_FALSE(buffet::TypedValueFromJson(CreateValue("0").get(), nullptr,
83 &value, &error));
Alex Vakulenkoa32d83a2014-09-19 15:05:24 -070084 EXPECT_EQ(buffet::errors::commands::kTypeMismatch, error->GetCode());
Alex Vakulenko66ec2922014-06-17 15:30:22 -070085 error.reset();
86}
87
88TEST(CommandSchemaUtils, TypedValueFromJson_Int) {
89 int value;
90
91 EXPECT_TRUE(buffet::TypedValueFromJson(CreateValue("0").get(), nullptr,
92 &value, nullptr));
93 EXPECT_EQ(0, value);
94
95 EXPECT_TRUE(buffet::TypedValueFromJson(CreateValue("23").get(), nullptr,
96 &value, nullptr));
97 EXPECT_EQ(23, value);
98
99 EXPECT_TRUE(buffet::TypedValueFromJson(CreateValue("-1234").get(), nullptr,
100 &value, nullptr));
101 EXPECT_EQ(-1234, value);
102
Alex Vakulenko5f472062014-08-14 17:54:04 -0700103 chromeos::ErrorPtr error;
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700104 EXPECT_FALSE(buffet::TypedValueFromJson(CreateValue("'abc'").get(), nullptr,
105 &value, &error));
Alex Vakulenkoa32d83a2014-09-19 15:05:24 -0700106 EXPECT_EQ(buffet::errors::commands::kTypeMismatch, error->GetCode());
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700107 error.reset();
108}
109
110TEST(CommandSchemaUtils, TypedValueFromJson_Double) {
111 double value;
112
113 EXPECT_TRUE(buffet::TypedValueFromJson(CreateValue("0").get(), nullptr,
114 &value, nullptr));
115 EXPECT_DOUBLE_EQ(0.0, value);
116 EXPECT_TRUE(buffet::TypedValueFromJson(CreateValue("0.0").get(), nullptr,
117 &value, nullptr));
118 EXPECT_DOUBLE_EQ(0.0, value);
119
120 EXPECT_TRUE(buffet::TypedValueFromJson(CreateValue("23").get(), nullptr,
121 &value, nullptr));
122 EXPECT_EQ(23.0, value);
123 EXPECT_TRUE(buffet::TypedValueFromJson(CreateValue("23.1").get(), nullptr,
124 &value, nullptr));
125 EXPECT_EQ(23.1, value);
126
127 EXPECT_TRUE(buffet::TypedValueFromJson(CreateValue("-1.23E+02").get(),
128 nullptr, &value, nullptr));
129 EXPECT_EQ(-123.0, value);
130
Alex Vakulenko5f472062014-08-14 17:54:04 -0700131 chromeos::ErrorPtr error;
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700132 EXPECT_FALSE(buffet::TypedValueFromJson(CreateValue("'abc'").get(), nullptr,
133 &value, &error));
Alex Vakulenkoa32d83a2014-09-19 15:05:24 -0700134 EXPECT_EQ(buffet::errors::commands::kTypeMismatch, error->GetCode());
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700135 error.reset();
136}
137
138TEST(CommandSchemaUtils, TypedValueFromJson_String) {
139 std::string value;
140
141 EXPECT_TRUE(buffet::TypedValueFromJson(CreateValue("''").get(), nullptr,
142 &value, nullptr));
143 EXPECT_EQ("", value);
144
145 EXPECT_TRUE(buffet::TypedValueFromJson(CreateValue("'23'").get(), nullptr,
146 &value, nullptr));
147 EXPECT_EQ("23", value);
148
149 EXPECT_TRUE(buffet::TypedValueFromJson(CreateValue("'abc'").get(), nullptr,
150 &value, nullptr));
151 EXPECT_EQ("abc", value);
152
Alex Vakulenko5f472062014-08-14 17:54:04 -0700153 chromeos::ErrorPtr error;
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700154 EXPECT_FALSE(buffet::TypedValueFromJson(CreateValue("12").get(), nullptr,
155 &value, &error));
Alex Vakulenkoa32d83a2014-09-19 15:05:24 -0700156 EXPECT_EQ(buffet::errors::commands::kTypeMismatch, error->GetCode());
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700157 error.reset();
158}
159
160TEST(CommandSchemaUtils, TypedValueFromJson_Object) {
161 buffet::native_types::Object value;
162 buffet::ObjectSchema schema;
163
164 auto age_prop = std::make_shared<buffet::IntPropType>();
165 age_prop->AddMinMaxConstraint(0, 150);
166 schema.AddProp("age", age_prop);
167
168 auto name_prop = std::make_shared<buffet::StringPropType>();
169 name_prop->AddLengthConstraint(1, 30);
170 schema.AddProp("name", name_prop);
171
172 EXPECT_TRUE(buffet::TypedValueFromJson(
173 CreateValue("{'age':20,'name':'Bob'}").get(), &schema, &value, nullptr));
174 buffet::native_types::Object value2;
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700175 value2.insert(std::make_pair("age", age_prop->CreateValue(20, nullptr)));
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700176 value2.insert(std::make_pair("name",
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700177 name_prop->CreateValue(std::string("Bob"),
178 nullptr)));
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700179 EXPECT_EQ(value2, value);
180
Alex Vakulenko5f472062014-08-14 17:54:04 -0700181 chromeos::ErrorPtr error;
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700182 EXPECT_FALSE(buffet::TypedValueFromJson(CreateValue("'abc'").get(), nullptr,
183 &value, &error));
Alex Vakulenkoa32d83a2014-09-19 15:05:24 -0700184 EXPECT_EQ(buffet::errors::commands::kTypeMismatch, error->GetCode());
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700185 error.reset();
186}
Alex Vakulenkoa32d83a2014-09-19 15:05:24 -0700187
188TEST(CommandSchemaUtils, PropValueToDBusVariant) {
189 buffet::IntPropType int_type;
190 auto prop_value = int_type.CreateValue(5, nullptr);
191 EXPECT_EQ(5, PropValueToDBusVariant(prop_value.get()).Get<int>());
192
193 buffet::BooleanPropType bool_type;
194 prop_value = bool_type.CreateValue(true, nullptr);
195 EXPECT_TRUE(PropValueToDBusVariant(prop_value.get()).Get<bool>());
196
197 buffet::DoublePropType dbl_type;
198 prop_value = dbl_type.CreateValue(5.5, nullptr);
199 EXPECT_DOUBLE_EQ(5.5, PropValueToDBusVariant(prop_value.get()).Get<double>());
200
201 buffet::StringPropType str_type;
202 prop_value = str_type.CreateValue(std::string{"foo"}, nullptr);
203 EXPECT_EQ("foo", PropValueToDBusVariant(prop_value.get()).Get<std::string>());
204
205 buffet::ObjectPropType obj_type;
206 ASSERT_TRUE(obj_type.FromJson(CreateDictionaryValue(
207 "{'properties':{'width':'integer','height':'integer'},"
208 "'enum':[{'width':10,'height':20},{'width':100,'height':200}]}").get(),
209 nullptr, nullptr));
210 buffet::native_types::Object obj{
211 {"width", int_type.CreateValue(10, nullptr)},
212 {"height", int_type.CreateValue(20, nullptr)},
213 };
214 prop_value = obj_type.CreateValue(obj, nullptr);
Alex Vakulenko576c9792014-09-22 16:49:45 -0700215 VariantDictionary dict =
216 PropValueToDBusVariant(prop_value.get()).Get<VariantDictionary>();
Alex Vakulenkoa32d83a2014-09-19 15:05:24 -0700217 EXPECT_EQ(20, dict["height"].Get<int>());
218 EXPECT_EQ(10, dict["width"].Get<int>());
219}
220
221TEST(CommandSchemaUtils, PropValueFromDBusVariant_Int) {
222 buffet::IntPropType int_type;
223 ASSERT_TRUE(int_type.FromJson(CreateDictionaryValue("{'enum':[1,2]}").get(),
224 nullptr, nullptr));
225
226 auto prop_value = PropValueFromDBusVariant(&int_type, 1, nullptr);
227 ASSERT_NE(nullptr, prop_value.get());
228 EXPECT_EQ(1, prop_value->GetValueAsAny().Get<int>());
229
230 chromeos::ErrorPtr error;
231 prop_value = PropValueFromDBusVariant(&int_type, 5, &error);
232 EXPECT_EQ(nullptr, prop_value.get());
233 ASSERT_NE(nullptr, error.get());
234 EXPECT_EQ(buffet::errors::commands::kOutOfRange, error->GetCode());
235}
236
237TEST(CommandSchemaUtils, PropValueFromDBusVariant_Bool) {
238 buffet::BooleanPropType bool_type;
239 ASSERT_TRUE(bool_type.FromJson(CreateDictionaryValue("{'enum':[true]}").get(),
240 nullptr, nullptr));
241
242 auto prop_value = PropValueFromDBusVariant(&bool_type, true, nullptr);
243 ASSERT_NE(nullptr, prop_value.get());
244 EXPECT_TRUE(prop_value->GetValueAsAny().Get<bool>());
245
246 chromeos::ErrorPtr error;
247 prop_value = PropValueFromDBusVariant(&bool_type, false, &error);
248 EXPECT_EQ(nullptr, prop_value.get());
249 ASSERT_NE(nullptr, error.get());
250 EXPECT_EQ(buffet::errors::commands::kOutOfRange, error->GetCode());
251}
252
253TEST(CommandSchemaUtils, PropValueFromDBusVariant_Double) {
254 buffet::DoublePropType dbl_type;
255 ASSERT_TRUE(dbl_type.FromJson(CreateDictionaryValue("{'maximum':2.0}").get(),
256 nullptr, nullptr));
257
258 auto prop_value = PropValueFromDBusVariant(&dbl_type, 1.0, nullptr);
259 ASSERT_NE(nullptr, prop_value.get());
260 EXPECT_DOUBLE_EQ(1.0, prop_value->GetValueAsAny().Get<double>());
261
262 chromeos::ErrorPtr error;
263 prop_value = PropValueFromDBusVariant(&dbl_type, 10.0, &error);
264 EXPECT_EQ(nullptr, prop_value.get());
265 ASSERT_NE(nullptr, error.get());
266 EXPECT_EQ(buffet::errors::commands::kOutOfRange, error->GetCode());
267}
268
269TEST(CommandSchemaUtils, PropValueFromDBusVariant_String) {
270 buffet::StringPropType str_type;
271 ASSERT_TRUE(str_type.FromJson(CreateDictionaryValue("{'minLength': 4}").get(),
272 nullptr, nullptr));
273
274 auto prop_value = PropValueFromDBusVariant(&str_type, std::string{"blah"},
275 nullptr);
276 ASSERT_NE(nullptr, prop_value.get());
277 EXPECT_EQ("blah", prop_value->GetValueAsAny().Get<std::string>());
278
279 chromeos::ErrorPtr error;
280 prop_value = PropValueFromDBusVariant(&str_type, std::string{"foo"}, &error);
281 EXPECT_EQ(nullptr, prop_value.get());
282 ASSERT_NE(nullptr, error.get());
283 EXPECT_EQ(buffet::errors::commands::kOutOfRange, error->GetCode());
284}
285
286TEST(CommandSchemaUtils, PropValueFromDBusVariant_Object) {
287 buffet::ObjectPropType obj_type;
288 ASSERT_TRUE(obj_type.FromJson(CreateDictionaryValue(
289 "{'properties':{'width':'integer','height':'integer'},"
290 "'enum':[{'width':10,'height':20},{'width':100,'height':200}]}").get(),
291 nullptr, nullptr));
292
Alex Vakulenko576c9792014-09-22 16:49:45 -0700293 VariantDictionary obj{
Alex Vakulenkoa32d83a2014-09-19 15:05:24 -0700294 {"width", 100},
295 {"height", 200},
296 };
297 auto prop_value = PropValueFromDBusVariant(&obj_type, obj, nullptr);
298 ASSERT_NE(nullptr, prop_value.get());
299 auto value = prop_value->GetValueAsAny().Get<buffet::native_types::Object>();
300 EXPECT_EQ(100, value["width"].get()->GetValueAsAny().Get<int>());
301 EXPECT_EQ(200, value["height"].get()->GetValueAsAny().Get<int>());
302
303 chromeos::ErrorPtr error;
304 obj["height"] = 20;
305 prop_value = PropValueFromDBusVariant(&obj_type, obj, &error);
306 EXPECT_EQ(nullptr, prop_value.get());
307 ASSERT_NE(nullptr, error.get());
308 EXPECT_EQ(buffet::errors::commands::kOutOfRange, error->GetCode());
309}