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 |
index 8a3ba90b1bd09876b9f0f98900fb11a9ddd50b6c..0c80a440fbe441477c5dc9cbd0a0757c6a9cae4b 100644 |
--- a/components/policy/core/common/schema_unittest.cc |
+++ b/components/policy/core/common/schema_unittest.cc |
@@ -4,6 +4,7 @@ |
#include "components/policy/core/common/schema.h" |
+#include "base/memory/scoped_ptr.h" |
#include "components/policy/core/common/schema_internal.h" |
#include "testing/gtest/include/gtest/gtest.h" |
@@ -49,6 +50,18 @@ const char kTestSchema[] = |
" }," |
" \"additionalProperties\": { \"type\": \"string\" }" |
" }," |
+ " \"ObjectOfObject\": {" |
+ " \"type\": \"object\"," |
+ " \"properties\": {" |
+ " \"Object\": {" |
+ " \"type\": \"object\"," |
+ " \"properties\": {" |
+ " \"one\": { \"type\": \"string\" }," |
+ " \"two\": { \"type\": \"integer\" }" |
+ " }" |
+ " }" |
+ " }" |
+ " }," |
" \"IntegerWithEnums\": {" |
" \"type\": \"integer\"," |
" \"enum\": [1, 2, 3]" |
@@ -65,6 +78,27 @@ const char kTestSchema[] = |
" \"type\": \"integer\"," |
" \"minimum\": 1," |
" \"maximum\": 3" |
+ " }," |
+ " \"ObjectOfArray\": {" |
+ " \"type\": \"object\"," |
+ " \"properties\": {" |
+ " \"List\": {" |
+ " \"type\": \"array\"," |
+ " \"items\": { \"type\": \"integer\" }" |
+ " }" |
+ " }" |
+ " }," |
+ " \"ArrayOfObjectOfArray\": {" |
+ " \"type\": \"array\"," |
+ " \"items\": {" |
+ " \"type\": \"object\"," |
+ " \"properties\": {" |
+ " \"List\": {" |
+ " \"type\": \"array\"," |
+ " \"items\": { \"type\": \"string\" }" |
+ " }" |
+ " }" |
+ " }" |
" }" |
" }" |
"}"; |
@@ -78,6 +112,33 @@ bool ParseFails(const std::string& content) { |
return true; |
} |
+void TestSchemaValidation(Schema schema, |
+ const base::Value& value, |
+ SchemaOnErrorStrategy strategy, |
+ bool expected_return_value) { |
+ std::string error; |
+ static const char kNoErrorReturned[] = "No error returned."; |
+ |
+ // Test that Schema::Validate() works as expected. |
+ error = kNoErrorReturned; |
+ bool returned = schema.Validate(value, strategy, &error); |
+ EXPECT_EQ(returned, expected_return_value) << error; |
+ |
+ // Test that Schema::Normalize() will return the same value as |
+ // Schema::Validate(). |
+ error = kNoErrorReturned; |
+ scoped_ptr<base::Value> cloned_value(value.DeepCopy()); |
+ returned = schema.Normalize(cloned_value.get(), strategy, &error); |
+ EXPECT_EQ(returned, expected_return_value) << error; |
+ |
+ // Test that Schema::Normalize() have actually dropped invalid and unknown |
+ // properties. |
+ if (expected_return_value) { |
+ EXPECT_TRUE(schema.Validate(*cloned_value.get(), SCHEMA_STRICT, &error)); |
+ EXPECT_TRUE(schema.Normalize(cloned_value.get(), SCHEMA_STRICT, &error)); |
+ } |
+} |
+ |
std::string SchemaObjectWrapper(const std::string& subschema) { |
return "{" |
" \"type\": \"object\"," |
@@ -277,6 +338,7 @@ TEST(SchemaTest, ValidSchema) { |
} kExpectedProperties[] = { |
{ "Array", base::Value::TYPE_LIST }, |
{ "ArrayOfArray", base::Value::TYPE_LIST }, |
+ { "ArrayOfObjectOfArray", base::Value::TYPE_LIST }, |
{ "ArrayOfObjects", base::Value::TYPE_LIST }, |
{ "Boolean", base::Value::TYPE_BOOLEAN }, |
{ "Integer", base::Value::TYPE_INTEGER }, |
@@ -286,6 +348,8 @@ TEST(SchemaTest, ValidSchema) { |
{ "Null", base::Value::TYPE_NULL }, |
{ "Number", base::Value::TYPE_DOUBLE }, |
{ "Object", base::Value::TYPE_DICTIONARY }, |
+ { "ObjectOfArray", base::Value::TYPE_DICTIONARY }, |
+ { "ObjectOfObject", base::Value::TYPE_DICTIONARY }, |
{ "String", base::Value::TYPE_STRING }, |
{ "StringWithEnums", base::Value::TYPE_STRING }, |
}; |
@@ -467,11 +531,11 @@ TEST(SchemaTest, Validate) { |
ASSERT_TRUE(schema.valid()) << error; |
base::DictionaryValue bundle; |
- EXPECT_TRUE(schema.Validate(bundle)); |
+ TestSchemaValidation(schema, bundle, SCHEMA_STRICT, true); |
// Wrong type, expected integer. |
bundle.SetBoolean("Integer", true); |
- EXPECT_FALSE(schema.Validate(bundle)); |
+ TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false); |
// Wrong type, expected list of strings. |
{ |
@@ -479,7 +543,7 @@ TEST(SchemaTest, Validate) { |
base::ListValue list; |
list.AppendInteger(1); |
bundle.Set("Array", list.DeepCopy()); |
- EXPECT_FALSE(schema.Validate(bundle)); |
+ TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false); |
} |
// Wrong type in a sub-object. |
@@ -488,13 +552,13 @@ TEST(SchemaTest, Validate) { |
base::DictionaryValue dict; |
dict.SetString("one", "one"); |
bundle.Set("Object", dict.DeepCopy()); |
- EXPECT_FALSE(schema.Validate(bundle)); |
+ TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false); |
} |
// Unknown name. |
bundle.Clear(); |
bundle.SetBoolean("Unknown", true); |
- EXPECT_FALSE(schema.Validate(bundle)); |
+ TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false); |
// All of these will be valid. |
bundle.Clear(); |
@@ -545,47 +609,169 @@ TEST(SchemaTest, Validate) { |
bundle.SetString("StringWithEnums", "two"); |
bundle.SetInteger("IntegerWithRange", 3); |
- EXPECT_TRUE(schema.Validate(bundle)); |
- |
- bundle.SetString("boom", "bang"); |
- EXPECT_FALSE(schema.Validate(bundle)); |
- bundle.Remove("boom", NULL); |
+ TestSchemaValidation(schema, bundle, SCHEMA_STRICT, true); |
bundle.SetInteger("IntegerWithEnums", 0); |
- EXPECT_FALSE(schema.Validate(bundle)); |
+ TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false); |
bundle.SetInteger("IntegerWithEnums", 1); |
bundle.SetInteger("IntegerWithEnumsGaps", 0); |
- EXPECT_FALSE(schema.Validate(bundle)); |
+ TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false); |
bundle.SetInteger("IntegerWithEnumsGaps", 9); |
- EXPECT_FALSE(schema.Validate(bundle)); |
+ TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false); |
bundle.SetInteger("IntegerWithEnumsGaps", 10); |
- EXPECT_TRUE(schema.Validate(bundle)); |
+ TestSchemaValidation(schema, bundle, SCHEMA_STRICT, true); |
bundle.SetInteger("IntegerWithEnumsGaps", 11); |
- EXPECT_FALSE(schema.Validate(bundle)); |
+ TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false); |
bundle.SetInteger("IntegerWithEnumsGaps", 19); |
- EXPECT_FALSE(schema.Validate(bundle)); |
+ TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false); |
bundle.SetInteger("IntegerWithEnumsGaps", 21); |
- EXPECT_FALSE(schema.Validate(bundle)); |
+ TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false); |
bundle.SetInteger("IntegerWithEnumsGaps", 29); |
- EXPECT_FALSE(schema.Validate(bundle)); |
+ TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false); |
bundle.SetInteger("IntegerWithEnumsGaps", 30); |
- EXPECT_TRUE(schema.Validate(bundle)); |
+ TestSchemaValidation(schema, bundle, SCHEMA_STRICT, true); |
bundle.SetInteger("IntegerWithEnumsGaps", 31); |
- EXPECT_FALSE(schema.Validate(bundle)); |
+ TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false); |
bundle.SetInteger("IntegerWithEnumsGaps", 100); |
- EXPECT_FALSE(schema.Validate(bundle)); |
+ TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false); |
bundle.SetInteger("IntegerWithEnumsGaps", 20); |
bundle.SetString("StringWithEnums", "FOUR"); |
- EXPECT_FALSE(schema.Validate(bundle)); |
+ TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false); |
bundle.SetString("StringWithEnums", "two"); |
bundle.SetInteger("IntegerWithRange", 4); |
- EXPECT_FALSE(schema.Validate(bundle)); |
+ TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false); |
bundle.SetInteger("IntegerWithRange", 3); |
+ // Unknown top level property. |
+ bundle.SetString("boom", "bang"); |
+ TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false); |
+ TestSchemaValidation(schema, bundle, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, true); |
+ TestSchemaValidation(schema, bundle, SCHEMA_ALLOW_UNKNOWN, true); |
+ bundle.Remove("boom", NULL); |
+ |
+ // Invalid top level property. |
+ bundle.SetInteger("Boolean", 12345); |
+ TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false); |
+ TestSchemaValidation(schema, bundle, SCHEMA_ALLOW_INVALID_TOPLEVEL, true); |
+ TestSchemaValidation(schema, bundle, SCHEMA_ALLOW_INVALID, true); |
+ bundle.SetBoolean("Boolean", true); |
+ |
+ // Tests on ObjectOfObject. |
+ { |
+ Schema subschema = schema.GetProperty("ObjectOfObject"); |
+ ASSERT_TRUE(subschema.valid()); |
+ base::DictionaryValue root; |
+ |
+ // Unknown property. |
+ root.SetBoolean("Object.three", false); |
+ TestSchemaValidation(subschema, root, SCHEMA_STRICT, false); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, false); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, true); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID_TOPLEVEL, true); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID, true); |
+ root.Remove("Object.three", NULL); |
+ |
+ // Invalid property. |
+ root.SetInteger("Object.one", 12345); |
+ TestSchemaValidation(subschema, root, SCHEMA_STRICT, false); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, false); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, false); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID_TOPLEVEL, true); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID, true); |
+ root.Remove("Object.one", NULL); |
+ } |
+ |
+ // Tests on ArrayOfObjects. |
+ { |
+ Schema subschema = schema.GetProperty("ArrayOfObjects"); |
+ ASSERT_TRUE(subschema.valid()); |
+ base::ListValue root; |
+ |
+ // Unknown property. |
+ base::DictionaryValue* dict_value = new base::DictionaryValue(); |
+ dict_value->SetBoolean("three", true); |
+ root.Append(dict_value); // Pass ownership to root. |
+ TestSchemaValidation(subschema, root, SCHEMA_STRICT, false); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, false); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, true); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID_TOPLEVEL, true); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID, true); |
+ root.Remove(root.GetSize() - 1, NULL); |
+ |
+ // Invalid property. |
+ dict_value = new base::DictionaryValue(); |
+ dict_value->SetBoolean("two", true); |
+ root.Append(dict_value); // Pass ownership to root. |
+ TestSchemaValidation(subschema, root, SCHEMA_STRICT, false); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, false); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, false); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID_TOPLEVEL, true); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID, true); |
+ root.Remove(root.GetSize() - 1, NULL); |
+ } |
+ |
+ // Tests on ObjectOfArray. |
+ { |
+ Schema subschema = schema.GetProperty("ObjectOfArray"); |
+ ASSERT_TRUE(subschema.valid()); |
+ base::DictionaryValue root; |
+ |
+ base::ListValue* list_value = new base::ListValue(); |
+ root.Set("List", list_value); // Pass ownership to root. |
+ |
+ // No errors. |
+ list_value->Append(new base::FundamentalValue(12345)); |
+ TestSchemaValidation(subschema, root, SCHEMA_STRICT, true); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, true); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, true); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID_TOPLEVEL, true); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID, true); |
+ |
+ // Invalid list item. |
+ list_value->Append(new base::StringValue("blabla")); |
+ TestSchemaValidation(subschema, root, SCHEMA_STRICT, false); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, false); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, false); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID_TOPLEVEL, true); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID, true); |
+ } |
+ |
+ // Tests on ArrayOfObjectOfArray. |
+ { |
+ Schema subschema = schema.GetProperty("ArrayOfObjectOfArray"); |
+ ASSERT_TRUE(subschema.valid()); |
+ base::ListValue root; |
+ |
+ base::ListValue* list_value = new base::ListValue(); |
+ base::DictionaryValue* dict_value = new base::DictionaryValue(); |
+ dict_value->Set("List", list_value); // Pass ownership to dict_value. |
+ root.Append(dict_value); // Pass ownership to root. |
+ |
+ // No errors. |
+ list_value->Append(new base::StringValue("blabla")); |
+ TestSchemaValidation(subschema, root, SCHEMA_STRICT, true); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, true); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, true); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID_TOPLEVEL, true); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID, true); |
+ |
+ // Invalid list item. |
+ list_value->Append(new base::FundamentalValue(12345)); |
+ TestSchemaValidation(subschema, root, SCHEMA_STRICT, false); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, false); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, false); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID_TOPLEVEL, true); |
+ TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID, true); |
+ } |
+ |
+ // Test that integer to double promotion is allowed. |
+ bundle.SetInteger("Number", 31415); |
+ TestSchemaValidation(schema, bundle, SCHEMA_STRICT, true); |
} |
+ |
TEST(SchemaTest, InvalidReferences) { |
// References to undeclared schemas fail. |
EXPECT_TRUE(ParseFails( |