blob: 6417952016f1da1962dbf96da9133132b102edb9 [file] [log] [blame]
Vitaly Buka4615e0d2015-10-14 15:35:12 -07001// Copyright 2015 The Weave Authors. All rights reserved.
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Stefan Sauer2d16dfa2015-09-25 17:08:35 +02005#include "src/commands/object_schema.h"
Alex Deymof6cbe322014-11-10 19:55:35 -08006
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
Stefan Sauer2d16dfa2015-09-25 17:08:35 +020017#include "src/commands/prop_constraints.h"
18#include "src/commands/prop_types.h"
19#include "src/commands/schema_constants.h"
20#include "src/commands/unittest_utils.h"
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070021
Vitaly Bukab6f015a2015-07-09 14:59:23 -070022namespace weave {
Vitaly Buka32005de2015-05-01 12:33:31 -070023
Vitaly Buka0f6b2ec2015-08-20 15:35:19 -070024using test::CreateValue;
25using test::CreateDictionaryValue;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070026
Alex Vakulenko9e25ecd2015-03-20 09:43:10 -070027namespace {
28
Vitaly Buka32005de2015-05-01 12:33:31 -070029template <typename T>
Vitaly Buka774cdf52015-07-21 13:55:00 -070030std::vector<T> GetArrayValues(const ValueVector& arr) {
Alex Vakulenko9e25ecd2015-03-20 09:43:10 -070031 std::vector<T> values;
Alex Vakulenko29e64442015-03-20 13:59:19 -070032 values.reserve(arr.size());
33 for (const auto& prop_value : arr) {
Vitaly Bukac58a8282015-07-29 01:25:20 -070034 const auto& value = static_cast<const TypedValueBase<T>&>(*prop_value);
35 values.push_back(value.GetValue());
Alex Vakulenko9e25ecd2015-03-20 09:43:10 -070036 }
37 return values;
38}
39
Vitaly Buka32005de2015-05-01 12:33:31 -070040template <typename T>
41std::vector<T> GetOneOfValues(const PropType* prop_type) {
42 auto one_of = static_cast<const ConstraintOneOf*>(
43 prop_type->GetConstraint(ConstraintType::OneOf));
Alex Vakulenko29e64442015-03-20 13:59:19 -070044 if (!one_of)
45 return {};
46
47 return GetArrayValues<T>(one_of->set_.value);
48}
49
Vitaly Buka79c05e92015-07-29 12:25:37 -070050bool ValidateValue(const PropType& type,
51 const base::Value& value,
Vitaly Buka0801a1f2015-08-14 10:03:46 -070052 ErrorPtr* error) {
Vitaly Buka79c05e92015-07-29 12:25:37 -070053 std::unique_ptr<PropValue> val = type.CreatePropValue(value, error);
54 return val != nullptr;
55}
56
Alex Vakulenko9e25ecd2015-03-20 09:43:10 -070057} // anonymous namespace
58
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070059TEST(CommandSchema, IntPropType_Empty) {
Vitaly Buka32005de2015-05-01 12:33:31 -070060 IntPropType prop;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070061 EXPECT_TRUE(prop.GetConstraints().empty());
62 EXPECT_FALSE(prop.HasOverriddenAttributes());
63 EXPECT_FALSE(prop.IsBasedOnSchema());
Alex Vakulenko2a17a532015-02-24 14:51:13 -080064 EXPECT_EQ(nullptr, prop.GetDefaultValue());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070065}
66
67TEST(CommandSchema, IntPropType_Types) {
Vitaly Buka32005de2015-05-01 12:33:31 -070068 IntPropType prop;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070069 EXPECT_EQ(nullptr, prop.GetBoolean());
70 EXPECT_EQ(&prop, prop.GetInt());
71 EXPECT_EQ(nullptr, prop.GetDouble());
72 EXPECT_EQ(nullptr, prop.GetString());
Alex Vakulenko66ec2922014-06-17 15:30:22 -070073 EXPECT_EQ(nullptr, prop.GetObject());
Alex Vakulenko29e64442015-03-20 13:59:19 -070074 EXPECT_EQ(nullptr, prop.GetArray());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070075}
76
77TEST(CommandSchema, IntPropType_ToJson) {
Vitaly Buka32005de2015-05-01 12:33:31 -070078 IntPropType prop;
Vitaly Buka6942e1f2015-07-28 15:33:55 -070079 EXPECT_JSON_EQ("'integer'", *prop.ToJson(false, false));
80 EXPECT_JSON_EQ("{'type':'integer'}", *prop.ToJson(true, false));
Vitaly Buka32005de2015-05-01 12:33:31 -070081 IntPropType param2;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070082 param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
Vitaly Buka6942e1f2015-07-28 15:33:55 -070083 EXPECT_JSON_EQ("{}", *param2.ToJson(false, false));
Vitaly Bukaa647c852015-07-06 14:51:01 -070084 param2.FromJson(CreateDictionaryValue("{'minimum':3}").get(), &prop, nullptr);
Vitaly Buka6942e1f2015-07-28 15:33:55 -070085 EXPECT_JSON_EQ("{'minimum':3}", *param2.ToJson(false, false));
Vitaly Bukaa647c852015-07-06 14:51:01 -070086 param2.FromJson(CreateDictionaryValue("{'maximum':-7}").get(), &prop,
87 nullptr);
Vitaly Buka6942e1f2015-07-28 15:33:55 -070088 EXPECT_JSON_EQ("{'maximum':-7}", *param2.ToJson(false, false));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070089 param2.FromJson(CreateDictionaryValue("{'minimum':0,'maximum':5}").get(),
90 &prop, nullptr);
Vitaly Buka6942e1f2015-07-28 15:33:55 -070091 EXPECT_JSON_EQ("{'maximum':5,'minimum':0}", *param2.ToJson(false, false));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070092 param2.FromJson(CreateDictionaryValue("{'enum':[1,2,3]}").get(), &prop,
93 nullptr);
Vitaly Buka6942e1f2015-07-28 15:33:55 -070094 EXPECT_JSON_EQ("[1,2,3]", *param2.ToJson(false, false));
Vitaly Bukaa647c852015-07-06 14:51:01 -070095 param2.FromJson(CreateDictionaryValue("{'default':123}").get(), &prop,
96 nullptr);
Vitaly Buka6942e1f2015-07-28 15:33:55 -070097 EXPECT_JSON_EQ("{'default':123}", *param2.ToJson(false, false));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070098}
99
100TEST(CommandSchema, IntPropType_FromJson) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700101 IntPropType prop;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700102 prop.AddMinMaxConstraint(2, 8);
Vitaly Buka32005de2015-05-01 12:33:31 -0700103 IntPropType param2;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700104 param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
105 EXPECT_FALSE(param2.HasOverriddenAttributes());
106 EXPECT_TRUE(param2.IsBasedOnSchema());
107 EXPECT_EQ(2, prop.GetMinValue());
108 EXPECT_EQ(8, prop.GetMaxValue());
109 prop.AddMinMaxConstraint(-2, 30);
Vitaly Bukaa647c852015-07-06 14:51:01 -0700110 param2.FromJson(CreateDictionaryValue("{'minimum':7}").get(), &prop, nullptr);
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700111 EXPECT_TRUE(param2.HasOverriddenAttributes());
112 EXPECT_TRUE(param2.IsBasedOnSchema());
113 EXPECT_EQ(7, param2.GetMinValue());
114 EXPECT_EQ(30, param2.GetMaxValue());
Vitaly Bukaa647c852015-07-06 14:51:01 -0700115 param2.FromJson(CreateDictionaryValue("{'maximum':17}").get(), &prop,
116 nullptr);
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700117 EXPECT_TRUE(param2.HasOverriddenAttributes());
118 EXPECT_TRUE(param2.IsBasedOnSchema());
119 EXPECT_EQ(-2, param2.GetMinValue());
120 EXPECT_EQ(17, param2.GetMaxValue());
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800121
122 ASSERT_TRUE(param2.FromJson(CreateDictionaryValue("{'default':3}").get(),
123 &prop, nullptr));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700124 EXPECT_TRUE(param2.HasOverriddenAttributes());
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800125 ASSERT_NE(nullptr, param2.GetDefaultValue());
126 EXPECT_EQ(3, param2.GetDefaultValue()->GetInt()->GetValue());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700127}
128
129TEST(CommandSchema, IntPropType_Validate) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700130 IntPropType prop;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700131 prop.AddMinMaxConstraint(2, 4);
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700132 ErrorPtr error;
Vitaly Buka79c05e92015-07-29 12:25:37 -0700133 EXPECT_FALSE(ValidateValue(prop, *CreateValue("-1"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700134 EXPECT_EQ("out_of_range", error->GetCode());
135 error.reset();
Vitaly Buka79c05e92015-07-29 12:25:37 -0700136 EXPECT_FALSE(ValidateValue(prop, *CreateValue("0"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700137 EXPECT_EQ("out_of_range", error->GetCode());
138 error.reset();
Vitaly Buka79c05e92015-07-29 12:25:37 -0700139 EXPECT_FALSE(ValidateValue(prop, *CreateValue("1"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700140 EXPECT_EQ("out_of_range", error->GetCode());
141 error.reset();
Vitaly Buka79c05e92015-07-29 12:25:37 -0700142 EXPECT_TRUE(ValidateValue(prop, *CreateValue("2"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700143 EXPECT_EQ(nullptr, error.get());
Vitaly Buka79c05e92015-07-29 12:25:37 -0700144 EXPECT_TRUE(ValidateValue(prop, *CreateValue("3"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700145 EXPECT_EQ(nullptr, error.get());
Vitaly Buka79c05e92015-07-29 12:25:37 -0700146 EXPECT_TRUE(ValidateValue(prop, *CreateValue("4"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700147 EXPECT_EQ(nullptr, error.get());
Vitaly Buka79c05e92015-07-29 12:25:37 -0700148 EXPECT_FALSE(ValidateValue(prop, *CreateValue("5"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700149 EXPECT_EQ("out_of_range", error->GetCode());
150 error.reset();
Vitaly Buka79c05e92015-07-29 12:25:37 -0700151 EXPECT_FALSE(ValidateValue(prop, *CreateValue("true"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700152 EXPECT_EQ("type_mismatch", error->GetCode());
153 error.reset();
Vitaly Buka79c05e92015-07-29 12:25:37 -0700154 EXPECT_FALSE(ValidateValue(prop, *CreateValue("3.0"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700155 EXPECT_EQ("type_mismatch", error->GetCode());
156 error.reset();
Vitaly Buka79c05e92015-07-29 12:25:37 -0700157 EXPECT_FALSE(ValidateValue(prop, *CreateValue("'3'"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700158 EXPECT_EQ("type_mismatch", error->GetCode());
159}
160
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700161TEST(CommandSchema, IntPropType_CreateValue) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700162 IntPropType prop;
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700163 ErrorPtr error;
Vitaly Bukac58a8282015-07-29 01:25:20 -0700164 auto val = prop.CreateValue(base::FundamentalValue{2}, &error);
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700165 ASSERT_NE(nullptr, val.get());
166 EXPECT_EQ(nullptr, error.get());
Vitaly Bukac58a8282015-07-29 01:25:20 -0700167 EXPECT_EQ(2, val->GetValue());
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700168
Vitaly Bukac58a8282015-07-29 01:25:20 -0700169 val = prop.CreateValue(base::StringValue{"blah"}, &error);
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700170 EXPECT_EQ(nullptr, val.get());
171 ASSERT_NE(nullptr, error.get());
Vitaly Buka32005de2015-05-01 12:33:31 -0700172 EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700173}
174
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700175///////////////////////////////////////////////////////////////////////////////
176
177TEST(CommandSchema, BoolPropType_Empty) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700178 BooleanPropType prop;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700179 EXPECT_TRUE(prop.GetConstraints().empty());
180 EXPECT_FALSE(prop.HasOverriddenAttributes());
181 EXPECT_FALSE(prop.IsBasedOnSchema());
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800182 EXPECT_EQ(nullptr, prop.GetDefaultValue());
Alex Vakulenko7e8df462015-07-07 10:59:20 -0700183 EXPECT_FALSE(prop.IsRequired());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700184}
185
186TEST(CommandSchema, BoolPropType_Types) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700187 BooleanPropType prop;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700188 EXPECT_EQ(nullptr, prop.GetInt());
189 EXPECT_EQ(&prop, prop.GetBoolean());
190 EXPECT_EQ(nullptr, prop.GetDouble());
191 EXPECT_EQ(nullptr, prop.GetString());
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700192 EXPECT_EQ(nullptr, prop.GetObject());
Alex Vakulenko29e64442015-03-20 13:59:19 -0700193 EXPECT_EQ(nullptr, prop.GetArray());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700194}
195
196TEST(CommandSchema, BoolPropType_ToJson) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700197 BooleanPropType prop;
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700198 EXPECT_JSON_EQ("'boolean'", *prop.ToJson(false, false));
199 EXPECT_JSON_EQ("{'type':'boolean'}", *prop.ToJson(true, false));
Vitaly Buka32005de2015-05-01 12:33:31 -0700200 BooleanPropType param2;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700201 param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700202 EXPECT_JSON_EQ("{}", *param2.ToJson(false, false));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700203 param2.FromJson(CreateDictionaryValue("{'enum':[true,false]}").get(), &prop,
204 nullptr);
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700205 EXPECT_JSON_EQ("[true,false]", *param2.ToJson(false, false));
Vitaly Buka7c82d292015-05-03 18:08:12 -0700206 EXPECT_JSON_EQ("{'enum':[true,false],'type':'boolean'}",
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700207 *param2.ToJson(true, false));
Vitaly Bukaa647c852015-07-06 14:51:01 -0700208 param2.FromJson(CreateDictionaryValue("{'default':true}").get(), &prop,
209 nullptr);
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700210 EXPECT_JSON_EQ("{'default':true}", *param2.ToJson(false, false));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700211}
212
213TEST(CommandSchema, BoolPropType_FromJson) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700214 BooleanPropType prop;
Vitaly Bukaa647c852015-07-06 14:51:01 -0700215 prop.FromJson(CreateDictionaryValue("{'enum':[true]}").get(), &prop, nullptr);
Vitaly Buka32005de2015-05-01 12:33:31 -0700216 BooleanPropType param2;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700217 param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
218 EXPECT_FALSE(param2.HasOverriddenAttributes());
219 EXPECT_TRUE(param2.IsBasedOnSchema());
Alex Vakulenko9e25ecd2015-03-20 09:43:10 -0700220 EXPECT_EQ(std::vector<bool>{true}, GetOneOfValues<bool>(&prop));
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800221
Vitaly Buka32005de2015-05-01 12:33:31 -0700222 BooleanPropType prop_base;
223 BooleanPropType param3;
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800224 ASSERT_TRUE(param3.FromJson(CreateDictionaryValue("{'default':false}").get(),
225 &prop_base, nullptr));
226 EXPECT_TRUE(param3.HasOverriddenAttributes());
227 ASSERT_NE(nullptr, param3.GetDefaultValue());
228 EXPECT_FALSE(param3.GetDefaultValue()->GetBoolean()->GetValue());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700229}
230
231TEST(CommandSchema, BoolPropType_Validate) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700232 BooleanPropType prop;
Vitaly Bukaa647c852015-07-06 14:51:01 -0700233 prop.FromJson(CreateDictionaryValue("{'enum':[true]}").get(), &prop, nullptr);
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700234 ErrorPtr error;
Vitaly Buka79c05e92015-07-29 12:25:37 -0700235 EXPECT_FALSE(ValidateValue(prop, *CreateValue("false"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700236 EXPECT_EQ("out_of_range", error->GetCode());
237 error.reset();
Vitaly Buka79c05e92015-07-29 12:25:37 -0700238 EXPECT_TRUE(ValidateValue(prop, *CreateValue("true"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700239 error.reset();
Vitaly Buka79c05e92015-07-29 12:25:37 -0700240 EXPECT_FALSE(ValidateValue(prop, *CreateValue("1"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700241 EXPECT_EQ("type_mismatch", error->GetCode());
242 error.reset();
Vitaly Buka79c05e92015-07-29 12:25:37 -0700243 EXPECT_FALSE(ValidateValue(prop, *CreateValue("3.0"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700244 EXPECT_EQ("type_mismatch", error->GetCode());
245 error.reset();
Vitaly Buka79c05e92015-07-29 12:25:37 -0700246 EXPECT_FALSE(ValidateValue(prop, *CreateValue("'3'"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700247 EXPECT_EQ("type_mismatch", error->GetCode());
248}
249
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700250TEST(CommandSchema, BoolPropType_CreateValue) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700251 BooleanPropType prop;
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700252 ErrorPtr error;
Vitaly Bukac58a8282015-07-29 01:25:20 -0700253 auto val = prop.CreateValue(base::FundamentalValue{true}, &error);
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700254 ASSERT_NE(nullptr, val.get());
255 EXPECT_EQ(nullptr, error.get());
Vitaly Bukac58a8282015-07-29 01:25:20 -0700256 EXPECT_TRUE(val->GetValue());
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700257
Vitaly Bukac58a8282015-07-29 01:25:20 -0700258 val = prop.CreateValue(base::StringValue{"blah"}, &error);
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700259 EXPECT_EQ(nullptr, val.get());
260 ASSERT_NE(nullptr, error.get());
Vitaly Buka32005de2015-05-01 12:33:31 -0700261 EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700262}
263
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700264///////////////////////////////////////////////////////////////////////////////
265
266TEST(CommandSchema, DoublePropType_Empty) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700267 DoublePropType prop;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700268 EXPECT_DOUBLE_EQ(std::numeric_limits<double>::lowest(), prop.GetMinValue());
269 EXPECT_DOUBLE_EQ((std::numeric_limits<double>::max)(), prop.GetMaxValue());
270 EXPECT_FALSE(prop.HasOverriddenAttributes());
271 EXPECT_FALSE(prop.IsBasedOnSchema());
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800272 EXPECT_EQ(nullptr, prop.GetDefaultValue());
Alex Vakulenko7e8df462015-07-07 10:59:20 -0700273 EXPECT_FALSE(prop.IsRequired());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700274}
275
276TEST(CommandSchema, DoublePropType_Types) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700277 DoublePropType prop;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700278 EXPECT_EQ(nullptr, prop.GetInt());
279 EXPECT_EQ(nullptr, prop.GetBoolean());
280 EXPECT_EQ(&prop, prop.GetDouble());
281 EXPECT_EQ(nullptr, prop.GetString());
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700282 EXPECT_EQ(nullptr, prop.GetObject());
Alex Vakulenko29e64442015-03-20 13:59:19 -0700283 EXPECT_EQ(nullptr, prop.GetArray());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700284}
285
286TEST(CommandSchema, DoublePropType_ToJson) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700287 DoublePropType prop;
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700288 EXPECT_JSON_EQ("'number'", *prop.ToJson(false, false));
289 EXPECT_JSON_EQ("{'type':'number'}", *prop.ToJson(true, false));
Vitaly Buka32005de2015-05-01 12:33:31 -0700290 DoublePropType param2;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700291 param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700292 EXPECT_JSON_EQ("{}", *param2.ToJson(false, false));
Vitaly Bukaa647c852015-07-06 14:51:01 -0700293 param2.FromJson(CreateDictionaryValue("{'minimum':3}").get(), &prop, nullptr);
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700294 EXPECT_JSON_EQ("{'minimum':3.0}", *param2.ToJson(false, false));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700295 param2.FromJson(CreateDictionaryValue("{'maximum':-7}").get(), &prop,
296 nullptr);
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700297 EXPECT_JSON_EQ("{'maximum':-7.0}", *param2.ToJson(false, false));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700298 param2.FromJson(CreateDictionaryValue("{'minimum':0,'maximum':5}").get(),
299 &prop, nullptr);
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700300 EXPECT_JSON_EQ("{'maximum':5.0,'minimum':0.0}", *param2.ToJson(false, false));
Vitaly Bukaa647c852015-07-06 14:51:01 -0700301 param2.FromJson(CreateDictionaryValue("{'default':12.3}").get(), &prop,
302 nullptr);
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700303 EXPECT_JSON_EQ("{'default':12.3}", *param2.ToJson(false, false));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700304}
305
306TEST(CommandSchema, DoublePropType_FromJson) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700307 DoublePropType prop;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700308 prop.AddMinMaxConstraint(2.5, 8.7);
Vitaly Buka32005de2015-05-01 12:33:31 -0700309 DoublePropType param2;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700310 param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
311 EXPECT_FALSE(param2.HasOverriddenAttributes());
312 EXPECT_TRUE(param2.IsBasedOnSchema());
313 EXPECT_DOUBLE_EQ(2.5, prop.GetMinValue());
314 EXPECT_DOUBLE_EQ(8.7, prop.GetMaxValue());
315 prop.AddMinMaxConstraint(-2.2, 30.4);
Vitaly Bukaa647c852015-07-06 14:51:01 -0700316 param2.FromJson(CreateDictionaryValue("{'minimum':7}").get(), &prop, nullptr);
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700317 EXPECT_TRUE(param2.HasOverriddenAttributes());
318 EXPECT_TRUE(param2.IsBasedOnSchema());
319 EXPECT_DOUBLE_EQ(7.0, param2.GetMinValue());
320 EXPECT_DOUBLE_EQ(30.4, param2.GetMaxValue());
321 param2.FromJson(CreateDictionaryValue("{'maximum':17.2}").get(), &prop,
322 nullptr);
323 EXPECT_TRUE(param2.HasOverriddenAttributes());
324 EXPECT_TRUE(param2.IsBasedOnSchema());
325 EXPECT_DOUBLE_EQ(-2.2, param2.GetMinValue());
326 EXPECT_DOUBLE_EQ(17.2, param2.GetMaxValue());
327 param2.FromJson(CreateDictionaryValue("{'minimum':0,'maximum':6.1}").get(),
328 &prop, nullptr);
329 EXPECT_TRUE(param2.HasOverriddenAttributes());
330 EXPECT_TRUE(param2.IsBasedOnSchema());
331 EXPECT_DOUBLE_EQ(0.0, param2.GetMinValue());
332 EXPECT_DOUBLE_EQ(6.1, param2.GetMaxValue());
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800333
334 ASSERT_TRUE(param2.FromJson(CreateDictionaryValue("{'default':-1.234}").get(),
335 &prop, nullptr));
336 EXPECT_TRUE(param2.HasOverriddenAttributes());
337 ASSERT_NE(nullptr, param2.GetDefaultValue());
338 EXPECT_DOUBLE_EQ(-1.234, param2.GetDefaultValue()->GetDouble()->GetValue());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700339}
340
341TEST(CommandSchema, DoublePropType_Validate) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700342 DoublePropType prop;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700343 prop.AddMinMaxConstraint(-1.2, 1.3);
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700344 ErrorPtr error;
Vitaly Buka79c05e92015-07-29 12:25:37 -0700345 EXPECT_FALSE(ValidateValue(prop, *CreateValue("-2"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700346 EXPECT_EQ("out_of_range", error->GetCode());
347 error.reset();
Vitaly Buka79c05e92015-07-29 12:25:37 -0700348 EXPECT_FALSE(ValidateValue(prop, *CreateValue("-1.3"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700349 EXPECT_EQ("out_of_range", error->GetCode());
350 error.reset();
Vitaly Buka79c05e92015-07-29 12:25:37 -0700351 EXPECT_TRUE(ValidateValue(prop, *CreateValue("-1.2"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700352 EXPECT_EQ(nullptr, error.get());
Vitaly Buka79c05e92015-07-29 12:25:37 -0700353 EXPECT_TRUE(ValidateValue(prop, *CreateValue("0.0"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700354 EXPECT_EQ(nullptr, error.get());
Vitaly Buka79c05e92015-07-29 12:25:37 -0700355 EXPECT_TRUE(ValidateValue(prop, *CreateValue("1.3"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700356 EXPECT_EQ(nullptr, error.get());
Vitaly Buka79c05e92015-07-29 12:25:37 -0700357 EXPECT_FALSE(ValidateValue(prop, *CreateValue("1.31"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700358 EXPECT_EQ("out_of_range", error->GetCode());
359 error.reset();
Vitaly Buka79c05e92015-07-29 12:25:37 -0700360 EXPECT_FALSE(ValidateValue(prop, *CreateValue("true"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700361 EXPECT_EQ("type_mismatch", error->GetCode());
362 error.reset();
Vitaly Buka79c05e92015-07-29 12:25:37 -0700363 EXPECT_FALSE(ValidateValue(prop, *CreateValue("'0.0'"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700364 EXPECT_EQ("type_mismatch", error->GetCode());
365}
366
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700367TEST(CommandSchema, DoublePropType_CreateValue) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700368 DoublePropType prop;
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700369 ErrorPtr error;
Vitaly Bukac58a8282015-07-29 01:25:20 -0700370 auto val = prop.CreateValue(base::FundamentalValue{2.0}, &error);
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700371 ASSERT_NE(nullptr, val.get());
372 EXPECT_EQ(nullptr, error.get());
Vitaly Bukac58a8282015-07-29 01:25:20 -0700373 EXPECT_DOUBLE_EQ(2.0, val->GetValue());
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700374
Vitaly Bukac58a8282015-07-29 01:25:20 -0700375 val = prop.CreateValue(base::StringValue{"blah"}, &error);
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700376 EXPECT_EQ(nullptr, val.get());
377 ASSERT_NE(nullptr, error.get());
Vitaly Buka32005de2015-05-01 12:33:31 -0700378 EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700379}
380
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700381///////////////////////////////////////////////////////////////////////////////
382
383TEST(CommandSchema, StringPropType_Empty) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700384 StringPropType prop;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700385 EXPECT_EQ(0, prop.GetMinLength());
386 EXPECT_EQ((std::numeric_limits<int>::max)(), prop.GetMaxLength());
387 EXPECT_FALSE(prop.HasOverriddenAttributes());
388 EXPECT_FALSE(prop.IsBasedOnSchema());
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800389 EXPECT_EQ(nullptr, prop.GetDefaultValue());
Alex Vakulenko7e8df462015-07-07 10:59:20 -0700390 EXPECT_FALSE(prop.IsRequired());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700391}
392
393TEST(CommandSchema, StringPropType_Types) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700394 StringPropType prop;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700395 EXPECT_EQ(nullptr, prop.GetInt());
396 EXPECT_EQ(nullptr, prop.GetBoolean());
397 EXPECT_EQ(nullptr, prop.GetDouble());
398 EXPECT_EQ(&prop, prop.GetString());
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700399 EXPECT_EQ(nullptr, prop.GetObject());
Alex Vakulenko29e64442015-03-20 13:59:19 -0700400 EXPECT_EQ(nullptr, prop.GetArray());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700401}
402
403TEST(CommandSchema, StringPropType_ToJson) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700404 StringPropType prop;
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700405 EXPECT_JSON_EQ("'string'", *prop.ToJson(false, false));
406 EXPECT_JSON_EQ("{'type':'string'}", *prop.ToJson(true, false));
Vitaly Buka32005de2015-05-01 12:33:31 -0700407 StringPropType param2;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700408 param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700409 EXPECT_JSON_EQ("{}", *param2.ToJson(false, false));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700410 param2.FromJson(CreateDictionaryValue("{'minLength':3}").get(), &prop,
411 nullptr);
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700412 EXPECT_JSON_EQ("{'minLength':3}", *param2.ToJson(false, false));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700413 param2.FromJson(CreateDictionaryValue("{'maxLength':7}").get(), &prop,
414 nullptr);
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700415 EXPECT_JSON_EQ("{'maxLength':7}", *param2.ToJson(false, false));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700416 param2.FromJson(CreateDictionaryValue("{'minLength':0,'maxLength':5}").get(),
417 &prop, nullptr);
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700418 EXPECT_JSON_EQ("{'maxLength':5,'minLength':0}", *param2.ToJson(false, false));
Vitaly Bukaa647c852015-07-06 14:51:01 -0700419 param2.FromJson(CreateDictionaryValue("{'default':'abcd'}").get(), &prop,
420 nullptr);
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700421 EXPECT_JSON_EQ("{'default':'abcd'}", *param2.ToJson(false, false));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700422}
423
424TEST(CommandSchema, StringPropType_FromJson) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700425 StringPropType prop;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700426 prop.AddLengthConstraint(2, 8);
Vitaly Buka32005de2015-05-01 12:33:31 -0700427 StringPropType param2;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700428 param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
429 EXPECT_FALSE(param2.HasOverriddenAttributes());
430 EXPECT_TRUE(param2.IsBasedOnSchema());
431 EXPECT_EQ(2, prop.GetMinLength());
432 EXPECT_EQ(8, prop.GetMaxLength());
433 prop.AddLengthConstraint(3, 5);
434 param2.FromJson(CreateDictionaryValue("{'minLength':4}").get(), &prop,
435 nullptr);
436 EXPECT_TRUE(param2.HasOverriddenAttributes());
437 EXPECT_TRUE(param2.IsBasedOnSchema());
438 EXPECT_EQ(4, param2.GetMinLength());
439 EXPECT_EQ(5, param2.GetMaxLength());
440 param2.FromJson(CreateDictionaryValue("{'maxLength':8}").get(), &prop,
441 nullptr);
442 EXPECT_TRUE(param2.HasOverriddenAttributes());
443 EXPECT_TRUE(param2.IsBasedOnSchema());
444 EXPECT_EQ(3, param2.GetMinLength());
445 EXPECT_EQ(8, param2.GetMaxLength());
Vitaly Bukaa647c852015-07-06 14:51:01 -0700446 param2.FromJson(CreateDictionaryValue("{'minLength':1,'maxLength':7}").get(),
447 &prop, nullptr);
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700448 EXPECT_TRUE(param2.HasOverriddenAttributes());
449 EXPECT_TRUE(param2.IsBasedOnSchema());
450 EXPECT_EQ(1, param2.GetMinLength());
451 EXPECT_EQ(7, param2.GetMaxLength());
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800452
453 ASSERT_TRUE(param2.FromJson(CreateDictionaryValue("{'default':'foo'}").get(),
454 &prop, nullptr));
455 EXPECT_TRUE(param2.HasOverriddenAttributes());
456 ASSERT_NE(nullptr, param2.GetDefaultValue());
457 EXPECT_EQ("foo", param2.GetDefaultValue()->GetString()->GetValue());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700458}
459
460TEST(CommandSchema, StringPropType_Validate) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700461 StringPropType prop;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700462 prop.AddLengthConstraint(1, 3);
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700463 ErrorPtr error;
Vitaly Buka79c05e92015-07-29 12:25:37 -0700464 EXPECT_FALSE(ValidateValue(prop, *CreateValue("''"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700465 EXPECT_EQ("out_of_range", error->GetCode());
466 error.reset();
467 prop.AddLengthConstraint(2, 3);
Vitaly Buka79c05e92015-07-29 12:25:37 -0700468 EXPECT_FALSE(ValidateValue(prop, *CreateValue("''"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700469 EXPECT_EQ("out_of_range", error->GetCode());
470 error.reset();
Vitaly Buka79c05e92015-07-29 12:25:37 -0700471 EXPECT_FALSE(ValidateValue(prop, *CreateValue("'a'"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700472 EXPECT_EQ("out_of_range", error->GetCode());
473 error.reset();
Vitaly Buka79c05e92015-07-29 12:25:37 -0700474 EXPECT_TRUE(ValidateValue(prop, *CreateValue("'ab'"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700475 EXPECT_EQ(nullptr, error.get());
Vitaly Buka79c05e92015-07-29 12:25:37 -0700476 EXPECT_TRUE(ValidateValue(prop, *CreateValue("'abc'"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700477 EXPECT_EQ(nullptr, error.get());
Vitaly Buka79c05e92015-07-29 12:25:37 -0700478 EXPECT_FALSE(ValidateValue(prop, *CreateValue("'abcd'"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700479 EXPECT_EQ("out_of_range", error->GetCode());
480 error.reset();
481
482 prop.FromJson(CreateDictionaryValue("{'enum':['abc','def','xyz!!']}").get(),
483 nullptr, &error);
Vitaly Buka79c05e92015-07-29 12:25:37 -0700484 EXPECT_TRUE(ValidateValue(prop, *CreateValue("'abc'"), &error));
485 EXPECT_TRUE(ValidateValue(prop, *CreateValue("'def'"), &error));
486 EXPECT_TRUE(ValidateValue(prop, *CreateValue("'xyz!!'"), &error));
487 EXPECT_FALSE(ValidateValue(prop, *CreateValue("'xyz'"), &error));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700488 EXPECT_EQ("out_of_range", error->GetCode());
489 error.reset();
490}
491
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700492TEST(CommandSchema, StringPropType_CreateValue) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700493 StringPropType prop;
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700494 ErrorPtr error;
Vitaly Bukac58a8282015-07-29 01:25:20 -0700495 auto val = prop.CreateValue(base::StringValue{"blah"}, &error);
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700496 ASSERT_NE(nullptr, val.get());
497 EXPECT_EQ(nullptr, error.get());
Vitaly Bukac58a8282015-07-29 01:25:20 -0700498 EXPECT_EQ("blah", val->GetValue());
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700499
Vitaly Bukac58a8282015-07-29 01:25:20 -0700500 val = prop.CreateValue(base::FundamentalValue{4}, &error);
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700501 EXPECT_EQ(nullptr, val.get());
502 ASSERT_NE(nullptr, error.get());
Vitaly Buka32005de2015-05-01 12:33:31 -0700503 EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700504}
505
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700506///////////////////////////////////////////////////////////////////////////////
507
508TEST(CommandSchema, ObjectPropType_Empty) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700509 ObjectPropType prop;
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700510 EXPECT_TRUE(prop.HasOverriddenAttributes());
511 EXPECT_FALSE(prop.IsBasedOnSchema());
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800512 EXPECT_EQ(nullptr, prop.GetDefaultValue());
Alex Vakulenko7e8df462015-07-07 10:59:20 -0700513 EXPECT_FALSE(prop.IsRequired());
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700514}
515
516TEST(CommandSchema, ObjectPropType_Types) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700517 ObjectPropType prop;
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700518 EXPECT_EQ(nullptr, prop.GetInt());
519 EXPECT_EQ(nullptr, prop.GetBoolean());
520 EXPECT_EQ(nullptr, prop.GetDouble());
521 EXPECT_EQ(nullptr, prop.GetString());
522 EXPECT_EQ(&prop, prop.GetObject());
Alex Vakulenko29e64442015-03-20 13:59:19 -0700523 EXPECT_EQ(nullptr, prop.GetArray());
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700524}
525
526TEST(CommandSchema, ObjectPropType_ToJson) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700527 ObjectPropType prop;
Vitaly Buka7c82d292015-05-03 18:08:12 -0700528 EXPECT_JSON_EQ("{'additionalProperties':false,'properties':{}}",
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700529 *prop.ToJson(false, false));
Vitaly Buka7c82d292015-05-03 18:08:12 -0700530 EXPECT_JSON_EQ(
531 "{'additionalProperties':false,'properties':{},'type':'object'}",
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700532 *prop.ToJson(true, false));
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700533 EXPECT_FALSE(prop.IsBasedOnSchema());
Vitaly Buka32005de2015-05-01 12:33:31 -0700534 ObjectPropType prop2;
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700535 prop2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700536 EXPECT_JSON_EQ("{}", *prop2.ToJson(false, false));
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700537 EXPECT_TRUE(prop2.IsBasedOnSchema());
538
Vitaly Buka32005de2015-05-01 12:33:31 -0700539 auto schema = ObjectSchema::Create();
540 schema->AddProp("expires", PropType::Create(ValueType::Int));
541 auto pw = PropType::Create(ValueType::String);
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700542 pw->GetString()->AddLengthConstraint(6, 100);
543 schema->AddProp("password", std::move(pw));
544 prop2.SetObjectSchema(std::move(schema));
Vitaly Buka7c82d292015-05-03 18:08:12 -0700545 auto expected = R"({
546 'additionalProperties': false,
547 'properties': {
548 'expires': 'integer',
549 'password': {
550 'maxLength': 100,
551 'minLength': 6
552 }
553 }
554 })";
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700555 EXPECT_JSON_EQ(expected, *prop2.ToJson(false, false));
Vitaly Buka7c82d292015-05-03 18:08:12 -0700556
557 expected = R"({
558 'additionalProperties': false,
559 'properties': {
560 'expires': {
561 'type': 'integer'
562 },
563 'password': {
564 'maxLength': 100,
565 'minLength': 6,
566 'type': 'string'
567 }
568 },
569 'type': 'object'
570 })";
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700571 EXPECT_JSON_EQ(expected, *prop2.ToJson(true, false));
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800572
Vitaly Buka32005de2015-05-01 12:33:31 -0700573 ObjectPropType prop3;
Vitaly Bukaa647c852015-07-06 14:51:01 -0700574 ASSERT_TRUE(
575 prop3.FromJson(CreateDictionaryValue(
576 "{'default':{'expires':3,'password':'abracadabra'}}")
577 .get(),
578 &prop2, nullptr));
Vitaly Buka7c82d292015-05-03 18:08:12 -0700579 expected = R"({
580 'default': {
581 'expires': 3,
582 'password': 'abracadabra'
583 }
584 })";
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700585 EXPECT_JSON_EQ(expected, *prop3.ToJson(false, false));
Vitaly Buka7c82d292015-05-03 18:08:12 -0700586
587 expected = R"({
588 'additionalProperties': false,
589 'default': {
590 'expires': 3,
591 'password': 'abracadabra'
592 },
593 'properties': {
594 'expires': {
595 'type': 'integer'
596 },
597 'password': {
598 'maxLength': 100,
599 'minLength': 6,
600 'type': 'string'
601 }
602 },
603 'type': 'object'
604 })";
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700605 EXPECT_JSON_EQ(expected, *prop3.ToJson(true, false));
Alex Vakulenko45d255b2015-03-31 10:44:49 -0700606
Vitaly Buka32005de2015-05-01 12:33:31 -0700607 ObjectPropType prop4;
Vitaly Buka4ebd3292015-09-23 18:04:17 -0700608 ASSERT_TRUE(prop4.FromJson(
609 CreateDictionaryValue("{'additionalProperties':true,"
610 "'default':{'expires':3,'password':'abracadabra'}}")
611 .get(),
612 &prop2, nullptr));
Vitaly Buka7c82d292015-05-03 18:08:12 -0700613 expected = R"({
614 'additionalProperties': true,
615 'default': {
616 'expires': 3,
617 'password': 'abracadabra'
618 },
619 'properties': {
620 'expires': 'integer',
621 'password': {
622 'maxLength': 100,
623 'minLength': 6
624 }
625 }
626 })";
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700627 EXPECT_JSON_EQ(expected, *prop4.ToJson(false, false));
Vitaly Buka7c82d292015-05-03 18:08:12 -0700628
629 expected = R"({
630 'additionalProperties': true,
631 'default': {
632 'expires': 3,
633 'password': 'abracadabra'
634 },
635 'properties': {
636 'expires': {
637 'type': 'integer'
638 },
639 'password': {
640 'maxLength': 100,
641 'minLength': 6,
642 'type': 'string'
643 }
644 },
645 'type': 'object'
646 })";
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700647 EXPECT_JSON_EQ(expected, *prop4.ToJson(true, false));
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700648}
649
650TEST(CommandSchema, ObjectPropType_FromJson) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700651 ObjectPropType base_prop;
Vitaly Bukaa647c852015-07-06 14:51:01 -0700652 EXPECT_TRUE(base_prop.FromJson(
653 CreateDictionaryValue("{'properties':{'name':'string','age':'integer'}}")
654 .get(),
655 nullptr, nullptr));
Alex Vakulenkod94656e2015-03-18 09:54:37 -0700656 auto schema = base_prop.GetObject()->GetObjectSchemaPtr();
Vitaly Buka32005de2015-05-01 12:33:31 -0700657 const PropType* prop = schema->GetProp("name");
658 EXPECT_EQ(ValueType::String, prop->GetType());
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700659 prop = schema->GetProp("age");
Vitaly Buka32005de2015-05-01 12:33:31 -0700660 EXPECT_EQ(ValueType::Int, prop->GetType());
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800661
Vitaly Buka32005de2015-05-01 12:33:31 -0700662 ObjectPropType prop2;
Vitaly Buka4ebd3292015-09-23 18:04:17 -0700663 ASSERT_TRUE(prop2.FromJson(
664 CreateDictionaryValue("{'properties':{'name':'string','age':'integer'},"
665 "'default':{'name':'Bob','age':33}}")
666 .get(),
667 nullptr, nullptr));
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800668 ASSERT_NE(nullptr, prop2.GetDefaultValue());
Vitaly Buka32005de2015-05-01 12:33:31 -0700669 const ObjectValue* defval = prop2.GetDefaultValue()->GetObject();
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800670 ASSERT_NE(nullptr, defval);
Vitaly Buka774cdf52015-07-21 13:55:00 -0700671 ValueMap objval = defval->GetValue();
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800672 EXPECT_EQ("Bob", objval["name"]->GetString()->GetValue());
673 EXPECT_EQ(33, objval["age"]->GetInt()->GetValue());
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700674}
675
676TEST(CommandSchema, ObjectPropType_Validate) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700677 ObjectPropType prop;
Vitaly Buka4ebd3292015-09-23 18:04:17 -0700678 prop.FromJson(
679 CreateDictionaryValue("{'properties':{'expires':'integer',"
680 "'password':{'maxLength':100,'minLength':6}},"
681 "'required':['expires','password']}")
682 .get(),
683 nullptr, nullptr);
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700684 ErrorPtr error;
Vitaly Buka79c05e92015-07-29 12:25:37 -0700685 EXPECT_TRUE(ValidateValue(
686 prop, *CreateValue("{'expires':10,'password':'abcdef'}"), &error));
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700687 error.reset();
688
Vitaly Buka79c05e92015-07-29 12:25:37 -0700689 EXPECT_FALSE(ValidateValue(prop, *CreateValue("{'expires':10}"), &error));
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700690 EXPECT_EQ("parameter_missing", error->GetCode());
691 error.reset();
692
Vitaly Bukaa647c852015-07-06 14:51:01 -0700693 EXPECT_FALSE(
Vitaly Buka79c05e92015-07-29 12:25:37 -0700694 ValidateValue(prop, *CreateValue("{'password':'abcdef'}"), &error));
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700695 EXPECT_EQ("parameter_missing", error->GetCode());
696 error.reset();
697
Vitaly Buka79c05e92015-07-29 12:25:37 -0700698 EXPECT_FALSE(ValidateValue(
699 prop, *CreateValue("{'expires':10,'password':'abcde'}"), &error));
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700700 EXPECT_EQ("out_of_range", error->GetFirstError()->GetCode());
701 error.reset();
702
Vitaly Buka79c05e92015-07-29 12:25:37 -0700703 EXPECT_FALSE(ValidateValue(prop, *CreateValue("2"), &error));
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700704 EXPECT_EQ("type_mismatch", error->GetCode());
705 error.reset();
706
Vitaly Buka79c05e92015-07-29 12:25:37 -0700707 EXPECT_FALSE(ValidateValue(
708 prop, *CreateValue("{'expires':10,'password':'abcdef','retry':true}"),
Vitaly Bukaa647c852015-07-06 14:51:01 -0700709 &error));
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700710 EXPECT_EQ("unexpected_parameter", error->GetCode());
711 error.reset();
712}
713
714TEST(CommandSchema, ObjectPropType_Validate_Enum) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700715 ObjectPropType prop;
Vitaly Bukaa647c852015-07-06 14:51:01 -0700716 EXPECT_TRUE(prop.FromJson(
717 CreateDictionaryValue(
718 "{'properties':{'width':'integer','height':'integer'},"
719 "'enum':[{'width':10,'height':20},{'width':100,'height':200}]}")
720 .get(),
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700721 nullptr, nullptr));
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700722 ErrorPtr error;
Vitaly Buka79c05e92015-07-29 12:25:37 -0700723 EXPECT_TRUE(
724 ValidateValue(prop, *CreateValue("{'height':20,'width':10}"), &error));
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700725 error.reset();
726
Vitaly Buka79c05e92015-07-29 12:25:37 -0700727 EXPECT_TRUE(
728 ValidateValue(prop, *CreateValue("{'height':200,'width':100}"), &error));
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700729 error.reset();
730
Vitaly Buka79c05e92015-07-29 12:25:37 -0700731 EXPECT_FALSE(
732 ValidateValue(prop, *CreateValue("{'height':12,'width':10}"), &error));
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700733 EXPECT_EQ("out_of_range", error->GetCode());
734 error.reset();
735}
736
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700737TEST(CommandSchema, ObjectPropType_CreateValue) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700738 ObjectPropType prop;
739 IntPropType int_type;
Vitaly Bukaa647c852015-07-06 14:51:01 -0700740 ASSERT_TRUE(prop.FromJson(
741 CreateDictionaryValue(
742 "{'properties':{'width':'integer','height':'integer'},"
743 "'enum':[{'width':10,'height':20},{'width':100,'height':200}]}")
744 .get(),
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700745 nullptr, nullptr));
Vitaly Buka774cdf52015-07-21 13:55:00 -0700746 ValueMap obj{
Vitaly Bukac58a8282015-07-29 01:25:20 -0700747 {"width", int_type.CreateValue(base::FundamentalValue{10}, nullptr)},
748 {"height", int_type.CreateValue(base::FundamentalValue{20}, nullptr)},
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700749 };
750
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700751 ErrorPtr error;
Vitaly Bukac58a8282015-07-29 01:25:20 -0700752 auto val = prop.CreateValue(
753 *CreateDictionaryValue("{'width': 10, 'height': 20}"), &error);
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700754 ASSERT_NE(nullptr, val.get());
755 EXPECT_EQ(nullptr, error.get());
Vitaly Bukac58a8282015-07-29 01:25:20 -0700756 EXPECT_EQ(obj, val->GetValue());
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700757
Vitaly Bukac58a8282015-07-29 01:25:20 -0700758 val = prop.CreateValue(base::StringValue{"blah"}, &error);
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700759 EXPECT_EQ(nullptr, val.get());
760 ASSERT_NE(nullptr, error.get());
Vitaly Buka32005de2015-05-01 12:33:31 -0700761 EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
Alex Vakulenko157ccaa2014-09-19 14:59:34 -0700762}
763
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700764///////////////////////////////////////////////////////////////////////////////
765
Alex Vakulenko29e64442015-03-20 13:59:19 -0700766TEST(CommandSchema, ArrayPropType_Empty) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700767 ArrayPropType prop;
Alex Vakulenko29e64442015-03-20 13:59:19 -0700768 EXPECT_FALSE(prop.HasOverriddenAttributes());
769 EXPECT_FALSE(prop.IsBasedOnSchema());
770 EXPECT_EQ(nullptr, prop.GetDefaultValue());
771 EXPECT_EQ(nullptr, prop.GetItemTypePtr());
Vitaly Buka32005de2015-05-01 12:33:31 -0700772 prop.SetItemType(PropType::Create(ValueType::Int));
Alex Vakulenko29e64442015-03-20 13:59:19 -0700773 EXPECT_TRUE(prop.HasOverriddenAttributes());
774 EXPECT_FALSE(prop.IsBasedOnSchema());
775 EXPECT_NE(nullptr, prop.GetItemTypePtr());
Alex Vakulenko7e8df462015-07-07 10:59:20 -0700776 EXPECT_FALSE(prop.IsRequired());
Alex Vakulenko29e64442015-03-20 13:59:19 -0700777}
778
779TEST(CommandSchema, ArrayPropType_Types) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700780 ArrayPropType prop;
Alex Vakulenko29e64442015-03-20 13:59:19 -0700781 EXPECT_EQ(nullptr, prop.GetInt());
782 EXPECT_EQ(nullptr, prop.GetBoolean());
783 EXPECT_EQ(nullptr, prop.GetDouble());
784 EXPECT_EQ(nullptr, prop.GetString());
785 EXPECT_EQ(nullptr, prop.GetObject());
786 EXPECT_EQ(&prop, prop.GetArray());
787}
788
789TEST(CommandSchema, ArrayPropType_ToJson) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700790 ArrayPropType prop;
791 prop.SetItemType(PropType::Create(ValueType::Int));
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700792 EXPECT_JSON_EQ("{'items':'integer'}", *prop.ToJson(false, false));
Vitaly Buka7c82d292015-05-03 18:08:12 -0700793 EXPECT_JSON_EQ("{'items':{'type':'integer'},'type':'array'}",
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700794 *prop.ToJson(true, false));
Alex Vakulenko29e64442015-03-20 13:59:19 -0700795 EXPECT_FALSE(prop.IsBasedOnSchema());
Vitaly Buka32005de2015-05-01 12:33:31 -0700796 ArrayPropType prop2;
Alex Vakulenko29e64442015-03-20 13:59:19 -0700797 prop2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700798 EXPECT_JSON_EQ("{}", *prop2.ToJson(false, false));
Alex Vakulenko29e64442015-03-20 13:59:19 -0700799 EXPECT_TRUE(prop2.IsBasedOnSchema());
Vitaly Bukaa647c852015-07-06 14:51:01 -0700800 prop2.FromJson(CreateDictionaryValue("{'default':[1,2,3]}").get(), &prop,
801 nullptr);
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700802 EXPECT_JSON_EQ("{'default':[1,2,3]}", *prop2.ToJson(false, false));
Vitaly Buka7c82d292015-05-03 18:08:12 -0700803 EXPECT_JSON_EQ(
804 "{'default':[1,2,3],'items':{'type':'integer'},'type':'array'}",
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700805 *prop2.ToJson(true, false));
Alex Vakulenko29e64442015-03-20 13:59:19 -0700806}
807
808TEST(CommandSchema, ArrayPropType_FromJson) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700809 ArrayPropType prop;
Vitaly Bukaa647c852015-07-06 14:51:01 -0700810 EXPECT_TRUE(prop.FromJson(CreateDictionaryValue("{'items':'integer'}").get(),
811 nullptr, nullptr));
Vitaly Buka32005de2015-05-01 12:33:31 -0700812 EXPECT_EQ(ValueType::Int, prop.GetItemTypePtr()->GetType());
Alex Vakulenko29e64442015-03-20 13:59:19 -0700813
Vitaly Buka32005de2015-05-01 12:33:31 -0700814 ArrayPropType prop2;
Vitaly Bukaa647c852015-07-06 14:51:01 -0700815 ASSERT_TRUE(
816 prop2.FromJson(CreateDictionaryValue(
817 "{'items':'string','default':['foo', 'bar', 'baz']}")
818 .get(),
819 nullptr, nullptr));
Alex Vakulenko29e64442015-03-20 13:59:19 -0700820 ASSERT_NE(nullptr, prop2.GetDefaultValue());
Vitaly Buka32005de2015-05-01 12:33:31 -0700821 const ArrayValue* defval = prop2.GetDefaultValue()->GetArray();
Alex Vakulenko29e64442015-03-20 13:59:19 -0700822 ASSERT_NE(nullptr, defval);
823 EXPECT_EQ((std::vector<std::string>{"foo", "bar", "baz"}),
824 GetArrayValues<std::string>(defval->GetValue()));
825}
826
827TEST(CommandSchema, ArrayPropType_Validate) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700828 ArrayPropType prop;
Vitaly Bukaa647c852015-07-06 14:51:01 -0700829 prop.FromJson(
830 CreateDictionaryValue("{'items':{'minimum':2.3, 'maximum':10.5}}").get(),
831 nullptr, nullptr);
Alex Vakulenko29e64442015-03-20 13:59:19 -0700832
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700833 ErrorPtr error;
Vitaly Buka79c05e92015-07-29 12:25:37 -0700834 EXPECT_TRUE(ValidateValue(prop, *CreateValue("[3,4,10.5]"), &error));
Alex Vakulenko29e64442015-03-20 13:59:19 -0700835 error.reset();
836
Vitaly Buka79c05e92015-07-29 12:25:37 -0700837 EXPECT_FALSE(ValidateValue(prop, *CreateValue("[2]"), &error));
Alex Vakulenko29e64442015-03-20 13:59:19 -0700838 EXPECT_EQ("out_of_range", error->GetCode());
Alex Vakulenko29e64442015-03-20 13:59:19 -0700839 error.reset();
840
Vitaly Buka79c05e92015-07-29 12:25:37 -0700841 EXPECT_FALSE(ValidateValue(prop, *CreateValue("[4, 5, 20]"), &error));
Alex Vakulenko29e64442015-03-20 13:59:19 -0700842 EXPECT_EQ("out_of_range", error->GetCode());
Alex Vakulenko29e64442015-03-20 13:59:19 -0700843 error.reset();
844}
845
846TEST(CommandSchema, ArrayPropType_Validate_Enum) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700847 ArrayPropType prop;
Vitaly Bukaa647c852015-07-06 14:51:01 -0700848 prop.FromJson(
849 CreateDictionaryValue("{'items':'integer', 'enum':[[1], [2,3], [4,5,6]]}")
850 .get(),
851 nullptr, nullptr);
Alex Vakulenko29e64442015-03-20 13:59:19 -0700852
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700853 ErrorPtr error;
Vitaly Buka79c05e92015-07-29 12:25:37 -0700854 EXPECT_TRUE(ValidateValue(prop, *CreateValue("[2,3]"), &error));
Alex Vakulenko29e64442015-03-20 13:59:19 -0700855 error.reset();
856
Vitaly Buka79c05e92015-07-29 12:25:37 -0700857 EXPECT_FALSE(ValidateValue(prop, *CreateValue("[2]"), &error));
Alex Vakulenko29e64442015-03-20 13:59:19 -0700858 EXPECT_EQ("out_of_range", error->GetCode());
Alex Vakulenko29e64442015-03-20 13:59:19 -0700859 error.reset();
860
Vitaly Buka79c05e92015-07-29 12:25:37 -0700861 EXPECT_FALSE(ValidateValue(prop, *CreateValue("[2,3,4]"), &error));
Alex Vakulenko29e64442015-03-20 13:59:19 -0700862 EXPECT_EQ("out_of_range", error->GetCode());
863 error.reset();
864}
865
866TEST(CommandSchema, ArrayPropType_CreateValue) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700867 ArrayPropType prop;
Vitaly Bukaa647c852015-07-06 14:51:01 -0700868 ASSERT_TRUE(prop.FromJson(
869 CreateDictionaryValue(
870 "{'items':{'properties':{'width':'integer','height':'integer'}}}")
871 .get(),
Alex Vakulenko29e64442015-03-20 13:59:19 -0700872 nullptr, nullptr));
873
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700874 ErrorPtr error;
Vitaly Buka774cdf52015-07-21 13:55:00 -0700875 ValueVector arr;
Alex Vakulenko29e64442015-03-20 13:59:19 -0700876
Vitaly Bukac58a8282015-07-29 01:25:20 -0700877 auto val = prop.CreateValue(base::ListValue{}, &error);
Alex Vakulenko29e64442015-03-20 13:59:19 -0700878 ASSERT_NE(nullptr, val.get());
879 EXPECT_EQ(nullptr, error.get());
Vitaly Bukac58a8282015-07-29 01:25:20 -0700880 EXPECT_EQ(arr, val->GetValue());
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700881 EXPECT_JSON_EQ("[]", *val->ToJson());
Alex Vakulenko29e64442015-03-20 13:59:19 -0700882
Vitaly Bukac58a8282015-07-29 01:25:20 -0700883 val = prop.CreateValue(
884 *CreateValue("[{'height':20,'width':10},{'width':17, 'height':18}]"),
885 &error);
Alex Vakulenko29e64442015-03-20 13:59:19 -0700886 ASSERT_NE(nullptr, val.get());
887 EXPECT_EQ(nullptr, error.get());
Vitaly Buka7c82d292015-05-03 18:08:12 -0700888 EXPECT_JSON_EQ("[{'height':20,'width':10},{'height':18,'width':17}]",
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700889 *val->ToJson());
Alex Vakulenko29e64442015-03-20 13:59:19 -0700890
Vitaly Bukac58a8282015-07-29 01:25:20 -0700891 val = prop.CreateValue(base::StringValue{"blah"}, &error);
Alex Vakulenko29e64442015-03-20 13:59:19 -0700892 EXPECT_EQ(nullptr, val.get());
893 ASSERT_NE(nullptr, error.get());
Vitaly Buka32005de2015-05-01 12:33:31 -0700894 EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
Alex Vakulenko29e64442015-03-20 13:59:19 -0700895}
896
897TEST(CommandSchema, ArrayPropType_NestedArrays_NotSupported) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700898 ArrayPropType prop;
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700899 ErrorPtr error;
Vitaly Bukaa647c852015-07-06 14:51:01 -0700900 EXPECT_FALSE(prop.FromJson(
901 CreateDictionaryValue("{'items':{'items':'integer'}}").get(), nullptr,
902 &error));
Vitaly Buka32005de2015-05-01 12:33:31 -0700903 EXPECT_EQ(errors::commands::kInvalidObjectSchema, error->GetCode());
Alex Vakulenko29e64442015-03-20 13:59:19 -0700904 error.reset();
905}
906
907///////////////////////////////////////////////////////////////////////////////
908
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700909TEST(CommandSchema, ObjectSchema_FromJson_Shorthand_TypeName) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700910 ObjectSchema schema;
Vitaly Bukaa647c852015-07-06 14:51:01 -0700911 const char* schema_str =
912 "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800913 "'param1':'integer',"
914 "'param2':'number',"
915 "'param3':'string'"
916 "}";
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700917 EXPECT_TRUE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
918 nullptr));
Vitaly Buka32005de2015-05-01 12:33:31 -0700919 EXPECT_EQ(ValueType::Int, schema.GetProp("param1")->GetType());
920 EXPECT_EQ(ValueType::Double, schema.GetProp("param2")->GetType());
921 EXPECT_EQ(ValueType::String, schema.GetProp("param3")->GetType());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700922 EXPECT_EQ("integer", schema.GetProp("param1")->GetTypeAsString());
923 EXPECT_EQ("number", schema.GetProp("param2")->GetTypeAsString());
924 EXPECT_EQ("string", schema.GetProp("param3")->GetTypeAsString());
925 EXPECT_EQ(nullptr, schema.GetProp("param4"));
926
927 int min_int = (std::numeric_limits<int>::min)();
928 int max_int = (std::numeric_limits<int>::max)();
929 double min_dbl = (std::numeric_limits<double>::lowest)();
930 double max_dbl = (std::numeric_limits<double>::max)();
931 EXPECT_EQ(min_int, schema.GetProp("param1")->GetInt()->GetMinValue());
932 EXPECT_EQ(max_int, schema.GetProp("param1")->GetInt()->GetMaxValue());
933 EXPECT_EQ(min_dbl, schema.GetProp("param2")->GetDouble()->GetMinValue());
934 EXPECT_EQ(max_dbl, schema.GetProp("param2")->GetDouble()->GetMaxValue());
935 EXPECT_EQ(0, schema.GetProp("param3")->GetString()->GetMinLength());
936 EXPECT_EQ(max_int, schema.GetProp("param3")->GetString()->GetMaxLength());
937}
938
939TEST(CommandSchema, ObjectSchema_FromJson_Full_TypeName) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700940 ObjectSchema schema;
Vitaly Bukaa647c852015-07-06 14:51:01 -0700941 const char* schema_str =
942 "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800943 "'param1':{'type':'integer'},"
944 "'param2':{'type':'number'},"
Alex Vakulenko29e64442015-03-20 13:59:19 -0700945 "'param3':{'type':'string'},"
946 "'param4':{'type':'array', 'items':'integer'},"
947 "'param5':{'type':'object', 'properties':{'p1':'integer'}}"
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800948 "}";
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700949 EXPECT_TRUE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
950 nullptr));
Vitaly Buka32005de2015-05-01 12:33:31 -0700951 EXPECT_EQ(ValueType::Int, schema.GetProp("param1")->GetType());
952 EXPECT_EQ(ValueType::Double, schema.GetProp("param2")->GetType());
953 EXPECT_EQ(ValueType::String, schema.GetProp("param3")->GetType());
954 EXPECT_EQ(ValueType::Array, schema.GetProp("param4")->GetType());
955 EXPECT_EQ(ValueType::Object, schema.GetProp("param5")->GetType());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700956 EXPECT_EQ("integer", schema.GetProp("param1")->GetTypeAsString());
957 EXPECT_EQ("number", schema.GetProp("param2")->GetTypeAsString());
958 EXPECT_EQ("string", schema.GetProp("param3")->GetTypeAsString());
Alex Vakulenko29e64442015-03-20 13:59:19 -0700959 EXPECT_EQ("array", schema.GetProp("param4")->GetTypeAsString());
960 EXPECT_EQ("object", schema.GetProp("param5")->GetTypeAsString());
961 EXPECT_EQ(nullptr, schema.GetProp("param77"));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700962
963 int min_int = (std::numeric_limits<int>::min)();
964 int max_int = (std::numeric_limits<int>::max)();
965 double min_dbl = (std::numeric_limits<double>::lowest)();
966 double max_dbl = (std::numeric_limits<double>::max)();
967 EXPECT_EQ(min_int, schema.GetProp("param1")->GetInt()->GetMinValue());
968 EXPECT_EQ(max_int, schema.GetProp("param1")->GetInt()->GetMaxValue());
969 EXPECT_EQ(min_dbl, schema.GetProp("param2")->GetDouble()->GetMinValue());
970 EXPECT_EQ(max_dbl, schema.GetProp("param2")->GetDouble()->GetMaxValue());
971 EXPECT_EQ(0, schema.GetProp("param3")->GetString()->GetMinLength());
972 EXPECT_EQ(max_int, schema.GetProp("param3")->GetString()->GetMaxLength());
973}
974
975TEST(CommandSchema, ObjectSchema_FromJson_Shorthand_TypeDeduction_Scalar) {
Vitaly Buka32005de2015-05-01 12:33:31 -0700976 ObjectSchema schema;
Vitaly Bukaa647c852015-07-06 14:51:01 -0700977 const char* schema_str =
978 "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800979 "'param1' :{'minimum':2},"
980 "'param2' :{'maximum':10},"
981 "'param3' :{'maximum':8, 'minimum':2},"
982 "'param4' :{'minimum':2.1},"
983 "'param5' :{'maximum':10.1},"
984 "'param6' :{'maximum':8.1, 'minimum':3.1},"
985 "'param7' :{'maximum':8, 'minimum':3.1},"
986 "'param8' :{'maximum':8.1, 'minimum':3},"
987 "'param9' :{'minLength':2},"
988 "'param10':{'maxLength':10},"
989 "'param11':{'maxLength':8, 'minLength':3},"
990 "'param12':{'default':12},"
991 "'param13':{'default':13.5},"
992 "'param14':{'default':true},"
993 "'param15':{'default':false},"
Alex Vakulenko29e64442015-03-20 13:59:19 -0700994 "'param16':{'default':'foobar'},"
995 "'param17':{'default':[1,2,3]},"
996 "'param18':{'items':'number', 'default':[]}"
Alex Vakulenko2a17a532015-02-24 14:51:13 -0800997 "}";
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700998 EXPECT_TRUE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
999 nullptr));
1000 EXPECT_EQ("integer", schema.GetProp("param1")->GetTypeAsString());
1001 EXPECT_EQ("integer", schema.GetProp("param2")->GetTypeAsString());
1002 EXPECT_EQ("integer", schema.GetProp("param3")->GetTypeAsString());
1003 EXPECT_EQ("number", schema.GetProp("param4")->GetTypeAsString());
1004 EXPECT_EQ("number", schema.GetProp("param5")->GetTypeAsString());
1005 EXPECT_EQ("number", schema.GetProp("param6")->GetTypeAsString());
1006 EXPECT_EQ("number", schema.GetProp("param7")->GetTypeAsString());
1007 EXPECT_EQ("number", schema.GetProp("param8")->GetTypeAsString());
1008 EXPECT_EQ("string", schema.GetProp("param9")->GetTypeAsString());
1009 EXPECT_EQ("string", schema.GetProp("param10")->GetTypeAsString());
1010 EXPECT_EQ("string", schema.GetProp("param11")->GetTypeAsString());
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001011 EXPECT_EQ("integer", schema.GetProp("param12")->GetTypeAsString());
1012 EXPECT_EQ("number", schema.GetProp("param13")->GetTypeAsString());
1013 EXPECT_EQ("boolean", schema.GetProp("param14")->GetTypeAsString());
1014 EXPECT_EQ("boolean", schema.GetProp("param15")->GetTypeAsString());
1015 EXPECT_EQ("string", schema.GetProp("param16")->GetTypeAsString());
Alex Vakulenko29e64442015-03-20 13:59:19 -07001016 EXPECT_EQ("array", schema.GetProp("param17")->GetTypeAsString());
1017 auto prop17 = schema.GetProp("param17");
Vitaly Bukaa647c852015-07-06 14:51:01 -07001018 EXPECT_EQ("integer", prop17->GetArray()->GetItemTypePtr()->GetTypeAsString());
Alex Vakulenko29e64442015-03-20 13:59:19 -07001019 EXPECT_EQ("array", schema.GetProp("param18")->GetTypeAsString());
1020 auto prop18 = schema.GetProp("param18");
Vitaly Bukaa647c852015-07-06 14:51:01 -07001021 EXPECT_EQ("number", prop18->GetArray()->GetItemTypePtr()->GetTypeAsString());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001022
1023 int min_int = (std::numeric_limits<int>::min)();
1024 int max_int = (std::numeric_limits<int>::max)();
1025 double min_dbl = (std::numeric_limits<double>::lowest)();
1026 double max_dbl = (std::numeric_limits<double>::max)();
1027 EXPECT_EQ(2, schema.GetProp("param1")->GetInt()->GetMinValue());
1028 EXPECT_EQ(max_int, schema.GetProp("param1")->GetInt()->GetMaxValue());
1029 EXPECT_EQ(min_int, schema.GetProp("param2")->GetInt()->GetMinValue());
1030 EXPECT_EQ(10, schema.GetProp("param2")->GetInt()->GetMaxValue());
1031 EXPECT_EQ(2, schema.GetProp("param3")->GetInt()->GetMinValue());
1032 EXPECT_EQ(8, schema.GetProp("param3")->GetInt()->GetMaxValue());
1033 EXPECT_DOUBLE_EQ(2.1, schema.GetProp("param4")->GetDouble()->GetMinValue());
1034 EXPECT_DOUBLE_EQ(max_dbl,
1035 schema.GetProp("param4")->GetDouble()->GetMaxValue());
1036 EXPECT_DOUBLE_EQ(min_dbl,
1037 schema.GetProp("param5")->GetDouble()->GetMinValue());
1038 EXPECT_DOUBLE_EQ(10.1, schema.GetProp("param5")->GetDouble()->GetMaxValue());
1039 EXPECT_DOUBLE_EQ(3.1, schema.GetProp("param6")->GetDouble()->GetMinValue());
1040 EXPECT_DOUBLE_EQ(8.1, schema.GetProp("param6")->GetDouble()->GetMaxValue());
1041 EXPECT_DOUBLE_EQ(3.1, schema.GetProp("param7")->GetDouble()->GetMinValue());
1042 EXPECT_DOUBLE_EQ(8.0, schema.GetProp("param7")->GetDouble()->GetMaxValue());
1043 EXPECT_DOUBLE_EQ(3.0, schema.GetProp("param8")->GetDouble()->GetMinValue());
1044 EXPECT_DOUBLE_EQ(8.1, schema.GetProp("param8")->GetDouble()->GetMaxValue());
1045 EXPECT_EQ(2, schema.GetProp("param9")->GetString()->GetMinLength());
1046 EXPECT_EQ(max_int, schema.GetProp("param9")->GetString()->GetMaxLength());
1047 EXPECT_EQ(0, schema.GetProp("param10")->GetString()->GetMinLength());
1048 EXPECT_EQ(10, schema.GetProp("param10")->GetString()->GetMaxLength());
1049 EXPECT_EQ(3, schema.GetProp("param11")->GetString()->GetMinLength());
1050 EXPECT_EQ(8, schema.GetProp("param11")->GetString()->GetMaxLength());
Vitaly Buka32005de2015-05-01 12:33:31 -07001051 const PropValue* val = schema.GetProp("param12")->GetDefaultValue();
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001052 EXPECT_EQ(12, val->GetInt()->GetValue());
1053 val = schema.GetProp("param13")->GetDefaultValue();
1054 EXPECT_DOUBLE_EQ(13.5, val->GetDouble()->GetValue());
1055 val = schema.GetProp("param14")->GetDefaultValue();
1056 EXPECT_TRUE(val->GetBoolean()->GetValue());
1057 val = schema.GetProp("param15")->GetDefaultValue();
1058 EXPECT_FALSE(val->GetBoolean()->GetValue());
1059 val = schema.GetProp("param16")->GetDefaultValue();
1060 EXPECT_EQ("foobar", val->GetString()->GetValue());
Alex Vakulenko29e64442015-03-20 13:59:19 -07001061 val = schema.GetProp("param17")->GetDefaultValue();
1062 EXPECT_EQ((std::vector<int>{1, 2, 3}),
1063 GetArrayValues<int>(val->GetArray()->GetValue()));
1064 val = schema.GetProp("param18")->GetDefaultValue();
1065 EXPECT_TRUE(val->GetArray()->GetValue().empty());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001066}
1067
1068TEST(CommandSchema, ObjectSchema_FromJson_Shorthand_TypeDeduction_Array) {
Vitaly Buka32005de2015-05-01 12:33:31 -07001069 ObjectSchema schema;
Vitaly Bukaa647c852015-07-06 14:51:01 -07001070 const char* schema_str =
1071 "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001072 "'param1' :[0,1,2,3],"
1073 "'param2' :[0.0,1.1,2.2],"
1074 "'param3' :['id1', 'id2'],"
1075 "'param4' :{'enum':[1,2,3]},"
1076 "'param5' :{'enum':[-1.1,2.2,3]},"
1077 "'param6' :{'enum':['id0', 'id1']},"
1078 "'param7' :{'type':'integer', 'enum':[1,2,3]},"
1079 "'param8' :{'type':'number', 'enum':[1,2,3]},"
1080 "'param9' :{'type':'number', 'enum':[]},"
Alex Vakulenko29e64442015-03-20 13:59:19 -07001081 "'param10':{'type':'integer', 'enum':[]},"
1082 "'param11':[[0,1],[2,3]],"
1083 "'param12':[['foo','bar']],"
1084 "'param13':{'enum':[['id0', 'id1']]}"
Vitaly Bukaa647c852015-07-06 14:51:01 -07001085 "}";
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001086 EXPECT_TRUE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
1087 nullptr));
1088 EXPECT_EQ("integer", schema.GetProp("param1")->GetTypeAsString());
1089 EXPECT_EQ("number", schema.GetProp("param2")->GetTypeAsString());
1090 EXPECT_EQ("string", schema.GetProp("param3")->GetTypeAsString());
1091 EXPECT_EQ("integer", schema.GetProp("param4")->GetTypeAsString());
1092 EXPECT_EQ("number", schema.GetProp("param5")->GetTypeAsString());
1093 EXPECT_EQ("string", schema.GetProp("param6")->GetTypeAsString());
1094 EXPECT_EQ("integer", schema.GetProp("param7")->GetTypeAsString());
1095 EXPECT_EQ("number", schema.GetProp("param8")->GetTypeAsString());
1096 EXPECT_EQ("number", schema.GetProp("param9")->GetTypeAsString());
1097 EXPECT_EQ("integer", schema.GetProp("param10")->GetTypeAsString());
1098
Alex Vakulenko29e64442015-03-20 13:59:19 -07001099 auto prop_type11 = schema.GetProp("param11");
1100 EXPECT_EQ("array", prop_type11->GetTypeAsString());
1101 EXPECT_EQ("integer",
1102 prop_type11->GetArray()->GetItemTypePtr()->GetTypeAsString());
1103
1104 auto prop_type12 = schema.GetProp("param12");
1105 EXPECT_EQ("array", prop_type12->GetTypeAsString());
1106 EXPECT_EQ("string",
1107 prop_type12->GetArray()->GetItemTypePtr()->GetTypeAsString());
1108
1109 auto prop_type13 = schema.GetProp("param13");
1110 EXPECT_EQ("array", prop_type12->GetTypeAsString());
1111 EXPECT_EQ("string",
1112 prop_type13->GetArray()->GetItemTypePtr()->GetTypeAsString());
1113
Alex Vakulenko9e25ecd2015-03-20 09:43:10 -07001114 EXPECT_EQ((std::vector<int>{0, 1, 2, 3}),
1115 GetOneOfValues<int>(schema.GetProp("param1")));
1116 EXPECT_EQ((std::vector<double>{0.0, 1.1, 2.2}),
1117 GetOneOfValues<double>(schema.GetProp("param2")));
1118 EXPECT_EQ((std::vector<std::string>{"id1", "id2"}),
1119 GetOneOfValues<std::string>(schema.GetProp("param3")));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001120
Alex Vakulenko9e25ecd2015-03-20 09:43:10 -07001121 EXPECT_EQ((std::vector<int>{1, 2, 3}),
1122 GetOneOfValues<int>(schema.GetProp("param4")));
1123 EXPECT_EQ((std::vector<double>{-1.1, 2.2, 3.0}),
1124 GetOneOfValues<double>(schema.GetProp("param5")));
1125 EXPECT_EQ((std::vector<std::string>{"id0", "id1"}),
1126 GetOneOfValues<std::string>(schema.GetProp("param6")));
1127 EXPECT_EQ((std::vector<int>{1, 2, 3}),
1128 GetOneOfValues<int>(schema.GetProp("param7")));
1129 EXPECT_EQ((std::vector<double>{1.0, 2.0, 3.0}),
1130 GetOneOfValues<double>(schema.GetProp("param8")));
1131 EXPECT_TRUE(GetOneOfValues<double>(schema.GetProp("param9")).empty());
1132 EXPECT_TRUE(GetOneOfValues<int>(schema.GetProp("param10")).empty());
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001133}
1134
1135TEST(CommandSchema, ObjectSchema_FromJson_Inheritance) {
Vitaly Bukaa647c852015-07-06 14:51:01 -07001136 const char* base_schema_str =
1137 "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001138 "'param0' :{'minimum':1, 'maximum':5},"
1139 "'param1' :{'minimum':1, 'maximum':5},"
1140 "'param2' :{'minimum':1, 'maximum':5},"
1141 "'param3' :{'minimum':1, 'maximum':5},"
1142 "'param4' :{'minimum':1, 'maximum':5},"
1143 "'param5' :{'minimum':1.1, 'maximum':5.5},"
1144 "'param6' :{'minimum':1.1, 'maximum':5.5},"
1145 "'param7' :{'minimum':1.1, 'maximum':5.5},"
1146 "'param8' :{'minimum':1.1, 'maximum':5.5},"
1147 "'param9' :{'minLength':1, 'maxLength':5},"
1148 "'param10':{'minLength':1, 'maxLength':5},"
1149 "'param11':{'minLength':1, 'maxLength':5},"
1150 "'param12':{'minLength':1, 'maxLength':5},"
1151 "'param13':[1,2,3],"
1152 "'param14':[1,2,3],"
1153 "'param15':[1.1,2.2,3.3],"
1154 "'param16':[1.1,2.2,3.3],"
1155 "'param17':['id1', 'id2'],"
1156 "'param18':['id1', 'id2'],"
1157 "'param19':{'minimum':1, 'maximum':5},"
1158 "'param20':{'default':49},"
1159 "'param21':{'default':49},"
1160 "'param22':'integer'"
1161 "}";
Vitaly Buka32005de2015-05-01 12:33:31 -07001162 ObjectSchema base_schema;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001163 EXPECT_TRUE(base_schema.FromJson(CreateDictionaryValue(base_schema_str).get(),
1164 nullptr, nullptr));
Vitaly Bukaa647c852015-07-06 14:51:01 -07001165 const char* schema_str =
1166 "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001167 "'param1' :{},"
1168 "'param2' :{'minimum':2},"
1169 "'param3' :{'maximum':9},"
1170 "'param4' :{'minimum':2, 'maximum':9},"
1171 "'param5' :{},"
1172 "'param6' :{'minimum':2.2},"
1173 "'param7' :{'maximum':9.9},"
1174 "'param8' :{'minimum':2.2, 'maximum':9.9},"
1175 "'param9' :{},"
1176 "'param10':{'minLength':3},"
1177 "'param11':{'maxLength':8},"
1178 "'param12':{'minLength':3, 'maxLength':8},"
1179 "'param13':{},"
1180 "'param14':[1,2,3,4],"
1181 "'param15':{},"
1182 "'param16':[1.1,2.2,3.3,4.4],"
1183 "'param17':{},"
1184 "'param18':['id1', 'id3'],"
1185 "'param19':{},"
1186 "'param20':{},"
1187 "'param21':{'default':8},"
1188 "'param22':{'default':123}"
1189 "}";
Vitaly Buka32005de2015-05-01 12:33:31 -07001190 ObjectSchema schema;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001191 EXPECT_TRUE(schema.FromJson(CreateDictionaryValue(schema_str).get(),
1192 &base_schema, nullptr));
1193 EXPECT_EQ(nullptr, schema.GetProp("param0"));
1194 EXPECT_NE(nullptr, schema.GetProp("param1"));
1195 EXPECT_EQ("integer", schema.GetProp("param1")->GetTypeAsString());
1196 EXPECT_EQ(1, schema.GetProp("param1")->GetInt()->GetMinValue());
1197 EXPECT_EQ(5, schema.GetProp("param1")->GetInt()->GetMaxValue());
1198 EXPECT_EQ("integer", schema.GetProp("param2")->GetTypeAsString());
1199 EXPECT_EQ(2, schema.GetProp("param2")->GetInt()->GetMinValue());
1200 EXPECT_EQ(5, schema.GetProp("param2")->GetInt()->GetMaxValue());
1201 EXPECT_EQ("integer", schema.GetProp("param3")->GetTypeAsString());
1202 EXPECT_EQ(1, schema.GetProp("param3")->GetInt()->GetMinValue());
1203 EXPECT_EQ(9, schema.GetProp("param3")->GetInt()->GetMaxValue());
1204 EXPECT_EQ("integer", schema.GetProp("param4")->GetTypeAsString());
1205 EXPECT_EQ(2, schema.GetProp("param4")->GetInt()->GetMinValue());
1206 EXPECT_EQ(9, schema.GetProp("param4")->GetInt()->GetMaxValue());
1207 EXPECT_EQ("number", schema.GetProp("param5")->GetTypeAsString());
1208 EXPECT_EQ(1.1, schema.GetProp("param5")->GetDouble()->GetMinValue());
1209 EXPECT_EQ(5.5, schema.GetProp("param5")->GetDouble()->GetMaxValue());
1210 EXPECT_EQ("number", schema.GetProp("param6")->GetTypeAsString());
1211 EXPECT_EQ(2.2, schema.GetProp("param6")->GetDouble()->GetMinValue());
1212 EXPECT_EQ(5.5, schema.GetProp("param6")->GetDouble()->GetMaxValue());
1213 EXPECT_EQ("number", schema.GetProp("param7")->GetTypeAsString());
1214 EXPECT_EQ(1.1, schema.GetProp("param7")->GetDouble()->GetMinValue());
1215 EXPECT_EQ(9.9, schema.GetProp("param7")->GetDouble()->GetMaxValue());
1216 EXPECT_EQ("number", schema.GetProp("param8")->GetTypeAsString());
1217 EXPECT_EQ(2.2, schema.GetProp("param8")->GetDouble()->GetMinValue());
1218 EXPECT_EQ(9.9, schema.GetProp("param8")->GetDouble()->GetMaxValue());
1219 EXPECT_EQ("string", schema.GetProp("param9")->GetTypeAsString());
1220 EXPECT_EQ(1, schema.GetProp("param9")->GetString()->GetMinLength());
1221 EXPECT_EQ(5, schema.GetProp("param9")->GetString()->GetMaxLength());
1222 EXPECT_EQ("string", schema.GetProp("param10")->GetTypeAsString());
1223 EXPECT_EQ(3, schema.GetProp("param10")->GetString()->GetMinLength());
1224 EXPECT_EQ(5, schema.GetProp("param10")->GetString()->GetMaxLength());
1225 EXPECT_EQ("string", schema.GetProp("param11")->GetTypeAsString());
1226 EXPECT_EQ(1, schema.GetProp("param11")->GetString()->GetMinLength());
1227 EXPECT_EQ(8, schema.GetProp("param11")->GetString()->GetMaxLength());
1228 EXPECT_EQ("string", schema.GetProp("param12")->GetTypeAsString());
1229 EXPECT_EQ(3, schema.GetProp("param12")->GetString()->GetMinLength());
1230 EXPECT_EQ(8, schema.GetProp("param12")->GetString()->GetMaxLength());
1231 EXPECT_EQ("integer", schema.GetProp("param13")->GetTypeAsString());
Alex Vakulenko9e25ecd2015-03-20 09:43:10 -07001232 EXPECT_EQ((std::vector<int>{1, 2, 3}),
1233 GetOneOfValues<int>(schema.GetProp("param13")));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001234 EXPECT_EQ("integer", schema.GetProp("param14")->GetTypeAsString());
Alex Vakulenko9e25ecd2015-03-20 09:43:10 -07001235 EXPECT_EQ((std::vector<int>{1, 2, 3, 4}),
1236 GetOneOfValues<int>(schema.GetProp("param14")));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001237 EXPECT_EQ("number", schema.GetProp("param15")->GetTypeAsString());
Alex Vakulenko9e25ecd2015-03-20 09:43:10 -07001238 EXPECT_EQ((std::vector<double>{1.1, 2.2, 3.3}),
1239 GetOneOfValues<double>(schema.GetProp("param15")));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001240 EXPECT_EQ("number", schema.GetProp("param16")->GetTypeAsString());
Alex Vakulenko9e25ecd2015-03-20 09:43:10 -07001241 EXPECT_EQ((std::vector<double>{1.1, 2.2, 3.3, 4.4}),
1242 GetOneOfValues<double>(schema.GetProp("param16")));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001243 EXPECT_EQ("string", schema.GetProp("param17")->GetTypeAsString());
Alex Vakulenko9e25ecd2015-03-20 09:43:10 -07001244 EXPECT_EQ((std::vector<std::string>{"id1", "id2"}),
1245 GetOneOfValues<std::string>(schema.GetProp("param17")));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001246 EXPECT_EQ("string", schema.GetProp("param18")->GetTypeAsString());
Alex Vakulenko9e25ecd2015-03-20 09:43:10 -07001247 EXPECT_EQ((std::vector<std::string>{"id1", "id3"}),
1248 GetOneOfValues<std::string>(schema.GetProp("param18")));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001249 EXPECT_EQ("integer", schema.GetProp("param19")->GetTypeAsString());
1250 EXPECT_EQ(1, schema.GetProp("param19")->GetInt()->GetMinValue());
1251 EXPECT_EQ(5, schema.GetProp("param19")->GetInt()->GetMaxValue());
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001252 EXPECT_EQ(49,
1253 schema.GetProp("param20")->GetDefaultValue()->GetInt()->GetValue());
1254 EXPECT_EQ(8,
1255 schema.GetProp("param21")->GetDefaultValue()->GetInt()->GetValue());
1256 EXPECT_EQ(123,
1257 schema.GetProp("param22")->GetDefaultValue()->GetInt()->GetValue());
1258}
1259
1260TEST(CommandSchema, ObjectSchema_UseDefaults) {
Vitaly Buka32005de2015-05-01 12:33:31 -07001261 ObjectPropType prop;
Vitaly Bukaa647c852015-07-06 14:51:01 -07001262 const char* schema_str =
1263 "{'properties':{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001264 "'param1':{'default':true},"
1265 "'param2':{'default':2},"
1266 "'param3':{'default':3.3},"
1267 "'param4':{'default':'four'},"
1268 "'param5':{'default':{'x':5,'y':6},"
Vitaly Bukaa647c852015-07-06 14:51:01 -07001269 "'properties':{'x':'integer','y':'integer'}},"
Alex Vakulenko29e64442015-03-20 13:59:19 -07001270 "'param6':{'default':[1,2,3]}"
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001271 "}}";
Vitaly Bukaa647c852015-07-06 14:51:01 -07001272 ASSERT_TRUE(
1273 prop.FromJson(CreateDictionaryValue(schema_str).get(), nullptr, nullptr));
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001274
1275 // Omit all.
Vitaly Buka79c05e92015-07-29 12:25:37 -07001276 auto value =
1277 prop.CreatePropValue(*CreateDictionaryValue("{}").get(), nullptr);
1278 ASSERT_NE(nullptr, value);
Vitaly Buka774cdf52015-07-21 13:55:00 -07001279 ValueMap obj = value->GetObject()->GetValue();
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001280 EXPECT_TRUE(obj["param1"]->GetBoolean()->GetValue());
1281 EXPECT_EQ(2, obj["param2"]->GetInt()->GetValue());
1282 EXPECT_DOUBLE_EQ(3.3, obj["param3"]->GetDouble()->GetValue());
1283 EXPECT_EQ("four", obj["param4"]->GetString()->GetValue());
Vitaly Buka774cdf52015-07-21 13:55:00 -07001284 ValueMap param5 = obj["param5"]->GetObject()->GetValue();
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001285 EXPECT_EQ(5, param5["x"]->GetInt()->GetValue());
1286 EXPECT_EQ(6, param5["y"]->GetInt()->GetValue());
Vitaly Buka774cdf52015-07-21 13:55:00 -07001287 ValueVector param6 = obj["param6"]->GetArray()->GetValue();
Alex Vakulenko29e64442015-03-20 13:59:19 -07001288 EXPECT_EQ((std::vector<int>{1, 2, 3}), GetArrayValues<int>(param6));
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001289
1290 // Specify some.
Vitaly Bukaa647c852015-07-06 14:51:01 -07001291 const char* val_json =
1292 "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001293 "'param1':false,"
1294 "'param3':33.3,"
1295 "'param5':{'x':-5,'y':-6}"
1296 "}";
Vitaly Buka79c05e92015-07-29 12:25:37 -07001297 value = prop.CreatePropValue(*CreateDictionaryValue(val_json).get(), nullptr);
1298 ASSERT_NE(nullptr, value);
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001299 obj = value->GetObject()->GetValue();
1300 EXPECT_FALSE(obj["param1"]->GetBoolean()->GetValue());
1301 EXPECT_EQ(2, obj["param2"]->GetInt()->GetValue());
1302 EXPECT_DOUBLE_EQ(33.3, obj["param3"]->GetDouble()->GetValue());
1303 EXPECT_EQ("four", obj["param4"]->GetString()->GetValue());
1304 param5 = obj["param5"]->GetObject()->GetValue();
1305 EXPECT_EQ(-5, param5["x"]->GetInt()->GetValue());
1306 EXPECT_EQ(-6, param5["y"]->GetInt()->GetValue());
Alex Vakulenko29e64442015-03-20 13:59:19 -07001307 param6 = obj["param6"]->GetArray()->GetValue();
1308 EXPECT_EQ((std::vector<int>{1, 2, 3}), GetArrayValues<int>(param6));
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001309
1310 // Specify all.
Vitaly Bukaa647c852015-07-06 14:51:01 -07001311 val_json =
1312 "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001313 "'param1':false,"
1314 "'param2':22,"
1315 "'param3':333.3,"
1316 "'param4':'FOUR',"
Alex Vakulenko29e64442015-03-20 13:59:19 -07001317 "'param5':{'x':-55,'y':66},"
1318 "'param6':[-1, 0]"
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001319 "}";
Vitaly Buka79c05e92015-07-29 12:25:37 -07001320 value = prop.CreatePropValue(*CreateDictionaryValue(val_json).get(), nullptr);
1321 ASSERT_NE(nullptr, value);
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001322 obj = value->GetObject()->GetValue();
1323 EXPECT_FALSE(obj["param1"]->GetBoolean()->GetValue());
1324 EXPECT_EQ(22, obj["param2"]->GetInt()->GetValue());
1325 EXPECT_DOUBLE_EQ(333.3, obj["param3"]->GetDouble()->GetValue());
1326 EXPECT_EQ("FOUR", obj["param4"]->GetString()->GetValue());
1327 param5 = obj["param5"]->GetObject()->GetValue();
1328 EXPECT_EQ(-55, param5["x"]->GetInt()->GetValue());
1329 EXPECT_EQ(66, param5["y"]->GetInt()->GetValue());
Alex Vakulenko29e64442015-03-20 13:59:19 -07001330 param6 = obj["param6"]->GetArray()->GetValue();
1331 EXPECT_EQ((std::vector<int>{-1, 0}), GetArrayValues<int>(param6));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001332}
1333
1334TEST(CommandSchema, ObjectSchema_FromJson_BaseSchema_Failures) {
Vitaly Buka32005de2015-05-01 12:33:31 -07001335 ObjectSchema schema;
Vitaly Buka0801a1f2015-08-14 10:03:46 -07001336 ErrorPtr error;
Vitaly Bukaa647c852015-07-06 14:51:01 -07001337 const char* schema_str =
1338 "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001339 "'param1':{}"
1340 "}";
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001341 EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
1342 &error));
1343 EXPECT_EQ("no_type_info", error->GetFirstError()->GetCode());
1344 error.reset();
1345
Vitaly Bukaa647c852015-07-06 14:51:01 -07001346 schema_str =
1347 "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001348 "'param1':{'type':'foo'}"
1349 "}";
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001350 EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
1351 &error));
1352 EXPECT_EQ("unknown_type", error->GetFirstError()->GetCode());
1353 error.reset();
1354
Vitaly Bukaa647c852015-07-06 14:51:01 -07001355 schema_str =
1356 "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001357 "'param1':[]"
1358 "}";
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001359 EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
1360 &error));
1361 EXPECT_EQ("no_type_info", error->GetFirstError()->GetCode());
1362 error.reset();
1363
Vitaly Bukaa647c852015-07-06 14:51:01 -07001364 schema_str =
1365 "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001366 "'param1':{'minimum':'foo'}"
1367 "}";
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001368 EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
1369 &error));
1370 EXPECT_EQ("type_mismatch", error->GetFirstError()->GetCode());
1371 error.reset();
1372
Vitaly Bukaa647c852015-07-06 14:51:01 -07001373 schema_str =
1374 "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001375 "'param1':[1,2.2]"
1376 "}";
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001377 EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
1378 &error));
1379 EXPECT_EQ("type_mismatch", error->GetFirstError()->GetCode());
1380 error.reset();
Alex Vakulenko5109b202014-06-20 14:49:41 -07001381
Vitaly Bukaa647c852015-07-06 14:51:01 -07001382 schema_str =
1383 "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001384 "'param1':{'minimum':1, 'enum':[1,2,3]}" // can't have min/max & enum.
1385 "}";
Alex Vakulenko5109b202014-06-20 14:49:41 -07001386 EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
1387 &error));
1388 EXPECT_EQ("unexpected_parameter", error->GetFirstError()->GetCode());
1389 error.reset();
1390
Vitaly Bukaa647c852015-07-06 14:51:01 -07001391 schema_str =
1392 "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001393 "'param1':{'maximum':1, 'blah':2}" // 'blah' is unexpected.
1394 "}";
Alex Vakulenko5109b202014-06-20 14:49:41 -07001395 EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
1396 &error));
1397 EXPECT_EQ("unexpected_parameter", error->GetFirstError()->GetCode());
1398 error.reset();
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001399
Vitaly Bukaa647c852015-07-06 14:51:01 -07001400 schema_str =
1401 "{"
Alex Vakulenko2a17a532015-02-24 14:51:13 -08001402 "'param1':{'enum':[1,2,3],'default':5}" // 'default' must be 1, 2, or 3.
1403 "}";
1404 EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
1405 &error));
1406 EXPECT_EQ("out_of_range", error->GetFirstError()->GetCode());
1407 error.reset();
Alex Vakulenko29e64442015-03-20 13:59:19 -07001408
Vitaly Bukaa647c852015-07-06 14:51:01 -07001409 schema_str =
1410 "{"
Alex Vakulenko29e64442015-03-20 13:59:19 -07001411 "'param1':[[1,2.3]]"
1412 "}";
1413 EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
1414 &error));
1415 EXPECT_EQ("type_mismatch", error->GetFirstError()->GetCode());
1416 error.reset();
1417
Vitaly Bukaa647c852015-07-06 14:51:01 -07001418 schema_str =
1419 "{"
Alex Vakulenko29e64442015-03-20 13:59:19 -07001420 "'param1':[[1,2],[3,4],['blah']]"
1421 "}";
1422 EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
1423 &error));
1424 EXPECT_EQ("type_mismatch", error->GetFirstError()->GetCode());
1425 error.reset();
1426
Vitaly Bukaa647c852015-07-06 14:51:01 -07001427 schema_str =
1428 "{"
Alex Vakulenko29e64442015-03-20 13:59:19 -07001429 "'param1':{'default':[]}"
1430 "}";
1431 EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
1432 &error));
1433 EXPECT_EQ("no_type_info", error->GetFirstError()->GetCode());
1434 error.reset();
1435
Vitaly Bukaa647c852015-07-06 14:51:01 -07001436 schema_str =
1437 "{"
Alex Vakulenko29e64442015-03-20 13:59:19 -07001438 "'param1':[[[1]],[[2]]]"
1439 "}";
1440 EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
1441 &error));
1442 EXPECT_EQ("no_type_info", error->GetFirstError()->GetCode());
1443 error.reset();
1444
Vitaly Bukaa647c852015-07-06 14:51:01 -07001445 schema_str =
1446 "{"
Alex Vakulenko29e64442015-03-20 13:59:19 -07001447 "'param1':{'enum':[[['foo']]]}"
1448 "}";
1449 EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
1450 &error));
1451 EXPECT_EQ("no_type_info", error->GetFirstError()->GetCode());
1452 error.reset();
1453
Vitaly Bukaa647c852015-07-06 14:51:01 -07001454 schema_str =
1455 "{"
Alex Vakulenko29e64442015-03-20 13:59:19 -07001456 "'param1':{'default':[[1],[2]]}"
1457 "}";
1458 EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
1459 &error));
1460 EXPECT_EQ("no_type_info", error->GetFirstError()->GetCode());
1461 error.reset();
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001462}
Vitaly Buka32005de2015-05-01 12:33:31 -07001463
Alex Vakulenko7e8df462015-07-07 10:59:20 -07001464TEST(CommandSchema, RequiredProperties_Integral) {
1465 IntPropType prop;
1466
1467 prop.MakeRequired(false);
Vitaly Buka6942e1f2015-07-28 15:33:55 -07001468 EXPECT_JSON_EQ("{'type':'integer'}", *prop.ToJson(true, false));
Alex Vakulenko7e8df462015-07-07 10:59:20 -07001469 EXPECT_JSON_EQ("{'isRequired':false,'type':'integer'}",
Vitaly Buka6942e1f2015-07-28 15:33:55 -07001470 *prop.ToJson(true, true));
Alex Vakulenko7e8df462015-07-07 10:59:20 -07001471
1472 prop.MakeRequired(true);
Vitaly Buka6942e1f2015-07-28 15:33:55 -07001473 EXPECT_JSON_EQ("{'type':'integer'}", *prop.ToJson(true, false));
Alex Vakulenko7e8df462015-07-07 10:59:20 -07001474 EXPECT_JSON_EQ("{'isRequired':true,'type':'integer'}",
Vitaly Buka6942e1f2015-07-28 15:33:55 -07001475 *prop.ToJson(true, true));
Alex Vakulenko7e8df462015-07-07 10:59:20 -07001476
1477 IntPropType prop2;
Vitaly Buka4ebd3292015-09-23 18:04:17 -07001478 EXPECT_TRUE(
1479 prop2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr));
Alex Vakulenko7e8df462015-07-07 10:59:20 -07001480 EXPECT_TRUE(prop2.IsRequired());
1481
1482 EXPECT_TRUE(prop2.FromJson(
1483 CreateDictionaryValue("{'isRequired': false}").get(), &prop, nullptr));
1484 EXPECT_FALSE(prop2.IsRequired());
1485
Vitaly Buka6942e1f2015-07-28 15:33:55 -07001486 EXPECT_JSON_EQ("{'type':'integer'}", *prop2.ToJson(true, false));
Alex Vakulenko7e8df462015-07-07 10:59:20 -07001487 EXPECT_JSON_EQ("{'isRequired':false,'type':'integer'}",
Vitaly Buka6942e1f2015-07-28 15:33:55 -07001488 *prop2.ToJson(true, true));
Alex Vakulenko7e8df462015-07-07 10:59:20 -07001489}
1490
1491TEST(CommandSchema, RequiredProperties_Object) {
1492 ObjectPropType obj_type;
1493 auto schema = ObjectSchema::Create();
1494 auto type = PropType::Create(ValueType::Int);
1495 type->MakeRequired(true);
1496 schema->AddProp("prop1", std::move(type));
1497 type = PropType::Create(ValueType::String);
1498 type->MakeRequired(false);
1499 schema->AddProp("prop2", std::move(type));
1500 type = PropType::Create(ValueType::Boolean);
1501 type->MakeRequired(true);
1502 schema->AddProp("prop3", std::move(type));
1503 type = PropType::Create(ValueType::Array);
1504 type->GetArray()->SetItemType(PropType::Create(ValueType::String));
1505 schema->AddProp("prop4", std::move(type));
1506 auto expected1 = R"({
1507 'prop1': 'integer',
1508 'prop2': 'string',
1509 'prop3': 'boolean',
1510 'prop4': {'items': 'string'}
1511 })";
Vitaly Buka6942e1f2015-07-28 15:33:55 -07001512 EXPECT_JSON_EQ(expected1, *schema->ToJson(false, false));
Alex Vakulenko7e8df462015-07-07 10:59:20 -07001513 auto expected2 = R"({
1514 'prop1': {'type':'integer','isRequired': true},
1515 'prop2': {'type':'string','isRequired': false},
1516 'prop3': {'type':'boolean','isRequired': true},
1517 'prop4': {'items': 'string'}
1518 })";
Vitaly Buka6942e1f2015-07-28 15:33:55 -07001519 EXPECT_JSON_EQ(expected2, *schema->ToJson(false, true));
Alex Vakulenko7e8df462015-07-07 10:59:20 -07001520
1521 obj_type.SetObjectSchema(std::move(schema));
1522 auto expected3 = R"({
1523 'additionalProperties': false,
1524 'properties': {
1525 'prop1': 'integer',
1526 'prop2': 'string',
1527 'prop3': 'boolean',
1528 'prop4': {'items': 'string'}
1529 },
1530 'required': ['prop1','prop3']
1531 })";
Vitaly Buka6942e1f2015-07-28 15:33:55 -07001532 EXPECT_JSON_EQ(expected3, *obj_type.ToJson(false, false));
1533 EXPECT_JSON_EQ(expected3, *obj_type.ToJson(false, true));
Alex Vakulenko7e8df462015-07-07 10:59:20 -07001534}
1535
1536TEST(CommandSchema, RequiredProperties_Schema_FromJson) {
1537 ObjectSchema schema;
1538 auto schema_str = R"({
1539 'prop1': {'type':'integer','isRequired': true},
1540 'prop2': {'type':'string','isRequired': false},
1541 'prop3': 'boolean'
1542 })";
1543 EXPECT_TRUE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
1544 nullptr));
1545 EXPECT_TRUE(schema.GetProp("prop1")->IsRequired());
1546 EXPECT_FALSE(schema.GetProp("prop2")->IsRequired());
1547 EXPECT_FALSE(schema.GetProp("prop3")->IsRequired());
Vitaly Buka6942e1f2015-07-28 15:33:55 -07001548 EXPECT_JSON_EQ(schema_str, *schema.ToJson(false, true));
Alex Vakulenko7e8df462015-07-07 10:59:20 -07001549}
1550
1551TEST(CommandSchema, RequiredProperties_Schema_FromJson_Inherit) {
1552 ObjectSchema base_schema;
1553 auto base_schema_str = R"({
1554 'prop1': {'type':'integer','isRequired': true},
1555 'prop2': {'type':'integer','isRequired': false},
1556 'prop3': {'type':'integer','isRequired': true},
1557 'prop4': {'type':'integer','isRequired': false}
1558 })";
1559 EXPECT_TRUE(base_schema.FromJson(CreateDictionaryValue(base_schema_str).get(),
1560 nullptr, nullptr));
1561 ObjectSchema schema;
1562 auto schema_str = R"({
1563 'prop1': {'isRequired': false},
1564 'prop2': {'isRequired': true},
1565 'prop3': {},
1566 'prop4': 'integer'
1567 })";
1568 EXPECT_TRUE(schema.FromJson(CreateDictionaryValue(schema_str).get(),
1569 &base_schema, nullptr));
1570 EXPECT_FALSE(schema.GetProp("prop1")->IsRequired());
1571 EXPECT_TRUE(schema.GetProp("prop2")->IsRequired());
1572 EXPECT_TRUE(schema.GetProp("prop3")->IsRequired());
1573 EXPECT_FALSE(schema.GetProp("prop4")->IsRequired());
1574 auto expected = R"({
1575 'prop1': {'type':'integer','isRequired': false},
1576 'prop2': {'type':'integer','isRequired': true},
1577 'prop3': {},
1578 'prop4': {}
1579 })";
Vitaly Buka6942e1f2015-07-28 15:33:55 -07001580 EXPECT_JSON_EQ(expected, *schema.ToJson(false, true));
Alex Vakulenko7e8df462015-07-07 10:59:20 -07001581}
1582
1583TEST(CommandSchema, RequiredProperties_ObjectPropType_FromJson) {
1584 ObjectPropType obj_type;
1585 auto type_str = R"({
1586 'properties': {
1587 'prop1': 'integer',
1588 'prop2': 'string',
1589 'prop3': {'type':'boolean','isRequired':true},
1590 'prop4': {'items': 'string','isRequired':false},
1591 'prop5': {'type':'number','isRequired':true}
1592 },
1593 'required': ['prop1','prop3','prop4','prop5']
1594 })";
1595 EXPECT_TRUE(obj_type.FromJson(CreateDictionaryValue(type_str).get(), nullptr,
1596 nullptr));
1597 EXPECT_TRUE(obj_type.GetObjectSchemaPtr()->GetProp("prop1")->IsRequired());
1598 EXPECT_FALSE(obj_type.GetObjectSchemaPtr()->GetProp("prop2")->IsRequired());
1599 EXPECT_TRUE(obj_type.GetObjectSchemaPtr()->GetProp("prop3")->IsRequired());
1600 // 'required' takes precedence over 'isRequired'.
1601 EXPECT_TRUE(obj_type.GetObjectSchemaPtr()->GetProp("prop4")->IsRequired());
1602 EXPECT_TRUE(obj_type.GetObjectSchemaPtr()->GetProp("prop5")->IsRequired());
1603}
1604
1605TEST(CommandSchema, RequiredProperties_Failures) {
1606 ObjectPropType obj_type;
Vitaly Buka0801a1f2015-08-14 10:03:46 -07001607 ErrorPtr error;
Alex Vakulenko7e8df462015-07-07 10:59:20 -07001608
1609 auto type_str = R"({
1610 'properties': {
1611 'prop1': 'integer',
1612 'prop2': 'string'
1613 },
1614 'required': ['prop1','prop3','prop4']
1615 })";
1616 EXPECT_FALSE(obj_type.FromJson(CreateDictionaryValue(type_str).get(), nullptr,
1617 &error));
1618 EXPECT_EQ(errors::commands::kUnknownProperty, error->GetCode());
Alex Vakulenko7e8df462015-07-07 10:59:20 -07001619 error.reset();
1620
1621 type_str = R"({
1622 'properties': {
1623 'prop1': 'integer',
1624 'prop2': 'string'
1625 },
1626 'required': 'prop1'
1627 })";
1628 EXPECT_FALSE(obj_type.FromJson(CreateDictionaryValue(type_str).get(), nullptr,
1629 &error));
1630 EXPECT_EQ(errors::commands::kInvalidObjectSchema, error->GetCode());
Alex Vakulenko7e8df462015-07-07 10:59:20 -07001631 error.reset();
1632}
1633
1634TEST(CommandSchema, ObjectSchema_UseRequired) {
1635 ObjectPropType prop;
1636 auto schema_str = R"({
1637 'properties':{
1638 'param1':'integer',
1639 'param2':'integer',
1640 'param3':{'default':3},
1641 'param4':{'default':4}
1642 },
1643 'required':['param1','param3']
1644 })";
Vitaly Buka4ebd3292015-09-23 18:04:17 -07001645 ASSERT_TRUE(
1646 prop.FromJson(CreateDictionaryValue(schema_str).get(), nullptr, nullptr));
Alex Vakulenko7e8df462015-07-07 10:59:20 -07001647
Alex Vakulenko7e8df462015-07-07 10:59:20 -07001648 auto val_json = R"({
1649 'param1':10,
1650 'param2':20,
1651 'param3':30,
1652 'param4':40
1653 })";
Vitaly Buka79c05e92015-07-29 12:25:37 -07001654 auto value =
1655 prop.CreatePropValue(*CreateDictionaryValue(val_json).get(), nullptr);
1656 ASSERT_NE(nullptr, value);
Vitaly Buka774cdf52015-07-21 13:55:00 -07001657 ValueMap obj = value->GetObject()->GetValue();
Alex Vakulenko7e8df462015-07-07 10:59:20 -07001658 EXPECT_EQ(10, obj["param1"]->GetInt()->GetValue());
1659 EXPECT_EQ(20, obj["param2"]->GetInt()->GetValue());
1660 EXPECT_EQ(30, obj["param3"]->GetInt()->GetValue());
1661 EXPECT_EQ(40, obj["param4"]->GetInt()->GetValue());
1662
Alex Vakulenko7e8df462015-07-07 10:59:20 -07001663 val_json = "{'param1':100}";
Vitaly Buka79c05e92015-07-29 12:25:37 -07001664 value = prop.CreatePropValue(*CreateDictionaryValue(val_json).get(), nullptr);
1665 ASSERT_NE(nullptr, value);
Alex Vakulenko7e8df462015-07-07 10:59:20 -07001666 obj = value->GetObject()->GetValue();
1667 EXPECT_EQ(3, obj.size());
1668
1669 EXPECT_EQ(100, obj["param1"]->GetInt()->GetValue());
1670 EXPECT_EQ(obj.end(), obj.find("param2"));
1671 EXPECT_EQ(3, obj["param3"]->GetInt()->GetValue());
1672 EXPECT_EQ(4, obj["param4"]->GetInt()->GetValue());
1673}
1674
1675TEST(CommandSchema, ObjectSchema_UseRequired_Failure) {
1676 ObjectPropType prop;
1677 auto schema_str = R"({
1678 'properties':{
1679 'param1':'integer',
1680 'param2':'integer',
1681 'param3':{'default':3},
1682 'param4':{'default':4}
1683 },
1684 'required':['param1','param3']
1685 })";
Vitaly Buka4ebd3292015-09-23 18:04:17 -07001686 ASSERT_TRUE(
1687 prop.FromJson(CreateDictionaryValue(schema_str).get(), nullptr, nullptr));
Alex Vakulenko7e8df462015-07-07 10:59:20 -07001688
Alex Vakulenko7e8df462015-07-07 10:59:20 -07001689 auto val_json = "{'param2':20}";
Vitaly Buka0801a1f2015-08-14 10:03:46 -07001690 ErrorPtr error;
Vitaly Buka79c05e92015-07-29 12:25:37 -07001691 auto value =
1692 prop.CreatePropValue(*CreateDictionaryValue(val_json).get(), &error);
1693 ASSERT_EQ(nullptr, value);
Alex Vakulenko7e8df462015-07-07 10:59:20 -07001694 EXPECT_EQ(errors::commands::kPropertyMissing, error->GetCode());
Alex Vakulenko7e8df462015-07-07 10:59:20 -07001695}
1696
Vitaly Bukab6f015a2015-07-09 14:59:23 -07001697} // namespace weave