diff options
Diffstat (limited to 'test/test-json-schema.js')
-rw-r--r-- | test/test-json-schema.js | 1048 |
1 files changed, 0 insertions, 1048 deletions
diff --git a/test/test-json-schema.js b/test/test-json-schema.js deleted file mode 100644 index f9cb023c..00000000 --- a/test/test-json-schema.js +++ /dev/null @@ -1,1048 +0,0 @@ -/* - * Copyright (C) 2023 Yomitan Authors - * Copyright (C) 2020-2022 Yomichan Authors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - */ - -const assert = require('assert'); -const {testMain} = require('../dev/util'); -const {VM} = require('../dev/vm'); - -const vm = new VM(); -vm.execute([ - 'js/core.js', - 'js/core/extension-error.js', - 'js/general/cache-map.js', - 'js/data/json-schema.js' -]); -/** @type {typeof JsonSchema} */ -const JsonSchema2 = vm.getSingle('JsonSchema'); - - -/** - * @param {import('json-schema').Schema} schema - * @param {unknown} value - * @returns {boolean} - */ -function schemaValidate(schema, value) { - return new JsonSchema2(schema).isValid(value); -} - -/** - * @param {import('json-schema').Schema} schema - * @param {unknown} value - * @returns {import('json-schema').Value} - */ -function getValidValueOrDefault(schema, value) { - return new JsonSchema2(schema).getValidValueOrDefault(value); -} - -/** - * @param {import('json-schema').Schema} schema - * @param {import('json-schema').Value} value - * @returns {import('json-schema').Value} - */ -function createProxy(schema, value) { - return new JsonSchema2(schema).createProxy(value); -} - -/** - * @template T - * @param {T} value - * @returns {T} - */ -function clone(value) { - return JSON.parse(JSON.stringify(value)); -} - - -/** */ -function testValidate1() { - /** @type {import('json-schema').Schema} */ - const schema = { - allOf: [ - { - type: 'number' - }, - { - anyOf: [ - {minimum: 10, maximum: 100}, - {minimum: -100, maximum: -10} - ] - }, - { - oneOf: [ - {multipleOf: 3}, - {multipleOf: 5} - ] - }, - { - not: { - anyOf: [ - {multipleOf: 20} - ] - } - } - ] - }; - - /** - * @param {number} value - * @returns {boolean} - */ - const jsValidate = (value) => { - return ( - typeof value === 'number' && - ( - (value >= 10 && value <= 100) || - (value >= -100 && value <= -10) - ) && - ( - ( - (value % 3) === 0 || - (value % 5) === 0 - ) && - (value % 15) !== 0 - ) && - (value % 20) !== 0 - ); - }; - - for (let i = -111; i <= 111; i++) { - const actual = schemaValidate(schema, i); - const expected = jsValidate(i); - assert.strictEqual(actual, expected, `i=${i}; expected=${expected}; actual=${actual}`); - } -} - -/** */ -function testValidate2() { - /** @type {{schema: import('json-schema').Schema, inputs: {expected: boolean, value: unknown}[]}[]} */ - const data = [ - // String tests - { - schema: { - type: 'string' - }, - inputs: [ - {expected: false, value: null}, - {expected: false, value: void 0}, - {expected: false, value: 0}, - {expected: false, value: {}}, - {expected: false, value: []}, - {expected: true, value: ''} - ] - }, - { - schema: { - type: 'string', - minLength: 2 - }, - inputs: [ - {expected: false, value: ''}, - {expected: false, value: '1'}, - {expected: true, value: '12'}, - {expected: true, value: '123'} - ] - }, - { - schema: { - type: 'string', - maxLength: 2 - }, - inputs: [ - {expected: true, value: ''}, - {expected: true, value: '1'}, - {expected: true, value: '12'}, - {expected: false, value: '123'} - ] - }, - { - schema: { - type: 'string', - pattern: 'test' - }, - inputs: [ - {expected: false, value: ''}, - {expected: true, value: 'test'}, - {expected: false, value: 'TEST'}, - {expected: true, value: 'ABCtestDEF'}, - {expected: false, value: 'ABCTESTDEF'} - ] - }, - { - schema: { - type: 'string', - pattern: '^test$' - }, - inputs: [ - {expected: false, value: ''}, - {expected: true, value: 'test'}, - {expected: false, value: 'TEST'}, - {expected: false, value: 'ABCtestDEF'}, - {expected: false, value: 'ABCTESTDEF'} - ] - }, - { - schema: { - type: 'string', - pattern: '^test$', - patternFlags: 'i' - }, - inputs: [ - {expected: false, value: ''}, - {expected: true, value: 'test'}, - {expected: true, value: 'TEST'}, - {expected: false, value: 'ABCtestDEF'}, - {expected: false, value: 'ABCTESTDEF'} - ] - }, - { - schema: { - type: 'string', - pattern: '*' - }, - inputs: [ - {expected: false, value: ''} - ] - }, - { - schema: { - type: 'string', - pattern: '.', - patternFlags: '?' - }, - inputs: [ - {expected: false, value: ''} - ] - }, - - // Const tests - { - schema: { - const: 32 - }, - inputs: [ - {expected: true, value: 32}, - {expected: false, value: 0}, - {expected: false, value: '32'}, - {expected: false, value: null}, - {expected: false, value: {a: 'b'}}, - {expected: false, value: [1, 2, 3]} - ] - }, - { - schema: { - const: '32' - }, - inputs: [ - {expected: false, value: 32}, - {expected: false, value: 0}, - {expected: true, value: '32'}, - {expected: false, value: null}, - {expected: false, value: {a: 'b'}}, - {expected: false, value: [1, 2, 3]} - ] - }, - { - schema: { - const: null - }, - inputs: [ - {expected: false, value: 32}, - {expected: false, value: 0}, - {expected: false, value: '32'}, - {expected: true, value: null}, - {expected: false, value: {a: 'b'}}, - {expected: false, value: [1, 2, 3]} - ] - }, - { - schema: { - const: {a: 'b'} - }, - inputs: [ - {expected: false, value: 32}, - {expected: false, value: 0}, - {expected: false, value: '32'}, - {expected: false, value: null}, - {expected: false, value: {a: 'b'}}, - {expected: false, value: [1, 2, 3]} - ] - }, - { - schema: { - const: [1, 2, 3] - }, - inputs: [ - {expected: false, value: 32}, - {expected: false, value: 0}, - {expected: false, value: '32'}, - {expected: false, value: null}, - {expected: false, value: {a: 'b'}}, - {expected: false, value: [1, 2, 3]} - ] - }, - - // Array contains tests - { - schema: { - type: 'array', - contains: {const: 32} - }, - inputs: [ - {expected: false, value: []}, - {expected: true, value: [32]}, - {expected: true, value: [1, 32]}, - {expected: true, value: [1, 32, 1]}, - {expected: false, value: [33]}, - {expected: false, value: [1, 33]}, - {expected: false, value: [1, 33, 1]} - ] - }, - - // Number limits tests - { - schema: { - type: 'number', - minimum: 0 - }, - inputs: [ - {expected: false, value: -1}, - {expected: true, value: 0}, - {expected: true, value: 1} - ] - }, - { - schema: { - type: 'number', - exclusiveMinimum: 0 - }, - inputs: [ - {expected: false, value: -1}, - {expected: false, value: 0}, - {expected: true, value: 1} - ] - }, - { - schema: { - type: 'number', - maximum: 0 - }, - inputs: [ - {expected: true, value: -1}, - {expected: true, value: 0}, - {expected: false, value: 1} - ] - }, - { - schema: { - type: 'number', - exclusiveMaximum: 0 - }, - inputs: [ - {expected: true, value: -1}, - {expected: false, value: 0}, - {expected: false, value: 1} - ] - }, - - // Integer limits tests - { - schema: { - type: 'integer', - minimum: 0 - }, - inputs: [ - {expected: false, value: -1}, - {expected: true, value: 0}, - {expected: true, value: 1} - ] - }, - { - schema: { - type: 'integer', - exclusiveMinimum: 0 - }, - inputs: [ - {expected: false, value: -1}, - {expected: false, value: 0}, - {expected: true, value: 1} - ] - }, - { - schema: { - type: 'integer', - maximum: 0 - }, - inputs: [ - {expected: true, value: -1}, - {expected: true, value: 0}, - {expected: false, value: 1} - ] - }, - { - schema: { - type: 'integer', - exclusiveMaximum: 0 - }, - inputs: [ - {expected: true, value: -1}, - {expected: false, value: 0}, - {expected: false, value: 1} - ] - }, - { - schema: { - type: 'integer', - multipleOf: 2 - }, - inputs: [ - {expected: true, value: -2}, - {expected: false, value: -1}, - {expected: true, value: 0}, - {expected: false, value: 1}, - {expected: true, value: 2} - ] - }, - - // Numeric type tests - { - schema: { - type: 'number' - }, - inputs: [ - {expected: true, value: 0}, - {expected: true, value: 0.5}, - {expected: true, value: 1}, - {expected: false, value: '0'}, - {expected: false, value: null}, - {expected: false, value: []}, - {expected: false, value: {}} - ] - }, - { - schema: { - type: 'integer' - }, - inputs: [ - {expected: true, value: 0}, - {expected: false, value: 0.5}, - {expected: true, value: 1}, - {expected: false, value: '0'}, - {expected: false, value: null}, - {expected: false, value: []}, - {expected: false, value: {}} - ] - }, - - // Reference tests - { - schema: { - definitions: { - example: { - type: 'number' - } - }, - $ref: '#/definitions/example' - }, - inputs: [ - {expected: true, value: 0}, - {expected: true, value: 0.5}, - {expected: true, value: 1}, - {expected: false, value: '0'}, - {expected: false, value: null}, - {expected: false, value: []}, - {expected: false, value: {}} - ] - }, - { - schema: { - definitions: { - example: { - type: 'integer' - } - }, - $ref: '#/definitions/example' - }, - inputs: [ - {expected: true, value: 0}, - {expected: false, value: 0.5}, - {expected: true, value: 1}, - {expected: false, value: '0'}, - {expected: false, value: null}, - {expected: false, value: []}, - {expected: false, value: {}} - ] - }, - { - schema: { - definitions: { - example: { - type: 'object', - additionalProperties: false, - properties: { - test: { - $ref: '#/definitions/example' - } - } - } - }, - $ref: '#/definitions/example' - }, - inputs: [ - {expected: false, value: 0}, - {expected: false, value: 0.5}, - {expected: false, value: 1}, - {expected: false, value: '0'}, - {expected: false, value: null}, - {expected: false, value: []}, - {expected: true, value: {}}, - {expected: false, value: {test: 0}}, - {expected: false, value: {test: 0.5}}, - {expected: false, value: {test: 1}}, - {expected: false, value: {test: '0'}}, - {expected: false, value: {test: null}}, - {expected: false, value: {test: []}}, - {expected: true, value: {test: {}}}, - {expected: true, value: {test: {test: {}}}}, - {expected: true, value: {test: {test: {test: {}}}}} - ] - } - ]; - - for (const {schema, inputs} of data) { - for (const {expected, value} of inputs) { - const actual = schemaValidate(schema, value); - assert.strictEqual(actual, expected); - } - } -} - - -/** */ -function testGetValidValueOrDefault1() { - /** @type {{schema: import('json-schema').Schema, inputs: [value: unknown, expected: unknown][]}[]} */ - const data = [ - // Test value defaulting on objects with additionalProperties=false - { - schema: { - type: 'object', - required: ['test'], - properties: { - test: { - type: 'string', - default: 'default' - } - }, - additionalProperties: false - }, - inputs: [ - [ - void 0, - {test: 'default'} - ], - [ - null, - {test: 'default'} - ], - [ - 0, - {test: 'default'} - ], - [ - '', - {test: 'default'} - ], - [ - [], - {test: 'default'} - ], - [ - {}, - {test: 'default'} - ], - [ - {test: 'value'}, - {test: 'value'} - ], - [ - {test2: 'value2'}, - {test: 'default'} - ], - [ - {test: 'value', test2: 'value2'}, - {test: 'value'} - ] - ] - }, - - // Test value defaulting on objects with additionalProperties=true - { - schema: { - type: 'object', - required: ['test'], - properties: { - test: { - type: 'string', - default: 'default' - } - }, - additionalProperties: true - }, - inputs: [ - [ - {}, - {test: 'default'} - ], - [ - {test: 'value'}, - {test: 'value'} - ], - [ - {test2: 'value2'}, - {test: 'default', test2: 'value2'} - ], - [ - {test: 'value', test2: 'value2'}, - {test: 'value', test2: 'value2'} - ] - ] - }, - - // Test value defaulting on objects with additionalProperties={schema} - { - schema: { - type: 'object', - required: ['test'], - properties: { - test: { - type: 'string', - default: 'default' - } - }, - additionalProperties: { - type: 'number', - default: 10 - } - }, - inputs: [ - [ - {}, - {test: 'default'} - ], - [ - {test: 'value'}, - {test: 'value'} - ], - [ - {test2: 'value2'}, - {test: 'default', test2: 10} - ], - [ - {test: 'value', test2: 'value2'}, - {test: 'value', test2: 10} - ], - [ - {test2: 2}, - {test: 'default', test2: 2} - ], - [ - {test: 'value', test2: 2}, - {test: 'value', test2: 2} - ], - [ - {test: 'value', test2: 2, test3: null}, - {test: 'value', test2: 2, test3: 10} - ], - [ - {test: 'value', test2: 2, test3: void 0}, - {test: 'value', test2: 2, test3: 10} - ] - ] - }, - - // Test value defaulting where hasOwnProperty is false - { - schema: { - type: 'object', - required: ['test'], - properties: { - test: { - type: 'string', - default: 'default' - } - } - }, - inputs: [ - [ - {}, - {test: 'default'} - ], - [ - {test: 'value'}, - {test: 'value'} - ], - [ - Object.create({test: 'value'}), - {test: 'default'} - ] - ] - }, - { - schema: { - type: 'object', - required: ['toString'], - properties: { - toString: /** @type {import('json-schema').SchemaObject} */ ({ - type: 'string', - default: 'default' - }) - } - }, - inputs: [ - [ - {}, - {toString: 'default'} - ], - [ - {toString: 'value'}, - {toString: 'value'} - ], - [ - Object.create({toString: 'value'}), - {toString: 'default'} - ] - ] - }, - - // Test enum - { - schema: { - type: 'object', - required: ['test'], - properties: { - test: { - type: 'string', - default: 'value1', - enum: ['value1', 'value2', 'value3'] - } - } - }, - inputs: [ - [ - {test: 'value1'}, - {test: 'value1'} - ], - [ - {test: 'value2'}, - {test: 'value2'} - ], - [ - {test: 'value3'}, - {test: 'value3'} - ], - [ - {test: 'value4'}, - {test: 'value1'} - ] - ] - }, - - // Test valid vs invalid default - { - schema: { - type: 'object', - required: ['test'], - properties: { - test: { - type: 'integer', - default: 2, - minimum: 1 - } - } - }, - inputs: [ - [ - {test: -1}, - {test: 2} - ] - ] - }, - { - schema: { - type: 'object', - required: ['test'], - properties: { - test: { - type: 'integer', - default: 1, - minimum: 2 - } - } - }, - inputs: [ - [ - {test: -1}, - {test: -1} - ] - ] - }, - - // Test references - { - schema: { - definitions: { - example: { - type: 'number', - default: 0 - } - }, - $ref: '#/definitions/example' - }, - inputs: [ - [ - 1, - 1 - ], - [ - null, - 0 - ], - [ - 'test', - 0 - ], - [ - {test: 'value'}, - 0 - ] - ] - }, - { - schema: { - definitions: { - example: { - type: 'object', - additionalProperties: false, - properties: { - test: { - $ref: '#/definitions/example' - } - } - } - }, - $ref: '#/definitions/example' - }, - inputs: [ - [ - 1, - {} - ], - [ - null, - {} - ], - [ - 'test', - {} - ], - [ - {}, - {} - ], - [ - {test: {}}, - {test: {}} - ], - [ - {test: 'value'}, - {test: {}} - ], - [ - {test: {test: {}}}, - {test: {test: {}}} - ] - ] - } - ]; - - for (const {schema, inputs} of data) { - for (const [value, expected] of inputs) { - const actual = getValidValueOrDefault(schema, value); - vm.assert.deepStrictEqual(actual, expected); - } - } -} - - -/** */ -function testProxy1() { - /** @type {{schema: import('json-schema').Schema, tests: {error: boolean, value?: import('json-schema').Value, action: (value: import('core').SafeAny) => void}[]}[]} */ - const data = [ - // Object tests - { - schema: { - type: 'object', - required: ['test'], - additionalProperties: false, - properties: { - test: { - type: 'string', - default: 'default' - } - } - }, - tests: [ - {error: false, value: {test: 'default'}, action: (value) => { value.test = 'string'; }}, - {error: true, value: {test: 'default'}, action: (value) => { value.test = null; }}, - {error: true, value: {test: 'default'}, action: (value) => { delete value.test; }}, - {error: true, value: {test: 'default'}, action: (value) => { value.test2 = 'string'; }}, - {error: false, value: {test: 'default'}, action: (value) => { delete value.test2; }} - ] - }, - { - schema: { - type: 'object', - required: ['test'], - additionalProperties: true, - properties: { - test: { - type: 'string', - default: 'default' - } - } - }, - tests: [ - {error: false, value: {test: 'default'}, action: (value) => { value.test = 'string'; }}, - {error: true, value: {test: 'default'}, action: (value) => { value.test = null; }}, - {error: true, value: {test: 'default'}, action: (value) => { delete value.test; }}, - {error: false, value: {test: 'default'}, action: (value) => { value.test2 = 'string'; }}, - {error: false, value: {test: 'default'}, action: (value) => { delete value.test2; }} - ] - }, - { - schema: { - type: 'object', - required: ['test1'], - additionalProperties: false, - properties: { - test1: { - type: 'object', - required: ['test2'], - additionalProperties: false, - properties: { - test2: { - type: 'object', - required: ['test3'], - additionalProperties: false, - properties: { - test3: { - type: 'string', - default: 'default' - } - } - } - } - } - } - }, - tests: [ - {error: false, action: (value) => { value.test1.test2.test3 = 'string'; }}, - {error: true, action: (value) => { value.test1.test2.test3 = null; }}, - {error: true, action: (value) => { delete value.test1.test2.test3; }}, - {error: true, action: (value) => { value.test1.test2 = null; }}, - {error: true, action: (value) => { value.test1 = null; }}, - {error: true, action: (value) => { value.test4 = 'string'; }}, - {error: false, action: (value) => { delete value.test4; }} - ] - }, - - // Array tests - { - schema: { - type: 'array', - items: { - type: 'string', - default: 'default' - } - }, - tests: [ - {error: false, value: ['default'], action: (value) => { value[0] = 'string'; }}, - {error: true, value: ['default'], action: (value) => { value[0] = null; }}, - {error: false, value: ['default'], action: (value) => { delete value[0]; }}, - {error: false, value: ['default'], action: (value) => { value[1] = 'string'; }}, - {error: false, value: ['default'], action: (value) => { - value[1] = 'string'; - if (value.length !== 2) { throw new Error(`Invalid length; expected=2; actual=${value.length}`); } - if (typeof value.push !== 'function') { throw new Error(`Invalid push; expected=function; actual=${typeof value.push}`); } - }} - ] - }, - - // Reference tests - { - schema: { - definitions: { - example: { - type: 'object', - additionalProperties: false, - properties: { - test: { - $ref: '#/definitions/example' - } - } - } - }, - $ref: '#/definitions/example' - }, - tests: [ - {error: false, value: {}, action: (value) => { value.test = {}; }}, - {error: false, value: {}, action: (value) => { value.test = {}; value.test.test = {}; }}, - {error: false, value: {}, action: (value) => { value.test = {test: {}}; }}, - {error: true, value: {}, action: (value) => { value.test = null; }}, - {error: true, value: {}, action: (value) => { value.test = 'string'; }}, - {error: true, value: {}, action: (value) => { value.test = {}; value.test.test = 'string'; }}, - {error: true, value: {}, action: (value) => { value.test = {test: 'string'}; }} - ] - } - ]; - - for (const {schema, tests} of data) { - for (let {error, value, action} of tests) { - if (typeof value === 'undefined') { value = getValidValueOrDefault(schema, void 0); } - value = clone(value); - assert.ok(schemaValidate(schema, value)); - const valueProxy = createProxy(schema, value); - if (error) { - assert.throws(() => action(valueProxy)); - } else { - assert.doesNotThrow(() => action(valueProxy)); - } - } - } -} - - -/** */ -function main() { - testValidate1(); - testValidate2(); - testGetValidValueOrDefault1(); - testProxy1(); -} - - -if (require.main === module) { testMain(main); } |