зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1440782 Part 1 - Move PolicyEngine's JSON schema validator to toolkit r=Felipe
MozReview-Commit-ID: 41K9xzry21w --HG-- rename : browser/components/enterprisepolicies/PoliciesValidator.jsm => toolkit/components/utils/JsonSchemaValidator.jsm rename : toolkit/components/normandy/test/browser/.eslintrc.js => toolkit/components/utils/test/browser/.eslintrc.js rename : browser/components/enterprisepolicies/tests/browser/browser_policies_validate_and_parse_API.js => toolkit/components/utils/test/browser/browser_JsonSchemaValidator.js extra : rebase_source : ea227390d924cc14a8c5b0f8dde64efcc14bbcd1
This commit is contained in:
Родитель
7d19b65c4f
Коммит
ab318eabb2
|
@ -9,7 +9,7 @@ ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
|
|||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
WindowsGPOParser: "resource:///modules/policies/WindowsGPOParser.jsm",
|
||||
Policies: "resource:///modules/policies/Policies.jsm",
|
||||
PoliciesValidator: "resource:///modules/policies/PoliciesValidator.jsm",
|
||||
JsonSchemaValidator: "resource://gre/modules/components-utils/JsonSchemaValidator.jsm",
|
||||
});
|
||||
|
||||
// This is the file that will be searched for in the
|
||||
|
@ -127,8 +127,7 @@ EnterprisePoliciesManager.prototype = {
|
|||
}
|
||||
|
||||
let [parametersAreValid, parsedParameters] =
|
||||
PoliciesValidator.validateAndParseParameters(policyParameters,
|
||||
policySchema);
|
||||
JsonSchemaValidator.validateAndParseParameters(policyParameters, policySchema);
|
||||
|
||||
if (!parametersAreValid) {
|
||||
log.error(`Invalid parameters specified for ${policyName}.`);
|
||||
|
|
|
@ -24,7 +24,6 @@ EXTRA_COMPONENTS += [
|
|||
|
||||
EXTRA_JS_MODULES.policies += [
|
||||
'Policies.jsm',
|
||||
'PoliciesValidator.jsm',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
|
|
|
@ -18,7 +18,6 @@ support-files =
|
|||
[browser_policies_setAndLockPref_API.js]
|
||||
[browser_policies_simple_pref_policies.js]
|
||||
[browser_policies_sorted_alphabetically.js]
|
||||
[browser_policies_validate_and_parse_API.js]
|
||||
[browser_policy_app_update.js]
|
||||
[browser_policy_block_about_addons.js]
|
||||
[browser_policy_block_about_config.js]
|
||||
|
|
|
@ -1,327 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
/* This file will test the parameters parsing and validation directly through
|
||||
the PoliciesValidator API.
|
||||
*/
|
||||
|
||||
const { PoliciesValidator } = ChromeUtils.import("resource:///modules/policies/PoliciesValidator.jsm", {});
|
||||
|
||||
add_task(async function test_boolean_values() {
|
||||
let schema = {
|
||||
type: "boolean"
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters(true, schema);
|
||||
ok(valid && parsed === true, "Parsed boolean value correctly");
|
||||
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters(false, schema);
|
||||
ok(valid && parsed === false, "Parsed boolean value correctly");
|
||||
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters(0, schema);
|
||||
ok(valid && parsed === false, "0 parsed as false correctly");
|
||||
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters(1, schema);
|
||||
ok(valid && parsed === true, "1 parsed as true correctly");
|
||||
|
||||
// Invalid values:
|
||||
ok(!PoliciesValidator.validateAndParseParameters("0", schema)[0], "No type coercion");
|
||||
ok(!PoliciesValidator.validateAndParseParameters("true", schema)[0], "No type coercion");
|
||||
ok(!PoliciesValidator.validateAndParseParameters(2, schema)[0], "Other number values are not valid");
|
||||
ok(!PoliciesValidator.validateAndParseParameters(undefined, schema)[0], "Invalid value");
|
||||
ok(!PoliciesValidator.validateAndParseParameters({}, schema)[0], "Invalid value");
|
||||
ok(!PoliciesValidator.validateAndParseParameters(null, schema)[0], "Invalid value");
|
||||
});
|
||||
|
||||
add_task(async function test_number_values() {
|
||||
let schema = {
|
||||
type: "number"
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters(1, schema);
|
||||
ok(valid && parsed === 1, "Parsed number value correctly");
|
||||
|
||||
// Invalid values:
|
||||
ok(!PoliciesValidator.validateAndParseParameters("1", schema)[0], "No type coercion");
|
||||
ok(!PoliciesValidator.validateAndParseParameters(true, schema)[0], "Invalid value");
|
||||
ok(!PoliciesValidator.validateAndParseParameters({}, schema)[0], "Invalid value");
|
||||
ok(!PoliciesValidator.validateAndParseParameters(null, schema)[0], "Invalid value");
|
||||
});
|
||||
|
||||
add_task(async function test_integer_values() {
|
||||
// Integer is an alias for number
|
||||
let schema = {
|
||||
type: "integer"
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters(1, schema);
|
||||
ok(valid && parsed == 1, "Parsed integer value correctly");
|
||||
|
||||
// Invalid values:
|
||||
ok(!PoliciesValidator.validateAndParseParameters("1", schema)[0], "No type coercion");
|
||||
ok(!PoliciesValidator.validateAndParseParameters(true, schema)[0], "Invalid value");
|
||||
ok(!PoliciesValidator.validateAndParseParameters({}, schema)[0], "Invalid value");
|
||||
ok(!PoliciesValidator.validateAndParseParameters(null, schema)[0], "Invalid value");
|
||||
});
|
||||
|
||||
add_task(async function test_string_values() {
|
||||
let schema = {
|
||||
type: "string"
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters("foobar", schema);
|
||||
ok(valid && parsed == "foobar", "Parsed string value correctly");
|
||||
|
||||
// Invalid values:
|
||||
ok(!PoliciesValidator.validateAndParseParameters(1, schema)[0], "No type coercion");
|
||||
ok(!PoliciesValidator.validateAndParseParameters(true, schema)[0], "No type coercion");
|
||||
ok(!PoliciesValidator.validateAndParseParameters(undefined, schema)[0], "Invalid value");
|
||||
ok(!PoliciesValidator.validateAndParseParameters({}, schema)[0], "Invalid value");
|
||||
ok(!PoliciesValidator.validateAndParseParameters(null, schema)[0], "Invalid value");
|
||||
});
|
||||
|
||||
add_task(async function test_URL_values() {
|
||||
let schema = {
|
||||
type: "URL"
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters("https://www.example.com/foo#bar", schema);
|
||||
ok(valid, "URL is valid");
|
||||
ok(parsed instanceof Ci.nsIURI, "parsed is a nsIURI");
|
||||
is(parsed.prePath, "https://www.example.com", "prePath is correct");
|
||||
is(parsed.pathQueryRef, "/foo#bar", "pathQueryRef is correct");
|
||||
|
||||
// Invalid values:
|
||||
ok(!PoliciesValidator.validateAndParseParameters("", schema)[0], "Empty string is not accepted for URL");
|
||||
ok(!PoliciesValidator.validateAndParseParameters("www.example.com", schema)[0], "Scheme is required for URL");
|
||||
ok(!PoliciesValidator.validateAndParseParameters("https://:!$%", schema)[0], "Invalid URL");
|
||||
ok(!PoliciesValidator.validateAndParseParameters({}, schema)[0], "Invalid value");
|
||||
});
|
||||
|
||||
add_task(async function test_URLorEmpty_values() {
|
||||
let schema = {
|
||||
type: "URLorEmpty"
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters("https://www.example.com/foo#bar", schema);
|
||||
ok(valid, "URL is valid");
|
||||
ok(parsed instanceof Ci.nsIURI, "parsed is a nsIURI");
|
||||
is(parsed.prePath, "https://www.example.com", "prePath is correct");
|
||||
is(parsed.pathQueryRef, "/foo#bar", "pathQueryRef is correct");
|
||||
|
||||
// Test that this type also accept empty strings
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters("", schema);
|
||||
ok(valid, "URLorEmpty is valid");
|
||||
ok(!parsed, "parsed value is falsy");
|
||||
is(typeof(parsed), "string", "parsed is a string");
|
||||
is(parsed, "", "parsed is an empty string");
|
||||
|
||||
// Invalid values:
|
||||
ok(!PoliciesValidator.validateAndParseParameters(" ", schema)[0], "Non-empty string is not accepted");
|
||||
ok(!PoliciesValidator.validateAndParseParameters("www.example.com", schema)[0], "Scheme is required for URL");
|
||||
ok(!PoliciesValidator.validateAndParseParameters("https://:!$%", schema)[0], "Invalid URL");
|
||||
ok(!PoliciesValidator.validateAndParseParameters({}, schema)[0], "Invalid value");
|
||||
});
|
||||
|
||||
|
||||
add_task(async function test_origin_values() {
|
||||
// Origin is a URL that doesn't contain a path/query string (i.e., it's only scheme + host + port)
|
||||
let schema = {
|
||||
type: "origin"
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters("https://www.example.com", schema);
|
||||
ok(valid, "Origin is valid");
|
||||
ok(parsed instanceof Ci.nsIURI, "parsed is a nsIURI");
|
||||
is(parsed.prePath, "https://www.example.com", "prePath is correct");
|
||||
is(parsed.pathQueryRef, "/", "pathQueryRef is corect");
|
||||
|
||||
// Invalid values:
|
||||
ok(!PoliciesValidator.validateAndParseParameters("https://www.example.com/foobar", schema)[0], "Origin cannot contain a path part");
|
||||
ok(!PoliciesValidator.validateAndParseParameters("https://:!$%", schema)[0], "Invalid origin");
|
||||
ok(!PoliciesValidator.validateAndParseParameters({}, schema)[0], "Invalid value");
|
||||
});
|
||||
|
||||
add_task(async function test_array_values() {
|
||||
// The types inside an array object must all be the same
|
||||
let schema = {
|
||||
type: "array",
|
||||
items: {
|
||||
type: "number"
|
||||
}
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters([1, 2, 3], schema);
|
||||
ok(valid, "Array is valid");
|
||||
ok(Array.isArray(parsed), "parsed is an array");
|
||||
is(parsed.length, 3, "array is correct");
|
||||
|
||||
// An empty array is also valid
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters([], schema);
|
||||
ok(valid, "Array is valid");
|
||||
ok(Array.isArray(parsed), "parsed is an array");
|
||||
is(parsed.length, 0, "array is correct");
|
||||
|
||||
// Invalid values:
|
||||
ok(!PoliciesValidator.validateAndParseParameters([1, true, 3], schema)[0], "Mixed types");
|
||||
ok(!PoliciesValidator.validateAndParseParameters(2, schema)[0], "Type is correct but not in an array");
|
||||
ok(!PoliciesValidator.validateAndParseParameters({}, schema)[0], "Object is not an array");
|
||||
});
|
||||
|
||||
add_task(async function test_object_values() {
|
||||
let schema = {
|
||||
type: "object",
|
||||
properties: {
|
||||
url: {
|
||||
type: "URL"
|
||||
},
|
||||
title: {
|
||||
type: "string"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters(
|
||||
{
|
||||
url: "https://www.example.com/foo#bar",
|
||||
title: "Foo",
|
||||
alias: "Bar"
|
||||
},
|
||||
schema);
|
||||
|
||||
ok(valid, "Object is valid");
|
||||
ok(typeof(parsed) == "object", "parsed in an object");
|
||||
ok(parsed.url instanceof Ci.nsIURI, "types inside the object are also parsed");
|
||||
is(parsed.url.spec, "https://www.example.com/foo#bar", "URL was correctly parsed");
|
||||
is(parsed.title, "Foo", "title was correctly parsed");
|
||||
is(parsed.alias, undefined, "property not described in the schema is not present in the parsed object");
|
||||
|
||||
// Invalid values:
|
||||
ok(!PoliciesValidator.validateAndParseParameters(
|
||||
{
|
||||
url: "https://www.example.com/foo#bar",
|
||||
title: 3,
|
||||
},
|
||||
schema)[0], "Mismatched type for title");
|
||||
|
||||
ok(!PoliciesValidator.validateAndParseParameters(
|
||||
{
|
||||
url: "www.example.com",
|
||||
title: 3,
|
||||
},
|
||||
schema)[0], "Invalid URL inside the object");
|
||||
});
|
||||
|
||||
add_task(async function test_array_of_objects() {
|
||||
// This schema is used, for example, for bookmarks
|
||||
let schema = {
|
||||
type: "array",
|
||||
items: {
|
||||
type: "object",
|
||||
properties: {
|
||||
url: {
|
||||
type: "URL",
|
||||
},
|
||||
title: {
|
||||
type: "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters(
|
||||
[{
|
||||
url: "https://www.example.com/bookmark1",
|
||||
title: "Foo",
|
||||
},
|
||||
{
|
||||
url: "https://www.example.com/bookmark2",
|
||||
title: "Bar",
|
||||
}],
|
||||
schema);
|
||||
|
||||
ok(valid, "Array is valid");
|
||||
is(parsed.length, 2, "Correct number of items");
|
||||
|
||||
ok(typeof(parsed[0]) == "object" && typeof(parsed[1]) == "object", "Correct objects inside array");
|
||||
|
||||
is(parsed[0].url.spec, "https://www.example.com/bookmark1", "Correct URL for bookmark 1");
|
||||
is(parsed[1].url.spec, "https://www.example.com/bookmark2", "Correct URL for bookmark 2");
|
||||
|
||||
is(parsed[0].title, "Foo", "Correct title for bookmark 1");
|
||||
is(parsed[1].title, "Bar", "Correct title for bookmark 2");
|
||||
});
|
||||
|
||||
add_task(async function test_missing_arrays_inside_objects() {
|
||||
let schema = {
|
||||
type: "object",
|
||||
properties: {
|
||||
allow: {
|
||||
type: "array",
|
||||
items: {
|
||||
type: "boolean"
|
||||
}
|
||||
},
|
||||
block: {
|
||||
type: "array",
|
||||
items: {
|
||||
type: "boolean"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters({
|
||||
allow: [true, true, true]
|
||||
}, schema);
|
||||
|
||||
ok(valid, "Object is valid");
|
||||
is(parsed.allow.length, 3, "Allow array is correct.");
|
||||
is(parsed.block, undefined, "Block array is undefined, as expected.");
|
||||
});
|
||||
|
||||
add_task(async function test_required_vs_nonrequired_properties() {
|
||||
let schema = {
|
||||
type: "object",
|
||||
properties: {
|
||||
"non-required-property": {
|
||||
type: "number"
|
||||
},
|
||||
|
||||
"required-property": {
|
||||
type: "number"
|
||||
}
|
||||
},
|
||||
required: ["required-property"]
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters({
|
||||
"required-property": 5
|
||||
}, schema);
|
||||
|
||||
ok(valid, "Object is valid since required property is present");
|
||||
is(parsed["required-property"], 5, "required property is correct");
|
||||
is(parsed["non-required-property"], undefined, "non-required property is undefined, as expected");
|
||||
|
||||
[valid, parsed] = PoliciesValidator.validateAndParseParameters({
|
||||
"non-required-property": 5
|
||||
}, schema);
|
||||
|
||||
ok(!valid, "Object is not valid since the required property is missing");
|
||||
is(parsed, null, "Nothing was returned as parsed");
|
||||
});
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
ChromeUtils.defineModuleGetter(this, "LogManager", "resource://normandy/lib/LogManager.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "Uptake", "resource://normandy/lib/Uptake.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "PoliciesValidator", "resource:///modules/policies/PoliciesValidator.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "JsonSchemaValidator", "resource://gre/modules/components-utils/JsonSchemaValidator.jsm");
|
||||
|
||||
var EXPORTED_SYMBOLS = ["BaseAction"];
|
||||
|
||||
|
@ -72,7 +72,7 @@ class BaseAction {
|
|||
return;
|
||||
}
|
||||
|
||||
let [valid, validatedArguments] = PoliciesValidator.validateAndParseParameters(recipe.arguments, this.schema);
|
||||
let [valid, validatedArguments] = JsonSchemaValidator.validateAndParseParameters(recipe.arguments, this.schema);
|
||||
if (!valid) {
|
||||
Cu.reportError(new Error(`Arguments do not match schema. arguments: ${JSON.stringify(recipe.arguments)}. schema: ${JSON.stringify(this.schema)}`));
|
||||
Uptake.reportRecipe(recipe.id, Uptake.RECIPE_EXECUTION_ERROR);
|
||||
|
|
|
@ -2,27 +2,34 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* This file implements a not-quite standard JSON schema validator. It differs
|
||||
* from the spec in a few ways:
|
||||
*
|
||||
* - the spec doesn't allow custom types to be defined, but this validator
|
||||
* defines "URL", "URLorEmpty", "origin" etc.
|
||||
* - Strings are automatically converted to nsIURIs for the appropriate types.
|
||||
* - It doesn't support "pattern" when matching strings.
|
||||
* - The boolean type accepts (and casts) 0 and 1 as valid values.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const PREF_LOGLEVEL = "browser.policies.loglevel";
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "log", () => {
|
||||
let { ConsoleAPI } = ChromeUtils.import("resource://gre/modules/Console.jsm", {});
|
||||
return new ConsoleAPI({
|
||||
prefix: "PoliciesValidator.jsm",
|
||||
prefix: "JsonSchemaValidator.jsm",
|
||||
// tip: set maxLogLevel to "debug" and use log.debug() to create detailed
|
||||
// messages during development. See LOG_LEVELS in Console.jsm for details.
|
||||
maxLogLevel: "error",
|
||||
maxLogLevelPref: PREF_LOGLEVEL,
|
||||
});
|
||||
});
|
||||
|
||||
var EXPORTED_SYMBOLS = ["PoliciesValidator"];
|
||||
var EXPORTED_SYMBOLS = ["JsonSchemaValidator"];
|
||||
|
||||
var PoliciesValidator = {
|
||||
var JsonSchemaValidator = {
|
||||
validateAndParseParameters(param, properties) {
|
||||
return validateAndParseParamRecursive(param, properties);
|
||||
}
|
||||
|
@ -37,6 +44,24 @@ function validateAndParseParamRecursive(param, properties) {
|
|||
}
|
||||
|
||||
log.debug(`checking @${param}@ for type ${properties.type}`);
|
||||
|
||||
if (Array.isArray(properties.type)) {
|
||||
log.debug("type is an array");
|
||||
// For an array of types, the value is valid if it matches any of the listed
|
||||
// types. To check this, make versions of the object definition that include
|
||||
// only one type at a time, and check the value against each one.
|
||||
for (const type of properties.type) {
|
||||
let typeProperties = Object.assign({}, properties, {type});
|
||||
log.debug(`checking subtype ${type}`);
|
||||
let [valid, data] = validateAndParseParamRecursive(param, typeProperties);
|
||||
if (valid) {
|
||||
return [true, data];
|
||||
}
|
||||
}
|
||||
// None of the types matched
|
||||
return [false, null];
|
||||
}
|
||||
|
||||
switch (properties.type) {
|
||||
case "boolean":
|
||||
case "number":
|
|
@ -13,5 +13,8 @@ EXTRA_COMPONENTS += [
|
|||
]
|
||||
|
||||
EXTRA_JS_MODULES['components-utils'] = [
|
||||
'ClientEnvironment.jsm'
|
||||
'ClientEnvironment.jsm',
|
||||
'JsonSchemaValidator.jsm',
|
||||
]
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
extends: [
|
||||
"plugin:mozilla/browser-test"
|
||||
],
|
||||
|
||||
plugins: [
|
||||
"mozilla"
|
||||
],
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
[browser_JsonSchemaValidator.js]
|
|
@ -0,0 +1,371 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
ChromeUtils.import("resource://gre/modules/components-utils/JsonSchemaValidator.jsm", this);
|
||||
|
||||
add_task(async function test_boolean_values() {
|
||||
let schema = {
|
||||
type: "boolean"
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = JsonSchemaValidator.validateAndParseParameters(true, schema);
|
||||
ok(valid && parsed === true, "Parsed boolean value correctly");
|
||||
|
||||
[valid, parsed] = JsonSchemaValidator.validateAndParseParameters(false, schema);
|
||||
ok(valid && parsed === false, "Parsed boolean value correctly");
|
||||
|
||||
[valid, parsed] = JsonSchemaValidator.validateAndParseParameters(0, schema);
|
||||
ok(valid && parsed === false, "0 parsed as false correctly");
|
||||
|
||||
[valid, parsed] = JsonSchemaValidator.validateAndParseParameters(1, schema);
|
||||
ok(valid && parsed === true, "1 parsed as true correctly");
|
||||
|
||||
// Invalid values:
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters("0", schema)[0], "No type coercion");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters("true", schema)[0], "No type coercion");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters(2, schema)[0], "Other number values are not valid");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters(undefined, schema)[0], "Invalid value");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters({}, schema)[0], "Invalid value");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters(null, schema)[0], "Invalid value");
|
||||
});
|
||||
|
||||
add_task(async function test_number_values() {
|
||||
let schema = {
|
||||
type: "number"
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = JsonSchemaValidator.validateAndParseParameters(1, schema);
|
||||
ok(valid && parsed === 1, "Parsed number value correctly");
|
||||
|
||||
// Invalid values:
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters("1", schema)[0], "No type coercion");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters(true, schema)[0], "Invalid value");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters({}, schema)[0], "Invalid value");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters(null, schema)[0], "Invalid value");
|
||||
});
|
||||
|
||||
add_task(async function test_integer_values() {
|
||||
// Integer is an alias for number
|
||||
let schema = {
|
||||
type: "integer"
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = JsonSchemaValidator.validateAndParseParameters(1, schema);
|
||||
ok(valid && parsed == 1, "Parsed integer value correctly");
|
||||
|
||||
// Invalid values:
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters("1", schema)[0], "No type coercion");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters(true, schema)[0], "Invalid value");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters({}, schema)[0], "Invalid value");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters(null, schema)[0], "Invalid value");
|
||||
});
|
||||
|
||||
add_task(async function test_string_values() {
|
||||
let schema = {
|
||||
type: "string"
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = JsonSchemaValidator.validateAndParseParameters("foobar", schema);
|
||||
ok(valid && parsed == "foobar", "Parsed string value correctly");
|
||||
|
||||
// Invalid values:
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters(1, schema)[0], "No type coercion");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters(true, schema)[0], "No type coercion");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters(undefined, schema)[0], "Invalid value");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters({}, schema)[0], "Invalid value");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters(null, schema)[0], "Invalid value");
|
||||
});
|
||||
|
||||
add_task(async function test_URL_values() {
|
||||
let schema = {
|
||||
type: "URL"
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = JsonSchemaValidator.validateAndParseParameters("https://www.example.com/foo#bar", schema);
|
||||
ok(valid, "URL is valid");
|
||||
ok(parsed instanceof Ci.nsIURI, "parsed is a nsIURI");
|
||||
is(parsed.prePath, "https://www.example.com", "prePath is correct");
|
||||
is(parsed.pathQueryRef, "/foo#bar", "pathQueryRef is correct");
|
||||
|
||||
// Invalid values:
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters("", schema)[0], "Empty string is not accepted for URL");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters("www.example.com", schema)[0], "Scheme is required for URL");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters("https://:!$%", schema)[0], "Invalid URL");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters({}, schema)[0], "Invalid value");
|
||||
});
|
||||
|
||||
add_task(async function test_URLorEmpty_values() {
|
||||
let schema = {
|
||||
type: "URLorEmpty"
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = JsonSchemaValidator.validateAndParseParameters("https://www.example.com/foo#bar", schema);
|
||||
ok(valid, "URL is valid");
|
||||
ok(parsed instanceof Ci.nsIURI, "parsed is a nsIURI");
|
||||
is(parsed.prePath, "https://www.example.com", "prePath is correct");
|
||||
is(parsed.pathQueryRef, "/foo#bar", "pathQueryRef is correct");
|
||||
|
||||
// Test that this type also accept empty strings
|
||||
[valid, parsed] = JsonSchemaValidator.validateAndParseParameters("", schema);
|
||||
ok(valid, "URLorEmpty is valid");
|
||||
ok(!parsed, "parsed value is falsy");
|
||||
is(typeof(parsed), "string", "parsed is a string");
|
||||
is(parsed, "", "parsed is an empty string");
|
||||
|
||||
// Invalid values:
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters(" ", schema)[0], "Non-empty string is not accepted");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters("www.example.com", schema)[0], "Scheme is required for URL");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters("https://:!$%", schema)[0], "Invalid URL");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters({}, schema)[0], "Invalid value");
|
||||
});
|
||||
|
||||
|
||||
add_task(async function test_origin_values() {
|
||||
// Origin is a URL that doesn't contain a path/query string (i.e., it's only scheme + host + port)
|
||||
let schema = {
|
||||
type: "origin"
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = JsonSchemaValidator.validateAndParseParameters("https://www.example.com", schema);
|
||||
ok(valid, "Origin is valid");
|
||||
ok(parsed instanceof Ci.nsIURI, "parsed is a nsIURI");
|
||||
is(parsed.prePath, "https://www.example.com", "prePath is correct");
|
||||
is(parsed.pathQueryRef, "/", "pathQueryRef is corect");
|
||||
|
||||
// Invalid values:
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters("https://www.example.com/foobar", schema)[0], "Origin cannot contain a path part");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters("https://:!$%", schema)[0], "Invalid origin");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters({}, schema)[0], "Invalid value");
|
||||
});
|
||||
|
||||
add_task(async function test_array_values() {
|
||||
// The types inside an array object must all be the same
|
||||
let schema = {
|
||||
type: "array",
|
||||
items: {
|
||||
type: "number"
|
||||
}
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = JsonSchemaValidator.validateAndParseParameters([1, 2, 3], schema);
|
||||
ok(valid, "Array is valid");
|
||||
ok(Array.isArray(parsed), "parsed is an array");
|
||||
is(parsed.length, 3, "array is correct");
|
||||
|
||||
// An empty array is also valid
|
||||
[valid, parsed] = JsonSchemaValidator.validateAndParseParameters([], schema);
|
||||
ok(valid, "Array is valid");
|
||||
ok(Array.isArray(parsed), "parsed is an array");
|
||||
is(parsed.length, 0, "array is correct");
|
||||
|
||||
// Invalid values:
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters([1, true, 3], schema)[0], "Mixed types");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters(2, schema)[0], "Type is correct but not in an array");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters({}, schema)[0], "Object is not an array");
|
||||
});
|
||||
|
||||
add_task(async function test_object_values() {
|
||||
let schema = {
|
||||
type: "object",
|
||||
properties: {
|
||||
url: {
|
||||
type: "URL"
|
||||
},
|
||||
title: {
|
||||
type: "string"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = JsonSchemaValidator.validateAndParseParameters(
|
||||
{
|
||||
url: "https://www.example.com/foo#bar",
|
||||
title: "Foo",
|
||||
alias: "Bar"
|
||||
},
|
||||
schema);
|
||||
|
||||
ok(valid, "Object is valid");
|
||||
ok(typeof(parsed) == "object", "parsed in an object");
|
||||
ok(parsed.url instanceof Ci.nsIURI, "types inside the object are also parsed");
|
||||
is(parsed.url.spec, "https://www.example.com/foo#bar", "URL was correctly parsed");
|
||||
is(parsed.title, "Foo", "title was correctly parsed");
|
||||
is(parsed.alias, undefined, "property not described in the schema is not present in the parsed object");
|
||||
|
||||
// Invalid values:
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters(
|
||||
{
|
||||
url: "https://www.example.com/foo#bar",
|
||||
title: 3,
|
||||
},
|
||||
schema)[0], "Mismatched type for title");
|
||||
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters(
|
||||
{
|
||||
url: "www.example.com",
|
||||
title: 3,
|
||||
},
|
||||
schema)[0], "Invalid URL inside the object");
|
||||
});
|
||||
|
||||
add_task(async function test_array_of_objects() {
|
||||
// This schema is used, for example, for bookmarks
|
||||
let schema = {
|
||||
type: "array",
|
||||
items: {
|
||||
type: "object",
|
||||
properties: {
|
||||
url: {
|
||||
type: "URL",
|
||||
},
|
||||
title: {
|
||||
type: "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = JsonSchemaValidator.validateAndParseParameters(
|
||||
[{
|
||||
url: "https://www.example.com/bookmark1",
|
||||
title: "Foo",
|
||||
},
|
||||
{
|
||||
url: "https://www.example.com/bookmark2",
|
||||
title: "Bar",
|
||||
}],
|
||||
schema);
|
||||
|
||||
ok(valid, "Array is valid");
|
||||
is(parsed.length, 2, "Correct number of items");
|
||||
|
||||
ok(typeof(parsed[0]) == "object" && typeof(parsed[1]) == "object", "Correct objects inside array");
|
||||
|
||||
is(parsed[0].url.spec, "https://www.example.com/bookmark1", "Correct URL for bookmark 1");
|
||||
is(parsed[1].url.spec, "https://www.example.com/bookmark2", "Correct URL for bookmark 2");
|
||||
|
||||
is(parsed[0].title, "Foo", "Correct title for bookmark 1");
|
||||
is(parsed[1].title, "Bar", "Correct title for bookmark 2");
|
||||
});
|
||||
|
||||
add_task(async function test_missing_arrays_inside_objects() {
|
||||
let schema = {
|
||||
type: "object",
|
||||
properties: {
|
||||
allow: {
|
||||
type: "array",
|
||||
items: {
|
||||
type: "boolean"
|
||||
}
|
||||
},
|
||||
block: {
|
||||
type: "array",
|
||||
items: {
|
||||
type: "boolean"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = JsonSchemaValidator.validateAndParseParameters({
|
||||
allow: [true, true, true]
|
||||
}, schema);
|
||||
|
||||
ok(valid, "Object is valid");
|
||||
is(parsed.allow.length, 3, "Allow array is correct.");
|
||||
is(parsed.block, undefined, "Block array is undefined, as expected.");
|
||||
});
|
||||
|
||||
add_task(async function test_required_vs_nonrequired_properties() {
|
||||
let schema = {
|
||||
type: "object",
|
||||
properties: {
|
||||
"non-required-property": {
|
||||
type: "number"
|
||||
},
|
||||
|
||||
"required-property": {
|
||||
type: "number"
|
||||
}
|
||||
},
|
||||
required: ["required-property"]
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
[valid, parsed] = JsonSchemaValidator.validateAndParseParameters({
|
||||
"required-property": 5
|
||||
}, schema);
|
||||
|
||||
ok(valid, "Object is valid since required property is present");
|
||||
is(parsed["required-property"], 5, "required property is correct");
|
||||
is(parsed["non-required-property"], undefined, "non-required property is undefined, as expected");
|
||||
|
||||
[valid, parsed] = JsonSchemaValidator.validateAndParseParameters({
|
||||
"non-required-property": 5
|
||||
}, schema);
|
||||
|
||||
ok(!valid, "Object is not valid since the required property is missing");
|
||||
is(parsed, null, "Nothing was returned as parsed");
|
||||
});
|
||||
|
||||
add_task(async function test_number_or_string_values() {
|
||||
let schema = {
|
||||
type: ["number", "string"],
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
// valid values
|
||||
[valid, parsed] = JsonSchemaValidator.validateAndParseParameters(1, schema);
|
||||
ok(valid && parsed === 1, "Parsed number value correctly");
|
||||
[valid, parsed] = JsonSchemaValidator.validateAndParseParameters("foobar", schema);
|
||||
ok(valid && parsed === "foobar", "Parsed string value correctly");
|
||||
[valid, parsed] = JsonSchemaValidator.validateAndParseParameters("1", schema);
|
||||
ok(valid && parsed === "1", "Did not coerce string to number");
|
||||
|
||||
// Invalid values:
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters(true, schema)[0], "Invalid value");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters({}, schema)[0], "Invalid value");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters(null, schema)[0], "Invalid value");
|
||||
});
|
||||
|
||||
add_task(async function test_number_or_array_values() {
|
||||
let schema = {
|
||||
type: ["number", "array"],
|
||||
items: {
|
||||
type: "number",
|
||||
}
|
||||
};
|
||||
|
||||
let valid, parsed;
|
||||
// valid values
|
||||
[valid, parsed] = JsonSchemaValidator.validateAndParseParameters(1, schema);
|
||||
ok(valid, "Number is valid");
|
||||
is(parsed, 1, "Parsed correctly");
|
||||
ok(valid && parsed === 1, "Parsed number value correctly");
|
||||
|
||||
[valid, parsed] = JsonSchemaValidator.validateAndParseParameters([1, 2, 3], schema);
|
||||
ok(valid, "Array is valid");
|
||||
Assert.deepEqual(parsed, [1, 2, 3], "Parsed correctly");
|
||||
|
||||
// Invalid values:
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters(true, schema)[0], "Invalid value");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters({}, schema)[0], "Invalid value");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters(null, schema)[0], "Invalid value");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters(["a", "b"], schema)[0], "Invalid value");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters([[]], schema)[0], "Invalid value");
|
||||
ok(!JsonSchemaValidator.validateAndParseParameters([0, 1, [2, 3]], schema)[0], "Invalid value");
|
||||
});
|
Загрузка…
Ссылка в новой задаче