Skip to content

Commit

Permalink
Merge pull request #41 from ajv-validator/ep/json-schema-tests
Browse files Browse the repository at this point in the history
pass all JSON Schema Test Suite tests
  • Loading branch information
epoberezkin authored Nov 7, 2021
2 parents fdbd714 + 86d71eb commit 46dbae5
Showing 3 changed files with 44 additions and 26 deletions.
21 changes: 11 additions & 10 deletions src/formats.ts
Original file line number Diff line number Diff line change
@@ -62,7 +62,7 @@ export const fullFormats: DefinedFormats = {
hostname:
/^(?=.{1,253}\.?$)[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[-0-9a-z]{0,61}[0-9a-z])?)*\.?$/i,
// optimized https://www.safaribooksonline.com/library/view/regular-expressions-cookbook/9780596802837/ch07s16.html
ipv4: /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/,
ipv4: /^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$/,
ipv6: /^((([0-9a-f]{1,4}:){7}([0-9a-f]{1,4}|:))|(([0-9a-f]{1,4}:){6}(:[0-9a-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){5}(((:[0-9a-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){4}(((:[0-9a-f]{1,4}){1,3})|((:[0-9a-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){3}(((:[0-9a-f]{1,4}){1,4})|((:[0-9a-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){2}(((:[0-9a-f]{1,4}){1,5})|((:[0-9a-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){1}(((:[0-9a-f]{1,4}){1,6})|((:[0-9a-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9a-f]{1,4}){1,7})|((:[0-9a-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))$/i,
regex,
// uuid: http://tools.ietf.org/html/rfc4122
@@ -149,7 +149,7 @@ function compareDate(d1: string, d2: string): number | undefined {
return 0
}

const TIME = /^(\d\d):(\d\d):(\d\d(?:\.\d+)?)(z|([+-]\d\d)(?::?(\d\d))?)?$/i
const TIME = /^(\d\d):(\d\d):(\d\d(?:\.\d+)?)(z|([+-])(\d\d)(?::?(\d\d))?)?$/i

function time(str: string, withTimeZone?: boolean, strictTime?: boolean): boolean {
const matches: string[] | null = TIME.exec(str)
@@ -158,14 +158,15 @@ function time(str: string, withTimeZone?: boolean, strictTime?: boolean): boolea
const min: number = +matches[2]
const sec: number = +matches[3]
const tz: string | undefined = matches[4]
const tzH: number = +(matches[5] || 0)
const tzM: number = +(matches[6] || 0)
return (
((hr <= 23 && min <= 59 && sec < 60 && tzH <= 24 && tzM < 60) ||
// leap second
(hr - tzH === 23 && min - tzM === 59 && sec < 61 && tzH <= 24 && tzM < 60)) &&
(!withTimeZone || (tz !== "" && (!strictTime || !!tz)))
)
const tzSign: number = matches[5] === "-" ? -1 : 1
const tzH: number = +(matches[6] || 0)
const tzM: number = +(matches[7] || 0)
if (tzH > 23 || tzM > 59 || (withTimeZone && (tz === "" || (strictTime && !tz)))) return false
if (hr <= 23 && min <= 59 && sec < 60) return true
// leap second
const utcMin = min - tzM * tzSign
const utcHr = hr - tzH * tzSign - (utcMin < 0 ? 1 : 0)
return (utcHr === 23 || utcHr === -1) && (utcMin === 59 || utcMin === -1) && sec < 61
}

function strict_time(str: string): boolean {
2 changes: 1 addition & 1 deletion tests/JSON-Schema-Test-Suite
47 changes: 32 additions & 15 deletions tests/json-schema.spec.js
Original file line number Diff line number Diff line change
@@ -2,30 +2,47 @@ const jsonSchemaTest = require("json-schema-test")
const Ajv = require("ajv").default
const addFormats = require("../dist")

const ajv = new Ajv({$data: true, strictTypes: false, formats: {allowedUnknown: true}})
addFormats(ajv)

jsonSchemaTest(ajv, {
description: `JSON-Schema Test Suite draft-07 formats + extras`,
jsonSchemaTest(getAjv(true), {
description: `JSON-Schema Test Suite formats`,
suites: {
"draft-07 formats": "./JSON-Schema-Test-Suite/tests/draft7/optional/format/*.json",
"draft-07 regex": "./JSON-Schema-Test-Suite/tests/draft7/optional/ecmascript-regex.json",
"draft-2019-09 formats": "./JSON-Schema-Test-Suite/tests/draft2019-09/optional/format/*.json",
"draft-2019-09 regex":
"./JSON-Schema-Test-Suite/tests/draft2019-09/optional/ecmascript-regex.json",
extras: "./extras/{**/,}*.json",
"draft-2020-12 formats": "./JSON-Schema-Test-Suite/tests/draft2020-12/optional/format/*.json",
"draft-2020-12 regex":
"./JSON-Schema-Test-Suite/tests/draft2020-12/optional/ecmascript-regex.json",
},
only: [],
skip: ["format/idn-email", "format/idn-hostname", "format/iri", "format/iri-reference"],
afterEach({valid, errors}) {
expect(typeof valid).toBe("boolean")
if (valid === true) {
expect(errors).toBe(null)
} else {
expect(Array.isArray(errors)).toBe(true)
errors.every((err) => expect(typeof err).toBe("object"))
}
},
afterEach,
cwd: __dirname,
hideFolder: "draft7/",
})

jsonSchemaTest(getAjv(), {
description: `Extra tests`,
suites: {
extras: "./extras/{**/,}*.json",
},
only: [],
afterEach,
cwd: __dirname,
})

function getAjv(strictTime) {
const ajv = new Ajv({$data: true, strictTypes: false, formats: {allowedUnknown: true}})
addFormats(ajv, {mode: "full", keywords: true, strictTime})
return ajv
}

function afterEach({valid, errors}) {
expect(typeof valid).toBe("boolean")
if (valid === true) {
expect(errors).toBe(null)
} else {
expect(Array.isArray(errors)).toBe(true)
errors.every((err) => expect(typeof err).toBe("object"))
}
}

0 comments on commit 46dbae5

Please sign in to comment.