aboutsummaryrefslogtreecommitdiff
path: root/src/commands
diff options
context:
space:
mode:
authorAlex Vakulenko <avakulenko@google.com>2015-11-24 17:13:20 -0800
committerAlex Vakulenko <avakulenko@google.com>2015-11-25 02:18:04 +0000
commit8a05bebb95f5f3f9bf6b72bd9e58b6ba6b8c9bdd (patch)
tree61cc3751a92cebe57e77dad742a131de938f5a8b /src/commands
parent42d63b9d2b41aab4cb13d55482f7ebf66fee7f27 (diff)
downloadlibweave-8a05bebb95f5f3f9bf6b72bd9e58b6ba6b8c9bdd.tar.gz
Remove object schema type system
Since libweave no longer semantically parses command/state definitions and validates commands and states, there is no need for this extra code. BUG: 25841230 Change-Id: I53dfab20db8c97b621c07fe234a7b3c6da7325bb Reviewed-on: https://weave-review.googlesource.com/1660 Reviewed-by: Vitaly Buka <vitalybuka@google.com>
Diffstat (limited to 'src/commands')
-rw-r--r--src/commands/cloud_command_proxy.cc2
-rw-r--r--src/commands/cloud_command_proxy_unittest.cc2
-rw-r--r--src/commands/command_definition_unittest.cc3
-rw-r--r--src/commands/command_dictionary_unittest.cc3
-rw-r--r--src/commands/command_instance.h3
-rw-r--r--src/commands/command_instance_unittest.cc2
-rw-r--r--src/commands/command_manager_unittest.cc2
-rw-r--r--src/commands/command_queue_unittest.cc1
-rw-r--r--src/commands/object_schema.cc379
-rw-r--r--src/commands/object_schema.h95
-rw-r--r--src/commands/object_schema_unittest.cc1697
-rw-r--r--src/commands/prop_constraints.cc202
-rw-r--r--src/commands/prop_constraints.h315
-rw-r--r--src/commands/prop_types.cc655
-rw-r--r--src/commands/prop_types.h352
-rw-r--r--src/commands/prop_values.cc17
-rw-r--r--src/commands/prop_values.h266
-rw-r--r--src/commands/schema_constants.cc27
-rw-r--r--src/commands/schema_constants.h27
-rw-r--r--src/commands/schema_utils.cc266
-rw-r--r--src/commands/schema_utils.h136
-rw-r--r--src/commands/schema_utils_unittest.cc212
-rw-r--r--src/commands/unittest_utils.h47
23 files changed, 5 insertions, 4706 deletions
diff --git a/src/commands/cloud_command_proxy.cc b/src/commands/cloud_command_proxy.cc
index 9ec3d3e..91db18c 100644
--- a/src/commands/cloud_command_proxy.cc
+++ b/src/commands/cloud_command_proxy.cc
@@ -9,8 +9,6 @@
#include <weave/provider/task_runner.h>
#include "src/commands/command_instance.h"
-#include "src/commands/prop_constraints.h"
-#include "src/commands/prop_types.h"
#include "src/commands/schema_constants.h"
#include "src/utils.h"
diff --git a/src/commands/cloud_command_proxy_unittest.cc b/src/commands/cloud_command_proxy_unittest.cc
index fdb22fc..a65a967 100644
--- a/src/commands/cloud_command_proxy_unittest.cc
+++ b/src/commands/cloud_command_proxy_unittest.cc
@@ -10,10 +10,10 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <weave/provider/test/fake_task_runner.h>
+#include <weave/test/unittest_utils.h>
#include "src/commands/command_dictionary.h"
#include "src/commands/command_instance.h"
-#include "src/commands/unittest_utils.h"
#include "src/states/mock_state_change_queue_interface.h"
using testing::_;
diff --git a/src/commands/command_definition_unittest.cc b/src/commands/command_definition_unittest.cc
index ecd6e54..867d48f 100644
--- a/src/commands/command_definition_unittest.cc
+++ b/src/commands/command_definition_unittest.cc
@@ -5,8 +5,7 @@
#include "src/commands/command_definition.h"
#include <gtest/gtest.h>
-
-#include "src/commands/unittest_utils.h"
+#include <weave/test/unittest_utils.h>
namespace weave {
diff --git a/src/commands/command_dictionary_unittest.cc b/src/commands/command_dictionary_unittest.cc
index 7298363..adae4ec 100644
--- a/src/commands/command_dictionary_unittest.cc
+++ b/src/commands/command_dictionary_unittest.cc
@@ -5,8 +5,7 @@
#include "src/commands/command_dictionary.h"
#include <gtest/gtest.h>
-
-#include "src/commands/unittest_utils.h"
+#include <weave/test/unittest_utils.h>
namespace weave {
diff --git a/src/commands/command_instance.h b/src/commands/command_instance.h
index 30ef907..e7a6eca 100644
--- a/src/commands/command_instance.h
+++ b/src/commands/command_instance.h
@@ -15,9 +15,6 @@
#include <weave/error.h>
#include <weave/command.h>
-#include "src/commands/prop_values.h"
-#include "src/commands/schema_utils.h"
-
namespace base {
class Value;
} // namespace base
diff --git a/src/commands/command_instance_unittest.cc b/src/commands/command_instance_unittest.cc
index cacb86c..1d32cd9 100644
--- a/src/commands/command_instance_unittest.cc
+++ b/src/commands/command_instance_unittest.cc
@@ -5,9 +5,9 @@
#include "src/commands/command_instance.h"
#include <gtest/gtest.h>
+#include <weave/test/unittest_utils.h>
#include "src/commands/command_dictionary.h"
-#include "src/commands/unittest_utils.h"
namespace weave {
diff --git a/src/commands/command_manager_unittest.cc b/src/commands/command_manager_unittest.cc
index 2b2b055..f0dc95d 100644
--- a/src/commands/command_manager_unittest.cc
+++ b/src/commands/command_manager_unittest.cc
@@ -9,9 +9,9 @@
#include <base/json/json_writer.h>
#include <gtest/gtest.h>
#include <weave/provider/test/mock_config_store.h>
+#include <weave/test/unittest_utils.h>
#include "src/bind_lambda.h"
-#include "src/commands/unittest_utils.h"
using testing::Return;
diff --git a/src/commands/command_queue_unittest.cc b/src/commands/command_queue_unittest.cc
index 394ae20..dc7290a 100644
--- a/src/commands/command_queue_unittest.cc
+++ b/src/commands/command_queue_unittest.cc
@@ -13,7 +13,6 @@
#include <gtest/gtest.h>
#include "src/commands/command_definition.h"
-#include "src/commands/object_schema.h"
#include "src/string_utils.h"
namespace weave {
diff --git a/src/commands/object_schema.cc b/src/commands/object_schema.cc
deleted file mode 100644
index 6cfa5f4..0000000
--- a/src/commands/object_schema.cc
+++ /dev/null
@@ -1,379 +0,0 @@
-// Copyright 2015 The Weave Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/commands/object_schema.h"
-
-#include <algorithm>
-#include <limits>
-
-#include <base/logging.h>
-#include <base/values.h>
-#include <weave/enum_to_string.h>
-
-#include "src/commands/prop_types.h"
-#include "src/commands/prop_values.h"
-#include "src/commands/schema_constants.h"
-#include "src/string_utils.h"
-
-namespace weave {
-
-namespace {
-
-// Helper function for to create a PropType based on type string.
-// Generates an error if the string identifies an unknown type.
-std::unique_ptr<PropType> CreatePropType(const std::string& type_name,
- ErrorPtr* error) {
- auto parts = SplitAtFirst(type_name, ".", false);
- const std::string& primary_type = parts.first;
- const std::string& array_type = parts.second;
-
- std::unique_ptr<PropType> prop;
- ValueType type;
- if (PropType::GetTypeFromTypeString(primary_type, &type)) {
- prop = PropType::Create(type);
- if (prop && type == ValueType::Array && !array_type.empty()) {
- auto items_type = CreatePropType(array_type, error);
- if (items_type) {
- prop->GetArray()->SetItemType(std::move(items_type));
- } else {
- prop.reset();
- return prop;
- }
- }
- }
- if (!prop) {
- Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kUnknownType, "Unknown type %s",
- type_name.c_str());
- }
- return prop;
-}
-
-// Generates "no_type_info" error.
-void ErrorInvalidTypeInfo(ErrorPtr* error) {
- Error::AddTo(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kNoTypeInfo,
- "Unable to determine parameter type");
-}
-
-// Helper function for PropFromJson to handle the case of parameter being
-// defined as a JSON string like this:
-// "prop":"..."
-std::unique_ptr<PropType> PropFromJsonString(const base::Value& value,
- const PropType* base_schema,
- ErrorPtr* error) {
- std::string type_name;
- CHECK(value.GetAsString(&type_name)) << "Unable to get string value";
- std::unique_ptr<PropType> prop = CreatePropType(type_name, error);
- base::DictionaryValue empty;
- if (prop && !prop->FromJson(&empty, base_schema, error))
- prop.reset();
-
- return prop;
-}
-
-// Detects a type based on JSON array. Inspects the first element of the array
-// to deduce the PropType from. Returns the string name of the type detected
-// or empty string is type detection failed.
-std::string DetectArrayType(const base::ListValue* list,
- const PropType* base_schema,
- bool allow_arrays) {
- std::string type_name;
- if (base_schema) {
- type_name = base_schema->GetTypeAsString();
- } else if (list->GetSize() > 0) {
- const base::Value* first_element = nullptr;
- if (list->Get(0, &first_element)) {
- switch (first_element->GetType()) {
- case base::Value::TYPE_BOOLEAN:
- type_name = PropType::GetTypeStringFromType(ValueType::Boolean);
- break;
- case base::Value::TYPE_INTEGER:
- type_name = PropType::GetTypeStringFromType(ValueType::Int);
- break;
- case base::Value::TYPE_DOUBLE:
- type_name = PropType::GetTypeStringFromType(ValueType::Double);
- break;
- case base::Value::TYPE_STRING:
- type_name = PropType::GetTypeStringFromType(ValueType::String);
- break;
- case base::Value::TYPE_DICTIONARY:
- type_name = PropType::GetTypeStringFromType(ValueType::Object);
- break;
- case base::Value::TYPE_LIST: {
- if (allow_arrays) {
- type_name = PropType::GetTypeStringFromType(ValueType::Array);
- const base::ListValue* first_element_list = nullptr;
- if (first_element->GetAsList(&first_element_list)) {
- // We do not allow arrays of arrays.
- auto child_type =
- DetectArrayType(first_element_list, nullptr, false);
- if (child_type.empty()) {
- type_name.clear();
- } else {
- type_name += '.' + child_type;
- }
- }
- }
- break;
- }
- default:
- // The rest are unsupported.
- break;
- }
- }
- }
- return type_name;
-}
-
-// Helper function for PropFromJson to handle the case of parameter being
-// defined as a JSON array like this:
-// "prop":[...]
-std::unique_ptr<PropType> PropFromJsonArray(const base::Value& value,
- const PropType* base_schema,
- ErrorPtr* error) {
- std::unique_ptr<PropType> prop;
- const base::ListValue* list = nullptr;
- CHECK(value.GetAsList(&list)) << "Unable to get array value";
- std::string type_name = DetectArrayType(list, base_schema, true);
- if (type_name.empty()) {
- ErrorInvalidTypeInfo(error);
- return prop;
- }
- base::DictionaryValue array_object;
- array_object.SetWithoutPathExpansion(commands::attributes::kOneOf_Enum,
- list->DeepCopy());
- prop = CreatePropType(type_name, error);
- if (prop && !prop->FromJson(&array_object, base_schema, error))
- prop.reset();
-
- return prop;
-}
-
-// Detects a type based on JSON object definition of type. Looks at various
-// members such as minimum/maximum constraints, default and enum values to
-// try to deduce the underlying type of the element. Returns the string name of
-// the type detected or empty string is type detection failed.
-std::string DetectObjectType(const base::DictionaryValue* dict,
- const PropType* base_schema) {
- bool has_min_max = dict->HasKey(commands::attributes::kNumeric_Min) ||
- dict->HasKey(commands::attributes::kNumeric_Max);
-
- // Here we are trying to "detect the type and read in the object based on
- // the deduced type". Later, we'll verify that this detected type matches
- // the expectation of the base schema, if applicable, to make sure we are not
- // changing the expected type. This makes the vendor-side (re)definition of
- // standard and custom commands behave exactly the same.
- // The only problem with this approach was the double-vs-int types.
- // If the type is meant to be a double we want to allow its definition as
- // "min:0, max:0" instead of just forcing it to be only "min:0.0, max:0.0".
- // If we have "minimum" or "maximum", and we have a Double schema object,
- // treat this object as a Double (even if both min and max are integers).
- if (has_min_max && base_schema && base_schema->GetType() == ValueType::Double)
- return PropType::GetTypeStringFromType(ValueType::Double);
-
- // If we have at least one "minimum" or "maximum" that is Double,
- // it's a Double.
- const base::Value* value = nullptr;
- if (dict->Get(commands::attributes::kNumeric_Min, &value) &&
- value->IsType(base::Value::TYPE_DOUBLE))
- return PropType::GetTypeStringFromType(ValueType::Double);
- if (dict->Get(commands::attributes::kNumeric_Max, &value) &&
- value->IsType(base::Value::TYPE_DOUBLE))
- return PropType::GetTypeStringFromType(ValueType::Double);
-
- // If we have "minimum" or "maximum", it's an Integer.
- if (has_min_max)
- return PropType::GetTypeStringFromType(ValueType::Int);
-
- // If we have "minLength" or "maxLength", it's a String.
- if (dict->HasKey(commands::attributes::kString_MinLength) ||
- dict->HasKey(commands::attributes::kString_MaxLength))
- return PropType::GetTypeStringFromType(ValueType::String);
-
- // If we have "properties", it's an object.
- if (dict->HasKey(commands::attributes::kObject_Properties))
- return PropType::GetTypeStringFromType(ValueType::Object);
-
- // If we have "items", it's an array.
- if (dict->HasKey(commands::attributes::kItems))
- return PropType::GetTypeStringFromType(ValueType::Array);
-
- // If we have "enum", it's an array. Detect type from array elements.
- const base::ListValue* list = nullptr;
- if (dict->GetListWithoutPathExpansion(commands::attributes::kOneOf_Enum,
- &list))
- return DetectArrayType(list, base_schema, true);
-
- // If we have "default", try to use it for type detection.
- if (dict->Get(commands::attributes::kDefault, &value)) {
- if (value->IsType(base::Value::TYPE_DOUBLE))
- return PropType::GetTypeStringFromType(ValueType::Double);
- if (value->IsType(base::Value::TYPE_INTEGER))
- return PropType::GetTypeStringFromType(ValueType::Int);
- if (value->IsType(base::Value::TYPE_BOOLEAN))
- return PropType::GetTypeStringFromType(ValueType::Boolean);
- if (value->IsType(base::Value::TYPE_STRING))
- return PropType::GetTypeStringFromType(ValueType::String);
- if (value->IsType(base::Value::TYPE_LIST)) {
- CHECK(value->GetAsList(&list)) << "List value expected";
- std::string child_type = DetectArrayType(list, base_schema, false);
- if (!child_type.empty()) {
- return PropType::GetTypeStringFromType(ValueType::Array) + '.' +
- child_type;
- }
- }
- }
-
- return std::string{};
-}
-
-// Helper function for PropFromJson to handle the case of parameter being
-// defined as a JSON object like this:
-// "prop":{...}
-std::unique_ptr<PropType> PropFromJsonObject(const base::Value& value,
- const PropType* base_schema,
- ErrorPtr* error) {
- std::unique_ptr<PropType> prop;
- const base::DictionaryValue* dict = nullptr;
- CHECK(value.GetAsDictionary(&dict)) << "Unable to get dictionary value";
- std::string type_name;
- if (dict->HasKey(commands::attributes::kType)) {
- if (!dict->GetString(commands::attributes::kType, &type_name)) {
- ErrorInvalidTypeInfo(error);
- return prop;
- }
- } else {
- type_name = DetectObjectType(dict, base_schema);
- }
- if (type_name.empty()) {
- if (!base_schema) {
- ErrorInvalidTypeInfo(error);
- return prop;
- }
- type_name = base_schema->GetTypeAsString();
- }
- prop = CreatePropType(type_name, error);
- if (prop && !prop->FromJson(dict, base_schema, error))
- prop.reset();
-
- return prop;
-}
-
-const EnumToStringMap<base::Value::Type>::Map kMap[] = {
- {base::Value::TYPE_NULL, "Null"},
- {base::Value::TYPE_BOOLEAN, "Boolean"},
- {base::Value::TYPE_INTEGER, "Integer"},
- {base::Value::TYPE_DOUBLE, "Double"},
- {base::Value::TYPE_STRING, "String"},
- {base::Value::TYPE_BINARY, "Binary"},
- {base::Value::TYPE_DICTIONARY, "Object"},
- {base::Value::TYPE_LIST, "Array"},
-};
-
-} // anonymous namespace
-
-template <>
-EnumToStringMap<base::Value::Type>::EnumToStringMap() : EnumToStringMap(kMap) {}
-
-ObjectSchema::ObjectSchema() {}
-ObjectSchema::~ObjectSchema() {}
-
-std::unique_ptr<ObjectSchema> ObjectSchema::Clone() const {
- std::unique_ptr<ObjectSchema> cloned{new ObjectSchema};
- for (const auto& pair : properties_) {
- cloned->properties_.insert(
- std::make_pair(pair.first, pair.second->Clone()));
- }
- cloned->extra_properties_allowed_ = extra_properties_allowed_;
- return cloned;
-}
-
-void ObjectSchema::AddProp(const std::string& name,
- std::unique_ptr<PropType> prop) {
- // Not using emplace() here to make sure we override existing properties.
- properties_[name] = std::move(prop);
-}
-
-const PropType* ObjectSchema::GetProp(const std::string& name) const {
- auto p = properties_.find(name);
- return p != properties_.end() ? p->second.get() : nullptr;
-}
-
-bool ObjectSchema::MarkPropRequired(const std::string& name, ErrorPtr* error) {
- auto p = properties_.find(name);
- if (p == properties_.end()) {
- Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kUnknownProperty,
- "Unknown property '%s'", name.c_str());
- return false;
- }
- p->second->MakeRequired(true);
- return true;
-}
-
-std::unique_ptr<base::DictionaryValue> ObjectSchema::ToJson(
- bool full_schema,
- bool in_command_def) const {
- std::unique_ptr<base::DictionaryValue> value(new base::DictionaryValue);
- for (const auto& pair : properties_) {
- auto prop_def = pair.second->ToJson(full_schema, in_command_def);
- CHECK(prop_def);
- value->SetWithoutPathExpansion(pair.first, prop_def.release());
- }
- return value;
-}
-
-bool ObjectSchema::FromJson(const base::DictionaryValue* value,
- const ObjectSchema* object_schema,
- ErrorPtr* error) {
- Properties properties;
- base::DictionaryValue::Iterator iter(*value);
- while (!iter.IsAtEnd()) {
- std::string name = iter.key();
- const PropType* base_schema =
- object_schema ? object_schema->GetProp(iter.key()) : nullptr;
- auto prop_type = PropFromJson(iter.value(), base_schema, error);
- if (prop_type) {
- properties.insert(std::make_pair(iter.key(), std::move(prop_type)));
- } else {
- Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kInvalidPropDef,
- "Error in definition of property '%s'",
- iter.key().c_str());
- return false;
- }
- iter.Advance();
- }
- properties_ = std::move(properties);
- return true;
-}
-
-std::unique_ptr<PropType> ObjectSchema::PropFromJson(
- const base::Value& value,
- const PropType* base_schema,
- ErrorPtr* error) {
- if (value.IsType(base::Value::TYPE_STRING)) {
- // A string value is a short-hand object specification and provides
- // the parameter type.
- return PropFromJsonString(value, base_schema, error);
- } else if (value.IsType(base::Value::TYPE_LIST)) {
- // One of the enumerated types.
- return PropFromJsonArray(value, base_schema, error);
- } else if (value.IsType(base::Value::TYPE_DICTIONARY)) {
- // Full parameter definition.
- return PropFromJsonObject(value, base_schema, error);
- }
- Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kUnknownType,
- "Unexpected JSON value type: %s",
- EnumToString(value.GetType()).c_str());
- return nullptr;
-}
-
-std::unique_ptr<ObjectSchema> ObjectSchema::Create() {
- return std::unique_ptr<ObjectSchema>{new ObjectSchema};
-}
-
-} // namespace weave
diff --git a/src/commands/object_schema.h b/src/commands/object_schema.h
deleted file mode 100644
index 504e1dd..0000000
--- a/src/commands/object_schema.h
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2015 The Weave Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef LIBWEAVE_SRC_COMMANDS_OBJECT_SCHEMA_H_
-#define LIBWEAVE_SRC_COMMANDS_OBJECT_SCHEMA_H_
-
-#include <map>
-#include <memory>
-#include <string>
-
-#include <weave/error.h>
-
-namespace base {
-class Value;
-class DictionaryValue;
-} // namespace base
-
-namespace weave {
-
-class PropType;
-
-// ObjectSchema is a class representing an object definition in GCD command
-// schema. This could represent a GCD command definition, but also it can be
-// used when defining custom object types for command properties such as
-// output media type (paper) for print command. The schema definition for
-// these type of object description is the same.
-class ObjectSchema final {
- public:
- // Do not inline the constructor/destructor to allow forward-declared type
- // PropType to be part of |properties_| member.
- ObjectSchema();
- ~ObjectSchema();
-
- // Properties is a string-to-PropType map representing a list of
- // properties defined for a command/object. The key is the parameter
- // name and the value is the parameter type definition object.
- using Properties = std::map<std::string, std::unique_ptr<PropType>>;
-
- // Makes a full copy of this object.
- virtual std::unique_ptr<ObjectSchema> Clone() const;
-
- // Add a new parameter definition.
- void AddProp(const std::string& name, std::unique_ptr<PropType> prop);
-
- // Finds parameter type definition by name. Returns nullptr if not found.
- const PropType* GetProp(const std::string& name) const;
-
- // Gets the list of all the properties defined.
- const Properties& GetProps() const { return properties_; }
-
- // Marks the property with given name as "required". If |name| specifies
- // an unknown property, false is returned and |error| is set with detailed
- // error message for the failure.
- bool MarkPropRequired(const std::string& name, ErrorPtr* error);
-
- // Specify whether extra properties are allowed on objects described by
- // this schema. When validating a value of an object type, we can
- // make sure that the value has only the properties explicitly defined by
- // the schema and no other (custom) properties are allowed.
- // This is to support JSON Schema's "additionalProperties" specification.
- bool GetExtraPropertiesAllowed() const { return extra_properties_allowed_; }
- void SetExtraPropertiesAllowed(bool allowed) {
- extra_properties_allowed_ = allowed;
- }
-
- // Saves the object schema to JSON. When |full_schema| is set to true,
- // then all properties and constraints are saved, otherwise, only
- // the overridden (not inherited) ones are saved.
- std::unique_ptr<base::DictionaryValue> ToJson(bool full_schema,
- bool in_command_def) const;
-
- // Loads the object schema from JSON. If |object_schema| is not nullptr, it is
- // used as a base schema to inherit omitted properties and constraints from.
- bool FromJson(const base::DictionaryValue* value,
- const ObjectSchema* object_schema,
- ErrorPtr* error);
-
- // Helper factory method to create a new instance of ObjectSchema object.
- static std::unique_ptr<ObjectSchema> Create();
-
- // Helper method to load property type definitions from JSON.
- static std::unique_ptr<PropType> PropFromJson(const base::Value& value,
- const PropType* base_schema,
- ErrorPtr* error);
-
- private:
- // Internal parameter type definition map.
- Properties properties_;
- bool extra_properties_allowed_{false};
-};
-
-} // namespace weave
-
-#endif // LIBWEAVE_SRC_COMMANDS_OBJECT_SCHEMA_H_
diff --git a/src/commands/object_schema_unittest.cc b/src/commands/object_schema_unittest.cc
deleted file mode 100644
index 7cdc16d..0000000
--- a/src/commands/object_schema_unittest.cc
+++ /dev/null
@@ -1,1697 +0,0 @@
-// Copyright 2015 The Weave Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/commands/object_schema.h"
-
-#include <algorithm>
-#include <limits>
-#include <memory>
-#include <vector>
-
-#include <base/json/json_reader.h>
-#include <base/json/json_writer.h>
-#include <base/values.h>
-#include <gtest/gtest.h>
-
-#include "src/commands/prop_constraints.h"
-#include "src/commands/prop_types.h"
-#include "src/commands/schema_constants.h"
-#include "src/commands/unittest_utils.h"
-
-namespace weave {
-
-using test::CreateValue;
-using test::CreateDictionaryValue;
-
-namespace {
-
-template <typename T>
-std::vector<T> GetArrayValues(const ValueVector& arr) {
- std::vector<T> values;
- values.reserve(arr.size());
- for (const auto& prop_value : arr) {
- const auto& value = static_cast<const TypedValueBase<T>&>(*prop_value);
- values.push_back(value.GetValue());
- }
- return values;
-}
-
-template <typename T>
-std::vector<T> GetOneOfValues(const PropType* prop_type) {
- auto one_of = static_cast<const ConstraintOneOf*>(
- prop_type->GetConstraint(ConstraintType::OneOf));
- if (!one_of)
- return {};
-
- return GetArrayValues<T>(one_of->set_.value);
-}
-
-bool ValidateValue(const PropType& type,
- const base::Value& value,
- ErrorPtr* error) {
- std::unique_ptr<PropValue> val = type.CreatePropValue(value, error);
- return val != nullptr;
-}
-
-} // anonymous namespace
-
-TEST(CommandSchema, IntPropType_Empty) {
- IntPropType prop;
- EXPECT_TRUE(prop.GetConstraints().empty());
- EXPECT_FALSE(prop.HasOverriddenAttributes());
- EXPECT_FALSE(prop.IsBasedOnSchema());
- EXPECT_EQ(nullptr, prop.GetDefaultValue());
-}
-
-TEST(CommandSchema, IntPropType_Types) {
- IntPropType prop;
- EXPECT_EQ(nullptr, prop.GetBoolean());
- EXPECT_EQ(&prop, prop.GetInt());
- EXPECT_EQ(nullptr, prop.GetDouble());
- EXPECT_EQ(nullptr, prop.GetString());
- EXPECT_EQ(nullptr, prop.GetObject());
- EXPECT_EQ(nullptr, prop.GetArray());
-}
-
-TEST(CommandSchema, IntPropType_ToJson) {
- IntPropType prop;
- EXPECT_JSON_EQ("'integer'", *prop.ToJson(false, false));
- EXPECT_JSON_EQ("{'type':'integer'}", *prop.ToJson(true, false));
- IntPropType param2;
- param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
- EXPECT_JSON_EQ("{}", *param2.ToJson(false, false));
- param2.FromJson(CreateDictionaryValue("{'minimum':3}").get(), &prop, nullptr);
- EXPECT_JSON_EQ("{'minimum':3}", *param2.ToJson(false, false));
- param2.FromJson(CreateDictionaryValue("{'maximum':-7}").get(), &prop,
- nullptr);
- EXPECT_JSON_EQ("{'maximum':-7}", *param2.ToJson(false, false));
- param2.FromJson(CreateDictionaryValue("{'minimum':0,'maximum':5}").get(),
- &prop, nullptr);
- EXPECT_JSON_EQ("{'maximum':5,'minimum':0}", *param2.ToJson(false, false));
- param2.FromJson(CreateDictionaryValue("{'enum':[1,2,3]}").get(), &prop,
- nullptr);
- EXPECT_JSON_EQ("[1,2,3]", *param2.ToJson(false, false));
- param2.FromJson(CreateDictionaryValue("{'default':123}").get(), &prop,
- nullptr);
- EXPECT_JSON_EQ("{'default':123}", *param2.ToJson(false, false));
-}
-
-TEST(CommandSchema, IntPropType_FromJson) {
- IntPropType prop;
- prop.AddMinMaxConstraint(2, 8);
- IntPropType param2;
- param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
- EXPECT_FALSE(param2.HasOverriddenAttributes());
- EXPECT_TRUE(param2.IsBasedOnSchema());
- EXPECT_EQ(2, prop.GetMinValue());
- EXPECT_EQ(8, prop.GetMaxValue());
- prop.AddMinMaxConstraint(-2, 30);
- param2.FromJson(CreateDictionaryValue("{'minimum':7}").get(), &prop, nullptr);
- EXPECT_TRUE(param2.HasOverriddenAttributes());
- EXPECT_TRUE(param2.IsBasedOnSchema());
- EXPECT_EQ(7, param2.GetMinValue());
- EXPECT_EQ(30, param2.GetMaxValue());
- param2.FromJson(CreateDictionaryValue("{'maximum':17}").get(), &prop,
- nullptr);
- EXPECT_TRUE(param2.HasOverriddenAttributes());
- EXPECT_TRUE(param2.IsBasedOnSchema());
- EXPECT_EQ(-2, param2.GetMinValue());
- EXPECT_EQ(17, param2.GetMaxValue());
-
- ASSERT_TRUE(param2.FromJson(CreateDictionaryValue("{'default':3}").get(),
- &prop, nullptr));
- EXPECT_TRUE(param2.HasOverriddenAttributes());
- ASSERT_NE(nullptr, param2.GetDefaultValue());
- EXPECT_EQ(3, param2.GetDefaultValue()->GetInt()->GetValue());
-}
-
-TEST(CommandSchema, IntPropType_Validate) {
- IntPropType prop;
- prop.AddMinMaxConstraint(2, 4);
- ErrorPtr error;
- EXPECT_FALSE(ValidateValue(prop, *CreateValue("-1"), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
- EXPECT_FALSE(ValidateValue(prop, *CreateValue("0"), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
- EXPECT_FALSE(ValidateValue(prop, *CreateValue("1"), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
- EXPECT_TRUE(ValidateValue(prop, *CreateValue("2"), &error));
- EXPECT_EQ(nullptr, error.get());
- EXPECT_TRUE(ValidateValue(prop, *CreateValue("3"), &error));
- EXPECT_EQ(nullptr, error.get());
- EXPECT_TRUE(ValidateValue(prop, *CreateValue("4"), &error));
- EXPECT_EQ(nullptr, error.get());
- EXPECT_FALSE(ValidateValue(prop, *CreateValue("5"), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
- EXPECT_FALSE(ValidateValue(prop, *CreateValue("true"), &error));
- EXPECT_EQ("type_mismatch", error->GetCode());
- error.reset();
- EXPECT_FALSE(ValidateValue(prop, *CreateValue("3.0"), &error));
- EXPECT_EQ("type_mismatch", error->GetCode());
- error.reset();
- EXPECT_FALSE(ValidateValue(prop, *CreateValue("'3'"), &error));
- EXPECT_EQ("type_mismatch", error->GetCode());
-}
-
-TEST(CommandSchema, IntPropType_CreateValue) {
- IntPropType prop;
- ErrorPtr error;
- auto val = prop.CreateValue(base::FundamentalValue{2}, &error);
- ASSERT_NE(nullptr, val.get());
- EXPECT_EQ(nullptr, error.get());
- EXPECT_EQ(2, val->GetValue());
-
- val = prop.CreateValue(base::StringValue{"blah"}, &error);
- EXPECT_EQ(nullptr, val.get());
- ASSERT_NE(nullptr, error.get());
- EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-TEST(CommandSchema, BoolPropType_Empty) {
- BooleanPropType prop;
- EXPECT_TRUE(prop.GetConstraints().empty());
- EXPECT_FALSE(prop.HasOverriddenAttributes());
- EXPECT_FALSE(prop.IsBasedOnSchema());
- EXPECT_EQ(nullptr, prop.GetDefaultValue());
- EXPECT_FALSE(prop.IsRequired());
-}
-
-TEST(CommandSchema, BoolPropType_Types) {
- BooleanPropType prop;
- EXPECT_EQ(nullptr, prop.GetInt());
- EXPECT_EQ(&prop, prop.GetBoolean());
- EXPECT_EQ(nullptr, prop.GetDouble());
- EXPECT_EQ(nullptr, prop.GetString());
- EXPECT_EQ(nullptr, prop.GetObject());
- EXPECT_EQ(nullptr, prop.GetArray());
-}
-
-TEST(CommandSchema, BoolPropType_ToJson) {
- BooleanPropType prop;
- EXPECT_JSON_EQ("'boolean'", *prop.ToJson(false, false));
- EXPECT_JSON_EQ("{'type':'boolean'}", *prop.ToJson(true, false));
- BooleanPropType param2;
- param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
- EXPECT_JSON_EQ("{}", *param2.ToJson(false, false));
- param2.FromJson(CreateDictionaryValue("{'enum':[true,false]}").get(), &prop,
- nullptr);
- EXPECT_JSON_EQ("[true,false]", *param2.ToJson(false, false));
- EXPECT_JSON_EQ("{'enum':[true,false],'type':'boolean'}",
- *param2.ToJson(true, false));
- param2.FromJson(CreateDictionaryValue("{'default':true}").get(), &prop,
- nullptr);
- EXPECT_JSON_EQ("{'default':true}", *param2.ToJson(false, false));
-}
-
-TEST(CommandSchema, BoolPropType_FromJson) {
- BooleanPropType prop;
- prop.FromJson(CreateDictionaryValue("{'enum':[true]}").get(), &prop, nullptr);
- BooleanPropType param2;
- param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
- EXPECT_FALSE(param2.HasOverriddenAttributes());
- EXPECT_TRUE(param2.IsBasedOnSchema());
- EXPECT_EQ(std::vector<bool>{true}, GetOneOfValues<bool>(&prop));
-
- BooleanPropType prop_base;
- BooleanPropType param3;
- ASSERT_TRUE(param3.FromJson(CreateDictionaryValue("{'default':false}").get(),
- &prop_base, nullptr));
- EXPECT_TRUE(param3.HasOverriddenAttributes());
- ASSERT_NE(nullptr, param3.GetDefaultValue());
- EXPECT_FALSE(param3.GetDefaultValue()->GetBoolean()->GetValue());
-}
-
-TEST(CommandSchema, BoolPropType_Validate) {
- BooleanPropType prop;
- prop.FromJson(CreateDictionaryValue("{'enum':[true]}").get(), &prop, nullptr);
- ErrorPtr error;
- EXPECT_FALSE(ValidateValue(prop, *CreateValue("false"), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
- EXPECT_TRUE(ValidateValue(prop, *CreateValue("true"), &error));
- error.reset();
- EXPECT_FALSE(ValidateValue(prop, *CreateValue("1"), &error));
- EXPECT_EQ("type_mismatch", error->GetCode());
- error.reset();
- EXPECT_FALSE(ValidateValue(prop, *CreateValue("3.0"), &error));
- EXPECT_EQ("type_mismatch", error->GetCode());
- error.reset();
- EXPECT_FALSE(ValidateValue(prop, *CreateValue("'3'"), &error));
- EXPECT_EQ("type_mismatch", error->GetCode());
-}
-
-TEST(CommandSchema, BoolPropType_CreateValue) {
- BooleanPropType prop;
- ErrorPtr error;
- auto val = prop.CreateValue(base::FundamentalValue{true}, &error);
- ASSERT_NE(nullptr, val.get());
- EXPECT_EQ(nullptr, error.get());
- EXPECT_TRUE(val->GetValue());
-
- val = prop.CreateValue(base::StringValue{"blah"}, &error);
- EXPECT_EQ(nullptr, val.get());
- ASSERT_NE(nullptr, error.get());
- EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-TEST(CommandSchema, DoublePropType_Empty) {
- DoublePropType prop;
- EXPECT_DOUBLE_EQ(std::numeric_limits<double>::lowest(), prop.GetMinValue());
- EXPECT_DOUBLE_EQ((std::numeric_limits<double>::max)(), prop.GetMaxValue());
- EXPECT_FALSE(prop.HasOverriddenAttributes());
- EXPECT_FALSE(prop.IsBasedOnSchema());
- EXPECT_EQ(nullptr, prop.GetDefaultValue());
- EXPECT_FALSE(prop.IsRequired());
-}
-
-TEST(CommandSchema, DoublePropType_Types) {
- DoublePropType prop;
- EXPECT_EQ(nullptr, prop.GetInt());
- EXPECT_EQ(nullptr, prop.GetBoolean());
- EXPECT_EQ(&prop, prop.GetDouble());
- EXPECT_EQ(nullptr, prop.GetString());
- EXPECT_EQ(nullptr, prop.GetObject());
- EXPECT_EQ(nullptr, prop.GetArray());
-}
-
-TEST(CommandSchema, DoublePropType_ToJson) {
- DoublePropType prop;
- EXPECT_JSON_EQ("'number'", *prop.ToJson(false, false));
- EXPECT_JSON_EQ("{'type':'number'}", *prop.ToJson(true, false));
- DoublePropType param2;
- param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
- EXPECT_JSON_EQ("{}", *param2.ToJson(false, false));
- param2.FromJson(CreateDictionaryValue("{'minimum':3}").get(), &prop, nullptr);
- EXPECT_JSON_EQ("{'minimum':3.0}", *param2.ToJson(false, false));
- param2.FromJson(CreateDictionaryValue("{'maximum':-7}").get(), &prop,
- nullptr);
- EXPECT_JSON_EQ("{'maximum':-7.0}", *param2.ToJson(false, false));
- param2.FromJson(CreateDictionaryValue("{'minimum':0,'maximum':5}").get(),
- &prop, nullptr);
- EXPECT_JSON_EQ("{'maximum':5.0,'minimum':0.0}", *param2.ToJson(false, false));
- param2.FromJson(CreateDictionaryValue("{'default':12.3}").get(), &prop,
- nullptr);
- EXPECT_JSON_EQ("{'default':12.3}", *param2.ToJson(false, false));
-}
-
-TEST(CommandSchema, DoublePropType_FromJson) {
- DoublePropType prop;
- prop.AddMinMaxConstraint(2.5, 8.7);
- DoublePropType param2;
- param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
- EXPECT_FALSE(param2.HasOverriddenAttributes());
- EXPECT_TRUE(param2.IsBasedOnSchema());
- EXPECT_DOUBLE_EQ(2.5, prop.GetMinValue());
- EXPECT_DOUBLE_EQ(8.7, prop.GetMaxValue());
- prop.AddMinMaxConstraint(-2.2, 30.4);
- param2.FromJson(CreateDictionaryValue("{'minimum':7}").get(), &prop, nullptr);
- EXPECT_TRUE(param2.HasOverriddenAttributes());
- EXPECT_TRUE(param2.IsBasedOnSchema());
- EXPECT_DOUBLE_EQ(7.0, param2.GetMinValue());
- EXPECT_DOUBLE_EQ(30.4, param2.GetMaxValue());
- param2.FromJson(CreateDictionaryValue("{'maximum':17.2}").get(), &prop,
- nullptr);
- EXPECT_TRUE(param2.HasOverriddenAttributes());
- EXPECT_TRUE(param2.IsBasedOnSchema());
- EXPECT_DOUBLE_EQ(-2.2, param2.GetMinValue());
- EXPECT_DOUBLE_EQ(17.2, param2.GetMaxValue());
- param2.FromJson(CreateDictionaryValue("{'minimum':0,'maximum':6.1}").get(),
- &prop, nullptr);
- EXPECT_TRUE(param2.HasOverriddenAttributes());
- EXPECT_TRUE(param2.IsBasedOnSchema());
- EXPECT_DOUBLE_EQ(0.0, param2.GetMinValue());
- EXPECT_DOUBLE_EQ(6.1, param2.GetMaxValue());
-
- ASSERT_TRUE(param2.FromJson(CreateDictionaryValue("{'default':-1.234}").get(),
- &prop, nullptr));
- EXPECT_TRUE(param2.HasOverriddenAttributes());
- ASSERT_NE(nullptr, param2.GetDefaultValue());
- EXPECT_DOUBLE_EQ(-1.234, param2.GetDefaultValue()->GetDouble()->GetValue());
-}
-
-TEST(CommandSchema, DoublePropType_Validate) {
- DoublePropType prop;
- prop.AddMinMaxConstraint(-1.2, 1.3);
- ErrorPtr error;
- EXPECT_FALSE(ValidateValue(prop, *CreateValue("-2"), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
- EXPECT_FALSE(ValidateValue(prop, *CreateValue("-1.3"), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
- EXPECT_TRUE(ValidateValue(prop, *CreateValue("-1.2"), &error));
- EXPECT_EQ(nullptr, error.get());
- EXPECT_TRUE(ValidateValue(prop, *CreateValue("0.0"), &error));
- EXPECT_EQ(nullptr, error.get());
- EXPECT_TRUE(ValidateValue(prop, *CreateValue("1.3"), &error));
- EXPECT_EQ(nullptr, error.get());
- EXPECT_FALSE(ValidateValue(prop, *CreateValue("1.31"), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
- EXPECT_FALSE(ValidateValue(prop, *CreateValue("true"), &error));
- EXPECT_EQ("type_mismatch", error->GetCode());
- error.reset();
- EXPECT_FALSE(ValidateValue(prop, *CreateValue("'0.0'"), &error));
- EXPECT_EQ("type_mismatch", error->GetCode());
-}
-
-TEST(CommandSchema, DoublePropType_CreateValue) {
- DoublePropType prop;
- ErrorPtr error;
- auto val = prop.CreateValue(base::FundamentalValue{2.0}, &error);
- ASSERT_NE(nullptr, val.get());
- EXPECT_EQ(nullptr, error.get());
- EXPECT_DOUBLE_EQ(2.0, val->GetValue());
-
- val = prop.CreateValue(base::StringValue{"blah"}, &error);
- EXPECT_EQ(nullptr, val.get());
- ASSERT_NE(nullptr, error.get());
- EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-TEST(CommandSchema, StringPropType_Empty) {
- StringPropType prop;
- EXPECT_EQ(0, prop.GetMinLength());
- EXPECT_EQ((std::numeric_limits<int>::max)(), prop.GetMaxLength());
- EXPECT_FALSE(prop.HasOverriddenAttributes());
- EXPECT_FALSE(prop.IsBasedOnSchema());
- EXPECT_EQ(nullptr, prop.GetDefaultValue());
- EXPECT_FALSE(prop.IsRequired());
-}
-
-TEST(CommandSchema, StringPropType_Types) {
- StringPropType prop;
- EXPECT_EQ(nullptr, prop.GetInt());
- EXPECT_EQ(nullptr, prop.GetBoolean());
- EXPECT_EQ(nullptr, prop.GetDouble());
- EXPECT_EQ(&prop, prop.GetString());
- EXPECT_EQ(nullptr, prop.GetObject());
- EXPECT_EQ(nullptr, prop.GetArray());
-}
-
-TEST(CommandSchema, StringPropType_ToJson) {
- StringPropType prop;
- EXPECT_JSON_EQ("'string'", *prop.ToJson(false, false));
- EXPECT_JSON_EQ("{'type':'string'}", *prop.ToJson(true, false));
- StringPropType param2;
- param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
- EXPECT_JSON_EQ("{}", *param2.ToJson(false, false));
- param2.FromJson(CreateDictionaryValue("{'minLength':3}").get(), &prop,
- nullptr);
- EXPECT_JSON_EQ("{'minLength':3}", *param2.ToJson(false, false));
- param2.FromJson(CreateDictionaryValue("{'maxLength':7}").get(), &prop,
- nullptr);
- EXPECT_JSON_EQ("{'maxLength':7}", *param2.ToJson(false, false));
- param2.FromJson(CreateDictionaryValue("{'minLength':0,'maxLength':5}").get(),
- &prop, nullptr);
- EXPECT_JSON_EQ("{'maxLength':5,'minLength':0}", *param2.ToJson(false, false));
- param2.FromJson(CreateDictionaryValue("{'default':'abcd'}").get(), &prop,
- nullptr);
- EXPECT_JSON_EQ("{'default':'abcd'}", *param2.ToJson(false, false));
-}
-
-TEST(CommandSchema, StringPropType_FromJson) {
- StringPropType prop;
- prop.AddLengthConstraint(2, 8);
- StringPropType param2;
- param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
- EXPECT_FALSE(param2.HasOverriddenAttributes());
- EXPECT_TRUE(param2.IsBasedOnSchema());
- EXPECT_EQ(2, prop.GetMinLength());
- EXPECT_EQ(8, prop.GetMaxLength());
- prop.AddLengthConstraint(3, 5);
- param2.FromJson(CreateDictionaryValue("{'minLength':4}").get(), &prop,
- nullptr);
- EXPECT_TRUE(param2.HasOverriddenAttributes());
- EXPECT_TRUE(param2.IsBasedOnSchema());
- EXPECT_EQ(4, param2.GetMinLength());
- EXPECT_EQ(5, param2.GetMaxLength());
- param2.FromJson(CreateDictionaryValue("{'maxLength':8}").get(), &prop,
- nullptr);
- EXPECT_TRUE(param2.HasOverriddenAttributes());
- EXPECT_TRUE(param2.IsBasedOnSchema());
- EXPECT_EQ(3, param2.GetMinLength());
- EXPECT_EQ(8, param2.GetMaxLength());
- param2.FromJson(CreateDictionaryValue("{'minLength':1,'maxLength':7}").get(),
- &prop, nullptr);
- EXPECT_TRUE(param2.HasOverriddenAttributes());
- EXPECT_TRUE(param2.IsBasedOnSchema());
- EXPECT_EQ(1, param2.GetMinLength());
- EXPECT_EQ(7, param2.GetMaxLength());
-
- ASSERT_TRUE(param2.FromJson(CreateDictionaryValue("{'default':'foo'}").get(),
- &prop, nullptr));
- EXPECT_TRUE(param2.HasOverriddenAttributes());
- ASSERT_NE(nullptr, param2.GetDefaultValue());
- EXPECT_EQ("foo", param2.GetDefaultValue()->GetString()->GetValue());
-}
-
-TEST(CommandSchema, StringPropType_Validate) {
- StringPropType prop;
- prop.AddLengthConstraint(1, 3);
- ErrorPtr error;
- EXPECT_FALSE(ValidateValue(prop, *CreateValue("''"), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
- prop.AddLengthConstraint(2, 3);
- EXPECT_FALSE(ValidateValue(prop, *CreateValue("''"), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
- EXPECT_FALSE(ValidateValue(prop, *CreateValue("'a'"), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
- EXPECT_TRUE(ValidateValue(prop, *CreateValue("'ab'"), &error));
- EXPECT_EQ(nullptr, error.get());
- EXPECT_TRUE(ValidateValue(prop, *CreateValue("'abc'"), &error));
- EXPECT_EQ(nullptr, error.get());
- EXPECT_FALSE(ValidateValue(prop, *CreateValue("'abcd'"), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
-
- prop.FromJson(CreateDictionaryValue("{'enum':['abc','def','xyz!!']}").get(),
- nullptr, &error);
- EXPECT_TRUE(ValidateValue(prop, *CreateValue("'abc'"), &error));
- EXPECT_TRUE(ValidateValue(prop, *CreateValue("'def'"), &error));
- EXPECT_TRUE(ValidateValue(prop, *CreateValue("'xyz!!'"), &error));
- EXPECT_FALSE(ValidateValue(prop, *CreateValue("'xyz'"), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
-}
-
-TEST(CommandSchema, StringPropType_CreateValue) {
- StringPropType prop;
- ErrorPtr error;
- auto val = prop.CreateValue(base::StringValue{"blah"}, &error);
- ASSERT_NE(nullptr, val.get());
- EXPECT_EQ(nullptr, error.get());
- EXPECT_EQ("blah", val->GetValue());
-
- val = prop.CreateValue(base::FundamentalValue{4}, &error);
- EXPECT_EQ(nullptr, val.get());
- ASSERT_NE(nullptr, error.get());
- EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-TEST(CommandSchema, ObjectPropType_Empty) {
- ObjectPropType prop;
- EXPECT_TRUE(prop.HasOverriddenAttributes());
- EXPECT_FALSE(prop.IsBasedOnSchema());
- EXPECT_EQ(nullptr, prop.GetDefaultValue());
- EXPECT_FALSE(prop.IsRequired());
-}
-
-TEST(CommandSchema, ObjectPropType_Types) {
- ObjectPropType prop;
- EXPECT_EQ(nullptr, prop.GetInt());
- EXPECT_EQ(nullptr, prop.GetBoolean());
- EXPECT_EQ(nullptr, prop.GetDouble());
- EXPECT_EQ(nullptr, prop.GetString());
- EXPECT_EQ(&prop, prop.GetObject());
- EXPECT_EQ(nullptr, prop.GetArray());
-}
-
-TEST(CommandSchema, ObjectPropType_ToJson) {
- ObjectPropType prop;
- EXPECT_JSON_EQ("{'additionalProperties':false,'properties':{}}",
- *prop.ToJson(false, false));
- EXPECT_JSON_EQ(
- "{'additionalProperties':false,'properties':{},'type':'object'}",
- *prop.ToJson(true, false));
- EXPECT_FALSE(prop.IsBasedOnSchema());
- ObjectPropType prop2;
- prop2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
- EXPECT_JSON_EQ("{}", *prop2.ToJson(false, false));
- EXPECT_TRUE(prop2.IsBasedOnSchema());
-
- auto schema = ObjectSchema::Create();
- schema->AddProp("expires", PropType::Create(ValueType::Int));
- auto pw = PropType::Create(ValueType::String);
- pw->GetString()->AddLengthConstraint(6, 100);
- schema->AddProp("password", std::move(pw));
- prop2.SetObjectSchema(std::move(schema));
- auto expected = R"({
- 'additionalProperties': false,
- 'properties': {
- 'expires': 'integer',
- 'password': {
- 'maxLength': 100,
- 'minLength': 6
- }
- }
- })";
- EXPECT_JSON_EQ(expected, *prop2.ToJson(false, false));
-
- expected = R"({
- 'additionalProperties': false,
- 'properties': {
- 'expires': {
- 'type': 'integer'
- },
- 'password': {
- 'maxLength': 100,
- 'minLength': 6,
- 'type': 'string'
- }
- },
- 'type': 'object'
- })";
- EXPECT_JSON_EQ(expected, *prop2.ToJson(true, false));
-
- ObjectPropType prop3;
- ASSERT_TRUE(
- prop3.FromJson(CreateDictionaryValue(
- "{'default':{'expires':3,'password':'abracadabra'}}")
- .get(),
- &prop2, nullptr));
- expected = R"({
- 'default': {
- 'expires': 3,
- 'password': 'abracadabra'
- }
- })";
- EXPECT_JSON_EQ(expected, *prop3.ToJson(false, false));
-
- expected = R"({
- 'additionalProperties': false,
- 'default': {
- 'expires': 3,
- 'password': 'abracadabra'
- },
- 'properties': {
- 'expires': {
- 'type': 'integer'
- },
- 'password': {
- 'maxLength': 100,
- 'minLength': 6,
- 'type': 'string'
- }
- },
- 'type': 'object'
- })";
- EXPECT_JSON_EQ(expected, *prop3.ToJson(true, false));
-
- ObjectPropType prop4;
- ASSERT_TRUE(prop4.FromJson(
- CreateDictionaryValue("{'additionalProperties':true,"
- "'default':{'expires':3,'password':'abracadabra'}}")
- .get(),
- &prop2, nullptr));
- expected = R"({
- 'additionalProperties': true,
- 'default': {
- 'expires': 3,
- 'password': 'abracadabra'
- },
- 'properties': {
- 'expires': 'integer',
- 'password': {
- 'maxLength': 100,
- 'minLength': 6
- }
- }
- })";
- EXPECT_JSON_EQ(expected, *prop4.ToJson(false, false));
-
- expected = R"({
- 'additionalProperties': true,
- 'default': {
- 'expires': 3,
- 'password': 'abracadabra'
- },
- 'properties': {
- 'expires': {
- 'type': 'integer'
- },
- 'password': {
- 'maxLength': 100,
- 'minLength': 6,
- 'type': 'string'
- }
- },
- 'type': 'object'
- })";
- EXPECT_JSON_EQ(expected, *prop4.ToJson(true, false));
-}
-
-TEST(CommandSchema, ObjectPropType_FromJson) {
- ObjectPropType base_prop;
- EXPECT_TRUE(base_prop.FromJson(
- CreateDictionaryValue("{'properties':{'name':'string','age':'integer'}}")
- .get(),
- nullptr, nullptr));
- auto schema = base_prop.GetObject()->GetObjectSchemaPtr();
- const PropType* prop = schema->GetProp("name");
- EXPECT_EQ(ValueType::String, prop->GetType());
- prop = schema->GetProp("age");
- EXPECT_EQ(ValueType::Int, prop->GetType());
-
- ObjectPropType prop2;
- ASSERT_TRUE(prop2.FromJson(
- CreateDictionaryValue("{'properties':{'name':'string','age':'integer'},"
- "'default':{'name':'Bob','age':33}}")
- .get(),
- nullptr, nullptr));
- ASSERT_NE(nullptr, prop2.GetDefaultValue());
- const ObjectValue* defval = prop2.GetDefaultValue()->GetObject();
- ASSERT_NE(nullptr, defval);
- ValueMap objval = defval->GetValue();
- EXPECT_EQ("Bob", objval["name"]->GetString()->GetValue());
- EXPECT_EQ(33, objval["age"]->GetInt()->GetValue());
-}
-
-TEST(CommandSchema, ObjectPropType_Validate) {
- ObjectPropType prop;
- prop.FromJson(
- CreateDictionaryValue("{'properties':{'expires':'integer',"
- "'password':{'maxLength':100,'minLength':6}},"
- "'required':['expires','password']}")
- .get(),
- nullptr, nullptr);
- ErrorPtr error;
- EXPECT_TRUE(ValidateValue(
- prop, *CreateValue("{'expires':10,'password':'abcdef'}"), &error));
- error.reset();
-
- EXPECT_FALSE(ValidateValue(prop, *CreateValue("{'expires':10}"), &error));
- EXPECT_EQ("parameter_missing", error->GetCode());
- error.reset();
-
- EXPECT_FALSE(
- ValidateValue(prop, *CreateValue("{'password':'abcdef'}"), &error));
- EXPECT_EQ("parameter_missing", error->GetCode());
- error.reset();
-
- EXPECT_FALSE(ValidateValue(
- prop, *CreateValue("{'expires':10,'password':'abcde'}"), &error));
- EXPECT_EQ("out_of_range", error->GetFirstError()->GetCode());
- error.reset();
-
- EXPECT_FALSE(ValidateValue(prop, *CreateValue("2"), &error));
- EXPECT_EQ("type_mismatch", error->GetCode());
- error.reset();
-
- EXPECT_FALSE(ValidateValue(
- prop, *CreateValue("{'expires':10,'password':'abcdef','retry':true}"),
- &error));
- EXPECT_EQ("unexpected_parameter", error->GetCode());
- error.reset();
-}
-
-TEST(CommandSchema, ObjectPropType_Validate_Enum) {
- ObjectPropType prop;
- EXPECT_TRUE(prop.FromJson(
- CreateDictionaryValue(
- "{'properties':{'width':'integer','height':'integer'},"
- "'enum':[{'width':10,'height':20},{'width':100,'height':200}]}")
- .get(),
- nullptr, nullptr));
- ErrorPtr error;
- EXPECT_TRUE(
- ValidateValue(prop, *CreateValue("{'height':20,'width':10}"), &error));
- error.reset();
-
- EXPECT_TRUE(
- ValidateValue(prop, *CreateValue("{'height':200,'width':100}"), &error));
- error.reset();
-
- EXPECT_FALSE(
- ValidateValue(prop, *CreateValue("{'height':12,'width':10}"), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
-}
-
-TEST(CommandSchema, ObjectPropType_CreateValue) {
- ObjectPropType prop;
- IntPropType int_type;
- ASSERT_TRUE(prop.FromJson(
- CreateDictionaryValue(
- "{'properties':{'width':'integer','height':'integer'},"
- "'enum':[{'width':10,'height':20},{'width':100,'height':200}]}")
- .get(),
- nullptr, nullptr));
- ValueMap obj{
- {"width", int_type.CreateValue(base::FundamentalValue{10}, nullptr)},
- {"height", int_type.CreateValue(base::FundamentalValue{20}, nullptr)},
- };
-
- ErrorPtr error;
- auto val = prop.CreateValue(
- *CreateDictionaryValue("{'width': 10, 'height': 20}"), &error);
- ASSERT_NE(nullptr, val.get());
- EXPECT_EQ(nullptr, error.get());
- EXPECT_EQ(obj, val->GetValue());
-
- val = prop.CreateValue(base::StringValue{"blah"}, &error);
- EXPECT_EQ(nullptr, val.get());
- ASSERT_NE(nullptr, error.get());
- EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-TEST(CommandSchema, ArrayPropType_Empty) {
- ArrayPropType prop;
- EXPECT_FALSE(prop.HasOverriddenAttributes());
- EXPECT_FALSE(prop.IsBasedOnSchema());
- EXPECT_EQ(nullptr, prop.GetDefaultValue());
- EXPECT_EQ(nullptr, prop.GetItemTypePtr());
- prop.SetItemType(PropType::Create(ValueType::Int));
- EXPECT_TRUE(prop.HasOverriddenAttributes());
- EXPECT_FALSE(prop.IsBasedOnSchema());
- EXPECT_NE(nullptr, prop.GetItemTypePtr());
- EXPECT_FALSE(prop.IsRequired());
-}
-
-TEST(CommandSchema, ArrayPropType_Types) {
- ArrayPropType prop;
- EXPECT_EQ(nullptr, prop.GetInt());
- EXPECT_EQ(nullptr, prop.GetBoolean());
- EXPECT_EQ(nullptr, prop.GetDouble());
- EXPECT_EQ(nullptr, prop.GetString());
- EXPECT_EQ(nullptr, prop.GetObject());
- EXPECT_EQ(&prop, prop.GetArray());
-}
-
-TEST(CommandSchema, ArrayPropType_ToJson) {
- ArrayPropType prop;
- prop.SetItemType(PropType::Create(ValueType::Int));
- EXPECT_JSON_EQ("{'items':'integer'}", *prop.ToJson(false, false));
- EXPECT_JSON_EQ("{'items':{'type':'integer'},'type':'array'}",
- *prop.ToJson(true, false));
- EXPECT_FALSE(prop.IsBasedOnSchema());
- ArrayPropType prop2;
- prop2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
- EXPECT_JSON_EQ("{}", *prop2.ToJson(false, false));
- EXPECT_TRUE(prop2.IsBasedOnSchema());
- prop2.FromJson(CreateDictionaryValue("{'default':[1,2,3]}").get(), &prop,
- nullptr);
- EXPECT_JSON_EQ("{'default':[1,2,3]}", *prop2.ToJson(false, false));
- EXPECT_JSON_EQ(
- "{'default':[1,2,3],'items':{'type':'integer'},'type':'array'}",
- *prop2.ToJson(true, false));
-}
-
-TEST(CommandSchema, ArrayPropType_FromJson) {
- ArrayPropType prop;
- EXPECT_TRUE(prop.FromJson(CreateDictionaryValue("{'items':'integer'}").get(),
- nullptr, nullptr));
- EXPECT_EQ(ValueType::Int, prop.GetItemTypePtr()->GetType());
-
- ArrayPropType prop2;
- ASSERT_TRUE(
- prop2.FromJson(CreateDictionaryValue(
- "{'items':'string','default':['foo', 'bar', 'baz']}")
- .get(),
- nullptr, nullptr));
- ASSERT_NE(nullptr, prop2.GetDefaultValue());
- const ArrayValue* defval = prop2.GetDefaultValue()->GetArray();
- ASSERT_NE(nullptr, defval);
- EXPECT_EQ((std::vector<std::string>{"foo", "bar", "baz"}),
- GetArrayValues<std::string>(defval->GetValue()));
-}
-
-TEST(CommandSchema, ArrayPropType_Validate) {
- ArrayPropType prop;
- prop.FromJson(
- CreateDictionaryValue("{'items':{'minimum':2.3, 'maximum':10.5}}").get(),
- nullptr, nullptr);
-
- ErrorPtr error;
- EXPECT_TRUE(ValidateValue(prop, *CreateValue("[3,4,10.5]"), &error));
- error.reset();
-
- EXPECT_FALSE(ValidateValue(prop, *CreateValue("[2]"), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
-
- EXPECT_FALSE(ValidateValue(prop, *CreateValue("[4, 5, 20]"), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
-}
-
-TEST(CommandSchema, ArrayPropType_Validate_Enum) {
- ArrayPropType prop;
- prop.FromJson(
- CreateDictionaryValue("{'items':'integer', 'enum':[[1], [2,3], [4,5,6]]}")
- .get(),
- nullptr, nullptr);
-
- ErrorPtr error;
- EXPECT_TRUE(ValidateValue(prop, *CreateValue("[2,3]"), &error));
- error.reset();
-
- EXPECT_FALSE(ValidateValue(prop, *CreateValue("[2]"), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
-
- EXPECT_FALSE(ValidateValue(prop, *CreateValue("[2,3,4]"), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
-}
-
-TEST(CommandSchema, ArrayPropType_CreateValue) {
- ArrayPropType prop;
- ASSERT_TRUE(prop.FromJson(
- CreateDictionaryValue(
- "{'items':{'properties':{'width':'integer','height':'integer'}}}")
- .get(),
- nullptr, nullptr));
-
- ErrorPtr error;
- ValueVector arr;
-
- auto val = prop.CreateValue(base::ListValue{}, &error);
- ASSERT_NE(nullptr, val.get());
- EXPECT_EQ(nullptr, error.get());
- EXPECT_EQ(arr, val->GetValue());
- EXPECT_JSON_EQ("[]", *val->ToJson());
-
- val = prop.CreateValue(
- *CreateValue("[{'height':20,'width':10},{'width':17, 'height':18}]"),
- &error);
- ASSERT_NE(nullptr, val.get());
- EXPECT_EQ(nullptr, error.get());
- EXPECT_JSON_EQ("[{'height':20,'width':10},{'height':18,'width':17}]",
- *val->ToJson());
-
- val = prop.CreateValue(base::StringValue{"blah"}, &error);
- EXPECT_EQ(nullptr, val.get());
- ASSERT_NE(nullptr, error.get());
- EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
-}
-
-TEST(CommandSchema, ArrayPropType_NestedArrays_NotSupported) {
- ArrayPropType prop;
- ErrorPtr error;
- EXPECT_FALSE(prop.FromJson(
- CreateDictionaryValue("{'items':{'items':'integer'}}").get(), nullptr,
- &error));
- EXPECT_EQ(errors::commands::kInvalidObjectSchema, error->GetCode());
- error.reset();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-TEST(CommandSchema, ObjectSchema_FromJson_Shorthand_TypeName) {
- ObjectSchema schema;
- const char* schema_str =
- "{"
- "'param1':'integer',"
- "'param2':'number',"
- "'param3':'string'"
- "}";
- EXPECT_TRUE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- nullptr));
- EXPECT_EQ(ValueType::Int, schema.GetProp("param1")->GetType());
- EXPECT_EQ(ValueType::Double, schema.GetProp("param2")->GetType());
- EXPECT_EQ(ValueType::String, schema.GetProp("param3")->GetType());
- EXPECT_EQ("integer", schema.GetProp("param1")->GetTypeAsString());
- EXPECT_EQ("number", schema.GetProp("param2")->GetTypeAsString());
- EXPECT_EQ("string", schema.GetProp("param3")->GetTypeAsString());
- EXPECT_EQ(nullptr, schema.GetProp("param4"));
-
- int min_int = (std::numeric_limits<int>::min)();
- int max_int = (std::numeric_limits<int>::max)();
- double min_dbl = (std::numeric_limits<double>::lowest)();
- double max_dbl = (std::numeric_limits<double>::max)();
- EXPECT_EQ(min_int, schema.GetProp("param1")->GetInt()->GetMinValue());
- EXPECT_EQ(max_int, schema.GetProp("param1")->GetInt()->GetMaxValue());
- EXPECT_EQ(min_dbl, schema.GetProp("param2")->GetDouble()->GetMinValue());
- EXPECT_EQ(max_dbl, schema.GetProp("param2")->GetDouble()->GetMaxValue());
- EXPECT_EQ(0, schema.GetProp("param3")->GetString()->GetMinLength());
- EXPECT_EQ(max_int, schema.GetProp("param3")->GetString()->GetMaxLength());
-}
-
-TEST(CommandSchema, ObjectSchema_FromJson_Full_TypeName) {
- ObjectSchema schema;
- const char* schema_str =
- "{"
- "'param1':{'type':'integer'},"
- "'param2':{'type':'number'},"
- "'param3':{'type':'string'},"
- "'param4':{'type':'array', 'items':'integer'},"
- "'param5':{'type':'object', 'properties':{'p1':'integer'}}"
- "}";
- EXPECT_TRUE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- nullptr));
- EXPECT_EQ(ValueType::Int, schema.GetProp("param1")->GetType());
- EXPECT_EQ(ValueType::Double, schema.GetProp("param2")->GetType());
- EXPECT_EQ(ValueType::String, schema.GetProp("param3")->GetType());
- EXPECT_EQ(ValueType::Array, schema.GetProp("param4")->GetType());
- EXPECT_EQ(ValueType::Object, schema.GetProp("param5")->GetType());
- EXPECT_EQ("integer", schema.GetProp("param1")->GetTypeAsString());
- EXPECT_EQ("number", schema.GetProp("param2")->GetTypeAsString());
- EXPECT_EQ("string", schema.GetProp("param3")->GetTypeAsString());
- EXPECT_EQ("array", schema.GetProp("param4")->GetTypeAsString());
- EXPECT_EQ("object", schema.GetProp("param5")->GetTypeAsString());
- EXPECT_EQ(nullptr, schema.GetProp("param77"));
-
- int min_int = (std::numeric_limits<int>::min)();
- int max_int = (std::numeric_limits<int>::max)();
- double min_dbl = (std::numeric_limits<double>::lowest)();
- double max_dbl = (std::numeric_limits<double>::max)();
- EXPECT_EQ(min_int, schema.GetProp("param1")->GetInt()->GetMinValue());
- EXPECT_EQ(max_int, schema.GetProp("param1")->GetInt()->GetMaxValue());
- EXPECT_EQ(min_dbl, schema.GetProp("param2")->GetDouble()->GetMinValue());
- EXPECT_EQ(max_dbl, schema.GetProp("param2")->GetDouble()->GetMaxValue());
- EXPECT_EQ(0, schema.GetProp("param3")->GetString()->GetMinLength());
- EXPECT_EQ(max_int, schema.GetProp("param3")->GetString()->GetMaxLength());
-}
-
-TEST(CommandSchema, ObjectSchema_FromJson_Shorthand_TypeDeduction_Scalar) {
- ObjectSchema schema;
- const char* schema_str =
- "{"
- "'param1' :{'minimum':2},"
- "'param2' :{'maximum':10},"
- "'param3' :{'maximum':8, 'minimum':2},"
- "'param4' :{'minimum':2.1},"
- "'param5' :{'maximum':10.1},"
- "'param6' :{'maximum':8.1, 'minimum':3.1},"
- "'param7' :{'maximum':8, 'minimum':3.1},"
- "'param8' :{'maximum':8.1, 'minimum':3},"
- "'param9' :{'minLength':2},"
- "'param10':{'maxLength':10},"
- "'param11':{'maxLength':8, 'minLength':3},"
- "'param12':{'default':12},"
- "'param13':{'default':13.5},"
- "'param14':{'default':true},"
- "'param15':{'default':false},"
- "'param16':{'default':'foobar'},"
- "'param17':{'default':[1,2,3]},"
- "'param18':{'items':'number', 'default':[]}"
- "}";
- EXPECT_TRUE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- nullptr));
- EXPECT_EQ("integer", schema.GetProp("param1")->GetTypeAsString());
- EXPECT_EQ("integer", schema.GetProp("param2")->GetTypeAsString());
- EXPECT_EQ("integer", schema.GetProp("param3")->GetTypeAsString());
- EXPECT_EQ("number", schema.GetProp("param4")->GetTypeAsString());
- EXPECT_EQ("number", schema.GetProp("param5")->GetTypeAsString());
- EXPECT_EQ("number", schema.GetProp("param6")->GetTypeAsString());
- EXPECT_EQ("number", schema.GetProp("param7")->GetTypeAsString());
- EXPECT_EQ("number", schema.GetProp("param8")->GetTypeAsString());
- EXPECT_EQ("string", schema.GetProp("param9")->GetTypeAsString());
- EXPECT_EQ("string", schema.GetProp("param10")->GetTypeAsString());
- EXPECT_EQ("string", schema.GetProp("param11")->GetTypeAsString());
- EXPECT_EQ("integer", schema.GetProp("param12")->GetTypeAsString());
- EXPECT_EQ("number", schema.GetProp("param13")->GetTypeAsString());
- EXPECT_EQ("boolean", schema.GetProp("param14")->GetTypeAsString());
- EXPECT_EQ("boolean", schema.GetProp("param15")->GetTypeAsString());
- EXPECT_EQ("string", schema.GetProp("param16")->GetTypeAsString());
- EXPECT_EQ("array", schema.GetProp("param17")->GetTypeAsString());
- auto prop17 = schema.GetProp("param17");
- EXPECT_EQ("integer", prop17->GetArray()->GetItemTypePtr()->GetTypeAsString());
- EXPECT_EQ("array", schema.GetProp("param18")->GetTypeAsString());
- auto prop18 = schema.GetProp("param18");
- EXPECT_EQ("number", prop18->GetArray()->GetItemTypePtr()->GetTypeAsString());
-
- int min_int = (std::numeric_limits<int>::min)();
- int max_int = (std::numeric_limits<int>::max)();
- double min_dbl = (std::numeric_limits<double>::lowest)();
- double max_dbl = (std::numeric_limits<double>::max)();
- EXPECT_EQ(2, schema.GetProp("param1")->GetInt()->GetMinValue());
- EXPECT_EQ(max_int, schema.GetProp("param1")->GetInt()->GetMaxValue());
- EXPECT_EQ(min_int, schema.GetProp("param2")->GetInt()->GetMinValue());
- EXPECT_EQ(10, schema.GetProp("param2")->GetInt()->GetMaxValue());
- EXPECT_EQ(2, schema.GetProp("param3")->GetInt()->GetMinValue());
- EXPECT_EQ(8, schema.GetProp("param3")->GetInt()->GetMaxValue());
- EXPECT_DOUBLE_EQ(2.1, schema.GetProp("param4")->GetDouble()->GetMinValue());
- EXPECT_DOUBLE_EQ(max_dbl,
- schema.GetProp("param4")->GetDouble()->GetMaxValue());
- EXPECT_DOUBLE_EQ(min_dbl,
- schema.GetProp("param5")->GetDouble()->GetMinValue());
- EXPECT_DOUBLE_EQ(10.1, schema.GetProp("param5")->GetDouble()->GetMaxValue());
- EXPECT_DOUBLE_EQ(3.1, schema.GetProp("param6")->GetDouble()->GetMinValue());
- EXPECT_DOUBLE_EQ(8.1, schema.GetProp("param6")->GetDouble()->GetMaxValue());
- EXPECT_DOUBLE_EQ(3.1, schema.GetProp("param7")->GetDouble()->GetMinValue());
- EXPECT_DOUBLE_EQ(8.0, schema.GetProp("param7")->GetDouble()->GetMaxValue());
- EXPECT_DOUBLE_EQ(3.0, schema.GetProp("param8")->GetDouble()->GetMinValue());
- EXPECT_DOUBLE_EQ(8.1, schema.GetProp("param8")->GetDouble()->GetMaxValue());
- EXPECT_EQ(2, schema.GetProp("param9")->GetString()->GetMinLength());
- EXPECT_EQ(max_int, schema.GetProp("param9")->GetString()->GetMaxLength());
- EXPECT_EQ(0, schema.GetProp("param10")->GetString()->GetMinLength());
- EXPECT_EQ(10, schema.GetProp("param10")->GetString()->GetMaxLength());
- EXPECT_EQ(3, schema.GetProp("param11")->GetString()->GetMinLength());
- EXPECT_EQ(8, schema.GetProp("param11")->GetString()->GetMaxLength());
- const PropValue* val = schema.GetProp("param12")->GetDefaultValue();
- EXPECT_EQ(12, val->GetInt()->GetValue());
- val = schema.GetProp("param13")->GetDefaultValue();
- EXPECT_DOUBLE_EQ(13.5, val->GetDouble()->GetValue());
- val = schema.GetProp("param14")->GetDefaultValue();
- EXPECT_TRUE(val->GetBoolean()->GetValue());
- val = schema.GetProp("param15")->GetDefaultValue();
- EXPECT_FALSE(val->GetBoolean()->GetValue());
- val = schema.GetProp("param16")->GetDefaultValue();
- EXPECT_EQ("foobar", val->GetString()->GetValue());
- val = schema.GetProp("param17")->GetDefaultValue();
- EXPECT_EQ((std::vector<int>{1, 2, 3}),
- GetArrayValues<int>(val->GetArray()->GetValue()));
- val = schema.GetProp("param18")->GetDefaultValue();
- EXPECT_TRUE(val->GetArray()->GetValue().empty());
-}
-
-TEST(CommandSchema, ObjectSchema_FromJson_Shorthand_TypeDeduction_Array) {
- ObjectSchema schema;
- const char* schema_str =
- "{"
- "'param1' :[0,1,2,3],"
- "'param2' :[0.0,1.1,2.2],"
- "'param3' :['id1', 'id2'],"
- "'param4' :{'enum':[1,2,3]},"
- "'param5' :{'enum':[-1.1,2.2,3]},"
- "'param6' :{'enum':['id0', 'id1']},"
- "'param7' :{'type':'integer', 'enum':[1,2,3]},"
- "'param8' :{'type':'number', 'enum':[1,2,3]},"
- "'param9' :{'type':'number', 'enum':[]},"
- "'param10':{'type':'integer', 'enum':[]},"
- "'param11':[[0,1],[2,3]],"
- "'param12':[['foo','bar']],"
- "'param13':{'enum':[['id0', 'id1']]}"
- "}";
- EXPECT_TRUE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- nullptr));
- EXPECT_EQ("integer", schema.GetProp("param1")->GetTypeAsString());
- EXPECT_EQ("number", schema.GetProp("param2")->GetTypeAsString());
- EXPECT_EQ("string", schema.GetProp("param3")->GetTypeAsString());
- EXPECT_EQ("integer", schema.GetProp("param4")->GetTypeAsString());
- EXPECT_EQ("number", schema.GetProp("param5")->GetTypeAsString());
- EXPECT_EQ("string", schema.GetProp("param6")->GetTypeAsString());
- EXPECT_EQ("integer", schema.GetProp("param7")->GetTypeAsString());
- EXPECT_EQ("number", schema.GetProp("param8")->GetTypeAsString());
- EXPECT_EQ("number", schema.GetProp("param9")->GetTypeAsString());
- EXPECT_EQ("integer", schema.GetProp("param10")->GetTypeAsString());
-
- auto prop_type11 = schema.GetProp("param11");
- EXPECT_EQ("array", prop_type11->GetTypeAsString());
- EXPECT_EQ("integer",
- prop_type11->GetArray()->GetItemTypePtr()->GetTypeAsString());
-
- auto prop_type12 = schema.GetProp("param12");
- EXPECT_EQ("array", prop_type12->GetTypeAsString());
- EXPECT_EQ("string",
- prop_type12->GetArray()->GetItemTypePtr()->GetTypeAsString());
-
- auto prop_type13 = schema.GetProp("param13");
- EXPECT_EQ("array", prop_type12->GetTypeAsString());
- EXPECT_EQ("string",
- prop_type13->GetArray()->GetItemTypePtr()->GetTypeAsString());
-
- EXPECT_EQ((std::vector<int>{0, 1, 2, 3}),
- GetOneOfValues<int>(schema.GetProp("param1")));
- EXPECT_EQ((std::vector<double>{0.0, 1.1, 2.2}),
- GetOneOfValues<double>(schema.GetProp("param2")));
- EXPECT_EQ((std::vector<std::string>{"id1", "id2"}),
- GetOneOfValues<std::string>(schema.GetProp("param3")));
-
- EXPECT_EQ((std::vector<int>{1, 2, 3}),
- GetOneOfValues<int>(schema.GetProp("param4")));
- EXPECT_EQ((std::vector<double>{-1.1, 2.2, 3.0}),
- GetOneOfValues<double>(schema.GetProp("param5")));
- EXPECT_EQ((std::vector<std::string>{"id0", "id1"}),
- GetOneOfValues<std::string>(schema.GetProp("param6")));
- EXPECT_EQ((std::vector<int>{1, 2, 3}),
- GetOneOfValues<int>(schema.GetProp("param7")));
- EXPECT_EQ((std::vector<double>{1.0, 2.0, 3.0}),
- GetOneOfValues<double>(schema.GetProp("param8")));
- EXPECT_TRUE(GetOneOfValues<double>(schema.GetProp("param9")).empty());
- EXPECT_TRUE(GetOneOfValues<int>(schema.GetProp("param10")).empty());
-}
-
-TEST(CommandSchema, ObjectSchema_FromJson_Inheritance) {
- const char* base_schema_str =
- "{"
- "'param0' :{'minimum':1, 'maximum':5},"
- "'param1' :{'minimum':1, 'maximum':5},"
- "'param2' :{'minimum':1, 'maximum':5},"
- "'param3' :{'minimum':1, 'maximum':5},"
- "'param4' :{'minimum':1, 'maximum':5},"
- "'param5' :{'minimum':1.1, 'maximum':5.5},"
- "'param6' :{'minimum':1.1, 'maximum':5.5},"
- "'param7' :{'minimum':1.1, 'maximum':5.5},"
- "'param8' :{'minimum':1.1, 'maximum':5.5},"
- "'param9' :{'minLength':1, 'maxLength':5},"
- "'param10':{'minLength':1, 'maxLength':5},"
- "'param11':{'minLength':1, 'maxLength':5},"
- "'param12':{'minLength':1, 'maxLength':5},"
- "'param13':[1,2,3],"
- "'param14':[1,2,3],"
- "'param15':[1.1,2.2,3.3],"
- "'param16':[1.1,2.2,3.3],"
- "'param17':['id1', 'id2'],"
- "'param18':['id1', 'id2'],"
- "'param19':{'minimum':1, 'maximum':5},"
- "'param20':{'default':49},"
- "'param21':{'default':49},"
- "'param22':'integer'"
- "}";
- ObjectSchema base_schema;
- EXPECT_TRUE(base_schema.FromJson(CreateDictionaryValue(base_schema_str).get(),
- nullptr, nullptr));
- const char* schema_str =
- "{"
- "'param1' :{},"
- "'param2' :{'minimum':2},"
- "'param3' :{'maximum':9},"
- "'param4' :{'minimum':2, 'maximum':9},"
- "'param5' :{},"
- "'param6' :{'minimum':2.2},"
- "'param7' :{'maximum':9.9},"
- "'param8' :{'minimum':2.2, 'maximum':9.9},"
- "'param9' :{},"
- "'param10':{'minLength':3},"
- "'param11':{'maxLength':8},"
- "'param12':{'minLength':3, 'maxLength':8},"
- "'param13':{},"
- "'param14':[1,2,3,4],"
- "'param15':{},"
- "'param16':[1.1,2.2,3.3,4.4],"
- "'param17':{},"
- "'param18':['id1', 'id3'],"
- "'param19':{},"
- "'param20':{},"
- "'param21':{'default':8},"
- "'param22':{'default':123}"
- "}";
- ObjectSchema schema;
- EXPECT_TRUE(schema.FromJson(CreateDictionaryValue(schema_str).get(),
- &base_schema, nullptr));
- EXPECT_EQ(nullptr, schema.GetProp("param0"));
- EXPECT_NE(nullptr, schema.GetProp("param1"));
- EXPECT_EQ("integer", schema.GetProp("param1")->GetTypeAsString());
- EXPECT_EQ(1, schema.GetProp("param1")->GetInt()->GetMinValue());
- EXPECT_EQ(5, schema.GetProp("param1")->GetInt()->GetMaxValue());
- EXPECT_EQ("integer", schema.GetProp("param2")->GetTypeAsString());
- EXPECT_EQ(2, schema.GetProp("param2")->GetInt()->GetMinValue());
- EXPECT_EQ(5, schema.GetProp("param2")->GetInt()->GetMaxValue());
- EXPECT_EQ("integer", schema.GetProp("param3")->GetTypeAsString());
- EXPECT_EQ(1, schema.GetProp("param3")->GetInt()->GetMinValue());
- EXPECT_EQ(9, schema.GetProp("param3")->GetInt()->GetMaxValue());
- EXPECT_EQ("integer", schema.GetProp("param4")->GetTypeAsString());
- EXPECT_EQ(2, schema.GetProp("param4")->GetInt()->GetMinValue());
- EXPECT_EQ(9, schema.GetProp("param4")->GetInt()->GetMaxValue());
- EXPECT_EQ("number", schema.GetProp("param5")->GetTypeAsString());
- EXPECT_EQ(1.1, schema.GetProp("param5")->GetDouble()->GetMinValue());
- EXPECT_EQ(5.5, schema.GetProp("param5")->GetDouble()->GetMaxValue());
- EXPECT_EQ("number", schema.GetProp("param6")->GetTypeAsString());
- EXPECT_EQ(2.2, schema.GetProp("param6")->GetDouble()->GetMinValue());
- EXPECT_EQ(5.5, schema.GetProp("param6")->GetDouble()->GetMaxValue());
- EXPECT_EQ("number", schema.GetProp("param7")->GetTypeAsString());
- EXPECT_EQ(1.1, schema.GetProp("param7")->GetDouble()->GetMinValue());
- EXPECT_EQ(9.9, schema.GetProp("param7")->GetDouble()->GetMaxValue());
- EXPECT_EQ("number", schema.GetProp("param8")->GetTypeAsString());
- EXPECT_EQ(2.2, schema.GetProp("param8")->GetDouble()->GetMinValue());
- EXPECT_EQ(9.9, schema.GetProp("param8")->GetDouble()->GetMaxValue());
- EXPECT_EQ("string", schema.GetProp("param9")->GetTypeAsString());
- EXPECT_EQ(1, schema.GetProp("param9")->GetString()->GetMinLength());
- EXPECT_EQ(5, schema.GetProp("param9")->GetString()->GetMaxLength());
- EXPECT_EQ("string", schema.GetProp("param10")->GetTypeAsString());
- EXPECT_EQ(3, schema.GetProp("param10")->GetString()->GetMinLength());
- EXPECT_EQ(5, schema.GetProp("param10")->GetString()->GetMaxLength());
- EXPECT_EQ("string", schema.GetProp("param11")->GetTypeAsString());
- EXPECT_EQ(1, schema.GetProp("param11")->GetString()->GetMinLength());
- EXPECT_EQ(8, schema.GetProp("param11")->GetString()->GetMaxLength());
- EXPECT_EQ("string", schema.GetProp("param12")->GetTypeAsString());
- EXPECT_EQ(3, schema.GetProp("param12")->GetString()->GetMinLength());
- EXPECT_EQ(8, schema.GetProp("param12")->GetString()->GetMaxLength());
- EXPECT_EQ("integer", schema.GetProp("param13")->GetTypeAsString());
- EXPECT_EQ((std::vector<int>{1, 2, 3}),
- GetOneOfValues<int>(schema.GetProp("param13")));
- EXPECT_EQ("integer", schema.GetProp("param14")->GetTypeAsString());
- EXPECT_EQ((std::vector<int>{1, 2, 3, 4}),
- GetOneOfValues<int>(schema.GetProp("param14")));
- EXPECT_EQ("number", schema.GetProp("param15")->GetTypeAsString());
- EXPECT_EQ((std::vector<double>{1.1, 2.2, 3.3}),
- GetOneOfValues<double>(schema.GetProp("param15")));
- EXPECT_EQ("number", schema.GetProp("param16")->GetTypeAsString());
- EXPECT_EQ((std::vector<double>{1.1, 2.2, 3.3, 4.4}),
- GetOneOfValues<double>(schema.GetProp("param16")));
- EXPECT_EQ("string", schema.GetProp("param17")->GetTypeAsString());
- EXPECT_EQ((std::vector<std::string>{"id1", "id2"}),
- GetOneOfValues<std::string>(schema.GetProp("param17")));
- EXPECT_EQ("string", schema.GetProp("param18")->GetTypeAsString());
- EXPECT_EQ((std::vector<std::string>{"id1", "id3"}),
- GetOneOfValues<std::string>(schema.GetProp("param18")));
- EXPECT_EQ("integer", schema.GetProp("param19")->GetTypeAsString());
- EXPECT_EQ(1, schema.GetProp("param19")->GetInt()->GetMinValue());
- EXPECT_EQ(5, schema.GetProp("param19")->GetInt()->GetMaxValue());
- EXPECT_EQ(49,
- schema.GetProp("param20")->GetDefaultValue()->GetInt()->GetValue());
- EXPECT_EQ(8,
- schema.GetProp("param21")->GetDefaultValue()->GetInt()->GetValue());
- EXPECT_EQ(123,
- schema.GetProp("param22")->GetDefaultValue()->GetInt()->GetValue());
-}
-
-TEST(CommandSchema, ObjectSchema_UseDefaults) {
- ObjectPropType prop;
- const char* schema_str =
- "{'properties':{"
- "'param1':{'default':true},"
- "'param2':{'default':2},"
- "'param3':{'default':3.3},"
- "'param4':{'default':'four'},"
- "'param5':{'default':{'x':5,'y':6},"
- "'properties':{'x':'integer','y':'integer'}},"
- "'param6':{'default':[1,2,3]}"
- "}}";
- ASSERT_TRUE(
- prop.FromJson(CreateDictionaryValue(schema_str).get(), nullptr, nullptr));
-
- // Omit all.
- auto value =
- prop.CreatePropValue(*CreateDictionaryValue("{}").get(), nullptr);
- ASSERT_NE(nullptr, value);
- ValueMap obj = value->GetObject()->GetValue();
- EXPECT_TRUE(obj["param1"]->GetBoolean()->GetValue());
- EXPECT_EQ(2, obj["param2"]->GetInt()->GetValue());
- EXPECT_DOUBLE_EQ(3.3, obj["param3"]->GetDouble()->GetValue());
- EXPECT_EQ("four", obj["param4"]->GetString()->GetValue());
- ValueMap param5 = obj["param5"]->GetObject()->GetValue();
- EXPECT_EQ(5, param5["x"]->GetInt()->GetValue());
- EXPECT_EQ(6, param5["y"]->GetInt()->GetValue());
- ValueVector param6 = obj["param6"]->GetArray()->GetValue();
- EXPECT_EQ((std::vector<int>{1, 2, 3}), GetArrayValues<int>(param6));
-
- // Specify some.
- const char* val_json =
- "{"
- "'param1':false,"
- "'param3':33.3,"
- "'param5':{'x':-5,'y':-6}"
- "}";
- value = prop.CreatePropValue(*CreateDictionaryValue(val_json).get(), nullptr);
- ASSERT_NE(nullptr, value);
- obj = value->GetObject()->GetValue();
- EXPECT_FALSE(obj["param1"]->GetBoolean()->GetValue());
- EXPECT_EQ(2, obj["param2"]->GetInt()->GetValue());
- EXPECT_DOUBLE_EQ(33.3, obj["param3"]->GetDouble()->GetValue());
- EXPECT_EQ("four", obj["param4"]->GetString()->GetValue());
- param5 = obj["param5"]->GetObject()->GetValue();
- EXPECT_EQ(-5, param5["x"]->GetInt()->GetValue());
- EXPECT_EQ(-6, param5["y"]->GetInt()->GetValue());
- param6 = obj["param6"]->GetArray()->GetValue();
- EXPECT_EQ((std::vector<int>{1, 2, 3}), GetArrayValues<int>(param6));
-
- // Specify all.
- val_json =
- "{"
- "'param1':false,"
- "'param2':22,"
- "'param3':333.3,"
- "'param4':'FOUR',"
- "'param5':{'x':-55,'y':66},"
- "'param6':[-1, 0]"
- "}";
- value = prop.CreatePropValue(*CreateDictionaryValue(val_json).get(), nullptr);
- ASSERT_NE(nullptr, value);
- obj = value->GetObject()->GetValue();
- EXPECT_FALSE(obj["param1"]->GetBoolean()->GetValue());
- EXPECT_EQ(22, obj["param2"]->GetInt()->GetValue());
- EXPECT_DOUBLE_EQ(333.3, obj["param3"]->GetDouble()->GetValue());
- EXPECT_EQ("FOUR", obj["param4"]->GetString()->GetValue());
- param5 = obj["param5"]->GetObject()->GetValue();
- EXPECT_EQ(-55, param5["x"]->GetInt()->GetValue());
- EXPECT_EQ(66, param5["y"]->GetInt()->GetValue());
- param6 = obj["param6"]->GetArray()->GetValue();
- EXPECT_EQ((std::vector<int>{-1, 0}), GetArrayValues<int>(param6));
-}
-
-TEST(CommandSchema, ObjectSchema_FromJson_BaseSchema_Failures) {
- ObjectSchema schema;
- ErrorPtr error;
- const char* schema_str =
- "{"
- "'param1':{}"
- "}";
- EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- &error));
- EXPECT_EQ("no_type_info", error->GetFirstError()->GetCode());
- error.reset();
-
- schema_str =
- "{"
- "'param1':{'type':'foo'}"
- "}";
- EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- &error));
- EXPECT_EQ("unknown_type", error->GetFirstError()->GetCode());
- error.reset();
-
- schema_str =
- "{"
- "'param1':[]"
- "}";
- EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- &error));
- EXPECT_EQ("no_type_info", error->GetFirstError()->GetCode());
- error.reset();
-
- schema_str =
- "{"
- "'param1':{'minimum':'foo'}"
- "}";
- EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- &error));
- EXPECT_EQ("type_mismatch", error->GetFirstError()->GetCode());
- error.reset();
-
- schema_str =
- "{"
- "'param1':[1,2.2]"
- "}";
- EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- &error));
- EXPECT_EQ("type_mismatch", error->GetFirstError()->GetCode());
- error.reset();
-
- schema_str =
- "{"
- "'param1':{'minimum':1, 'enum':[1,2,3]}" // can't have min/max & enum.
- "}";
- EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- &error));
- EXPECT_EQ("unexpected_parameter", error->GetFirstError()->GetCode());
- error.reset();
-
- schema_str =
- "{"
- "'param1':{'maximum':1, 'blah':2}" // 'blah' is unexpected.
- "}";
- EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- &error));
- EXPECT_EQ("unexpected_parameter", error->GetFirstError()->GetCode());
- error.reset();
-
- schema_str =
- "{"
- "'param1':{'enum':[1,2,3],'default':5}" // 'default' must be 1, 2, or 3.
- "}";
- EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- &error));
- EXPECT_EQ("out_of_range", error->GetFirstError()->GetCode());
- error.reset();
-
- schema_str =
- "{"
- "'param1':[[1,2.3]]"
- "}";
- EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- &error));
- EXPECT_EQ("type_mismatch", error->GetFirstError()->GetCode());
- error.reset();
-
- schema_str =
- "{"
- "'param1':[[1,2],[3,4],['blah']]"
- "}";
- EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- &error));
- EXPECT_EQ("type_mismatch", error->GetFirstError()->GetCode());
- error.reset();
-
- schema_str =
- "{"
- "'param1':{'default':[]}"
- "}";
- EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- &error));
- EXPECT_EQ("no_type_info", error->GetFirstError()->GetCode());
- error.reset();
-
- schema_str =
- "{"
- "'param1':[[[1]],[[2]]]"
- "}";
- EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- &error));
- EXPECT_EQ("no_type_info", error->GetFirstError()->GetCode());
- error.reset();
-
- schema_str =
- "{"
- "'param1':{'enum':[[['foo']]]}"
- "}";
- EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- &error));
- EXPECT_EQ("no_type_info", error->GetFirstError()->GetCode());
- error.reset();
-
- schema_str =
- "{"
- "'param1':{'default':[[1],[2]]}"
- "}";
- EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- &error));
- EXPECT_EQ("no_type_info", error->GetFirstError()->GetCode());
- error.reset();
-}
-
-TEST(CommandSchema, RequiredProperties_Integral) {
- IntPropType prop;
-
- prop.MakeRequired(false);
- EXPECT_JSON_EQ("{'type':'integer'}", *prop.ToJson(true, false));
- EXPECT_JSON_EQ("{'isRequired':false,'type':'integer'}",
- *prop.ToJson(true, true));
-
- prop.MakeRequired(true);
- EXPECT_JSON_EQ("{'type':'integer'}", *prop.ToJson(true, false));
- EXPECT_JSON_EQ("{'isRequired':true,'type':'integer'}",
- *prop.ToJson(true, true));
-
- IntPropType prop2;
- EXPECT_TRUE(
- prop2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr));
- EXPECT_TRUE(prop2.IsRequired());
-
- EXPECT_TRUE(prop2.FromJson(
- CreateDictionaryValue("{'isRequired': false}").get(), &prop, nullptr));
- EXPECT_FALSE(prop2.IsRequired());
-
- EXPECT_JSON_EQ("{'type':'integer'}", *prop2.ToJson(true, false));
- EXPECT_JSON_EQ("{'isRequired':false,'type':'integer'}",
- *prop2.ToJson(true, true));
-}
-
-TEST(CommandSchema, RequiredProperties_Object) {
- ObjectPropType obj_type;
- auto schema = ObjectSchema::Create();
- auto type = PropType::Create(ValueType::Int);
- type->MakeRequired(true);
- schema->AddProp("prop1", std::move(type));
- type = PropType::Create(ValueType::String);
- type->MakeRequired(false);
- schema->AddProp("prop2", std::move(type));
- type = PropType::Create(ValueType::Boolean);
- type->MakeRequired(true);
- schema->AddProp("prop3", std::move(type));
- type = PropType::Create(ValueType::Array);
- type->GetArray()->SetItemType(PropType::Create(ValueType::String));
- schema->AddProp("prop4", std::move(type));
- auto expected1 = R"({
- 'prop1': 'integer',
- 'prop2': 'string',
- 'prop3': 'boolean',
- 'prop4': {'items': 'string'}
- })";
- EXPECT_JSON_EQ(expected1, *schema->ToJson(false, false));
- auto expected2 = R"({
- 'prop1': {'type':'integer','isRequired': true},
- 'prop2': {'type':'string','isRequired': false},
- 'prop3': {'type':'boolean','isRequired': true},
- 'prop4': {'items': 'string'}
- })";
- EXPECT_JSON_EQ(expected2, *schema->ToJson(false, true));
-
- obj_type.SetObjectSchema(std::move(schema));
- auto expected3 = R"({
- 'additionalProperties': false,
- 'properties': {
- 'prop1': 'integer',
- 'prop2': 'string',
- 'prop3': 'boolean',
- 'prop4': {'items': 'string'}
- },
- 'required': ['prop1','prop3']
- })";
- EXPECT_JSON_EQ(expected3, *obj_type.ToJson(false, false));
- EXPECT_JSON_EQ(expected3, *obj_type.ToJson(false, true));
-}
-
-TEST(CommandSchema, RequiredProperties_Schema_FromJson) {
- ObjectSchema schema;
- auto schema_str = R"({
- 'prop1': {'type':'integer','isRequired': true},
- 'prop2': {'type':'string','isRequired': false},
- 'prop3': 'boolean'
- })";
- EXPECT_TRUE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- nullptr));
- EXPECT_TRUE(schema.GetProp("prop1")->IsRequired());
- EXPECT_FALSE(schema.GetProp("prop2")->IsRequired());
- EXPECT_FALSE(schema.GetProp("prop3")->IsRequired());
- EXPECT_JSON_EQ(schema_str, *schema.ToJson(false, true));
-}
-
-TEST(CommandSchema, RequiredProperties_Schema_FromJson_Inherit) {
- ObjectSchema base_schema;
- auto base_schema_str = R"({
- 'prop1': {'type':'integer','isRequired': true},
- 'prop2': {'type':'integer','isRequired': false},
- 'prop3': {'type':'integer','isRequired': true},
- 'prop4': {'type':'integer','isRequired': false}
- })";
- EXPECT_TRUE(base_schema.FromJson(CreateDictionaryValue(base_schema_str).get(),
- nullptr, nullptr));
- ObjectSchema schema;
- auto schema_str = R"({
- 'prop1': {'isRequired': false},
- 'prop2': {'isRequired': true},
- 'prop3': {},
- 'prop4': 'integer'
- })";
- EXPECT_TRUE(schema.FromJson(CreateDictionaryValue(schema_str).get(),
- &base_schema, nullptr));
- EXPECT_FALSE(schema.GetProp("prop1")->IsRequired());
- EXPECT_TRUE(schema.GetProp("prop2")->IsRequired());
- EXPECT_TRUE(schema.GetProp("prop3")->IsRequired());
- EXPECT_FALSE(schema.GetProp("prop4")->IsRequired());
- auto expected = R"({
- 'prop1': {'type':'integer','isRequired': false},
- 'prop2': {'type':'integer','isRequired': true},
- 'prop3': {},
- 'prop4': {}
- })";
- EXPECT_JSON_EQ(expected, *schema.ToJson(false, true));
-}
-
-TEST(CommandSchema, RequiredProperties_ObjectPropType_FromJson) {
- ObjectPropType obj_type;
- auto type_str = R"({
- 'properties': {
- 'prop1': 'integer',
- 'prop2': 'string',
- 'prop3': {'type':'boolean','isRequired':true},
- 'prop4': {'items': 'string','isRequired':false},
- 'prop5': {'type':'number','isRequired':true}
- },
- 'required': ['prop1','prop3','prop4','prop5']
- })";
- EXPECT_TRUE(obj_type.FromJson(CreateDictionaryValue(type_str).get(), nullptr,
- nullptr));
- EXPECT_TRUE(obj_type.GetObjectSchemaPtr()->GetProp("prop1")->IsRequired());
- EXPECT_FALSE(obj_type.GetObjectSchemaPtr()->GetProp("prop2")->IsRequired());
- EXPECT_TRUE(obj_type.GetObjectSchemaPtr()->GetProp("prop3")->IsRequired());
- // 'required' takes precedence over 'isRequired'.
- EXPECT_TRUE(obj_type.GetObjectSchemaPtr()->GetProp("prop4")->IsRequired());
- EXPECT_TRUE(obj_type.GetObjectSchemaPtr()->GetProp("prop5")->IsRequired());
-}
-
-TEST(CommandSchema, RequiredProperties_Failures) {
- ObjectPropType obj_type;
- ErrorPtr error;
-
- auto type_str = R"({
- 'properties': {
- 'prop1': 'integer',
- 'prop2': 'string'
- },
- 'required': ['prop1','prop3','prop4']
- })";
- EXPECT_FALSE(obj_type.FromJson(CreateDictionaryValue(type_str).get(), nullptr,
- &error));
- EXPECT_EQ(errors::commands::kUnknownProperty, error->GetCode());
- error.reset();
-
- type_str = R"({
- 'properties': {
- 'prop1': 'integer',
- 'prop2': 'string'
- },
- 'required': 'prop1'
- })";
- EXPECT_FALSE(obj_type.FromJson(CreateDictionaryValue(type_str).get(), nullptr,
- &error));
- EXPECT_EQ(errors::commands::kInvalidObjectSchema, error->GetCode());
- error.reset();
-}
-
-TEST(CommandSchema, ObjectSchema_UseRequired) {
- ObjectPropType prop;
- auto schema_str = R"({
- 'properties':{
- 'param1':'integer',
- 'param2':'integer',
- 'param3':{'default':3},
- 'param4':{'default':4}
- },
- 'required':['param1','param3']
- })";
- ASSERT_TRUE(
- prop.FromJson(CreateDictionaryValue(schema_str).get(), nullptr, nullptr));
-
- auto val_json = R"({
- 'param1':10,
- 'param2':20,
- 'param3':30,
- 'param4':40
- })";
- auto value =
- prop.CreatePropValue(*CreateDictionaryValue(val_json).get(), nullptr);
- ASSERT_NE(nullptr, value);
- ValueMap obj = value->GetObject()->GetValue();
- EXPECT_EQ(10, obj["param1"]->GetInt()->GetValue());
- EXPECT_EQ(20, obj["param2"]->GetInt()->GetValue());
- EXPECT_EQ(30, obj["param3"]->GetInt()->GetValue());
- EXPECT_EQ(40, obj["param4"]->GetInt()->GetValue());
-
- val_json = "{'param1':100}";
- value = prop.CreatePropValue(*CreateDictionaryValue(val_json).get(), nullptr);
- ASSERT_NE(nullptr, value);
- obj = value->GetObject()->GetValue();
- EXPECT_EQ(3u, obj.size());
-
- EXPECT_EQ(100, obj["param1"]->GetInt()->GetValue());
- EXPECT_EQ(obj.end(), obj.find("param2"));
- EXPECT_EQ(3, obj["param3"]->GetInt()->GetValue());
- EXPECT_EQ(4, obj["param4"]->GetInt()->GetValue());
-}
-
-TEST(CommandSchema, ObjectSchema_UseRequired_Failure) {
- ObjectPropType prop;
- auto schema_str = R"({
- 'properties':{
- 'param1':'integer',
- 'param2':'integer',
- 'param3':{'default':3},
- 'param4':{'default':4}
- },
- 'required':['param1','param3']
- })";
- ASSERT_TRUE(
- prop.FromJson(CreateDictionaryValue(schema_str).get(), nullptr, nullptr));
-
- auto val_json = "{'param2':20}";
- ErrorPtr error;
- auto value =
- prop.CreatePropValue(*CreateDictionaryValue(val_json).get(), &error);
- ASSERT_EQ(nullptr, value);
- EXPECT_EQ(errors::commands::kPropertyMissing, error->GetCode());
-}
-
-} // namespace weave
diff --git a/src/commands/prop_constraints.cc b/src/commands/prop_constraints.cc
deleted file mode 100644
index b7e9cf6..0000000
--- a/src/commands/prop_constraints.cc
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright 2015 The Weave Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/commands/prop_constraints.h"
-
-#include <base/json/json_writer.h>
-#include <base/logging.h>
-
-#include "src/commands/prop_values.h"
-#include "src/commands/schema_constants.h"
-#include "src/string_utils.h"
-
-namespace weave {
-
-namespace {
-
-// Helper function to convert a property value to string, which is used for
-// error reporting.
-std::string PropValueToString(const PropValue& value) {
- std::string result;
- auto json = value.ToJson();
- CHECK(json);
- base::JSONWriter::Write(*json, &result);
- return result;
-}
-
-} // anonymous namespace
-
-// Constraint ----------------------------------------------------------------
-Constraint::~Constraint() {}
-
-bool Constraint::ReportErrorLessThan(ErrorPtr* error,
- const std::string& val,
- const std::string& limit) {
- Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kOutOfRange,
- "Value %s is out of range. It must not be less than %s",
- val.c_str(), limit.c_str());
- return false;
-}
-
-bool Constraint::ReportErrorGreaterThan(ErrorPtr* error,
- const std::string& val,
- const std::string& limit) {
- Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kOutOfRange,
- "Value %s is out of range. It must not be greater than %s",
- val.c_str(), limit.c_str());
- return false;
-}
-
-bool Constraint::ReportErrorNotOneOf(ErrorPtr* error,
- const std::string& val,
- const std::vector<std::string>& values) {
- Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kOutOfRange,
- "Value %s is invalid. Expected one of [%s]", val.c_str(),
- Join(",", values).c_str());
- return false;
-}
-
-void Constraint::AddToJsonDict(base::DictionaryValue* dict,
- bool overridden_only) const {
- if (!overridden_only || HasOverriddenAttributes()) {
- auto value = ToJson();
- CHECK(value);
- dict->SetWithoutPathExpansion(GetDictKey(), value.release());
- }
-}
-
-// ConstraintStringLength -----------------------------------------------------
-ConstraintStringLength::ConstraintStringLength(
- const InheritableAttribute<int>& limit)
- : limit_(limit) {}
-ConstraintStringLength::ConstraintStringLength(int limit) : limit_(limit) {}
-
-bool ConstraintStringLength::HasOverriddenAttributes() const {
- return !limit_.is_inherited;
-}
-
-std::unique_ptr<base::Value> ConstraintStringLength::ToJson() const {
- return TypedValueToJson(limit_.value);
-}
-
-// ConstraintStringLengthMin --------------------------------------------------
-ConstraintStringLengthMin::ConstraintStringLengthMin(
- const InheritableAttribute<int>& limit)
- : ConstraintStringLength(limit) {}
-ConstraintStringLengthMin::ConstraintStringLengthMin(int limit)
- : ConstraintStringLength(limit) {}
-
-bool ConstraintStringLengthMin::Validate(const PropValue& value,
- ErrorPtr* error) const {
- CHECK(value.GetString()) << "Expecting a string value for this constraint";
- const std::string& str = value.GetString()->GetValue();
- int length = static_cast<int>(str.size());
- if (length < limit_.value) {
- if (limit_.value == 1) {
- Error::AddTo(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kOutOfRange, "String must not be empty");
- } else {
- Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kOutOfRange,
- "String must be at least %d characters long,"
- " actual length of string '%s' is %d",
- limit_.value, str.c_str(), length);
- }
- return false;
- }
- return true;
-}
-
-std::unique_ptr<Constraint> ConstraintStringLengthMin::Clone() const {
- return std::unique_ptr<Constraint>{new ConstraintStringLengthMin{limit_}};
-}
-
-std::unique_ptr<Constraint> ConstraintStringLengthMin::CloneAsInherited()
- const {
- return std::unique_ptr<Constraint>{
- new ConstraintStringLengthMin{limit_.value}};
-}
-
-// ConstraintStringLengthMax --------------------------------------------------
-ConstraintStringLengthMax::ConstraintStringLengthMax(
- const InheritableAttribute<int>& limit)
- : ConstraintStringLength(limit) {}
-ConstraintStringLengthMax::ConstraintStringLengthMax(int limit)
- : ConstraintStringLength(limit) {}
-
-bool ConstraintStringLengthMax::Validate(const PropValue& value,
- ErrorPtr* error) const {
- CHECK(value.GetString()) << "Expecting a string value for this constraint";
- const std::string& str = value.GetString()->GetValue();
- int length = static_cast<int>(str.size());
- if (length > limit_.value) {
- Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kOutOfRange,
- "String must be no more than %d character(s) "
- "long, actual length of string '%s' is %d",
- limit_.value, str.c_str(), length);
- return false;
- }
- return true;
-}
-
-std::unique_ptr<Constraint> ConstraintStringLengthMax::Clone() const {
- return std::unique_ptr<Constraint>{new ConstraintStringLengthMax{limit_}};
-}
-
-std::unique_ptr<Constraint> ConstraintStringLengthMax::CloneAsInherited()
- const {
- return std::unique_ptr<Constraint>{
- new ConstraintStringLengthMax{limit_.value}};
-}
-
-// ConstraintOneOf --------------------------------------------------
-ConstraintOneOf::ConstraintOneOf(InheritableAttribute<ValueVector> set)
- : set_(std::move(set)) {}
-ConstraintOneOf::ConstraintOneOf(ValueVector set) : set_(std::move(set)) {}
-
-bool ConstraintOneOf::Validate(const PropValue& value, ErrorPtr* error) const {
- for (const auto& item : set_.value) {
- if (value.IsEqual(item.get()))
- return true;
- }
- std::vector<std::string> choice_list;
- choice_list.reserve(set_.value.size());
- for (const auto& item : set_.value) {
- choice_list.push_back(PropValueToString(*item));
- }
- return ReportErrorNotOneOf(error, PropValueToString(value), choice_list);
-}
-
-std::unique_ptr<Constraint> ConstraintOneOf::Clone() const {
- InheritableAttribute<ValueVector> attr;
- attr.is_inherited = set_.is_inherited;
- attr.value.reserve(set_.value.size());
- for (const auto& prop_value : set_.value) {
- attr.value.push_back(prop_value->Clone());
- }
- return std::unique_ptr<Constraint>{new ConstraintOneOf{std::move(attr)}};
-}
-
-std::unique_ptr<Constraint> ConstraintOneOf::CloneAsInherited() const {
- ValueVector cloned;
- cloned.reserve(set_.value.size());
- for (const auto& prop_value : set_.value) {
- cloned.push_back(prop_value->Clone());
- }
- return std::unique_ptr<Constraint>{new ConstraintOneOf{std::move(cloned)}};
-}
-
-std::unique_ptr<base::Value> ConstraintOneOf::ToJson() const {
- return TypedValueToJson(set_.value);
-}
-
-const char* ConstraintOneOf::GetDictKey() const {
- return commands::attributes::kOneOf_Enum;
-}
-
-} // namespace weave
diff --git a/src/commands/prop_constraints.h b/src/commands/prop_constraints.h
deleted file mode 100644
index 53a4d93..0000000
--- a/src/commands/prop_constraints.h
+++ /dev/null
@@ -1,315 +0,0 @@
-// Copyright 2015 The Weave Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef LIBWEAVE_SRC_COMMANDS_PROP_CONSTRAINTS_H_
-#define LIBWEAVE_SRC_COMMANDS_PROP_CONSTRAINTS_H_
-
-#include <string>
-#include <type_traits>
-#include <vector>
-
-#include <base/macros.h>
-#include <base/values.h>
-#include <weave/error.h>
-
-#include "src/commands/prop_values.h"
-#include "src/commands/schema_constants.h"
-#include "src/commands/schema_utils.h"
-#include "src/string_utils.h"
-
-namespace weave {
-
-enum class ConstraintType { Min, Max, StringLengthMin, StringLengthMax, OneOf };
-
-// Abstract base class for all parameter constraints. Many constraints are
-// type-dependent. Thus, a numeric parameter could have "minimum" and/or
-// "maximum" constraints specified. Some constraints, such as "OneOf" apply to
-// any data type.
-class Constraint {
- public:
- Constraint() = default;
- virtual ~Constraint();
-
- // Gets the constraint type.
- virtual ConstraintType GetType() const = 0;
-
- // Checks if any of the constraint properties/attributes are overridden
- // from their base schema definition. If the constraint is inherited, then
- // it will not be written to JSON when saving partial schema.
- virtual bool HasOverriddenAttributes() const = 0;
-
- // Validates a parameter against the constraint. Returns true if parameter
- // value satisfies the constraint, otherwise fills the optional |error| with
- // the details for the failure.
- virtual bool Validate(const PropValue& value, ErrorPtr* error) const = 0;
-
- // Makes a full copy of this Constraint instance.
- virtual std::unique_ptr<Constraint> Clone() const = 0;
-
- // Makes a copy of the constraint object, marking all the attributes
- // as inherited from the original definition.
- virtual std::unique_ptr<Constraint> CloneAsInherited() const = 0;
-
- // Saves the constraint into the specified JSON |dict| object, representing
- // the object schema. If |overridden_only| is set to true, then the
- // inherited constraints will not be added to the schema object.
- virtual void AddToJsonDict(base::DictionaryValue* dict,
- bool overridden_only) const;
-
- // Saves the value of constraint to JSON value. E.g., if the numeric
- // constraint was defined as {"minimum":20} this will create a JSON value
- // of 20. The current design implies that each constraint has one value
- // only. If this assumption changes, this interface needs to be updated
- // accordingly.
- virtual std::unique_ptr<base::Value> ToJson() const = 0;
-
- // Overloaded by the concrete class implementation, it should return the
- // JSON object property name to store the constraint's value as.
- // E.g., if the numeric constraint was defined as {"minimum":20} this
- // method should return "minimum".
- virtual const char* GetDictKey() const = 0;
-
- protected:
- // Static helper methods to format common constraint validation errors.
- // They fill the |error| object with specific error message.
- // Since these functions could be used by constraint objects for various
- // data types, the values used in validation are expected to be
- // send as strings already.
- static bool ReportErrorLessThan(ErrorPtr* error,
- const std::string& val,
- const std::string& limit);
- static bool ReportErrorGreaterThan(ErrorPtr* error,
- const std::string& val,
- const std::string& limit);
-
- static bool ReportErrorNotOneOf(ErrorPtr* error,
- const std::string& val,
- const std::vector<std::string>& values);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Constraint);
-};
-
-// ConstraintMinMaxBase is a base class for numeric Minimum and Maximum
-// constraints.
-template <typename T>
-class ConstraintMinMaxBase : public Constraint {
- public:
- explicit ConstraintMinMaxBase(const InheritableAttribute<T>& limit)
- : limit_(limit) {}
- explicit ConstraintMinMaxBase(const T& limit) : limit_(limit) {}
-
- // Implementation of Constraint::HasOverriddenAttributes().
- bool HasOverriddenAttributes() const override { return !limit_.is_inherited; }
-
- // Implementation of Constraint::ToJson().
- std::unique_ptr<base::Value> ToJson() const override {
- return TypedValueToJson(limit_.value);
- }
-
- // Stores the upper/lower value limit for maximum/minimum constraint.
- // |limit_.is_inherited| indicates whether the constraint is inherited
- // from base schema or overridden.
- InheritableAttribute<T> limit_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ConstraintMinMaxBase);
-};
-
-// Implementation of Minimum value constraint for Integer/Double types.
-template <typename T>
-class ConstraintMin : public ConstraintMinMaxBase<T> {
- public:
- explicit ConstraintMin(const InheritableAttribute<T>& limit)
- : ConstraintMinMaxBase<T>(limit) {}
- explicit ConstraintMin(const T& limit) : ConstraintMinMaxBase<T>(limit) {}
-
- // Implementation of Constraint::GetType().
- ConstraintType GetType() const override { return ConstraintType::Min; }
-
- // Implementation of Constraint::Validate().
- bool Validate(const PropValue& value, ErrorPtr* error) const override {
- const T& v = static_cast<const TypedValueBase<T>&>(value).GetValue();
- if (v < this->limit_.value) {
- return this->ReportErrorLessThan(error, std::to_string(v),
- std::to_string(this->limit_.value));
- }
- return true;
- }
-
- // Implementation of Constraint::Clone().
- std::unique_ptr<Constraint> Clone() const override {
- return std::unique_ptr<Constraint>{new ConstraintMin{this->limit_}};
- }
-
- // Implementation of Constraint::CloneAsInherited().
- std::unique_ptr<Constraint> CloneAsInherited() const override {
- return std::unique_ptr<Constraint>{new ConstraintMin{this->limit_.value}};
- }
-
- // Implementation of Constraint::GetDictKey().
- const char* GetDictKey() const override {
- return commands::attributes::kNumeric_Min;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ConstraintMin);
-};
-
-// Implementation of Maximum value constraint for Integer/Double types.
-template <typename T>
-class ConstraintMax : public ConstraintMinMaxBase<T> {
- public:
- explicit ConstraintMax(const InheritableAttribute<T>& limit)
- : ConstraintMinMaxBase<T>(limit) {}
- explicit ConstraintMax(const T& limit) : ConstraintMinMaxBase<T>(limit) {}
-
- // Implementation of Constraint::GetType().
- ConstraintType GetType() const override { return ConstraintType::Max; }
-
- // Implementation of Constraint::Validate().
- bool Validate(const PropValue& value, ErrorPtr* error) const override {
- const T& v = static_cast<const TypedValueBase<T>&>(value).GetValue();
- if (v > this->limit_.value)
- return this->ReportErrorGreaterThan(error, std::to_string(v),
- std::to_string(this->limit_.value));
- return true;
- }
-
- // Implementation of Constraint::Clone().
- std::unique_ptr<Constraint> Clone() const override {
- return std::unique_ptr<Constraint>{new ConstraintMax{this->limit_}};
- }
-
- // Implementation of Constraint::CloneAsInherited().
- std::unique_ptr<Constraint> CloneAsInherited() const override {
- return std::unique_ptr<Constraint>{new ConstraintMax{this->limit_.value}};
- }
-
- // Implementation of Constraint::GetDictKey().
- const char* GetDictKey() const override {
- return commands::attributes::kNumeric_Max;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ConstraintMax);
-};
-
-// ConstraintStringLength is a base class for Minimum/Maximum string length
-// constraints, similar to ConstraintMinMaxBase of numeric types.
-class ConstraintStringLength : public Constraint {
- public:
- explicit ConstraintStringLength(const InheritableAttribute<int>& limit);
- explicit ConstraintStringLength(int limit);
-
- // Implementation of Constraint::HasOverriddenAttributes().
- bool HasOverriddenAttributes() const override;
- // Implementation of Constraint::ToJson().
- std::unique_ptr<base::Value> ToJson() const override;
-
- // Stores the upper/lower value limit for string length constraint.
- // |limit_.is_inherited| indicates whether the constraint is inherited
- // from base schema or overridden.
- InheritableAttribute<int> limit_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ConstraintStringLength);
-};
-
-// Implementation of Minimum string length constraint.
-class ConstraintStringLengthMin : public ConstraintStringLength {
- public:
- explicit ConstraintStringLengthMin(const InheritableAttribute<int>& limit);
- explicit ConstraintStringLengthMin(int limit);
-
- // Implementation of Constraint::GetType().
- ConstraintType GetType() const override {
- return ConstraintType::StringLengthMin;
- }
-
- // Implementation of Constraint::Validate().
- bool Validate(const PropValue& value, ErrorPtr* error) const override;
-
- // Implementation of Constraint::Clone().
- std::unique_ptr<Constraint> Clone() const override;
-
- // Implementation of Constraint::CloneAsInherited().
- std::unique_ptr<Constraint> CloneAsInherited() const override;
- // Implementation of Constraint::GetDictKey().
- const char* GetDictKey() const override {
- return commands::attributes::kString_MinLength;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ConstraintStringLengthMin);
-};
-
-// Implementation of Maximum string length constraint.
-class ConstraintStringLengthMax : public ConstraintStringLength {
- public:
- explicit ConstraintStringLengthMax(const InheritableAttribute<int>& limit);
- explicit ConstraintStringLengthMax(int limit);
-
- // Implementation of Constraint::GetType().
- ConstraintType GetType() const override {
- return ConstraintType::StringLengthMax;
- }
-
- // Implementation of Constraint::Validate().
- bool Validate(const PropValue& value, ErrorPtr* error) const override;
-
- // Implementation of Constraint::Clone().
- std::unique_ptr<Constraint> Clone() const override;
-
- // Implementation of Constraint::CloneAsInherited().
- std::unique_ptr<Constraint> CloneAsInherited() const override;
-
- // Implementation of Constraint::GetDictKey().
- const char* GetDictKey() const override {
- return commands::attributes::kString_MaxLength;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ConstraintStringLengthMax);
-};
-
-// Implementation of OneOf constraint for different data types.
-class ConstraintOneOf : public Constraint {
- public:
- explicit ConstraintOneOf(InheritableAttribute<ValueVector> set);
- explicit ConstraintOneOf(ValueVector set);
-
- // Implementation of Constraint::GetType().
- ConstraintType GetType() const override { return ConstraintType::OneOf; }
-
- // Implementation of Constraint::HasOverriddenAttributes().
- bool HasOverriddenAttributes() const override { return !set_.is_inherited; }
-
- // Implementation of Constraint::Validate().
- bool Validate(const PropValue& value, ErrorPtr* error) const override;
-
- // Implementation of Constraint::Clone().
- std::unique_ptr<Constraint> Clone() const override;
-
- // Implementation of Constraint::CloneAsInherited().
- std::unique_ptr<Constraint> CloneAsInherited() const override;
-
- // Implementation of Constraint::ToJson().
- std::unique_ptr<base::Value> ToJson() const override;
-
- // Implementation of Constraint::GetDictKey().
- const char* GetDictKey() const override;
-
- // Stores the list of acceptable values for the parameter.
- // |set_.is_inherited| indicates whether the constraint is inherited
- // from base schema or overridden.
- InheritableAttribute<ValueVector> set_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ConstraintOneOf);
-};
-
-} // namespace weave
-
-#endif // LIBWEAVE_SRC_COMMANDS_PROP_CONSTRAINTS_H_
diff --git a/src/commands/prop_types.cc b/src/commands/prop_types.cc
deleted file mode 100644
index def68b1..0000000
--- a/src/commands/prop_types.cc
+++ /dev/null
@@ -1,655 +0,0 @@
-// Copyright 2015 The Weave Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/commands/prop_types.h"
-
-#include <algorithm>
-#include <limits>
-#include <set>
-
-#include <base/json/json_writer.h>
-#include <base/logging.h>
-#include <base/values.h>
-
-#include "src/commands/object_schema.h"
-#include "src/commands/prop_values.h"
-#include "src/commands/schema_constants.h"
-
-namespace weave {
-
-// PropType -------------------------------------------------------------------
-PropType::PropType() {}
-
-PropType::~PropType() {}
-
-std::string PropType::GetTypeAsString() const {
- return GetTypeStringFromType(GetType());
-}
-
-bool PropType::HasOverriddenAttributes() const {
- if (default_.value && !default_.is_inherited)
- return true;
-
- for (const auto& pair : constraints_) {
- if (pair.second->HasOverriddenAttributes())
- return true;
- }
- return false;
-}
-
-bool PropType::IsRequired() const {
- return required_.value;
-}
-
-void PropType::MakeRequired(bool required) {
- required_.value = required;
- required_.is_inherited = false;
-}
-
-std::unique_ptr<base::Value> PropType::ToJson(bool full_schema,
- bool in_command_def) const {
- // Determine if we need to output "isRequired" attribute.
- const bool include_required = in_command_def && !required_.is_inherited;
-
- // If we must include "isRequired" attribute, then treat this as "full schema"
- // request because there could be cases where we have just this attribute and
- // won't be able to infer the type from the constraints only.
- if (include_required)
- full_schema = true;
-
- if (!full_schema && !HasOverriddenAttributes()) {
- if (based_on_schema_)
- return std::unique_ptr<base::Value>(new base::DictionaryValue);
- return TypedValueToJson(GetTypeAsString());
- }
-
- std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
- if (full_schema) {
- // If we are asked for full_schema definition, then we need to output every
- // parameter property, including the "type", and any constraints.
- // So, we write the "type" only if asked for full schema.
- // Otherwise we will be able to infer the parameter type based on
- // the constraints and their types.
- // That is, the following JSONs could possibly define a parameter:
- // {'type':'integer'} -> explicit "integer" with no constraints
- // {'minimum':10} -> no type specified, but since we have "minimum"
- // and 10 is integer, than this is an integer
- // parameter with min constraint.
- // {'enum':[1,2,3]} -> integer with OneOf constraint.
- // And so is this: [1,2,3] -> an array of ints assume it's an "int" enum.
- dict->SetString(commands::attributes::kType, GetTypeAsString());
- }
-
- if (!full_schema && constraints_.size() == 1) {
- // If we are not asked for full schema, and we have only one constraint
- // which is OneOf, we short-circuit the whole thing and return just
- // the array [1,2,3] instead of an object with "enum" property like:
- // {'enum':[1,2,3]}
- auto p = constraints_.find(ConstraintType::OneOf);
- if (p != constraints_.end()) {
- return p->second->ToJson();
- }
- }
-
- for (const auto& pair : constraints_)
- pair.second->AddToJsonDict(dict.get(), !full_schema);
-
- if (default_.value && (full_schema || !default_.is_inherited)) {
- auto def_val = default_.value->ToJson();
- CHECK(def_val);
- dict->Set(commands::attributes::kDefault, def_val.release());
- }
-
- if (include_required)
- dict->SetBoolean(commands::attributes::kIsRequired, required_.value);
- return std::unique_ptr<base::Value>(dict.release());
-}
-
-std::unique_ptr<PropType> PropType::Clone() const {
- auto cloned = PropType::Create(GetType());
- cloned->based_on_schema_ = based_on_schema_;
- for (const auto& pair : constraints_) {
- cloned->constraints_.insert(
- std::make_pair(pair.first, pair.second->Clone()));
- }
- cloned->default_.is_inherited = default_.is_inherited;
- if (default_.value)
- cloned->default_.value = default_.value->Clone();
- cloned->required_ = required_;
- return cloned;
-}
-
-bool PropType::FromJson(const base::DictionaryValue* value,
- const PropType* base_schema,
- ErrorPtr* error) {
- if (base_schema && base_schema->GetType() != GetType()) {
- Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kPropTypeChanged,
- "Redefining a property of type %s as %s",
- base_schema->GetTypeAsString().c_str(),
- GetTypeAsString().c_str());
- return false;
- }
- based_on_schema_ = (base_schema != nullptr);
- constraints_.clear();
- // Add the well-known object properties first (like "type", "displayName",
- // "default") to the list of "processed" keys so we do not complain about them
- // when we check for unknown/unexpected keys below.
- std::set<std::string> processed_keys{
- commands::attributes::kType, commands::attributes::kDisplayName,
- commands::attributes::kDefault, commands::attributes::kIsRequired,
- };
- if (!ObjectSchemaFromJson(value, base_schema, &processed_keys, error))
- return false;
- if (base_schema) {
- for (const auto& pair : base_schema->GetConstraints()) {
- constraints_.insert(
- std::make_pair(pair.first, pair.second->CloneAsInherited()));
- }
- }
- if (!ConstraintsFromJson(value, &processed_keys, error))
- return false;
-
- // Now make sure there are no unexpected/unknown keys in the property schema
- // definition object.
- base::DictionaryValue::Iterator iter(*value);
- while (!iter.IsAtEnd()) {
- std::string key = iter.key();
- if (processed_keys.find(key) == processed_keys.end()) {
- Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kUnknownProperty,
- "Unexpected property '%s'", key.c_str());
- return false;
- }
- iter.Advance();
- }
-
- // Read the "isRequired" attribute, if specified.
- bool required = false;
- if (value->GetBoolean(commands::attributes::kIsRequired, &required)) {
- required_.value = required;
- required_.is_inherited = false;
- } else if (base_schema) {
- // If we have the base schema, inherit the type's required value from it.
- if (base_schema->required_.value)
- required_.value = base_schema->required_.value;
- required_.is_inherited = true;
- }
-
- // Read the default value, if specified.
- // We need to do this last since the current type definition must be complete,
- // so we can parse and validate the value of the default.
- const base::Value* defval = nullptr; // Owned by value
- if (value->GetWithoutPathExpansion(commands::attributes::kDefault, &defval)) {
- std::unique_ptr<PropValue> prop_value = CreatePropValue(*defval, error);
- if (!prop_value) {
- Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kInvalidPropValue,
- "Invalid value for property '%s'",
- commands::attributes::kDefault);
- return false;
- }
- default_.value = std::move(prop_value);
- default_.is_inherited = false;
- } else if (base_schema) {
- // If we have the base schema, inherit the type's default value from it.
- // It doesn't matter if the base schema actually has a default value
- // specified or not. If it doesn't, then the current type definition will
- // have no default value set either (|default_.value| is a unique_ptr to
- // PropValue, which can be set to nullptr).
- if (base_schema->default_.value)
- default_.value = base_schema->default_.value->Clone();
- default_.is_inherited = true;
- }
- return true;
-}
-
-void PropType::AddConstraint(std::unique_ptr<Constraint> constraint) {
- constraints_[constraint->GetType()] = std::move(constraint);
-}
-
-void PropType::RemoveConstraint(ConstraintType constraint_type) {
- constraints_.erase(constraint_type);
-}
-
-void PropType::RemoveAllConstraints() {
- constraints_.clear();
-}
-
-const Constraint* PropType::GetConstraint(
- ConstraintType constraint_type) const {
- auto p = constraints_.find(constraint_type);
- return p != constraints_.end() ? p->second.get() : nullptr;
-}
-
-Constraint* PropType::GetConstraint(ConstraintType constraint_type) {
- auto p = constraints_.find(constraint_type);
- return p != constraints_.end() ? p->second.get() : nullptr;
-}
-
-bool PropType::ValidateConstraints(const PropValue& value,
- ErrorPtr* error) const {
- for (const auto& pair : constraints_) {
- if (!pair.second->Validate(value, error))
- return false;
- }
- return true;
-}
-
-const PropType::TypeMap& PropType::GetTypeMap() {
- static TypeMap map = {
- {ValueType::Int, "integer"}, {ValueType::Double, "number"},
- {ValueType::String, "string"}, {ValueType::Boolean, "boolean"},
- {ValueType::Object, "object"}, {ValueType::Array, "array"},
- };
- return map;
-}
-
-std::string PropType::GetTypeStringFromType(ValueType type) {
- for (const auto& pair : GetTypeMap()) {
- if (pair.first == type)
- return pair.second;
- }
- LOG(FATAL) << "Type map is missing a type";
- return std::string();
-}
-
-bool PropType::GetTypeFromTypeString(const std::string& name, ValueType* type) {
- for (const auto& pair : GetTypeMap()) {
- if (pair.second == name) {
- *type = pair.first;
- return true;
- }
- }
- return false;
-}
-
-std::unique_ptr<PropType> PropType::Create(ValueType type) {
- PropType* prop = nullptr;
- switch (type) {
- case ValueType::Int:
- prop = new IntPropType;
- break;
- case ValueType::Double:
- prop = new DoublePropType;
- break;
- case ValueType::String:
- prop = new StringPropType;
- break;
- case ValueType::Boolean:
- prop = new BooleanPropType;
- break;
- case ValueType::Object:
- prop = new ObjectPropType;
- break;
- case ValueType::Array:
- prop = new ArrayPropType;
- break;
- }
- return std::unique_ptr<PropType>(prop);
-}
-
-template <typename T>
-static std::unique_ptr<Constraint> LoadOneOfConstraint(
- const base::DictionaryValue* value,
- const PropType* prop_type,
- ErrorPtr* error) {
- std::unique_ptr<Constraint> constraint;
- const base::Value* list = nullptr; // Owned by |value|
- CHECK(value->Get(commands::attributes::kOneOf_Enum, &list))
- << "'enum' property missing in JSON dictionary";
- ValueVector choice_list;
- ArrayPropType array_type;
- array_type.SetItemType(prop_type->Clone());
- if (!TypedValueFromJson(list, &array_type, &choice_list, error))
- return constraint;
- InheritableAttribute<ValueVector> val(std::move(choice_list), false);
- constraint.reset(new ConstraintOneOf{std::move(val)});
- return constraint;
-}
-
-template <class ConstraintClass, typename T>
-static std::unique_ptr<Constraint> LoadMinMaxConstraint(
- const char* dict_key,
- const base::DictionaryValue* value,
- ErrorPtr* error) {
- std::unique_ptr<Constraint> constraint;
- InheritableAttribute<T> limit;
-
- const base::Value* src_val = nullptr;
- CHECK(value->Get(dict_key, &src_val)) << "Unable to get min/max constraints";
- if (!TypedValueFromJson(src_val, nullptr, &limit.value, error))
- return constraint;
- limit.is_inherited = false;
-
- constraint.reset(new ConstraintClass{limit});
- return constraint;
-}
-
-// PropTypeBase ----------------------------------------------------------------
-
-template <class Derived, class Value, typename T>
-bool PropTypeBase<Derived, Value, T>::ConstraintsFromJson(
- const base::DictionaryValue* value,
- std::set<std::string>* processed_keys,
- ErrorPtr* error) {
- if (!PropType::ConstraintsFromJson(value, processed_keys, error))
- return false;
-
- if (value->HasKey(commands::attributes::kOneOf_Enum)) {
- auto type = Clone();
- type->RemoveAllConstraints();
- auto constraint = LoadOneOfConstraint<T>(value, type.get(), error);
- if (!constraint)
- return false;
- this->AddConstraint(std::move(constraint));
- this->RemoveConstraint(ConstraintType::Min);
- this->RemoveConstraint(ConstraintType::Max);
- processed_keys->insert(commands::attributes::kOneOf_Enum);
- }
-
- return true;
-}
-
-// NumericPropTypeBase ---------------------------------------------------------
-
-template <class Derived, class Value, typename T>
-bool NumericPropTypeBase<Derived, Value, T>::ConstraintsFromJson(
- const base::DictionaryValue* value,
- std::set<std::string>* processed_keys,
- ErrorPtr* error) {
- if (!Base::ConstraintsFromJson(value, processed_keys, error))
- return false;
-
- if (processed_keys->find(commands::attributes::kOneOf_Enum) ==
- processed_keys->end()) {
- // Process min/max constraints only if "enum" constraint wasn't already
- // specified.
- if (value->HasKey(commands::attributes::kNumeric_Min)) {
- auto constraint = LoadMinMaxConstraint<ConstraintMin<T>, T>(
- commands::attributes::kNumeric_Min, value, error);
- if (!constraint)
- return false;
- this->AddConstraint(std::move(constraint));
- this->RemoveConstraint(ConstraintType::OneOf);
- processed_keys->insert(commands::attributes::kNumeric_Min);
- }
- if (value->HasKey(commands::attributes::kNumeric_Max)) {
- auto constraint = LoadMinMaxConstraint<ConstraintMax<T>, T>(
- commands::attributes::kNumeric_Max, value, error);
- if (!constraint)
- return false;
- this->AddConstraint(std::move(constraint));
- this->RemoveConstraint(ConstraintType::OneOf);
- processed_keys->insert(commands::attributes::kNumeric_Max);
- }
- }
-
- return true;
-}
-
-// StringPropType -------------------------------------------------------------
-
-bool StringPropType::ConstraintsFromJson(const base::DictionaryValue* value,
- std::set<std::string>* processed_keys,
- ErrorPtr* error) {
- if (!Base::ConstraintsFromJson(value, processed_keys, error))
- return false;
-
- if (processed_keys->find(commands::attributes::kOneOf_Enum) ==
- processed_keys->end()) {
- // Process min/max constraints only if "enum" constraint wasn't already
- // specified.
- if (value->HasKey(commands::attributes::kString_MinLength)) {
- auto constraint = LoadMinMaxConstraint<ConstraintStringLengthMin, int>(
- commands::attributes::kString_MinLength, value, error);
- if (!constraint)
- return false;
- AddConstraint(std::move(constraint));
- RemoveConstraint(ConstraintType::OneOf);
- processed_keys->insert(commands::attributes::kString_MinLength);
- }
- if (value->HasKey(commands::attributes::kString_MaxLength)) {
- auto constraint = LoadMinMaxConstraint<ConstraintStringLengthMax, int>(
- commands::attributes::kString_MaxLength, value, error);
- if (!constraint)
- return false;
- AddConstraint(std::move(constraint));
- RemoveConstraint(ConstraintType::OneOf);
- processed_keys->insert(commands::attributes::kString_MaxLength);
- }
- }
- return true;
-}
-
-void StringPropType::AddLengthConstraint(int min_len, int max_len) {
- InheritableAttribute<int> min_attr(min_len, false);
- InheritableAttribute<int> max_attr(max_len, false);
- AddConstraint(std::unique_ptr<ConstraintStringLengthMin>{
- new ConstraintStringLengthMin{min_attr}});
- AddConstraint(std::unique_ptr<ConstraintStringLengthMax>{
- new ConstraintStringLengthMax{max_attr}});
-}
-
-int StringPropType::GetMinLength() const {
- auto slc = static_cast<const ConstraintStringLength*>(
- GetConstraint(ConstraintType::StringLengthMin));
- return slc ? slc->limit_.value : 0;
-}
-
-int StringPropType::GetMaxLength() const {
- auto slc = static_cast<const ConstraintStringLength*>(
- GetConstraint(ConstraintType::StringLengthMax));
- return slc ? slc->limit_.value : std::numeric_limits<int>::max();
-}
-
-// ObjectPropType -------------------------------------------------------------
-
-ObjectPropType::ObjectPropType()
- : object_schema_{ObjectSchema::Create(), false} {}
-
-bool ObjectPropType::HasOverriddenAttributes() const {
- return PropType::HasOverriddenAttributes() || !object_schema_.is_inherited;
-}
-
-std::unique_ptr<PropType> ObjectPropType::Clone() const {
- auto cloned = Base::Clone();
-
- cloned->GetObject()->object_schema_.is_inherited =
- object_schema_.is_inherited;
- cloned->GetObject()->object_schema_.value = object_schema_.value->Clone();
- return cloned;
-}
-
-std::unique_ptr<base::Value> ObjectPropType::ToJson(bool full_schema,
- bool in_command_def) const {
- std::unique_ptr<base::Value> value =
- PropType::ToJson(full_schema, in_command_def);
- CHECK(value);
- base::DictionaryValue* dict = nullptr;
- CHECK(value->GetAsDictionary(&dict)) << "Expecting a JSON object";
- if (!object_schema_.is_inherited || full_schema) {
- auto object_schema = object_schema_.value->ToJson(full_schema, false);
- CHECK(object_schema);
-
- dict->SetWithoutPathExpansion(commands::attributes::kObject_Properties,
- object_schema.release());
- dict->SetBooleanWithoutPathExpansion(
- commands::attributes::kObject_AdditionalProperties,
- object_schema_.value->GetExtraPropertiesAllowed());
- std::unique_ptr<base::ListValue> required{new base::ListValue};
- for (const auto& pair : object_schema_.value->GetProps()) {
- if (pair.second->IsRequired())
- required->AppendString(pair.first);
- }
- if (required->GetSize() > 0) {
- dict->Set(commands::attributes::kObject_Required, required.release());
- }
- }
- return value;
-}
-
-bool ObjectPropType::ObjectSchemaFromJson(const base::DictionaryValue* value,
- const PropType* base_schema,
- std::set<std::string>* processed_keys,
- ErrorPtr* error) {
- if (!Base::ObjectSchemaFromJson(value, base_schema, processed_keys, error))
- return false;
-
- using commands::attributes::kObject_Properties;
- using commands::attributes::kObject_AdditionalProperties;
-
- const ObjectSchema* base_object_schema = nullptr;
- if (base_schema)
- base_object_schema = base_schema->GetObject()->GetObjectSchemaPtr();
-
- const base::DictionaryValue* props = nullptr;
- std::unique_ptr<ObjectSchema> object_schema;
- bool inherited = false;
- if (value->GetDictionaryWithoutPathExpansion(kObject_Properties, &props)) {
- processed_keys->insert(kObject_Properties);
- object_schema.reset(new ObjectSchema);
- if (!object_schema->FromJson(props, base_object_schema, error)) {
- Error::AddTo(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kInvalidObjectSchema,
- "Error parsing object property schema");
- return false;
- }
- } else if (base_object_schema) {
- object_schema = base_object_schema->Clone();
- inherited = true;
- } else {
- Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kInvalidObjectSchema,
- "Object type definition must include the "
- "object schema ('%s' field not found)",
- kObject_Properties);
- return false;
- }
- bool extra_properties_allowed = false;
- if (value->GetBooleanWithoutPathExpansion(kObject_AdditionalProperties,
- &extra_properties_allowed)) {
- processed_keys->insert(kObject_AdditionalProperties);
- object_schema->SetExtraPropertiesAllowed(extra_properties_allowed);
- inherited = false;
- }
- const base::Value* required = nullptr;
- if (value->Get(commands::attributes::kObject_Required, &required)) {
- processed_keys->insert(commands::attributes::kObject_Required);
- const base::ListValue* required_list = nullptr;
- if (!required->GetAsList(&required_list)) {
- Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kInvalidObjectSchema,
- "Property '%s' must be an array",
- commands::attributes::kObject_Required);
- return false;
- }
- for (const base::Value* value : *required_list) {
- std::string name;
- if (!value->GetAsString(&name)) {
- std::string json_value;
- CHECK(base::JSONWriter::Write(*value, &json_value));
- Error::AddToPrintf(
- error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kInvalidObjectSchema,
- "Property '%s' contains invalid element (%s). String expected",
- commands::attributes::kObject_Required, json_value.c_str());
- return false;
- }
- if (!object_schema->MarkPropRequired(name, error))
- return false;
- inherited = false;
- }
- }
- object_schema_.value = std::move(object_schema);
- object_schema_.is_inherited = inherited;
-
- return true;
-}
-
-void ObjectPropType::SetObjectSchema(
- std::unique_ptr<const ObjectSchema> schema) {
- object_schema_.value = std::move(schema);
- object_schema_.is_inherited = false;
-}
-
-// ArrayPropType -------------------------------------------------------------
-
-ArrayPropType::ArrayPropType() {}
-
-bool ArrayPropType::HasOverriddenAttributes() const {
- return PropType::HasOverriddenAttributes() || !item_type_.is_inherited;
-}
-
-std::unique_ptr<PropType> ArrayPropType::Clone() const {
- auto cloned = Base::Clone();
-
- cloned->GetArray()->item_type_.is_inherited = item_type_.is_inherited;
- cloned->GetArray()->item_type_.value = item_type_.value->Clone();
- return cloned;
-}
-
-std::unique_ptr<base::Value> ArrayPropType::ToJson(bool full_schema,
- bool in_command_def) const {
- std::unique_ptr<base::Value> value =
- PropType::ToJson(full_schema, in_command_def);
- CHECK(value);
- if (!item_type_.is_inherited || full_schema) {
- base::DictionaryValue* dict = nullptr;
- CHECK(value->GetAsDictionary(&dict)) << "Expecting a JSON object";
- auto type = item_type_.value->ToJson(full_schema, false);
- CHECK(type);
- dict->SetWithoutPathExpansion(commands::attributes::kItems, type.release());
- }
- return value;
-}
-
-bool ArrayPropType::ObjectSchemaFromJson(const base::DictionaryValue* value,
- const PropType* base_schema,
- std::set<std::string>* processed_keys,
- ErrorPtr* error) {
- if (!Base::ObjectSchemaFromJson(value, base_schema, processed_keys, error))
- return false;
-
- using commands::attributes::kItems;
-
- const PropType* base_type = nullptr;
- if (base_schema)
- base_type = base_schema->GetArray()->GetItemTypePtr();
-
- const base::Value* type_value = nullptr;
- if (value->GetWithoutPathExpansion(kItems, &type_value)) {
- processed_keys->insert(kItems);
- auto item_type = ObjectSchema::PropFromJson(*type_value, base_type, error);
- if (!item_type)
- return false;
- if (item_type->GetType() == ValueType::Array) {
- Error::AddTo(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kInvalidObjectSchema,
- "Arrays of arrays are not supported");
- return false;
- }
- SetItemType(std::move(item_type));
- } else if (!item_type_.value) {
- if (base_type) {
- item_type_.value = base_type->Clone();
- item_type_.is_inherited = true;
- } else {
- Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kInvalidObjectSchema,
- "Array type definition must include the "
- "array item type ('%s' field not found)",
- kItems);
- return false;
- }
- }
- return true;
-}
-
-void ArrayPropType::SetItemType(std::unique_ptr<const PropType> item_type) {
- item_type_.value = std::move(item_type);
- item_type_.is_inherited = false;
-}
-
-} // namespace weave
diff --git a/src/commands/prop_types.h b/src/commands/prop_types.h
deleted file mode 100644
index f784eb6..0000000
--- a/src/commands/prop_types.h
+++ /dev/null
@@ -1,352 +0,0 @@
-// Copyright 2015 The Weave Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef LIBWEAVE_SRC_COMMANDS_PROP_TYPES_H_
-#define LIBWEAVE_SRC_COMMANDS_PROP_TYPES_H_
-
-#include <limits>
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include <weave/error.h>
-
-#include "src/commands/prop_constraints.h"
-#include "src/commands/prop_values.h"
-
-namespace weave {
-
-class IntPropType;
-class DoublePropType;
-class StringPropType;
-class BooleanPropType;
-class ObjectPropType;
-class ArrayPropType;
-
-// PropType is a base class for all parameter type definition objects.
-// Property definitions of a particular type will derive from this class and
-// provide type-specific implementations.
-class PropType {
- public:
- // ConstraintMap is a type alias for a map containing parameter
- // constraints. It is implemented as a map for fast look-ups of constraints
- // of particular type. Also it is expected to have at most one constraint
- // of each type (e.g. it makes no sense to impose two "minimum" constraints
- // onto a numeric parameter).
- using ConstraintMap = std::map<ConstraintType, std::unique_ptr<Constraint>>;
-
- PropType();
- virtual ~PropType();
-
- // Gets the parameter type as an enumeration.
- virtual ValueType GetType() const = 0;
- // Gets the parameter type as a string.
- std::string GetTypeAsString() const;
- // Returns true if this parameter definition inherits a type
- // definition from a base object schema.
- bool IsBasedOnSchema() const { return based_on_schema_; }
- // Returns a default value specified for the type, or nullptr if no default
- // is available.
- const PropValue* GetDefaultValue() const { return default_.value.get(); }
- // Gets the constraints specified for the parameter, if any.
- const ConstraintMap& GetConstraints() const { return constraints_; }
- // Returns true if this value is required. Properties are marked as required
- // by using "isRequired" attribute or listed in "required" array.
- bool IsRequired() const;
- // Sets the required attribute to the value of |required| and marks it as
- // overridden (not-inherited).
- void MakeRequired(bool required);
- // Checks if any of the type attributes were overridden from the base
- // schema definition. If this type does not inherit from a base schema,
- // this method returns true.
- // An attribute could be the value of any of the constraints, default
- // value of a parameter or any other data that may be specified in
- // parameter type definition in and can be inherited from the base schema.
- virtual bool HasOverriddenAttributes() const;
-
- // Type conversion methods. Used in lieu of RTTI and dynamic_cast<>.
- virtual IntPropType* GetInt() { return nullptr; }
- virtual IntPropType const* GetInt() const { return nullptr; }
- virtual DoublePropType* GetDouble() { return nullptr; }
- virtual DoublePropType const* GetDouble() const { return nullptr; }
- virtual StringPropType* GetString() { return nullptr; }
- virtual StringPropType const* GetString() const { return nullptr; }
- virtual BooleanPropType* GetBoolean() { return nullptr; }
- virtual BooleanPropType const* GetBoolean() const { return nullptr; }
- virtual ObjectPropType* GetObject() { return nullptr; }
- virtual ObjectPropType const* GetObject() const { return nullptr; }
- virtual ArrayPropType* GetArray() { return nullptr; }
- virtual ArrayPropType const* GetArray() const { return nullptr; }
-
- // Makes a full copy of this type definition.
- virtual std::unique_ptr<PropType> Clone() const;
-
- // Creates an instance of associated value object.
- virtual std::unique_ptr<PropValue> CreatePropValue(const base::Value& value,
- ErrorPtr* error) const = 0;
-
- // Saves the parameter type definition as a JSON object.
- // If |full_schema| is set to true, the full type definition is saved,
- // otherwise only the overridden properties and attributes from the base
- // schema is saved. That is, inherited properties and attributes are not
- // saved.
- // If it fails, returns "nullptr" and fills in the |error| with additional
- // error information.
- // |in_command_def| is set to true if the property type describes a
- // GCD command parameter, otherwise it is for an object property.
- // Command definitions handle required parameters differently (using
- // "isRequired" property as opposed to "required" list for object properties).
- virtual std::unique_ptr<base::Value> ToJson(bool full_schema,
- bool in_command_def) const;
- // Parses an JSON parameter type definition. Optional |base_schema| may
- // specify the base schema type definition this type should be based upon.
- // If not specified (nullptr), the parameter type is assumed to be a full
- // definition and any omitted required properties are treated as an error.
- // Returns true on success, otherwise fills in the |error| with additional
- // error information.
- virtual bool FromJson(const base::DictionaryValue* value,
- const PropType* base_schema,
- ErrorPtr* error);
- // Helper function to load object schema from JSON.
- virtual bool ObjectSchemaFromJson(const base::DictionaryValue* value,
- const PropType* base_schema,
- std::set<std::string>* processed_keys,
- ErrorPtr* error) {
- return true;
- }
- // Helper function to load type-specific constraints from JSON.
- virtual bool ConstraintsFromJson(const base::DictionaryValue* value,
- std::set<std::string>* processed_keys,
- ErrorPtr* error) {
- return true;
- }
-
- // Additional helper static methods to help with converting a type enum
- // value into a string and back.
- using TypeMap = std::vector<std::pair<ValueType, std::string>>;
- // Returns a list of value types and corresponding type names.
- static const TypeMap& GetTypeMap();
- // Gets the type name string for the given type.
- static std::string GetTypeStringFromType(ValueType type);
- // Finds the type for the given type name. Returns true on success.
- static bool GetTypeFromTypeString(const std::string& name, ValueType* type);
-
- // Creates an instance of PropType-derived class for the specified
- // parameter type.
- static std::unique_ptr<PropType> Create(ValueType type);
-
- // Adds a constraint to the type definition.
- void AddConstraint(std::unique_ptr<Constraint> constraint);
- // Removes a constraint of given type, if it exists.
- void RemoveConstraint(ConstraintType constraint_type);
- // Removes all constraints.
- void RemoveAllConstraints();
-
- // Finds a constraint of given type. Returns nullptr if not found.
- const Constraint* GetConstraint(ConstraintType constraint_type) const;
- Constraint* GetConstraint(ConstraintType constraint_type);
-
- // Validates the given value against all the constraints.
- bool ValidateConstraints(const PropValue& value, ErrorPtr* error) const;
-
- protected:
- friend class StatePackage;
- virtual std::unique_ptr<PropValue> CreateDefaultValue() const = 0;
-
- // Specifies if this parameter definition is derived from a base
- // object schema.
- bool based_on_schema_ = false;
- // A list of constraints specified for the parameter.
- ConstraintMap constraints_;
- // The default value specified for the parameter, if any. If the default
- // value is present, the parameter is treated as optional and the default
- // value is used if the parameter value is omitted when sending a command.
- // Otherwise the parameter is treated as required and, if it is omitted,
- // this is treated as an error.
- InheritableAttribute<std::unique_ptr<PropValue>> default_;
- // Specifies whether the parameter/property is required and must be specified
- // (either directly, or by the default value being provided in the schema).
- // Non-required parameters can be omitted completely and their values will not
- // be present in the object instance.
- InheritableAttribute<bool> required_;
-};
-
-// Base class for all the derived concrete implementations of property
-// type classes. Provides implementations for common methods of PropType base.
-template <class Derived, class Value, typename T>
-class PropTypeBase : public PropType {
- public:
- // Overrides from PropType.
- ValueType GetType() const override { return GetValueType<T>(); }
-
- std::unique_ptr<PropValue> CreatePropValue(const base::Value& value,
- ErrorPtr* error) const override {
- return CreateValue(value, error);
- }
-
- std::unique_ptr<Value> CreateValue(const base::Value& value,
- ErrorPtr* error) const {
- return Value::CreateFromJson(value, *this, error);
- }
-
- bool ConstraintsFromJson(const base::DictionaryValue* value,
- std::set<std::string>* processed_keys,
- ErrorPtr* error) override;
-
- protected:
- std::unique_ptr<PropValue> CreateDefaultValue() const override {
- if (GetDefaultValue())
- return GetDefaultValue()->Clone();
- return std::unique_ptr<PropValue>{new Value{*this}};
- }
-};
-
-// Helper base class for Int and Double parameter types.
-template <class Derived, class Value, typename T>
-class NumericPropTypeBase : public PropTypeBase<Derived, Value, T> {
- public:
- using Base = PropTypeBase<Derived, Value, T>;
- bool ConstraintsFromJson(const base::DictionaryValue* value,
- std::set<std::string>* processed_keys,
- ErrorPtr* error) override;
-
- // Helper method to set and obtain a min/max constraint values.
- // Used mostly for unit testing.
- void AddMinMaxConstraint(T min_value, T max_value) {
- InheritableAttribute<T> min_attr(min_value, false);
- InheritableAttribute<T> max_attr(max_value, false);
- this->AddConstraint(
- std::unique_ptr<ConstraintMin<T>>{new ConstraintMin<T>{min_attr}});
- this->AddConstraint(
- std::unique_ptr<ConstraintMax<T>>{new ConstraintMax<T>{max_attr}});
- }
- T GetMinValue() const {
- auto mmc = static_cast<const ConstraintMin<T>*>(
- this->GetConstraint(ConstraintType::Min));
- return mmc ? mmc->limit_.value : std::numeric_limits<T>::lowest();
- }
- T GetMaxValue() const {
- auto mmc = static_cast<const ConstraintMax<T>*>(
- this->GetConstraint(ConstraintType::Max));
- return mmc ? mmc->limit_.value : (std::numeric_limits<T>::max)();
- }
-};
-
-// Property definition of Integer type.
-class IntPropType : public NumericPropTypeBase<IntPropType, IntValue, int> {
- public:
- // Overrides from the PropType base class.
- IntPropType* GetInt() override { return this; }
- IntPropType const* GetInt() const override { return this; }
-};
-
-// Property definition of Number type.
-class DoublePropType
- : public NumericPropTypeBase<DoublePropType, DoubleValue, double> {
- public:
- // Overrides from the PropType base class.
- DoublePropType* GetDouble() override { return this; }
- DoublePropType const* GetDouble() const override { return this; }
-};
-
-// Property definition of String type.
-class StringPropType
- : public PropTypeBase<StringPropType, StringValue, std::string> {
- public:
- using Base = PropTypeBase<StringPropType, StringValue, std::string>;
- // Overrides from the PropType base class.
- StringPropType* GetString() override { return this; }
- StringPropType const* GetString() const override { return this; }
-
- bool ConstraintsFromJson(const base::DictionaryValue* value,
- std::set<std::string>* processed_keys,
- ErrorPtr* error) override;
-
- // Helper methods to add and inspect simple constraints.
- // Used mostly for unit testing.
- void AddLengthConstraint(int min_len, int max_len);
- int GetMinLength() const;
- int GetMaxLength() const;
-};
-
-// Property definition of Boolean type.
-class BooleanPropType
- : public PropTypeBase<BooleanPropType, BooleanValue, bool> {
- public:
- // Overrides from the PropType base class.
- BooleanPropType* GetBoolean() override { return this; }
- BooleanPropType const* GetBoolean() const override { return this; }
-};
-
-// Parameter definition of Object type.
-class ObjectPropType
- : public PropTypeBase<ObjectPropType, ObjectValue, ValueMap> {
- public:
- using Base = PropTypeBase<ObjectPropType, ObjectValue, ValueMap>;
- ObjectPropType();
-
- // Overrides from the ParamType base class.
- bool HasOverriddenAttributes() const override;
-
- ObjectPropType* GetObject() override { return this; }
- ObjectPropType const* GetObject() const override { return this; }
-
- std::unique_ptr<PropType> Clone() const override;
-
- std::unique_ptr<base::Value> ToJson(bool full_schema,
- bool in_command_def) const override;
- bool ObjectSchemaFromJson(const base::DictionaryValue* value,
- const PropType* base_schema,
- std::set<std::string>* processed_keys,
- ErrorPtr* error) override;
-
- // Returns a schema for Object-type parameter.
- inline const ObjectSchema* GetObjectSchemaPtr() const {
- return object_schema_.value.get();
- }
- void SetObjectSchema(std::unique_ptr<const ObjectSchema> schema);
-
- private:
- InheritableAttribute<std::unique_ptr<const ObjectSchema>> object_schema_;
-};
-
-// Parameter definition of Array type.
-class ArrayPropType
- : public PropTypeBase<ArrayPropType, ArrayValue, ValueVector> {
- public:
- using Base = PropTypeBase<ArrayPropType, ArrayValue, ValueVector>;
- ArrayPropType();
-
- // Overrides from the ParamType base class.
- bool HasOverriddenAttributes() const override;
-
- ArrayPropType* GetArray() override { return this; }
- ArrayPropType const* GetArray() const override { return this; }
-
- std::unique_ptr<PropType> Clone() const override;
-
- std::unique_ptr<base::Value> ToJson(bool full_schema,
- bool in_command_def) const override;
-
- bool ObjectSchemaFromJson(const base::DictionaryValue* value,
- const PropType* base_schema,
- std::set<std::string>* processed_keys,
- ErrorPtr* error) override;
-
- // Returns a type for Array elements.
- inline const PropType* GetItemTypePtr() const {
- return item_type_.value.get();
- }
- void SetItemType(std::unique_ptr<const PropType> item_type);
-
- private:
- InheritableAttribute<std::unique_ptr<const PropType>> item_type_;
-};
-
-} // namespace weave
-
-#endif // LIBWEAVE_SRC_COMMANDS_PROP_TYPES_H_
diff --git a/src/commands/prop_values.cc b/src/commands/prop_values.cc
deleted file mode 100644
index 6f30bee..0000000
--- a/src/commands/prop_values.cc
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2015 The Weave Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/commands/prop_values.h"
-
-#include "src/commands/prop_types.h"
-
-namespace weave {
-
-PropValue::PropValue(const PropType& type) : type_{type.Clone()} {}
-
-PropValue::PropValue(const PropValue& other) : PropValue{*other.type_} {}
-
-PropValue::~PropValue() {}
-
-} // namespace weave
diff --git a/src/commands/prop_values.h b/src/commands/prop_values.h
deleted file mode 100644
index 960802b..0000000
--- a/src/commands/prop_values.h
+++ /dev/null
@@ -1,266 +0,0 @@
-// Copyright 2015 The Weave Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef LIBWEAVE_SRC_COMMANDS_PROP_VALUES_H_
-#define LIBWEAVE_SRC_COMMANDS_PROP_VALUES_H_
-
-#include <map>
-#include <memory>
-#include <string>
-
-#include <weave/error.h>
-
-#include "src/commands/schema_utils.h"
-
-namespace base {
-class Value;
-class DictionaryValue;
-} // namespace base
-
-namespace weave {
-
-// Enumeration to indicate supported command parameter types.
-enum class ValueType {
- Int,
- Double,
- String,
- Boolean,
- Object,
- Array,
-};
-
-class PropValue;
-class IntValue;
-class DoubleValue;
-class StringValue;
-class BooleanValue;
-class ObjectValue;
-class ArrayValue;
-
-class PropType;
-
-// Helper methods to get the parameter type enum value for the given
-// native C++ data representation.
-// The generic GetValueType<T>() is undefined, however particular
-// type specializations return the appropriate ValueType.
-template <typename T>
-ValueType GetValueType(); // Undefined.
-template <>
-inline ValueType GetValueType<int>() {
- return ValueType::Int;
-}
-template <>
-inline ValueType GetValueType<double>() {
- return ValueType::Double;
-}
-template <>
-inline ValueType GetValueType<std::string>() {
- return ValueType::String;
-}
-template <>
-inline ValueType GetValueType<bool>() {
- return ValueType::Boolean;
-}
-template <>
-inline ValueType GetValueType<ValueMap>() {
- return ValueType::Object;
-}
-template <>
-inline ValueType GetValueType<ValueVector>() {
- return ValueType::Array;
-}
-
-// The base class for property values.
-// Concrete value classes of various types will be derived from this base.
-// A property value is the actual command parameter value (or a concrete value
-// that can be used in constraints and presets). The PropValue is mostly
-// just parsed content of base::Value when a command is dispatched, however
-// it does have some additional functionality:
-// - it has a reference to the type definition (PropType) which is used
-// when validating the value, especially for "object" types.
-// - it can be compared with another instances of values of the same type.
-// This is used to validate the values against "enum"/"one of" constraints.
-class PropValue {
- public:
- // Only CreateDefaultValue should use this constructor.
- explicit PropValue(const PropType& type);
- virtual ~PropValue();
-
- // Gets the type of the value.
- virtual ValueType GetType() const = 0;
-
- // Type conversion methods. Used in lieu of RTTI and dynamic_cast<>.
- virtual IntValue* GetInt() { return nullptr; }
- virtual IntValue const* GetInt() const { return nullptr; }
- virtual DoubleValue* GetDouble() { return nullptr; }
- virtual DoubleValue const* GetDouble() const { return nullptr; }
- virtual StringValue* GetString() { return nullptr; }
- virtual StringValue const* GetString() const { return nullptr; }
- virtual BooleanValue* GetBoolean() { return nullptr; }
- virtual BooleanValue const* GetBoolean() const { return nullptr; }
- virtual ObjectValue* GetObject() { return nullptr; }
- virtual ObjectValue const* GetObject() const { return nullptr; }
- virtual ArrayValue* GetArray() { return nullptr; }
- virtual ArrayValue const* GetArray() const { return nullptr; }
-
- // Makes a full copy of this value class.
- virtual std::unique_ptr<PropValue> Clone() const = 0;
-
- // Saves the value as a JSON object. Never fails.
- virtual std::unique_ptr<base::Value> ToJson() const = 0;
-
- // Return the type definition of this value.
- const PropType* GetPropType() const { return type_.get(); }
- // Compares two values and returns true if they are equal.
- virtual bool IsEqual(const PropValue* value) const = 0;
-
- protected:
- // Special out-of-line constructor to help implement PropValue::Clone().
- // That method needs to clone the underlying type but can't do this in this
- // header file since PropType is just forward-declared (it needs PropValue
- // fully defined in its own inner workings).
- explicit PropValue(const PropValue& other);
-
- private:
- std::unique_ptr<const PropType> type_;
-};
-
-// A helper template base class for implementing value classes.
-template <typename T>
-class TypedValueBase : public PropValue {
- public:
- TypedValueBase(const PropType& type) : PropValue(type) {}
-
- // Overrides from PropValue base class.
- ValueType GetType() const override { return GetValueType<T>(); }
-
- std::unique_ptr<base::Value> ToJson() const override {
- return TypedValueToJson(value_);
- }
-
- bool IsEqual(const PropValue* value) const override {
- if (GetType() != value->GetType())
- return false;
- return CompareValue(GetValue(),
- static_cast<const TypedValueBase*>(value)->GetValue());
- }
-
- // Helper methods to get and set the C++ representation of the value.
- const T& GetValue() const { return value_; }
-
- protected:
- explicit TypedValueBase(const TypedValueBase& other)
- : PropValue(other), value_(other.value_) {}
-
- TypedValueBase(const PropType& type, T value)
- : PropValue(type), value_(value) {}
-
- private:
- T value_{}; // The value of the parameter in C++ data representation.
-};
-
-// A helper template base class for implementing value classes.
-template <typename Derived, typename T>
-class TypedValueWithClone : public TypedValueBase<T> {
- public:
- TypedValueWithClone(const PropType& type) : TypedValueBase<T>(type) {}
- TypedValueWithClone(const PropType& type, const T& value)
- : TypedValueBase<T>(type, value) {}
-
- std::unique_ptr<PropValue> Clone() const override {
- return std::unique_ptr<PropValue>{
- new Derived{*static_cast<const Derived*>(this)}};
- }
-
- static std::unique_ptr<Derived> CreateFromJson(const base::Value& value,
- const PropType& type,
- ErrorPtr* error) {
- T tmp_value;
- if (!TypedValueFromJson(&value, &type, &tmp_value, error))
- return nullptr;
-
- // Only place where invalid value can exist.
- std::unique_ptr<Derived> result(new Derived(type, tmp_value));
- if (!result->GetPropType()->ValidateConstraints(*result, error))
- return nullptr;
-
- return result;
- }
-};
-
-// Value of type Integer.
-class IntValue final : public TypedValueWithClone<IntValue, int> {
- public:
- explicit IntValue(const PropType& type)
- : TypedValueWithClone<IntValue, int>(type) {}
- IntValue(const PropType& type, int value)
- : TypedValueWithClone<IntValue, int>(type, value) {}
-
- IntValue* GetInt() override { return this; }
- IntValue const* GetInt() const override { return this; }
-};
-
-// Value of type Number.
-class DoubleValue final : public TypedValueWithClone<DoubleValue, double> {
- public:
- explicit DoubleValue(const PropType& type)
- : TypedValueWithClone<DoubleValue, double>(type) {}
- DoubleValue(const PropType& type, double value)
- : TypedValueWithClone<DoubleValue, double>(type, value) {}
-
- DoubleValue* GetDouble() override { return this; }
- DoubleValue const* GetDouble() const override { return this; }
-};
-
-// Value of type String.
-class StringValue final : public TypedValueWithClone<StringValue, std::string> {
- public:
- explicit StringValue(const PropType& type)
- : TypedValueWithClone<StringValue, std::string>(type) {}
- StringValue(const PropType& type, std::string value)
- : TypedValueWithClone<StringValue, std::string>(type, value) {}
-
- StringValue* GetString() override { return this; }
- StringValue const* GetString() const override { return this; }
-};
-
-// Value of type Boolean.
-class BooleanValue final : public TypedValueWithClone<BooleanValue, bool> {
- public:
- explicit BooleanValue(const PropType& type)
- : TypedValueWithClone<BooleanValue, bool>(type) {}
- BooleanValue(const PropType& type, bool value)
- : TypedValueWithClone<BooleanValue, bool>(type, value) {}
-
- BooleanValue* GetBoolean() override { return this; }
- BooleanValue const* GetBoolean() const override { return this; }
-};
-
-// Value of type Object.
-class ObjectValue final : public TypedValueWithClone<ObjectValue, ValueMap> {
- public:
- explicit ObjectValue(const PropType& type)
- : TypedValueWithClone<ObjectValue, ValueMap>(type) {}
- ObjectValue(const PropType& type, ValueMap value)
- : TypedValueWithClone<ObjectValue, ValueMap>(type, value) {}
-
- ObjectValue* GetObject() override { return this; }
- ObjectValue const* GetObject() const override { return this; }
-};
-
-// Value of type Array.
-class ArrayValue final : public TypedValueWithClone<ArrayValue, ValueVector> {
- public:
- explicit ArrayValue(const PropType& type)
- : TypedValueWithClone<ArrayValue, ValueVector>(type) {}
- ArrayValue(const PropType& type, ValueVector value)
- : TypedValueWithClone<ArrayValue, ValueVector>(type, value) {}
-
- ArrayValue* GetArray() override { return this; }
- ArrayValue const* GetArray() const override { return this; }
-};
-
-} // namespace weave
-
-#endif // LIBWEAVE_SRC_COMMANDS_PROP_VALUES_H_
diff --git a/src/commands/schema_constants.cc b/src/commands/schema_constants.cc
index 7f8431f..cd8bf84 100644
--- a/src/commands/schema_constants.cc
+++ b/src/commands/schema_constants.cc
@@ -10,17 +10,9 @@ namespace errors {
namespace commands {
const char kDomain[] = "command_schema";
-const char kOutOfRange[] = "out_of_range";
const char kTypeMismatch[] = "type_mismatch";
-const char kPropTypeChanged[] = "param_type_changed";
-const char kUnknownType[] = "unknown_type";
-const char kInvalidPropDef[] = "invalid_parameter_definition";
const char kInvalidPropValue[] = "invalid_parameter_value";
-const char kNoTypeInfo[] = "no_type_info";
const char kPropertyMissing[] = "parameter_missing";
-const char kUnknownProperty[] = "unexpected_parameter";
-const char kInvalidObjectSchema[] = "invalid_object_schema";
-const char kDuplicateCommandDef[] = "duplicate_command_definition";
const char kInvalidCommandName[] = "invalid_command_name";
const char kCommandFailed[] = "command_failed";
const char kInvalidMinimalRole[] = "invalid_minimal_role";
@@ -32,25 +24,6 @@ const char kInvalidState[] = "invalid_state";
namespace commands {
namespace attributes {
-const char kType[] = "type";
-const char kDisplayName[] = "displayName";
-const char kDefault[] = "default";
-const char kItems[] = "items";
-const char kIsRequired[] = "isRequired";
-
-const char kNumeric_Min[] = "minimum";
-const char kNumeric_Max[] = "maximum";
-
-const char kString_MinLength[] = "minLength";
-const char kString_MaxLength[] = "maxLength";
-
-const char kOneOf_Enum[] = "enum";
-const char kOneOf_Metadata[] = "metadata";
-
-const char kObject_Properties[] = "properties";
-const char kObject_AdditionalProperties[] = "additionalProperties";
-const char kObject_Required[] = "required";
-
const char kCommand_Id[] = "id";
const char kCommand_Name[] = "name";
const char kCommand_Parameters[] = "parameters";
diff --git a/src/commands/schema_constants.h b/src/commands/schema_constants.h
index ea59f17..57766e6 100644
--- a/src/commands/schema_constants.h
+++ b/src/commands/schema_constants.h
@@ -13,17 +13,9 @@ namespace commands {
extern const char kDomain[];
// Common command definition error codes.
-extern const char kOutOfRange[];
extern const char kTypeMismatch[];
-extern const char kPropTypeChanged[];
-extern const char kUnknownType[];
-extern const char kInvalidPropDef[];
extern const char kInvalidPropValue[];
-extern const char kNoTypeInfo[];
extern const char kPropertyMissing[];
-extern const char kUnknownProperty[];
-extern const char kInvalidObjectSchema[];
-extern const char kDuplicateCommandDef[];
extern const char kInvalidCommandName[];
extern const char kCommandFailed[];
extern const char kInvalidMinimalRole[];
@@ -35,25 +27,6 @@ extern const char kInvalidState[];
namespace commands {
namespace attributes {
// Command description JSON schema attributes.
-extern const char kType[];
-extern const char kDisplayName[];
-extern const char kDefault[];
-extern const char kItems[];
-extern const char kIsRequired[];
-
-extern const char kNumeric_Min[];
-extern const char kNumeric_Max[];
-
-extern const char kString_MinLength[];
-extern const char kString_MaxLength[];
-
-extern const char kOneOf_Enum[];
-extern const char kOneOf_Metadata[];
-
-extern const char kObject_Properties[];
-extern const char kObject_AdditionalProperties[];
-extern const char kObject_Required[];
-
extern const char kCommand_Id[];
extern const char kCommand_Name[];
extern const char kCommand_Parameters[];
diff --git a/src/commands/schema_utils.cc b/src/commands/schema_utils.cc
deleted file mode 100644
index be6cb16..0000000
--- a/src/commands/schema_utils.cc
+++ /dev/null
@@ -1,266 +0,0 @@
-// Copyright 2015 The Weave Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/commands/schema_utils.h"
-
-#include <algorithm>
-#include <set>
-#include <string>
-
-#include <base/json/json_writer.h>
-#include <base/logging.h>
-
-#include "src/commands/object_schema.h"
-#include "src/commands/prop_types.h"
-#include "src/commands/prop_values.h"
-
-namespace weave {
-namespace {
-// Helper function to report "type mismatch" errors when parsing JSON.
-void ReportJsonTypeMismatch(const tracked_objects::Location& location,
- const base::Value* value_in,
- const std::string& expected_type,
- ErrorPtr* error) {
- std::string value_as_string;
- base::JSONWriter::Write(*value_in, &value_as_string);
- Error::AddToPrintf(error, location, errors::commands::kDomain,
- errors::commands::kTypeMismatch,
- "Unable to convert value %s into %s",
- value_as_string.c_str(), expected_type.c_str());
-}
-
-// Template version of ReportJsonTypeMismatch that deduces the type of expected
-// data from the value_out parameter passed to particular overload of
-// TypedValueFromJson() function. Always returns false.
-template <typename T>
-bool ReportUnexpectedJson(const tracked_objects::Location& location,
- const base::Value* value_in,
- T*,
- ErrorPtr* error) {
- ReportJsonTypeMismatch(location, value_in,
- PropType::GetTypeStringFromType(GetValueType<T>()),
- error);
- return false;
-}
-
-bool ErrorMissingProperty(ErrorPtr* error,
- const tracked_objects::Location& location,
- const char* param_name) {
- Error::AddToPrintf(error, location, errors::commands::kDomain,
- errors::commands::kPropertyMissing,
- "Required parameter missing: %s", param_name);
- return false;
-}
-
-} // namespace
-
-// Specializations of TypedValueToJson<T>() for supported C++ types.
-std::unique_ptr<base::FundamentalValue> TypedValueToJson(bool value) {
- return std::unique_ptr<base::FundamentalValue>(
- new base::FundamentalValue(value));
-}
-
-std::unique_ptr<base::FundamentalValue> TypedValueToJson(int value) {
- return std::unique_ptr<base::FundamentalValue>(
- new base::FundamentalValue(value));
-}
-
-std::unique_ptr<base::FundamentalValue> TypedValueToJson(double value) {
- return std::unique_ptr<base::FundamentalValue>(
- new base::FundamentalValue(value));
-}
-
-std::unique_ptr<base::StringValue> TypedValueToJson(const std::string& value) {
- return std::unique_ptr<base::StringValue>(new base::StringValue(value));
-}
-
-std::unique_ptr<base::DictionaryValue> TypedValueToJson(const ValueMap& value) {
- std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
- for (const auto& pair : value) {
- auto prop_value = pair.second->ToJson();
- CHECK(prop_value);
- dict->SetWithoutPathExpansion(pair.first, prop_value.release());
- }
- return dict;
-}
-
-std::unique_ptr<base::ListValue> TypedValueToJson(const ValueVector& value) {
- std::unique_ptr<base::ListValue> list(new base::ListValue);
- for (const auto& item : value) {
- auto json = item->ToJson();
- CHECK(json);
- list->Append(json.release());
- }
- return list;
-}
-
-bool TypedValueFromJson(const base::Value* value_in,
- const PropType* type,
- bool* value_out,
- ErrorPtr* error) {
- return value_in->GetAsBoolean(value_out) ||
- ReportUnexpectedJson(FROM_HERE, value_in, value_out, error);
-}
-
-bool TypedValueFromJson(const base::Value* value_in,
- const PropType* type,
- int* value_out,
- ErrorPtr* error) {
- return value_in->GetAsInteger(value_out) ||
- ReportUnexpectedJson(FROM_HERE, value_in, value_out, error);
-}
-
-bool TypedValueFromJson(const base::Value* value_in,
- const PropType* type,
- double* value_out,
- ErrorPtr* error) {
- return value_in->GetAsDouble(value_out) ||
- ReportUnexpectedJson(FROM_HERE, value_in, value_out, error);
-}
-
-bool TypedValueFromJson(const base::Value* value_in,
- const PropType* type,
- std::string* value_out,
- ErrorPtr* error) {
- return value_in->GetAsString(value_out) ||
- ReportUnexpectedJson(FROM_HERE, value_in, value_out, error);
-}
-
-bool TypedValueFromJson(const base::Value* value_in,
- const PropType* type,
- ValueMap* value_out,
- ErrorPtr* error) {
- const base::DictionaryValue* dict = nullptr;
- if (!value_in->GetAsDictionary(&dict))
- return ReportUnexpectedJson(FROM_HERE, value_in, value_out, error);
-
- CHECK(type) << "Object definition must be provided";
- CHECK(ValueType::Object == type->GetType()) << "Type must be Object";
-
- const ObjectSchema* object_schema = type->GetObject()->GetObjectSchemaPtr();
- std::set<std::string> keys_processed;
- value_out->clear(); // Clear possible default values already in |value_out|.
- for (const auto& pair : object_schema->GetProps()) {
- const PropValue* def_value = pair.second->GetDefaultValue();
- if (dict->HasKey(pair.first)) {
- const base::Value* param_value = nullptr;
- CHECK(dict->GetWithoutPathExpansion(pair.first, &param_value))
- << "Unable to get parameter";
- auto value = pair.second->CreatePropValue(*param_value, error);
- if (!value) {
- Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kInvalidPropValue,
- "Invalid value for property '%s'",
- pair.first.c_str());
- return false;
- }
- value_out->insert(std::make_pair(pair.first, std::move(value)));
- keys_processed.insert(pair.first);
- } else if (def_value) {
- value_out->insert(std::make_pair(pair.first, def_value->Clone()));
- keys_processed.insert(pair.first);
- } else if (pair.second->IsRequired()) {
- return ErrorMissingProperty(error, FROM_HERE, pair.first.c_str());
- }
- }
-
- // Just for sanity, make sure that we processed all the necessary properties
- // and there weren't any extra (unknown) ones specified. If so, ignore
- // them, but log as warnings...
- base::DictionaryValue::Iterator iter(*dict);
- while (!iter.IsAtEnd()) {
- std::string key = iter.key();
- if (keys_processed.find(key) == keys_processed.end() &&
- !object_schema->GetExtraPropertiesAllowed()) {
- Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kUnknownProperty,
- "Unrecognized parameter '%s'", key.c_str());
- return false;
- }
- iter.Advance();
- }
-
- // Now go over all property values and validate them.
- for (const auto& pair : *value_out) {
- const PropType* prop_type = pair.second->GetPropType();
- CHECK(prop_type) << "Value property type must be available";
- if (!prop_type->ValidateConstraints(*pair.second, error)) {
- Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kInvalidPropValue,
- "Invalid value for property '%s'", pair.first.c_str());
- return false;
- }
- }
- return true;
-}
-
-bool TypedValueFromJson(const base::Value* value_in,
- const PropType* type,
- ValueVector* value_out,
- ErrorPtr* error) {
- const base::ListValue* list = nullptr;
- if (!value_in->GetAsList(&list))
- return ReportUnexpectedJson(FROM_HERE, value_in, value_out, error);
-
- CHECK(type) << "Array type definition must be provided";
- CHECK(ValueType::Array == type->GetType()) << "Type must be Array";
- const PropType* item_type = type->GetArray()->GetItemTypePtr();
- CHECK(item_type) << "Incomplete array type definition";
-
- // This value might already contain values from the type defaults.
- // Clear them first before proceeding.
- value_out->clear();
- value_out->reserve(list->GetSize());
- for (const base::Value* item : *list) {
- std::unique_ptr<PropValue> prop_value =
- item_type->CreatePropValue(*item, error);
- if (!prop_value)
- return false;
- value_out->push_back(std::move(prop_value));
- }
- return true;
-}
-
-// Compares two sets of key-value pairs from two Objects.
-static bool obj_cmp(const ValueMap::value_type& v1,
- const ValueMap::value_type& v2) {
- return (v1.first == v2.first) && v1.second->IsEqual(v2.second.get());
-}
-
-bool operator==(const ValueMap& obj1, const ValueMap& obj2) {
- if (obj1.size() != obj2.size())
- return false;
-
- auto pair = std::mismatch(obj1.begin(), obj1.end(), obj2.begin(), obj_cmp);
- return pair == std::make_pair(obj1.end(), obj2.end());
-}
-
-bool operator==(const ValueVector& arr1, const ValueVector& arr2) {
- if (arr1.size() != arr2.size())
- return false;
-
- using Type = const ValueVector::value_type;
- // Compare two array items.
- auto arr_cmp = [](const Type& v1, const Type& v2) {
- return v1->IsEqual(v2.get());
- };
- auto pair = std::mismatch(arr1.begin(), arr1.end(), arr2.begin(), arr_cmp);
- return pair == std::make_pair(arr1.end(), arr2.end());
-}
-
-std::string ToString(const ValueMap& obj) {
- auto val = TypedValueToJson(obj);
- std::string str;
- base::JSONWriter::Write(*val, &str);
- return str;
-}
-
-std::string ToString(const ValueVector& arr) {
- auto val = TypedValueToJson(arr);
- std::string str;
- base::JSONWriter::Write(*val, &str);
- return str;
-}
-
-} // namespace weave
diff --git a/src/commands/schema_utils.h b/src/commands/schema_utils.h
deleted file mode 100644
index 0c1d1b3..0000000
--- a/src/commands/schema_utils.h
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright 2015 The Weave Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef LIBWEAVE_SRC_COMMANDS_SCHEMA_UTILS_H_
-#define LIBWEAVE_SRC_COMMANDS_SCHEMA_UTILS_H_
-
-#include <cmath>
-#include <limits>
-#include <map>
-#include <memory>
-#include <string>
-#include <type_traits>
-#include <vector>
-
-#include <base/logging.h>
-#include <base/values.h>
-#include <weave/error.h>
-
-namespace weave {
-
-class PropType;
-class PropValue;
-class ObjectSchema;
-class ObjectValue;
-
-// C++ representation of object values.
-using ValueMap = std::map<std::string, std::shared_ptr<const PropValue>>;
-
-// C++ representation of array of values.
-using ValueVector = std::vector<std::shared_ptr<const PropValue>>;
-
-// Converts an object to string.
-std::string ToString(const ValueMap& obj);
-
-// Converts an array to string.
-std::string ToString(const ValueVector& arr);
-
-// InheritableAttribute class is used for specifying various command parameter
-// attributes that can be inherited from a base (parent) schema.
-// The |value| still specifies the actual attribute values, whether it
-// is inherited or overridden, while |is_inherited| can be used to identify
-// if the attribute was inherited (true) or overridden (false).
-template <typename T>
-class InheritableAttribute final {
- public:
- InheritableAttribute() = default;
- explicit InheritableAttribute(T val)
- : value(std::move(val)), is_inherited(true) {}
- InheritableAttribute(T val, bool inherited)
- : value(std::move(val)), is_inherited(inherited) {}
- T value{};
- bool is_inherited{true};
-};
-
-// A bunch of helper function to create base::Value for specific C++ classes,
-// including vectors of types. These are used in template classes below
-// to simplify specialization logic.
-std::unique_ptr<base::FundamentalValue> TypedValueToJson(bool value);
-std::unique_ptr<base::FundamentalValue> TypedValueToJson(int value);
-std::unique_ptr<base::FundamentalValue> TypedValueToJson(double value);
-std::unique_ptr<base::StringValue> TypedValueToJson(const std::string& value);
-std::unique_ptr<base::DictionaryValue> TypedValueToJson(const ValueMap& value);
-std::unique_ptr<base::ListValue> TypedValueToJson(const ValueVector& value);
-template <typename T>
-std::unique_ptr<base::ListValue> TypedValueToJson(
- const std::vector<T>& values) {
- std::unique_ptr<base::ListValue> list(new base::ListValue);
- for (const auto& v : values) {
- auto json = TypedValueToJson(v);
- CHECK(json);
- list->Append(json.release());
- }
- return list;
-}
-
-// Similarly to TypedValueToJson() function above, the following overloaded
-// helper methods allow to extract specific C++ data types from base::Value.
-// Also used in template classes below to simplify specialization logic.
-// TODO(vitalybuka): Fix this. Interface is misleading. Seeing PropType internal
-// type validation is expected. In reality only ValueMap and ValueVector do
-// validation.
-bool TypedValueFromJson(const base::Value* value_in,
- const PropType* type,
- bool* value_out,
- ErrorPtr* error);
-bool TypedValueFromJson(const base::Value* value_in,
- const PropType* type,
- int* value_out,
- ErrorPtr* error);
-bool TypedValueFromJson(const base::Value* value_in,
- const PropType* type,
- double* value_out,
- ErrorPtr* error);
-bool TypedValueFromJson(const base::Value* value_in,
- const PropType* type,
- std::string* value_out,
- ErrorPtr* error);
-bool TypedValueFromJson(const base::Value* value_in,
- const PropType* type,
- ValueMap* value_out,
- ErrorPtr* error);
-bool TypedValueFromJson(const base::Value* value_in,
- const PropType* type,
- ValueVector* value_out,
- ErrorPtr* error);
-
-bool operator==(const ValueMap& obj1, const ValueMap& obj2);
-bool operator==(const ValueVector& arr1, const ValueVector& arr2);
-
-// CompareValue is a helper function to help with implementing EqualsTo operator
-// for various data types. For most scalar types it is using operator==(),
-// however, for floating point values, rounding errors in binary representation
-// of IEEE floats/doubles can cause straight == comparison to fail for seemingly
-// equivalent values. For these, use approximate comparison with the error
-// margin equal to the epsilon value defined for the corresponding data type.
-// This is used when looking up values for implementation of OneOf constraints
-// which should work reliably for floating points also ("number" type).
-
-// Compare exact types using ==.
-template <typename T>
-inline typename std::enable_if<!std::is_floating_point<T>::value, bool>::type
-CompareValue(const T& v1, const T& v2) {
- return v1 == v2;
-}
-
-// Compare non-exact types (such as double) using precision margin (epsilon).
-template <typename T>
-inline typename std::enable_if<std::is_floating_point<T>::value, bool>::type
-CompareValue(const T& v1, const T& v2) {
- return std::abs(v1 - v2) <= std::numeric_limits<T>::epsilon();
-}
-
-} // namespace weave
-
-#endif // LIBWEAVE_SRC_COMMANDS_SCHEMA_UTILS_H_
diff --git a/src/commands/schema_utils_unittest.cc b/src/commands/schema_utils_unittest.cc
deleted file mode 100644
index 1ea4c90..0000000
--- a/src/commands/schema_utils_unittest.cc
+++ /dev/null
@@ -1,212 +0,0 @@
-// Copyright 2015 The Weave Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/commands/schema_utils.h"
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <base/values.h>
-#include <gtest/gtest.h>
-
-#include "src/commands/object_schema.h"
-#include "src/commands/prop_types.h"
-#include "src/commands/prop_values.h"
-#include "src/commands/schema_constants.h"
-#include "src/commands/unittest_utils.h"
-
-namespace weave {
-
-using test::CreateDictionaryValue;
-using test::CreateValue;
-
-TEST(CommandSchemaUtils, TypedValueToJson_Scalar) {
- EXPECT_JSON_EQ("true", *TypedValueToJson(true));
- EXPECT_JSON_EQ("false", *TypedValueToJson(false));
-
- EXPECT_JSON_EQ("0", *TypedValueToJson(0));
- EXPECT_JSON_EQ("-10", *TypedValueToJson(-10));
- EXPECT_JSON_EQ("20", *TypedValueToJson(20));
-
- EXPECT_JSON_EQ("0.0", *TypedValueToJson(0.0));
- EXPECT_JSON_EQ("1.2", *TypedValueToJson(1.2));
-
- EXPECT_JSON_EQ("'abc'", *TypedValueToJson(std::string("abc")));
-
- std::vector<bool> bool_array{true, false};
- EXPECT_JSON_EQ("[true,false]", *TypedValueToJson(bool_array));
-
- std::vector<int> int_array{1, 2, 5};
- EXPECT_JSON_EQ("[1,2,5]", *TypedValueToJson(int_array));
-
- std::vector<double> dbl_array{1.1, 2.2};
- EXPECT_JSON_EQ("[1.1,2.2]", *TypedValueToJson(dbl_array));
-
- std::vector<std::string> str_array{"a", "bc"};
- EXPECT_JSON_EQ("['a','bc']", *TypedValueToJson(str_array));
-}
-
-TEST(CommandSchemaUtils, TypedValueToJson_Object) {
- IntPropType int_type;
- ValueMap object;
-
- object.insert(std::make_pair(
- "width", int_type.CreateValue(base::FundamentalValue{640}, nullptr)));
- object.insert(std::make_pair(
- "height", int_type.CreateValue(base::FundamentalValue{480}, nullptr)));
- EXPECT_JSON_EQ("{'height':480,'width':640}", *TypedValueToJson(object));
-}
-
-TEST(CommandSchemaUtils, TypedValueToJson_Array) {
- IntPropType int_type;
- ValueVector arr;
-
- arr.push_back(int_type.CreateValue(base::FundamentalValue{640}, nullptr));
- arr.push_back(int_type.CreateValue(base::FundamentalValue{480}, nullptr));
- EXPECT_JSON_EQ("[640,480]", *TypedValueToJson(arr));
-}
-
-TEST(CommandSchemaUtils, TypedValueFromJson_Bool) {
- bool value;
-
- EXPECT_TRUE(
- TypedValueFromJson(CreateValue("true").get(), nullptr, &value, nullptr));
- EXPECT_TRUE(value);
-
- EXPECT_TRUE(
- TypedValueFromJson(CreateValue("false").get(), nullptr, &value, nullptr));
- EXPECT_FALSE(value);
-
- ErrorPtr error;
- EXPECT_FALSE(
- TypedValueFromJson(CreateValue("0").get(), nullptr, &value, &error));
- EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
- error.reset();
-}
-
-TEST(CommandSchemaUtils, TypedValueFromJson_Int) {
- int value;
-
- EXPECT_TRUE(
- TypedValueFromJson(CreateValue("0").get(), nullptr, &value, nullptr));
- EXPECT_EQ(0, value);
-
- EXPECT_TRUE(
- TypedValueFromJson(CreateValue("23").get(), nullptr, &value, nullptr));
- EXPECT_EQ(23, value);
-
- EXPECT_TRUE(
- TypedValueFromJson(CreateValue("-1234").get(), nullptr, &value, nullptr));
- EXPECT_EQ(-1234, value);
-
- ErrorPtr error;
- EXPECT_FALSE(
- TypedValueFromJson(CreateValue("'abc'").get(), nullptr, &value, &error));
- EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
- error.reset();
-}
-
-TEST(CommandSchemaUtils, TypedValueFromJson_Double) {
- double value;
-
- EXPECT_TRUE(
- TypedValueFromJson(CreateValue("0").get(), nullptr, &value, nullptr));
- EXPECT_DOUBLE_EQ(0.0, value);
- EXPECT_TRUE(
- TypedValueFromJson(CreateValue("0.0").get(), nullptr, &value, nullptr));
- EXPECT_DOUBLE_EQ(0.0, value);
-
- EXPECT_TRUE(
- TypedValueFromJson(CreateValue("23").get(), nullptr, &value, nullptr));
- EXPECT_EQ(23.0, value);
- EXPECT_TRUE(
- TypedValueFromJson(CreateValue("23.1").get(), nullptr, &value, nullptr));
- EXPECT_EQ(23.1, value);
-
- EXPECT_TRUE(TypedValueFromJson(CreateValue("-1.23E+02").get(), nullptr,
- &value, nullptr));
- EXPECT_EQ(-123.0, value);
-
- ErrorPtr error;
- EXPECT_FALSE(
- TypedValueFromJson(CreateValue("'abc'").get(), nullptr, &value, &error));
- EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
- error.reset();
-}
-
-TEST(CommandSchemaUtils, TypedValueFromJson_String) {
- std::string value;
-
- EXPECT_TRUE(
- TypedValueFromJson(CreateValue("''").get(), nullptr, &value, nullptr));
- EXPECT_EQ("", value);
-
- EXPECT_TRUE(
- TypedValueFromJson(CreateValue("'23'").get(), nullptr, &value, nullptr));
- EXPECT_EQ("23", value);
-
- EXPECT_TRUE(
- TypedValueFromJson(CreateValue("'abc'").get(), nullptr, &value, nullptr));
- EXPECT_EQ("abc", value);
-
- ErrorPtr error;
- EXPECT_FALSE(
- TypedValueFromJson(CreateValue("12").get(), nullptr, &value, &error));
- EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
- error.reset();
-}
-
-TEST(CommandSchemaUtils, TypedValueFromJson_Object) {
- ValueMap value;
- std::unique_ptr<ObjectSchema> schema{new ObjectSchema};
-
- IntPropType age_prop;
- age_prop.AddMinMaxConstraint(0, 150);
- schema->AddProp("age", age_prop.Clone());
-
- StringPropType name_prop;
- name_prop.AddLengthConstraint(1, 30);
- schema->AddProp("name", name_prop.Clone());
-
- ObjectPropType type;
- type.SetObjectSchema(std::move(schema));
- EXPECT_TRUE(TypedValueFromJson(CreateValue("{'age':20,'name':'Bob'}").get(),
- &type, &value, nullptr));
- ValueMap value2;
- value2.insert(std::make_pair(
- "age", age_prop.CreateValue(base::FundamentalValue{20}, nullptr)));
- value2.insert(std::make_pair(
- "name", name_prop.CreateValue(base::StringValue("Bob"), nullptr)));
- EXPECT_EQ(value2, value);
-
- ErrorPtr error;
- EXPECT_FALSE(
- TypedValueFromJson(CreateValue("'abc'").get(), nullptr, &value, &error));
- EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
- error.reset();
-}
-
-TEST(CommandSchemaUtils, TypedValueFromJson_Array) {
- ValueVector arr;
- StringPropType str_type;
- str_type.AddLengthConstraint(3, 100);
- ArrayPropType type;
- type.SetItemType(str_type.Clone());
-
- EXPECT_TRUE(TypedValueFromJson(CreateValue("['foo', 'bar']").get(), &type,
- &arr, nullptr));
- ValueVector arr2;
- arr2.push_back(str_type.CreateValue(base::StringValue{"foo"}, nullptr));
- arr2.push_back(str_type.CreateValue(base::StringValue{"bar"}, nullptr));
- EXPECT_EQ(arr2, arr);
-
- ErrorPtr error;
- EXPECT_FALSE(TypedValueFromJson(CreateValue("['baz', 'ab']").get(), &type,
- &arr, &error));
- EXPECT_EQ(errors::commands::kOutOfRange, error->GetCode());
- error.reset();
-}
-
-} // namespace weave
diff --git a/src/commands/unittest_utils.h b/src/commands/unittest_utils.h
deleted file mode 100644
index 25392ee..0000000
--- a/src/commands/unittest_utils.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2015 The Weave Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef LIBWEAVE_SRC_COMMANDS_UNITTEST_UTILS_H_
-#define LIBWEAVE_SRC_COMMANDS_UNITTEST_UTILS_H_
-
-#include <memory>
-#include <string>
-
-#include <base/values.h>
-#include <gtest/gtest.h>
-#include <weave/test/unittest_utils.h>
-
-#include "src/commands/prop_types.h"
-#include "src/commands/prop_values.h"
-
-namespace weave {
-namespace test {
-
-template <typename T>
-std::unique_ptr<const PropValue> make_prop_value(const base::Value& value) {
- auto prop_type = PropType::Create(GetValueType<T>());
- return prop_type->CreatePropValue(value, nullptr);
-}
-
-inline std::unique_ptr<const PropValue> make_int_prop_value(int value) {
- return make_prop_value<int>(base::FundamentalValue{value});
-}
-
-inline std::unique_ptr<const PropValue> make_double_prop_value(double value) {
- return make_prop_value<double>(base::FundamentalValue{value});
-}
-
-inline std::unique_ptr<const PropValue> make_bool_prop_value(bool value) {
- return make_prop_value<bool>(base::FundamentalValue{value});
-}
-
-inline std::unique_ptr<const PropValue> make_string_prop_value(
- const std::string& value) {
- return make_prop_value<std::string>(base::StringValue{value});
-}
-
-} // namespace test
-} // namespace weave
-
-#endif // LIBWEAVE_SRC_COMMANDS_UNITTEST_UTILS_H_