blob: 0f429a18521715467ba24742c8815b563cfbb487 [file] [log] [blame]
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -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/object_schema.h"
6
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07007#include <algorithm>
8#include <limits>
9#include <memory>
10#include <vector>
11
12#include <base/json/json_reader.h>
13#include <base/json/json_writer.h>
14#include <base/values.h>
15#include <gtest/gtest.h>
16
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070017#include "buffet/commands/prop_types.h"
Alex Vakulenko157ccaa2014-09-19 14:59:34 -070018#include "buffet/commands/schema_constants.h"
Alex Vakulenko6201d2d2014-07-16 14:46:48 -070019#include "buffet/commands/unittest_utils.h"
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070020
Alex Vakulenko6201d2d2014-07-16 14:46:48 -070021using buffet::unittests::CreateValue;
22using buffet::unittests::CreateDictionaryValue;
23using buffet::unittests::ValueToString;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070024
25TEST(CommandSchema, IntPropType_Empty) {
26 buffet::IntPropType prop;
27 EXPECT_TRUE(prop.GetConstraints().empty());
28 EXPECT_FALSE(prop.HasOverriddenAttributes());
29 EXPECT_FALSE(prop.IsBasedOnSchema());
Alex Vakulenko2a17a532015-02-24 14:51:13 -080030 EXPECT_EQ(nullptr, prop.GetDefaultValue());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070031}
32
33TEST(CommandSchema, IntPropType_Types) {
34 buffet::IntPropType prop;
35 EXPECT_EQ(nullptr, prop.GetBoolean());
36 EXPECT_EQ(&prop, prop.GetInt());
37 EXPECT_EQ(nullptr, prop.GetDouble());
38 EXPECT_EQ(nullptr, prop.GetString());
Alex Vakulenko66ec2922014-06-17 15:30:22 -070039 EXPECT_EQ(nullptr, prop.GetObject());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070040}
41
42TEST(CommandSchema, IntPropType_ToJson) {
43 buffet::IntPropType prop;
44 EXPECT_EQ("'integer'", ValueToString(prop.ToJson(false, nullptr).get()));
45 EXPECT_EQ("{'type':'integer'}",
46 ValueToString(prop.ToJson(true, nullptr).get()));
47 buffet::IntPropType param2;
48 param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
49 EXPECT_EQ("{}", ValueToString(param2.ToJson(false, nullptr).get()));
50 param2.FromJson(CreateDictionaryValue("{'minimum':3}").get(),
51 &prop, nullptr);
52 EXPECT_EQ("{'minimum':3}",
53 ValueToString(param2.ToJson(false, nullptr).get()));
54 param2.FromJson(CreateDictionaryValue("{'maximum':-7}").get(),
55 &prop, nullptr);
56 EXPECT_EQ("{'maximum':-7}",
57 ValueToString(param2.ToJson(false, nullptr).get()));
58 param2.FromJson(CreateDictionaryValue("{'minimum':0,'maximum':5}").get(),
59 &prop, nullptr);
60 EXPECT_EQ("{'maximum':5,'minimum':0}",
61 ValueToString(param2.ToJson(false, nullptr).get()));
62 param2.FromJson(CreateDictionaryValue("{'enum':[1,2,3]}").get(), &prop,
63 nullptr);
64 EXPECT_EQ("[1,2,3]",
65 ValueToString(param2.ToJson(false, nullptr).get()));
Alex Vakulenko2a17a532015-02-24 14:51:13 -080066 param2.FromJson(CreateDictionaryValue("{'default':123}").get(),
67 &prop, nullptr);
68 EXPECT_EQ("{'default':123}",
69 ValueToString(param2.ToJson(false, nullptr).get()));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070070}
71
72TEST(CommandSchema, IntPropType_FromJson) {
73 buffet::IntPropType prop;
74 prop.AddMinMaxConstraint(2, 8);
75 buffet::IntPropType param2;
76 param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
77 EXPECT_FALSE(param2.HasOverriddenAttributes());
78 EXPECT_TRUE(param2.IsBasedOnSchema());
79 EXPECT_EQ(2, prop.GetMinValue());
80 EXPECT_EQ(8, prop.GetMaxValue());
81 prop.AddMinMaxConstraint(-2, 30);
82 param2.FromJson(CreateDictionaryValue("{'minimum':7}").get(),
83 &prop, nullptr);
84 EXPECT_TRUE(param2.HasOverriddenAttributes());
85 EXPECT_TRUE(param2.IsBasedOnSchema());
86 EXPECT_EQ(7, param2.GetMinValue());
87 EXPECT_EQ(30, param2.GetMaxValue());
88 param2.FromJson(CreateDictionaryValue("{'maximum':17}").get(),
89 &prop, nullptr);
90 EXPECT_TRUE(param2.HasOverriddenAttributes());
91 EXPECT_TRUE(param2.IsBasedOnSchema());
92 EXPECT_EQ(-2, param2.GetMinValue());
93 EXPECT_EQ(17, param2.GetMaxValue());
Alex Vakulenko2a17a532015-02-24 14:51:13 -080094
95 ASSERT_TRUE(param2.FromJson(CreateDictionaryValue("{'default':3}").get(),
96 &prop, nullptr));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070097 EXPECT_TRUE(param2.HasOverriddenAttributes());
Alex Vakulenko2a17a532015-02-24 14:51:13 -080098 ASSERT_NE(nullptr, param2.GetDefaultValue());
99 EXPECT_EQ(3, param2.GetDefaultValue()->GetInt()->GetValue());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700100}
101
102TEST(CommandSchema, IntPropType_Validate) {
103 buffet::IntPropType prop;
104 prop.AddMinMaxConstraint(2, 4);
Alex Vakulenko5f472062014-08-14 17:54:04 -0700105 chromeos::ErrorPtr error;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700106 EXPECT_FALSE(prop.ValidateValue(CreateValue("-1").get(), &error));
107 EXPECT_EQ("out_of_range", error->GetCode());
108 error.reset();
109 EXPECT_FALSE(prop.ValidateValue(CreateValue("0").get(), &error));
110 EXPECT_EQ("out_of_range", error->GetCode());
111 error.reset();
112 EXPECT_FALSE(prop.ValidateValue(CreateValue("1").get(), &error));
113 EXPECT_EQ("out_of_range", error->GetCode());
114 error.reset();
115 EXPECT_TRUE(prop.ValidateValue(CreateValue("2").get(), &error));
116 EXPECT_EQ(nullptr, error.get());
117 EXPECT_TRUE(prop.ValidateValue(CreateValue("3").get(), &error));
118 EXPECT_EQ(nullptr, error.get());
119 EXPECT_TRUE(prop.ValidateValue(CreateValue("4").get(), &error));
120 EXPECT_EQ(nullptr, error.get());
121 EXPECT_FALSE(prop.ValidateValue(CreateValue("5").get(), &error));
122 EXPECT_EQ("out_of_range", error->GetCode());
123 error.reset();
124 EXPECT_FALSE(prop.ValidateValue(CreateValue("true").get(), &error));
125 EXPECT_EQ("type_mismatch", error->GetCode());
126 error.reset();
127 EXPECT_FALSE(prop.ValidateValue(CreateValue("3.0").get(), &error));
128 EXPECT_EQ("type_mismatch", error->GetCode());
129 error.reset();
130 EXPECT_FALSE(prop.ValidateValue(CreateValue("'3'").get(), &error));
131 EXPECT_EQ("type_mismatch", error->GetCode());
132}
133
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700134TEST(CommandSchema, IntPropType_CreateValue) {
135 buffet::IntPropType prop;
136 chromeos::ErrorPtr error;
137 auto val = prop.CreateValue(2, &error);
138 ASSERT_NE(nullptr, val.get());
139 EXPECT_EQ(nullptr, error.get());
140 EXPECT_EQ(2, val->GetValueAsAny().Get<int>());
141
142 val = prop.CreateValue("blah", &error);
143 EXPECT_EQ(nullptr, val.get());
144 ASSERT_NE(nullptr, error.get());
145 EXPECT_EQ(buffet::errors::commands::kTypeMismatch, error->GetCode());
146}
147
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700148///////////////////////////////////////////////////////////////////////////////
149
150TEST(CommandSchema, BoolPropType_Empty) {
151 buffet::BooleanPropType prop;
152 EXPECT_TRUE(prop.GetConstraints().empty());
153 EXPECT_FALSE(prop.HasOverriddenAttributes());
154 EXPECT_FALSE(prop.IsBasedOnSchema());
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800155 EXPECT_EQ(nullptr, prop.GetDefaultValue());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700156}
157
158TEST(CommandSchema, BoolPropType_Types) {
159 buffet::BooleanPropType prop;
160 EXPECT_EQ(nullptr, prop.GetInt());
161 EXPECT_EQ(&prop, prop.GetBoolean());
162 EXPECT_EQ(nullptr, prop.GetDouble());
163 EXPECT_EQ(nullptr, prop.GetString());
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700164 EXPECT_EQ(nullptr, prop.GetObject());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700165}
166
167TEST(CommandSchema, BoolPropType_ToJson) {
168 buffet::BooleanPropType prop;
169 EXPECT_EQ("'boolean'", ValueToString(prop.ToJson(false, nullptr).get()));
170 EXPECT_EQ("{'type':'boolean'}",
171 ValueToString(prop.ToJson(true, nullptr).get()));
172 buffet::BooleanPropType param2;
173 param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
174 EXPECT_EQ("{}", ValueToString(param2.ToJson(false, nullptr).get()));
175 param2.FromJson(CreateDictionaryValue("{'enum':[true,false]}").get(), &prop,
176 nullptr);
177 EXPECT_EQ("[true,false]", ValueToString(param2.ToJson(false, nullptr).get()));
178 EXPECT_EQ("{'enum':[true,false],'type':'boolean'}",
179 ValueToString(param2.ToJson(true, nullptr).get()));
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800180 param2.FromJson(CreateDictionaryValue("{'default':true}").get(),
181 &prop, nullptr);
182 EXPECT_EQ("{'default':true}",
183 ValueToString(param2.ToJson(false, nullptr).get()));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700184}
185
186TEST(CommandSchema, BoolPropType_FromJson) {
187 buffet::BooleanPropType prop;
188 prop.FromJson(CreateDictionaryValue("{'enum':[true]}").get(), &prop,
189 nullptr);
190 buffet::BooleanPropType param2;
191 param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
192 EXPECT_FALSE(param2.HasOverriddenAttributes());
193 EXPECT_TRUE(param2.IsBasedOnSchema());
194 EXPECT_EQ(std::vector<bool>{true}, prop.GetOneOfValues());
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800195
196 buffet::BooleanPropType prop_base;
197 buffet::BooleanPropType param3;
198 ASSERT_TRUE(param3.FromJson(CreateDictionaryValue("{'default':false}").get(),
199 &prop_base, nullptr));
200 EXPECT_TRUE(param3.HasOverriddenAttributes());
201 ASSERT_NE(nullptr, param3.GetDefaultValue());
202 EXPECT_FALSE(param3.GetDefaultValue()->GetBoolean()->GetValue());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700203}
204
205TEST(CommandSchema, BoolPropType_Validate) {
206 buffet::BooleanPropType prop;
207 prop.FromJson(CreateDictionaryValue("{'enum':[true]}").get(), &prop,
208 nullptr);
Alex Vakulenko5f472062014-08-14 17:54:04 -0700209 chromeos::ErrorPtr error;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700210 EXPECT_FALSE(prop.ValidateValue(CreateValue("false").get(), &error));
211 EXPECT_EQ("out_of_range", error->GetCode());
212 error.reset();
213 EXPECT_TRUE(prop.ValidateValue(CreateValue("true").get(), &error));
214 error.reset();
215 EXPECT_FALSE(prop.ValidateValue(CreateValue("1").get(), &error));
216 EXPECT_EQ("type_mismatch", error->GetCode());
217 error.reset();
218 EXPECT_FALSE(prop.ValidateValue(CreateValue("3.0").get(), &error));
219 EXPECT_EQ("type_mismatch", error->GetCode());
220 error.reset();
221 EXPECT_FALSE(prop.ValidateValue(CreateValue("'3'").get(), &error));
222 EXPECT_EQ("type_mismatch", error->GetCode());
223}
224
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700225TEST(CommandSchema, BoolPropType_CreateValue) {
226 buffet::BooleanPropType prop;
227 chromeos::ErrorPtr error;
228 auto val = prop.CreateValue(true, &error);
229 ASSERT_NE(nullptr, val.get());
230 EXPECT_EQ(nullptr, error.get());
231 EXPECT_TRUE(val->GetValueAsAny().Get<bool>());
232
233 val = prop.CreateValue("blah", &error);
234 EXPECT_EQ(nullptr, val.get());
235 ASSERT_NE(nullptr, error.get());
236 EXPECT_EQ(buffet::errors::commands::kTypeMismatch, error->GetCode());
237}
238
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700239///////////////////////////////////////////////////////////////////////////////
240
241TEST(CommandSchema, DoublePropType_Empty) {
242 buffet::DoublePropType prop;
243 EXPECT_DOUBLE_EQ(std::numeric_limits<double>::lowest(), prop.GetMinValue());
244 EXPECT_DOUBLE_EQ((std::numeric_limits<double>::max)(), prop.GetMaxValue());
245 EXPECT_FALSE(prop.HasOverriddenAttributes());
246 EXPECT_FALSE(prop.IsBasedOnSchema());
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800247 EXPECT_EQ(nullptr, prop.GetDefaultValue());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700248}
249
250TEST(CommandSchema, DoublePropType_Types) {
251 buffet::DoublePropType prop;
252 EXPECT_EQ(nullptr, prop.GetInt());
253 EXPECT_EQ(nullptr, prop.GetBoolean());
254 EXPECT_EQ(&prop, prop.GetDouble());
255 EXPECT_EQ(nullptr, prop.GetString());
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700256 EXPECT_EQ(nullptr, prop.GetObject());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700257}
258
259TEST(CommandSchema, DoublePropType_ToJson) {
260 buffet::DoublePropType prop;
261 EXPECT_EQ("'number'", ValueToString(prop.ToJson(false, nullptr).get()));
262 EXPECT_EQ("{'type':'number'}",
263 ValueToString(prop.ToJson(true, nullptr).get()));
264 buffet::DoublePropType param2;
265 param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
266 EXPECT_EQ("{}", ValueToString(param2.ToJson(false, nullptr).get()));
267 param2.FromJson(CreateDictionaryValue("{'minimum':3}").get(), &prop,
268 nullptr);
269 EXPECT_EQ("{'minimum':3.0}",
270 ValueToString(param2.ToJson(false, nullptr).get()));
271 param2.FromJson(CreateDictionaryValue("{'maximum':-7}").get(), &prop,
272 nullptr);
273 EXPECT_EQ("{'maximum':-7.0}",
274 ValueToString(param2.ToJson(false, nullptr).get()));
275 param2.FromJson(CreateDictionaryValue("{'minimum':0,'maximum':5}").get(),
276 &prop, nullptr);
277 EXPECT_EQ("{'maximum':5.0,'minimum':0.0}",
278 ValueToString(param2.ToJson(false, nullptr).get()));
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800279 param2.FromJson(CreateDictionaryValue("{'default':12.3}").get(),
280 &prop, nullptr);
281 EXPECT_EQ("{'default':12.3}",
282 ValueToString(param2.ToJson(false, nullptr).get()));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700283}
284
285TEST(CommandSchema, DoublePropType_FromJson) {
286 buffet::DoublePropType prop;
287 prop.AddMinMaxConstraint(2.5, 8.7);
288 buffet::DoublePropType param2;
289 param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
290 EXPECT_FALSE(param2.HasOverriddenAttributes());
291 EXPECT_TRUE(param2.IsBasedOnSchema());
292 EXPECT_DOUBLE_EQ(2.5, prop.GetMinValue());
293 EXPECT_DOUBLE_EQ(8.7, prop.GetMaxValue());
294 prop.AddMinMaxConstraint(-2.2, 30.4);
295 param2.FromJson(CreateDictionaryValue("{'minimum':7}").get(), &prop,
296 nullptr);
297 EXPECT_TRUE(param2.HasOverriddenAttributes());
298 EXPECT_TRUE(param2.IsBasedOnSchema());
299 EXPECT_DOUBLE_EQ(7.0, param2.GetMinValue());
300 EXPECT_DOUBLE_EQ(30.4, param2.GetMaxValue());
301 param2.FromJson(CreateDictionaryValue("{'maximum':17.2}").get(), &prop,
302 nullptr);
303 EXPECT_TRUE(param2.HasOverriddenAttributes());
304 EXPECT_TRUE(param2.IsBasedOnSchema());
305 EXPECT_DOUBLE_EQ(-2.2, param2.GetMinValue());
306 EXPECT_DOUBLE_EQ(17.2, param2.GetMaxValue());
307 param2.FromJson(CreateDictionaryValue("{'minimum':0,'maximum':6.1}").get(),
308 &prop, nullptr);
309 EXPECT_TRUE(param2.HasOverriddenAttributes());
310 EXPECT_TRUE(param2.IsBasedOnSchema());
311 EXPECT_DOUBLE_EQ(0.0, param2.GetMinValue());
312 EXPECT_DOUBLE_EQ(6.1, param2.GetMaxValue());
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800313
314 ASSERT_TRUE(param2.FromJson(CreateDictionaryValue("{'default':-1.234}").get(),
315 &prop, nullptr));
316 EXPECT_TRUE(param2.HasOverriddenAttributes());
317 ASSERT_NE(nullptr, param2.GetDefaultValue());
318 EXPECT_DOUBLE_EQ(-1.234, param2.GetDefaultValue()->GetDouble()->GetValue());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700319}
320
321TEST(CommandSchema, DoublePropType_Validate) {
322 buffet::DoublePropType prop;
323 prop.AddMinMaxConstraint(-1.2, 1.3);
Alex Vakulenko5f472062014-08-14 17:54:04 -0700324 chromeos::ErrorPtr error;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700325 EXPECT_FALSE(prop.ValidateValue(CreateValue("-2").get(), &error));
326 EXPECT_EQ("out_of_range", error->GetCode());
327 error.reset();
328 EXPECT_FALSE(prop.ValidateValue(CreateValue("-1.3").get(), &error));
329 EXPECT_EQ("out_of_range", error->GetCode());
330 error.reset();
331 EXPECT_TRUE(prop.ValidateValue(CreateValue("-1.2").get(), &error));
332 EXPECT_EQ(nullptr, error.get());
333 EXPECT_TRUE(prop.ValidateValue(CreateValue("0.0").get(), &error));
334 EXPECT_EQ(nullptr, error.get());
335 EXPECT_TRUE(prop.ValidateValue(CreateValue("1.3").get(), &error));
336 EXPECT_EQ(nullptr, error.get());
337 EXPECT_FALSE(prop.ValidateValue(CreateValue("1.31").get(), &error));
338 EXPECT_EQ("out_of_range", error->GetCode());
339 error.reset();
340 EXPECT_FALSE(prop.ValidateValue(CreateValue("true").get(), &error));
341 EXPECT_EQ("type_mismatch", error->GetCode());
342 error.reset();
343 EXPECT_FALSE(prop.ValidateValue(CreateValue("'0.0'").get(), &error));
344 EXPECT_EQ("type_mismatch", error->GetCode());
345}
346
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700347TEST(CommandSchema, DoublePropType_CreateValue) {
348 buffet::DoublePropType prop;
349 chromeos::ErrorPtr error;
350 auto val = prop.CreateValue(2.0, &error);
351 ASSERT_NE(nullptr, val.get());
352 EXPECT_EQ(nullptr, error.get());
353 EXPECT_DOUBLE_EQ(2.0, val->GetValueAsAny().Get<double>());
354
355 val = prop.CreateValue("blah", &error);
356 EXPECT_EQ(nullptr, val.get());
357 ASSERT_NE(nullptr, error.get());
358 EXPECT_EQ(buffet::errors::commands::kTypeMismatch, error->GetCode());
359}
360
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700361///////////////////////////////////////////////////////////////////////////////
362
363TEST(CommandSchema, StringPropType_Empty) {
364 buffet::StringPropType prop;
365 EXPECT_EQ(0, prop.GetMinLength());
366 EXPECT_EQ((std::numeric_limits<int>::max)(), prop.GetMaxLength());
367 EXPECT_FALSE(prop.HasOverriddenAttributes());
368 EXPECT_FALSE(prop.IsBasedOnSchema());
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800369 EXPECT_EQ(nullptr, prop.GetDefaultValue());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700370}
371
372TEST(CommandSchema, StringPropType_Types) {
373 buffet::StringPropType prop;
374 EXPECT_EQ(nullptr, prop.GetInt());
375 EXPECT_EQ(nullptr, prop.GetBoolean());
376 EXPECT_EQ(nullptr, prop.GetDouble());
377 EXPECT_EQ(&prop, prop.GetString());
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700378 EXPECT_EQ(nullptr, prop.GetObject());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700379}
380
381TEST(CommandSchema, StringPropType_ToJson) {
382 buffet::StringPropType prop;
383 EXPECT_EQ("'string'", ValueToString(prop.ToJson(false, nullptr).get()));
384 EXPECT_EQ("{'type':'string'}",
385 ValueToString(prop.ToJson(true, nullptr).get()));
386 buffet::StringPropType param2;
387 param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
388 EXPECT_EQ("{}", ValueToString(param2.ToJson(false, nullptr).get()));
389 param2.FromJson(CreateDictionaryValue("{'minLength':3}").get(), &prop,
390 nullptr);
391 EXPECT_EQ("{'minLength':3}",
392 ValueToString(param2.ToJson(false, nullptr).get()));
393 param2.FromJson(CreateDictionaryValue("{'maxLength':7}").get(), &prop,
394 nullptr);
395 EXPECT_EQ("{'maxLength':7}",
396 ValueToString(param2.ToJson(false, nullptr).get()));
397 param2.FromJson(CreateDictionaryValue("{'minLength':0,'maxLength':5}").get(),
398 &prop, nullptr);
399 EXPECT_EQ("{'maxLength':5,'minLength':0}",
400 ValueToString(param2.ToJson(false, nullptr).get()));
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800401 param2.FromJson(CreateDictionaryValue("{'default':'abcd'}").get(),
402 &prop, nullptr);
403 EXPECT_EQ("{'default':'abcd'}",
404 ValueToString(param2.ToJson(false, nullptr).get()));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700405}
406
407TEST(CommandSchema, StringPropType_FromJson) {
408 buffet::StringPropType prop;
409 prop.AddLengthConstraint(2, 8);
410 buffet::StringPropType param2;
411 param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
412 EXPECT_FALSE(param2.HasOverriddenAttributes());
413 EXPECT_TRUE(param2.IsBasedOnSchema());
414 EXPECT_EQ(2, prop.GetMinLength());
415 EXPECT_EQ(8, prop.GetMaxLength());
416 prop.AddLengthConstraint(3, 5);
417 param2.FromJson(CreateDictionaryValue("{'minLength':4}").get(), &prop,
418 nullptr);
419 EXPECT_TRUE(param2.HasOverriddenAttributes());
420 EXPECT_TRUE(param2.IsBasedOnSchema());
421 EXPECT_EQ(4, param2.GetMinLength());
422 EXPECT_EQ(5, param2.GetMaxLength());
423 param2.FromJson(CreateDictionaryValue("{'maxLength':8}").get(), &prop,
424 nullptr);
425 EXPECT_TRUE(param2.HasOverriddenAttributes());
426 EXPECT_TRUE(param2.IsBasedOnSchema());
427 EXPECT_EQ(3, param2.GetMinLength());
428 EXPECT_EQ(8, param2.GetMaxLength());
429 param2.FromJson(CreateDictionaryValue(
430 "{'minLength':1,'maxLength':7}").get(), &prop, nullptr);
431 EXPECT_TRUE(param2.HasOverriddenAttributes());
432 EXPECT_TRUE(param2.IsBasedOnSchema());
433 EXPECT_EQ(1, param2.GetMinLength());
434 EXPECT_EQ(7, param2.GetMaxLength());
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800435
436 ASSERT_TRUE(param2.FromJson(CreateDictionaryValue("{'default':'foo'}").get(),
437 &prop, nullptr));
438 EXPECT_TRUE(param2.HasOverriddenAttributes());
439 ASSERT_NE(nullptr, param2.GetDefaultValue());
440 EXPECT_EQ("foo", param2.GetDefaultValue()->GetString()->GetValue());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700441}
442
443TEST(CommandSchema, StringPropType_Validate) {
444 buffet::StringPropType prop;
445 prop.AddLengthConstraint(1, 3);
Alex Vakulenko5f472062014-08-14 17:54:04 -0700446 chromeos::ErrorPtr error;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700447 EXPECT_FALSE(prop.ValidateValue(CreateValue("''").get(), &error));
448 EXPECT_EQ("out_of_range", error->GetCode());
449 error.reset();
450 prop.AddLengthConstraint(2, 3);
451 EXPECT_FALSE(prop.ValidateValue(CreateValue("''").get(), &error));
452 EXPECT_EQ("out_of_range", error->GetCode());
453 error.reset();
454 EXPECT_FALSE(prop.ValidateValue(CreateValue("'a'").get(), &error));
455 EXPECT_EQ("out_of_range", error->GetCode());
456 error.reset();
457 EXPECT_TRUE(prop.ValidateValue(CreateValue("'ab'").get(), &error));
458 EXPECT_EQ(nullptr, error.get());
459 EXPECT_TRUE(prop.ValidateValue(CreateValue("'abc'").get(), &error));
460 EXPECT_EQ(nullptr, error.get());
461 EXPECT_FALSE(prop.ValidateValue(CreateValue("'abcd'").get(), &error));
462 EXPECT_EQ("out_of_range", error->GetCode());
463 error.reset();
464
465 prop.FromJson(CreateDictionaryValue("{'enum':['abc','def','xyz!!']}").get(),
466 nullptr, &error);
467 EXPECT_TRUE(prop.ValidateValue(CreateValue("'abc'").get(), &error));
468 EXPECT_TRUE(prop.ValidateValue(CreateValue("'def'").get(), &error));
469 EXPECT_TRUE(prop.ValidateValue(CreateValue("'xyz!!'").get(), &error));
470 EXPECT_FALSE(prop.ValidateValue(CreateValue("'xyz'").get(), &error));
471 EXPECT_EQ("out_of_range", error->GetCode());
472 error.reset();
473}
474
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700475TEST(CommandSchema, StringPropType_CreateValue) {
476 buffet::StringPropType prop;
477 chromeos::ErrorPtr error;
478 auto val = prop.CreateValue(std::string{"blah"}, &error);
479 ASSERT_NE(nullptr, val.get());
480 EXPECT_EQ(nullptr, error.get());
481 EXPECT_EQ("blah", val->GetValueAsAny().Get<std::string>());
482
483 val = prop.CreateValue(4, &error);
484 EXPECT_EQ(nullptr, val.get());
485 ASSERT_NE(nullptr, error.get());
486 EXPECT_EQ(buffet::errors::commands::kTypeMismatch, error->GetCode());
487}
488
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700489///////////////////////////////////////////////////////////////////////////////
490
491TEST(CommandSchema, ObjectPropType_Empty) {
492 buffet::ObjectPropType prop;
493 EXPECT_TRUE(prop.HasOverriddenAttributes());
494 EXPECT_FALSE(prop.IsBasedOnSchema());
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800495 EXPECT_EQ(nullptr, prop.GetDefaultValue());
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700496}
497
498TEST(CommandSchema, ObjectPropType_Types) {
499 buffet::ObjectPropType prop;
500 EXPECT_EQ(nullptr, prop.GetInt());
501 EXPECT_EQ(nullptr, prop.GetBoolean());
502 EXPECT_EQ(nullptr, prop.GetDouble());
503 EXPECT_EQ(nullptr, prop.GetString());
504 EXPECT_EQ(&prop, prop.GetObject());
505}
506
507TEST(CommandSchema, ObjectPropType_ToJson) {
508 buffet::ObjectPropType prop;
509 EXPECT_EQ("{'properties':{}}",
510 ValueToString(prop.ToJson(false, nullptr).get()));
511 EXPECT_EQ("{'properties':{},'type':'object'}",
512 ValueToString(prop.ToJson(true, nullptr).get()));
513 EXPECT_FALSE(prop.IsBasedOnSchema());
514 buffet::ObjectPropType prop2;
515 prop2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
516 EXPECT_EQ("{}", ValueToString(prop2.ToJson(false, nullptr).get()));
517 EXPECT_TRUE(prop2.IsBasedOnSchema());
518
519 auto schema = std::make_shared<buffet::ObjectSchema>();
520 schema->AddProp("expires", std::make_shared<buffet::IntPropType>());
521 auto pw = std::make_shared<buffet::StringPropType>();
522 pw->AddLengthConstraint(6, 100);
523 schema->AddProp("password", pw);
524 prop2.SetObjectSchema(schema);
525 EXPECT_EQ("{'properties':{'expires':'integer',"
526 "'password':{'maxLength':100,'minLength':6}}}",
527 ValueToString(prop2.ToJson(false, nullptr).get()));
528 EXPECT_EQ("{'properties':{'expires':{'type':'integer'},"
529 "'password':{'maxLength':100,'minLength':6,'type':'string'}},"
530 "'type':'object'}",
531 ValueToString(prop2.ToJson(true, nullptr).get()));
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800532
533 buffet::ObjectPropType prop3;
534 ASSERT_TRUE(prop3.FromJson(CreateDictionaryValue(
535 "{'default':{'expires':3,'password':'abracadabra'}}").get(), &prop2,
536 nullptr));
537 EXPECT_EQ("{'default':{'expires':3,'password':'abracadabra'}}",
538 ValueToString(prop3.ToJson(false, nullptr).get()));
539 EXPECT_EQ("{'default':{'expires':3,'password':'abracadabra'},"
540 "'properties':{'expires':{'type':'integer'},"
541 "'password':{'maxLength':100,'minLength':6,'type':'string'}},"
542 "'type':'object'}",
543 ValueToString(prop3.ToJson(true, nullptr).get()));
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700544}
545
546TEST(CommandSchema, ObjectPropType_FromJson) {
547 buffet::ObjectPropType base_prop;
548 EXPECT_TRUE(base_prop.FromJson(CreateDictionaryValue(
549 "{'properties':{'name':'string','age':'integer'}}").get(), nullptr,
550 nullptr));
551 auto schema = base_prop.GetObjectSchemaPtr();
552 const buffet::PropType* prop = schema->GetProp("name");
553 EXPECT_EQ(buffet::ValueType::String, prop->GetType());
554 prop = schema->GetProp("age");
555 EXPECT_EQ(buffet::ValueType::Int, prop->GetType());
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800556
557 buffet::ObjectPropType prop2;
558 ASSERT_TRUE(prop2.FromJson(CreateDictionaryValue(
559 "{'properties':{'name':'string','age':'integer'},"
560 "'default':{'name':'Bob','age':33}}").get(), nullptr, nullptr));
561 ASSERT_NE(nullptr, prop2.GetDefaultValue());
562 const buffet::ObjectValue* defval = prop2.GetDefaultValue()->GetObject();
563 ASSERT_NE(nullptr, defval);
564 buffet::native_types::Object objval = defval->GetValue();
565 EXPECT_EQ("Bob", objval["name"]->GetString()->GetValue());
566 EXPECT_EQ(33, objval["age"]->GetInt()->GetValue());
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700567}
568
569TEST(CommandSchema, ObjectPropType_Validate) {
570 buffet::ObjectPropType prop;
571 prop.FromJson(CreateDictionaryValue(
572 "{'properties':{'expires':'integer',"
573 "'password':{'maxLength':100,'minLength':6}}}").get(), nullptr,
574 nullptr);
Alex Vakulenko5f472062014-08-14 17:54:04 -0700575 chromeos::ErrorPtr error;
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700576 EXPECT_TRUE(prop.ValidateValue(CreateValue(
577 "{'expires':10,'password':'abcdef'}").get(), &error));
578 error.reset();
579
580 EXPECT_FALSE(prop.ValidateValue(CreateValue(
581 "{'expires':10}").get(), &error));
582 EXPECT_EQ("parameter_missing", error->GetCode());
583 error.reset();
584
585 EXPECT_FALSE(prop.ValidateValue(CreateValue(
586 "{'password':'abcdef'}").get(), &error));
587 EXPECT_EQ("parameter_missing", error->GetCode());
588 error.reset();
589
590 EXPECT_FALSE(prop.ValidateValue(CreateValue(
591 "{'expires':10,'password':'abcde'}").get(), &error));
592 EXPECT_EQ("out_of_range", error->GetFirstError()->GetCode());
593 error.reset();
594
595 EXPECT_FALSE(prop.ValidateValue(CreateValue("2").get(), &error));
596 EXPECT_EQ("type_mismatch", error->GetCode());
597 error.reset();
598
599 EXPECT_FALSE(prop.ValidateValue(CreateValue(
600 "{'expires':10,'password':'abcdef','retry':true}").get(), &error));
601 EXPECT_EQ("unexpected_parameter", error->GetCode());
602 error.reset();
603}
604
605TEST(CommandSchema, ObjectPropType_Validate_Enum) {
606 buffet::ObjectPropType prop;
607 EXPECT_TRUE(prop.FromJson(CreateDictionaryValue(
608 "{'properties':{'width':'integer','height':'integer'},"
609 "'enum':[{'width':10,'height':20},{'width':100,'height':200}]}").get(),
610 nullptr, nullptr));
Alex Vakulenko5f472062014-08-14 17:54:04 -0700611 chromeos::ErrorPtr error;
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700612 EXPECT_TRUE(prop.ValidateValue(CreateValue(
613 "{'height':20,'width':10}").get(), &error));
614 error.reset();
615
616 EXPECT_TRUE(prop.ValidateValue(CreateValue(
617 "{'height':200,'width':100}").get(), &error));
618 error.reset();
619
620 EXPECT_FALSE(prop.ValidateValue(CreateValue(
621 "{'height':12,'width':10}").get(), &error));
622 EXPECT_EQ("out_of_range", error->GetCode());
623 error.reset();
624}
625
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700626TEST(CommandSchema, ObjectPropType_CreateValue) {
627 buffet::ObjectPropType prop;
628 buffet::IntPropType int_type;
629 ASSERT_TRUE(prop.FromJson(CreateDictionaryValue(
630 "{'properties':{'width':'integer','height':'integer'},"
631 "'enum':[{'width':10,'height':20},{'width':100,'height':200}]}").get(),
632 nullptr, nullptr));
633 buffet::native_types::Object obj{
634 {"width", int_type.CreateValue(10, nullptr)},
635 {"height", int_type.CreateValue(20, nullptr)},
636 };
637
638 chromeos::ErrorPtr error;
639 auto val = prop.CreateValue(obj, &error);
640 ASSERT_NE(nullptr, val.get());
641 EXPECT_EQ(nullptr, error.get());
642 EXPECT_EQ(obj, val->GetValueAsAny().Get<buffet::native_types::Object>());
643
644 val = prop.CreateValue("blah", &error);
645 EXPECT_EQ(nullptr, val.get());
646 ASSERT_NE(nullptr, error.get());
647 EXPECT_EQ(buffet::errors::commands::kTypeMismatch, error->GetCode());
648}
649
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700650///////////////////////////////////////////////////////////////////////////////
651
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700652TEST(CommandSchema, ObjectSchema_FromJson_Shorthand_TypeName) {
653 buffet::ObjectSchema schema;
654 const char* schema_str = "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800655 "'param1':'integer',"
656 "'param2':'number',"
657 "'param3':'string'"
658 "}";
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700659 EXPECT_TRUE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
660 nullptr));
661 EXPECT_EQ(buffet::ValueType::Int, schema.GetProp("param1")->GetType());
662 EXPECT_EQ(buffet::ValueType::Double, schema.GetProp("param2")->GetType());
663 EXPECT_EQ(buffet::ValueType::String, schema.GetProp("param3")->GetType());
664 EXPECT_EQ("integer", schema.GetProp("param1")->GetTypeAsString());
665 EXPECT_EQ("number", schema.GetProp("param2")->GetTypeAsString());
666 EXPECT_EQ("string", schema.GetProp("param3")->GetTypeAsString());
667 EXPECT_EQ(nullptr, schema.GetProp("param4"));
668
669 int min_int = (std::numeric_limits<int>::min)();
670 int max_int = (std::numeric_limits<int>::max)();
671 double min_dbl = (std::numeric_limits<double>::lowest)();
672 double max_dbl = (std::numeric_limits<double>::max)();
673 EXPECT_EQ(min_int, schema.GetProp("param1")->GetInt()->GetMinValue());
674 EXPECT_EQ(max_int, schema.GetProp("param1")->GetInt()->GetMaxValue());
675 EXPECT_EQ(min_dbl, schema.GetProp("param2")->GetDouble()->GetMinValue());
676 EXPECT_EQ(max_dbl, schema.GetProp("param2")->GetDouble()->GetMaxValue());
677 EXPECT_EQ(0, schema.GetProp("param3")->GetString()->GetMinLength());
678 EXPECT_EQ(max_int, schema.GetProp("param3")->GetString()->GetMaxLength());
679}
680
681TEST(CommandSchema, ObjectSchema_FromJson_Full_TypeName) {
682 buffet::ObjectSchema schema;
683 const char* schema_str = "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800684 "'param1':{'type':'integer'},"
685 "'param2':{'type':'number'},"
686 "'param3':{'type':'string'}"
687 "}";
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700688 EXPECT_TRUE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
689 nullptr));
690 EXPECT_EQ(buffet::ValueType::Int, schema.GetProp("param1")->GetType());
691 EXPECT_EQ(buffet::ValueType::Double, schema.GetProp("param2")->GetType());
692 EXPECT_EQ(buffet::ValueType::String, schema.GetProp("param3")->GetType());
693 EXPECT_EQ("integer", schema.GetProp("param1")->GetTypeAsString());
694 EXPECT_EQ("number", schema.GetProp("param2")->GetTypeAsString());
695 EXPECT_EQ("string", schema.GetProp("param3")->GetTypeAsString());
696 EXPECT_EQ(nullptr, schema.GetProp("param4"));
697
698 int min_int = (std::numeric_limits<int>::min)();
699 int max_int = (std::numeric_limits<int>::max)();
700 double min_dbl = (std::numeric_limits<double>::lowest)();
701 double max_dbl = (std::numeric_limits<double>::max)();
702 EXPECT_EQ(min_int, schema.GetProp("param1")->GetInt()->GetMinValue());
703 EXPECT_EQ(max_int, schema.GetProp("param1")->GetInt()->GetMaxValue());
704 EXPECT_EQ(min_dbl, schema.GetProp("param2")->GetDouble()->GetMinValue());
705 EXPECT_EQ(max_dbl, schema.GetProp("param2")->GetDouble()->GetMaxValue());
706 EXPECT_EQ(0, schema.GetProp("param3")->GetString()->GetMinLength());
707 EXPECT_EQ(max_int, schema.GetProp("param3")->GetString()->GetMaxLength());
708}
709
710TEST(CommandSchema, ObjectSchema_FromJson_Shorthand_TypeDeduction_Scalar) {
711 buffet::ObjectSchema schema;
712 const char* schema_str = "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800713 "'param1' :{'minimum':2},"
714 "'param2' :{'maximum':10},"
715 "'param3' :{'maximum':8, 'minimum':2},"
716 "'param4' :{'minimum':2.1},"
717 "'param5' :{'maximum':10.1},"
718 "'param6' :{'maximum':8.1, 'minimum':3.1},"
719 "'param7' :{'maximum':8, 'minimum':3.1},"
720 "'param8' :{'maximum':8.1, 'minimum':3},"
721 "'param9' :{'minLength':2},"
722 "'param10':{'maxLength':10},"
723 "'param11':{'maxLength':8, 'minLength':3},"
724 "'param12':{'default':12},"
725 "'param13':{'default':13.5},"
726 "'param14':{'default':true},"
727 "'param15':{'default':false},"
728 "'param16':{'default':'foobar'}"
729 "}";
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700730 EXPECT_TRUE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
731 nullptr));
732 EXPECT_EQ("integer", schema.GetProp("param1")->GetTypeAsString());
733 EXPECT_EQ("integer", schema.GetProp("param2")->GetTypeAsString());
734 EXPECT_EQ("integer", schema.GetProp("param3")->GetTypeAsString());
735 EXPECT_EQ("number", schema.GetProp("param4")->GetTypeAsString());
736 EXPECT_EQ("number", schema.GetProp("param5")->GetTypeAsString());
737 EXPECT_EQ("number", schema.GetProp("param6")->GetTypeAsString());
738 EXPECT_EQ("number", schema.GetProp("param7")->GetTypeAsString());
739 EXPECT_EQ("number", schema.GetProp("param8")->GetTypeAsString());
740 EXPECT_EQ("string", schema.GetProp("param9")->GetTypeAsString());
741 EXPECT_EQ("string", schema.GetProp("param10")->GetTypeAsString());
742 EXPECT_EQ("string", schema.GetProp("param11")->GetTypeAsString());
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800743 EXPECT_EQ("integer", schema.GetProp("param12")->GetTypeAsString());
744 EXPECT_EQ("number", schema.GetProp("param13")->GetTypeAsString());
745 EXPECT_EQ("boolean", schema.GetProp("param14")->GetTypeAsString());
746 EXPECT_EQ("boolean", schema.GetProp("param15")->GetTypeAsString());
747 EXPECT_EQ("string", schema.GetProp("param16")->GetTypeAsString());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700748
749 int min_int = (std::numeric_limits<int>::min)();
750 int max_int = (std::numeric_limits<int>::max)();
751 double min_dbl = (std::numeric_limits<double>::lowest)();
752 double max_dbl = (std::numeric_limits<double>::max)();
753 EXPECT_EQ(2, schema.GetProp("param1")->GetInt()->GetMinValue());
754 EXPECT_EQ(max_int, schema.GetProp("param1")->GetInt()->GetMaxValue());
755 EXPECT_EQ(min_int, schema.GetProp("param2")->GetInt()->GetMinValue());
756 EXPECT_EQ(10, schema.GetProp("param2")->GetInt()->GetMaxValue());
757 EXPECT_EQ(2, schema.GetProp("param3")->GetInt()->GetMinValue());
758 EXPECT_EQ(8, schema.GetProp("param3")->GetInt()->GetMaxValue());
759 EXPECT_DOUBLE_EQ(2.1, schema.GetProp("param4")->GetDouble()->GetMinValue());
760 EXPECT_DOUBLE_EQ(max_dbl,
761 schema.GetProp("param4")->GetDouble()->GetMaxValue());
762 EXPECT_DOUBLE_EQ(min_dbl,
763 schema.GetProp("param5")->GetDouble()->GetMinValue());
764 EXPECT_DOUBLE_EQ(10.1, schema.GetProp("param5")->GetDouble()->GetMaxValue());
765 EXPECT_DOUBLE_EQ(3.1, schema.GetProp("param6")->GetDouble()->GetMinValue());
766 EXPECT_DOUBLE_EQ(8.1, schema.GetProp("param6")->GetDouble()->GetMaxValue());
767 EXPECT_DOUBLE_EQ(3.1, schema.GetProp("param7")->GetDouble()->GetMinValue());
768 EXPECT_DOUBLE_EQ(8.0, schema.GetProp("param7")->GetDouble()->GetMaxValue());
769 EXPECT_DOUBLE_EQ(3.0, schema.GetProp("param8")->GetDouble()->GetMinValue());
770 EXPECT_DOUBLE_EQ(8.1, schema.GetProp("param8")->GetDouble()->GetMaxValue());
771 EXPECT_EQ(2, schema.GetProp("param9")->GetString()->GetMinLength());
772 EXPECT_EQ(max_int, schema.GetProp("param9")->GetString()->GetMaxLength());
773 EXPECT_EQ(0, schema.GetProp("param10")->GetString()->GetMinLength());
774 EXPECT_EQ(10, schema.GetProp("param10")->GetString()->GetMaxLength());
775 EXPECT_EQ(3, schema.GetProp("param11")->GetString()->GetMinLength());
776 EXPECT_EQ(8, schema.GetProp("param11")->GetString()->GetMaxLength());
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800777 const buffet::PropValue* val = schema.GetProp("param12")->GetDefaultValue();
778 EXPECT_EQ(12, val->GetInt()->GetValue());
779 val = schema.GetProp("param13")->GetDefaultValue();
780 EXPECT_DOUBLE_EQ(13.5, val->GetDouble()->GetValue());
781 val = schema.GetProp("param14")->GetDefaultValue();
782 EXPECT_TRUE(val->GetBoolean()->GetValue());
783 val = schema.GetProp("param15")->GetDefaultValue();
784 EXPECT_FALSE(val->GetBoolean()->GetValue());
785 val = schema.GetProp("param16")->GetDefaultValue();
786 EXPECT_EQ("foobar", val->GetString()->GetValue());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700787}
788
789TEST(CommandSchema, ObjectSchema_FromJson_Shorthand_TypeDeduction_Array) {
790 buffet::ObjectSchema schema;
791 const char* schema_str = "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800792 "'param1' :[0,1,2,3],"
793 "'param2' :[0.0,1.1,2.2],"
794 "'param3' :['id1', 'id2'],"
795 "'param4' :{'enum':[1,2,3]},"
796 "'param5' :{'enum':[-1.1,2.2,3]},"
797 "'param6' :{'enum':['id0', 'id1']},"
798 "'param7' :{'type':'integer', 'enum':[1,2,3]},"
799 "'param8' :{'type':'number', 'enum':[1,2,3]},"
800 "'param9' :{'type':'number', 'enum':[]},"
801 "'param10':{'type':'integer', 'enum':[]}"
802 "}";
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700803 EXPECT_TRUE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
804 nullptr));
805 EXPECT_EQ("integer", schema.GetProp("param1")->GetTypeAsString());
806 EXPECT_EQ("number", schema.GetProp("param2")->GetTypeAsString());
807 EXPECT_EQ("string", schema.GetProp("param3")->GetTypeAsString());
808 EXPECT_EQ("integer", schema.GetProp("param4")->GetTypeAsString());
809 EXPECT_EQ("number", schema.GetProp("param5")->GetTypeAsString());
810 EXPECT_EQ("string", schema.GetProp("param6")->GetTypeAsString());
811 EXPECT_EQ("integer", schema.GetProp("param7")->GetTypeAsString());
812 EXPECT_EQ("number", schema.GetProp("param8")->GetTypeAsString());
813 EXPECT_EQ("number", schema.GetProp("param9")->GetTypeAsString());
814 EXPECT_EQ("integer", schema.GetProp("param10")->GetTypeAsString());
815
816 EXPECT_EQ(4, schema.GetProp("param1")->GetInt()->GetOneOfValues().size());
817 EXPECT_EQ(3, schema.GetProp("param2")->GetDouble()->GetOneOfValues().size());
818 EXPECT_EQ(2, schema.GetProp("param3")->GetString()->GetOneOfValues().size());
819 EXPECT_EQ(3, schema.GetProp("param4")->GetInt()->GetOneOfValues().size());
820 EXPECT_EQ(3, schema.GetProp("param5")->GetDouble()->GetOneOfValues().size());
821 EXPECT_EQ(2, schema.GetProp("param6")->GetString()->GetOneOfValues().size());
822 EXPECT_EQ(3, schema.GetProp("param7")->GetInt()->GetOneOfValues().size());
823 EXPECT_EQ(3, schema.GetProp("param8")->GetDouble()->GetOneOfValues().size());
824 EXPECT_EQ(0, schema.GetProp("param9")->GetDouble()->GetOneOfValues().size());
825 EXPECT_EQ(0, schema.GetProp("param10")->GetInt()->GetOneOfValues().size());
826
827 EXPECT_EQ(std::vector<int>({0, 1, 2, 3}),
828 schema.GetProp("param1")->GetInt()->GetOneOfValues());
829 EXPECT_EQ(std::vector<double>({0.0, 1.1, 2.2}),
830 schema.GetProp("param2")->GetDouble()->GetOneOfValues());
831 EXPECT_EQ(std::vector<std::string>({"id1", "id2"}),
832 schema.GetProp("param3")->GetString()->GetOneOfValues());
833
834 EXPECT_EQ(std::vector<int>({1, 2, 3}),
835 schema.GetProp("param4")->GetInt()->GetOneOfValues());
836 EXPECT_EQ(std::vector<double>({-1.1, 2.2, 3.0}),
837 schema.GetProp("param5")->GetDouble()->GetOneOfValues());
838 EXPECT_EQ(std::vector<std::string>({"id0", "id1"}),
839 schema.GetProp("param6")->GetString()->GetOneOfValues());
840 EXPECT_EQ(std::vector<int>({1, 2, 3}),
841 schema.GetProp("param7")->GetInt()->GetOneOfValues());
842 EXPECT_EQ(std::vector<double>({1.0, 2.0, 3.0}),
843 schema.GetProp("param8")->GetDouble()->GetOneOfValues());
844}
845
846TEST(CommandSchema, ObjectSchema_FromJson_Inheritance) {
847 const char* base_schema_str = "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800848 "'param0' :{'minimum':1, 'maximum':5},"
849 "'param1' :{'minimum':1, 'maximum':5},"
850 "'param2' :{'minimum':1, 'maximum':5},"
851 "'param3' :{'minimum':1, 'maximum':5},"
852 "'param4' :{'minimum':1, 'maximum':5},"
853 "'param5' :{'minimum':1.1, 'maximum':5.5},"
854 "'param6' :{'minimum':1.1, 'maximum':5.5},"
855 "'param7' :{'minimum':1.1, 'maximum':5.5},"
856 "'param8' :{'minimum':1.1, 'maximum':5.5},"
857 "'param9' :{'minLength':1, 'maxLength':5},"
858 "'param10':{'minLength':1, 'maxLength':5},"
859 "'param11':{'minLength':1, 'maxLength':5},"
860 "'param12':{'minLength':1, 'maxLength':5},"
861 "'param13':[1,2,3],"
862 "'param14':[1,2,3],"
863 "'param15':[1.1,2.2,3.3],"
864 "'param16':[1.1,2.2,3.3],"
865 "'param17':['id1', 'id2'],"
866 "'param18':['id1', 'id2'],"
867 "'param19':{'minimum':1, 'maximum':5},"
868 "'param20':{'default':49},"
869 "'param21':{'default':49},"
870 "'param22':'integer'"
871 "}";
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700872 buffet::ObjectSchema base_schema;
873 EXPECT_TRUE(base_schema.FromJson(CreateDictionaryValue(base_schema_str).get(),
874 nullptr, nullptr));
875 const char* schema_str = "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800876 "'param1' :{},"
877 "'param2' :{'minimum':2},"
878 "'param3' :{'maximum':9},"
879 "'param4' :{'minimum':2, 'maximum':9},"
880 "'param5' :{},"
881 "'param6' :{'minimum':2.2},"
882 "'param7' :{'maximum':9.9},"
883 "'param8' :{'minimum':2.2, 'maximum':9.9},"
884 "'param9' :{},"
885 "'param10':{'minLength':3},"
886 "'param11':{'maxLength':8},"
887 "'param12':{'minLength':3, 'maxLength':8},"
888 "'param13':{},"
889 "'param14':[1,2,3,4],"
890 "'param15':{},"
891 "'param16':[1.1,2.2,3.3,4.4],"
892 "'param17':{},"
893 "'param18':['id1', 'id3'],"
894 "'param19':{},"
895 "'param20':{},"
896 "'param21':{'default':8},"
897 "'param22':{'default':123}"
898 "}";
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700899 buffet::ObjectSchema schema;
900 EXPECT_TRUE(schema.FromJson(CreateDictionaryValue(schema_str).get(),
901 &base_schema, nullptr));
902 EXPECT_EQ(nullptr, schema.GetProp("param0"));
903 EXPECT_NE(nullptr, schema.GetProp("param1"));
904 EXPECT_EQ("integer", schema.GetProp("param1")->GetTypeAsString());
905 EXPECT_EQ(1, schema.GetProp("param1")->GetInt()->GetMinValue());
906 EXPECT_EQ(5, schema.GetProp("param1")->GetInt()->GetMaxValue());
907 EXPECT_EQ("integer", schema.GetProp("param2")->GetTypeAsString());
908 EXPECT_EQ(2, schema.GetProp("param2")->GetInt()->GetMinValue());
909 EXPECT_EQ(5, schema.GetProp("param2")->GetInt()->GetMaxValue());
910 EXPECT_EQ("integer", schema.GetProp("param3")->GetTypeAsString());
911 EXPECT_EQ(1, schema.GetProp("param3")->GetInt()->GetMinValue());
912 EXPECT_EQ(9, schema.GetProp("param3")->GetInt()->GetMaxValue());
913 EXPECT_EQ("integer", schema.GetProp("param4")->GetTypeAsString());
914 EXPECT_EQ(2, schema.GetProp("param4")->GetInt()->GetMinValue());
915 EXPECT_EQ(9, schema.GetProp("param4")->GetInt()->GetMaxValue());
916 EXPECT_EQ("number", schema.GetProp("param5")->GetTypeAsString());
917 EXPECT_EQ(1.1, schema.GetProp("param5")->GetDouble()->GetMinValue());
918 EXPECT_EQ(5.5, schema.GetProp("param5")->GetDouble()->GetMaxValue());
919 EXPECT_EQ("number", schema.GetProp("param6")->GetTypeAsString());
920 EXPECT_EQ(2.2, schema.GetProp("param6")->GetDouble()->GetMinValue());
921 EXPECT_EQ(5.5, schema.GetProp("param6")->GetDouble()->GetMaxValue());
922 EXPECT_EQ("number", schema.GetProp("param7")->GetTypeAsString());
923 EXPECT_EQ(1.1, schema.GetProp("param7")->GetDouble()->GetMinValue());
924 EXPECT_EQ(9.9, schema.GetProp("param7")->GetDouble()->GetMaxValue());
925 EXPECT_EQ("number", schema.GetProp("param8")->GetTypeAsString());
926 EXPECT_EQ(2.2, schema.GetProp("param8")->GetDouble()->GetMinValue());
927 EXPECT_EQ(9.9, schema.GetProp("param8")->GetDouble()->GetMaxValue());
928 EXPECT_EQ("string", schema.GetProp("param9")->GetTypeAsString());
929 EXPECT_EQ(1, schema.GetProp("param9")->GetString()->GetMinLength());
930 EXPECT_EQ(5, schema.GetProp("param9")->GetString()->GetMaxLength());
931 EXPECT_EQ("string", schema.GetProp("param10")->GetTypeAsString());
932 EXPECT_EQ(3, schema.GetProp("param10")->GetString()->GetMinLength());
933 EXPECT_EQ(5, schema.GetProp("param10")->GetString()->GetMaxLength());
934 EXPECT_EQ("string", schema.GetProp("param11")->GetTypeAsString());
935 EXPECT_EQ(1, schema.GetProp("param11")->GetString()->GetMinLength());
936 EXPECT_EQ(8, schema.GetProp("param11")->GetString()->GetMaxLength());
937 EXPECT_EQ("string", schema.GetProp("param12")->GetTypeAsString());
938 EXPECT_EQ(3, schema.GetProp("param12")->GetString()->GetMinLength());
939 EXPECT_EQ(8, schema.GetProp("param12")->GetString()->GetMaxLength());
940 EXPECT_EQ("integer", schema.GetProp("param13")->GetTypeAsString());
941 EXPECT_EQ(std::vector<int>({1, 2, 3}),
942 schema.GetProp("param13")->GetInt()->GetOneOfValues());
943 EXPECT_EQ("integer", schema.GetProp("param14")->GetTypeAsString());
944 EXPECT_EQ(std::vector<int>({1, 2, 3, 4}),
945 schema.GetProp("param14")->GetInt()->GetOneOfValues());
946 EXPECT_EQ("number", schema.GetProp("param15")->GetTypeAsString());
947 EXPECT_EQ(std::vector<double>({1.1, 2.2, 3.3}),
948 schema.GetProp("param15")->GetDouble()->GetOneOfValues());
949 EXPECT_EQ("number", schema.GetProp("param16")->GetTypeAsString());
950 EXPECT_EQ(std::vector<double>({1.1, 2.2, 3.3, 4.4}),
951 schema.GetProp("param16")->GetDouble()->GetOneOfValues());
952 EXPECT_EQ("string", schema.GetProp("param17")->GetTypeAsString());
953 EXPECT_EQ(std::vector<std::string>({"id1", "id2"}),
954 schema.GetProp("param17")->GetString()->GetOneOfValues());
955 EXPECT_EQ("string", schema.GetProp("param18")->GetTypeAsString());
956 EXPECT_EQ(std::vector<std::string>({"id1", "id3"}),
957 schema.GetProp("param18")->GetString()->GetOneOfValues());
958 EXPECT_EQ("integer", schema.GetProp("param19")->GetTypeAsString());
959 EXPECT_EQ(1, schema.GetProp("param19")->GetInt()->GetMinValue());
960 EXPECT_EQ(5, schema.GetProp("param19")->GetInt()->GetMaxValue());
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800961 EXPECT_EQ(49,
962 schema.GetProp("param20")->GetDefaultValue()->GetInt()->GetValue());
963 EXPECT_EQ(8,
964 schema.GetProp("param21")->GetDefaultValue()->GetInt()->GetValue());
965 EXPECT_EQ(123,
966 schema.GetProp("param22")->GetDefaultValue()->GetInt()->GetValue());
967}
968
969TEST(CommandSchema, ObjectSchema_UseDefaults) {
970 buffet::ObjectPropType prop;
971 const char* schema_str = "{'properties':{"
972 "'param1':{'default':true},"
973 "'param2':{'default':2},"
974 "'param3':{'default':3.3},"
975 "'param4':{'default':'four'},"
976 "'param5':{'default':{'x':5,'y':6},"
977 "'properties':{'x':'integer','y':'integer'}}"
978 "}}";
979 ASSERT_TRUE(prop.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
980 nullptr));
981
982 // Omit all.
983 auto value = prop.CreateValue();
984 ASSERT_TRUE(value->FromJson(CreateDictionaryValue("{}").get(), nullptr));
985 buffet::native_types::Object obj = value->GetObject()->GetValue();
986 EXPECT_TRUE(obj["param1"]->GetBoolean()->GetValue());
987 EXPECT_EQ(2, obj["param2"]->GetInt()->GetValue());
988 EXPECT_DOUBLE_EQ(3.3, obj["param3"]->GetDouble()->GetValue());
989 EXPECT_EQ("four", obj["param4"]->GetString()->GetValue());
990 buffet::native_types::Object param5 = obj["param5"]->GetObject()->GetValue();
991 EXPECT_EQ(5, param5["x"]->GetInt()->GetValue());
992 EXPECT_EQ(6, param5["y"]->GetInt()->GetValue());
993
994 // Specify some.
995 value = prop.CreateValue();
996 const char* val_json = "{"
997 "'param1':false,"
998 "'param3':33.3,"
999 "'param5':{'x':-5,'y':-6}"
1000 "}";
1001 ASSERT_TRUE(value->FromJson(CreateDictionaryValue(val_json).get(), nullptr));
1002 obj = value->GetObject()->GetValue();
1003 EXPECT_FALSE(obj["param1"]->GetBoolean()->GetValue());
1004 EXPECT_EQ(2, obj["param2"]->GetInt()->GetValue());
1005 EXPECT_DOUBLE_EQ(33.3, obj["param3"]->GetDouble()->GetValue());
1006 EXPECT_EQ("four", obj["param4"]->GetString()->GetValue());
1007 param5 = obj["param5"]->GetObject()->GetValue();
1008 EXPECT_EQ(-5, param5["x"]->GetInt()->GetValue());
1009 EXPECT_EQ(-6, param5["y"]->GetInt()->GetValue());
1010
1011 // Specify all.
1012 value = prop.CreateValue();
1013 val_json = "{"
1014 "'param1':false,"
1015 "'param2':22,"
1016 "'param3':333.3,"
1017 "'param4':'FOUR',"
1018 "'param5':{'x':-55,'y':66}"
1019 "}";
1020 ASSERT_TRUE(value->FromJson(CreateDictionaryValue(val_json).get(), nullptr));
1021 obj = value->GetObject()->GetValue();
1022 EXPECT_FALSE(obj["param1"]->GetBoolean()->GetValue());
1023 EXPECT_EQ(22, obj["param2"]->GetInt()->GetValue());
1024 EXPECT_DOUBLE_EQ(333.3, obj["param3"]->GetDouble()->GetValue());
1025 EXPECT_EQ("FOUR", obj["param4"]->GetString()->GetValue());
1026 param5 = obj["param5"]->GetObject()->GetValue();
1027 EXPECT_EQ(-55, param5["x"]->GetInt()->GetValue());
1028 EXPECT_EQ(66, param5["y"]->GetInt()->GetValue());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001029}
1030
1031TEST(CommandSchema, ObjectSchema_FromJson_BaseSchema_Failures) {
1032 buffet::ObjectSchema schema;
Alex Vakulenko5f472062014-08-14 17:54:04 -07001033 chromeos::ErrorPtr error;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001034 const char* schema_str = "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001035 "'param1':{}"
1036 "}";
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001037 EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
1038 &error));
1039 EXPECT_EQ("no_type_info", error->GetFirstError()->GetCode());
1040 error.reset();
1041
1042 schema_str = "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001043 "'param1':{'type':'foo'}"
1044 "}";
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001045 EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
1046 &error));
1047 EXPECT_EQ("unknown_type", error->GetFirstError()->GetCode());
1048 error.reset();
1049
1050 schema_str = "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001051 "'param1':[]"
1052 "}";
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001053 EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
1054 &error));
1055 EXPECT_EQ("no_type_info", error->GetFirstError()->GetCode());
1056 error.reset();
1057
1058 schema_str = "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001059 "'param1':{'minimum':'foo'}"
1060 "}";
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001061 EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
1062 &error));
1063 EXPECT_EQ("type_mismatch", error->GetFirstError()->GetCode());
1064 error.reset();
1065
1066 schema_str = "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001067 "'param1':[1,2.2]"
1068 "}";
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001069 EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
1070 &error));
1071 EXPECT_EQ("type_mismatch", error->GetFirstError()->GetCode());
1072 error.reset();
Alex Vakulenko5109b202014-06-20 14:49:41 -07001073
1074 schema_str = "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001075 "'param1':{'minimum':1, 'enum':[1,2,3]}" // can't have min/max & enum.
1076 "}";
Alex Vakulenko5109b202014-06-20 14:49:41 -07001077 EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
1078 &error));
1079 EXPECT_EQ("unexpected_parameter", error->GetFirstError()->GetCode());
1080 error.reset();
1081
1082 schema_str = "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001083 "'param1':{'maximum':1, 'blah':2}" // 'blah' is unexpected.
1084 "}";
Alex Vakulenko5109b202014-06-20 14:49:41 -07001085 EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
1086 &error));
1087 EXPECT_EQ("unexpected_parameter", error->GetFirstError()->GetCode());
1088 error.reset();
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001089
1090 schema_str = "{"
1091 "'param1':{'enum':[1,2,3],'default':5}" // 'default' must be 1, 2, or 3.
1092 "}";
1093 EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
1094 &error));
1095 EXPECT_EQ("out_of_range", error->GetFirstError()->GetCode());
1096 error.reset();
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001097}