Index: components/policy/core/common/schema_unittest.cc |
diff --git a/components/policy/core/common/schema_unittest.cc b/components/policy/core/common/schema_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..06fb3bf34a39d9f0d5c1d00ade4ae61030705c51 |
--- /dev/null |
+++ b/components/policy/core/common/schema_unittest.cc |
@@ -0,0 +1,338 @@ |
+// Copyright 2013 The Chromium 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 "components/policy/core/common/schema.h" |
+ |
+#include "components/policy/core/common/schema_internal.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace policy { |
+ |
+namespace { |
+ |
+#define OBJECT_TYPE "\"type\":\"object\"" |
+ |
+const internal::SchemaNode kTypeBoolean = { base::Value::TYPE_BOOLEAN, NULL, }; |
+const internal::SchemaNode kTypeInteger = { base::Value::TYPE_INTEGER, NULL, }; |
+const internal::SchemaNode kTypeNumber = { base::Value::TYPE_DOUBLE, NULL, }; |
+const internal::SchemaNode kTypeString = { base::Value::TYPE_STRING, NULL, }; |
+ |
+bool ParseFails(const std::string& content) { |
+ std::string error; |
+ scoped_ptr<SchemaOwner> schema = SchemaOwner::Parse(content, &error); |
+ if (schema) |
+ EXPECT_TRUE(schema->schema().valid()); |
+ else |
+ EXPECT_FALSE(error.empty()); |
+ return !schema; |
+} |
+ |
+} // namespace |
+ |
+TEST(SchemaTest, MinimalSchema) { |
+ EXPECT_FALSE(ParseFails( |
+ "{" |
+ OBJECT_TYPE |
+ "}")); |
+} |
+ |
+TEST(SchemaTest, InvalidSchemas) { |
+ EXPECT_TRUE(ParseFails("")); |
+ EXPECT_TRUE(ParseFails("omg")); |
+ EXPECT_TRUE(ParseFails("\"omg\"")); |
+ EXPECT_TRUE(ParseFails("123")); |
+ EXPECT_TRUE(ParseFails("[]")); |
+ EXPECT_TRUE(ParseFails("null")); |
+ EXPECT_TRUE(ParseFails("{}")); |
+ |
+ EXPECT_TRUE(ParseFails( |
+ "{" |
+ OBJECT_TYPE "," |
+ "\"additionalProperties\": { \"type\":\"object\" }" |
+ "}")); |
+ |
+ EXPECT_TRUE(ParseFails( |
+ "{" |
+ OBJECT_TYPE "," |
+ "\"patternProperties\": { \"a+b*\": { \"type\": \"object\" } }" |
+ "}")); |
+ |
+ EXPECT_TRUE(ParseFails( |
+ "{" |
+ OBJECT_TYPE "," |
+ "\"properties\": { \"Policy\": { \"type\": \"bogus\" } }" |
+ "}")); |
+ |
+ EXPECT_TRUE(ParseFails( |
+ "{" |
+ OBJECT_TYPE "," |
+ "\"properties\": { \"Policy\": { \"type\": [\"string\", \"number\"] } }" |
+ "}")); |
+ |
+ EXPECT_TRUE(ParseFails( |
+ "{" |
+ OBJECT_TYPE "," |
+ "\"properties\": { \"Policy\": { \"type\": \"any\" } }" |
+ "}")); |
+} |
+ |
+TEST(SchemaTest, ValidSchema) { |
+ std::string error; |
+ scoped_ptr<SchemaOwner> policy_schema = SchemaOwner::Parse( |
+ "{" |
+ OBJECT_TYPE "," |
+ "\"properties\": {" |
+ " \"Boolean\": { \"type\": \"boolean\" }," |
+ " \"Integer\": { \"type\": \"integer\" }," |
+ " \"Null\": { \"type\": \"null\" }," |
+ " \"Number\": { \"type\": \"number\" }," |
+ " \"String\": { \"type\": \"string\" }," |
+ " \"Array\": {" |
+ " \"type\": \"array\"," |
+ " \"items\": { \"type\": \"string\" }" |
+ " }," |
+ " \"ArrayOfObjects\": {" |
+ " \"type\": \"array\"," |
+ " \"items\": {" |
+ " \"type\": \"object\"," |
+ " \"properties\": {" |
+ " \"one\": { \"type\": \"string\" }," |
+ " \"two\": { \"type\": \"integer\" }" |
+ " }" |
+ " }" |
+ " }," |
+ " \"ArrayOfArray\": {" |
+ " \"type\": \"array\"," |
+ " \"items\": {" |
+ " \"type\": \"array\"," |
+ " \"items\": { \"type\": \"string\" }" |
+ " }" |
+ " }," |
+ " \"Object\": {" |
+ " \"type\": \"object\"," |
+ " \"properties\": {" |
+ " \"one\": { \"type\": \"boolean\" }," |
+ " \"two\": { \"type\": \"integer\" }" |
+ " }," |
+ " \"additionalProperties\": { \"type\": \"string\" }" |
+ " }" |
+ "}" |
+ "}", &error); |
+ ASSERT_TRUE(policy_schema) << error; |
+ ASSERT_TRUE(policy_schema->schema().valid()); |
+ |
+ Schema schema = policy_schema->schema(); |
+ ASSERT_EQ(base::Value::TYPE_DICTIONARY, schema.type()); |
+ EXPECT_FALSE(schema.GetProperty("invalid").valid()); |
+ |
+ Schema sub = schema.GetProperty("Boolean"); |
+ ASSERT_TRUE(sub.valid()); |
+ EXPECT_EQ(base::Value::TYPE_BOOLEAN, sub.type()); |
+ |
+ sub = schema.GetProperty("Integer"); |
+ ASSERT_TRUE(sub.valid()); |
+ EXPECT_EQ(base::Value::TYPE_INTEGER, sub.type()); |
+ |
+ sub = schema.GetProperty("Null"); |
+ ASSERT_TRUE(sub.valid()); |
+ EXPECT_EQ(base::Value::TYPE_NULL, sub.type()); |
+ |
+ sub = schema.GetProperty("Number"); |
+ ASSERT_TRUE(sub.valid()); |
+ EXPECT_EQ(base::Value::TYPE_DOUBLE, sub.type()); |
+ |
+ sub = schema.GetProperty("String"); |
+ ASSERT_TRUE(sub.valid()); |
+ EXPECT_EQ(base::Value::TYPE_STRING, sub.type()); |
+ |
+ sub = schema.GetProperty("Array"); |
+ ASSERT_TRUE(sub.valid()); |
+ ASSERT_EQ(base::Value::TYPE_LIST, sub.type()); |
+ sub = sub.GetItems(); |
+ ASSERT_TRUE(sub.valid()); |
+ EXPECT_EQ(base::Value::TYPE_STRING, sub.type()); |
+ |
+ sub = schema.GetProperty("ArrayOfObjects"); |
+ ASSERT_TRUE(sub.valid()); |
+ ASSERT_EQ(base::Value::TYPE_LIST, sub.type()); |
+ sub = sub.GetItems(); |
+ ASSERT_TRUE(sub.valid()); |
+ EXPECT_EQ(base::Value::TYPE_DICTIONARY, sub.type()); |
+ Schema subsub = sub.GetProperty("one"); |
+ ASSERT_TRUE(subsub.valid()); |
+ EXPECT_EQ(base::Value::TYPE_STRING, subsub.type()); |
+ subsub = sub.GetProperty("two"); |
+ ASSERT_TRUE(subsub.valid()); |
+ EXPECT_EQ(base::Value::TYPE_INTEGER, subsub.type()); |
+ subsub = sub.GetProperty("invalid"); |
+ EXPECT_FALSE(subsub.valid()); |
+ |
+ sub = schema.GetProperty("ArrayOfArray"); |
+ ASSERT_TRUE(sub.valid()); |
+ ASSERT_EQ(base::Value::TYPE_LIST, sub.type()); |
+ sub = sub.GetItems(); |
+ ASSERT_TRUE(sub.valid()); |
+ ASSERT_EQ(base::Value::TYPE_LIST, sub.type()); |
+ sub = sub.GetItems(); |
+ ASSERT_TRUE(sub.valid()); |
+ EXPECT_EQ(base::Value::TYPE_STRING, sub.type()); |
+ |
+ sub = schema.GetProperty("Object"); |
+ ASSERT_TRUE(sub.valid()); |
+ ASSERT_EQ(base::Value::TYPE_DICTIONARY, sub.type()); |
+ subsub = sub.GetProperty("one"); |
+ ASSERT_TRUE(subsub.valid()); |
+ EXPECT_EQ(base::Value::TYPE_BOOLEAN, subsub.type()); |
+ subsub = sub.GetProperty("two"); |
+ ASSERT_TRUE(subsub.valid()); |
+ EXPECT_EQ(base::Value::TYPE_INTEGER, subsub.type()); |
+ subsub = sub.GetProperty("undeclared"); |
+ ASSERT_TRUE(subsub.valid()); |
+ EXPECT_EQ(base::Value::TYPE_STRING, subsub.type()); |
+ |
+ struct { |
+ const char* expected_key; |
+ base::Value::Type expected_type; |
+ } kExpectedProperties[] = { |
+ { "Array", base::Value::TYPE_LIST }, |
+ { "ArrayOfArray", base::Value::TYPE_LIST }, |
+ { "ArrayOfObjects", base::Value::TYPE_LIST }, |
+ { "Boolean", base::Value::TYPE_BOOLEAN }, |
+ { "Integer", base::Value::TYPE_INTEGER }, |
+ { "Null", base::Value::TYPE_NULL }, |
+ { "Number", base::Value::TYPE_DOUBLE }, |
+ { "Object", base::Value::TYPE_DICTIONARY }, |
+ { "String", base::Value::TYPE_STRING }, |
+ }; |
+ Schema::Iterator it = schema.GetPropertiesIterator(); |
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kExpectedProperties); ++i) { |
+ ASSERT_FALSE(it.IsAtEnd()); |
+ EXPECT_STREQ(kExpectedProperties[i].expected_key, it.key()); |
+ ASSERT_TRUE(it.schema().valid()); |
+ EXPECT_EQ(kExpectedProperties[i].expected_type, it.schema().type()); |
+ it.Advance(); |
+ } |
+ EXPECT_TRUE(it.IsAtEnd()); |
+} |
+ |
+TEST(SchemaTest, Lookups) { |
+ std::string error; |
+ scoped_ptr<SchemaOwner> policy_schema = SchemaOwner::Parse( |
+ "{" |
+ OBJECT_TYPE |
+ "}", &error); |
+ ASSERT_TRUE(policy_schema) << error; |
+ Schema schema = policy_schema->schema(); |
+ ASSERT_TRUE(schema.valid()); |
+ ASSERT_EQ(base::Value::TYPE_DICTIONARY, schema.type()); |
+ |
+ // This empty schema should never find named properties. |
+ EXPECT_FALSE(schema.GetKnownProperty("").valid()); |
+ EXPECT_FALSE(schema.GetKnownProperty("xyz").valid()); |
+ EXPECT_TRUE(schema.GetPropertiesIterator().IsAtEnd()); |
+ |
+ policy_schema = SchemaOwner::Parse( |
+ "{" |
+ OBJECT_TYPE "," |
+ "\"properties\": {" |
+ " \"Boolean\": { \"type\": \"boolean\" }" |
+ "}" |
+ "}", &error); |
+ ASSERT_TRUE(policy_schema) << error; |
+ schema = policy_schema->schema(); |
+ ASSERT_TRUE(schema.valid()); |
+ ASSERT_EQ(base::Value::TYPE_DICTIONARY, schema.type()); |
+ |
+ EXPECT_FALSE(schema.GetKnownProperty("").valid()); |
+ EXPECT_FALSE(schema.GetKnownProperty("xyz").valid()); |
+ EXPECT_TRUE(schema.GetKnownProperty("Boolean").valid()); |
+ |
+ policy_schema = SchemaOwner::Parse( |
+ "{" |
+ OBJECT_TYPE "," |
+ "\"properties\": {" |
+ " \"bb\" : { \"type\": \"null\" }," |
+ " \"aa\" : { \"type\": \"boolean\" }," |
+ " \"abab\" : { \"type\": \"string\" }," |
+ " \"ab\" : { \"type\": \"number\" }," |
+ " \"aba\" : { \"type\": \"integer\" }" |
+ "}" |
+ "}", &error); |
+ ASSERT_TRUE(policy_schema) << error; |
+ schema = policy_schema->schema(); |
+ ASSERT_TRUE(schema.valid()); |
+ ASSERT_EQ(base::Value::TYPE_DICTIONARY, schema.type()); |
+ |
+ EXPECT_FALSE(schema.GetKnownProperty("").valid()); |
+ EXPECT_FALSE(schema.GetKnownProperty("xyz").valid()); |
+ |
+ struct { |
+ const char* expected_key; |
+ base::Value::Type expected_type; |
+ } kExpectedKeys[] = { |
+ { "aa", base::Value::TYPE_BOOLEAN }, |
+ { "ab", base::Value::TYPE_DOUBLE }, |
+ { "aba", base::Value::TYPE_INTEGER }, |
+ { "abab", base::Value::TYPE_STRING }, |
+ { "bb", base::Value::TYPE_NULL }, |
+ }; |
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kExpectedKeys); ++i) { |
+ Schema sub = schema.GetKnownProperty(kExpectedKeys[i].expected_key); |
+ ASSERT_TRUE(sub.valid()); |
+ EXPECT_EQ(kExpectedKeys[i].expected_type, sub.type()); |
+ } |
+} |
+ |
+TEST(SchemaTest, WrapSimpleNode) { |
+ scoped_ptr<SchemaOwner> policy_schema = SchemaOwner::Wrap(&kTypeString); |
+ ASSERT_TRUE(policy_schema); |
+ Schema schema = policy_schema->schema(); |
+ ASSERT_TRUE(schema.valid()); |
+ EXPECT_EQ(base::Value::TYPE_STRING, schema.type()); |
+} |
+ |
+TEST(SchemaTest, WrapDictionary) { |
+ const internal::SchemaNode kList = { |
+ base::Value::TYPE_LIST, |
+ &kTypeString, |
+ }; |
+ |
+ const internal::PropertyNode kPropertyNodes[] = { |
+ { "Boolean", &kTypeBoolean }, |
+ { "Integer", &kTypeInteger }, |
+ { "List", &kList }, |
+ { "Number", &kTypeNumber }, |
+ { "String", &kTypeString }, |
+ }; |
+ |
+ const internal::PropertiesNode kProperties = { |
+ kPropertyNodes, |
+ kPropertyNodes + arraysize(kPropertyNodes), |
+ NULL, |
+ }; |
+ |
+ const internal::SchemaNode root = { |
+ base::Value::TYPE_DICTIONARY, |
+ &kProperties, |
+ }; |
+ |
+ scoped_ptr<SchemaOwner> policy_schema = SchemaOwner::Wrap(&root); |
+ ASSERT_TRUE(policy_schema); |
+ Schema schema = policy_schema->schema(); |
+ ASSERT_TRUE(schema.valid()); |
+ EXPECT_EQ(base::Value::TYPE_DICTIONARY, schema.type()); |
+ |
+ Schema::Iterator it = schema.GetPropertiesIterator(); |
+ for (size_t i = 0; i < arraysize(kPropertyNodes); ++i) { |
+ ASSERT_FALSE(it.IsAtEnd()); |
+ EXPECT_STREQ(kPropertyNodes[i].key, it.key()); |
+ Schema sub = it.schema(); |
+ ASSERT_TRUE(sub.valid()); |
+ EXPECT_EQ(kPropertyNodes[i].schema->type, sub.type()); |
+ it.Advance(); |
+ } |
+ EXPECT_TRUE(it.IsAtEnd()); |
+} |
+ |
+} // namespace policy |