OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "chrome/common/json_schema_validator_unittest_base.h" |
| 6 |
| 7 #include "base/file_util.h" |
| 8 #include "base/path_service.h" |
| 9 #include "base/scoped_ptr.h" |
| 10 #include "base/stringprintf.h" |
| 11 #include "base/values.h" |
| 12 #include "chrome/common/chrome_paths.h" |
| 13 #include "chrome/common/json_schema_validator.h" |
| 14 #include "chrome/common/json_value_serializer.h" |
| 15 |
| 16 namespace { |
| 17 |
| 18 #define TEST_SOURCE base::StringPrintf("%s:%i", __FILE__, __LINE__) |
| 19 |
| 20 Value* LoadValue(const std::string& filename) { |
| 21 FilePath path; |
| 22 PathService::Get(chrome::DIR_TEST_DATA, &path); |
| 23 path = path.AppendASCII("json_schema_validator").AppendASCII(filename); |
| 24 EXPECT_TRUE(file_util::PathExists(path)); |
| 25 |
| 26 std::string error_message; |
| 27 JSONFileValueSerializer serializer(path); |
| 28 Value* result = serializer.Deserialize(NULL, &error_message); |
| 29 if (!result) |
| 30 ADD_FAILURE() << "Could not parse JSON: " << error_message; |
| 31 return result; |
| 32 } |
| 33 |
| 34 Value* LoadValue(const std::string& filename, Value::ValueType type) { |
| 35 scoped_ptr<Value> result(LoadValue(filename)); |
| 36 if (!result.get()) |
| 37 return NULL; |
| 38 if (!result->IsType(type)) { |
| 39 ADD_FAILURE() << "Expected type " << type << ", got: " << result->GetType(); |
| 40 return NULL; |
| 41 } |
| 42 return result.release(); |
| 43 } |
| 44 |
| 45 ListValue* LoadList(const std::string& filename) { |
| 46 return static_cast<ListValue*>( |
| 47 LoadValue(filename, Value::TYPE_LIST)); |
| 48 } |
| 49 |
| 50 DictionaryValue* LoadDictionary(const std::string& filename) { |
| 51 return static_cast<DictionaryValue*>( |
| 52 LoadValue(filename, Value::TYPE_DICTIONARY)); |
| 53 } |
| 54 |
| 55 } |
| 56 |
| 57 JSONSchemaValidatorTestBase::JSONSchemaValidatorTestBase( |
| 58 JSONSchemaValidatorTestBase::ValidatorType type) |
| 59 : type_(type) { |
| 60 } |
| 61 |
| 62 void JSONSchemaValidatorTestBase::RunTests() { |
| 63 TestComplex(); |
| 64 TestStringPattern(); |
| 65 TestEnum(); |
| 66 TestChoices(); |
| 67 TestExtends(); |
| 68 TestObject(); |
| 69 TestTypeReference(); |
| 70 } |
| 71 |
| 72 void JSONSchemaValidatorTestBase::TestComplex() { |
| 73 scoped_ptr<DictionaryValue> schema(LoadDictionary("complex_schema.json")); |
| 74 scoped_ptr<ListValue> instance(LoadList("complex_instance.json")); |
| 75 |
| 76 ASSERT_TRUE(schema.get()); |
| 77 ASSERT_TRUE(instance.get()); |
| 78 |
| 79 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), NULL); |
| 80 instance->Remove(instance->GetSize() - 1, NULL); |
| 81 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), NULL); |
| 82 instance->Append(new DictionaryValue()); |
| 83 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), NULL, "1", |
| 84 JSONSchemaValidator::FormatErrorMessage( |
| 85 JSONSchemaValidator::kInvalidType, "number", "object")); |
| 86 instance->Remove(instance->GetSize() - 1, NULL); |
| 87 |
| 88 DictionaryValue* item = NULL; |
| 89 ASSERT_TRUE(instance->GetDictionary(0, &item)); |
| 90 item->SetString("url", "xxxxxxxxxxx"); |
| 91 |
| 92 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), NULL, |
| 93 "0.url", |
| 94 JSONSchemaValidator::FormatErrorMessage( |
| 95 JSONSchemaValidator::kStringMaxLength, "10")); |
| 96 } |
| 97 |
| 98 void JSONSchemaValidatorTestBase::TestStringPattern() { |
| 99 // Regex patterns not supported in CPP validator. |
| 100 if (type_ == CPP) |
| 101 return; |
| 102 |
| 103 scoped_ptr<DictionaryValue> schema( |
| 104 LoadDictionary("string_pattern_schema.json")); |
| 105 scoped_ptr<DictionaryValue> instance( |
| 106 LoadDictionary("string_pattern_instance.json")); |
| 107 |
| 108 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), NULL); |
| 109 instance->SetString("prop", "fooooooo"); |
| 110 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), NULL); |
| 111 instance->SetString("prop", "bar"); |
| 112 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), NULL, |
| 113 "prop", JSONSchemaValidator::FormatErrorMessage( |
| 114 JSONSchemaValidator::kStringPattern, "foo+")); |
| 115 } |
| 116 |
| 117 void JSONSchemaValidatorTestBase::TestEnum() { |
| 118 scoped_ptr<DictionaryValue> schema(LoadDictionary("enum_schema.json")); |
| 119 |
| 120 ExpectValid(TEST_SOURCE, |
| 121 scoped_ptr<Value>(Value::CreateStringValue("foo")).get(), |
| 122 schema.get(), NULL); |
| 123 ExpectValid(TEST_SOURCE, |
| 124 scoped_ptr<Value>(Value::CreateIntegerValue(42)).get(), |
| 125 schema.get(), NULL); |
| 126 ExpectValid(TEST_SOURCE, |
| 127 scoped_ptr<Value>(Value::CreateBooleanValue(false)).get(), |
| 128 schema.get(), NULL); |
| 129 |
| 130 ExpectNotValid(TEST_SOURCE, |
| 131 scoped_ptr<Value>(Value::CreateStringValue("42")).get(), |
| 132 schema.get(), NULL, "", JSONSchemaValidator::kInvalidEnum); |
| 133 ExpectNotValid(TEST_SOURCE, |
| 134 scoped_ptr<Value>(Value::CreateNullValue()).get(), |
| 135 schema.get(), NULL, "", JSONSchemaValidator::kInvalidEnum); |
| 136 } |
| 137 |
| 138 void JSONSchemaValidatorTestBase::TestChoices() { |
| 139 scoped_ptr<DictionaryValue> schema(LoadDictionary("choices_schema.json")); |
| 140 |
| 141 ExpectValid(TEST_SOURCE, |
| 142 scoped_ptr<Value>(Value::CreateNullValue()).get(), |
| 143 schema.get(), NULL); |
| 144 ExpectValid(TEST_SOURCE, |
| 145 scoped_ptr<Value>(Value::CreateIntegerValue(42)).get(), |
| 146 schema.get(), NULL); |
| 147 |
| 148 scoped_ptr<DictionaryValue> instance(new DictionaryValue()); |
| 149 instance->SetString("foo", "bar"); |
| 150 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), NULL); |
| 151 |
| 152 ExpectNotValid(TEST_SOURCE, |
| 153 scoped_ptr<Value>(Value::CreateStringValue("foo")).get(), |
| 154 schema.get(), NULL, "", JSONSchemaValidator::kInvalidChoice); |
| 155 ExpectNotValid(TEST_SOURCE, |
| 156 scoped_ptr<Value>(new ListValue()).get(), |
| 157 schema.get(), NULL, "", JSONSchemaValidator::kInvalidChoice); |
| 158 |
| 159 instance->SetInteger("foo", 42); |
| 160 ExpectNotValid(TEST_SOURCE, instance.get(), |
| 161 schema.get(), NULL, "", JSONSchemaValidator::kInvalidChoice); |
| 162 } |
| 163 |
| 164 void JSONSchemaValidatorTestBase::TestExtends() { |
| 165 // TODO(aa): JS only |
| 166 } |
| 167 |
| 168 void JSONSchemaValidatorTestBase::TestObject() { |
| 169 scoped_ptr<DictionaryValue> schema(LoadDictionary("object_schema.json")); |
| 170 scoped_ptr<DictionaryValue> instance(LoadDictionary("object_instance.json")); |
| 171 |
| 172 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), NULL); |
| 173 |
| 174 instance->SetBoolean("extra", true); |
| 175 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), NULL, |
| 176 "extra", JSONSchemaValidator::kUnexpectedProperty); |
| 177 |
| 178 instance->Remove("extra", NULL); |
| 179 instance->Remove("bar", NULL); |
| 180 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), NULL, "bar", |
| 181 JSONSchemaValidator::kObjectPropertyIsRequired); |
| 182 |
| 183 instance->SetString("bar", "42"); |
| 184 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), NULL, "bar", |
| 185 JSONSchemaValidator::FormatErrorMessage( |
| 186 JSONSchemaValidator::kInvalidType, "integer", "string")); |
| 187 |
| 188 DictionaryValue* additional_properties = new DictionaryValue(); |
| 189 additional_properties->SetString("type", "any"); |
| 190 schema->Set("additionalProperties", additional_properties); |
| 191 |
| 192 instance->SetInteger("bar", 42); |
| 193 instance->SetBoolean("extra", true); |
| 194 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), NULL); |
| 195 |
| 196 instance->SetString("extra", "foo"); |
| 197 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), NULL); |
| 198 |
| 199 additional_properties->SetString("type", "boolean"); |
| 200 instance->SetBoolean("extra", true); |
| 201 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), NULL); |
| 202 |
| 203 instance->SetString("extra", "foo"); |
| 204 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), NULL, |
| 205 "extra", JSONSchemaValidator::FormatErrorMessage( |
| 206 JSONSchemaValidator::kInvalidType, "boolean", "string")); |
| 207 |
| 208 DictionaryValue* properties = NULL; |
| 209 DictionaryValue* bar_property = NULL; |
| 210 CHECK(schema->GetDictionary("properties", &properties)); |
| 211 CHECK(properties->GetDictionary("bar", &bar_property)); |
| 212 |
| 213 bar_property->SetBoolean("optional", true); |
| 214 instance->Remove("extra", NULL); |
| 215 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), NULL); |
| 216 instance->Remove("bar", NULL); |
| 217 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), NULL); |
| 218 instance->Set("bar", Value::CreateNullValue()); |
| 219 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), NULL, |
| 220 "bar", JSONSchemaValidator::FormatErrorMessage( |
| 221 JSONSchemaValidator::kInvalidType, "integer", "null")); |
| 222 instance->SetString("bar", "42"); |
| 223 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), NULL, |
| 224 "bar", JSONSchemaValidator::FormatErrorMessage( |
| 225 JSONSchemaValidator::kInvalidType, "integer", "string")); |
| 226 } |
| 227 |
| 228 void JSONSchemaValidatorTestBase::TestTypeReference() { |
| 229 scoped_ptr<ListValue> types(LoadList("reference_types.json")); |
| 230 scoped_ptr<DictionaryValue> schema(LoadDictionary("reference_schema.json")); |
| 231 scoped_ptr<DictionaryValue> schema_inline( |
| 232 LoadDictionary("reference_schema_inline.json")); |
| 233 scoped_ptr<DictionaryValue> instance( |
| 234 LoadDictionary("reference_instance.json")); |
| 235 scoped_ptr<DictionaryValue> instance_inline( |
| 236 LoadDictionary("reference_instance_inline.json")); |
| 237 |
| 238 ASSERT_TRUE(types.get()); |
| 239 ASSERT_TRUE(schema.get()); |
| 240 ASSERT_TRUE(schema_inline.get()); |
| 241 ASSERT_TRUE(instance.get()); |
| 242 ASSERT_TRUE(instance_inline.get()); |
| 243 |
| 244 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), types.get()); |
| 245 ExpectValid(TEST_SOURCE, instance_inline.get(), schema_inline.get(), NULL); |
| 246 |
| 247 // Validation failure, but successful schema reference. |
| 248 instance->SetString("baz", "a"); |
| 249 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), types.get(), |
| 250 "baz", JSONSchemaValidator::FormatErrorMessage( |
| 251 JSONSchemaValidator::kStringMinLength, "2")); |
| 252 |
| 253 instance_inline->SetInteger("bar", 20); |
| 254 ExpectNotValid(TEST_SOURCE, instance_inline.get(), schema_inline.get(), NULL, |
| 255 "bar", JSONSchemaValidator::FormatErrorMessage( |
| 256 JSONSchemaValidator::kNumberMaximum, "0")); |
| 257 |
| 258 // Remove MinLengthString type. |
| 259 types->Remove(types->GetSize() - 1, NULL); |
| 260 instance->SetString("baz", "ab"); |
| 261 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), types.get(), |
| 262 "bar", JSONSchemaValidator::FormatErrorMessage( |
| 263 JSONSchemaValidator::kUnknownTypeReference, |
| 264 "Max10Int")); |
| 265 |
| 266 // Remove internal type "NegativeInt". |
| 267 schema_inline->Remove("properties.bar", NULL); |
| 268 instance_inline->Remove("bar", NULL); |
| 269 ExpectNotValid(TEST_SOURCE, instance_inline.get(), schema_inline.get(), NULL, |
| 270 "baz", JSONSchemaValidator::FormatErrorMessage( |
| 271 JSONSchemaValidator::kUnknownTypeReference, |
| 272 "NegativeInt")); |
| 273 } |
OLD | NEW |