diff options
author | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-14 23:40:41 +0000 |
---|---|---|
committer | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-14 23:40:41 +0000 |
commit | 4c29efd402105cd29908d21550829bc089a8fe36 (patch) | |
tree | e2e2ac0f5a5d47db3417c1e85205c57ede5e7cb8 /chrome/test/data/extensions/json_schema_test.js | |
parent | 5ea8fc38c5cc261077b61469d8ccb158f3e347b8 (diff) | |
download | chromium_src-4c29efd402105cd29908d21550829bc089a8fe36.zip chromium_src-4c29efd402105cd29908d21550829bc089a8fe36.tar.gz chromium_src-4c29efd402105cd29908d21550829bc089a8fe36.tar.bz2 |
Add JsonSchema-based validation for the tab APIs.
Arv: can you take json_schema.js and json_schema_test.js.
Matt: you take the rest.
Review URL: http://codereview.chromium.org/66006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@13720 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/test/data/extensions/json_schema_test.js')
-rwxr-xr-x | chrome/test/data/extensions/json_schema_test.js | 314 |
1 files changed, 314 insertions, 0 deletions
diff --git a/chrome/test/data/extensions/json_schema_test.js b/chrome/test/data/extensions/json_schema_test.js new file mode 100755 index 0000000..497c344 --- /dev/null +++ b/chrome/test/data/extensions/json_schema_test.js @@ -0,0 +1,314 @@ +// Copyright (c) 2009 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. + +function assert(truth) { + if (!truth) + throw new Error("Assertion failed."); +} + +function assertValid(type, instance, schema) { + var validator = new chromium.JSONSchemaValidator(); + validator["validate" + type](instance, schema, ""); + if (validator.errors.length != 0) { + console.log("Got unexpected errors"); + console.log(validator.errors); + assert(false); + } +} + +function assertNotValid(type, instance, schema, errors) { + var validator = new chromium.JSONSchemaValidator(); + validator["validate" + type](instance, schema, ""); + assert(validator.errors.length === errors.length); + for (var i = 0; i < errors.length; i++) { + if (validator.errors[i].message == errors[i]) { + log("Got expected error: " + validator.errors[i].message + " for path: " + + validator.errors[i].path); + } else { + log("Missed expected error: " + errors[i] + ". Got: " + + validator.errors[i].message + " instead."); + assert(false); + } + } +} + +function formatError(key, replacements) { + return chromium.JSONSchemaValidator.formatError(key, replacements); +} + +function testFormatError() { + assert(formatError("propertyRequired") == "Property is required."); + assert(formatError("invalidEnum", ["foo, bar"]) == + "Value must be one of: [foo, bar]."); + assert(formatError("invalidType", ["foo", "bar"]) == + "Expected 'foo' but got 'bar'."); +} + +function testComplex() { + var schema = { + type: "array", + items: [ + { + type: "object", + properties: { + id: { + type: "integer", + minimum: 1 + }, + url: { + type: "string", + pattern: /^https?\:/, + optional: true + }, + index: { + type: "integer", + minimum: 0, + optional: true + }, + selected: { + type: "boolean", + optional: true + } + } + }, + { type: "function", optional: true }, + { type: "function", optional: true } + ] + }; + + var instance = [ + { + id: 42, + url: "http://www.google.com/", + index: 2, + selected: true + }, + function(){}, + function(){} + ]; + + assertValid("", instance, schema); + instance.length = 2; + assertValid("", instance, schema); + instance.length = 1; + instance.push({}); + assertNotValid("", instance, schema, + [formatError("invalidType", ["function", "object"])]); + instance[1] = function(){}; + + instance[0].url = "foo"; + assertNotValid("", instance, schema, + [formatError("stringPattern", + [schema.items[0].properties.url.pattern])]); + delete instance[0].url; + assertValid("", instance, schema); + + instance[0].id = 0; + assertNotValid("", instance, schema, + [formatError("numberMinValue", + [schema.items[0].properties.id.minimum])]); +} + +function testEnum() { + var schema = { + enum: ["foo", 42, false] + }; + + assertValid("", "foo", schema); + assertValid("", 42, schema); + assertValid("", false, schema); + assertNotValid("", "42", schema, [formatError("invalidEnum", + [schema.enum.join(", ")])]); + assertNotValid("", null, schema, [formatError("invalidEnum", + [schema.enum.join(", ")])]); +} + +function testExtends() { + var parent = { + type: "number" + } + var schema = { + extends: parent + }; + + assertValid("", 42, schema); + assertNotValid("", "42", schema, + [formatError("invalidType", ["number", "string"])]); + + // Make the derived schema more restrictive + parent.minimum = 43; + assertNotValid("", 42, schema, [formatError("numberMinValue", [43])]); + assertValid("", 43, schema); +} + +function testObject() { + var schema = { + properties: { + "foo": { + type: "string" + }, + "bar": { + type: "integer" + } + } + }; + + assertValid("Object", {foo:"foo",bar:42}, schema); + assertValid("Object", {foo:"foo",bar:42,"extra":true}, schema); + assertNotValid("Object", {foo:"foo"}, schema, + [formatError("propertyRequired")]); + assertNotValid("Object", {foo:"foo", bar:"42"}, schema, + [formatError("invalidType", ["integer", "string"])]); + + schema.additionalProperties = false; + assertNotValid("Object", {foo:"foo",bar:42,"extra":true}, schema, + [formatError("unexpectedProperty")]); + + schema.additionalProperties = { + type: "boolean" + }; + assertValid("Object", {foo:"foo",bar:42,"extra":true}, schema); + + schema.properties.bar.optional = true; + assertValid("Object", {foo:"foo",bar:42}, schema); + assertValid("Object", {foo:"foo"}, schema); + assertNotValid("Object", {foo:"foo", bar:"42"}, schema, + [formatError("invalidType", ["integer", "string"])]); +} + +function testArrayTuple() { + var schema = { + items: [ + { + type: "string" + }, + { + type: "integer" + } + ] + }; + + assertValid("Array", ["42", 42], schema); + assertValid("Array", ["42", 42, "anything"], schema); + assertNotValid("Array", ["42"], schema, [formatError("itemRequired")]); + assertNotValid("Array", [42, 42], schema, + [formatError("invalidType", ["string", "integer"])]); + + schema.additionalProperties = false; + assertNotValid("Array", ["42", 42, "anything"], schema, + [formatError("arrayMaxItems", [schema.items.length])]); + + schema.additionalProperties = { + type: "boolean" + }; + assertNotValid("Array", ["42", 42, "anything"], schema, + [formatError("invalidType", ["boolean", "string"])]); + assertValid("Array", ["42", 42, false], schema); + + schema.items[0].optional = true; + assertValid("Array", ["42", 42], schema); + assertValid("Array", [, 42], schema); + assertNotValid("Array", [42, 42], schema, + [formatError("invalidType", ["string", "integer"])]); +} + +function testArrayNonTuple() { + var schema = { + items: { + type: "string" + }, + minItems: 2, + maxItems: 3 + }; + + assertValid("Array", ["x", "x"], schema); + assertValid("Array", ["x", "x", "x"], schema); + + assertNotValid("Array", ["x"], schema, + [formatError("arrayMinItems", [schema.minItems])]); + assertNotValid("Array", ["x", "x", "x", "x"], schema, + [formatError("arrayMaxItems", [schema.maxItems])]); + assertNotValid("Array", [42], schema, + [formatError("arrayMinItems", [schema.minItems]), + formatError("invalidType", ["string", "integer"])]); +} + +function testString() { + var schema = { + minLength: 1, + maxLength: 10, + pattern: /^x/ + }; + + assertValid("String", "x", schema); + assertValid("String", "xxxxxxxxxx", schema); + + assertNotValid("String", "y", schema, + [formatError("stringPattern", [schema.pattern])]); + assertNotValid("String", "xxxxxxxxxxx", schema, + [formatError("stringMaxLength", [schema.maxLength])]); + assertNotValid("String", "", schema, + [formatError("stringMinLength", [schema.minLength]), + formatError("stringPattern", [schema.pattern])]); +} + +function testNumber() { + var schema = { + minimum: 1, + maximum: 100, + maxDecimal: 2 + }; + + assertValid("Number", 1, schema); + assertValid("Number", 50, schema); + assertValid("Number", 100, schema); + assertValid("Number", 88.88, schema); + + assertNotValid("Number", 0.5, schema, + [formatError("numberMinValue", [schema.minimum])]); + assertNotValid("Number", 100.1, schema, + [formatError("numberMaxValue", [schema.maximum])]); + assertNotValid("Number", 100.111, schema, + [formatError("numberMaxValue", [schema.maximum]), + formatError("numberMaxDecimal", [schema.maxDecimal])]); +} + +function testType() { + // valid + assertValid("Type", {}, {type:"object"}); + assertValid("Type", [], {type:"array"}); + assertValid("Type", function(){}, {type:"function"}); + assertValid("Type", "foobar", {type:"string"}); + assertValid("Type", "", {type:"string"}); + assertValid("Type", 88.8, {type:"number"}); + assertValid("Type", 42, {type:"number"}); + assertValid("Type", 0, {type:"number"}); + assertValid("Type", 42, {type:"integer"}); + assertValid("Type", 0, {type:"integer"}); + assertValid("Type", true, {type:"boolean"}); + assertValid("Type", false, {type:"boolean"}); + assertValid("Type", null, {type:"null"}); + + // not valid + assertNotValid("Type", [], {type: "object"}, + [formatError("invalidType", ["object", "array"])]); + assertNotValid("Type", null, {type: "object"}, + [formatError("invalidType", ["object", "null"])]); + assertNotValid("Type", function(){}, {type: "object"}, + [formatError("invalidType", ["object", "function"])]); + assertNotValid("Type", 42, {type: "array"}, + [formatError("invalidType", ["array", "integer"])]); + assertNotValid("Type", 42, {type: "string"}, + [formatError("invalidType", ["string", "integer"])]); + assertNotValid("Type", "42", {type: "number"}, + [formatError("invalidType", ["number", "string"])]); + assertNotValid("Type", 88.8, {type: "integer"}, + [formatError("invalidType", ["integer", "number"])]); + assertNotValid("Type", 1, {type: "boolean"}, + [formatError("invalidType", ["boolean", "integer"])]); + assertNotValid("Type", false, {type: "null"}, + [formatError("invalidType", ["null", "boolean"])]); + assertNotValid("Type", {}, {type: "function"}, + [formatError("invalidType", ["function", "object"])]); +} |