summaryrefslogtreecommitdiff
path: root/test/test-json-schema.js
diff options
context:
space:
mode:
Diffstat (limited to 'test/test-json-schema.js')
-rw-r--r--test/test-json-schema.js1048
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); }