diff --git a/GEMINI.md b/GEMINI.md index 15cdf04..234ae72 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -67,30 +67,41 @@ Returns a debug dump of the currently cached schemas (for development/debugging) ## ✨ Custom Features & Deviations -JSPG implements specific extensions to the Draft 2020-12 standard to support the Punc architecture's object-oriented needs. +JSPG implements specific extensions to the Draft 2020-12 standard to support the Punc architecture's object-oriented needs while heavily optimizing for zero-runtime lookups. -### 1. The Unified Semantic Graph & Native Inheritance -JSPG goes beyond Draft 2020-12 to natively understand Object-Oriented inheritance and polymorphism. During the `cache_json_schemas()` phase, JSPG builds a single Directed Acyclic Graph (DAG) using **only** the `$ref` keyword. Every schema that uses `$ref` establishes a parent-to-child relationship. +### 1. Polymorphism & Referencing (`$ref`, `$family`, and Native Types) -Furthermore, `jspg` knows which schemas belong directly to database tables (Entities) versus which are ad-hoc API shapes. -* **Native `type` Discrimination**: For any schema that traces its ancestry back to the base `entity`, JSPG securely and implicitly manages the `type` property. You do **not** need to explicitly override `"type": {"const": "person"}` in entity subclasses. If a schema `$ref`s `organization`, JSPG automatically allows the incoming `type` to be anything in the `organization` family tree (e.g., `person`, `bot`), but rigidly truncates/masks the data structure to the requested `organization` shape. -* **Ad-Hoc Objects**: If an ad-hoc schema `$ref`s a base object but does not trace back to `entity`, standard JSON Schema rules apply (no magical `type` tracking). +JSPG replaces the complex, dynamic reference resolution logic of standard JSON Schema (e.g., `$defs`, relative URIs, `$dynamicRef`, `$dynamicAnchor`, `if/then/else`) with a strict, explicitly structured global `$id` system. This powers predictable code generation and blazing-fast runtime validation. -> [!NOTE] -> **`$ref` never creates a Union.** When you use `$ref`, you are asking for a single, concrete struct/shape. The schema's strict fields will be rigidly enforced, but the `type` property is permitted to match any valid descendant via the native discrimination. +#### A. Global `$id` Conventions & Schema Buckets +Every schema is part of a flat, globally addressable namespace. However, where a schema is defined in the database determines its physical boundaries: +* **Types (Entities)**: Schemas defined within a Postgres `type` represent entities. The `$id` must be exactly the type name (`person`) or suffixed (`full.person`). All schemas in this bucket receive strict Native Type Discrimination based on the physical table hierarchy. +* **Puncs (APIs)**: Schemas defined within a `punc` are ad-hoc containers. The `$id` must be exactly `[punc_name].request` or `[punc_name].response`. They are never entities themselves. +* **Enums (Domains)**: Schemas defined within an `enum` represent enum definitions. The `$id` must be exactly the enum name (`job_status`) or suffixed (`short.job_status`). -### 2. Shape Polymorphism & Virtual Unions (`$family`) -To support polymorphic API contracts and deeply nested UI Unions without manually writing massive `oneOf` blocks, JSPG provides the `$family` macro. While `$ref` guarantees a single shape, `$family` asks the code generators for a true Polymorphic Union class. +#### B. Native Type Discrimination (The `variations` Property) +Because `jspg` knows which schemas are Entities based on their origin bucket (Types), it securely and implicitly manages the `"type"` property by attaching `compiled_variations`. +If a schema originates in the `user` bucket, the validator does *not* rigidly require `{"type": "user"}`. Instead, it queries the physical Postgres type inheritance graph (e.g. `[entity, organization, user]`) and allows the JSON to be `{"type": "person"}` or `{"type": "bot"}` automatically, enabling seamless API polymorphism. -When `{"$family": "organization.light"}` is encountered, JSPG: -1. Locates the base `organization` node in the Semantic Graph. -2. Recursively walks down to find all descendants via `$ref`. -3. **Strictly Filters** the descendants using the exact dot-notation suffix requested. It will only include descendants whose `$id` matches the shape modifier (e.g., `person.light`, `user.light`). If `bot` has no `.light` shape defined, it is securely omitted from the union. -4. Generates a virtual `oneOf` array containing those precise `$ref`s. +#### C. Structural Inheritance & Viral Infection (`$ref`) +`$ref` is used exclusively for structural inheritance. +* **Viral Infection**: If an anonymous schema or an ad-hoc schema (like a Punc Request) `$ref`s a strict Entity schema (like `person.light`), it *virally inherits* the `compiled_variations` of that target. This means a Punc request instantly gains the exact polymorphic security boundaries of the Entity it points to. +* **`$ref` never creates a Union.** When you use `$ref`, you are asking for a single, concrete struct/shape. -This cleanly separates **Database Ancestry** (managed entirely and implicitly by `$ref` for single shapes) from **Shape Variations** (managed explicitly by `$family` to build `oneOf` unions). +#### D. Shape Polymorphism & Virtual Unions (`$family`) +To support polymorphic API contracts (e.g., heterogeneous arrays of generic widgets) without manually writing massive `oneOf` blocks, JSPG provides the `$family` macro. +While `$ref` defines rigid structure, `$family` relies on an abstract **Descendants Graph**. -### 3. Strict by Default & Extensibility +During compilation, `jspg` temporarily tracks every `$ref` pointer globally to build a reverse-lookup graph of "Descendants". +When `{"$family": "widget"}` is encountered, JSPG: +1. Locates the `widget` schema in the Descendants graph. +2. Expands the macro by finding *every* schema in the entire database that structurally `$ref`s `widget`, directly or indirectly (e.g., `stock.widget`, an anonymous object, etc.). +3. Replaces the `$family` keyword with a standard `one_of` array containing `$ref`s to those discovered descendants. + +If you request `{"$family": "light.widget"}`, it simply expands to all schemas that `$ref` the generic abstract `light.widget` interface. +This cleanly separates **Database Physics** (derived from the Postgres `Types` bucket and viral `$ref` inheritance) from **Structural Polymorphism** (derived purely from the abstract `$ref` tree). + +### 2. Strict by Default & Extensibility JSPG enforces a "Secure by Default" philosophy. All schemas are treated as if `unevaluatedProperties: false` (and `unevaluatedItems: false`) is set, unless explicitly overridden. * **Strictness**: By default, any property or array item in the instance data that is not explicitly defined in the schema causes a validation error. This prevents clients from sending undeclared fields or extra array elements. @@ -99,19 +110,17 @@ JSPG enforces a "Secure by Default" philosophy. All schemas are treated as if `u * **Ref Boundaries**: Strictness is reset when crossing `$ref` boundaries. The referenced schema's strictness is determined by its own definition (strict by default unless `extensible: true`), ignoring the caller's state. * **Inheritance**: Strictness is inherited. A schema extending a strict parent will also be strict unless it declares itself `extensible: true`. Conversely, a schema extending a loose parent will also be loose unless it declares itself `extensible: false`. +### 3. Implicit Keyword Shadowing +Standard JSON Schema composition (`allOf`) is additive (Intersection), meaning constraints can only be tightened, not replaced. However, JSPG treats `$ref` differently when it appears alongside other properties to support object-oriented inheritance. + +* **Inheritance (`$ref` + properties)**: When a schema uses `$ref` and defines its own properties, JSPG implements Smart Merge (or Shadowing). If a property is defined in the current schema, its constraints take precedence over the inherited constraints for that specific keyword. + * **Example**: If Entity defines `type: { const: "entity" }` and Person (which refs Entity) defines `type: { const: "person" }`, validation passes for "person". The local const shadows the inherited const. + * **Granularity**: Shadowing is per-keyword. If Entity defined `type: { const: "entity", minLength: 5 }`, Person would shadow `const` but still inherit `minLength: 5`. +* **Composition (`allOf`)**: When using `allOf`, standard intersection rules apply. No shadowing occurs; all constraints from all branches must pass. This is used for mixins or interfaces. + ### 4. Format Leniency for Empty Strings To simplify frontend form logic, the format validators for `uuid`, `date-time`, and `email` explicitly allow empty strings (`""`). This treats an empty string as "present but unset" rather than "invalid format". -### 5. Masking (Constructive Validation) -JSPG supports a "Constructive Validation" mode via `mask_json_schema`. This is designed for high-performance API responses where the schema dictates the exact shape of the returned data. - -* **Mechanism**: The validator traverses the instance against the schema. -* **Valid Fields**: Kept in the output. -* **Unknown/Extra Fields**: Silently removed (pruned) if `extensible: false` (default). -* **Invalid Fields**: Still trigger standard validation errors. - -This allows the database to return "raw" joined rows (e.g. `SELECT * FROM person JOIN organization ...`) and have JSPG automatically shape the result into the expected API response, removing any internal or unrelated columns not defined in the schema. - ## 🏗️ Architecture The extension is written in Rust using `pgrx` and structures its schema parser to mirror the Punc Generator's design: diff --git a/build.rs b/build.rs index 5988526..aed958b 100644 --- a/build.rs +++ b/build.rs @@ -49,7 +49,41 @@ fn main() { let val: serde_json::Value = serde_json::from_reader(file).unwrap(); if let Some(arr) = val.as_array() { - for (i, _item) in arr.iter().enumerate() { + for (i, item) in arr.iter().enumerate() { + // Enforce test suite structure + let group = item.as_object().expect("Test suite must be an object"); + + // Validate required suite fields + if !group.contains_key("description") + || !group.contains_key("database") + || !group.contains_key("tests") + { + panic!( + "File {} index {} is missing required suite fields (description, database, tests)", + file_name, i + ); + } + + // Validate required test case fields + let tests = group + .get("tests") + .unwrap() + .as_array() + .expect("Tests must be an array"); + for (t_idx, test) in tests.iter().enumerate() { + let t_obj = test.as_object().expect("Test case must be an object"); + if !t_obj.contains_key("description") + || !t_obj.contains_key("data") + || !t_obj.contains_key("valid") + || !t_obj.contains_key("schema_id") + { + panic!( + "File {} suite {} test {} is missing required case fields (description, data, valid, schema_id)", + file_name, i, t_idx + ); + } + } + // Use deterministic names: test_{filename}_{index} let safe_filename = to_safe_identifier(file_name); let fn_name = format!("test_{}_{}", safe_filename, i); diff --git a/src/bin/pgrx_embed.rs b/src/bin/pgrx_embed.rs index 57483f1..5f5c4d8 100644 --- a/src/bin/pgrx_embed.rs +++ b/src/bin/pgrx_embed.rs @@ -1 +1 @@ -::pgrx::pgrx_embed!(); \ No newline at end of file +::pgrx::pgrx_embed!(); diff --git a/src/database/formats.rs b/src/database/formats.rs index 0788b4b..5963f34 100644 --- a/src/database/formats.rs +++ b/src/database/formats.rs @@ -1,7 +1,7 @@ use std::{ - collections::HashMap, - error::Error, - net::{Ipv4Addr, Ipv6Addr}, + collections::HashMap, + error::Error, + net::{Ipv4Addr, Ipv6Addr}, }; use lazy_static::lazy_static; @@ -14,11 +14,11 @@ use url::Url; /// Defines format for `format` keyword. #[derive(Clone, Copy)] pub struct Format { - /// Name of the format - pub name: &'static str, + /// Name of the format + pub name: &'static str, - /// validates given value. - pub func: fn(v: &Value) -> Result<(), Box>, // Ensure thread safety if needed + /// validates given value. + pub func: fn(v: &Value) -> Result<(), Box>, // Ensure thread safety if needed } lazy_static! { @@ -26,7 +26,7 @@ lazy_static! { let mut m = HashMap::<&'static str, Format>::new(); // Helper to register formats let mut register = |name, func| m.insert(name, Format { name, func }); - + // register("regex", validate_regex); // Stubbed register("ipv4", validate_ipv4); register("ipv6", validate_ipv6); @@ -62,814 +62,819 @@ fn validate_regex(v: &Value) -> Result<(), Box> { */ fn validate_ipv4(v: &Value) -> Result<(), Box> { - let Value::String(s) = v else { - return Ok(()); - }; - s.parse::()?; - Ok(()) + let Value::String(s) = v else { + return Ok(()); + }; + s.parse::()?; + Ok(()) } fn validate_ipv6(v: &Value) -> Result<(), Box> { - let Value::String(s) = v else { - return Ok(()); - }; - s.parse::()?; - Ok(()) + let Value::String(s) = v else { + return Ok(()); + }; + s.parse::()?; + Ok(()) } fn validate_date(v: &Value) -> Result<(), Box> { - let Value::String(s) = v else { - return Ok(()); - }; - check_date(s)?; - Ok(()) + let Value::String(s) = v else { + return Ok(()); + }; + check_date(s)?; + Ok(()) } fn matches_char(s: &str, index: usize, ch: char) -> bool { - s.is_char_boundary(index) && s[index..].starts_with(ch) + s.is_char_boundary(index) && s[index..].starts_with(ch) } // see https://datatracker.ietf.org/doc/html/rfc3339#section-5.6 fn check_date(s: &str) -> Result<(), Box> { - // yyyy-mm-dd - if s.len() != 10 { - Err("must be 10 characters long")?; - } - if !matches_char(s, 4, '-') || !matches_char(s, 7, '-') { - Err("missing hyphen in correct place")?; - } + // yyyy-mm-dd + if s.len() != 10 { + Err("must be 10 characters long")?; + } + if !matches_char(s, 4, '-') || !matches_char(s, 7, '-') { + Err("missing hyphen in correct place")?; + } - let mut ymd = s.splitn(3, '-').filter_map(|t| t.parse::().ok()); - let (Some(y), Some(m), Some(d)) = (ymd.next(), ymd.next(), ymd.next()) else { - Err("non-positive year/month/day")? - }; + let mut ymd = s.splitn(3, '-').filter_map(|t| t.parse::().ok()); + let (Some(y), Some(m), Some(d)) = (ymd.next(), ymd.next(), ymd.next()) else { + Err("non-positive year/month/day")? + }; - if !matches!(m, 1..=12) { - Err(format!("{m} months in year"))?; - } - if !matches!(d, 1..=31) { - Err(format!("{d} days in month"))?; - } + if !matches!(m, 1..=12) { + Err(format!("{m} months in year"))?; + } + if !matches!(d, 1..=31) { + Err(format!("{d} days in month"))?; + } - match m { - 2 => { - let mut feb_days = 28; - if y % 4 == 0 && (y % 100 != 0 || y % 400 == 0) { - feb_days += 1; // leap year - }; - if d > feb_days { - Err(format!("february has {feb_days} days only"))?; - } - } - 4 | 6 | 9 | 11 => { - if d > 30 { - Err("month has 30 days only")?; - } - } - _ => {} + match m { + 2 => { + let mut feb_days = 28; + if y % 4 == 0 && (y % 100 != 0 || y % 400 == 0) { + feb_days += 1; // leap year + }; + if d > feb_days { + Err(format!("february has {feb_days} days only"))?; + } } - Ok(()) + 4 | 6 | 9 | 11 => { + if d > 30 { + Err("month has 30 days only")?; + } + } + _ => {} + } + Ok(()) } fn validate_time(v: &Value) -> Result<(), Box> { - let Value::String(s) = v else { - return Ok(()); - }; - check_time(s) + let Value::String(s) = v else { + return Ok(()); + }; + check_time(s) } fn check_time(mut str: &str) -> Result<(), Box> { - // min: hh:mm:ssZ - if str.len() < 9 { - Err("less than 9 characters long")? - } - if !matches_char(str, 2, ':') || !matches_char(str, 5, ':') { - Err("missing colon in correct place")? - } + // min: hh:mm:ssZ + if str.len() < 9 { + Err("less than 9 characters long")? + } + if !matches_char(str, 2, ':') || !matches_char(str, 5, ':') { + Err("missing colon in correct place")? + } - // parse hh:mm:ss - if !str.is_char_boundary(8) { - Err("contains non-ascii char")? + // parse hh:mm:ss + if !str.is_char_boundary(8) { + Err("contains non-ascii char")? + } + let mut hms = (str[..8]) + .splitn(3, ':') + .filter_map(|t| t.parse::().ok()); + let (Some(mut h), Some(mut m), Some(s)) = (hms.next(), hms.next(), hms.next()) else { + Err("non-positive hour/min/sec")? + }; + if h > 23 || m > 59 || s > 60 { + Err("hour/min/sec out of range")? + } + str = &str[8..]; + + // parse sec-frac if present + if let Some(rem) = str.strip_prefix('.') { + let n_digits = rem.chars().take_while(char::is_ascii_digit).count(); + if n_digits == 0 { + Err("no digits in second fraction")?; } - let mut hms = (str[..8]) - .splitn(3, ':') - .filter_map(|t| t.parse::().ok()); - let (Some(mut h), Some(mut m), Some(s)) = (hms.next(), hms.next(), hms.next()) else { - Err("non-positive hour/min/sec")? + str = &rem[n_digits..]; + } + + if str != "z" && str != "Z" { + // parse time-numoffset + if str.len() != 6 { + Err("offset must be 6 characters long")?; + } + let sign: isize = match str.chars().next() { + Some('+') => -1, + Some('-') => 1, + _ => return Err("offset must begin with plus/minus")?, }; - if h > 23 || m > 59 || s > 60 { - Err("hour/min/sec out of range")? - } - str = &str[8..]; - - // parse sec-frac if present - if let Some(rem) = str.strip_prefix('.') { - let n_digits = rem.chars().take_while(char::is_ascii_digit).count(); - if n_digits == 0 { - Err("no digits in second fraction")?; - } - str = &rem[n_digits..]; + str = &str[1..]; + if !matches_char(str, 2, ':') { + Err("missing colon in offset at correct place")? } - if str != "z" && str != "Z" { - // parse time-numoffset - if str.len() != 6 { - Err("offset must be 6 characters long")?; - } - let sign: isize = match str.chars().next() { - Some('+') => -1, - Some('-') => 1, - _ => return Err("offset must begin with plus/minus")?, - }; - str = &str[1..]; - if !matches_char(str, 2, ':') { - Err("missing colon in offset at correct place")? - } - - let mut zhm = str.splitn(2, ':').filter_map(|t| t.parse::().ok()); - let (Some(zh), Some(zm)) = (zhm.next(), zhm.next()) else { - Err("non-positive hour/min in offset")? - }; - if zh > 23 || zm > 59 { - Err("hour/min in offset out of range")? - } - - // apply timezone - let mut hm = (h * 60 + m) as isize + sign * (zh * 60 + zm) as isize; - if hm < 0 { - hm += 24 * 60; - debug_assert!(hm >= 0); - } - let hm = hm as usize; - (h, m) = (hm / 60, hm % 60); + let mut zhm = str.splitn(2, ':').filter_map(|t| t.parse::().ok()); + let (Some(zh), Some(zm)) = (zhm.next(), zhm.next()) else { + Err("non-positive hour/min in offset")? + }; + if zh > 23 || zm > 59 { + Err("hour/min in offset out of range")? } - // check leap second - if !(s < 60 || (h == 23 && m == 59)) { - Err("invalid leap second")? + // apply timezone + let mut hm = (h * 60 + m) as isize + sign * (zh * 60 + zm) as isize; + if hm < 0 { + hm += 24 * 60; + debug_assert!(hm >= 0); } - Ok(()) + let hm = hm as usize; + (h, m) = (hm / 60, hm % 60); + } + + // check leap second + if !(s < 60 || (h == 23 && m == 59)) { + Err("invalid leap second")? + } + Ok(()) } fn validate_date_time(v: &Value) -> Result<(), Box> { - let Value::String(s) = v else { - return Ok(()); - }; - check_date_time(s) + let Value::String(s) = v else { + return Ok(()); + }; + check_date_time(s) } fn check_date_time(s: &str) -> Result<(), Box> { - // min: yyyy-mm-ddThh:mm:ssZ - if s.len() < 20 { - Err("less than 20 characters long")?; - } - if !s.is_char_boundary(10) || !s[10..].starts_with(['t', 'T']) { - Err("11th character must be t or T")?; - } - if let Err(e) = check_date(&s[..10]) { - Err(format!("invalid date element: {e}"))?; - } - if let Err(e) = check_time(&s[11..]) { - Err(format!("invalid time element: {e}"))?; - } - Ok(()) + // min: yyyy-mm-ddThh:mm:ssZ + if s.len() < 20 { + Err("less than 20 characters long")?; + } + if !s.is_char_boundary(10) || !s[10..].starts_with(['t', 'T']) { + Err("11th character must be t or T")?; + } + if let Err(e) = check_date(&s[..10]) { + Err(format!("invalid date element: {e}"))?; + } + if let Err(e) = check_time(&s[11..]) { + Err(format!("invalid time element: {e}"))?; + } + Ok(()) } fn validate_duration(v: &Value) -> Result<(), Box> { - let Value::String(s) = v else { - return Ok(()); - }; - check_duration(s)?; - Ok(()) + let Value::String(s) = v else { + return Ok(()); + }; + check_duration(s)?; + Ok(()) } // see https://datatracker.ietf.org/doc/html/rfc3339#appendix-A fn check_duration(s: &str) -> Result<(), Box> { - // must start with 'P' - let Some(s) = s.strip_prefix('P') else { - Err("must start with P")? - }; + // must start with 'P' + let Some(s) = s.strip_prefix('P') else { + Err("must start with P")? + }; + if s.is_empty() { + Err("nothing after P")? + } + + // dur-week + if let Some(s) = s.strip_suffix('W') { if s.is_empty() { - Err("nothing after P")? + Err("no number in week")? } - - // dur-week - if let Some(s) = s.strip_suffix('W') { - if s.is_empty() { - Err("no number in week")? - } - if !s.chars().all(|c| c.is_ascii_digit()) { - Err("invalid week")? - } - return Ok(()); + if !s.chars().all(|c| c.is_ascii_digit()) { + Err("invalid week")? } + return Ok(()); + } - static UNITS: [&str; 2] = ["YMD", "HMS"]; - for (i, s) in s.split('T').enumerate() { - let mut s = s; - if i != 0 && s.is_empty() { - Err("no time elements")? - } - let Some(mut units) = UNITS.get(i).cloned() else { - Err("more than one T")? - }; - while !s.is_empty() { - let digit_count = s.chars().take_while(char::is_ascii_digit).count(); - if digit_count == 0 { - Err("missing number")? - } - s = &s[digit_count..]; - let Some(unit) = s.chars().next() else { - Err("missing unit")? - }; - let Some(j) = units.find(unit) else { - if UNITS[i].contains(unit) { - Err(format!("unit {unit} out of order"))? - } - Err(format!("invalid unit {unit}"))? - }; - units = &units[j + 1..]; - s = &s[1..]; - } + static UNITS: [&str; 2] = ["YMD", "HMS"]; + for (i, s) in s.split('T').enumerate() { + let mut s = s; + if i != 0 && s.is_empty() { + Err("no time elements")? } + let Some(mut units) = UNITS.get(i).cloned() else { + Err("more than one T")? + }; + while !s.is_empty() { + let digit_count = s.chars().take_while(char::is_ascii_digit).count(); + if digit_count == 0 { + Err("missing number")? + } + s = &s[digit_count..]; + let Some(unit) = s.chars().next() else { + Err("missing unit")? + }; + let Some(j) = units.find(unit) else { + if UNITS[i].contains(unit) { + Err(format!("unit {unit} out of order"))? + } + Err(format!("invalid unit {unit}"))? + }; + units = &units[j + 1..]; + s = &s[1..]; + } + } - Ok(()) + Ok(()) } // see https://datatracker.ietf.org/doc/html/rfc3339#appendix-A fn validate_period(v: &Value) -> Result<(), Box> { - let Value::String(s) = v else { - return Ok(()); - }; + let Value::String(s) = v else { + return Ok(()); + }; - let Some(slash) = s.find('/') else { - Err("missing slash")? - }; + let Some(slash) = s.find('/') else { + Err("missing slash")? + }; - let (start, end) = (&s[..slash], &s[slash + 1..]); - if start.starts_with('P') { - if let Err(e) = check_duration(start) { - Err(format!("invalid start duration: {e}"))? - } - if let Err(e) = check_date_time(end) { - Err(format!("invalid end date-time: {e}"))? - } - } else { - if let Err(e) = check_date_time(start) { - Err(format!("invalid start date-time: {e}"))? - } - if end.starts_with('P') { - if let Err(e) = check_duration(end) { - Err(format!("invalid end duration: {e}"))?; - } - } else if let Err(e) = check_date_time(end) { - Err(format!("invalid end date-time: {e}"))?; - } + let (start, end) = (&s[..slash], &s[slash + 1..]); + if start.starts_with('P') { + if let Err(e) = check_duration(start) { + Err(format!("invalid start duration: {e}"))? } - Ok(()) + if let Err(e) = check_date_time(end) { + Err(format!("invalid end date-time: {e}"))? + } + } else { + if let Err(e) = check_date_time(start) { + Err(format!("invalid start date-time: {e}"))? + } + if end.starts_with('P') { + if let Err(e) = check_duration(end) { + Err(format!("invalid end duration: {e}"))?; + } + } else if let Err(e) = check_date_time(end) { + Err(format!("invalid end date-time: {e}"))?; + } + } + Ok(()) } fn validate_hostname(v: &Value) -> Result<(), Box> { - let Value::String(s) = v else { - return Ok(()); - }; - check_hostname(s)?; - Ok(()) + let Value::String(s) = v else { + return Ok(()); + }; + check_hostname(s)?; + Ok(()) } // see https://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_host_names fn check_hostname(s: &str) -> Result<(), Box> { - // entire hostname (including the delimiting dots but not a trailing dot) has a maximum of 253 ASCII characters + // entire hostname (including the delimiting dots but not a trailing dot) has a maximum of 253 ASCII characters - if s.len() > 253 { - Err("more than 253 characters long")? + if s.len() > 253 { + Err("more than 253 characters long")? + } + + // Hostnames are composed of series of labels concatenated with dots, as are all domain names + for label in s.split('.') { + // Each label must be from 1 to 63 characters long + if !matches!(label.len(), 1..=63) { + Err("label must be 1 to 63 characters long")?; } - // Hostnames are composed of series of labels concatenated with dots, as are all domain names - for label in s.split('.') { - // Each label must be from 1 to 63 characters long - if !matches!(label.len(), 1..=63) { - Err("label must be 1 to 63 characters long")?; - } - - // labels must not start or end with a hyphen - if label.starts_with('-') { - Err("label starts with hyphen")?; - } - - if label.ends_with('-') { - Err("label ends with hyphen")?; - } - - // labels may contain only the ASCII letters 'a' through 'z' (in a case-insensitive manner), - // the digits '0' through '9', and the hyphen ('-') - if let Some(ch) = label - .chars() - .find(|c| !matches!(c, 'a'..='z' | 'A'..='Z' | '0'..='9' | '-')) - { - Err(format!("invalid character {ch:?}"))?; - } - - // labels must not contain "--" in 3rd and 4th position unless they start with "xn--" - if label.len() >= 4 && &label[2..4] == "--" { - if !label.starts_with("xn--") { - Err("label has -- in 3rd/4th position but does not start with xn--")?; - } else { - let (unicode, errors) = idna::domain_to_unicode(label); - if let Err(_) = errors { - Err("invalid punycode")?; - } - check_unicode_idn_constraints(&unicode).map_err(|e| format!("invalid punycode/IDN: {e}"))?; - } - } + // labels must not start or end with a hyphen + if label.starts_with('-') { + Err("label starts with hyphen")?; } - Ok(()) + if label.ends_with('-') { + Err("label ends with hyphen")?; + } + + // labels may contain only the ASCII letters 'a' through 'z' (in a case-insensitive manner), + // the digits '0' through '9', and the hyphen ('-') + if let Some(ch) = label + .chars() + .find(|c| !matches!(c, 'a'..='z' | 'A'..='Z' | '0'..='9' | '-')) + { + Err(format!("invalid character {ch:?}"))?; + } + + // labels must not contain "--" in 3rd and 4th position unless they start with "xn--" + if label.len() >= 4 && &label[2..4] == "--" { + if !label.starts_with("xn--") { + Err("label has -- in 3rd/4th position but does not start with xn--")?; + } else { + let (unicode, errors) = idna::domain_to_unicode(label); + if let Err(_) = errors { + Err("invalid punycode")?; + } + check_unicode_idn_constraints(&unicode) + .map_err(|e| format!("invalid punycode/IDN: {e}"))?; + } + } + } + + Ok(()) } fn validate_idn_hostname(v: &Value) -> Result<(), Box> { - let Value::String(s) = v else { - return Ok(()); - }; - check_idn_hostname(s)?; - Ok(()) + let Value::String(s) = v else { + return Ok(()); + }; + check_idn_hostname(s)?; + Ok(()) } static DISALLOWED: [char; 10] = [ - '\u{0640}', // ARABIC TATWEEL - '\u{07FA}', // NKO LAJANYALAN - '\u{302E}', // HANGUL SINGLE DOT TONE MARK - '\u{302F}', // HANGUL DOUBLE DOT TONE MARK - '\u{3031}', // VERTICAL KANA REPEAT MARK - '\u{3032}', // VERTICAL KANA REPEAT WITH VOICED SOUND MARK - '\u{3033}', // VERTICAL KANA REPEAT MARK UPPER HALF - '\u{3034}', // VERTICAL KANA REPEAT WITH VOICED SOUND MARK UPPER HA - '\u{3035}', // VERTICAL KANA REPEAT MARK LOWER HALF - '\u{303B}', // VERTICAL IDEOGRAPHIC ITERATION MARK + '\u{0640}', // ARABIC TATWEEL + '\u{07FA}', // NKO LAJANYALAN + '\u{302E}', // HANGUL SINGLE DOT TONE MARK + '\u{302F}', // HANGUL DOUBLE DOT TONE MARK + '\u{3031}', // VERTICAL KANA REPEAT MARK + '\u{3032}', // VERTICAL KANA REPEAT WITH VOICED SOUND MARK + '\u{3033}', // VERTICAL KANA REPEAT MARK UPPER HALF + '\u{3034}', // VERTICAL KANA REPEAT WITH VOICED SOUND MARK UPPER HA + '\u{3035}', // VERTICAL KANA REPEAT MARK LOWER HALF + '\u{303B}', // VERTICAL IDEOGRAPHIC ITERATION MARK ]; fn check_idn_hostname(s: &str) -> Result<(), Box> { - let s = idna::domain_to_ascii_strict(s).map_err(|e| format!("idna error: {:?}", e))?; - let (unicode, errors) = idna::domain_to_unicode(&s); - if let Err(e) = errors { - Err(format!("idna decoding error: {:?}", e))?; - } - check_unicode_idn_constraints(&unicode)?; - check_hostname(&s)?; - Ok(()) + let s = idna::domain_to_ascii_strict(s).map_err(|e| format!("idna error: {:?}", e))?; + let (unicode, errors) = idna::domain_to_unicode(&s); + if let Err(e) = errors { + Err(format!("idna decoding error: {:?}", e))?; + } + check_unicode_idn_constraints(&unicode)?; + check_hostname(&s)?; + Ok(()) } fn check_unicode_idn_constraints(unicode: &str) -> Result<(), Box> { - // see https://www.rfc-editor.org/rfc/rfc5892#section-2.6 - { - if unicode.contains(DISALLOWED) { - Err("contains disallowed character")?; - } + // see https://www.rfc-editor.org/rfc/rfc5892#section-2.6 + { + if unicode.contains(DISALLOWED) { + Err("contains disallowed character")?; } + } - // unicode string must not contain "--" in 3rd and 4th position - // and must not start and end with a '-' - // see https://www.rfc-editor.org/rfc/rfc5891#section-4.2.3.1 - { - let count: usize = unicode - .chars() - .skip(2) - .take(2) - .map(|c| if c == '-' { 1 } else { 0 }) - .sum(); - if count == 2 { - Err("unicode string must not contain '--' in 3rd and 4th position")?; - } + // unicode string must not contain "--" in 3rd and 4th position + // and must not start and end with a '-' + // see https://www.rfc-editor.org/rfc/rfc5891#section-4.2.3.1 + { + let count: usize = unicode + .chars() + .skip(2) + .take(2) + .map(|c| if c == '-' { 1 } else { 0 }) + .sum(); + if count == 2 { + Err("unicode string must not contain '--' in 3rd and 4th position")?; } + } - // MIDDLE DOT is allowed between 'l' characters only - // see https://www.rfc-editor.org/rfc/rfc5892#appendix-A.3 - { - let middle_dot = '\u{00b7}'; - let mut s = unicode; - while let Some(i) = s.find(middle_dot) { - let prefix = &s[..i]; - let suffix = &s[i + middle_dot.len_utf8()..]; - if !prefix.ends_with('l') || !suffix.ends_with('l') { - Err("MIDDLE DOT is allowed between 'l' characters only")?; - } - s = suffix; - } + // MIDDLE DOT is allowed between 'l' characters only + // see https://www.rfc-editor.org/rfc/rfc5892#appendix-A.3 + { + let middle_dot = '\u{00b7}'; + let mut s = unicode; + while let Some(i) = s.find(middle_dot) { + let prefix = &s[..i]; + let suffix = &s[i + middle_dot.len_utf8()..]; + if !prefix.ends_with('l') || !suffix.ends_with('l') { + Err("MIDDLE DOT is allowed between 'l' characters only")?; + } + s = suffix; } + } - // Greek KERAIA must be followed by Greek character - // see https://www.rfc-editor.org/rfc/rfc5892#appendix-A.4 - { - let keralia = '\u{0375}'; - let greek = '\u{0370}'..='\u{03FF}'; - let mut s = unicode; - while let Some(i) = s.find(keralia) { - let suffix = &s[i + keralia.len_utf8()..]; - if !suffix.starts_with(|c| greek.contains(&c)) { - Err("Greek KERAIA must be followed by Greek character")?; - } - s = suffix; - } + // Greek KERAIA must be followed by Greek character + // see https://www.rfc-editor.org/rfc/rfc5892#appendix-A.4 + { + let keralia = '\u{0375}'; + let greek = '\u{0370}'..='\u{03FF}'; + let mut s = unicode; + while let Some(i) = s.find(keralia) { + let suffix = &s[i + keralia.len_utf8()..]; + if !suffix.starts_with(|c| greek.contains(&c)) { + Err("Greek KERAIA must be followed by Greek character")?; + } + s = suffix; } + } - // Hebrew GERESH must be preceded by Hebrew character - // see https://www.rfc-editor.org/rfc/rfc5892#appendix-A.5 - // - // Hebrew GERSHAYIM must be preceded by Hebrew character - // see https://www.rfc-editor.org/rfc/rfc5892#appendix-A.6 - { - let geresh = '\u{05F3}'; - let gereshayim = '\u{05F4}'; - let hebrew = '\u{0590}'..='\u{05FF}'; - for ch in [geresh, gereshayim] { - let mut s = unicode; - while let Some(i) = s.find(ch) { - let prefix = &s[..i]; - if !prefix.ends_with(|c| hebrew.contains(&c)) { - if i == 0 { - Err("Hebrew GERESH must be preceded by Hebrew character")?; - } else { - Err("Hebrew GERESHYIM must be preceded by Hebrew character")?; - } - } - let suffix = &s[i + ch.len_utf8()..]; - s = suffix; - } + // Hebrew GERESH must be preceded by Hebrew character + // see https://www.rfc-editor.org/rfc/rfc5892#appendix-A.5 + // + // Hebrew GERSHAYIM must be preceded by Hebrew character + // see https://www.rfc-editor.org/rfc/rfc5892#appendix-A.6 + { + let geresh = '\u{05F3}'; + let gereshayim = '\u{05F4}'; + let hebrew = '\u{0590}'..='\u{05FF}'; + for ch in [geresh, gereshayim] { + let mut s = unicode; + while let Some(i) = s.find(ch) { + let prefix = &s[..i]; + if !prefix.ends_with(|c| hebrew.contains(&c)) { + if i == 0 { + Err("Hebrew GERESH must be preceded by Hebrew character")?; + } else { + Err("Hebrew GERESHYIM must be preceded by Hebrew character")?; + } } + let suffix = &s[i + ch.len_utf8()..]; + s = suffix; + } } + } - // KATAKANA MIDDLE DOT must be with Hiragana, Katakana, or Han - // see https://www.rfc-editor.org/rfc/rfc5892#appendix-A.7 + // KATAKANA MIDDLE DOT must be with Hiragana, Katakana, or Han + // see https://www.rfc-editor.org/rfc/rfc5892#appendix-A.7 + { + let katakana_middle_dot = '\u{30FB}'; + if unicode.contains(katakana_middle_dot) { + let hiragana = '\u{3040}'..='\u{309F}'; + let katakana = '\u{30A0}'..='\u{30FF}'; + let han = '\u{4E00}'..='\u{9FFF}'; // https://en.wikipedia.org/wiki/CJK_Unified_Ideographs_(Unicode_block): is this range correct?? + if unicode.contains(|c| hiragana.contains(&c)) + || unicode.contains(|c| c != katakana_middle_dot && katakana.contains(&c)) + || unicode.contains(|c| han.contains(&c)) + { + // ok + } else { + Err("KATAKANA MIDDLE DOT must be with Hiragana, Katakana, or Han")?; + } + } + } + + // ARABIC-INDIC DIGITS and Extended Arabic-Indic Digits cannot be mixed + // see https://www.rfc-editor.org/rfc/rfc5892#appendix-A.8 + // see https://www.rfc-editor.org/rfc/rfc5892#appendix-A.9 + { + let arabic_indic_digits = '\u{0660}'..='\u{0669}'; + let extended_arabic_indic_digits = '\u{06F0}'..='\u{06F9}'; + if unicode.contains(|c| arabic_indic_digits.contains(&c)) + && unicode.contains(|c| extended_arabic_indic_digits.contains(&c)) { - let katakana_middle_dot = '\u{30FB}'; - if unicode.contains(katakana_middle_dot) { - let hiragana = '\u{3040}'..='\u{309F}'; - let katakana = '\u{30A0}'..='\u{30FF}'; - let han = '\u{4E00}'..='\u{9FFF}'; // https://en.wikipedia.org/wiki/CJK_Unified_Ideographs_(Unicode_block): is this range correct?? - if unicode.contains(|c| hiragana.contains(&c)) - || unicode.contains(|c| c != katakana_middle_dot && katakana.contains(&c)) - || unicode.contains(|c| han.contains(&c)) - { - // ok - } else { - Err("KATAKANA MIDDLE DOT must be with Hiragana, Katakana, or Han")?; - } - } + Err("ARABIC-INDIC DIGITS and Extended Arabic-Indic Digits cannot be mixed")?; } + } - // ARABIC-INDIC DIGITS and Extended Arabic-Indic Digits cannot be mixed - // see https://www.rfc-editor.org/rfc/rfc5892#appendix-A.8 - // see https://www.rfc-editor.org/rfc/rfc5892#appendix-A.9 - { - let arabic_indic_digits = '\u{0660}'..='\u{0669}'; - let extended_arabic_indic_digits = '\u{06F0}'..='\u{06F9}'; - if unicode.contains(|c| arabic_indic_digits.contains(&c)) - && unicode.contains(|c| extended_arabic_indic_digits.contains(&c)) - { - Err("ARABIC-INDIC DIGITS and Extended Arabic-Indic Digits cannot be mixed")?; - } + // ZERO WIDTH JOINER must be preceded by Virama + // see https://www.rfc-editor.org/rfc/rfc5892#appendix-A.2 + { + let zero_width_jointer = '\u{200D}'; + static VIRAMA: [char; 61] = [ + '\u{094D}', + '\u{09CD}', + '\u{0A4D}', + '\u{0ACD}', + '\u{0B4D}', + '\u{0BCD}', + '\u{0C4D}', + '\u{0CCD}', + '\u{0D3B}', + '\u{0D3C}', + '\u{0D4D}', + '\u{0DCA}', + '\u{0E3A}', + '\u{0EBA}', + '\u{0F84}', + '\u{1039}', + '\u{103A}', + '\u{1714}', + '\u{1734}', + '\u{17D2}', + '\u{1A60}', + '\u{1B44}', + '\u{1BAA}', + '\u{1BAB}', + '\u{1BF2}', + '\u{1BF3}', + '\u{2D7F}', + '\u{A806}', + '\u{A82C}', + '\u{A8C4}', + '\u{A953}', + '\u{A9C0}', + '\u{AAF6}', + '\u{ABED}', + '\u{10A3F}', + '\u{11046}', + '\u{1107F}', + '\u{110B9}', + '\u{11133}', + '\u{11134}', + '\u{111C0}', + '\u{11235}', + '\u{112EA}', + '\u{1134D}', + '\u{11442}', + '\u{114C2}', + '\u{115BF}', + '\u{1163F}', + '\u{116B6}', + '\u{1172B}', + '\u{11839}', + '\u{1193D}', + '\u{1193E}', + '\u{119E0}', + '\u{11A34}', + '\u{11A47}', + '\u{11A99}', + '\u{11C3F}', + '\u{11D44}', + '\u{11D45}', + '\u{11D97}', + ]; // https://www.compart.com/en/unicode/combining/9 + let mut s = unicode; + while let Some(i) = s.find(zero_width_jointer) { + let prefix = &s[..i]; + if !prefix.ends_with(VIRAMA) { + Err("ZERO WIDTH JOINER must be preceded by Virama")?; + } + let suffix = &s[i + zero_width_jointer.len_utf8()..]; + s = suffix; } + } - // ZERO WIDTH JOINER must be preceded by Virama - // see https://www.rfc-editor.org/rfc/rfc5892#appendix-A.2 - { - let zero_width_jointer = '\u{200D}'; - static VIRAMA: [char; 61] = [ - '\u{094D}', - '\u{09CD}', - '\u{0A4D}', - '\u{0ACD}', - '\u{0B4D}', - '\u{0BCD}', - '\u{0C4D}', - '\u{0CCD}', - '\u{0D3B}', - '\u{0D3C}', - '\u{0D4D}', - '\u{0DCA}', - '\u{0E3A}', - '\u{0EBA}', - '\u{0F84}', - '\u{1039}', - '\u{103A}', - '\u{1714}', - '\u{1734}', - '\u{17D2}', - '\u{1A60}', - '\u{1B44}', - '\u{1BAA}', - '\u{1BAB}', - '\u{1BF2}', - '\u{1BF3}', - '\u{2D7F}', - '\u{A806}', - '\u{A82C}', - '\u{A8C4}', - '\u{A953}', - '\u{A9C0}', - '\u{AAF6}', - '\u{ABED}', - '\u{10A3F}', - '\u{11046}', - '\u{1107F}', - '\u{110B9}', - '\u{11133}', - '\u{11134}', - '\u{111C0}', - '\u{11235}', - '\u{112EA}', - '\u{1134D}', - '\u{11442}', - '\u{114C2}', - '\u{115BF}', - '\u{1163F}', - '\u{116B6}', - '\u{1172B}', - '\u{11839}', - '\u{1193D}', - '\u{1193E}', - '\u{119E0}', - '\u{11A34}', - '\u{11A47}', - '\u{11A99}', - '\u{11C3F}', - '\u{11D44}', - '\u{11D45}', - '\u{11D97}', - ]; // https://www.compart.com/en/unicode/combining/9 - let mut s = unicode; - while let Some(i) = s.find(zero_width_jointer) { - let prefix = &s[..i]; - if !prefix.ends_with(VIRAMA) { - Err("ZERO WIDTH JOINER must be preceded by Virama")?; - } - let suffix = &s[i + zero_width_jointer.len_utf8()..]; - s = suffix; - } - } - - Ok(()) + Ok(()) } fn validate_email(v: &Value) -> Result<(), Box> { - let Value::String(s) = v else { - return Ok(()); - }; - check_email(s)?; - Ok(()) + let Value::String(s) = v else { + return Ok(()); + }; + check_email(s)?; + Ok(()) } // see https://en.wikipedia.org/wiki/Email_address fn check_email(s: &str) -> Result<(), Box> { - // entire email address to be no more than 254 characters long - if s.len() > 254 { - Err("more than 254 characters long")? + // entire email address to be no more than 254 characters long + if s.len() > 254 { + Err("more than 254 characters long")? + } + + // email address is generally recognized as having two parts joined with an at-sign + let Some(at) = s.rfind('@') else { + Err("missing @")? + }; + let (local, domain) = (&s[..at], &s[at + 1..]); + + // local part may be up to 64 characters long + if local.len() > 64 { + Err("local part more than 64 characters long")? + } + + if local.len() > 1 && local.starts_with('"') && local.ends_with('"') { + // quoted + let local = &local[1..local.len() - 1]; + if local.contains(['\\', '"']) { + Err("backslash and quote not allowed within quoted local part")? + } + } else { + // unquoted + + if local.starts_with('.') { + Err("starts with dot")? + } + if local.ends_with('.') { + Err("ends with dot")? } - // email address is generally recognized as having two parts joined with an at-sign - let Some(at) = s.rfind('@') else { - Err("missing @")? - }; - let (local, domain) = (&s[..at], &s[at + 1..]); - - // local part may be up to 64 characters long - if local.len() > 64 { - Err("local part more than 64 characters long")? + // consecutive dots not allowed + if local.contains("..") { + Err("consecutive dots")? } - if local.len() > 1 && local.starts_with('"') && local.ends_with('"') { - // quoted - let local = &local[1..local.len() - 1]; - if local.contains(['\\', '"']) { - Err("backslash and quote not allowed within quoted local part")? - } - } else { - // unquoted - - if local.starts_with('.') { - Err("starts with dot")? - } - if local.ends_with('.') { - Err("ends with dot")? - } - - // consecutive dots not allowed - if local.contains("..") { - Err("consecutive dots")? - } - - // check allowd chars - if let Some(ch) = local - .chars() - .find(|c| !(c.is_ascii_alphanumeric() || ".!#$%&'*+-/=?^_`{|}~".contains(*c))) - { - Err(format!("invalid character {ch:?}"))? - } + // check allowd chars + if let Some(ch) = local + .chars() + .find(|c| !(c.is_ascii_alphanumeric() || ".!#$%&'*+-/=?^_`{|}~".contains(*c))) + { + Err(format!("invalid character {ch:?}"))? } + } - // domain if enclosed in brackets, must match an IP address - if domain.starts_with('[') && domain.ends_with(']') { - let s = &domain[1..domain.len() - 1]; - if let Some(s) = s.strip_prefix("IPv6:") { - if let Err(e) = s.parse::() { - Err(format!("invalid ipv6 address: {e}"))? - } - return Ok(()); - } - if let Err(e) = s.parse::() { - Err(format!("invalid ipv4 address: {e}"))? - } - return Ok(()); + // domain if enclosed in brackets, must match an IP address + if domain.starts_with('[') && domain.ends_with(']') { + let s = &domain[1..domain.len() - 1]; + if let Some(s) = s.strip_prefix("IPv6:") { + if let Err(e) = s.parse::() { + Err(format!("invalid ipv6 address: {e}"))? + } + return Ok(()); } - - // domain must match the requirements for a hostname - if let Err(e) = check_hostname(domain) { - Err(format!("invalid domain: {e}"))? + if let Err(e) = s.parse::() { + Err(format!("invalid ipv4 address: {e}"))? } + return Ok(()); + } - Ok(()) + // domain must match the requirements for a hostname + if let Err(e) = check_hostname(domain) { + Err(format!("invalid domain: {e}"))? + } + + Ok(()) } fn validate_idn_email(v: &Value) -> Result<(), Box> { - let Value::String(s) = v else { - return Ok(()); - }; + let Value::String(s) = v else { + return Ok(()); + }; - let Some(at) = s.rfind('@') else { - Err("missing @")? - }; - let (local, domain) = (&s[..at], &s[at + 1..]); + let Some(at) = s.rfind('@') else { + Err("missing @")? + }; + let (local, domain) = (&s[..at], &s[at + 1..]); - let local = idna::domain_to_ascii_strict(local).map_err(|e| format!("idna error: {:?}", e))?; - let domain = idna::domain_to_ascii_strict(domain).map_err(|e| format!("idna error: {:?}", e))?; - if let Err(e) = check_idn_hostname(&domain) { - Err(format!("invalid domain: {e}"))? - } - check_email(&format!("{local}@{domain}")) + let local = idna::domain_to_ascii_strict(local).map_err(|e| format!("idna error: {:?}", e))?; + let domain = idna::domain_to_ascii_strict(domain).map_err(|e| format!("idna error: {:?}", e))?; + if let Err(e) = check_idn_hostname(&domain) { + Err(format!("invalid domain: {e}"))? + } + check_email(&format!("{local}@{domain}")) } fn validate_json_pointer(v: &Value) -> Result<(), Box> { - let Value::String(s) = v else { - return Ok(()); - }; - check_json_pointer(s)?; - Ok(()) + let Value::String(s) = v else { + return Ok(()); + }; + check_json_pointer(s)?; + Ok(()) } // see https://www.rfc-editor.org/rfc/rfc6901#section-3 fn check_json_pointer(s: &str) -> Result<(), Box> { - if s.is_empty() { - return Ok(()); - } - if !s.starts_with('/') { - Err("not starting with slash")?; - } - for token in s.split('/').skip(1) { - let mut chars = token.chars(); - while let Some(ch) = chars.next() { - if ch == '~' { - if !matches!(chars.next(), Some('0' | '1')) { - Err("~ must be followed by 0 or 1")?; - } - } else if !matches!(ch, '\x00'..='\x2E' | '\x30'..='\x7D' | '\x7F'..='\u{10FFFF}') { - Err("contains disallowed character")?; - } + if s.is_empty() { + return Ok(()); + } + if !s.starts_with('/') { + Err("not starting with slash")?; + } + for token in s.split('/').skip(1) { + let mut chars = token.chars(); + while let Some(ch) = chars.next() { + if ch == '~' { + if !matches!(chars.next(), Some('0' | '1')) { + Err("~ must be followed by 0 or 1")?; } + } else if !matches!(ch, '\x00'..='\x2E' | '\x30'..='\x7D' | '\x7F'..='\u{10FFFF}') { + Err("contains disallowed character")?; + } } - Ok(()) + } + Ok(()) } // see https://tools.ietf.org/html/draft-handrews-relative-json-pointer-01#section-3 fn validate_relative_json_pointer(v: &Value) -> Result<(), Box> { - let Value::String(s) = v else { - return Ok(()); - }; + let Value::String(s) = v else { + return Ok(()); + }; - // start with non-negative-integer - let num_digits = s.chars().take_while(char::is_ascii_digit).count(); - if num_digits == 0 { - Err("must start with non-negative integer")?; - } - if num_digits > 1 && s.starts_with('0') { - Err("starts with zero")?; - } - let s = &s[num_digits..]; + // start with non-negative-integer + let num_digits = s.chars().take_while(char::is_ascii_digit).count(); + if num_digits == 0 { + Err("must start with non-negative integer")?; + } + if num_digits > 1 && s.starts_with('0') { + Err("starts with zero")?; + } + let s = &s[num_digits..]; - // followed by either json-pointer or '#' - if s == "#" { - return Ok(()); - } - if let Err(e) = check_json_pointer(s) { - Err(format!("invalid json-pointer element: {e}"))?; - } - Ok(()) + // followed by either json-pointer or '#' + if s == "#" { + return Ok(()); + } + if let Err(e) = check_json_pointer(s) { + Err(format!("invalid json-pointer element: {e}"))?; + } + Ok(()) } // see https://datatracker.ietf.org/doc/html/rfc4122#page-4 fn validate_uuid(v: &Value) -> Result<(), Box> { - let Value::String(s) = v else { - return Ok(()); - }; + let Value::String(s) = v else { + return Ok(()); + }; - static HEX_GROUPS: [usize; 5] = [8, 4, 4, 4, 12]; - let mut i = 0; - for group in s.split('-') { - if i >= HEX_GROUPS.len() { - Err("more than 5 elements")?; - } - if group.len() != HEX_GROUPS[i] { - Err(format!( - "element {} must be {} characters long", - i + 1, - HEX_GROUPS[i] - ))?; - } - if let Some(ch) = group.chars().find(|c| !c.is_ascii_hexdigit()) { - Err(format!("non-hex character {ch:?}"))?; - } - i += 1; + static HEX_GROUPS: [usize; 5] = [8, 4, 4, 4, 12]; + let mut i = 0; + for group in s.split('-') { + if i >= HEX_GROUPS.len() { + Err("more than 5 elements")?; } - if i != HEX_GROUPS.len() { - Err("must have 5 elements")?; + if group.len() != HEX_GROUPS[i] { + Err(format!( + "element {} must be {} characters long", + i + 1, + HEX_GROUPS[i] + ))?; } - Ok(()) + if let Some(ch) = group.chars().find(|c| !c.is_ascii_hexdigit()) { + Err(format!("non-hex character {ch:?}"))?; + } + i += 1; + } + if i != HEX_GROUPS.len() { + Err("must have 5 elements")?; + } + Ok(()) } fn validate_uri(v: &Value) -> Result<(), Box> { - let Value::String(s) = v else { - return Ok(()); - }; - if fluent_uri::UriRef::parse(s.as_str()).map_err(|e| e.to_string())?.scheme().is_none() { - Err("relative url")?; - }; - Ok(()) + let Value::String(s) = v else { + return Ok(()); + }; + if fluent_uri::UriRef::parse(s.as_str()) + .map_err(|e| e.to_string())? + .scheme() + .is_none() + { + Err("relative url")?; + }; + Ok(()) } fn validate_iri(v: &Value) -> Result<(), Box> { - let Value::String(s) = v else { - return Ok(()); - }; - match Url::parse(s) { - Ok(_) => Ok(()), - Err(url::ParseError::RelativeUrlWithoutBase) => Err("relative url")?, - Err(e) => Err(e)?, - } + let Value::String(s) = v else { + return Ok(()); + }; + match Url::parse(s) { + Ok(_) => Ok(()), + Err(url::ParseError::RelativeUrlWithoutBase) => Err("relative url")?, + Err(e) => Err(e)?, + } } lazy_static! { - static ref TEMP_URL: Url = Url::parse("http://temp.com").unwrap(); + static ref TEMP_URL: Url = Url::parse("http://temp.com").unwrap(); } fn parse_uri_reference(s: &str) -> Result> { - if s.contains('\\') { - Err("contains \\\\")?; - } - Ok(TEMP_URL.join(s)?) + if s.contains('\\') { + Err("contains \\\\")?; + } + Ok(TEMP_URL.join(s)?) } fn validate_uri_reference(v: &Value) -> Result<(), Box> { - let Value::String(s) = v else { - return Ok(()); - }; - fluent_uri::UriRef::parse(s.as_str()).map_err(|e| e.to_string())?; - Ok(()) + let Value::String(s) = v else { + return Ok(()); + }; + fluent_uri::UriRef::parse(s.as_str()).map_err(|e| e.to_string())?; + Ok(()) } fn validate_iri_reference(v: &Value) -> Result<(), Box> { - let Value::String(s) = v else { - return Ok(()); - }; - parse_uri_reference(s)?; - Ok(()) + let Value::String(s) = v else { + return Ok(()); + }; + parse_uri_reference(s)?; + Ok(()) } fn validate_uri_template(v: &Value) -> Result<(), Box> { - let Value::String(s) = v else { - return Ok(()); - }; + let Value::String(s) = v else { + return Ok(()); + }; - let url = parse_uri_reference(s)?; + let url = parse_uri_reference(s)?; - let path = url.path(); - // path we got has curly bases percent encoded - let path = percent_decode_str(path).decode_utf8()?; + let path = url.path(); + // path we got has curly bases percent encoded + let path = percent_decode_str(path).decode_utf8()?; - // ensure curly brackets are not nested and balanced - for part in path.as_ref().split('/') { - let mut want = true; - for got in part - .chars() - .filter(|c| matches!(c, '{' | '}')) - .map(|c| c == '{') - { - if got != want { - Err("nested curly braces")?; - } - want = !want; - } - if !want { - Err("no matching closing brace")? - } + // ensure curly brackets are not nested and balanced + for part in path.as_ref().split('/') { + let mut want = true; + for got in part + .chars() + .filter(|c| matches!(c, '{' | '}')) + .map(|c| c == '{') + { + if got != want { + Err("nested curly braces")?; + } + want = !want; } - Ok(()) + if !want { + Err("no matching closing brace")? + } + } + Ok(()) } diff --git a/src/database/mod.rs b/src/database/mod.rs index 8815e6a..5918ab3 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -16,7 +16,6 @@ pub struct Database { pub types: HashMap, pub puncs: HashMap, pub schemas: HashMap, - pub descendants: HashMap>, } impl Database { @@ -26,7 +25,6 @@ impl Database { types: HashMap::new(), puncs: HashMap::new(), schemas: HashMap::new(), - descendants: HashMap::new(), }; if let Some(arr) = val.get("enums").and_then(|v| v.as_array()) { @@ -75,146 +73,137 @@ impl Database { fn compile(&mut self) -> Result<(), String> { self.collect_schemas(); - // 1. Compile regex and formats sequentially - for schema in self.schemas.values_mut() { - schema.compile(); + // 1. Build a structural descendant graph for $family macro expansion + let mut direct_refs: std::collections::HashMap> = + std::collections::HashMap::new(); + for (id, schema) in &self.schemas { + if let Some(ref_str) = &schema.obj.ref_string { + direct_refs + .entry(ref_str.clone()) + .or_default() + .push(id.clone()); + } } - // 2. Compute the Unified Semantic Graph (descendants) - self.collect_descendents(); + let schema_ids: Vec = self.schemas.keys().cloned().collect(); - // 3. For any schema representing a Postgres table, cache its allowed subclasses - self.compile_allowed_types(); + // 2. Expand $family macros into oneOf blocks + for id in &schema_ids { + if let Some(schema) = self.schemas.get_mut(id) { + schema.map_children(|mut child| { + Self::expand_family(&mut child, &direct_refs); + }); + Self::expand_family(schema, &direct_refs); + } + } - // 4. Finally, securely link all string $refs into memory pointers (Arc) - self.compile_pointers(); + let schemas_snap = self.schemas.clone(); + + // 3. Compile internals and link memory pointers + for id in schema_ids { + if let Some(schema) = self.schemas.get_mut(&id) { + schema.compile_internals(); + schema.link_refs(&schemas_snap); + } + } Ok(()) } fn collect_schemas(&mut self) { let mut to_insert = Vec::new(); - for (_, type_def) in &self.types { - for schema in &type_def.schemas { - if let Some(id) = &schema.obj.id { - to_insert.push((id.clone(), schema.clone())); - } + + // Pass A: Entities - Compute Variations from hierarchies + // `hierarchy` is an array of ancestors. E.g. `person` -> `['entity', 'user', 'person']`. + // We map this backward so that `user`'s allowed variations = `['user', 'person']`. + let mut variations_by_entity = std::collections::HashMap::new(); + for type_def in self.types.values() { + for ancestor in &type_def.hierarchy { + variations_by_entity + .entry(ancestor.clone()) + .or_insert_with(std::collections::HashSet::new) + .insert(type_def.name.clone()); } } + + // Now stamp all exported entity schemas with their precise physical variations + for (_, type_def) in &self.types { + let allowed_strings = variations_by_entity + .get(&type_def.name) + .cloned() + .unwrap_or_default(); + for mut schema in type_def.schemas.clone() { + schema.stamp_variations(Some(allowed_strings.clone())); + schema.harvest(&mut to_insert); + } + } + + // Pass B: APIs and Enums (No initial variations stamped) for (_, punc_def) in &self.puncs { - for schema in &punc_def.schemas { - if let Some(id) = &schema.obj.id { - to_insert.push((id.clone(), schema.clone())); - } + for mut schema in punc_def.schemas.clone() { + schema.harvest(&mut to_insert); } } for (_, enum_def) in &self.enums { - for schema in &enum_def.schemas { - if let Some(id) = &schema.obj.id { - to_insert.push((id.clone(), schema.clone())); - } + for mut schema in enum_def.schemas.clone() { + schema.harvest(&mut to_insert); } } + for (id, schema) in to_insert { self.schemas.insert(id, schema); } } - fn collect_descendents(&mut self) { - let mut direct_children: HashMap> = HashMap::new(); + fn expand_family( + schema: &mut crate::database::schema::Schema, + direct_refs: &std::collections::HashMap>, + ) { + if let Some(family_target) = &schema.obj.family { + let mut descendants = std::collections::HashSet::new(); + Self::collect_descendants(family_target, direct_refs, &mut descendants); - // First pass: Find all schemas that have a $ref to another schema - let schema_ids: Vec = self.schemas.keys().cloned().collect(); - for id in schema_ids { - if let Some(ref_str) = self.schemas.get(&id).and_then(|s| s.obj.ref_string.clone()) { - if self.schemas.contains_key(&ref_str) { - direct_children.entry(ref_str).or_default().push(id.clone()); - } - } - } + // the "$family" macro is logically replaced by an anyOf of its descendants + itself + let mut derived_any_of = Vec::new(); - // Now compute descendants for all schemas - let mut descendants_map: HashMap> = HashMap::new(); - for key in self.schemas.keys() { - let mut descendants = Vec::new(); - let mut queue = Vec::new(); - if let Some(children) = direct_children.get(key) { - queue.extend(children.iter().cloned()); + // Include the target base itself if valid (which it always is structurally) + let mut base_ref = crate::database::schema::SchemaObject::default(); + base_ref.ref_string = Some(family_target.clone()); + derived_any_of.push(std::sync::Arc::new(crate::database::schema::Schema { + obj: base_ref, + always_fail: false, + })); + + // Sort descendants for determinism during testing + let mut desc_vec: Vec = descendants.into_iter().collect(); + desc_vec.sort(); + + for child_id in desc_vec { + let mut child_ref = crate::database::schema::SchemaObject::default(); + child_ref.ref_string = Some(child_id); + derived_any_of.push(std::sync::Arc::new(crate::database::schema::Schema { + obj: child_ref, + always_fail: false, + })); } - let mut visited = std::collections::HashSet::new(); - while let Some(child) = queue.pop() { - if visited.insert(child.clone()) { - descendants.push(child.clone()); - if let Some(grandchildren) = direct_children.get(&child) { - queue.extend(grandchildren.iter().cloned()); - } - } - } - descendants_map.insert(key.clone(), descendants); - } - self.descendants = descendants_map; - } - - fn compile_allowed_types(&mut self) { - // 1. Identify which types act as bases (table-backed schemas) - let mut entity_bases = HashMap::new(); - for type_def in self.types.values() { - for type_schema in &type_def.schemas { - if let Some(id) = &type_schema.obj.id { - entity_bases.insert(id.clone(), type_def.name.clone()); - } - } - } - - // 2. Compute compiled_allowed_types for all descendants of entity bases - let mut allowed_types_map: HashMap> = HashMap::new(); - for base_id in entity_bases.keys() { - allowed_types_map.insert( - base_id.clone(), - self - .descendants - .get(base_id) - .unwrap_or(&vec![]) - .iter() - .cloned() - .collect(), - ); - if let Some(descendants) = self.descendants.get(base_id) { - let set: std::collections::HashSet = descendants.iter().cloned().collect(); - for desc_id in descendants { - allowed_types_map.insert(desc_id.clone(), set.clone()); - } - } - } - - // 3. Inject types into the schemas - let schema_ids: Vec = self.schemas.keys().cloned().collect(); - for id in schema_ids { - if let Some(set) = allowed_types_map.get(&id) { - if let Some(schema) = self.schemas.get_mut(&id) { - schema.obj.compiled_allowed_types = Some(set.clone()); - } - } + schema.obj.any_of = Some(derived_any_of); + // Remove family so it doesn't cause conflicts or fail the simple validation + schema.obj.family = None; } } - fn compile_pointers(&mut self) { - let schema_ids: Vec = self.schemas.keys().cloned().collect(); - for id in schema_ids { - let mut compiled_ref = None; - - if let Some(schema) = self.schemas.get(&id) { - if let Some(ref_str) = &schema.obj.ref_string { - if let Some(target) = self.schemas.get(ref_str) { - compiled_ref = Some(std::sync::Arc::new(target.clone())); - } + fn collect_descendants( + target: &str, + direct_refs: &std::collections::HashMap>, + descendants: &mut std::collections::HashSet, + ) { + if let Some(children) = direct_refs.get(target) { + for child in children { + if descendants.insert(child.clone()) { + Self::collect_descendants(child, direct_refs, descendants); } } - - if let Some(schema) = self.schemas.get_mut(&id) { - schema.obj.compiled_ref = compiled_ref; - } } } } diff --git a/src/database/schema.rs b/src/database/schema.rs index 109baae..9933a94 100644 --- a/src/database/schema.rs +++ b/src/database/schema.rs @@ -124,7 +124,7 @@ pub struct SchemaObject { #[serde(skip)] pub compiled_ref: Option>, #[serde(skip)] - pub compiled_allowed_types: Option>, + pub compiled_variations: Option>, #[serde(skip)] pub compiled_format: Option, #[serde(skip)] @@ -133,11 +133,6 @@ pub struct SchemaObject { pub compiled_pattern_properties: Option)>>, } -pub enum ResolvedRef<'a> { - Local(&'a Schema), - Global(&'a Schema, &'a Schema), -} - /// Represents a compiled format validator #[derive(Clone)] pub enum CompiledFormat { @@ -188,12 +183,9 @@ impl std::ops::DerefMut for Schema { } impl Schema { - pub fn resolve_ref(&self, _ref_string: &str) -> Option<&Arc> { - // This is vestigial for now. References are global pointers. We will remove this shortly. - None - } + pub fn compile_internals(&mut self) { + self.map_children(|child| child.compile_internals()); - pub fn compile(&mut self) { if let Some(format_str) = &self.obj.format { if let Some(fmt) = crate::database::formats::FORMATS.get(format_str.as_str()) { self.obj.compiled_format = Some(crate::database::schema::CompiledFormat::Func(fmt.func)); @@ -217,96 +209,112 @@ impl Schema { self.obj.compiled_pattern_properties = Some(compiled); } } + } - // Crawl children recursively to compile their internals + pub fn link_refs(&mut self, schemas: &std::collections::HashMap) { + if let Some(ref_str) = &self.obj.ref_string { + if let Some(target) = schemas.get(ref_str) { + self.obj.compiled_ref = Some(Arc::new(target.clone())); + + // Viral Infection: Inherit physical entity boundaries across the $ref pointer recursively + if self.obj.compiled_variations.is_none() { + let mut visited = std::collections::HashSet::new(); + self.obj.compiled_variations = Self::resolve_variations(ref_str, schemas, &mut visited); + } + } + } + self.map_children(|child| child.link_refs(schemas)); + } + + fn resolve_variations( + ref_str: &str, + schemas: &std::collections::HashMap, + visited: &mut std::collections::HashSet, + ) -> Option> { + if !visited.insert(ref_str.to_string()) { + return None; // Cycle detected + } + + if let Some(target) = schemas.get(ref_str) { + if let Some(vars) = &target.obj.compiled_variations { + return Some(vars.clone()); + } + if let Some(next_ref) = &target.obj.ref_string { + return Self::resolve_variations(next_ref, schemas, visited); + } + } + None + } + + pub fn stamp_variations(&mut self, variations: Option>) { + self.obj.compiled_variations = variations.clone(); + self.map_children(|child| child.stamp_variations(variations.clone())); + } + + pub fn harvest(&mut self, to_insert: &mut Vec<(String, Schema)>) { + if let Some(id) = &self.obj.id { + to_insert.push((id.clone(), self.clone())); + } + self.map_children(|child| child.harvest(to_insert)); + } + + pub fn map_children(&mut self, mut f: F) + where + F: FnMut(&mut Schema), + { if let Some(props) = &mut self.obj.properties { for (_, v) in props { - // Safe deep mutation workaround without unsafe Arc unwrap let mut inner = (**v).clone(); - inner.compile(); + f(&mut inner); *v = Arc::new(inner); } } + if let Some(pattern_props) = &mut self.obj.pattern_properties { + for (_, v) in pattern_props { + let mut inner = (**v).clone(); + f(&mut inner); + *v = Arc::new(inner); + } + } + + let mut map_arr = |arr: &mut Vec>| { + for v in arr.iter_mut() { + let mut inner = (**v).clone(); + f(&mut inner); + *v = Arc::new(inner); + } + }; + if let Some(arr) = &mut self.obj.prefix_items { - for v in arr.iter_mut() { - let mut inner = (**v).clone(); - inner.compile(); - *v = Arc::new(inner); - } + map_arr(arr); } - if let Some(arr) = &mut self.obj.all_of { - for v in arr.iter_mut() { - let mut inner = (**v).clone(); - inner.compile(); - *v = Arc::new(inner); - } + map_arr(arr); } - if let Some(arr) = &mut self.obj.any_of { - for v in arr.iter_mut() { - let mut inner = (**v).clone(); - inner.compile(); - *v = Arc::new(inner); - } + map_arr(arr); } - if let Some(arr) = &mut self.obj.one_of { - for v in arr.iter_mut() { + map_arr(arr); + } + + let mut map_opt = |opt: &mut Option>| { + if let Some(v) = opt { let mut inner = (**v).clone(); - inner.compile(); + f(&mut inner); *v = Arc::new(inner); } - } + }; - if let Some(v) = &mut self.obj.additional_properties { - let mut inner = (**v).clone(); - inner.compile(); - *v = Arc::new(inner); - } - - if let Some(v) = &mut self.obj.items { - let mut inner = (**v).clone(); - inner.compile(); - *v = Arc::new(inner); - } - - if let Some(v) = &mut self.obj.contains { - let mut inner = (**v).clone(); - inner.compile(); - *v = Arc::new(inner); - } - - if let Some(v) = &mut self.obj.property_names { - let mut inner = (**v).clone(); - inner.compile(); - *v = Arc::new(inner); - } - - if let Some(v) = &mut self.obj.not { - let mut inner = (**v).clone(); - inner.compile(); - *v = Arc::new(inner); - } - - if let Some(v) = &mut self.obj.if_ { - let mut inner = (**v).clone(); - inner.compile(); - *v = Arc::new(inner); - } - - if let Some(v) = &mut self.obj.then_ { - let mut inner = (**v).clone(); - inner.compile(); - *v = Arc::new(inner); - } - - if let Some(v) = &mut self.obj.else_ { - let mut inner = (**v).clone(); - inner.compile(); - *v = Arc::new(inner); - } + map_opt(&mut self.obj.additional_properties); + map_opt(&mut self.obj.items); + map_opt(&mut self.obj.contains); + map_opt(&mut self.obj.property_names); + map_opt(&mut self.obj.not); + map_opt(&mut self.obj.if_); + map_opt(&mut self.obj.then_); + map_opt(&mut self.obj.else_); } } @@ -327,7 +335,37 @@ impl<'de> Deserialize<'de> for Schema { always_fail: !b, }); } - let obj: SchemaObject = serde_json::from_value(v.clone()).map_err(serde::de::Error::custom)?; + let mut obj: SchemaObject = + serde_json::from_value(v.clone()).map_err(serde::de::Error::custom)?; + + // If a schema is effectively empty (except for potentially carrying an ID), + // it functions as a boolean `true` schema in Draft2020 which means it should not + // restrict additional properties natively + let is_empty = obj.type_.is_none() + && obj.properties.is_none() + && obj.pattern_properties.is_none() + && obj.additional_properties.is_none() + && obj.required.is_none() + && obj.dependencies.is_none() + && obj.items.is_none() + && obj.prefix_items.is_none() + && obj.contains.is_none() + && obj.format.is_none() + && obj.enum_.is_none() + && obj.const_.is_none() + && obj.all_of.is_none() + && obj.any_of.is_none() + && obj.one_of.is_none() + && obj.not.is_none() + && obj.if_.is_none() + && obj.then_.is_none() + && obj.else_.is_none() + && obj.ref_string.is_none() + && obj.family.is_none(); + + if is_empty && obj.extensible.is_none() { + obj.extensible = Some(true); + } Ok(Schema { obj, diff --git a/src/tests/fixtures.rs b/src/tests/fixtures.rs index 3174cd8..4be1cac 100644 --- a/src/tests/fixtures.rs +++ b/src/tests/fixtures.rs @@ -101,6 +101,72 @@ fn test_additional_properties_2() { crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); } +#[pg_test] +fn test_dependencies_0() { + let path = format!("{}/tests/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); +} + +#[pg_test] +fn test_dependencies_1() { + let path = format!("{}/tests/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); +} + +#[pg_test] +fn test_dependencies_2() { + let path = format!("{}/tests/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); +} + +#[pg_test] +fn test_dependencies_3() { + let path = format!("{}/tests/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); +} + +#[pg_test] +fn test_dependencies_4() { + let path = format!("{}/tests/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + crate::validator::util::run_test_file_at_index(&path, 4).unwrap(); +} + +#[pg_test] +fn test_dependencies_5() { + let path = format!("{}/tests/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + crate::validator::util::run_test_file_at_index(&path, 5).unwrap(); +} + +#[pg_test] +fn test_dependencies_6() { + let path = format!("{}/tests/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + crate::validator::util::run_test_file_at_index(&path, 6).unwrap(); +} + +#[pg_test] +fn test_dependencies_7() { + let path = format!("{}/tests/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + crate::validator::util::run_test_file_at_index(&path, 7).unwrap(); +} + +#[pg_test] +fn test_dependencies_8() { + let path = format!("{}/tests/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + crate::validator::util::run_test_file_at_index(&path, 8).unwrap(); +} + +#[pg_test] +fn test_dependencies_9() { + let path = format!("{}/tests/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + crate::validator::util::run_test_file_at_index(&path, 9).unwrap(); +} + +#[pg_test] +fn test_dependencies_10() { + let path = format!("{}/tests/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + crate::validator::util::run_test_file_at_index(&path, 10).unwrap(); +} + #[pg_test] fn test_exclusive_minimum_0() { let path = format!("{}/tests/fixtures/exclusiveMinimum.json", env!("CARGO_MANIFEST_DIR")); @@ -497,30 +563,6 @@ fn test_items_15() { crate::validator::util::run_test_file_at_index(&path, 15).unwrap(); } -#[pg_test] -fn test_typed_refs_0() { - let path = format!("{}/tests/fixtures/typedRefs.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[pg_test] -fn test_typed_refs_1() { - let path = format!("{}/tests/fixtures/typedRefs.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[pg_test] -fn test_typed_refs_2() { - let path = format!("{}/tests/fixtures/typedRefs.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[pg_test] -fn test_typed_refs_3() { - let path = format!("{}/tests/fixtures/typedRefs.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); -} - #[pg_test] fn test_enum_0() { let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); @@ -803,42 +845,6 @@ fn test_max_length_1() { crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] -fn test_dependent_schemas_0() { - let path = format!("{}/tests/fixtures/dependentSchemas.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[pg_test] -fn test_dependent_schemas_1() { - let path = format!("{}/tests/fixtures/dependentSchemas.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[pg_test] -fn test_dependent_schemas_2() { - let path = format!("{}/tests/fixtures/dependentSchemas.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[pg_test] -fn test_dependent_schemas_3() { - let path = format!("{}/tests/fixtures/dependentSchemas.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); -} - -#[pg_test] -fn test_dependent_schemas_4() { - let path = format!("{}/tests/fixtures/dependentSchemas.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 4).unwrap(); -} - -#[pg_test] -fn test_dependent_schemas_5() { - let path = format!("{}/tests/fixtures/dependentSchemas.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 5).unwrap(); -} - #[pg_test] fn test_exclusive_maximum_0() { let path = format!("{}/tests/fixtures/exclusiveMaximum.json", env!("CARGO_MANIFEST_DIR")); @@ -1079,30 +1085,6 @@ fn test_pattern_1() { crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] -fn test_masking_0() { - let path = format!("{}/tests/fixtures/masking.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[pg_test] -fn test_masking_1() { - let path = format!("{}/tests/fixtures/masking.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[pg_test] -fn test_masking_2() { - let path = format!("{}/tests/fixtures/masking.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[pg_test] -fn test_masking_3() { - let path = format!("{}/tests/fixtures/masking.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); -} - #[pg_test] fn test_max_properties_0() { let path = format!("{}/tests/fixtures/maxProperties.json", env!("CARGO_MANIFEST_DIR")); @@ -1127,36 +1109,6 @@ fn test_max_properties_3() { crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); } -#[pg_test] -fn test_dependent_required_0() { - let path = format!("{}/tests/fixtures/dependentRequired.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[pg_test] -fn test_dependent_required_1() { - let path = format!("{}/tests/fixtures/dependentRequired.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[pg_test] -fn test_dependent_required_2() { - let path = format!("{}/tests/fixtures/dependentRequired.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[pg_test] -fn test_dependent_required_3() { - let path = format!("{}/tests/fixtures/dependentRequired.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); -} - -#[pg_test] -fn test_dependent_required_4() { - let path = format!("{}/tests/fixtures/dependentRequired.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 4).unwrap(); -} - #[pg_test] fn test_required_0() { let path = format!("{}/tests/fixtures/required.json", env!("CARGO_MANIFEST_DIR")); @@ -1685,150 +1637,6 @@ fn test_ref_15() { crate::validator::util::run_test_file_at_index(&path, 15).unwrap(); } -#[pg_test] -fn test_ref_16() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 16).unwrap(); -} - -#[pg_test] -fn test_ref_17() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 17).unwrap(); -} - -#[pg_test] -fn test_ref_18() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 18).unwrap(); -} - -#[pg_test] -fn test_ref_19() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 19).unwrap(); -} - -#[pg_test] -fn test_ref_20() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 20).unwrap(); -} - -#[pg_test] -fn test_ref_21() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 21).unwrap(); -} - -#[pg_test] -fn test_ref_22() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 22).unwrap(); -} - -#[pg_test] -fn test_ref_23() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 23).unwrap(); -} - -#[pg_test] -fn test_ref_24() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 24).unwrap(); -} - -#[pg_test] -fn test_ref_25() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 25).unwrap(); -} - -#[pg_test] -fn test_ref_26() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 26).unwrap(); -} - -#[pg_test] -fn test_ref_27() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 27).unwrap(); -} - -#[pg_test] -fn test_ref_28() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 28).unwrap(); -} - -#[pg_test] -fn test_ref_29() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 29).unwrap(); -} - -#[pg_test] -fn test_ref_30() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 30).unwrap(); -} - -#[pg_test] -fn test_ref_31() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 31).unwrap(); -} - -#[pg_test] -fn test_ref_32() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 32).unwrap(); -} - -#[pg_test] -fn test_ref_33() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 33).unwrap(); -} - -#[pg_test] -fn test_ref_34() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 34).unwrap(); -} - -#[pg_test] -fn test_ref_35() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 35).unwrap(); -} - -#[pg_test] -fn test_ref_36() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 36).unwrap(); -} - -#[pg_test] -fn test_ref_37() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 37).unwrap(); -} - -#[pg_test] -fn test_ref_38() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 38).unwrap(); -} - -#[pg_test] -fn test_ref_39() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 39).unwrap(); -} - #[pg_test] fn test_maximum_0() { let path = format!("{}/tests/fixtures/maximum.json", env!("CARGO_MANIFEST_DIR")); diff --git a/src/validator/context.rs b/src/validator/context.rs index 848c473..4c61f12 100644 --- a/src/validator/context.rs +++ b/src/validator/context.rs @@ -11,39 +11,16 @@ pub struct ValidationContext<'a> { pub depth: usize, pub extensible: bool, pub reporter: bool, + pub overrides: std::collections::HashSet, } impl<'a> ValidationContext<'a> { - pub fn resolve_ref( - &self, - ref_string: &str, - ) -> Option<(crate::database::schema::ResolvedRef<'a>, String)> { - if let Some(local_schema_arc) = self.root.resolve_ref(ref_string) { - if ref_string.starts_with('#') { - return Some(( - crate::database::schema::ResolvedRef::Local(local_schema_arc.as_ref()), - ref_string.to_string(), - )); - } - } - - // We will replace all of this with `self.schema.compiled_ref` heavily shortly. - // For now, doing a basic map lookup to pass compilation. - if let Some(s) = self.schemas.get(ref_string) { - return Some(( - crate::database::schema::ResolvedRef::Global(s, s), - ref_string.to_string(), - )); - } - - None - } - pub fn new( schemas: &'a std::collections::HashMap, root: &'a Schema, schema: &'a Schema, instance: &'a serde_json::Value, + overrides: std::collections::HashSet, extensible: bool, reporter: bool, ) -> Self { @@ -57,6 +34,7 @@ impl<'a> ValidationContext<'a> { depth: 0, extensible: effective_extensible, reporter, + overrides, } } @@ -65,6 +43,7 @@ impl<'a> ValidationContext<'a> { schema: &'a Schema, instance: &'a serde_json::Value, path: &str, + overrides: std::collections::HashSet, extensible: bool, reporter: bool, ) -> Self { @@ -79,11 +58,19 @@ impl<'a> ValidationContext<'a> { depth: self.depth + 1, extensible: effective_extensible, reporter, + overrides, } } pub fn derive_for_schema(&self, schema: &'a Schema, reporter: bool) -> Self { - self.derive(schema, self.instance, &self.path, self.extensible, reporter) + self.derive( + schema, + self.instance, + &self.path, + std::collections::HashSet::new(), + self.extensible, + reporter, + ) } pub fn validate(&self) -> Result { diff --git a/src/validator/mod.rs b/src/validator/mod.rs index 9a9f0fd..3004115 100644 --- a/src/validator/mod.rs +++ b/src/validator/mod.rs @@ -8,17 +8,16 @@ pub use context::ValidationContext; pub use error::ValidationError; pub use result::ValidationResult; +use crate::database::schema::Schema; use serde_json::Value; -use std::collections::HashSet; - +use std::collections::HashMap; +use std::sync::Arc; pub struct Validator { - pub schemas: std::sync::Arc>, + pub schemas: Arc>, } impl Validator { - pub fn new( - schemas: std::sync::Arc>, - ) -> Self { + pub fn new(schemas: Arc>) -> Self { Self { schemas } } @@ -50,7 +49,15 @@ impl Validator { instance: &Value, ) -> Result { if let Some(schema) = self.schemas.get(schema_id) { - let ctx = ValidationContext::new(&self.schemas, schema, schema, instance, false, false); + let ctx = ValidationContext::new( + &self.schemas, + schema, + schema, + instance, + std::collections::HashSet::new(), + false, + false, + ); ctx.validate_scoped() } else { Err(ValidationError { diff --git a/src/validator/rules/array.rs b/src/validator/rules/array.rs index 821b97b..0b23a60 100644 --- a/src/validator/rules/array.rs +++ b/src/validator/rules/array.rs @@ -1,5 +1,4 @@ use serde_json::Value; -use std::collections::HashSet; use crate::validator::context::ValidationContext; use crate::validator::error::ValidationError; @@ -53,6 +52,7 @@ impl<'a> ValidationContext<'a> { contains_schema, child_instance, &self.path, + std::collections::HashSet::new(), self.extensible, false, ); @@ -91,7 +91,14 @@ impl<'a> ValidationContext<'a> { if i < len { let path = format!("{}/{}", self.path, i); if let Some(child_instance) = arr.get(i) { - let derived = self.derive(sub_schema, child_instance, &path, self.extensible, false); + let derived = self.derive( + sub_schema, + child_instance, + &path, + std::collections::HashSet::new(), + self.extensible, + false, + ); let item_res = derived.validate()?; result.merge(item_res); result.evaluated_indices.insert(i); @@ -105,7 +112,14 @@ impl<'a> ValidationContext<'a> { for i in validation_index..len { let path = format!("{}/{}", self.path, i); if let Some(child_instance) = arr.get(i) { - let derived = self.derive(items_schema, child_instance, &path, self.extensible, false); + let derived = self.derive( + items_schema, + child_instance, + &path, + std::collections::HashSet::new(), + self.extensible, + false, + ); let item_res = derived.validate()?; result.merge(item_res); result.evaluated_indices.insert(i); diff --git a/src/validator/rules/conditionals.rs b/src/validator/rules/conditionals.rs index 61195a7..b489166 100644 --- a/src/validator/rules/conditionals.rs +++ b/src/validator/rules/conditionals.rs @@ -42,7 +42,7 @@ impl<'a> ValidationContext<'a> { if let Some(obj) = self.instance.as_object() { for key in obj.keys() { - if !result.evaluated_keys.contains(key) { + if !result.evaluated_keys.contains(key) && !self.overrides.contains(key) { result.errors.push(ValidationError { code: "STRICT_PROPERTY_VIOLATION".to_string(), message: format!("Unexpected property '{}'", key), diff --git a/src/validator/rules/mod.rs b/src/validator/rules/mod.rs index f10bfac..92a5896 100644 --- a/src/validator/rules/mod.rs +++ b/src/validator/rules/mod.rs @@ -1,5 +1,3 @@ -use serde_json::Value; -use std::collections::HashSet; use crate::validator::context::ValidationContext; use crate::validator::error::ValidationError; diff --git a/src/validator/rules/object.rs b/src/validator/rules/object.rs index a70432b..2154eae 100644 --- a/src/validator/rules/object.rs +++ b/src/validator/rules/object.rs @@ -1,5 +1,4 @@ use serde_json::Value; -use std::collections::HashSet; use crate::validator::context::ValidationContext; use crate::validator::error::ValidationError; @@ -13,7 +12,7 @@ impl<'a> ValidationContext<'a> { let current = self.instance; if let Some(obj) = current.as_object() { // Entity Bound Implicit Type Validation - if let Some(allowed_types) = &self.schema.obj.compiled_allowed_types { + if let Some(allowed_types) = &self.schema.obj.compiled_variations { if let Some(type_val) = obj.get("type") { if let Some(type_str) = type_val.as_str() { if allowed_types.contains(type_str) { @@ -62,8 +61,38 @@ impl<'a> ValidationContext<'a> { } } + if let Some(ref deps) = self.schema.dependencies { + for (prop, dep) in deps { + if obj.contains_key(prop) { + match dep { + crate::database::schema::Dependency::Props(required_props) => { + for req_prop in required_props { + if !obj.contains_key(req_prop) { + result.errors.push(ValidationError { + code: "DEPENDENCY_MISSING".to_string(), + message: format!("Property '{}' requires property '{}'", prop, req_prop), + path: self.path.to_string(), + }); + } + } + } + crate::database::schema::Dependency::Schema(dep_schema) => { + let derived = self.derive_for_schema(dep_schema, false); + let dep_res = derived.validate()?; + result.evaluated_keys.extend(dep_res.evaluated_keys.clone()); + result.merge(dep_res); + } + } + } + } + } + if let Some(props) = &self.schema.properties { for (key, sub_schema) in props { + if self.overrides.contains(key) { + continue; // Skip validation if exactly this property was overridden by a child + } + if let Some(child_instance) = obj.get(key) { let new_path = format!("{}/{}", self.path, key); let is_ref = sub_schema.ref_string.is_some() || sub_schema.obj.compiled_ref.is_some(); @@ -73,6 +102,7 @@ impl<'a> ValidationContext<'a> { sub_schema, child_instance, &new_path, + std::collections::HashSet::new(), next_extensible, false, ); @@ -80,7 +110,7 @@ impl<'a> ValidationContext<'a> { // Entity Bound Implicit Type Interception if key == "type" { - if let Some(allowed_types) = &self.schema.obj.compiled_allowed_types { + if let Some(allowed_types) = &self.schema.obj.compiled_variations { if let Some(instance_type) = child_instance.as_str() { if allowed_types.contains(instance_type) { item_res @@ -109,6 +139,7 @@ impl<'a> ValidationContext<'a> { sub_schema, child_instance, &new_path, + std::collections::HashSet::new(), next_extensible, false, ); @@ -149,6 +180,7 @@ impl<'a> ValidationContext<'a> { additional_schema, child_instance, &new_path, + std::collections::HashSet::new(), next_extensible, false, ); @@ -169,6 +201,7 @@ impl<'a> ValidationContext<'a> { self.root, property_names, &val_str, + std::collections::HashSet::new(), self.extensible, self.reporter, ); diff --git a/src/validator/rules/polymorphism.rs b/src/validator/rules/polymorphism.rs index b099e70..5f9ce25 100644 --- a/src/validator/rules/polymorphism.rs +++ b/src/validator/rules/polymorphism.rs @@ -39,22 +39,31 @@ impl<'a> ValidationContext<'a> { &self, result: &mut ValidationResult, ) -> Result { - // 1. Core $ref logic fully transitioned to memory pointer resolutions. - if let Some(_ref_str) = &self.schema.ref_string { - if let Some(global_schema) = &self.schema.compiled_ref { + // 1. Core $ref logic relies on the fast O(1) map to allow cycles and proper nesting + if let Some(ref_str) = &self.schema.ref_string { + if let Some(global_schema) = self.schemas.get(ref_str) { + let mut new_overrides = self.overrides.clone(); + if let Some(props) = &self.schema.properties { + new_overrides.extend(props.keys().map(|k| k.to_string())); + } + let mut shadow = self.derive( global_schema, self.instance, &self.path, + new_overrides, self.extensible, - false, + true, ); shadow.root = global_schema; result.merge(shadow.validate()?); } else { result.errors.push(ValidationError { code: "REF_RESOLUTION_FAILED".to_string(), - message: format!("Reference pointer was not compiled inside Database graph"), + message: format!( + "Reference pointer to '{}' was not found in schema registry", + ref_str + ), path: self.path.to_string(), }); } diff --git a/src/validator/util.rs b/src/validator/util.rs index 64cc8b8..de7bcd3 100644 --- a/src/validator/util.rs +++ b/src/validator/util.rs @@ -15,7 +15,7 @@ struct TestCase { data: serde_json::Value, valid: bool, // Support explicit schema ID target for test case - schema_id: Option, + schema_id: String, } // use crate::validator::registry::REGISTRY; // No longer used directly for tests! @@ -49,62 +49,36 @@ pub fn run_test_file_at_index(path: &str, index: usize) -> Result<(), String> { // 4. Run Tests for (_test_index, test) in group.tests.iter().enumerate() { - let mut schema_id = test.schema_id.clone(); + let schema_id = &test.schema_id; - // If no explicit schema_id, infer from the database structure - if schema_id.is_none() { - if let Some(schemas) = db_json.get("schemas").and_then(|v| v.as_array()) { - if let Some(first) = schemas.first() { - if let Some(id) = first.get("$id").and_then(|v| v.as_str()) { - schema_id = Some(id.to_string()); - } else { - schema_id = Some("schema_0".to_string()); - } - } - } - - if schema_id.is_none() { - if let Some(puncs) = db_json.get("puncs").and_then(|v| v.as_array()) { - if let Some(first_punc) = puncs.first() { - if let Some(schemas) = first_punc.get("schemas").and_then(|v| v.as_array()) { - if let Some(first) = schemas.first() { - if let Some(id) = first.get("$id").and_then(|v| v.as_str()) { - schema_id = Some(id.to_string()); - } - } - } - } - } - } + if validator.schemas.get(schema_id).is_none() { + failures.push(format!( + "[{}] Missing Schema: Cannot find schema ID '{}'", + group.description, schema_id + )); + continue; } - if let Some(sid) = schema_id { - let result = validator.validate(&sid, &test.data); + let result = validator.validate(schema_id, &test.data); - let (got_valid, _errors) = match &result { - Ok(res) => (res.is_valid(), &res.errors), - Err(_e) => { - // If we encounter an execution error (e.g. Schema Not Found), - // we treat it as a test failure. - (false, &vec![]) - } + let (got_valid, _errors) = match &result { + Ok(res) => (res.is_valid(), &res.errors), + Err(_e) => { + // If we encounter an execution error (e.g. Schema Not Found), + // we treat it as a test failure. + (false, &vec![]) + } + }; + + if got_valid != test.valid { + let error_msg = match &result { + Ok(res) => format!("{:?}", res.errors), + Err(e) => format!("Execution Error: {:?}", e), }; - if got_valid != test.valid { - let error_msg = match &result { - Ok(res) => format!("{:?}", res.errors), - Err(e) => format!("Execution Error: {:?}", e), - }; - - failures.push(format!( - "[{}] Test '{}' failed. Expected: {}, Got: {}. Errors: {}", - group.description, test.description, test.valid, got_valid, error_msg - )); - } - } else { failures.push(format!( - "[{}] Test '{}' skipped: No schema ID found.", - group.description, test.description + "[{}] Test '{}' failed. Expected: {}, Got: {}. Errors: {}", + group.description, test.description, test.valid, got_valid, error_msg )); } } diff --git a/tests/fixtures.rs b/tests/fixtures.rs index 57f5574..3df2c66 100644 --- a/tests/fixtures.rs +++ b/tests/fixtures.rs @@ -102,6 +102,72 @@ fn test_additional_properties_2() { util::run_test_file_at_index(&path, 2).unwrap(); } +#[test] +fn test_dependencies_0() { + let path = format!("{}/tests/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + util::run_test_file_at_index(&path, 0).unwrap(); +} + +#[test] +fn test_dependencies_1() { + let path = format!("{}/tests/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + util::run_test_file_at_index(&path, 1).unwrap(); +} + +#[test] +fn test_dependencies_2() { + let path = format!("{}/tests/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + util::run_test_file_at_index(&path, 2).unwrap(); +} + +#[test] +fn test_dependencies_3() { + let path = format!("{}/tests/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + util::run_test_file_at_index(&path, 3).unwrap(); +} + +#[test] +fn test_dependencies_4() { + let path = format!("{}/tests/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + util::run_test_file_at_index(&path, 4).unwrap(); +} + +#[test] +fn test_dependencies_5() { + let path = format!("{}/tests/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + util::run_test_file_at_index(&path, 5).unwrap(); +} + +#[test] +fn test_dependencies_6() { + let path = format!("{}/tests/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + util::run_test_file_at_index(&path, 6).unwrap(); +} + +#[test] +fn test_dependencies_7() { + let path = format!("{}/tests/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + util::run_test_file_at_index(&path, 7).unwrap(); +} + +#[test] +fn test_dependencies_8() { + let path = format!("{}/tests/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + util::run_test_file_at_index(&path, 8).unwrap(); +} + +#[test] +fn test_dependencies_9() { + let path = format!("{}/tests/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + util::run_test_file_at_index(&path, 9).unwrap(); +} + +#[test] +fn test_dependencies_10() { + let path = format!("{}/tests/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + util::run_test_file_at_index(&path, 10).unwrap(); +} + #[test] fn test_exclusive_minimum_0() { let path = format!("{}/tests/fixtures/exclusiveMinimum.json", env!("CARGO_MANIFEST_DIR")); @@ -498,30 +564,6 @@ fn test_items_15() { util::run_test_file_at_index(&path, 15).unwrap(); } -#[test] -fn test_typed_refs_0() { - let path = format!("{}/tests/fixtures/typedRefs.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_typed_refs_1() { - let path = format!("{}/tests/fixtures/typedRefs.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_typed_refs_2() { - let path = format!("{}/tests/fixtures/typedRefs.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_typed_refs_3() { - let path = format!("{}/tests/fixtures/typedRefs.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 3).unwrap(); -} - #[test] fn test_enum_0() { let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); @@ -804,42 +846,6 @@ fn test_max_length_1() { util::run_test_file_at_index(&path, 1).unwrap(); } -#[test] -fn test_dependent_schemas_0() { - let path = format!("{}/tests/fixtures/dependentSchemas.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_dependent_schemas_1() { - let path = format!("{}/tests/fixtures/dependentSchemas.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_dependent_schemas_2() { - let path = format!("{}/tests/fixtures/dependentSchemas.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_dependent_schemas_3() { - let path = format!("{}/tests/fixtures/dependentSchemas.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 3).unwrap(); -} - -#[test] -fn test_dependent_schemas_4() { - let path = format!("{}/tests/fixtures/dependentSchemas.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 4).unwrap(); -} - -#[test] -fn test_dependent_schemas_5() { - let path = format!("{}/tests/fixtures/dependentSchemas.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 5).unwrap(); -} - #[test] fn test_exclusive_maximum_0() { let path = format!("{}/tests/fixtures/exclusiveMaximum.json", env!("CARGO_MANIFEST_DIR")); @@ -1080,30 +1086,6 @@ fn test_pattern_1() { util::run_test_file_at_index(&path, 1).unwrap(); } -#[test] -fn test_masking_0() { - let path = format!("{}/tests/fixtures/masking.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_masking_1() { - let path = format!("{}/tests/fixtures/masking.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_masking_2() { - let path = format!("{}/tests/fixtures/masking.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_masking_3() { - let path = format!("{}/tests/fixtures/masking.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 3).unwrap(); -} - #[test] fn test_max_properties_0() { let path = format!("{}/tests/fixtures/maxProperties.json", env!("CARGO_MANIFEST_DIR")); @@ -1128,36 +1110,6 @@ fn test_max_properties_3() { util::run_test_file_at_index(&path, 3).unwrap(); } -#[test] -fn test_dependent_required_0() { - let path = format!("{}/tests/fixtures/dependentRequired.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_dependent_required_1() { - let path = format!("{}/tests/fixtures/dependentRequired.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_dependent_required_2() { - let path = format!("{}/tests/fixtures/dependentRequired.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_dependent_required_3() { - let path = format!("{}/tests/fixtures/dependentRequired.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 3).unwrap(); -} - -#[test] -fn test_dependent_required_4() { - let path = format!("{}/tests/fixtures/dependentRequired.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 4).unwrap(); -} - #[test] fn test_required_0() { let path = format!("{}/tests/fixtures/required.json", env!("CARGO_MANIFEST_DIR")); @@ -1686,150 +1638,6 @@ fn test_ref_15() { util::run_test_file_at_index(&path, 15).unwrap(); } -#[test] -fn test_ref_16() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 16).unwrap(); -} - -#[test] -fn test_ref_17() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 17).unwrap(); -} - -#[test] -fn test_ref_18() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 18).unwrap(); -} - -#[test] -fn test_ref_19() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 19).unwrap(); -} - -#[test] -fn test_ref_20() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 20).unwrap(); -} - -#[test] -fn test_ref_21() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 21).unwrap(); -} - -#[test] -fn test_ref_22() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 22).unwrap(); -} - -#[test] -fn test_ref_23() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 23).unwrap(); -} - -#[test] -fn test_ref_24() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 24).unwrap(); -} - -#[test] -fn test_ref_25() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 25).unwrap(); -} - -#[test] -fn test_ref_26() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 26).unwrap(); -} - -#[test] -fn test_ref_27() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 27).unwrap(); -} - -#[test] -fn test_ref_28() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 28).unwrap(); -} - -#[test] -fn test_ref_29() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 29).unwrap(); -} - -#[test] -fn test_ref_30() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 30).unwrap(); -} - -#[test] -fn test_ref_31() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 31).unwrap(); -} - -#[test] -fn test_ref_32() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 32).unwrap(); -} - -#[test] -fn test_ref_33() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 33).unwrap(); -} - -#[test] -fn test_ref_34() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 34).unwrap(); -} - -#[test] -fn test_ref_35() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 35).unwrap(); -} - -#[test] -fn test_ref_36() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 36).unwrap(); -} - -#[test] -fn test_ref_37() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 37).unwrap(); -} - -#[test] -fn test_ref_38() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 38).unwrap(); -} - -#[test] -fn test_ref_39() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 39).unwrap(); -} - #[test] fn test_maximum_0() { let path = format!("{}/tests/fixtures/maximum.json", env!("CARGO_MANIFEST_DIR")); diff --git a/tests/fixtures/additionalProperties.json b/tests/fixtures/additionalProperties.json index aaedbf0..08b15fe 100644 --- a/tests/fixtures/additionalProperties.json +++ b/tests/fixtures/additionalProperties.json @@ -4,7 +4,7 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "schema1", "properties": { "foo": { "type": "string" @@ -26,7 +26,8 @@ "foo": "value", "bar": 123 }, - "valid": true + "valid": true, + "schema_id": "schema1" }, { "description": "additional property matching schema is valid", @@ -35,7 +36,8 @@ "is_active": true, "hidden": false }, - "valid": true + "valid": true, + "schema_id": "schema1" }, { "description": "additional property not matching schema is invalid", @@ -43,7 +45,8 @@ "foo": "value", "is_active": 1 }, - "valid": false + "valid": false, + "schema_id": "schema1" } ] }, @@ -52,7 +55,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "foo": { "type": "string" @@ -61,7 +63,8 @@ "extensible": true, "additionalProperties": { "type": "integer" - } + }, + "$id": "additionalProperties_1_0" } ] }, @@ -73,7 +76,8 @@ "count": 5, "age": 42 }, - "valid": true + "valid": true, + "schema_id": "additionalProperties_1_0" }, { "description": "additional property not matching schema is invalid despite extensible: true", @@ -81,7 +85,8 @@ "foo": "hello", "count": "five" }, - "valid": false + "valid": false, + "schema_id": "additionalProperties_1_0" } ] }, @@ -90,7 +95,7 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "schema3", "properties": { "type": { "type": "string" @@ -118,7 +123,8 @@ "field3" ] }, - "valid": true + "valid": true, + "schema_id": "schema3" }, { "description": "invalid array of integers", @@ -129,7 +135,8 @@ 2 ] }, - "valid": false + "valid": false, + "schema_id": "schema3" }, { "description": "invalid non-array type", @@ -137,7 +144,8 @@ "type": "my_type", "group_a": "field1" }, - "valid": false + "valid": false, + "schema_id": "schema3" } ] } diff --git a/tests/fixtures/allOf.json b/tests/fixtures/allOf.json index 622fb60..38db358 100644 --- a/tests/fixtures/allOf.json +++ b/tests/fixtures/allOf.json @@ -4,7 +4,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "allOf": [ { "properties": { @@ -26,7 +25,8 @@ "foo" ] } - ] + ], + "$id": "allOf_0_0" } ] }, @@ -37,21 +37,24 @@ "foo": "baz", "bar": 2 }, - "valid": true + "valid": true, + "schema_id": "allOf_0_0" }, { "description": "mismatch second", "data": { "foo": "baz" }, - "valid": false + "valid": false, + "schema_id": "allOf_0_0" }, { "description": "mismatch first", "data": { "bar": 2 }, - "valid": false + "valid": false, + "schema_id": "allOf_0_0" }, { "description": "wrong type", @@ -59,7 +62,8 @@ "foo": "baz", "bar": "quux" }, - "valid": false + "valid": false, + "schema_id": "allOf_0_0" } ] }, @@ -68,7 +72,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "bar": { "type": "integer" @@ -102,7 +105,8 @@ "baz" ] } - ] + ], + "$id": "allOf_1_0" } ] }, @@ -114,7 +118,8 @@ "bar": 2, "baz": null }, - "valid": true + "valid": true, + "schema_id": "allOf_1_0" }, { "description": "mismatch base schema", @@ -122,7 +127,8 @@ "foo": "quux", "baz": null }, - "valid": false + "valid": false, + "schema_id": "allOf_1_0" }, { "description": "mismatch first allOf", @@ -130,7 +136,8 @@ "bar": 2, "baz": null }, - "valid": false + "valid": false, + "schema_id": "allOf_1_0" }, { "description": "mismatch second allOf", @@ -138,14 +145,16 @@ "foo": "quux", "bar": 2 }, - "valid": false + "valid": false, + "schema_id": "allOf_1_0" }, { "description": "mismatch both", "data": { "bar": 2 }, - "valid": false + "valid": false, + "schema_id": "allOf_1_0" } ] }, @@ -154,7 +163,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "allOf": [ { "maximum": 30 @@ -162,7 +170,8 @@ { "minimum": 20 } - ] + ], + "$id": "allOf_2_0" } ] }, @@ -170,12 +179,14 @@ { "description": "valid", "data": 25, - "valid": true + "valid": true, + "schema_id": "allOf_2_0" }, { "description": "mismatch one", "data": 35, - "valid": false + "valid": false, + "schema_id": "allOf_2_0" } ] }, @@ -184,11 +195,11 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "allOf": [ true, true - ] + ], + "$id": "allOf_3_0" } ] }, @@ -196,7 +207,8 @@ { "description": "any value is valid", "data": "foo", - "valid": true + "valid": true, + "schema_id": "allOf_3_0" } ] }, @@ -205,11 +217,11 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "allOf": [ true, false - ] + ], + "$id": "allOf_4_0" } ] }, @@ -217,7 +229,8 @@ { "description": "any value is invalid", "data": "foo", - "valid": false + "valid": false, + "schema_id": "allOf_4_0" } ] }, @@ -226,11 +239,11 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "allOf": [ false, false - ] + ], + "$id": "allOf_5_0" } ] }, @@ -238,7 +251,8 @@ { "description": "any value is invalid", "data": "foo", - "valid": false + "valid": false, + "schema_id": "allOf_5_0" } ] }, @@ -247,10 +261,10 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "allOf": [ {} - ] + ], + "$id": "allOf_6_0" } ] }, @@ -258,7 +272,8 @@ { "description": "any data is valid", "data": 1, - "valid": true + "valid": true, + "schema_id": "allOf_6_0" } ] }, @@ -267,11 +282,11 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "allOf": [ {}, {} - ] + ], + "$id": "allOf_7_0" } ] }, @@ -279,7 +294,8 @@ { "description": "any data is valid", "data": 1, - "valid": true + "valid": true, + "schema_id": "allOf_7_0" } ] }, @@ -288,13 +304,13 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "allOf": [ {}, { "type": "number" } - ] + ], + "$id": "allOf_8_0" } ] }, @@ -302,12 +318,14 @@ { "description": "number is valid", "data": 1, - "valid": true + "valid": true, + "schema_id": "allOf_8_0" }, { "description": "string is invalid", "data": "foo", - "valid": false + "valid": false, + "schema_id": "allOf_8_0" } ] }, @@ -316,13 +334,13 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "allOf": [ { "type": "number" }, {} - ] + ], + "$id": "allOf_9_0" } ] }, @@ -330,12 +348,14 @@ { "description": "number is valid", "data": 1, - "valid": true + "valid": true, + "schema_id": "allOf_9_0" }, { "description": "string is invalid", "data": "foo", - "valid": false + "valid": false, + "schema_id": "allOf_9_0" } ] }, @@ -344,7 +364,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "allOf": [ { "allOf": [ @@ -353,7 +372,8 @@ } ] } - ] + ], + "$id": "allOf_10_0" } ] }, @@ -361,12 +381,14 @@ { "description": "null is valid", "data": null, - "valid": true + "valid": true, + "schema_id": "allOf_10_0" }, { "description": "anything non-null is invalid", "data": 123, - "valid": false + "valid": false, + "schema_id": "allOf_10_0" } ] }, @@ -375,7 +397,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "allOf": [ { "multipleOf": 2 @@ -390,7 +411,8 @@ { "multipleOf": 5 } - ] + ], + "$id": "allOf_11_0" } ] }, @@ -398,42 +420,50 @@ { "description": "allOf: false, anyOf: false, oneOf: false", "data": 1, - "valid": false + "valid": false, + "schema_id": "allOf_11_0" }, { "description": "allOf: false, anyOf: false, oneOf: true", "data": 5, - "valid": false + "valid": false, + "schema_id": "allOf_11_0" }, { "description": "allOf: false, anyOf: true, oneOf: false", "data": 3, - "valid": false + "valid": false, + "schema_id": "allOf_11_0" }, { "description": "allOf: false, anyOf: true, oneOf: true", "data": 15, - "valid": false + "valid": false, + "schema_id": "allOf_11_0" }, { "description": "allOf: true, anyOf: false, oneOf: false", "data": 2, - "valid": false + "valid": false, + "schema_id": "allOf_11_0" }, { "description": "allOf: true, anyOf: false, oneOf: true", "data": 10, - "valid": false + "valid": false, + "schema_id": "allOf_11_0" }, { "description": "allOf: true, anyOf: true, oneOf: false", "data": 6, - "valid": false + "valid": false, + "schema_id": "allOf_11_0" }, { "description": "allOf: true, anyOf: true, oneOf: true", "data": 30, - "valid": true + "valid": true, + "schema_id": "allOf_11_0" } ] }, @@ -442,7 +472,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "allOf": [ { "properties": { @@ -465,7 +494,8 @@ ] } ], - "extensible": true + "extensible": true, + "$id": "allOf_12_0" } ] }, @@ -477,7 +507,8 @@ "bar": 2, "qux": 3 }, - "valid": true + "valid": true, + "schema_id": "allOf_12_0" } ] }, @@ -486,7 +517,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "allOf": [ { "properties": { @@ -502,7 +532,8 @@ } } } - ] + ], + "$id": "allOf_13_0" } ] }, @@ -513,7 +544,8 @@ "foo": 1, "bar": 2 }, - "valid": true + "valid": true, + "schema_id": "allOf_13_0" }, { "description": "fails on extra property z explicitly", @@ -522,7 +554,8 @@ "bar": 2, "z": 3 }, - "valid": false + "valid": false, + "schema_id": "allOf_13_0" } ] }, @@ -531,7 +564,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "allOf": [ { "properties": { @@ -548,7 +580,8 @@ } } } - ] + ], + "$id": "allOf_14_0" } ] }, @@ -560,7 +593,8 @@ "bar": 2, "z": 3 }, - "valid": true + "valid": true, + "schema_id": "allOf_14_0" } ] }, @@ -571,26 +605,27 @@ { "allOf": [ { - "$ref": "#/$defs/partA" + "$ref": "partA" }, { - "$ref": "#/$defs/partB" + "$ref": "partB" } ], - "$defs": { - "partA": { - "properties": { - "id": { - "type": "string" - } - } - }, - "partB": { - "properties": { - "name": { - "type": "string" - } - } + "$id": "allOf_15_0" + }, + { + "$id": "partA", + "properties": { + "id": { + "type": "string" + } + } + }, + { + "$id": "partB", + "properties": { + "name": { + "type": "string" } } } @@ -603,7 +638,8 @@ "id": "1", "name": "Me" }, - "valid": true + "valid": true, + "schema_id": "allOf_15_0" }, { "description": "extra property is invalid (root is strict)", @@ -612,7 +648,8 @@ "name": "Me", "extra": 1 }, - "valid": false + "valid": false, + "schema_id": "allOf_15_0" }, { "description": "partA mismatch is invalid", @@ -620,7 +657,8 @@ "id": 1, "name": "Me" }, - "valid": false + "valid": false, + "schema_id": "allOf_15_0" } ] } diff --git a/tests/fixtures/anyOf.json b/tests/fixtures/anyOf.json index d3a17d2..5a8c618 100644 --- a/tests/fixtures/anyOf.json +++ b/tests/fixtures/anyOf.json @@ -4,7 +4,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "anyOf": [ { "type": "integer" @@ -12,7 +11,8 @@ { "minimum": 2 } - ] + ], + "$id": "anyOf_0_0" } ] }, @@ -20,22 +20,26 @@ { "description": "first anyOf valid", "data": 1, - "valid": true + "valid": true, + "schema_id": "anyOf_0_0" }, { "description": "second anyOf valid", "data": 2.5, - "valid": true + "valid": true, + "schema_id": "anyOf_0_0" }, { "description": "both anyOf valid", "data": 3, - "valid": true + "valid": true, + "schema_id": "anyOf_0_0" }, { "description": "neither anyOf valid", "data": 1.5, - "valid": false + "valid": false, + "schema_id": "anyOf_0_0" } ] }, @@ -44,7 +48,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "string", "anyOf": [ { @@ -53,7 +56,8 @@ { "minLength": 4 } - ] + ], + "$id": "anyOf_1_0" } ] }, @@ -61,17 +65,20 @@ { "description": "mismatch base schema", "data": 3, - "valid": false + "valid": false, + "schema_id": "anyOf_1_0" }, { "description": "one anyOf valid", "data": "foobar", - "valid": true + "valid": true, + "schema_id": "anyOf_1_0" }, { "description": "both anyOf invalid", "data": "foo", - "valid": false + "valid": false, + "schema_id": "anyOf_1_0" } ] }, @@ -80,11 +87,11 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "anyOf": [ true, true - ] + ], + "$id": "anyOf_2_0" } ] }, @@ -92,7 +99,8 @@ { "description": "any value is valid", "data": "foo", - "valid": true + "valid": true, + "schema_id": "anyOf_2_0" } ] }, @@ -101,11 +109,11 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "anyOf": [ true, false - ] + ], + "$id": "anyOf_3_0" } ] }, @@ -113,7 +121,8 @@ { "description": "any value is valid", "data": "foo", - "valid": true + "valid": true, + "schema_id": "anyOf_3_0" } ] }, @@ -122,11 +131,11 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "anyOf": [ false, false - ] + ], + "$id": "anyOf_4_0" } ] }, @@ -134,7 +143,8 @@ { "description": "any value is invalid", "data": "foo", - "valid": false + "valid": false, + "schema_id": "anyOf_4_0" } ] }, @@ -143,7 +153,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "anyOf": [ { "properties": { @@ -165,7 +174,8 @@ "foo" ] } - ] + ], + "$id": "anyOf_5_0" } ] }, @@ -175,14 +185,16 @@ "data": { "bar": 2 }, - "valid": true + "valid": true, + "schema_id": "anyOf_5_0" }, { "description": "second anyOf valid (complex)", "data": { "foo": "baz" }, - "valid": true + "valid": true, + "schema_id": "anyOf_5_0" }, { "description": "both anyOf valid (complex)", @@ -190,7 +202,8 @@ "foo": "baz", "bar": 2 }, - "valid": true + "valid": true, + "schema_id": "anyOf_5_0" }, { "description": "neither anyOf valid (complex)", @@ -198,7 +211,8 @@ "foo": 2, "bar": "quux" }, - "valid": false + "valid": false, + "schema_id": "anyOf_5_0" } ] }, @@ -207,13 +221,13 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "anyOf": [ { "type": "number" }, {} - ] + ], + "$id": "anyOf_6_0" } ] }, @@ -221,12 +235,14 @@ { "description": "string is valid", "data": "foo", - "valid": true + "valid": true, + "schema_id": "anyOf_6_0" }, { "description": "number is valid", "data": 123, - "valid": true + "valid": true, + "schema_id": "anyOf_6_0" } ] }, @@ -235,7 +251,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "anyOf": [ { "anyOf": [ @@ -244,7 +259,8 @@ } ] } - ] + ], + "$id": "anyOf_7_0" } ] }, @@ -252,12 +268,14 @@ { "description": "null is valid", "data": null, - "valid": true + "valid": true, + "schema_id": "anyOf_7_0" }, { "description": "anything non-null is invalid", "data": 123, - "valid": false + "valid": false, + "schema_id": "anyOf_7_0" } ] }, @@ -266,7 +284,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "anyOf": [ { "type": "integer" @@ -275,7 +292,8 @@ "minimum": 2 } ], - "extensible": true + "extensible": true, + "$id": "anyOf_8_0" } ] }, @@ -285,7 +303,8 @@ "data": { "foo": 1 }, - "valid": true + "valid": true, + "schema_id": "anyOf_8_0" } ] }, @@ -294,7 +313,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "anyOf": [ { "properties": { @@ -310,7 +328,8 @@ } } } - ] + ], + "$id": "anyOf_9_0" } ] }, @@ -320,7 +339,8 @@ "data": { "foo": 1 }, - "valid": true + "valid": true, + "schema_id": "anyOf_9_0" }, { "description": "fails on extra property z explicitly", @@ -328,7 +348,8 @@ "foo": 1, "z": 3 }, - "valid": false + "valid": false, + "schema_id": "anyOf_9_0" } ] } diff --git a/tests/fixtures/booleanSchema.json b/tests/fixtures/booleanSchema.json index 794d8f8..e526c81 100644 --- a/tests/fixtures/booleanSchema.json +++ b/tests/fixtures/booleanSchema.json @@ -3,58 +3,69 @@ "description": "boolean schema 'true'", "database": { "schemas": [ - true + { + "$id": "booleanSchema_0_0" + } ] }, "tests": [ { "description": "number is valid", "data": 1, - "valid": true + "valid": true, + "schema_id": "booleanSchema_0_0" }, { "description": "string is valid", "data": "foo", - "valid": true + "valid": true, + "schema_id": "booleanSchema_0_0" }, { "description": "boolean true is valid", "data": true, - "valid": true + "valid": true, + "schema_id": "booleanSchema_0_0" }, { "description": "boolean false is valid", "data": false, - "valid": true + "valid": true, + "schema_id": "booleanSchema_0_0" }, { "description": "null is valid", "data": null, - "valid": true + "valid": true, + "schema_id": "booleanSchema_0_0" }, { "description": "object is valid", "data": { "foo": "bar" }, - "valid": true + "valid": true, + "schema_id": "booleanSchema_0_0" }, { "description": "empty object is valid", "data": {}, - "valid": true + "valid": true, + "schema_id": "booleanSchema_0_0" }, { "description": "array is valid", "data": [ "foo" ], - "valid": true + "valid": true, + "schema_id": "booleanSchema_0_0" }, { "description": "empty array is valid", "data": [], - "valid": true + "valid": true, + "schema_id": "booleanSchema_0_0" } ] }, @@ -62,58 +73,70 @@ "description": "boolean schema 'false'", "database": { "schemas": [ - false + { + "not": {}, + "$id": "booleanSchema_1_0" + } ] }, "tests": [ { "description": "number is invalid", "data": 1, - "valid": false + "valid": false, + "schema_id": "booleanSchema_1_0" }, { "description": "string is invalid", "data": "foo", - "valid": false + "valid": false, + "schema_id": "booleanSchema_1_0" }, { "description": "boolean true is invalid", "data": true, - "valid": false + "valid": false, + "schema_id": "booleanSchema_1_0" }, { "description": "boolean false is invalid", "data": false, - "valid": false + "valid": false, + "schema_id": "booleanSchema_1_0" }, { "description": "null is invalid", "data": null, - "valid": false + "valid": false, + "schema_id": "booleanSchema_1_0" }, { "description": "object is invalid", "data": { "foo": "bar" }, - "valid": false + "valid": false, + "schema_id": "booleanSchema_1_0" }, { "description": "empty object is invalid", "data": {}, - "valid": false + "valid": false, + "schema_id": "booleanSchema_1_0" }, { "description": "array is invalid", "data": [ "foo" ], - "valid": false + "valid": false, + "schema_id": "booleanSchema_1_0" }, { "description": "empty array is invalid", "data": [], - "valid": false + "valid": false, + "schema_id": "booleanSchema_1_0" } ] } diff --git a/tests/fixtures/const.json b/tests/fixtures/const.json index b31f5f6..1ad183e 100644 --- a/tests/fixtures/const.json +++ b/tests/fixtures/const.json @@ -4,8 +4,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "const": 2 + "const": 2, + "$id": "const_0_0" } ] }, @@ -13,17 +13,20 @@ { "description": "same value is valid", "data": 2, - "valid": true + "valid": true, + "schema_id": "const_0_0" }, { "description": "another value is invalid", "data": 5, - "valid": false + "valid": false, + "schema_id": "const_0_0" }, { "description": "another type is invalid", "data": "a", - "valid": false + "valid": false, + "schema_id": "const_0_0" } ] }, @@ -32,7 +35,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "const": { "foo": "bar", "baz": "bax" @@ -40,7 +42,8 @@ "properties": { "foo": {}, "baz": {} - } + }, + "$id": "const_1_0" } ] }, @@ -51,7 +54,8 @@ "foo": "bar", "baz": "bax" }, - "valid": true + "valid": true, + "schema_id": "const_1_0" }, { "description": "same object with different property order is valid", @@ -59,14 +63,16 @@ "baz": "bax", "foo": "bar" }, - "valid": true + "valid": true, + "schema_id": "const_1_0" }, { "description": "another object is invalid", "data": { "foo": "bar" }, - "valid": false + "valid": false, + "schema_id": "const_1_0" }, { "description": "another type is invalid", @@ -74,7 +80,8 @@ 1, 2 ], - "valid": false + "valid": false, + "schema_id": "const_1_0" } ] }, @@ -83,12 +90,12 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "const": [ { "foo": "bar" } - ] + ], + "$id": "const_2_0" } ] }, @@ -100,14 +107,16 @@ "foo": "bar" } ], - "valid": true + "valid": true, + "schema_id": "const_2_0" }, { "description": "another array item is invalid", "data": [ 2 ], - "valid": false + "valid": false, + "schema_id": "const_2_0" }, { "description": "array with additional items is invalid", @@ -116,7 +125,8 @@ 2, 3 ], - "valid": false + "valid": false, + "schema_id": "const_2_0" } ] }, @@ -125,8 +135,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "const": null + "const": null, + "$id": "const_3_0" } ] }, @@ -134,12 +144,14 @@ { "description": "null is valid", "data": null, - "valid": true + "valid": true, + "schema_id": "const_3_0" }, { "description": "not null is invalid", "data": 0, - "valid": false + "valid": false, + "schema_id": "const_3_0" } ] }, @@ -148,8 +160,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "const": false + "const": false, + "$id": "const_4_0" } ] }, @@ -157,17 +169,20 @@ { "description": "false is valid", "data": false, - "valid": true + "valid": true, + "schema_id": "const_4_0" }, { "description": "integer zero is invalid", "data": 0, - "valid": false + "valid": false, + "schema_id": "const_4_0" }, { "description": "float zero is invalid", - "data": 0.0, - "valid": false + "data": 0, + "valid": false, + "schema_id": "const_4_0" } ] }, @@ -176,8 +191,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "const": true + "const": true, + "$id": "const_5_0" } ] }, @@ -185,17 +200,20 @@ { "description": "true is valid", "data": true, - "valid": true + "valid": true, + "schema_id": "const_5_0" }, { "description": "integer one is invalid", "data": 1, - "valid": false + "valid": false, + "schema_id": "const_5_0" }, { "description": "float one is invalid", - "data": 1.0, - "valid": false + "data": 1, + "valid": false, + "schema_id": "const_5_0" } ] }, @@ -204,10 +222,10 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "const": [ false - ] + ], + "$id": "const_6_0" } ] }, @@ -217,21 +235,24 @@ "data": [ false ], - "valid": true + "valid": true, + "schema_id": "const_6_0" }, { "description": "[0] is invalid", "data": [ 0 ], - "valid": false + "valid": false, + "schema_id": "const_6_0" }, { "description": "[0.0] is invalid", "data": [ - 0.0 + 0 ], - "valid": false + "valid": false, + "schema_id": "const_6_0" } ] }, @@ -240,10 +261,10 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "const": [ true - ] + ], + "$id": "const_7_0" } ] }, @@ -253,21 +274,24 @@ "data": [ true ], - "valid": true + "valid": true, + "schema_id": "const_7_0" }, { "description": "[1] is invalid", "data": [ 1 ], - "valid": false + "valid": false, + "schema_id": "const_7_0" }, { "description": "[1.0] is invalid", "data": [ - 1.0 + 1 ], - "valid": false + "valid": false, + "schema_id": "const_7_0" } ] }, @@ -276,10 +300,10 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "const": { "a": false - } + }, + "$id": "const_8_0" } ] }, @@ -289,21 +313,24 @@ "data": { "a": false }, - "valid": true + "valid": true, + "schema_id": "const_8_0" }, { "description": "{\"a\": 0} is invalid", "data": { "a": 0 }, - "valid": false + "valid": false, + "schema_id": "const_8_0" }, { "description": "{\"a\": 0.0} is invalid", "data": { - "a": 0.0 + "a": 0 }, - "valid": false + "valid": false, + "schema_id": "const_8_0" } ] }, @@ -312,10 +339,10 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "const": { "a": true - } + }, + "$id": "const_9_0" } ] }, @@ -325,21 +352,24 @@ "data": { "a": true }, - "valid": true + "valid": true, + "schema_id": "const_9_0" }, { "description": "{\"a\": 1} is invalid", "data": { "a": 1 }, - "valid": false + "valid": false, + "schema_id": "const_9_0" }, { "description": "{\"a\": 1.0} is invalid", "data": { - "a": 1.0 + "a": 1 }, - "valid": false + "valid": false, + "schema_id": "const_9_0" } ] }, @@ -348,8 +378,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "const": 0 + "const": 0, + "$id": "const_10_0" } ] }, @@ -357,32 +387,38 @@ { "description": "false is invalid", "data": false, - "valid": false + "valid": false, + "schema_id": "const_10_0" }, { "description": "integer zero is valid", "data": 0, - "valid": true + "valid": true, + "schema_id": "const_10_0" }, { "description": "float zero is valid", - "data": 0.0, - "valid": true + "data": 0, + "valid": true, + "schema_id": "const_10_0" }, { "description": "empty object is invalid", "data": {}, - "valid": false + "valid": false, + "schema_id": "const_10_0" }, { "description": "empty array is invalid", "data": [], - "valid": false + "valid": false, + "schema_id": "const_10_0" }, { "description": "empty string is invalid", "data": "", - "valid": false + "valid": false, + "schema_id": "const_10_0" } ] }, @@ -391,8 +427,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "const": 1 + "const": 1, + "$id": "const_11_0" } ] }, @@ -400,17 +436,20 @@ { "description": "true is invalid", "data": true, - "valid": false + "valid": false, + "schema_id": "const_11_0" }, { "description": "integer one is valid", "data": 1, - "valid": true + "valid": true, + "schema_id": "const_11_0" }, { "description": "float one is valid", - "data": 1.0, - "valid": true + "data": 1, + "valid": true, + "schema_id": "const_11_0" } ] }, @@ -419,8 +458,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "const": -2.0 + "const": -2, + "$id": "const_12_0" } ] }, @@ -428,27 +467,32 @@ { "description": "integer -2 is valid", "data": -2, - "valid": true + "valid": true, + "schema_id": "const_12_0" }, { "description": "integer 2 is invalid", "data": 2, - "valid": false + "valid": false, + "schema_id": "const_12_0" }, { "description": "float -2.0 is valid", - "data": -2.0, - "valid": true + "data": -2, + "valid": true, + "schema_id": "const_12_0" }, { "description": "float 2.0 is invalid", - "data": 2.0, - "valid": false + "data": 2, + "valid": false, + "schema_id": "const_12_0" }, { "description": "float -2.00001 is invalid", "data": -2.00001, - "valid": false + "valid": false, + "schema_id": "const_12_0" } ] }, @@ -457,8 +501,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "const": 9007199254740992 + "const": 9007199254740992, + "$id": "const_13_0" } ] }, @@ -466,22 +510,26 @@ { "description": "integer is valid", "data": 9007199254740992, - "valid": true + "valid": true, + "schema_id": "const_13_0" }, { "description": "integer minus one is invalid", "data": 9007199254740991, - "valid": false + "valid": false, + "schema_id": "const_13_0" }, { "description": "float is valid", - "data": 9007199254740992.0, - "valid": true + "data": 9007199254740992, + "valid": true, + "schema_id": "const_13_0" }, { "description": "float minus one is invalid", - "data": 9007199254740991.0, - "valid": false + "data": 9007199254740991, + "valid": false, + "schema_id": "const_13_0" } ] }, @@ -490,8 +538,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "const": "hello\u0000there" + "const": "hello\u0000there", + "$id": "const_14_0" } ] }, @@ -499,12 +547,14 @@ { "description": "match string with nul", "data": "hello\u0000there", - "valid": true + "valid": true, + "schema_id": "const_14_0" }, { "description": "do not match string lacking nul", "data": "hellothere", - "valid": false + "valid": false, + "schema_id": "const_14_0" } ] }, @@ -513,9 +563,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "const": "μ", - "$comment": "U+03BC" + "$comment": "U+03BC", + "$id": "const_15_0" } ] }, @@ -524,13 +574,15 @@ "description": "character uses the same codepoint", "data": "μ", "comment": "U+03BC", - "valid": true + "valid": true, + "schema_id": "const_15_0" }, { "description": "character looks the same but uses a different codepoint", "data": "µ", "comment": "U+00B5", - "valid": false + "valid": false, + "schema_id": "const_15_0" } ] }, @@ -539,9 +591,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "const": "ä", - "$comment": "U+00E4" + "$comment": "U+00E4", + "$id": "const_16_0" } ] }, @@ -550,13 +602,15 @@ "description": "character uses the same codepoint", "data": "ä", "comment": "U+00E4", - "valid": true + "valid": true, + "schema_id": "const_16_0" }, { "description": "character looks the same but uses combining marks", "data": "ä", "comment": "a, U+0308", - "valid": false + "valid": false, + "schema_id": "const_16_0" } ] }, @@ -565,11 +619,11 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "const": { "a": 1 }, - "extensible": true + "extensible": true, + "$id": "const_17_0" } ] }, @@ -580,14 +634,16 @@ "a": 1, "b": 2 }, - "valid": false + "valid": false, + "schema_id": "const_17_0" }, { "description": "extra property match in const (this is effectively impossible if data has extra props not in const, it implicitly fails const check unless we assume const check ignored extra props? No, const check is strict. So this test is just to show strictness passes.)", "data": { "a": 1 }, - "valid": true + "valid": true, + "schema_id": "const_17_0" } ] } diff --git a/tests/fixtures/contains.json b/tests/fixtures/contains.json index 3358e19..5318063 100644 --- a/tests/fixtures/contains.json +++ b/tests/fixtures/contains.json @@ -4,11 +4,11 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "contains": { "minimum": 5 }, - "items": true + "items": true, + "$id": "contains_0_0" } ] }, @@ -20,7 +20,8 @@ 4, 5 ], - "valid": true + "valid": true, + "schema_id": "contains_0_0" }, { "description": "array with item matching schema (6) is valid (items: true)", @@ -29,7 +30,8 @@ 4, 6 ], - "valid": true + "valid": true, + "schema_id": "contains_0_0" }, { "description": "array with two items matching schema (5, 6) is valid (items: true)", @@ -39,7 +41,8 @@ 5, 6 ], - "valid": true + "valid": true, + "schema_id": "contains_0_0" }, { "description": "array without items matching schema is invalid", @@ -48,17 +51,20 @@ 3, 4 ], - "valid": false + "valid": false, + "schema_id": "contains_0_0" }, { "description": "empty array is invalid", "data": [], - "valid": false + "valid": false, + "schema_id": "contains_0_0" }, { "description": "not array is valid", "data": {}, - "valid": true + "valid": true, + "schema_id": "contains_0_0" } ] }, @@ -67,11 +73,11 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "contains": { "const": 5 }, - "items": true + "items": true, + "$id": "contains_1_0" } ] }, @@ -83,7 +89,8 @@ 4, 5 ], - "valid": true + "valid": true, + "schema_id": "contains_1_0" }, { "description": "array with two items 5 is valid (items: true)", @@ -93,7 +100,8 @@ 5, 5 ], - "valid": true + "valid": true, + "schema_id": "contains_1_0" }, { "description": "array without item 5 is invalid", @@ -103,7 +111,8 @@ 3, 4 ], - "valid": false + "valid": false, + "schema_id": "contains_1_0" } ] }, @@ -112,8 +121,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "contains": true + "contains": true, + "$id": "contains_2_0" } ] }, @@ -123,12 +132,14 @@ "data": [ "foo" ], - "valid": true + "valid": true, + "schema_id": "contains_2_0" }, { "description": "empty array is invalid", "data": [], - "valid": false + "valid": false, + "schema_id": "contains_2_0" } ] }, @@ -137,8 +148,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "contains": false + "contains": false, + "$id": "contains_3_0" } ] }, @@ -148,17 +159,20 @@ "data": [ "foo" ], - "valid": false + "valid": false, + "schema_id": "contains_3_0" }, { "description": "empty array is invalid", "data": [], - "valid": false + "valid": false, + "schema_id": "contains_3_0" }, { "description": "non-arrays are valid", "data": "contains does not apply to strings", - "valid": true + "valid": true, + "schema_id": "contains_3_0" } ] }, @@ -167,13 +181,13 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "items": { "multipleOf": 2 }, "contains": { "multipleOf": 3 - } + }, + "$id": "contains_4_0" } ] }, @@ -185,7 +199,8 @@ 4, 8 ], - "valid": false + "valid": false, + "schema_id": "contains_4_0" }, { "description": "does not match items, matches contains", @@ -194,7 +209,8 @@ 6, 9 ], - "valid": false + "valid": false, + "schema_id": "contains_4_0" }, { "description": "matches both items and contains", @@ -202,7 +218,8 @@ 6, 12 ], - "valid": true + "valid": true, + "schema_id": "contains_4_0" }, { "description": "matches neither items nor contains", @@ -210,7 +227,8 @@ 1, 5 ], - "valid": false + "valid": false, + "schema_id": "contains_4_0" } ] }, @@ -219,11 +237,11 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "contains": { "if": false, "else": true - } + }, + "$id": "contains_5_0" } ] }, @@ -233,12 +251,14 @@ "data": [ "foo" ], - "valid": true + "valid": true, + "schema_id": "contains_5_0" }, { "description": "empty array is invalid", "data": [], - "valid": false + "valid": false, + "schema_id": "contains_5_0" } ] }, @@ -247,10 +267,10 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "contains": { "type": "null" - } + }, + "$id": "contains_6_0" } ] }, @@ -260,7 +280,8 @@ "data": [ null ], - "valid": true + "valid": true, + "schema_id": "contains_6_0" } ] }, @@ -269,11 +290,11 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "contains": { "const": 1 }, - "extensible": true + "extensible": true, + "$id": "contains_7_0" } ] }, @@ -284,7 +305,8 @@ 1, 2 ], - "valid": true + "valid": true, + "schema_id": "contains_7_0" } ] }, @@ -293,10 +315,10 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "contains": { "const": 1 - } + }, + "$id": "contains_8_0" } ] }, @@ -307,7 +329,8 @@ 1, 2 ], - "valid": false + "valid": false, + "schema_id": "contains_8_0" }, { "description": "only matching items is valid", @@ -315,7 +338,8 @@ 1, 1 ], - "valid": true + "valid": true, + "schema_id": "contains_8_0" } ] } diff --git a/tests/fixtures/content.json b/tests/fixtures/content.json index e69aa95..6ab669d 100644 --- a/tests/fixtures/content.json +++ b/tests/fixtures/content.json @@ -4,8 +4,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "contentMediaType": "application/json" + "contentMediaType": "application/json", + "$id": "content_0_0" } ] }, @@ -13,17 +13,20 @@ { "description": "a valid JSON document", "data": "{\"foo\": \"bar\"}", - "valid": true + "valid": true, + "schema_id": "content_0_0" }, { "description": "an invalid JSON document; validates true", "data": "{:}", - "valid": true + "valid": true, + "schema_id": "content_0_0" }, { "description": "ignores non-strings", "data": 100, - "valid": true + "valid": true, + "schema_id": "content_0_0" } ] }, @@ -32,8 +35,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "contentEncoding": "base64" + "contentEncoding": "base64", + "$id": "content_1_0" } ] }, @@ -41,17 +44,20 @@ { "description": "a valid base64 string", "data": "eyJmb28iOiAiYmFyIn0K", - "valid": true + "valid": true, + "schema_id": "content_1_0" }, { "description": "an invalid base64 string (% is not a valid character); validates true", "data": "eyJmb28iOi%iYmFyIn0K", - "valid": true + "valid": true, + "schema_id": "content_1_0" }, { "description": "ignores non-strings", "data": 100, - "valid": true + "valid": true, + "schema_id": "content_1_0" } ] }, @@ -60,9 +66,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "contentMediaType": "application/json", - "contentEncoding": "base64" + "contentEncoding": "base64", + "$id": "content_2_0" } ] }, @@ -70,22 +76,26 @@ { "description": "a valid base64-encoded JSON document", "data": "eyJmb28iOiAiYmFyIn0K", - "valid": true + "valid": true, + "schema_id": "content_2_0" }, { "description": "a validly-encoded invalid JSON document; validates true", "data": "ezp9Cg==", - "valid": true + "valid": true, + "schema_id": "content_2_0" }, { "description": "an invalid base64 string that is valid JSON; validates true", "data": "{}", - "valid": true + "valid": true, + "schema_id": "content_2_0" }, { "description": "ignores non-strings", "data": 100, - "valid": true + "valid": true, + "schema_id": "content_2_0" } ] }, @@ -94,7 +104,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "contentMediaType": "application/json", "contentEncoding": "base64", "contentSchema": { @@ -110,7 +119,8 @@ "type": "integer" } } - } + }, + "$id": "content_3_0" } ] }, @@ -118,42 +128,50 @@ { "description": "a valid base64-encoded JSON document", "data": "eyJmb28iOiAiYmFyIn0K", - "valid": true + "valid": true, + "schema_id": "content_3_0" }, { "description": "another valid base64-encoded JSON document", "data": "eyJib28iOiAyMCwgImZvbyI6ICJiYXoifQ==", - "valid": true + "valid": true, + "schema_id": "content_3_0" }, { "description": "an invalid base64-encoded JSON document; validates true", "data": "eyJib28iOiAyMH0=", - "valid": true + "valid": true, + "schema_id": "content_3_0" }, { "description": "an empty object as a base64-encoded JSON document; validates true", "data": "e30=", - "valid": true + "valid": true, + "schema_id": "content_3_0" }, { "description": "an empty array as a base64-encoded JSON document", "data": "W10=", - "valid": true + "valid": true, + "schema_id": "content_3_0" }, { "description": "a validly-encoded invalid JSON document; validates true", "data": "ezp9Cg==", - "valid": true + "valid": true, + "schema_id": "content_3_0" }, { "description": "an invalid base64 string that is valid JSON; validates true", "data": "{}", - "valid": true + "valid": true, + "schema_id": "content_3_0" }, { "description": "ignores non-strings", "data": 100, - "valid": true + "valid": true, + "schema_id": "content_3_0" } ] } diff --git a/tests/fixtures/dependencies.json b/tests/fixtures/dependencies.json index ec19d65..6b497b3 100644 --- a/tests/fixtures/dependencies.json +++ b/tests/fixtures/dependencies.json @@ -19,14 +19,16 @@ { "description": "neither", "data": {}, - "valid": true + "valid": true, + "schema_id": "schema1" }, { "description": "nondependant", "data": { "foo": 1 }, - "valid": true + "valid": true, + "schema_id": "schema1" }, { "description": "with dependency", @@ -34,31 +36,36 @@ "foo": 1, "bar": 2 }, - "valid": true + "valid": true, + "schema_id": "schema1" }, { "description": "missing dependency", "data": { "bar": 2 }, - "valid": false + "valid": false, + "schema_id": "schema1" }, { "description": "ignores arrays", "data": [ "bar" ], - "valid": true + "valid": true, + "schema_id": "schema1" }, { "description": "ignores strings", "data": "foobar", - "valid": true + "valid": true, + "schema_id": "schema1" }, { "description": "ignores other non-objects", "data": 12, - "valid": true + "valid": true, + "schema_id": "schema1" } ] }, @@ -80,19 +87,22 @@ { "description": "empty object", "data": {}, - "valid": true + "valid": true, + "schema_id": "schema2" }, { "description": "object with one property", "data": { "bar": 2 }, - "valid": true + "valid": true, + "schema_id": "schema2" }, { "description": "non-object is valid", "data": 1, - "valid": true + "valid": true, + "schema_id": "schema2" } ] }, @@ -117,7 +127,8 @@ { "description": "neither", "data": {}, - "valid": true + "valid": true, + "schema_id": "schema3" }, { "description": "nondependants", @@ -125,7 +136,8 @@ "foo": 1, "bar": 2 }, - "valid": true + "valid": true, + "schema_id": "schema3" }, { "description": "with dependencies", @@ -134,7 +146,8 @@ "bar": 2, "quux": 3 }, - "valid": true + "valid": true, + "schema_id": "schema3" }, { "description": "missing dependency", @@ -142,7 +155,8 @@ "foo": 1, "quux": 2 }, - "valid": false + "valid": false, + "schema_id": "schema3" }, { "description": "missing other dependency", @@ -150,14 +164,16 @@ "bar": 1, "quux": 2 }, - "valid": false + "valid": false, + "schema_id": "schema3" }, { "description": "missing both dependencies", "data": { "quux": 1 }, - "valid": false + "valid": false, + "schema_id": "schema3" } ] }, @@ -187,7 +203,8 @@ "foo\nbar": 1, "foo\rbar": 2 }, - "valid": true + "valid": true, + "schema_id": "schema4" }, { "description": "quoted quotes", @@ -195,7 +212,8 @@ "foo'bar": 1, "foo\"bar": 2 }, - "valid": true + "valid": true, + "schema_id": "schema4" }, { "description": "CRLF missing dependent", @@ -203,14 +221,16 @@ "foo\nbar": 1, "foo": 2 }, - "valid": false + "valid": false, + "schema_id": "schema4" }, { "description": "quoted quotes missing dependent", "data": { "foo\"bar": 2 }, - "valid": false + "valid": false, + "schema_id": "schema4" } ] }, @@ -238,7 +258,8 @@ "bar": 2, "baz": 3 }, - "valid": true + "valid": true, + "schema_id": "schema5" } ] }, @@ -275,14 +296,16 @@ "foo": 1, "bar": 2 }, - "valid": true + "valid": true, + "schema_id": "schema_schema1" }, { "description": "no dependency", "data": { "foo": "quux" }, - "valid": true + "valid": true, + "schema_id": "schema_schema1" }, { "description": "wrong type", @@ -290,7 +313,8 @@ "foo": "quux", "bar": 2 }, - "valid": false + "valid": false, + "schema_id": "schema_schema1" }, { "description": "wrong type other", @@ -298,7 +322,8 @@ "foo": 2, "bar": "quux" }, - "valid": false + "valid": false, + "schema_id": "schema_schema1" }, { "description": "wrong type both", @@ -306,7 +331,8 @@ "foo": "quux", "bar": "quux" }, - "valid": false + "valid": false, + "schema_id": "schema_schema1" }, { "description": "ignores arrays (invalid in strict mode)", @@ -318,17 +344,20 @@ { "code": "STRICT_ITEM_VIOLATION" } - ] + ], + "schema_id": "schema_schema1" }, { "description": "ignores strings", "data": "foobar", - "valid": true + "valid": true, + "schema_id": "schema_schema1" }, { "description": "ignores other non-objects", "data": 12, - "valid": true + "valid": true, + "schema_id": "schema_schema1" } ] }, @@ -365,7 +394,8 @@ "data": [ "bar" ], - "valid": true + "valid": true, + "schema_id": "schema_schema2" } ] }, @@ -393,14 +423,16 @@ "data": { "foo": 1 }, - "valid": true + "valid": true, + "schema_id": "schema_schema3" }, { "description": "object with property having schema false is invalid", "data": { "bar": 2 }, - "valid": false + "valid": false, + "schema_id": "schema_schema3" }, { "description": "object with both properties is invalid", @@ -408,12 +440,14 @@ "foo": 1, "bar": 2 }, - "valid": false + "valid": false, + "schema_id": "schema_schema3" }, { "description": "empty object is valid", "data": {}, - "valid": true + "valid": true, + "schema_id": "schema_schema3" } ] }, @@ -454,7 +488,8 @@ "b": 3, "c": 4 }, - "valid": true + "valid": true, + "schema_id": "schema_schema4" }, { "description": "quoted quote", @@ -463,7 +498,8 @@ "foo\"bar": 1 } }, - "valid": false + "valid": false, + "schema_id": "schema_schema4" }, { "description": "quoted tab invalid under dependent schema", @@ -471,14 +507,16 @@ "foo\tbar": 1, "a": 2 }, - "valid": false + "valid": false, + "schema_id": "schema_schema4" }, { "description": "quoted quote invalid under dependent schema", "data": { "foo'bar": 1 }, - "valid": false + "valid": false, + "schema_id": "schema_schema4" } ] }, @@ -509,7 +547,8 @@ "data": { "foo": 1 }, - "valid": false + "valid": false, + "schema_id": "schema_schema5" }, { "description": "matches dependency (invalid in strict mode - bar not allowed if foo missing)", @@ -521,7 +560,8 @@ { "code": "STRICT_PROPERTY_VIOLATION" } - ] + ], + "schema_id": "schema_schema5" }, { "description": "matches both", @@ -529,14 +569,16 @@ "foo": 1, "bar": 2 }, - "valid": false + "valid": false, + "schema_id": "schema_schema5" }, { "description": "no dependency", "data": { "baz": 1 }, - "valid": true + "valid": true, + "schema_id": "schema_schema5" } ] }, @@ -569,7 +611,8 @@ "data": { "bar": 1 }, - "valid": true + "valid": true, + "schema_id": "schema_schema6" } ] } diff --git a/tests/fixtures/emptyString.json b/tests/fixtures/emptyString.json index 45b1b4d..85d1584 100644 --- a/tests/fixtures/emptyString.json +++ b/tests/fixtures/emptyString.json @@ -4,7 +4,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "obj": { "type": "object" @@ -37,7 +36,8 @@ "con_empty": { "const": "" } - } + }, + "$id": "emptyString_0_0" } ] }, @@ -47,56 +47,64 @@ "data": { "obj": "" }, - "valid": true + "valid": true, + "schema_id": "emptyString_0_0" }, { "description": "empty string valid for array", "data": { "arr": "" }, - "valid": true + "valid": true, + "schema_id": "emptyString_0_0" }, { "description": "empty string valid for string", "data": { "str": "" }, - "valid": true + "valid": true, + "schema_id": "emptyString_0_0" }, { "description": "empty string valid for integer", "data": { "int": "" }, - "valid": true + "valid": true, + "schema_id": "emptyString_0_0" }, { "description": "empty string valid for number", "data": { "num": "" }, - "valid": true + "valid": true, + "schema_id": "emptyString_0_0" }, { "description": "empty string valid for boolean", "data": { "bool": "" }, - "valid": true + "valid": true, + "schema_id": "emptyString_0_0" }, { "description": "empty string valid for null", "data": { "nul": "" }, - "valid": true + "valid": true, + "schema_id": "emptyString_0_0" }, { "description": "empty string valid for format", "data": { "fmt": "" }, - "valid": true + "valid": true, + "schema_id": "emptyString_0_0" }, { "description": "empty string INVALID for const (unless const is empty string)", @@ -109,14 +117,16 @@ "code": "CONST_VIOLATED", "path": "/con" } - ] + ], + "schema_id": "emptyString_0_0" }, { "description": "empty string VALID for const if const IS empty string", "data": { "con_empty": "" }, - "valid": true + "valid": true, + "schema_id": "emptyString_0_0" } ] } diff --git a/tests/fixtures/enum.json b/tests/fixtures/enum.json index 4273d45..7b6b679 100644 --- a/tests/fixtures/enum.json +++ b/tests/fixtures/enum.json @@ -4,12 +4,12 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "enum": [ 1, 2, 3 - ] + ], + "$id": "enum_0_0" } ] }, @@ -17,12 +17,14 @@ { "description": "one of the enum is valid", "data": 1, - "valid": true + "valid": true, + "schema_id": "enum_0_0" }, { "description": "something else is invalid", "data": 4, - "valid": false + "valid": false, + "schema_id": "enum_0_0" } ] }, @@ -31,7 +33,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "enum": [ 6, "foo", @@ -43,7 +44,8 @@ ], "properties": { "foo": {} - } + }, + "$id": "enum_1_0" } ] }, @@ -51,26 +53,30 @@ { "description": "one of the enum is valid", "data": [], - "valid": true + "valid": true, + "schema_id": "enum_1_0" }, { "description": "something else is invalid", "data": null, - "valid": false + "valid": false, + "schema_id": "enum_1_0" }, { "description": "objects are deep compared", "data": { "foo": false }, - "valid": false + "valid": false, + "schema_id": "enum_1_0" }, { "description": "valid object matches", "data": { "foo": 12 }, - "valid": true + "valid": true, + "schema_id": "enum_1_0" }, { "description": "extra properties in object is invalid", @@ -78,7 +84,8 @@ "foo": 12, "boo": 42 }, - "valid": false + "valid": false, + "schema_id": "enum_1_0" } ] }, @@ -87,11 +94,11 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "enum": [ 6, null - ] + ], + "$id": "enum_2_0" } ] }, @@ -99,17 +106,20 @@ { "description": "null is valid", "data": null, - "valid": true + "valid": true, + "schema_id": "enum_2_0" }, { "description": "number is valid", "data": 6, - "valid": true + "valid": true, + "schema_id": "enum_2_0" }, { "description": "something else is invalid", "data": "test", - "valid": false + "valid": false, + "schema_id": "enum_2_0" } ] }, @@ -118,7 +128,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "foo": { @@ -134,7 +143,8 @@ }, "required": [ "bar" - ] + ], + "$id": "enum_3_0" } ] }, @@ -145,7 +155,8 @@ "foo": "foo", "bar": "bar" }, - "valid": true + "valid": true, + "schema_id": "enum_3_0" }, { "description": "wrong foo value", @@ -153,7 +164,8 @@ "foo": "foot", "bar": "bar" }, - "valid": false + "valid": false, + "schema_id": "enum_3_0" }, { "description": "wrong bar value", @@ -161,26 +173,30 @@ "foo": "foo", "bar": "bart" }, - "valid": false + "valid": false, + "schema_id": "enum_3_0" }, { "description": "missing optional property is valid", "data": { "bar": "bar" }, - "valid": true + "valid": true, + "schema_id": "enum_3_0" }, { "description": "missing required property is invalid", "data": { "foo": "foo" }, - "valid": false + "valid": false, + "schema_id": "enum_3_0" }, { "description": "missing all properties is invalid", "data": {}, - "valid": false + "valid": false, + "schema_id": "enum_3_0" } ] }, @@ -189,11 +205,11 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "enum": [ "foo\nbar", "foo\rbar" - ] + ], + "$id": "enum_4_0" } ] }, @@ -201,17 +217,20 @@ { "description": "member 1 is valid", "data": "foo\nbar", - "valid": true + "valid": true, + "schema_id": "enum_4_0" }, { "description": "member 2 is valid", "data": "foo\rbar", - "valid": true + "valid": true, + "schema_id": "enum_4_0" }, { "description": "another string is invalid", "data": "abc", - "valid": false + "valid": false, + "schema_id": "enum_4_0" } ] }, @@ -220,10 +239,10 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "enum": [ false - ] + ], + "$id": "enum_5_0" } ] }, @@ -231,17 +250,20 @@ { "description": "false is valid", "data": false, - "valid": true + "valid": true, + "schema_id": "enum_5_0" }, { "description": "integer zero is invalid", "data": 0, - "valid": false + "valid": false, + "schema_id": "enum_5_0" }, { "description": "float zero is invalid", - "data": 0.0, - "valid": false + "data": 0, + "valid": false, + "schema_id": "enum_5_0" } ] }, @@ -250,12 +272,12 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "enum": [ [ false ] - ] + ], + "$id": "enum_6_0" } ] }, @@ -265,21 +287,24 @@ "data": [ false ], - "valid": true + "valid": true, + "schema_id": "enum_6_0" }, { "description": "[0] is invalid", "data": [ 0 ], - "valid": false + "valid": false, + "schema_id": "enum_6_0" }, { "description": "[0.0] is invalid", "data": [ - 0.0 + 0 ], - "valid": false + "valid": false, + "schema_id": "enum_6_0" } ] }, @@ -288,10 +313,10 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "enum": [ true - ] + ], + "$id": "enum_7_0" } ] }, @@ -299,17 +324,20 @@ { "description": "true is valid", "data": true, - "valid": true + "valid": true, + "schema_id": "enum_7_0" }, { "description": "integer one is invalid", "data": 1, - "valid": false + "valid": false, + "schema_id": "enum_7_0" }, { "description": "float one is invalid", - "data": 1.0, - "valid": false + "data": 1, + "valid": false, + "schema_id": "enum_7_0" } ] }, @@ -318,12 +346,12 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "enum": [ [ true ] - ] + ], + "$id": "enum_8_0" } ] }, @@ -333,21 +361,24 @@ "data": [ true ], - "valid": true + "valid": true, + "schema_id": "enum_8_0" }, { "description": "[1] is invalid", "data": [ 1 ], - "valid": false + "valid": false, + "schema_id": "enum_8_0" }, { "description": "[1.0] is invalid", "data": [ - 1.0 + 1 ], - "valid": false + "valid": false, + "schema_id": "enum_8_0" } ] }, @@ -356,10 +387,10 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "enum": [ 0 - ] + ], + "$id": "enum_9_0" } ] }, @@ -367,17 +398,20 @@ { "description": "false is invalid", "data": false, - "valid": false + "valid": false, + "schema_id": "enum_9_0" }, { "description": "integer zero is valid", "data": 0, - "valid": true + "valid": true, + "schema_id": "enum_9_0" }, { "description": "float zero is valid", - "data": 0.0, - "valid": true + "data": 0, + "valid": true, + "schema_id": "enum_9_0" } ] }, @@ -386,12 +420,12 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "enum": [ [ 0 ] - ] + ], + "$id": "enum_10_0" } ] }, @@ -401,21 +435,24 @@ "data": [ false ], - "valid": false + "valid": false, + "schema_id": "enum_10_0" }, { "description": "[0] is valid", "data": [ 0 ], - "valid": true + "valid": true, + "schema_id": "enum_10_0" }, { "description": "[0.0] is valid", "data": [ - 0.0 + 0 ], - "valid": true + "valid": true, + "schema_id": "enum_10_0" } ] }, @@ -424,10 +461,10 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "enum": [ 1 - ] + ], + "$id": "enum_11_0" } ] }, @@ -435,17 +472,20 @@ { "description": "true is invalid", "data": true, - "valid": false + "valid": false, + "schema_id": "enum_11_0" }, { "description": "integer one is valid", "data": 1, - "valid": true + "valid": true, + "schema_id": "enum_11_0" }, { "description": "float one is valid", - "data": 1.0, - "valid": true + "data": 1, + "valid": true, + "schema_id": "enum_11_0" } ] }, @@ -454,12 +494,12 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "enum": [ [ 1 ] - ] + ], + "$id": "enum_12_0" } ] }, @@ -469,21 +509,24 @@ "data": [ true ], - "valid": false + "valid": false, + "schema_id": "enum_12_0" }, { "description": "[1] is valid", "data": [ 1 ], - "valid": true + "valid": true, + "schema_id": "enum_12_0" }, { "description": "[1.0] is valid", "data": [ - 1.0 + 1 ], - "valid": true + "valid": true, + "schema_id": "enum_12_0" } ] }, @@ -492,10 +535,10 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "enum": [ "hello\u0000there" - ] + ], + "$id": "enum_13_0" } ] }, @@ -503,12 +546,14 @@ { "description": "match string with nul", "data": "hello\u0000there", - "valid": true + "valid": true, + "schema_id": "enum_13_0" }, { "description": "do not match string lacking nul", "data": "hellothere", - "valid": false + "valid": false, + "schema_id": "enum_13_0" } ] }, @@ -517,13 +562,13 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "enum": [ { "foo": 1 } ], - "extensible": true + "extensible": true, + "$id": "enum_14_0" } ] }, @@ -534,14 +579,16 @@ "foo": 1, "bar": 2 }, - "valid": false + "valid": false, + "schema_id": "enum_14_0" }, { "description": "extra property ignored during strict check, enum match succeeds", "data": { "foo": 1 }, - "valid": true + "valid": true, + "schema_id": "enum_14_0" } ] } diff --git a/tests/fixtures/exclusiveMaximum.json b/tests/fixtures/exclusiveMaximum.json index 9ab08fc..bea5f68 100644 --- a/tests/fixtures/exclusiveMaximum.json +++ b/tests/fixtures/exclusiveMaximum.json @@ -4,8 +4,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "exclusiveMaximum": 3.0 + "exclusiveMaximum": 3, + "$id": "exclusiveMaximum_0_0" } ] }, @@ -13,22 +13,26 @@ { "description": "below the exclusiveMaximum is valid", "data": 2.2, - "valid": true + "valid": true, + "schema_id": "exclusiveMaximum_0_0" }, { "description": "boundary point is invalid", - "data": 3.0, - "valid": false + "data": 3, + "valid": false, + "schema_id": "exclusiveMaximum_0_0" }, { "description": "above the exclusiveMaximum is invalid", "data": 3.5, - "valid": false + "valid": false, + "schema_id": "exclusiveMaximum_0_0" }, { "description": "ignores non-numbers", "data": "x", - "valid": true + "valid": true, + "schema_id": "exclusiveMaximum_0_0" } ] } diff --git a/tests/fixtures/exclusiveMinimum.json b/tests/fixtures/exclusiveMinimum.json index 3db1f68..2ed42ab 100644 --- a/tests/fixtures/exclusiveMinimum.json +++ b/tests/fixtures/exclusiveMinimum.json @@ -4,8 +4,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "exclusiveMinimum": 1.1 + "exclusiveMinimum": 1.1, + "$id": "exclusiveMinimum_0_0" } ] }, @@ -13,22 +13,26 @@ { "description": "above the exclusiveMinimum is valid", "data": 1.2, - "valid": true + "valid": true, + "schema_id": "exclusiveMinimum_0_0" }, { "description": "boundary point is invalid", "data": 1.1, - "valid": false + "valid": false, + "schema_id": "exclusiveMinimum_0_0" }, { "description": "below the exclusiveMinimum is invalid", "data": 0.6, - "valid": false + "valid": false, + "schema_id": "exclusiveMinimum_0_0" }, { "description": "ignores non-numbers", "data": "x", - "valid": true + "valid": true, + "schema_id": "exclusiveMinimum_0_0" } ] } diff --git a/tests/fixtures/families.json b/tests/fixtures/families.json index 6bc294d..3593aa4 100644 --- a/tests/fixtures/families.json +++ b/tests/fixtures/families.json @@ -1,6 +1,6 @@ [ { - "description": "Entity families with dot patterns", + "description": "Entity families via pure $ref graph", "database": { "types": [ { @@ -17,8 +17,7 @@ "type": "string" }, "type": { - "type": "string", - "const": "entity" + "type": "string" } } }, @@ -65,7 +64,7 @@ }, { "$id": "person.light", - "$ref": "person" + "$ref": "entity.light" } ] } @@ -113,7 +112,7 @@ "valid": true }, { - "description": "Dot pattern family matches entity.light", + "description": "Graph family matches entity.light", "schema_id": "get_light_entities.response", "data": { "id": "3", @@ -122,25 +121,29 @@ "valid": true }, { - "description": "Dot pattern family matches person.light", + "description": "Graph family matches person.light (because it $refs entity.light)", "schema_id": "get_light_entities.response", "data": { "id": "4", - "type": "person", - "name": "ACME", - "first_name": "John" + "type": "person" }, "valid": true }, { - "description": "Dot pattern family excludes organization (missing .light schema, constraint violation)", + "description": "Graph family excludes organization (missing .light schema that $refs entity.light)", "schema_id": "get_light_entities.response", "data": { "id": "5", "type": "organization", "name": "ACME" }, - "valid": false + "valid": false, + "expect_errors": [ + { + "code": "FAMILY_MISMATCH", + "path": "" + } + ] } ] }, @@ -182,20 +185,14 @@ }, "tests": [ { - "description": "Ad-hoc family does not implicitly match descendants (no magical implicit hierarchy on normal ad-hoc schemas)", + "description": "Ad-hoc family matches strictly by shape (no magic variations for base schemas)", "schema_id": "get_widgets.response", "data": { "id": "1", "widget_type": "special", "special_feature": "yes" }, - "valid": false, - "expect_errors": [ - { - "code": "FAMILY_MISMATCH", - "path": "" - } - ] + "valid": true } ] } diff --git a/tests/fixtures/format.json b/tests/fixtures/format.json index d1eadb2..a5bf55c 100644 --- a/tests/fixtures/format.json +++ b/tests/fixtures/format.json @@ -4,8 +4,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "format": "date-time" + "format": "date-time", + "$id": "format_0_0" } ] }, @@ -13,132 +13,158 @@ { "description": "all string formats ignore integers", "data": 12, - "valid": true + "valid": true, + "schema_id": "format_0_0" }, { "description": "all string formats ignore floats", "data": 13.7, - "valid": true + "valid": true, + "schema_id": "format_0_0" }, { "description": "all string formats ignore objects", "data": {}, - "valid": true + "valid": true, + "schema_id": "format_0_0" }, { "description": "all string formats ignore arrays", "data": [], - "valid": true + "valid": true, + "schema_id": "format_0_0" }, { "description": "all string formats ignore booleans", "data": false, - "valid": true + "valid": true, + "schema_id": "format_0_0" }, { "description": "all string formats ignore nulls", "data": null, - "valid": true + "valid": true, + "schema_id": "format_0_0" }, { "description": "a valid date-time string", "data": "1963-06-19T08:30:06.283185Z", - "valid": true + "valid": true, + "schema_id": "format_0_0" }, { "description": "a valid date-time string without second fraction", "data": "1963-06-19T08:30:06Z", - "valid": true + "valid": true, + "schema_id": "format_0_0" }, { "description": "a valid date-time string with plus offset", "data": "1937-01-01T12:00:27.87+00:20", - "valid": true + "valid": true, + "schema_id": "format_0_0" }, { "description": "a valid date-time string with minus offset", "data": "1990-12-31T15:59:50.123-08:00", - "valid": true + "valid": true, + "schema_id": "format_0_0" }, { "description": "a valid date-time with a leap second, UTC", "data": "1998-12-31T23:59:60Z", - "valid": true + "valid": true, + "schema_id": "format_0_0" }, { "description": "a valid date-time with a leap second, with minus offset", "data": "1998-12-31T15:59:60.123-08:00", - "valid": true + "valid": true, + "schema_id": "format_0_0" }, { "description": "an invalid date-time past leap second, UTC", "data": "1998-12-31T23:59:61Z", - "valid": false + "valid": false, + "schema_id": "format_0_0" }, { "description": "an invalid date-time with leap second on a wrong minute, UTC", "data": "1998-12-31T23:58:60Z", - "valid": false + "valid": false, + "schema_id": "format_0_0" }, { "description": "an invalid date-time with leap second on a wrong hour, UTC", "data": "1998-12-31T22:59:60Z", - "valid": false + "valid": false, + "schema_id": "format_0_0" }, { "description": "an invalid day in date-time string", "data": "1990-02-31T15:59:59.123-08:00", - "valid": false + "valid": false, + "schema_id": "format_0_0" }, { "description": "an invalid offset in date-time string", "data": "1990-12-31T15:59:59-24:00", - "valid": false + "valid": false, + "schema_id": "format_0_0" }, { "description": "an invalid closing Z after time-zone offset", "data": "1963-06-19T08:30:06.28123+01:00Z", - "valid": false + "valid": false, + "schema_id": "format_0_0" }, { "description": "an invalid date-time string", "data": "06/19/1963 08:30:06 PST", - "valid": false + "valid": false, + "schema_id": "format_0_0" }, { "description": "case-insensitive T and Z", "data": "1963-06-19t08:30:06.283185z", - "valid": true + "valid": true, + "schema_id": "format_0_0" }, { "description": "only RFC3339 not all of ISO 8601 are valid", "data": "2013-350T01:01:01", - "valid": false + "valid": false, + "schema_id": "format_0_0" }, { "description": "invalid non-padded month dates", "data": "1963-6-19T08:30:06.283185Z", - "valid": false + "valid": false, + "schema_id": "format_0_0" }, { "description": "invalid non-padded day dates", "data": "1963-06-1T08:30:06.283185Z", - "valid": false + "valid": false, + "schema_id": "format_0_0" }, { "description": "invalid non-ASCII '৪' (a Bengali 4) in date portion", "data": "1963-06-1৪T00:00:00Z", - "valid": false + "valid": false, + "schema_id": "format_0_0" }, { "description": "invalid non-ASCII '৪' (a Bengali 4) in time portion", "data": "1963-06-11T0৪:00:00Z", - "valid": false + "valid": false, + "schema_id": "format_0_0" }, { "description": "invalid extended year", "data": "+11963-06-19T08:30:06.283185Z", - "valid": false + "valid": false, + "schema_id": "format_0_0" } ] }, @@ -147,8 +173,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "format": "date" + "format": "date", + "$id": "format_1_0" } ] }, @@ -156,242 +182,290 @@ { "description": "all string formats ignore integers", "data": 12, - "valid": true + "valid": true, + "schema_id": "format_1_0" }, { "description": "all string formats ignore floats", "data": 13.7, - "valid": true + "valid": true, + "schema_id": "format_1_0" }, { "description": "all string formats ignore objects", "data": {}, - "valid": true + "valid": true, + "schema_id": "format_1_0" }, { "description": "all string formats ignore arrays", "data": [], - "valid": true + "valid": true, + "schema_id": "format_1_0" }, { "description": "all string formats ignore booleans", "data": false, - "valid": true + "valid": true, + "schema_id": "format_1_0" }, { "description": "all string formats ignore nulls", "data": null, - "valid": true + "valid": true, + "schema_id": "format_1_0" }, { "description": "a valid date string", "data": "1963-06-19", - "valid": true + "valid": true, + "schema_id": "format_1_0" }, { "description": "a valid date string with 31 days in January", "data": "2020-01-31", - "valid": true + "valid": true, + "schema_id": "format_1_0" }, { "description": "a invalid date string with 32 days in January", "data": "2020-01-32", - "valid": false + "valid": false, + "schema_id": "format_1_0" }, { "description": "a valid date string with 28 days in February (normal)", "data": "2021-02-28", - "valid": true + "valid": true, + "schema_id": "format_1_0" }, { "description": "a invalid date string with 29 days in February (normal)", "data": "2021-02-29", - "valid": false + "valid": false, + "schema_id": "format_1_0" }, { "description": "a valid date string with 29 days in February (leap)", "data": "2020-02-29", - "valid": true + "valid": true, + "schema_id": "format_1_0" }, { "description": "a invalid date string with 30 days in February (leap)", "data": "2020-02-30", - "valid": false + "valid": false, + "schema_id": "format_1_0" }, { "description": "a valid date string with 31 days in March", "data": "2020-03-31", - "valid": true + "valid": true, + "schema_id": "format_1_0" }, { "description": "a invalid date string with 32 days in March", "data": "2020-03-32", - "valid": false + "valid": false, + "schema_id": "format_1_0" }, { "description": "a valid date string with 30 days in April", "data": "2020-04-30", - "valid": true + "valid": true, + "schema_id": "format_1_0" }, { "description": "a invalid date string with 31 days in April", "data": "2020-04-31", - "valid": false + "valid": false, + "schema_id": "format_1_0" }, { "description": "a valid date string with 31 days in May", "data": "2020-05-31", - "valid": true + "valid": true, + "schema_id": "format_1_0" }, { "description": "a invalid date string with 32 days in May", "data": "2020-05-32", - "valid": false + "valid": false, + "schema_id": "format_1_0" }, { "description": "a valid date string with 30 days in June", "data": "2020-06-30", - "valid": true + "valid": true, + "schema_id": "format_1_0" }, { "description": "a invalid date string with 31 days in June", "data": "2020-06-31", - "valid": false + "valid": false, + "schema_id": "format_1_0" }, { "description": "a valid date string with 31 days in July", "data": "2020-07-31", - "valid": true + "valid": true, + "schema_id": "format_1_0" }, { "description": "a invalid date string with 32 days in July", "data": "2020-07-32", - "valid": false + "valid": false, + "schema_id": "format_1_0" }, { "description": "a valid date string with 31 days in August", "data": "2020-08-31", - "valid": true + "valid": true, + "schema_id": "format_1_0" }, { "description": "a invalid date string with 32 days in August", "data": "2020-08-32", - "valid": false + "valid": false, + "schema_id": "format_1_0" }, { "description": "a valid date string with 30 days in September", "data": "2020-09-30", - "valid": true + "valid": true, + "schema_id": "format_1_0" }, { "description": "a invalid date string with 31 days in September", "data": "2020-09-31", - "valid": false + "valid": false, + "schema_id": "format_1_0" }, { "description": "a valid date string with 31 days in October", "data": "2020-10-31", - "valid": true + "valid": true, + "schema_id": "format_1_0" }, { "description": "a invalid date string with 32 days in October", "data": "2020-10-32", - "valid": false + "valid": false, + "schema_id": "format_1_0" }, { "description": "a valid date string with 30 days in November", "data": "2020-11-30", - "valid": true + "valid": true, + "schema_id": "format_1_0" }, { "description": "a invalid date string with 31 days in November", "data": "2020-11-31", - "valid": false + "valid": false, + "schema_id": "format_1_0" }, { "description": "a valid date string with 31 days in December", "data": "2020-12-31", - "valid": true + "valid": true, + "schema_id": "format_1_0" }, { "description": "a invalid date string with 32 days in December", "data": "2020-12-32", - "valid": false + "valid": false, + "schema_id": "format_1_0" }, { "description": "a invalid date string with invalid month", "data": "2020-13-01", - "valid": false + "valid": false, + "schema_id": "format_1_0" }, { "description": "an invalid date string", "data": "06/19/1963", - "valid": false + "valid": false, + "schema_id": "format_1_0" }, { "description": "only RFC3339 not all of ISO 8601 are valid", "data": "2013-350", - "valid": false + "valid": false, + "schema_id": "format_1_0" }, { "description": "non-padded month dates are not valid", "data": "1998-1-20", - "valid": false + "valid": false, + "schema_id": "format_1_0" }, { "description": "non-padded day dates are not valid", "data": "1998-01-1", - "valid": false + "valid": false, + "schema_id": "format_1_0" }, { "description": "invalid month", "data": "1998-13-01", - "valid": false + "valid": false, + "schema_id": "format_1_0" }, { "description": "invalid month-day combination", "data": "1998-04-31", - "valid": false + "valid": false, + "schema_id": "format_1_0" }, { "description": "2021 is not a leap year", "data": "2021-02-29", - "valid": false + "valid": false, + "schema_id": "format_1_0" }, { "description": "2020 is a leap year", "data": "2020-02-29", - "valid": true + "valid": true, + "schema_id": "format_1_0" }, { "description": "invalid non-ASCII '৪' (a Bengali 4)", "data": "1963-06-1৪", - "valid": false + "valid": false, + "schema_id": "format_1_0" }, { "description": "ISO8601 / non-RFC3339: YYYYMMDD without dashes (2023-03-28)", "data": "20230328", - "valid": false + "valid": false, + "schema_id": "format_1_0" }, { "description": "ISO8601 / non-RFC3339: week number implicit day of week (2023-01-02)", "data": "2023-W01", - "valid": false + "valid": false, + "schema_id": "format_1_0" }, { "description": "ISO8601 / non-RFC3339: week number with day of week (2023-03-28)", "data": "2023-W13-2", - "valid": false + "valid": false, + "schema_id": "format_1_0" }, { "description": "ISO8601 / non-RFC3339: week number rollover to next year (2023-01-01)", "data": "2022W527", - "valid": false + "valid": false, + "schema_id": "format_1_0" }, { "description": "an invalid time string in date-time format", "data": "2020-11-28T23:55:45Z", - "valid": false + "valid": false, + "schema_id": "format_1_0" } ] }, @@ -400,8 +474,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "format": "duration" + "format": "duration", + "$id": "format_2_0" } ] }, @@ -409,132 +483,158 @@ { "description": "all string formats ignore integers", "data": 12, - "valid": true + "valid": true, + "schema_id": "format_2_0" }, { "description": "all string formats ignore floats", "data": 13.7, - "valid": true + "valid": true, + "schema_id": "format_2_0" }, { "description": "all string formats ignore objects", "data": {}, - "valid": true + "valid": true, + "schema_id": "format_2_0" }, { "description": "all string formats ignore arrays", "data": [], - "valid": true + "valid": true, + "schema_id": "format_2_0" }, { "description": "all string formats ignore booleans", "data": false, - "valid": true + "valid": true, + "schema_id": "format_2_0" }, { "description": "all string formats ignore nulls", "data": null, - "valid": true + "valid": true, + "schema_id": "format_2_0" }, { "description": "a valid duration string", "data": "P4DT12H30M5S", - "valid": true + "valid": true, + "schema_id": "format_2_0" }, { "description": "an invalid duration string", "data": "PT1D", - "valid": false + "valid": false, + "schema_id": "format_2_0" }, { "description": "must start with P", "data": "4DT12H30M5S", - "valid": false + "valid": false, + "schema_id": "format_2_0" }, { "description": "no elements present", "data": "P", - "valid": false + "valid": false, + "schema_id": "format_2_0" }, { "description": "no time elements present", "data": "P1YT", - "valid": false + "valid": false, + "schema_id": "format_2_0" }, { "description": "no date or time elements present", "data": "PT", - "valid": false + "valid": false, + "schema_id": "format_2_0" }, { "description": "elements out of order", "data": "P2D1Y", - "valid": false + "valid": false, + "schema_id": "format_2_0" }, { "description": "missing time separator", "data": "P1D2H", - "valid": false + "valid": false, + "schema_id": "format_2_0" }, { "description": "time element in the date position", "data": "P2S", - "valid": false + "valid": false, + "schema_id": "format_2_0" }, { "description": "four years duration", "data": "P4Y", - "valid": true + "valid": true, + "schema_id": "format_2_0" }, { "description": "zero time, in seconds", "data": "PT0S", - "valid": true + "valid": true, + "schema_id": "format_2_0" }, { "description": "zero time, in days", "data": "P0D", - "valid": true + "valid": true, + "schema_id": "format_2_0" }, { "description": "one month duration", "data": "P1M", - "valid": true + "valid": true, + "schema_id": "format_2_0" }, { "description": "one minute duration", "data": "PT1M", - "valid": true + "valid": true, + "schema_id": "format_2_0" }, { "description": "one and a half days, in hours", "data": "PT36H", - "valid": true + "valid": true, + "schema_id": "format_2_0" }, { "description": "one and a half days, in days and hours", "data": "P1DT12H", - "valid": true + "valid": true, + "schema_id": "format_2_0" }, { "description": "two weeks", "data": "P2W", - "valid": true + "valid": true, + "schema_id": "format_2_0" }, { "description": "weeks cannot be combined with other units", "data": "P1Y2W", - "valid": false + "valid": false, + "schema_id": "format_2_0" }, { "description": "invalid non-ASCII '২' (a Bengali 2)", "data": "P২Y", - "valid": false + "valid": false, + "schema_id": "format_2_0" }, { "description": "element without unit", "data": "P1", - "valid": false + "valid": false, + "schema_id": "format_2_0" } ] }, @@ -543,8 +643,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "format": "regex" + "format": "regex", + "$id": "format_3_0" } ] }, @@ -552,7 +652,8 @@ { "description": "when used as a pattern", "data": "\\a", - "valid": true + "valid": true, + "schema_id": "format_3_0" } ] }, @@ -561,8 +662,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "format": "email" + "format": "email", + "$id": "format_4_0" } ] }, @@ -570,122 +671,146 @@ { "description": "all string formats ignore integers", "data": 12, - "valid": true + "valid": true, + "schema_id": "format_4_0" }, { "description": "all string formats ignore floats", "data": 13.7, - "valid": true + "valid": true, + "schema_id": "format_4_0" }, { "description": "all string formats ignore objects", "data": {}, - "valid": true + "valid": true, + "schema_id": "format_4_0" }, { "description": "all string formats ignore arrays", "data": [], - "valid": true + "valid": true, + "schema_id": "format_4_0" }, { "description": "all string formats ignore booleans", "data": false, - "valid": true + "valid": true, + "schema_id": "format_4_0" }, { "description": "all string formats ignore nulls", "data": null, - "valid": true + "valid": true, + "schema_id": "format_4_0" }, { "description": "a valid e-mail address", "data": "joe.bloggs@example.com", - "valid": true + "valid": true, + "schema_id": "format_4_0" }, { "description": "an invalid e-mail address", "data": "2962", - "valid": false + "valid": false, + "schema_id": "format_4_0" }, { "description": "tilde in local part is valid", "data": "te~st@example.com", - "valid": true + "valid": true, + "schema_id": "format_4_0" }, { "description": "tilde before local part is valid", "data": "~test@example.com", - "valid": true + "valid": true, + "schema_id": "format_4_0" }, { "description": "tilde after local part is valid", "data": "test~@example.com", - "valid": true + "valid": true, + "schema_id": "format_4_0" }, { "description": "a quoted string with a space in the local part is valid", "data": "\"joe bloggs\"@example.com", - "valid": true + "valid": true, + "schema_id": "format_4_0" }, { "description": "a quoted string with a double dot in the local part is valid", "data": "\"joe..bloggs\"@example.com", - "valid": true + "valid": true, + "schema_id": "format_4_0" }, { "description": "a quoted string with a @ in the local part is valid", "data": "\"joe@bloggs\"@example.com", - "valid": true + "valid": true, + "schema_id": "format_4_0" }, { "description": "an IPv4-address-literal after the @ is valid", "data": "joe.bloggs@[127.0.0.1]", - "valid": true + "valid": true, + "schema_id": "format_4_0" }, { "description": "an IPv6-address-literal after the @ is valid", "data": "joe.bloggs@[IPv6:::1]", - "valid": true + "valid": true, + "schema_id": "format_4_0" }, { "description": "dot before local part is not valid", "data": ".test@example.com", - "valid": false + "valid": false, + "schema_id": "format_4_0" }, { "description": "dot after local part is not valid", "data": "test.@example.com", - "valid": false + "valid": false, + "schema_id": "format_4_0" }, { "description": "two separated dots inside local part are valid", "data": "te.s.t@example.com", - "valid": true + "valid": true, + "schema_id": "format_4_0" }, { "description": "two subsequent dots inside local part are not valid", "data": "te..st@example.com", - "valid": false + "valid": false, + "schema_id": "format_4_0" }, { "description": "an invalid domain", "data": "joe.bloggs@invalid=domain.com", - "valid": false + "valid": false, + "schema_id": "format_4_0" }, { "description": "an invalid IPv4-address-literal", "data": "joe.bloggs@[127.0.0.300]", - "valid": false + "valid": false, + "schema_id": "format_4_0" }, { "description": "two email addresses is not valid", "data": "user1@oceania.org, user2@oceania.org", - "valid": false + "valid": false, + "schema_id": "format_4_0" }, { "description": "full \"From\" header is invalid", "data": "\"Winston Smith\" (Records Department)", - "valid": false + "valid": false, + "schema_id": "format_4_0" } ] }, @@ -694,8 +819,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "format": "hostname" + "format": "hostname", + "$id": "format_5_0" } ] }, @@ -703,123 +828,147 @@ { "description": "all string formats ignore integers", "data": 12, - "valid": true + "valid": true, + "schema_id": "format_5_0" }, { "description": "all string formats ignore floats", "data": 13.7, - "valid": true + "valid": true, + "schema_id": "format_5_0" }, { "description": "all string formats ignore objects", "data": {}, - "valid": true + "valid": true, + "schema_id": "format_5_0" }, { "description": "all string formats ignore arrays", "data": [], - "valid": true + "valid": true, + "schema_id": "format_5_0" }, { "description": "all string formats ignore booleans", "data": false, - "valid": true + "valid": true, + "schema_id": "format_5_0" }, { "description": "all string formats ignore nulls", "data": null, - "valid": true + "valid": true, + "schema_id": "format_5_0" }, { "description": "a valid host name", "data": "www.example.com", - "valid": true + "valid": true, + "schema_id": "format_5_0" }, { "description": "single label", "data": "hostname", - "valid": true + "valid": true, + "schema_id": "format_5_0" }, { "description": "single label with digits", "data": "h0stn4me", - "valid": true + "valid": true, + "schema_id": "format_5_0" }, { "description": "single label starting with digit", "data": "1host", - "valid": true + "valid": true, + "schema_id": "format_5_0" }, { "description": "single label ending with digit", "data": "hostnam3", - "valid": true + "valid": true, + "schema_id": "format_5_0" }, { "description": "empty string", "data": "", - "valid": true + "valid": true, + "schema_id": "format_5_0" }, { "description": "single dot", "data": ".", - "valid": false + "valid": false, + "schema_id": "format_5_0" }, { "description": "leading dot", "data": ".example", - "valid": false + "valid": false, + "schema_id": "format_5_0" }, { "description": "trailing dot", "data": "example.", - "valid": false + "valid": false, + "schema_id": "format_5_0" }, { "description": "IDN label separator", "data": "example.com", - "valid": false + "valid": false, + "schema_id": "format_5_0" }, { "description": "single label with hyphen", "data": "host-name", - "valid": true + "valid": true, + "schema_id": "format_5_0" }, { "description": "starts with hyphen", "data": "-hostname", - "valid": false + "valid": false, + "schema_id": "format_5_0" }, { "description": "ends with hyphen", "data": "hostname-", - "valid": false + "valid": false, + "schema_id": "format_5_0" }, { "description": "contains \"--\" in the 3rd and 4th position", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.1 https://tools.ietf.org/html/rfc5890#section-2.3.2.1", "data": "XN--aa---o47jg78q", - "valid": false + "valid": false, + "schema_id": "format_5_0" }, { "description": "contains underscore", "data": "host_name", - "valid": false + "valid": false, + "schema_id": "format_5_0" }, { "description": "exceeds maximum overall length (256)", "data": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.com", - "valid": false + "valid": false, + "schema_id": "format_5_0" }, { "description": "maximum label length (63)", "data": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.com", - "valid": true + "valid": true, + "schema_id": "format_5_0" }, { "description": "exceeds maximum label length (63)", "data": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl.com", - "valid": false + "valid": false, + "schema_id": "format_5_0" } ] }, @@ -828,8 +977,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "format": "hostname" + "format": "hostname", + "$id": "format_6_0" } ] }, @@ -838,221 +987,258 @@ "description": "invalid Punycode", "comment": "https://tools.ietf.org/html/rfc5891#section-4.4 https://tools.ietf.org/html/rfc5890#section-2.3.2.1", "data": "xn--X", - "valid": false + "valid": false, + "schema_id": "format_6_0" }, { "description": "a valid host name (example.test in Hangul)", "data": "xn--9n2bp8q.xn--9t4b11yi5a", - "valid": true + "valid": true, + "schema_id": "format_6_0" }, { "description": "contains illegal char U+302E Hangul single dot tone mark", "data": "xn--07jt112bpxg.xn--9t4b11yi5a", - "valid": false + "valid": false, + "schema_id": "format_6_0" }, { "description": "Begins with a Spacing Combining Mark", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.2", "data": "xn--hello-txk", - "valid": false + "valid": false, + "schema_id": "format_6_0" }, { "description": "Begins with a Nonspacing Mark", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.2", "data": "xn--hello-zed", - "valid": false + "valid": false, + "schema_id": "format_6_0" }, { "description": "Begins with an Enclosing Mark", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.2", "data": "xn--hello-6bf", - "valid": false + "valid": false, + "schema_id": "format_6_0" }, { "description": "Exceptions that are PVALID, left-to-right chars", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.2 https://tools.ietf.org/html/rfc5892#section-2.6", "data": "xn--zca29lwxobi7a", - "valid": true + "valid": true, + "schema_id": "format_6_0" }, { "description": "Exceptions that are PVALID, right-to-left chars", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.2 https://tools.ietf.org/html/rfc5892#section-2.6", "data": "xn--qmbc", - "valid": true + "valid": true, + "schema_id": "format_6_0" }, { "description": "Exceptions that are DISALLOWED, right-to-left chars", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.2 https://tools.ietf.org/html/rfc5892#section-2.6", "data": "xn--chb89f", - "valid": false + "valid": false, + "schema_id": "format_6_0" }, { "description": "Exceptions that are DISALLOWED, left-to-right chars", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.2 https://tools.ietf.org/html/rfc5892#section-2.6 Note: The two combining marks (U+302E and U+302F) are in the middle and not at the start", "data": "xn--07jceefgh4c", - "valid": false + "valid": false, + "schema_id": "format_6_0" }, { "description": "MIDDLE DOT with no preceding 'l'", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.3", "data": "xn--al-0ea", - "valid": false + "valid": false, + "schema_id": "format_6_0" }, { "description": "MIDDLE DOT with nothing preceding", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.3", "data": "xn--l-fda", - "valid": false + "valid": false, + "schema_id": "format_6_0" }, { "description": "MIDDLE DOT with no following 'l'", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.3", "data": "xn--la-0ea", - "valid": false + "valid": false, + "schema_id": "format_6_0" }, { "description": "MIDDLE DOT with nothing following", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.3", "data": "xn--l-gda", - "valid": false + "valid": false, + "schema_id": "format_6_0" }, { "description": "MIDDLE DOT with surrounding 'l's", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.3", "data": "xn--ll-0ea", - "valid": true + "valid": true, + "schema_id": "format_6_0" }, { "description": "Greek KERAIA not followed by Greek", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.4", "data": "xn--S-jib3p", - "valid": false + "valid": false, + "schema_id": "format_6_0" }, { "description": "Greek KERAIA not followed by anything", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.4", "data": "xn--wva3j", - "valid": false + "valid": false, + "schema_id": "format_6_0" }, { "description": "Greek KERAIA followed by Greek", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.4", "data": "xn--wva3je", - "valid": true + "valid": true, + "schema_id": "format_6_0" }, { "description": "Hebrew GERESH not preceded by Hebrew", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.5", "data": "xn--A-2hc5h", - "valid": false + "valid": false, + "schema_id": "format_6_0" }, { "description": "Hebrew GERESH not preceded by anything", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.5", "data": "xn--5db1e", - "valid": false + "valid": false, + "schema_id": "format_6_0" }, { "description": "Hebrew GERESH preceded by Hebrew", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.5", "data": "xn--4dbc5h", - "valid": true + "valid": true, + "schema_id": "format_6_0" }, { "description": "Hebrew GERSHAYIM not preceded by Hebrew", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.6", "data": "xn--A-2hc8h", - "valid": false + "valid": false, + "schema_id": "format_6_0" }, { "description": "Hebrew GERSHAYIM not preceded by anything", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.6", "data": "xn--5db3e", - "valid": false + "valid": false, + "schema_id": "format_6_0" }, { "description": "Hebrew GERSHAYIM preceded by Hebrew", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.6", "data": "xn--4dbc8h", - "valid": true + "valid": true, + "schema_id": "format_6_0" }, { "description": "KATAKANA MIDDLE DOT with no Hiragana, Katakana, or Han", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.7", "data": "xn--defabc-k64e", - "valid": false + "valid": false, + "schema_id": "format_6_0" }, { "description": "KATAKANA MIDDLE DOT with no other characters", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.7", "data": "xn--vek", - "valid": false + "valid": false, + "schema_id": "format_6_0" }, { "description": "KATAKANA MIDDLE DOT with Hiragana", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.7", "data": "xn--k8j5u", - "valid": true + "valid": true, + "schema_id": "format_6_0" }, { "description": "KATAKANA MIDDLE DOT with Katakana", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.7", "data": "xn--bck0j", - "valid": true + "valid": true, + "schema_id": "format_6_0" }, { "description": "KATAKANA MIDDLE DOT with Han", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.7", "data": "xn--vek778f", - "valid": true + "valid": true, + "schema_id": "format_6_0" }, { "description": "Arabic-Indic digits mixed with Extended Arabic-Indic digits", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.8", "data": "xn--ngb6iyr", - "valid": false + "valid": false, + "schema_id": "format_6_0" }, { "description": "Arabic-Indic digits not mixed with Extended Arabic-Indic digits", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.8", "data": "xn--ngba1o", - "valid": true + "valid": true, + "schema_id": "format_6_0" }, { "description": "Extended Arabic-Indic digits not mixed with Arabic-Indic digits", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.9", "data": "xn--0-gyc", - "valid": true + "valid": true, + "schema_id": "format_6_0" }, { "description": "ZERO WIDTH JOINER not preceded by Virama", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.2 https://www.unicode.org/review/pr-37.pdf", "data": "xn--11b2er09f", - "valid": false + "valid": false, + "schema_id": "format_6_0" }, { "description": "ZERO WIDTH JOINER not preceded by anything", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.2 https://www.unicode.org/review/pr-37.pdf", "data": "xn--02b508i", - "valid": false + "valid": false, + "schema_id": "format_6_0" }, { "description": "ZERO WIDTH JOINER preceded by Virama", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.2 https://www.unicode.org/review/pr-37.pdf", "data": "xn--11b2ezcw70k", - "valid": true + "valid": true, + "schema_id": "format_6_0" }, { "description": "ZERO WIDTH NON-JOINER preceded by Virama", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.1", "data": "xn--11b2ezcs70k", - "valid": true + "valid": true, + "schema_id": "format_6_0" }, { "description": "ZERO WIDTH NON-JOINER not preceded by Virama but matches regexp", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.1 https://www.w3.org/TR/alreq/#h_disjoining_enforcement", "data": "xn--ngba5hb2804a", - "valid": true + "valid": true, + "schema_id": "format_6_0" } ] }, @@ -1061,8 +1247,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "format": "idn-email" + "format": "idn-email", + "$id": "format_7_0" } ] }, @@ -1070,52 +1256,62 @@ { "description": "all string formats ignore integers", "data": 12, - "valid": true + "valid": true, + "schema_id": "format_7_0" }, { "description": "all string formats ignore floats", "data": 13.7, - "valid": true + "valid": true, + "schema_id": "format_7_0" }, { "description": "all string formats ignore objects", "data": {}, - "valid": true + "valid": true, + "schema_id": "format_7_0" }, { "description": "all string formats ignore arrays", "data": [], - "valid": true + "valid": true, + "schema_id": "format_7_0" }, { "description": "all string formats ignore booleans", "data": false, - "valid": true + "valid": true, + "schema_id": "format_7_0" }, { "description": "all string formats ignore nulls", "data": null, - "valid": true + "valid": true, + "schema_id": "format_7_0" }, { "description": "a valid idn e-mail (example@example.test in Hangul)", "data": "실례@실례.테스트", - "valid": true + "valid": true, + "schema_id": "format_7_0" }, { "description": "an invalid idn e-mail address", "data": "2962", - "valid": false + "valid": false, + "schema_id": "format_7_0" }, { "description": "a valid e-mail address", "data": "joe.bloggs@example.com", - "valid": true + "valid": true, + "schema_id": "format_7_0" }, { "description": "an invalid e-mail address", "data": "2962", - "valid": false + "valid": false, + "schema_id": "format_7_0" } ] }, @@ -1124,8 +1320,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "format": "idn-hostname" + "format": "idn-hostname", + "$id": "format_8_0" } ] }, @@ -1133,328 +1329,385 @@ { "description": "all string formats ignore integers", "data": 12, - "valid": true + "valid": true, + "schema_id": "format_8_0" }, { "description": "all string formats ignore floats", "data": 13.7, - "valid": true + "valid": true, + "schema_id": "format_8_0" }, { "description": "all string formats ignore objects", "data": {}, - "valid": true + "valid": true, + "schema_id": "format_8_0" }, { "description": "all string formats ignore arrays", "data": [], - "valid": true + "valid": true, + "schema_id": "format_8_0" }, { "description": "all string formats ignore booleans", "data": false, - "valid": true + "valid": true, + "schema_id": "format_8_0" }, { "description": "all string formats ignore nulls", "data": null, - "valid": true + "valid": true, + "schema_id": "format_8_0" }, { "description": "a valid host name (example.test in Hangul)", "data": "실례.테스트", - "valid": true + "valid": true, + "schema_id": "format_8_0" }, { "description": "illegal first char U+302E Hangul single dot tone mark", "data": "〮실례.테스트", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "contains illegal char U+302E Hangul single dot tone mark", "data": "실〮례.테스트", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "a host name with a component too long", "data": "실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실례례테스트례례례례례례례례례례례례례례례례례테스트례례례례례례례례례례례례례례례례례례례테스트례례례례례례례례례례례례테스트례례실례.테스트", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "invalid label, correct Punycode", "comment": "https://tools.ietf.org/html/rfc5890#section-2.3.2.1 https://tools.ietf.org/html/rfc5891#section-4.4 https://tools.ietf.org/html/rfc3492#section-7.1", "data": "-> $1.00 <--", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "valid Chinese Punycode", "comment": "https://tools.ietf.org/html/rfc5890#section-2.3.2.1 https://tools.ietf.org/html/rfc5891#section-4.4", "data": "xn--ihqwcrb4cv8a8dqg056pqjye", - "valid": true + "valid": true, + "schema_id": "format_8_0" }, { "description": "invalid Punycode", "comment": "https://tools.ietf.org/html/rfc5891#section-4.4 https://tools.ietf.org/html/rfc5890#section-2.3.2.1", "data": "xn--X", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "U-label contains \"--\" in the 3rd and 4th position", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.1 https://tools.ietf.org/html/rfc5890#section-2.3.2.1", "data": "XN--aa---o47jg78q", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "U-label starts with a dash", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.1", "data": "-hello", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "U-label ends with a dash", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.1", "data": "hello-", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "U-label starts and ends with a dash", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.1", "data": "-hello-", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "Begins with a Spacing Combining Mark", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.2", "data": "ःhello", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "Begins with a Nonspacing Mark", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.2", "data": "̀hello", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "Begins with an Enclosing Mark", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.2", "data": "҈hello", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "Exceptions that are PVALID, left-to-right chars", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.2 https://tools.ietf.org/html/rfc5892#section-2.6", "data": "ßς་〇", - "valid": true + "valid": true, + "schema_id": "format_8_0" }, { "description": "Exceptions that are PVALID, right-to-left chars", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.2 https://tools.ietf.org/html/rfc5892#section-2.6", "data": "۽۾", - "valid": true + "valid": true, + "schema_id": "format_8_0" }, { "description": "Exceptions that are DISALLOWED, right-to-left chars", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.2 https://tools.ietf.org/html/rfc5892#section-2.6", "data": "ـߺ", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "Exceptions that are DISALLOWED, left-to-right chars", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.2 https://tools.ietf.org/html/rfc5892#section-2.6 Note: The two combining marks (U+302E and U+302F) are in the middle and not at the start", "data": "〱〲〳〴〵〮〯〻", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "MIDDLE DOT with no preceding 'l'", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.3", "data": "a·l", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "MIDDLE DOT with nothing preceding", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.3", "data": "·l", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "MIDDLE DOT with no following 'l'", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.3", "data": "l·a", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "MIDDLE DOT with nothing following", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.3", "data": "l·", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "MIDDLE DOT with surrounding 'l's", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.3", "data": "l·l", - "valid": true + "valid": true, + "schema_id": "format_8_0" }, { "description": "Greek KERAIA not followed by Greek", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.4", "data": "α͵S", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "Greek KERAIA not followed by anything", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.4", "data": "α͵", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "Greek KERAIA followed by Greek", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.4", "data": "α͵β", - "valid": true + "valid": true, + "schema_id": "format_8_0" }, { "description": "Hebrew GERESH not preceded by Hebrew", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.5", "data": "A׳ב", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "Hebrew GERESH not preceded by anything", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.5", "data": "׳ב", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "Hebrew GERESH preceded by Hebrew", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.5", "data": "א׳ב", - "valid": true + "valid": true, + "schema_id": "format_8_0" }, { "description": "Hebrew GERSHAYIM not preceded by Hebrew", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.6", "data": "A״ב", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "Hebrew GERSHAYIM not preceded by anything", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.6", "data": "״ב", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "Hebrew GERSHAYIM preceded by Hebrew", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.6", "data": "א״ב", - "valid": true + "valid": true, + "schema_id": "format_8_0" }, { "description": "KATAKANA MIDDLE DOT with no Hiragana, Katakana, or Han", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.7", "data": "def・abc", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "KATAKANA MIDDLE DOT with no other characters", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.7", "data": "・", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "KATAKANA MIDDLE DOT with Hiragana", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.7", "data": "・ぁ", - "valid": true + "valid": true, + "schema_id": "format_8_0" }, { "description": "KATAKANA MIDDLE DOT with Katakana", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.7", "data": "・ァ", - "valid": true + "valid": true, + "schema_id": "format_8_0" }, { "description": "KATAKANA MIDDLE DOT with Han", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.7", "data": "・丈", - "valid": true + "valid": true, + "schema_id": "format_8_0" }, { "description": "Arabic-Indic digits mixed with Extended Arabic-Indic digits", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.8", "data": "ب٠۰", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "Arabic-Indic digits not mixed with Extended Arabic-Indic digits", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.8", "data": "ب٠ب", - "valid": true + "valid": true, + "schema_id": "format_8_0" }, { "description": "Extended Arabic-Indic digits not mixed with Arabic-Indic digits", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.9", "data": "۰0", - "valid": true + "valid": true, + "schema_id": "format_8_0" }, { "description": "ZERO WIDTH JOINER not preceded by Virama", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.2 https://www.unicode.org/review/pr-37.pdf", "data": "क‍ष", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "ZERO WIDTH JOINER not preceded by anything", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.2 https://www.unicode.org/review/pr-37.pdf", "data": "‍ष", - "valid": false + "valid": false, + "schema_id": "format_8_0" }, { "description": "ZERO WIDTH JOINER preceded by Virama", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.2 https://www.unicode.org/review/pr-37.pdf", "data": "क्‍ष", - "valid": true + "valid": true, + "schema_id": "format_8_0" }, { "description": "ZERO WIDTH NON-JOINER preceded by Virama", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.1", "data": "क्‌ष", - "valid": true + "valid": true, + "schema_id": "format_8_0" }, { "description": "ZERO WIDTH NON-JOINER not preceded by Virama but matches regexp", "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.1 https://www.w3.org/TR/alreq/#h_disjoining_enforcement", "data": "بي‌بي", - "valid": true + "valid": true, + "schema_id": "format_8_0" }, { "description": "single label", "data": "hostname", - "valid": true + "valid": true, + "schema_id": "format_8_0" }, { "description": "single label with hyphen", "data": "host-name", - "valid": true + "valid": true, + "schema_id": "format_8_0" }, { "description": "single label with digits", "data": "h0stn4me", - "valid": true + "valid": true, + "schema_id": "format_8_0" }, { "description": "single label starting with digit", "data": "1host", - "valid": true + "valid": true, + "schema_id": "format_8_0" }, { "description": "single label ending with digit", "data": "hostnam3", - "valid": true + "valid": true, + "schema_id": "format_8_0" }, { "description": "empty string", "data": "", - "valid": true + "valid": true, + "schema_id": "format_8_0" } ] }, @@ -1469,8 +1722,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "format": "idn-hostname" + "format": "idn-hostname", + "$id": "format_9_0" } ] }, @@ -1478,102 +1731,122 @@ { "description": "single dot", "data": ".", - "valid": false + "valid": false, + "schema_id": "format_9_0" }, { "description": "single ideographic full stop", "data": "。", - "valid": false + "valid": false, + "schema_id": "format_9_0" }, { "description": "single fullwidth full stop", "data": ".", - "valid": false + "valid": false, + "schema_id": "format_9_0" }, { "description": "single halfwidth ideographic full stop", "data": "。", - "valid": false + "valid": false, + "schema_id": "format_9_0" }, { "description": "dot as label separator", "data": "a.b", - "valid": true + "valid": true, + "schema_id": "format_9_0" }, { "description": "ideographic full stop as label separator", "data": "a。b", - "valid": true + "valid": true, + "schema_id": "format_9_0" }, { "description": "fullwidth full stop as label separator", "data": "a.b", - "valid": true + "valid": true, + "schema_id": "format_9_0" }, { "description": "halfwidth ideographic full stop as label separator", "data": "a。b", - "valid": true + "valid": true, + "schema_id": "format_9_0" }, { "description": "leading dot", "data": ".example", - "valid": false + "valid": false, + "schema_id": "format_9_0" }, { "description": "leading ideographic full stop", "data": "。example", - "valid": false + "valid": false, + "schema_id": "format_9_0" }, { "description": "leading fullwidth full stop", "data": ".example", - "valid": false + "valid": false, + "schema_id": "format_9_0" }, { "description": "leading halfwidth ideographic full stop", "data": "。example", - "valid": false + "valid": false, + "schema_id": "format_9_0" }, { "description": "trailing dot", "data": "example.", - "valid": false + "valid": false, + "schema_id": "format_9_0" }, { "description": "trailing ideographic full stop", "data": "example。", - "valid": false + "valid": false, + "schema_id": "format_9_0" }, { "description": "trailing fullwidth full stop", "data": "example.", - "valid": false + "valid": false, + "schema_id": "format_9_0" }, { "description": "trailing halfwidth ideographic full stop", "data": "example。", - "valid": false + "valid": false, + "schema_id": "format_9_0" }, { "description": "label too long if separator ignored (full stop)", "data": "παράδειγμαπαράδειγμαπαράδειγμαπαράδειγμαπαράδειγμαπα.com", - "valid": true + "valid": true, + "schema_id": "format_9_0" }, { "description": "label too long if separator ignored (ideographic full stop)", "data": "παράδειγμαπαράδειγμαπαράδειγμαπαράδειγμαπαράδειγμαπα。com", - "valid": true + "valid": true, + "schema_id": "format_9_0" }, { "description": "label too long if separator ignored (fullwidth full stop)", "data": "παράδειγμαπαράδειγμαπαράδειγμαπαράδειγμαπαράδειγμαπα.com", - "valid": true + "valid": true, + "schema_id": "format_9_0" }, { "description": "label too long if separator ignored (halfwidth ideographic full stop)", "data": "παράδειγμαπαράδειγμαπαράδειγμαπαράδειγμαπαράδειγμαπα。com", - "valid": true + "valid": true, + "schema_id": "format_9_0" } ] }, @@ -1582,8 +1855,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "format": "ipv4" + "format": "ipv4", + "$id": "format_10_0" } ] }, @@ -1591,83 +1864,99 @@ { "description": "all string formats ignore integers", "data": 12, - "valid": true + "valid": true, + "schema_id": "format_10_0" }, { "description": "all string formats ignore floats", "data": 13.7, - "valid": true + "valid": true, + "schema_id": "format_10_0" }, { "description": "all string formats ignore objects", "data": {}, - "valid": true + "valid": true, + "schema_id": "format_10_0" }, { "description": "all string formats ignore arrays", "data": [], - "valid": true + "valid": true, + "schema_id": "format_10_0" }, { "description": "all string formats ignore booleans", "data": false, - "valid": true + "valid": true, + "schema_id": "format_10_0" }, { "description": "all string formats ignore nulls", "data": null, - "valid": true + "valid": true, + "schema_id": "format_10_0" }, { "description": "a valid IP address", "data": "192.168.0.1", - "valid": true + "valid": true, + "schema_id": "format_10_0" }, { "description": "an IP address with too many components", "data": "127.0.0.0.1", - "valid": false + "valid": false, + "schema_id": "format_10_0" }, { "description": "an IP address with out-of-range values", "data": "256.256.256.256", - "valid": false + "valid": false, + "schema_id": "format_10_0" }, { "description": "an IP address without 4 components", "data": "127.0", - "valid": false + "valid": false, + "schema_id": "format_10_0" }, { "description": "an IP address as an integer", "data": "0x7f000001", - "valid": false + "valid": false, + "schema_id": "format_10_0" }, { "description": "an IP address as an integer (decimal)", "data": "2130706433", - "valid": false + "valid": false, + "schema_id": "format_10_0" }, { "description": "invalid leading zeroes, as they are treated as octals", "comment": "see https://sick.codes/universal-netmask-npm-package-used-by-270000-projects-vulnerable-to-octal-input-data-server-side-request-forgery-remote-file-inclusion-local-file-inclusion-and-more-cve-2021-28918/", "data": "087.10.0.1", - "valid": false + "valid": false, + "schema_id": "format_10_0" }, { "description": "value without leading zero is valid", "data": "87.10.0.1", - "valid": true + "valid": true, + "schema_id": "format_10_0" }, { "description": "invalid non-ASCII '২' (a Bengali 2)", "data": "1২7.0.0.1", - "valid": false + "valid": false, + "schema_id": "format_10_0" }, { "description": "netmask is not a part of ipv4 address", "data": "192.168.1.0/24", - "valid": false + "valid": false, + "schema_id": "format_10_0" } ] }, @@ -1676,8 +1965,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "format": "ipv6" + "format": "ipv6", + "$id": "format_11_0" } ] }, @@ -1685,202 +1974,242 @@ { "description": "all string formats ignore integers", "data": 12, - "valid": true + "valid": true, + "schema_id": "format_11_0" }, { "description": "all string formats ignore floats", "data": 13.7, - "valid": true + "valid": true, + "schema_id": "format_11_0" }, { "description": "all string formats ignore objects", "data": {}, - "valid": true + "valid": true, + "schema_id": "format_11_0" }, { "description": "all string formats ignore arrays", "data": [], - "valid": true + "valid": true, + "schema_id": "format_11_0" }, { "description": "all string formats ignore booleans", "data": false, - "valid": true + "valid": true, + "schema_id": "format_11_0" }, { "description": "all string formats ignore nulls", "data": null, - "valid": true + "valid": true, + "schema_id": "format_11_0" }, { "description": "a valid IPv6 address", "data": "::1", - "valid": true + "valid": true, + "schema_id": "format_11_0" }, { "description": "an IPv6 address with out-of-range values", "data": "12345::", - "valid": false + "valid": false, + "schema_id": "format_11_0" }, { "description": "trailing 4 hex symbols is valid", "data": "::abef", - "valid": true + "valid": true, + "schema_id": "format_11_0" }, { "description": "trailing 5 hex symbols is invalid", "data": "::abcef", - "valid": false + "valid": false, + "schema_id": "format_11_0" }, { "description": "an IPv6 address with too many components", "data": "1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1", - "valid": false + "valid": false, + "schema_id": "format_11_0" }, { "description": "an IPv6 address containing illegal characters", "data": "::laptop", - "valid": false + "valid": false, + "schema_id": "format_11_0" }, { "description": "no digits is valid", "data": "::", - "valid": true + "valid": true, + "schema_id": "format_11_0" }, { "description": "leading colons is valid", "data": "::42:ff:1", - "valid": true + "valid": true, + "schema_id": "format_11_0" }, { "description": "trailing colons is valid", "data": "d6::", - "valid": true + "valid": true, + "schema_id": "format_11_0" }, { "description": "missing leading octet is invalid", "data": ":2:3:4:5:6:7:8", - "valid": false + "valid": false, + "schema_id": "format_11_0" }, { "description": "missing trailing octet is invalid", "data": "1:2:3:4:5:6:7:", - "valid": false + "valid": false, + "schema_id": "format_11_0" }, { "description": "missing leading octet with omitted octets later", "data": ":2:3:4::8", - "valid": false + "valid": false, + "schema_id": "format_11_0" }, { "description": "single set of double colons in the middle is valid", "data": "1:d6::42", - "valid": true + "valid": true, + "schema_id": "format_11_0" }, { "description": "two sets of double colons is invalid", "data": "1::d6::42", - "valid": false + "valid": false, + "schema_id": "format_11_0" }, { "description": "mixed format with the ipv4 section as decimal octets", "data": "1::d6:192.168.0.1", - "valid": true + "valid": true, + "schema_id": "format_11_0" }, { "description": "mixed format with double colons between the sections", "data": "1:2::192.168.0.1", - "valid": true + "valid": true, + "schema_id": "format_11_0" }, { "description": "mixed format with ipv4 section with octet out of range", "data": "1::2:192.168.256.1", - "valid": false + "valid": false, + "schema_id": "format_11_0" }, { "description": "mixed format with ipv4 section with a hex octet", "data": "1::2:192.168.ff.1", - "valid": false + "valid": false, + "schema_id": "format_11_0" }, { "description": "mixed format with leading double colons (ipv4-mapped ipv6 address)", "data": "::ffff:192.168.0.1", - "valid": true + "valid": true, + "schema_id": "format_11_0" }, { "description": "triple colons is invalid", "data": "1:2:3:4:5:::8", - "valid": false + "valid": false, + "schema_id": "format_11_0" }, { "description": "8 octets", "data": "1:2:3:4:5:6:7:8", - "valid": true + "valid": true, + "schema_id": "format_11_0" }, { "description": "insufficient octets without double colons", "data": "1:2:3:4:5:6:7", - "valid": false + "valid": false, + "schema_id": "format_11_0" }, { "description": "no colons is invalid", "data": "1", - "valid": false + "valid": false, + "schema_id": "format_11_0" }, { "description": "ipv4 is not ipv6", "data": "127.0.0.1", - "valid": false + "valid": false, + "schema_id": "format_11_0" }, { "description": "ipv4 segment must have 4 octets", "data": "1:2:3:4:1.2.3", - "valid": false + "valid": false, + "schema_id": "format_11_0" }, { "description": "leading whitespace is invalid", "data": " ::1", - "valid": false + "valid": false, + "schema_id": "format_11_0" }, { "description": "trailing whitespace is invalid", "data": "::1 ", - "valid": false + "valid": false, + "schema_id": "format_11_0" }, { "description": "netmask is not a part of ipv6 address", "data": "fe80::/64", - "valid": false + "valid": false, + "schema_id": "format_11_0" }, { "description": "zone id is not a part of ipv6 address", "data": "fe80::a%eth1", - "valid": false + "valid": false, + "schema_id": "format_11_0" }, { "description": "a long valid ipv6", "data": "1000:1000:1000:1000:1000:1000:255.255.255.255", - "valid": true + "valid": true, + "schema_id": "format_11_0" }, { "description": "a long invalid ipv6, below length limit, first", "data": "100:100:100:100:100:100:255.255.255.255.255", - "valid": false + "valid": false, + "schema_id": "format_11_0" }, { "description": "a long invalid ipv6, below length limit, second", "data": "100:100:100:100:100:100:100:255.255.255.255", - "valid": false + "valid": false, + "schema_id": "format_11_0" }, { "description": "invalid non-ASCII '৪' (a Bengali 4)", "data": "1:2:3:4:5:6:7:৪", - "valid": false + "valid": false, + "schema_id": "format_11_0" }, { "description": "invalid non-ASCII '৪' (a Bengali 4) in the IPv4 portion", "data": "1:2::192.16৪.0.1", - "valid": false + "valid": false, + "schema_id": "format_11_0" } ] }, @@ -1889,8 +2218,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "format": "iri-reference" + "format": "iri-reference", + "$id": "format_12_0" } ] }, @@ -1898,67 +2227,80 @@ { "description": "all string formats ignore integers", "data": 12, - "valid": true + "valid": true, + "schema_id": "format_12_0" }, { "description": "all string formats ignore floats", "data": 13.7, - "valid": true + "valid": true, + "schema_id": "format_12_0" }, { "description": "all string formats ignore objects", "data": {}, - "valid": true + "valid": true, + "schema_id": "format_12_0" }, { "description": "all string formats ignore arrays", "data": [], - "valid": true + "valid": true, + "schema_id": "format_12_0" }, { "description": "all string formats ignore booleans", "data": false, - "valid": true + "valid": true, + "schema_id": "format_12_0" }, { "description": "all string formats ignore nulls", "data": null, - "valid": true + "valid": true, + "schema_id": "format_12_0" }, { "description": "a valid IRI", "data": "http://ƒøø.ßår/?∂éœ=πîx#πîüx", - "valid": true + "valid": true, + "schema_id": "format_12_0" }, { "description": "a valid protocol-relative IRI Reference", "data": "//ƒøø.ßår/?∂éœ=πîx#πîüx", - "valid": true + "valid": true, + "schema_id": "format_12_0" }, { "description": "a valid relative IRI Reference", "data": "/âππ", - "valid": true + "valid": true, + "schema_id": "format_12_0" }, { "description": "an invalid IRI Reference", "data": "\\\\WINDOWS\\filëßåré", - "valid": false + "valid": false, + "schema_id": "format_12_0" }, { "description": "a valid IRI Reference", "data": "âππ", - "valid": true + "valid": true, + "schema_id": "format_12_0" }, { "description": "a valid IRI fragment", "data": "#ƒrägmênt", - "valid": true + "valid": true, + "schema_id": "format_12_0" }, { "description": "an invalid IRI fragment", "data": "#ƒräg\\mênt", - "valid": false + "valid": false, + "schema_id": "format_12_0" } ] }, @@ -1967,8 +2309,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "format": "iri" + "format": "iri", + "$id": "format_13_0" } ] }, @@ -1976,77 +2318,92 @@ { "description": "all string formats ignore integers", "data": 12, - "valid": true + "valid": true, + "schema_id": "format_13_0" }, { "description": "all string formats ignore floats", "data": 13.7, - "valid": true + "valid": true, + "schema_id": "format_13_0" }, { "description": "all string formats ignore objects", "data": {}, - "valid": true + "valid": true, + "schema_id": "format_13_0" }, { "description": "all string formats ignore arrays", "data": [], - "valid": true + "valid": true, + "schema_id": "format_13_0" }, { "description": "all string formats ignore booleans", "data": false, - "valid": true + "valid": true, + "schema_id": "format_13_0" }, { "description": "all string formats ignore nulls", "data": null, - "valid": true + "valid": true, + "schema_id": "format_13_0" }, { "description": "a valid IRI with anchor tag", "data": "http://ƒøø.ßår/?∂éœ=πîx#πîüx", - "valid": true + "valid": true, + "schema_id": "format_13_0" }, { "description": "a valid IRI with anchor tag and parentheses", "data": "http://ƒøø.com/blah_(wîkïpédiå)_blah#ßité-1", - "valid": true + "valid": true, + "schema_id": "format_13_0" }, { "description": "a valid IRI with URL-encoded stuff", "data": "http://ƒøø.ßår/?q=Test%20URL-encoded%20stuff", - "valid": true + "valid": true, + "schema_id": "format_13_0" }, { "description": "a valid IRI with many special characters", "data": "http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com", - "valid": true + "valid": true, + "schema_id": "format_13_0" }, { "description": "a valid IRI based on IPv6", "data": "http://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]", - "valid": true + "valid": true, + "schema_id": "format_13_0" }, { "description": "an invalid IRI based on IPv6", "data": "http://2001:0db8:85a3:0000:0000:8a2e:0370:7334", - "valid": false + "valid": false, + "schema_id": "format_13_0" }, { "description": "an invalid relative IRI Reference", "data": "/abc", - "valid": false + "valid": false, + "schema_id": "format_13_0" }, { "description": "an invalid IRI", "data": "\\\\WINDOWS\\filëßåré", - "valid": false + "valid": false, + "schema_id": "format_13_0" }, { "description": "an invalid IRI though valid IRI reference", "data": "âππ", - "valid": false + "valid": false, + "schema_id": "format_13_0" } ] }, @@ -2055,8 +2412,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "format": "json-pointer" + "format": "json-pointer", + "$id": "format_14_0" } ] }, @@ -2064,192 +2421,230 @@ { "description": "all string formats ignore integers", "data": 12, - "valid": true + "valid": true, + "schema_id": "format_14_0" }, { "description": "all string formats ignore floats", "data": 13.7, - "valid": true + "valid": true, + "schema_id": "format_14_0" }, { "description": "all string formats ignore objects", "data": {}, - "valid": true + "valid": true, + "schema_id": "format_14_0" }, { "description": "all string formats ignore arrays", "data": [], - "valid": true + "valid": true, + "schema_id": "format_14_0" }, { "description": "all string formats ignore booleans", "data": false, - "valid": true + "valid": true, + "schema_id": "format_14_0" }, { "description": "all string formats ignore nulls", "data": null, - "valid": true + "valid": true, + "schema_id": "format_14_0" }, { "description": "a valid JSON-pointer", "data": "/foo/bar~0/baz~1/%a", - "valid": true + "valid": true, + "schema_id": "format_14_0" }, { "description": "not a valid JSON-pointer (~ not escaped)", "data": "/foo/bar~", - "valid": false + "valid": false, + "schema_id": "format_14_0" }, { "description": "valid JSON-pointer with empty segment", "data": "/foo//bar", - "valid": true + "valid": true, + "schema_id": "format_14_0" }, { "description": "valid JSON-pointer with the last empty segment", "data": "/foo/bar/", - "valid": true + "valid": true, + "schema_id": "format_14_0" }, { "description": "valid JSON-pointer as stated in RFC 6901 #1", "data": "", - "valid": true + "valid": true, + "schema_id": "format_14_0" }, { "description": "valid JSON-pointer as stated in RFC 6901 #2", "data": "/foo", - "valid": true + "valid": true, + "schema_id": "format_14_0" }, { "description": "valid JSON-pointer as stated in RFC 6901 #3", "data": "/foo/0", - "valid": true + "valid": true, + "schema_id": "format_14_0" }, { "description": "valid JSON-pointer as stated in RFC 6901 #4", "data": "/", - "valid": true + "valid": true, + "schema_id": "format_14_0" }, { "description": "valid JSON-pointer as stated in RFC 6901 #5", "data": "/a~1b", - "valid": true + "valid": true, + "schema_id": "format_14_0" }, { "description": "valid JSON-pointer as stated in RFC 6901 #6", "data": "/c%d", - "valid": true + "valid": true, + "schema_id": "format_14_0" }, { "description": "valid JSON-pointer as stated in RFC 6901 #7", "data": "/e^f", - "valid": true + "valid": true, + "schema_id": "format_14_0" }, { "description": "valid JSON-pointer as stated in RFC 6901 #8", "data": "/g|h", - "valid": true + "valid": true, + "schema_id": "format_14_0" }, { "description": "valid JSON-pointer as stated in RFC 6901 #9", "data": "/i\\j", - "valid": true + "valid": true, + "schema_id": "format_14_0" }, { "description": "valid JSON-pointer as stated in RFC 6901 #10", "data": "/k\"l", - "valid": true + "valid": true, + "schema_id": "format_14_0" }, { "description": "valid JSON-pointer as stated in RFC 6901 #11", "data": "/ ", - "valid": true + "valid": true, + "schema_id": "format_14_0" }, { "description": "valid JSON-pointer as stated in RFC 6901 #12", "data": "/m~0n", - "valid": true + "valid": true, + "schema_id": "format_14_0" }, { "description": "valid JSON-pointer used adding to the last array position", "data": "/foo/-", - "valid": true + "valid": true, + "schema_id": "format_14_0" }, { "description": "valid JSON-pointer (- used as object member name)", "data": "/foo/-/bar", - "valid": true + "valid": true, + "schema_id": "format_14_0" }, { "description": "valid JSON-pointer (multiple escaped characters)", "data": "/~1~0~0~1~1", - "valid": true + "valid": true, + "schema_id": "format_14_0" }, { "description": "valid JSON-pointer (escaped with fraction part) #1", "data": "/~1.1", - "valid": true + "valid": true, + "schema_id": "format_14_0" }, { "description": "valid JSON-pointer (escaped with fraction part) #2", "data": "/~0.1", - "valid": true + "valid": true, + "schema_id": "format_14_0" }, { "description": "not a valid JSON-pointer (URI Fragment Identifier) #1", "data": "#", - "valid": false + "valid": false, + "schema_id": "format_14_0" }, { "description": "not a valid JSON-pointer (URI Fragment Identifier) #2", "data": "#/", - "valid": false + "valid": false, + "schema_id": "format_14_0" }, { "description": "not a valid JSON-pointer (URI Fragment Identifier) #3", "data": "#a", - "valid": false + "valid": false, + "schema_id": "format_14_0" }, { "description": "not a valid JSON-pointer (some escaped, but not all) #1", "data": "/~0~", - "valid": false + "valid": false, + "schema_id": "format_14_0" }, { "description": "not a valid JSON-pointer (some escaped, but not all) #2", "data": "/~0/~", - "valid": false + "valid": false, + "schema_id": "format_14_0" }, { "description": "not a valid JSON-pointer (wrong escape character) #1", "data": "/~2", - "valid": false + "valid": false, + "schema_id": "format_14_0" }, { "description": "not a valid JSON-pointer (wrong escape character) #2", "data": "/~-1", - "valid": false + "valid": false, + "schema_id": "format_14_0" }, { "description": "not a valid JSON-pointer (multiple characters not escaped)", "data": "/~~", - "valid": false + "valid": false, + "schema_id": "format_14_0" }, { "description": "not a valid JSON-pointer (isn't empty nor starts with /) #1", "data": "a", - "valid": false + "valid": false, + "schema_id": "format_14_0" }, { "description": "not a valid JSON-pointer (isn't empty nor starts with /) #2", "data": "0", - "valid": false + "valid": false, + "schema_id": "format_14_0" }, { "description": "not a valid JSON-pointer (isn't empty nor starts with /) #3", "data": "a/a", - "valid": false + "valid": false, + "schema_id": "format_14_0" } ] }, @@ -2258,8 +2653,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "format": "regex" + "format": "regex", + "$id": "format_15_0" } ] }, @@ -2267,42 +2662,50 @@ { "description": "all string formats ignore integers", "data": 12, - "valid": true + "valid": true, + "schema_id": "format_15_0" }, { "description": "all string formats ignore floats", "data": 13.7, - "valid": true + "valid": true, + "schema_id": "format_15_0" }, { "description": "all string formats ignore objects", "data": {}, - "valid": true + "valid": true, + "schema_id": "format_15_0" }, { "description": "all string formats ignore arrays", "data": [], - "valid": true + "valid": true, + "schema_id": "format_15_0" }, { "description": "all string formats ignore booleans", "data": false, - "valid": true + "valid": true, + "schema_id": "format_15_0" }, { "description": "all string formats ignore nulls", "data": null, - "valid": true + "valid": true, + "schema_id": "format_15_0" }, { "description": "a valid regular expression", "data": "([abc])+\\s+$", - "valid": true + "valid": true, + "schema_id": "format_15_0" }, { "description": "a regular expression with unclosed parens is invalid", "data": "^(abc]", - "valid": true + "valid": true, + "schema_id": "format_15_0" } ] }, @@ -2311,8 +2714,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "format": "relative-json-pointer" + "format": "relative-json-pointer", + "$id": "format_16_0" } ] }, @@ -2320,92 +2723,110 @@ { "description": "all string formats ignore integers", "data": 12, - "valid": true + "valid": true, + "schema_id": "format_16_0" }, { "description": "all string formats ignore floats", "data": 13.7, - "valid": true + "valid": true, + "schema_id": "format_16_0" }, { "description": "all string formats ignore objects", "data": {}, - "valid": true + "valid": true, + "schema_id": "format_16_0" }, { "description": "all string formats ignore arrays", "data": [], - "valid": true + "valid": true, + "schema_id": "format_16_0" }, { "description": "all string formats ignore booleans", "data": false, - "valid": true + "valid": true, + "schema_id": "format_16_0" }, { "description": "all string formats ignore nulls", "data": null, - "valid": true + "valid": true, + "schema_id": "format_16_0" }, { "description": "a valid upwards RJP", "data": "1", - "valid": true + "valid": true, + "schema_id": "format_16_0" }, { "description": "a valid downwards RJP", "data": "0/foo/bar", - "valid": true + "valid": true, + "schema_id": "format_16_0" }, { "description": "a valid up and then down RJP, with array index", "data": "2/0/baz/1/zip", - "valid": true + "valid": true, + "schema_id": "format_16_0" }, { "description": "a valid RJP taking the member or index name", "data": "0#", - "valid": true + "valid": true, + "schema_id": "format_16_0" }, { "description": "an invalid RJP that is a valid JSON Pointer", "data": "/foo/bar", - "valid": false + "valid": false, + "schema_id": "format_16_0" }, { "description": "negative prefix", "data": "-1/foo/bar", - "valid": false + "valid": false, + "schema_id": "format_16_0" }, { "description": "explicit positive prefix", "data": "+1/foo/bar", - "valid": false + "valid": false, + "schema_id": "format_16_0" }, { "description": "## is not a valid json-pointer", "data": "0##", - "valid": false + "valid": false, + "schema_id": "format_16_0" }, { "description": "zero cannot be followed by other digits, plus json-pointer", "data": "01/a", - "valid": false + "valid": false, + "schema_id": "format_16_0" }, { "description": "zero cannot be followed by other digits, plus octothorpe", "data": "01#", - "valid": false + "valid": false, + "schema_id": "format_16_0" }, { "description": "empty string", "data": "", - "valid": true + "valid": true, + "schema_id": "format_16_0" }, { "description": "multi-digit integer prefix", "data": "120/foo/bar", - "valid": true + "valid": true, + "schema_id": "format_16_0" } ] }, @@ -2414,8 +2835,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "format": "time" + "format": "time", + "$id": "format_17_0" } ] }, @@ -2423,232 +2844,278 @@ { "description": "all string formats ignore integers", "data": 12, - "valid": true + "valid": true, + "schema_id": "format_17_0" }, { "description": "all string formats ignore floats", "data": 13.7, - "valid": true + "valid": true, + "schema_id": "format_17_0" }, { "description": "all string formats ignore objects", "data": {}, - "valid": true + "valid": true, + "schema_id": "format_17_0" }, { "description": "all string formats ignore arrays", "data": [], - "valid": true + "valid": true, + "schema_id": "format_17_0" }, { "description": "all string formats ignore booleans", "data": false, - "valid": true + "valid": true, + "schema_id": "format_17_0" }, { "description": "all string formats ignore nulls", "data": null, - "valid": true + "valid": true, + "schema_id": "format_17_0" }, { "description": "a valid time string", "data": "08:30:06Z", - "valid": true + "valid": true, + "schema_id": "format_17_0" }, { "description": "invalid time string with extra leading zeros", "data": "008:030:006Z", - "valid": false + "valid": false, + "schema_id": "format_17_0" }, { "description": "invalid time string with no leading zero for single digit", "data": "8:3:6Z", - "valid": false + "valid": false, + "schema_id": "format_17_0" }, { "description": "hour, minute, second must be two digits", "data": "8:0030:6Z", - "valid": false + "valid": false, + "schema_id": "format_17_0" }, { "description": "a valid time string with leap second, Zulu", "data": "23:59:60Z", - "valid": true + "valid": true, + "schema_id": "format_17_0" }, { "description": "invalid leap second, Zulu (wrong hour)", "data": "22:59:60Z", - "valid": false + "valid": false, + "schema_id": "format_17_0" }, { "description": "invalid leap second, Zulu (wrong minute)", "data": "23:58:60Z", - "valid": false + "valid": false, + "schema_id": "format_17_0" }, { "description": "valid leap second, zero time-offset", "data": "23:59:60+00:00", - "valid": true + "valid": true, + "schema_id": "format_17_0" }, { "description": "invalid leap second, zero time-offset (wrong hour)", "data": "22:59:60+00:00", - "valid": false + "valid": false, + "schema_id": "format_17_0" }, { "description": "invalid leap second, zero time-offset (wrong minute)", "data": "23:58:60+00:00", - "valid": false + "valid": false, + "schema_id": "format_17_0" }, { "description": "valid leap second, positive time-offset", "data": "01:29:60+01:30", - "valid": true + "valid": true, + "schema_id": "format_17_0" }, { "description": "valid leap second, large positive time-offset", "data": "23:29:60+23:30", - "valid": true + "valid": true, + "schema_id": "format_17_0" }, { "description": "invalid leap second, positive time-offset (wrong hour)", "data": "23:59:60+01:00", - "valid": false + "valid": false, + "schema_id": "format_17_0" }, { "description": "invalid leap second, positive time-offset (wrong minute)", "data": "23:59:60+00:30", - "valid": false + "valid": false, + "schema_id": "format_17_0" }, { "description": "valid leap second, negative time-offset", "data": "15:59:60-08:00", - "valid": true + "valid": true, + "schema_id": "format_17_0" }, { "description": "valid leap second, large negative time-offset", "data": "00:29:60-23:30", - "valid": true + "valid": true, + "schema_id": "format_17_0" }, { "description": "invalid leap second, negative time-offset (wrong hour)", "data": "23:59:60-01:00", - "valid": false + "valid": false, + "schema_id": "format_17_0" }, { "description": "invalid leap second, negative time-offset (wrong minute)", "data": "23:59:60-00:30", - "valid": false + "valid": false, + "schema_id": "format_17_0" }, { "description": "a valid time string with second fraction", "data": "23:20:50.52Z", - "valid": true + "valid": true, + "schema_id": "format_17_0" }, { "description": "a valid time string with precise second fraction", "data": "08:30:06.283185Z", - "valid": true + "valid": true, + "schema_id": "format_17_0" }, { "description": "a valid time string with plus offset", "data": "08:30:06+00:20", - "valid": true + "valid": true, + "schema_id": "format_17_0" }, { "description": "a valid time string with minus offset", "data": "08:30:06-08:00", - "valid": true + "valid": true, + "schema_id": "format_17_0" }, { "description": "hour, minute in time-offset must be two digits", "data": "08:30:06-8:000", - "valid": false + "valid": false, + "schema_id": "format_17_0" }, { "description": "a valid time string with case-insensitive Z", "data": "08:30:06z", - "valid": true + "valid": true, + "schema_id": "format_17_0" }, { "description": "an invalid time string with invalid hour", "data": "24:00:00Z", - "valid": false + "valid": false, + "schema_id": "format_17_0" }, { "description": "an invalid time string with invalid minute", "data": "00:60:00Z", - "valid": false + "valid": false, + "schema_id": "format_17_0" }, { "description": "an invalid time string with invalid second", "data": "00:00:61Z", - "valid": false + "valid": false, + "schema_id": "format_17_0" }, { "description": "an invalid time string with invalid leap second (wrong hour)", "data": "22:59:60Z", - "valid": false + "valid": false, + "schema_id": "format_17_0" }, { "description": "an invalid time string with invalid leap second (wrong minute)", "data": "23:58:60Z", - "valid": false + "valid": false, + "schema_id": "format_17_0" }, { "description": "an invalid time string with invalid time numoffset hour", "data": "01:02:03+24:00", - "valid": false + "valid": false, + "schema_id": "format_17_0" }, { "description": "an invalid time string with invalid time numoffset minute", "data": "01:02:03+00:60", - "valid": false + "valid": false, + "schema_id": "format_17_0" }, { "description": "an invalid time string with invalid time with both Z and numoffset", "data": "01:02:03Z+00:30", - "valid": false + "valid": false, + "schema_id": "format_17_0" }, { "description": "an invalid offset indicator", "data": "08:30:06 PST", - "valid": false + "valid": false, + "schema_id": "format_17_0" }, { "description": "only RFC3339 not all of ISO 8601 are valid", "data": "01:01:01,1111", - "valid": false + "valid": false, + "schema_id": "format_17_0" }, { "description": "no time offset", "data": "12:00:00", - "valid": false + "valid": false, + "schema_id": "format_17_0" }, { "description": "no time offset with second fraction", "data": "12:00:00.52", - "valid": false + "valid": false, + "schema_id": "format_17_0" }, { "description": "invalid non-ASCII '২' (a Bengali 2)", "data": "1২:00:00Z", - "valid": false + "valid": false, + "schema_id": "format_17_0" }, { "description": "offset not starting with plus or minus", "data": "08:30:06#00:20", - "valid": false + "valid": false, + "schema_id": "format_17_0" }, { "description": "contains letters", "data": "ab:cd:ef", - "valid": false + "valid": false, + "schema_id": "format_17_0" }, { "description": "an invalid time string in date-time format", "data": "2020-11-28T23:55:45Z", - "valid": false + "valid": false, + "schema_id": "format_17_0" } ] }, @@ -2657,8 +3124,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "format": "unknown" + "format": "unknown", + "$id": "format_18_0" } ] }, @@ -2666,37 +3133,44 @@ { "description": "unknown formats ignore integers", "data": 12, - "valid": true + "valid": true, + "schema_id": "format_18_0" }, { "description": "unknown formats ignore floats", "data": 13.7, - "valid": true + "valid": true, + "schema_id": "format_18_0" }, { "description": "unknown formats ignore objects", "data": {}, - "valid": true + "valid": true, + "schema_id": "format_18_0" }, { "description": "unknown formats ignore arrays", "data": [], - "valid": true + "valid": true, + "schema_id": "format_18_0" }, { "description": "unknown formats ignore booleans", "data": false, - "valid": true + "valid": true, + "schema_id": "format_18_0" }, { "description": "unknown formats ignore nulls", "data": null, - "valid": true + "valid": true, + "schema_id": "format_18_0" }, { "description": "unknown formats ignore strings", "data": "string", - "valid": true + "valid": true, + "schema_id": "format_18_0" } ] }, @@ -2705,8 +3179,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "format": "uri-reference" + "format": "uri-reference", + "$id": "format_19_0" } ] }, @@ -2714,77 +3188,92 @@ { "description": "all string formats ignore integers", "data": 12, - "valid": true + "valid": true, + "schema_id": "format_19_0" }, { "description": "all string formats ignore floats", "data": 13.7, - "valid": true + "valid": true, + "schema_id": "format_19_0" }, { "description": "all string formats ignore objects", "data": {}, - "valid": true + "valid": true, + "schema_id": "format_19_0" }, { "description": "all string formats ignore arrays", "data": [], - "valid": true + "valid": true, + "schema_id": "format_19_0" }, { "description": "all string formats ignore booleans", "data": false, - "valid": true + "valid": true, + "schema_id": "format_19_0" }, { "description": "all string formats ignore nulls", "data": null, - "valid": true + "valid": true, + "schema_id": "format_19_0" }, { "description": "a valid URI", "data": "http://foo.bar/?baz=qux#quux", - "valid": true + "valid": true, + "schema_id": "format_19_0" }, { "description": "a valid protocol-relative URI Reference", "data": "//foo.bar/?baz=qux#quux", - "valid": true + "valid": true, + "schema_id": "format_19_0" }, { "description": "a valid relative URI Reference", "data": "/abc", - "valid": true + "valid": true, + "schema_id": "format_19_0" }, { "description": "an invalid URI Reference", "data": "\\\\WINDOWS\\fileshare", - "valid": false + "valid": false, + "schema_id": "format_19_0" }, { "description": "a valid URI Reference", "data": "abc", - "valid": true + "valid": true, + "schema_id": "format_19_0" }, { "description": "a valid URI fragment", "data": "#fragment", - "valid": true + "valid": true, + "schema_id": "format_19_0" }, { "description": "an invalid URI fragment", "data": "#frag\\ment", - "valid": false + "valid": false, + "schema_id": "format_19_0" }, { "description": "unescaped non US-ASCII characters", "data": "/foobar®.txt", - "valid": false + "valid": false, + "schema_id": "format_19_0" }, { "description": "invalid backslash character", "data": "https://example.org/foobar\\.txt", - "valid": false + "valid": false, + "schema_id": "format_19_0" } ] }, @@ -2793,8 +3282,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "format": "uri-template" + "format": "uri-template", + "$id": "format_20_0" } ] }, @@ -2802,52 +3291,62 @@ { "description": "all string formats ignore integers", "data": 12, - "valid": true + "valid": true, + "schema_id": "format_20_0" }, { "description": "all string formats ignore floats", "data": 13.7, - "valid": true + "valid": true, + "schema_id": "format_20_0" }, { "description": "all string formats ignore objects", "data": {}, - "valid": true + "valid": true, + "schema_id": "format_20_0" }, { "description": "all string formats ignore arrays", "data": [], - "valid": true + "valid": true, + "schema_id": "format_20_0" }, { "description": "all string formats ignore booleans", "data": false, - "valid": true + "valid": true, + "schema_id": "format_20_0" }, { "description": "all string formats ignore nulls", "data": null, - "valid": true + "valid": true, + "schema_id": "format_20_0" }, { "description": "a valid uri-template", "data": "http://example.com/dictionary/{term:1}/{term}", - "valid": true + "valid": true, + "schema_id": "format_20_0" }, { "description": "an invalid uri-template", "data": "http://example.com/dictionary/{term:1}/{term", - "valid": false + "valid": false, + "schema_id": "format_20_0" }, { "description": "a valid uri-template without variables", "data": "http://example.com/dictionary", - "valid": true + "valid": true, + "schema_id": "format_20_0" }, { "description": "a valid relative uri-template", "data": "dictionary/{term:1}/{term}", - "valid": true + "valid": true, + "schema_id": "format_20_0" } ] }, @@ -2856,8 +3355,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "format": "uri" + "format": "uri", + "$id": "format_21_0" } ] }, @@ -2865,182 +3364,218 @@ { "description": "all string formats ignore integers", "data": 12, - "valid": true + "valid": true, + "schema_id": "format_21_0" }, { "description": "all string formats ignore floats", "data": 13.7, - "valid": true + "valid": true, + "schema_id": "format_21_0" }, { "description": "all string formats ignore objects", "data": {}, - "valid": true + "valid": true, + "schema_id": "format_21_0" }, { "description": "all string formats ignore arrays", "data": [], - "valid": true + "valid": true, + "schema_id": "format_21_0" }, { "description": "all string formats ignore booleans", "data": false, - "valid": true + "valid": true, + "schema_id": "format_21_0" }, { "description": "all string formats ignore nulls", "data": null, - "valid": true + "valid": true, + "schema_id": "format_21_0" }, { "description": "a valid URL with anchor tag", "data": "http://foo.bar/?baz=qux#quux", - "valid": true + "valid": true, + "schema_id": "format_21_0" }, { "description": "a valid URL with anchor tag and parentheses", "data": "http://foo.com/blah_(wikipedia)_blah#cite-1", - "valid": true + "valid": true, + "schema_id": "format_21_0" }, { "description": "a valid URL with URL-encoded stuff", "data": "http://foo.bar/?q=Test%20URL-encoded%20stuff", - "valid": true + "valid": true, + "schema_id": "format_21_0" }, { "description": "a valid puny-coded URL ", "data": "http://xn--nw2a.xn--j6w193g/", - "valid": true + "valid": true, + "schema_id": "format_21_0" }, { "description": "a valid URL with many special characters", "data": "http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com", - "valid": true + "valid": true, + "schema_id": "format_21_0" }, { "description": "a valid URL based on IPv4", "data": "http://223.255.255.254", - "valid": true + "valid": true, + "schema_id": "format_21_0" }, { "description": "a valid URL with ftp scheme", "data": "ftp://ftp.is.co.za/rfc/rfc1808.txt", - "valid": true + "valid": true, + "schema_id": "format_21_0" }, { "description": "a valid URL for a simple text file", "data": "http://www.ietf.org/rfc/rfc2396.txt", - "valid": true + "valid": true, + "schema_id": "format_21_0" }, { "description": "a valid URL ", "data": "ldap://[2001:db8::7]/c=GB?objectClass?one", - "valid": true + "valid": true, + "schema_id": "format_21_0" }, { "description": "a valid mailto URI", "data": "mailto:John.Doe@example.com", - "valid": true + "valid": true, + "schema_id": "format_21_0" }, { "description": "a valid newsgroup URI", "data": "news:comp.infosystems.www.servers.unix", - "valid": true + "valid": true, + "schema_id": "format_21_0" }, { "description": "a valid tel URI", "data": "tel:+1-816-555-1212", - "valid": true + "valid": true, + "schema_id": "format_21_0" }, { "description": "a valid URN", "data": "urn:oasis:names:specification:docbook:dtd:xml:4.1.2", - "valid": true + "valid": true, + "schema_id": "format_21_0" }, { "description": "an invalid protocol-relative URI Reference", "data": "//foo.bar/?baz=qux#quux", - "valid": false + "valid": false, + "schema_id": "format_21_0" }, { "description": "an invalid relative URI Reference", "data": "/abc", - "valid": false + "valid": false, + "schema_id": "format_21_0" }, { "description": "an invalid URI", "data": "\\\\WINDOWS\\fileshare", - "valid": false + "valid": false, + "schema_id": "format_21_0" }, { "description": "an invalid URI though valid URI reference", "data": "abc", - "valid": false + "valid": false, + "schema_id": "format_21_0" }, { "description": "an invalid URI with spaces", "data": "http:// shouldfail.com", - "valid": false + "valid": false, + "schema_id": "format_21_0" }, { "description": "an invalid URI with spaces and missing scheme", "data": ":// should fail", - "valid": false + "valid": false, + "schema_id": "format_21_0" }, { "description": "an invalid URI with comma in scheme", "data": "bar,baz:foo", - "valid": false + "valid": false, + "schema_id": "format_21_0" }, { "description": "invalid userinfo", "data": "https://[@example.org/test.txt", - "valid": false + "valid": false, + "schema_id": "format_21_0" }, { "description": "unescaped non US-ASCII characters", "data": "https://example.org/foobar®.txt", - "valid": false + "valid": false, + "schema_id": "format_21_0" }, { "description": "invalid backslash character", "data": "https://example.org/foobar\\.txt", - "valid": false + "valid": false, + "schema_id": "format_21_0" }, { "description": "invalid \" character", "data": "https://example.org/foobar\".txt", - "valid": false + "valid": false, + "schema_id": "format_21_0" }, { "description": "invalid <> characters", "data": "https://example.org/foobar<>.txt", - "valid": false + "valid": false, + "schema_id": "format_21_0" }, { "description": "invalid {} characters", "data": "https://example.org/foobar{}.txt", - "valid": false + "valid": false, + "schema_id": "format_21_0" }, { "description": "invalid ^ character", "data": "https://example.org/foobar^.txt", - "valid": false + "valid": false, + "schema_id": "format_21_0" }, { "description": "invalid ` character", "data": "https://example.org/foobar`.txt", - "valid": false + "valid": false, + "schema_id": "format_21_0" }, { "description": "invalid SPACE character", "data": "https://example.org/foo bar.txt", - "valid": false + "valid": false, + "schema_id": "format_21_0" }, { "description": "invalid | character", "data": "https://example.org/foobar|.txt", - "valid": false + "valid": false, + "schema_id": "format_21_0" } ] }, @@ -3049,8 +3584,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "format": "uuid" + "format": "uuid", + "$id": "format_22_0" } ] }, @@ -3058,112 +3593,134 @@ { "description": "all string formats ignore integers", "data": 12, - "valid": true + "valid": true, + "schema_id": "format_22_0" }, { "description": "all string formats ignore floats", "data": 13.7, - "valid": true + "valid": true, + "schema_id": "format_22_0" }, { "description": "all string formats ignore objects", "data": {}, - "valid": true + "valid": true, + "schema_id": "format_22_0" }, { "description": "all string formats ignore arrays", "data": [], - "valid": true + "valid": true, + "schema_id": "format_22_0" }, { "description": "all string formats ignore booleans", "data": false, - "valid": true + "valid": true, + "schema_id": "format_22_0" }, { "description": "all string formats ignore nulls", "data": null, - "valid": true + "valid": true, + "schema_id": "format_22_0" }, { "description": "all upper-case", "data": "2EB8AA08-AA98-11EA-B4AA-73B441D16380", - "valid": true + "valid": true, + "schema_id": "format_22_0" }, { "description": "all lower-case", "data": "2eb8aa08-aa98-11ea-b4aa-73b441d16380", - "valid": true + "valid": true, + "schema_id": "format_22_0" }, { "description": "mixed case", "data": "2eb8aa08-AA98-11ea-B4Aa-73B441D16380", - "valid": true + "valid": true, + "schema_id": "format_22_0" }, { "description": "all zeroes is valid", "data": "00000000-0000-0000-0000-000000000000", - "valid": true + "valid": true, + "schema_id": "format_22_0" }, { "description": "wrong length", "data": "2eb8aa08-aa98-11ea-b4aa-73b441d1638", - "valid": false + "valid": false, + "schema_id": "format_22_0" }, { "description": "missing section", "data": "2eb8aa08-aa98-11ea-73b441d16380", - "valid": false + "valid": false, + "schema_id": "format_22_0" }, { "description": "bad characters (not hex)", "data": "2eb8aa08-aa98-11ea-b4ga-73b441d16380", - "valid": false + "valid": false, + "schema_id": "format_22_0" }, { "description": "no dashes", "data": "2eb8aa08aa9811eab4aa73b441d16380", - "valid": false + "valid": false, + "schema_id": "format_22_0" }, { "description": "too few dashes", "data": "2eb8aa08aa98-11ea-b4aa73b441d16380", - "valid": false + "valid": false, + "schema_id": "format_22_0" }, { "description": "too many dashes", "data": "2eb8-aa08-aa98-11ea-b4aa73b44-1d16380", - "valid": false + "valid": false, + "schema_id": "format_22_0" }, { "description": "dashes in the wrong spot", "data": "2eb8aa08aa9811eab4aa73b441d16380----", - "valid": false + "valid": false, + "schema_id": "format_22_0" }, { "description": "shifted dashes", "data": "2eb8aa0-8aa98-11e-ab4aa7-3b441d16380", - "valid": false + "valid": false, + "schema_id": "format_22_0" }, { "description": "valid version 4", "data": "98d80576-482e-427f-8434-7f86890ab222", - "valid": true + "valid": true, + "schema_id": "format_22_0" }, { "description": "valid version 5", "data": "99c17cbb-656f-564a-940f-1a4568f03487", - "valid": true + "valid": true, + "schema_id": "format_22_0" }, { "description": "hypothetical version 6", "data": "99c17cbb-656f-664a-940f-1a4568f03487", - "valid": true + "valid": true, + "schema_id": "format_22_0" }, { "description": "hypothetical version 15", "data": "99c17cbb-656f-f64a-940f-1a4568f03487", - "valid": true + "valid": true, + "schema_id": "format_22_0" } ] }, @@ -3172,8 +3729,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "format": "period" + "format": "period", + "$id": "format_23_0" } ] }, @@ -3181,27 +3738,32 @@ { "description": "valid period (start/duration)", "data": "2020-01-01T00:00:00Z/P1Y", - "valid": true + "valid": true, + "schema_id": "format_23_0" }, { "description": "valid period (duration/end)", "data": "P1Y/2021-01-01T00:00:00Z", - "valid": true + "valid": true, + "schema_id": "format_23_0" }, { "description": "valid period (start/end)", "data": "2020-01-01T00:00:00Z/2021-01-01T00:00:00Z", - "valid": true + "valid": true, + "schema_id": "format_23_0" }, { "description": "invalid period (missing slash)", "data": "2020-01-01T00:00:00ZP1Y", - "valid": false + "valid": false, + "schema_id": "format_23_0" }, { "description": "ignores non-strings", "data": 123, - "valid": true + "valid": true, + "schema_id": "format_23_0" } ] } diff --git a/tests/fixtures/if-then-else.json b/tests/fixtures/if-then-else.json index e4f2b33..5f724d2 100644 --- a/tests/fixtures/if-then-else.json +++ b/tests/fixtures/if-then-else.json @@ -4,10 +4,10 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "if": { "const": 0 - } + }, + "$id": "if-then-else_0_0" } ] }, @@ -15,12 +15,14 @@ { "description": "valid when valid against lone if", "data": 0, - "valid": true + "valid": true, + "schema_id": "if-then-else_0_0" }, { "description": "valid when invalid against lone if", "data": "hello", - "valid": true + "valid": true, + "schema_id": "if-then-else_0_0" } ] }, @@ -29,10 +31,10 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "then": { "const": 0 - } + }, + "$id": "if-then-else_1_0" } ] }, @@ -40,12 +42,14 @@ { "description": "valid when valid against lone then", "data": 0, - "valid": true + "valid": true, + "schema_id": "if-then-else_1_0" }, { "description": "valid when invalid against lone then", "data": "hello", - "valid": true + "valid": true, + "schema_id": "if-then-else_1_0" } ] }, @@ -54,10 +58,10 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "else": { "const": 0 - } + }, + "$id": "if-then-else_2_0" } ] }, @@ -65,12 +69,14 @@ { "description": "valid when valid against lone else", "data": 0, - "valid": true + "valid": true, + "schema_id": "if-then-else_2_0" }, { "description": "valid when invalid against lone else", "data": "hello", - "valid": true + "valid": true, + "schema_id": "if-then-else_2_0" } ] }, @@ -79,13 +85,13 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "if": { "exclusiveMaximum": 0 }, "then": { "minimum": -10 - } + }, + "$id": "if-then-else_3_0" } ] }, @@ -93,17 +99,20 @@ { "description": "valid through then", "data": -1, - "valid": true + "valid": true, + "schema_id": "if-then-else_3_0" }, { "description": "invalid through then", "data": -100, - "valid": false + "valid": false, + "schema_id": "if-then-else_3_0" }, { "description": "valid when if test fails", "data": 3, - "valid": true + "valid": true, + "schema_id": "if-then-else_3_0" } ] }, @@ -112,13 +121,13 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "if": { "exclusiveMaximum": 0 }, "else": { "multipleOf": 2 - } + }, + "$id": "if-then-else_4_0" } ] }, @@ -126,17 +135,20 @@ { "description": "valid when if test passes", "data": -1, - "valid": true + "valid": true, + "schema_id": "if-then-else_4_0" }, { "description": "valid through else", "data": 4, - "valid": true + "valid": true, + "schema_id": "if-then-else_4_0" }, { "description": "invalid through else", "data": 3, - "valid": false + "valid": false, + "schema_id": "if-then-else_4_0" } ] }, @@ -145,7 +157,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "if": { "exclusiveMaximum": 0 }, @@ -154,7 +165,8 @@ }, "else": { "multipleOf": 2 - } + }, + "$id": "if-then-else_5_0" } ] }, @@ -162,22 +174,26 @@ { "description": "valid through then", "data": -1, - "valid": true + "valid": true, + "schema_id": "if-then-else_5_0" }, { "description": "invalid through then", "data": -100, - "valid": false + "valid": false, + "schema_id": "if-then-else_5_0" }, { "description": "valid through else", "data": 4, - "valid": true + "valid": true, + "schema_id": "if-then-else_5_0" }, { "description": "invalid through else", "data": 3, - "valid": false + "valid": false, + "schema_id": "if-then-else_5_0" } ] }, @@ -186,7 +202,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "allOf": [ { "if": { @@ -203,7 +218,8 @@ "multipleOf": 2 } } - ] + ], + "$id": "if-then-else_6_0" } ] }, @@ -211,12 +227,14 @@ { "description": "valid, but would have been invalid through then", "data": -100, - "valid": true + "valid": true, + "schema_id": "if-then-else_6_0" }, { "description": "valid, but would have been invalid through else", "data": 3, - "valid": true + "valid": true, + "schema_id": "if-then-else_6_0" } ] }, @@ -225,14 +243,14 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "if": true, "then": { "const": "then" }, "else": { "const": "else" - } + }, + "$id": "if-then-else_7_0" } ] }, @@ -240,12 +258,14 @@ { "description": "boolean schema true in if always chooses the then path (valid)", "data": "then", - "valid": true + "valid": true, + "schema_id": "if-then-else_7_0" }, { "description": "boolean schema true in if always chooses the then path (invalid)", "data": "else", - "valid": false + "valid": false, + "schema_id": "if-then-else_7_0" } ] }, @@ -254,14 +274,14 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "if": false, "then": { "const": "then" }, "else": { "const": "else" - } + }, + "$id": "if-then-else_8_0" } ] }, @@ -269,12 +289,14 @@ { "description": "boolean schema false in if always chooses the else path (invalid)", "data": "then", - "valid": false + "valid": false, + "schema_id": "if-then-else_8_0" }, { "description": "boolean schema false in if always chooses the else path (valid)", "data": "else", - "valid": true + "valid": true, + "schema_id": "if-then-else_8_0" } ] }, @@ -283,7 +305,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "then": { "const": "yes" }, @@ -292,7 +313,8 @@ }, "if": { "maxLength": 4 - } + }, + "$id": "if-then-else_9_0" } ] }, @@ -300,22 +322,26 @@ { "description": "yes redirects to then and passes", "data": "yes", - "valid": true + "valid": true, + "schema_id": "if-then-else_9_0" }, { "description": "other redirects to else and passes", "data": "other", - "valid": true + "valid": true, + "schema_id": "if-then-else_9_0" }, { "description": "no redirects to then and fails", "data": "no", - "valid": false + "valid": false, + "schema_id": "if-then-else_9_0" }, { "description": "invalid redirects to else and fails", "data": "invalid", - "valid": false + "valid": false, + "schema_id": "if-then-else_9_0" } ] }, @@ -327,7 +353,8 @@ "if": { "const": 1 }, - "then": false + "then": false, + "$id": "if-then-else_10_0" } ] }, @@ -335,12 +362,14 @@ { "description": "matches if → then=false → invalid", "data": 1, - "valid": false + "valid": false, + "schema_id": "if-then-else_10_0" }, { "description": "does not match if → then ignored → valid", "data": 2, - "valid": true + "valid": true, + "schema_id": "if-then-else_10_0" } ] }, @@ -352,7 +381,8 @@ "if": { "const": 1 }, - "else": false + "else": false, + "$id": "if-then-else_11_0" } ] }, @@ -360,12 +390,14 @@ { "description": "matches if → else ignored → valid", "data": 1, - "valid": true + "valid": true, + "schema_id": "if-then-else_11_0" }, { "description": "does not match if → else executes → invalid", "data": 2, - "valid": false + "valid": false, + "schema_id": "if-then-else_11_0" } ] }, @@ -374,7 +406,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "if": { "properties": { "foo": { @@ -395,7 +426,8 @@ "bar" ] }, - "extensible": true + "extensible": true, + "$id": "if-then-else_12_0" } ] }, @@ -407,7 +439,8 @@ "bar": 2, "extra": "prop" }, - "valid": true + "valid": true, + "schema_id": "if-then-else_12_0" } ] }, @@ -416,7 +449,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "if": { "properties": { "foo": { @@ -433,7 +465,8 @@ "const": 2 } } - } + }, + "$id": "if-then-else_13_0" } ] }, @@ -444,7 +477,8 @@ "foo": 1, "bar": 2 }, - "valid": true + "valid": true, + "schema_id": "if-then-else_13_0" }, { "description": "fails on extra property z explicitly", @@ -453,7 +487,8 @@ "bar": 2, "z": 3 }, - "valid": false + "valid": false, + "schema_id": "if-then-else_13_0" } ] } diff --git a/tests/fixtures/items.json b/tests/fixtures/items.json index fc54901..fa5479c 100644 --- a/tests/fixtures/items.json +++ b/tests/fixtures/items.json @@ -4,10 +4,10 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "items": { "type": "integer" - } + }, + "$id": "items_0_0" } ] }, @@ -19,7 +19,8 @@ 2, 3 ], - "valid": true + "valid": true, + "schema_id": "items_0_0" }, { "description": "wrong type of items", @@ -27,14 +28,16 @@ 1, "x" ], - "valid": false + "valid": false, + "schema_id": "items_0_0" }, { "description": "non-arrays are invalid", "data": { "foo": "bar" }, - "valid": false + "valid": false, + "schema_id": "items_0_0" }, { "description": "JavaScript pseudo-arrays are invalid", @@ -42,7 +45,8 @@ "0": "invalid", "length": 1 }, - "valid": false + "valid": false, + "schema_id": "items_0_0" } ] }, @@ -51,8 +55,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "items": true + "items": true, + "$id": "items_1_0" } ] }, @@ -64,12 +68,14 @@ "foo", true ], - "valid": true + "valid": true, + "schema_id": "items_1_0" }, { "description": "empty array is valid", "data": [], - "valid": true + "valid": true, + "schema_id": "items_1_0" } ] }, @@ -78,8 +84,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "items": false + "items": false, + "$id": "items_2_0" } ] }, @@ -91,12 +97,14 @@ "foo", true ], - "valid": false + "valid": false, + "schema_id": "items_2_0" }, { "description": "empty array is valid", "data": [], - "valid": true + "valid": true, + "schema_id": "items_2_0" } ] }, @@ -105,39 +113,39 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$defs": { - "item": { - "type": "array", - "items": false, - "prefixItems": [ - { - "$ref": "#/$defs/sub-item" - }, - { - "$ref": "#/$defs/sub-item" - } - ] - }, - "sub-item": { - "type": "object", - "required": [ - "foo" - ] - } - }, "type": "array", "items": false, "prefixItems": [ { - "$ref": "#/$defs/item" + "$ref": "item" }, { - "$ref": "#/$defs/item" + "$ref": "item" }, { - "$ref": "#/$defs/item" + "$ref": "item" } + ], + "$id": "items_3_0" + }, + { + "$id": "item", + "type": "array", + "items": false, + "prefixItems": [ + { + "$ref": "sub-item" + }, + { + "$ref": "sub-item" + } + ] + }, + { + "$id": "sub-item", + "type": "object", + "required": [ + "foo" ] } ] @@ -171,7 +179,8 @@ } ] ], - "valid": false + "valid": false, + "schema_id": "items_3_0" }, { "description": "too many items", @@ -209,7 +218,8 @@ } ] ], - "valid": false + "valid": false, + "schema_id": "items_3_0" }, { "description": "too many sub-items", @@ -242,7 +252,8 @@ } ] ], - "valid": false + "valid": false, + "schema_id": "items_3_0" }, { "description": "wrong item", @@ -267,7 +278,8 @@ } ] ], - "valid": false + "valid": false, + "schema_id": "items_3_0" }, { "description": "wrong sub-item", @@ -295,7 +307,8 @@ } ] ], - "valid": false + "valid": false, + "schema_id": "items_3_0" }, { "description": "fewer items is invalid", @@ -311,7 +324,8 @@ } ] ], - "valid": false + "valid": false, + "schema_id": "items_3_0" } ] }, @@ -320,7 +334,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "array", "items": { "type": "array", @@ -333,7 +346,8 @@ } } } - } + }, + "$id": "items_4_0" } ] }, @@ -370,7 +384,8 @@ ] ] ], - "valid": true + "valid": true, + "schema_id": "items_4_0" }, { "description": "nested array with invalid type", @@ -404,7 +419,8 @@ ] ] ], - "valid": false + "valid": false, + "schema_id": "items_4_0" }, { "description": "not deep enough", @@ -432,7 +448,8 @@ ] ] ], - "valid": false + "valid": false, + "schema_id": "items_4_0" } ] }, @@ -441,13 +458,13 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "prefixItems": [ {}, {}, {} ], - "items": false + "items": false, + "$id": "items_5_0" } ] }, @@ -455,14 +472,16 @@ { "description": "empty array", "data": [], - "valid": true + "valid": true, + "schema_id": "items_5_0" }, { "description": "fewer number of items present (1)", "data": [ 1 ], - "valid": true + "valid": true, + "schema_id": "items_5_0" }, { "description": "fewer number of items present (2)", @@ -470,7 +489,8 @@ 1, 2 ], - "valid": true + "valid": true, + "schema_id": "items_5_0" }, { "description": "equal number of items present", @@ -479,7 +499,8 @@ 2, 3 ], - "valid": true + "valid": true, + "schema_id": "items_5_0" }, { "description": "additional items are not permitted", @@ -489,7 +510,8 @@ 3, 4 ], - "valid": false + "valid": false, + "schema_id": "items_5_0" } ] }, @@ -498,7 +520,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "allOf": [ { "prefixItems": [ @@ -510,7 +531,8 @@ ], "items": { "minimum": 5 - } + }, + "$id": "items_6_0" } ] }, @@ -521,7 +543,8 @@ 3, 5 ], - "valid": false + "valid": false, + "schema_id": "items_6_0" }, { "description": "prefixItems in allOf does not constrain items, valid case", @@ -529,7 +552,8 @@ 5, 5 ], - "valid": true + "valid": true, + "schema_id": "items_6_0" } ] }, @@ -538,7 +562,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "prefixItems": [ { "type": "string" @@ -546,7 +569,8 @@ ], "items": { "type": "integer" - } + }, + "$id": "items_7_0" } ] }, @@ -558,7 +582,8 @@ 2, 3 ], - "valid": true + "valid": true, + "schema_id": "items_7_0" }, { "description": "wrong type of second item", @@ -566,7 +591,8 @@ "x", "y" ], - "valid": false + "valid": false, + "schema_id": "items_7_0" } ] }, @@ -575,11 +601,11 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "prefixItems": [ {} ], - "items": false + "items": false, + "$id": "items_8_0" } ] }, @@ -591,14 +617,16 @@ "bar", 37 ], - "valid": false + "valid": false, + "schema_id": "items_8_0" }, { "description": "valid instance", "data": [ null ], - "valid": true + "valid": true, + "schema_id": "items_8_0" } ] }, @@ -607,10 +635,10 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "items": { "type": "null" - } + }, + "$id": "items_9_0" } ] }, @@ -620,7 +648,8 @@ "data": [ null ], - "valid": true + "valid": true, + "schema_id": "items_9_0" } ] }, @@ -629,9 +658,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "items": false, - "extensible": true + "extensible": true, + "$id": "items_10_0" } ] }, @@ -641,7 +670,8 @@ "data": [ 1 ], - "valid": false + "valid": false, + "schema_id": "items_10_0" } ] }, @@ -650,11 +680,11 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "items": { "minimum": 5 }, - "extensible": true + "extensible": true, + "$id": "items_11_0" } ] }, @@ -665,14 +695,16 @@ 5, 6 ], - "valid": true + "valid": true, + "schema_id": "items_11_0" }, { "description": "invalid item (less than min) is invalid even with extensible: true", "data": [ 4 ], - "valid": false + "valid": false, + "schema_id": "items_11_0" } ] }, @@ -681,9 +713,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "array", - "extensible": true + "extensible": true, + "$id": "items_12_0" } ] }, @@ -691,7 +723,8 @@ { "description": "empty array is valid", "data": [], - "valid": true + "valid": true, + "schema_id": "items_12_0" }, { "description": "array with items is valid (extensible)", @@ -699,7 +732,8 @@ 1, "foo" ], - "valid": true + "valid": true, + "schema_id": "items_12_0" } ] }, @@ -708,9 +742,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "array", - "extensible": false + "extensible": false, + "$id": "items_13_0" } ] }, @@ -718,14 +752,16 @@ { "description": "empty array is valid", "data": [], - "valid": true + "valid": true, + "schema_id": "items_13_0" }, { "description": "array with items is invalid (strict)", "data": [ 1 ], - "valid": false + "valid": false, + "schema_id": "items_13_0" } ] }, @@ -734,11 +770,11 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "array", "items": { "extensible": true - } + }, + "$id": "items_14_0" } ] }, @@ -746,7 +782,8 @@ { "description": "empty array is valid", "data": [], - "valid": true + "valid": true, + "schema_id": "items_14_0" }, { "description": "array with items is valid (items explicitly allowed to be anything extensible)", @@ -755,7 +792,8 @@ "foo", {} ], - "valid": true + "valid": true, + "schema_id": "items_14_0" } ] }, @@ -764,12 +802,12 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "array", "items": { "type": "object", "extensible": false - } + }, + "$id": "items_15_0" } ] }, @@ -779,14 +817,16 @@ "data": [ {} ], - "valid": true + "valid": true, + "schema_id": "items_15_0" }, { "description": "array with strict object items is valid", "data": [ {} ], - "valid": true + "valid": true, + "schema_id": "items_15_0" }, { "description": "array with invalid strict object items (extra property)", @@ -795,7 +835,8 @@ "extra": 1 } ], - "valid": false + "valid": false, + "schema_id": "items_15_0" } ] } diff --git a/tests/fixtures/masking.json b/tests/fixtures/masking.json deleted file mode 100644 index dad4082..0000000 --- a/tests/fixtures/masking.json +++ /dev/null @@ -1,187 +0,0 @@ -[ - { - "description": "Masking Properties", - "database": { - "schemas": [ - { - "$id": "mask_properties", - "type": "object", - "properties": { - "foo": { - "type": "string" - }, - "bar": { - "type": "integer" - } - }, - "required": [ - "foo" - ], - "extensible": false - } - ] - }, - "tests": [ - { - "description": "Keep valid properties", - "data": { - "foo": "a", - "bar": 1 - }, - "valid": true, - "expected": { - "foo": "a", - "bar": 1 - } - }, - { - "description": "Remove unknown properties", - "data": { - "foo": "a", - "baz": true - }, - "valid": true, - "expected": { - "foo": "a" - } - }, - { - "description": "Keep valid properties with unknown", - "data": { - "foo": "a", - "bar": 1, - "baz": true - }, - "valid": true, - "expected": { - "foo": "a", - "bar": 1 - } - } - ] - }, - { - "description": "Masking Nested Objects", - "database": { - "schemas": [ - { - "$id": "mask_nested", - "type": "object", - "properties": { - "meta": { - "type": "object", - "properties": { - "id": { - "type": "integer" - } - }, - "extensible": false - } - }, - "extensible": false - } - ] - }, - "tests": [ - { - "description": "Mask nested object", - "data": { - "meta": { - "id": 1, - "extra": "x" - }, - "top_extra": "y" - }, - "valid": true, - "expected": { - "meta": { - "id": 1 - } - } - } - ] - }, - { - "description": "Masking Arrays", - "database": { - "schemas": [ - { - "$id": "mask_arrays", - "type": "object", - "properties": { - "tags": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "extensible": false - } - ] - }, - "tests": [ - { - "description": "Arrays are kept (items are valid)", - "data": { - "tags": [ - "a", - "b" - ] - }, - "valid": true, - "expected": { - "tags": [ - "a", - "b" - ] - } - } - ] - }, - { - "description": "Masking Tuple Arrays (prefixItems)", - "database": { - "schemas": [ - { - "$id": "mask_tuple", - "type": "object", - "properties": { - "coord": { - "type": "array", - "prefixItems": [ - { - "type": "number" - }, - { - "type": "number" - } - ] - } - }, - "extensible": false - } - ] - }, - "tests": [ - { - "description": "Extra tuple items removed", - "data": { - "coord": [ - 1, - 2, - 3, - "extra" - ] - }, - "valid": true, - "expected": { - "coord": [ - 1, - 2 - ] - } - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/maxContains.json b/tests/fixtures/maxContains.json index e81a60a..dffcfb3 100644 --- a/tests/fixtures/maxContains.json +++ b/tests/fixtures/maxContains.json @@ -4,9 +4,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "maxContains": 1, - "extensible": true + "extensible": true, + "$id": "maxContains_0_0" } ] }, @@ -16,7 +16,8 @@ "data": [ 1 ], - "valid": true + "valid": true, + "schema_id": "maxContains_0_0" }, { "description": "two items still valid against lone maxContains", @@ -24,7 +25,8 @@ 1, 2 ], - "valid": true + "valid": true, + "schema_id": "maxContains_0_0" } ] }, @@ -33,12 +35,12 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "contains": { "const": 1 }, "maxContains": 1, - "extensible": true + "extensible": true, + "$id": "maxContains_1_0" } ] }, @@ -46,14 +48,16 @@ { "description": "empty data", "data": [], - "valid": false + "valid": false, + "schema_id": "maxContains_1_0" }, { "description": "all elements match, valid maxContains", "data": [ 1 ], - "valid": true + "valid": true, + "schema_id": "maxContains_1_0" }, { "description": "all elements match, invalid maxContains", @@ -61,7 +65,8 @@ 1, 1 ], - "valid": false + "valid": false, + "schema_id": "maxContains_1_0" }, { "description": "some elements match, valid maxContains", @@ -69,7 +74,8 @@ 1, 2 ], - "valid": true + "valid": true, + "schema_id": "maxContains_1_0" }, { "description": "some elements match, invalid maxContains", @@ -78,7 +84,8 @@ 2, 1 ], - "valid": false + "valid": false, + "schema_id": "maxContains_1_0" } ] }, @@ -87,12 +94,12 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "contains": { "const": 1 }, - "maxContains": 1.0, - "extensible": true + "maxContains": 1, + "extensible": true, + "$id": "maxContains_2_0" } ] }, @@ -102,7 +109,8 @@ "data": [ 1 ], - "valid": true + "valid": true, + "schema_id": "maxContains_2_0" }, { "description": "too many elements match, invalid maxContains", @@ -110,7 +118,8 @@ 1, 1 ], - "valid": false + "valid": false, + "schema_id": "maxContains_2_0" } ] }, @@ -119,13 +128,13 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "contains": { "const": 1 }, "minContains": 1, "maxContains": 3, - "extensible": true + "extensible": true, + "$id": "maxContains_3_0" } ] }, @@ -133,7 +142,8 @@ { "description": "actual < minContains < maxContains", "data": [], - "valid": false + "valid": false, + "schema_id": "maxContains_3_0" }, { "description": "minContains < actual < maxContains", @@ -141,7 +151,8 @@ 1, 1 ], - "valid": true + "valid": true, + "schema_id": "maxContains_3_0" }, { "description": "minContains < maxContains < actual", @@ -151,7 +162,8 @@ 1, 1 ], - "valid": false + "valid": false, + "schema_id": "maxContains_3_0" } ] }, @@ -160,12 +172,12 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "contains": { "const": 1 }, "maxContains": 1, - "extensible": true + "extensible": true, + "$id": "maxContains_4_0" } ] }, @@ -176,7 +188,8 @@ 1, 2 ], - "valid": true + "valid": true, + "schema_id": "maxContains_4_0" } ] } diff --git a/tests/fixtures/maxItems.json b/tests/fixtures/maxItems.json index 35547e2..c09ccab 100644 --- a/tests/fixtures/maxItems.json +++ b/tests/fixtures/maxItems.json @@ -4,9 +4,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "maxItems": 2, - "extensible": true + "extensible": true, + "$id": "maxItems_0_0" } ] }, @@ -16,7 +16,8 @@ "data": [ 1 ], - "valid": true + "valid": true, + "schema_id": "maxItems_0_0" }, { "description": "exact length is valid", @@ -24,7 +25,8 @@ 1, 2 ], - "valid": true + "valid": true, + "schema_id": "maxItems_0_0" }, { "description": "too long is invalid", @@ -33,12 +35,14 @@ 2, 3 ], - "valid": false + "valid": false, + "schema_id": "maxItems_0_0" }, { "description": "ignores non-arrays", "data": "foobar", - "valid": true + "valid": true, + "schema_id": "maxItems_0_0" } ] }, @@ -47,9 +51,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "maxItems": 2.0, - "extensible": true + "maxItems": 2, + "extensible": true, + "$id": "maxItems_1_0" } ] }, @@ -59,7 +63,8 @@ "data": [ 1 ], - "valid": true + "valid": true, + "schema_id": "maxItems_1_0" }, { "description": "too long is invalid", @@ -68,7 +73,8 @@ 2, 3 ], - "valid": false + "valid": false, + "schema_id": "maxItems_1_0" } ] }, @@ -77,9 +83,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "maxItems": 2, - "extensible": true + "extensible": true, + "$id": "maxItems_2_0" } ] }, @@ -91,7 +97,8 @@ 2, 3 ], - "valid": false + "valid": false, + "schema_id": "maxItems_2_0" } ] } diff --git a/tests/fixtures/maxLength.json b/tests/fixtures/maxLength.json index f4d55ac..b92a51b 100644 --- a/tests/fixtures/maxLength.json +++ b/tests/fixtures/maxLength.json @@ -4,8 +4,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "maxLength": 2 + "maxLength": 2, + "$id": "maxLength_0_0" } ] }, @@ -13,27 +13,32 @@ { "description": "shorter is valid", "data": "f", - "valid": true + "valid": true, + "schema_id": "maxLength_0_0" }, { "description": "exact length is valid", "data": "fo", - "valid": true + "valid": true, + "schema_id": "maxLength_0_0" }, { "description": "too long is invalid", "data": "foo", - "valid": false + "valid": false, + "schema_id": "maxLength_0_0" }, { "description": "ignores non-strings", "data": 100, - "valid": true + "valid": true, + "schema_id": "maxLength_0_0" }, { "description": "two graphemes is long enough", - "data": "\uD83D\uDCA9\uD83D\uDCA9", - "valid": true + "data": "💩💩", + "valid": true, + "schema_id": "maxLength_0_0" } ] }, @@ -42,8 +47,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "maxLength": 2.0 + "maxLength": 2, + "$id": "maxLength_1_0" } ] }, @@ -51,12 +56,14 @@ { "description": "shorter is valid", "data": "f", - "valid": true + "valid": true, + "schema_id": "maxLength_1_0" }, { "description": "too long is invalid", "data": "foo", - "valid": false + "valid": false, + "schema_id": "maxLength_1_0" } ] } diff --git a/tests/fixtures/maxProperties.json b/tests/fixtures/maxProperties.json index 4229901..de91855 100644 --- a/tests/fixtures/maxProperties.json +++ b/tests/fixtures/maxProperties.json @@ -4,9 +4,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "maxProperties": 2, - "extensible": true + "extensible": true, + "$id": "maxProperties_0_0" } ] }, @@ -16,7 +16,8 @@ "data": { "foo": 1 }, - "valid": true + "valid": true, + "schema_id": "maxProperties_0_0" }, { "description": "exact length is valid", @@ -24,7 +25,8 @@ "foo": 1, "bar": 2 }, - "valid": true + "valid": true, + "schema_id": "maxProperties_0_0" }, { "description": "too long is invalid", @@ -33,7 +35,8 @@ "bar": 2, "baz": 3 }, - "valid": false + "valid": false, + "schema_id": "maxProperties_0_0" }, { "description": "ignores arrays", @@ -42,17 +45,20 @@ 2, 3 ], - "valid": true + "valid": true, + "schema_id": "maxProperties_0_0" }, { "description": "ignores strings", "data": "foobar", - "valid": true + "valid": true, + "schema_id": "maxProperties_0_0" }, { "description": "ignores other non-objects", "data": 12, - "valid": true + "valid": true, + "schema_id": "maxProperties_0_0" } ] }, @@ -61,9 +67,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "maxProperties": 2.0, - "extensible": true + "maxProperties": 2, + "extensible": true, + "$id": "maxProperties_1_0" } ] }, @@ -73,7 +79,8 @@ "data": { "foo": 1 }, - "valid": true + "valid": true, + "schema_id": "maxProperties_1_0" }, { "description": "too long is invalid", @@ -82,7 +89,8 @@ "bar": 2, "baz": 3 }, - "valid": false + "valid": false, + "schema_id": "maxProperties_1_0" } ] }, @@ -91,9 +99,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "maxProperties": 0, - "extensible": true + "extensible": true, + "$id": "maxProperties_2_0" } ] }, @@ -101,14 +109,16 @@ { "description": "no properties is valid", "data": {}, - "valid": true + "valid": true, + "schema_id": "maxProperties_2_0" }, { "description": "one property is invalid", "data": { "foo": 1 }, - "valid": false + "valid": false, + "schema_id": "maxProperties_2_0" } ] }, @@ -117,9 +127,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "maxProperties": 2, - "extensible": true + "extensible": true, + "$id": "maxProperties_3_0" } ] }, @@ -131,14 +141,16 @@ "bar": 2, "baz": 3 }, - "valid": false + "valid": false, + "schema_id": "maxProperties_3_0" }, { "description": "extra property is valid if below maxProperties", "data": { "foo": 1 }, - "valid": true + "valid": true, + "schema_id": "maxProperties_3_0" } ] } diff --git a/tests/fixtures/maximum.json b/tests/fixtures/maximum.json index 8643998..ebbdc46 100644 --- a/tests/fixtures/maximum.json +++ b/tests/fixtures/maximum.json @@ -4,8 +4,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "maximum": 3.0 + "maximum": 3, + "$id": "maximum_0_0" } ] }, @@ -13,22 +13,26 @@ { "description": "below the maximum is valid", "data": 2.6, - "valid": true + "valid": true, + "schema_id": "maximum_0_0" }, { "description": "boundary point is valid", - "data": 3.0, - "valid": true + "data": 3, + "valid": true, + "schema_id": "maximum_0_0" }, { "description": "above the maximum is invalid", "data": 3.5, - "valid": false + "valid": false, + "schema_id": "maximum_0_0" }, { "description": "ignores non-numbers", "data": "x", - "valid": true + "valid": true, + "schema_id": "maximum_0_0" } ] }, @@ -37,8 +41,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "maximum": 300 + "maximum": 300, + "$id": "maximum_1_0" } ] }, @@ -46,22 +50,26 @@ { "description": "below the maximum is invalid", "data": 299.97, - "valid": true + "valid": true, + "schema_id": "maximum_1_0" }, { "description": "boundary point integer is valid", "data": 300, - "valid": true + "valid": true, + "schema_id": "maximum_1_0" }, { "description": "boundary point float is valid", - "data": 300.00, - "valid": true + "data": 300, + "valid": true, + "schema_id": "maximum_1_0" }, { "description": "above the maximum is invalid", "data": 300.5, - "valid": false + "valid": false, + "schema_id": "maximum_1_0" } ] } diff --git a/tests/fixtures/merge.json b/tests/fixtures/merge.json index 65703b7..d437931 100644 --- a/tests/fixtures/merge.json +++ b/tests/fixtures/merge.json @@ -4,22 +4,21 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$defs": { - "base": { - "properties": { - "base_prop": { - "type": "string" - } - } + "$id": "base_0", + "properties": { + "base_prop": { + "type": "string" } - }, - "$ref": "#/$defs/base", + } + }, + { + "$ref": "base_0", "properties": { "child_prop": { "type": "string" } - } + }, + "$id": "merge_0_0" } ] }, @@ -30,7 +29,8 @@ "base_prop": "a", "child_prop": "b" }, - "valid": true + "valid": true, + "schema_id": "merge_0_0" }, { "description": "invalid when base property has wrong type", @@ -44,7 +44,8 @@ "code": "TYPE_MISMATCH", "path": "/base_prop" } - ] + ], + "schema_id": "merge_0_0" } ] }, @@ -53,20 +54,18 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$defs": { - "base": { - "properties": { - "a": { - "type": "string" - } - }, - "required": [ - "a" - ] + "$id": "base_1", + "properties": { + "a": { + "type": "string" } }, - "$ref": "#/$defs/base", + "required": [ + "a" + ] + }, + { + "$ref": "base_1", "properties": { "b": { "type": "string" @@ -74,7 +73,8 @@ }, "required": [ "b" - ] + ], + "$id": "merge_1_0" } ] }, @@ -85,7 +85,8 @@ "a": "ok", "b": "ok" }, - "valid": true + "valid": true, + "schema_id": "merge_1_0" }, { "description": "invalid when base required missing", @@ -98,7 +99,8 @@ "code": "REQUIRED_FIELD_MISSING", "path": "/a" } - ] + ], + "schema_id": "merge_1_0" }, { "description": "invalid when child required missing", @@ -111,7 +113,8 @@ "code": "REQUIRED_FIELD_MISSING", "path": "/b" } - ] + ], + "schema_id": "merge_1_0" } ] }, @@ -120,25 +123,23 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$defs": { - "base": { - "properties": { - "trigger": { - "type": "string" - }, - "base_dep": { - "type": "string" - } - }, - "dependencies": { - "trigger": [ - "base_dep" - ] - } + "$id": "base_2", + "properties": { + "trigger": { + "type": "string" + }, + "base_dep": { + "type": "string" } }, - "$ref": "#/$defs/base", + "dependencies": { + "trigger": [ + "base_dep" + ] + } + }, + { + "$ref": "base_2", "properties": { "child_dep": { "type": "string" @@ -148,7 +149,8 @@ "trigger": [ "child_dep" ] - } + }, + "$id": "merge_2_0" } ] }, @@ -160,7 +162,8 @@ "base_dep": "ok", "child_dep": "ok" }, - "valid": true + "valid": true, + "schema_id": "merge_2_0" }, { "description": "invalid missing base dep", @@ -174,7 +177,8 @@ "code": "DEPENDENCY_FAILED", "path": "/base_dep" } - ] + ], + "schema_id": "merge_2_0" }, { "description": "invalid missing child dep", @@ -188,7 +192,8 @@ "code": "DEPENDENCY_FAILED", "path": "/child_dep" } - ] + ], + "schema_id": "merge_2_0" } ] }, @@ -197,24 +202,22 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$defs": { - "base": { - "properties": { - "a": { - "type": "string" - }, - "b": { - "type": "string" - } - }, - "form": [ - "a", - "b" - ] + "$id": "base_3", + "properties": { + "a": { + "type": "string" + }, + "b": { + "type": "string" } }, - "$ref": "#/$defs/base", + "form": [ + "a", + "b" + ] + }, + { + "$ref": "base_3", "properties": { "c": { "type": "string" @@ -222,7 +225,8 @@ }, "form": [ "c" - ] + ], + "$id": "merge_3_0" } ] }, @@ -235,7 +239,8 @@ "c": "ok" }, "valid": true, - "comment": "Verifies validator handles the unmerged metadata correctly (ignores it or handles replacement)" + "comment": "Verifies validator handles the unmerged metadata correctly (ignores it or handles replacement)", + "schema_id": "merge_3_0" } ] } diff --git a/tests/fixtures/minContains.json b/tests/fixtures/minContains.json index a4a0e74..3d21dc0 100644 --- a/tests/fixtures/minContains.json +++ b/tests/fixtures/minContains.json @@ -4,9 +4,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "minContains": 1, - "extensible": true + "extensible": true, + "$id": "minContains_0_0" } ] }, @@ -16,12 +16,14 @@ "data": [ 1 ], - "valid": true + "valid": true, + "schema_id": "minContains_0_0" }, { "description": "zero items still valid against lone minContains", "data": [], - "valid": true + "valid": true, + "schema_id": "minContains_0_0" } ] }, @@ -30,12 +32,12 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "contains": { "const": 1 }, "minContains": 1, - "extensible": true + "extensible": true, + "$id": "minContains_1_0" } ] }, @@ -43,21 +45,24 @@ { "description": "empty data", "data": [], - "valid": false + "valid": false, + "schema_id": "minContains_1_0" }, { "description": "no elements match", "data": [ 2 ], - "valid": false + "valid": false, + "schema_id": "minContains_1_0" }, { "description": "single element matches, valid minContains", "data": [ 1 ], - "valid": true + "valid": true, + "schema_id": "minContains_1_0" }, { "description": "some elements match, valid minContains", @@ -65,7 +70,8 @@ 1, 2 ], - "valid": true + "valid": true, + "schema_id": "minContains_1_0" }, { "description": "all elements match, valid minContains", @@ -73,7 +79,8 @@ 1, 1 ], - "valid": true + "valid": true, + "schema_id": "minContains_1_0" } ] }, @@ -82,12 +89,12 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "contains": { "const": 1 }, "minContains": 2, - "extensible": true + "extensible": true, + "$id": "minContains_2_0" } ] }, @@ -95,14 +102,16 @@ { "description": "empty data", "data": [], - "valid": false + "valid": false, + "schema_id": "minContains_2_0" }, { "description": "all elements match, invalid minContains", "data": [ 1 ], - "valid": false + "valid": false, + "schema_id": "minContains_2_0" }, { "description": "some elements match, invalid minContains", @@ -110,7 +119,8 @@ 1, 2 ], - "valid": false + "valid": false, + "schema_id": "minContains_2_0" }, { "description": "all elements match, valid minContains (exactly as needed)", @@ -118,7 +128,8 @@ 1, 1 ], - "valid": true + "valid": true, + "schema_id": "minContains_2_0" }, { "description": "all elements match, valid minContains (more than needed)", @@ -127,7 +138,8 @@ 1, 1 ], - "valid": true + "valid": true, + "schema_id": "minContains_2_0" }, { "description": "some elements match, valid minContains", @@ -136,7 +148,8 @@ 2, 1 ], - "valid": true + "valid": true, + "schema_id": "minContains_2_0" } ] }, @@ -145,12 +158,12 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "contains": { "const": 1 }, - "minContains": 2.0, - "extensible": true + "minContains": 2, + "extensible": true, + "$id": "minContains_3_0" } ] }, @@ -160,7 +173,8 @@ "data": [ 1 ], - "valid": false + "valid": false, + "schema_id": "minContains_3_0" }, { "description": "both elements match, valid minContains", @@ -168,7 +182,8 @@ 1, 1 ], - "valid": true + "valid": true, + "schema_id": "minContains_3_0" } ] }, @@ -177,13 +192,13 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "contains": { "const": 1 }, "maxContains": 2, "minContains": 2, - "extensible": true + "extensible": true, + "$id": "minContains_4_0" } ] }, @@ -191,14 +206,16 @@ { "description": "empty data", "data": [], - "valid": false + "valid": false, + "schema_id": "minContains_4_0" }, { "description": "all elements match, invalid minContains", "data": [ 1 ], - "valid": false + "valid": false, + "schema_id": "minContains_4_0" }, { "description": "all elements match, invalid maxContains", @@ -207,7 +224,8 @@ 1, 1 ], - "valid": false + "valid": false, + "schema_id": "minContains_4_0" }, { "description": "all elements match, valid maxContains and minContains", @@ -215,7 +233,8 @@ 1, 1 ], - "valid": true + "valid": true, + "schema_id": "minContains_4_0" } ] }, @@ -224,13 +243,13 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "contains": { "const": 1 }, "maxContains": 1, "minContains": 3, - "extensible": true + "extensible": true, + "$id": "minContains_5_0" } ] }, @@ -238,14 +257,16 @@ { "description": "empty data", "data": [], - "valid": false + "valid": false, + "schema_id": "minContains_5_0" }, { "description": "invalid minContains", "data": [ 1 ], - "valid": false + "valid": false, + "schema_id": "minContains_5_0" }, { "description": "invalid maxContains", @@ -254,7 +275,8 @@ 1, 1 ], - "valid": false + "valid": false, + "schema_id": "minContains_5_0" }, { "description": "invalid maxContains and minContains", @@ -262,7 +284,8 @@ 1, 1 ], - "valid": false + "valid": false, + "schema_id": "minContains_5_0" } ] }, @@ -271,12 +294,12 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "contains": { "const": 1 }, "minContains": 0, - "extensible": true + "extensible": true, + "$id": "minContains_6_0" } ] }, @@ -284,14 +307,16 @@ { "description": "empty data", "data": [], - "valid": true + "valid": true, + "schema_id": "minContains_6_0" }, { "description": "minContains = 0 makes contains always pass", "data": [ 2 ], - "valid": true + "valid": true, + "schema_id": "minContains_6_0" } ] }, @@ -300,13 +325,13 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "contains": { "const": 1 }, "minContains": 0, "maxContains": 1, - "extensible": true + "extensible": true, + "$id": "minContains_7_0" } ] }, @@ -314,14 +339,16 @@ { "description": "empty data", "data": [], - "valid": true + "valid": true, + "schema_id": "minContains_7_0" }, { "description": "not more than maxContains", "data": [ 1 ], - "valid": true + "valid": true, + "schema_id": "minContains_7_0" }, { "description": "too many", @@ -329,7 +356,8 @@ 1, 1 ], - "valid": false + "valid": false, + "schema_id": "minContains_7_0" } ] }, @@ -338,12 +366,12 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "contains": { "const": 1 }, "minContains": 1, - "extensible": true + "extensible": true, + "$id": "minContains_8_0" } ] }, @@ -354,7 +382,8 @@ 1, 2 ], - "valid": true + "valid": true, + "schema_id": "minContains_8_0" } ] } diff --git a/tests/fixtures/minItems.json b/tests/fixtures/minItems.json index ec28842..2cb5a2b 100644 --- a/tests/fixtures/minItems.json +++ b/tests/fixtures/minItems.json @@ -4,9 +4,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "minItems": 1, - "extensible": true + "extensible": true, + "$id": "minItems_0_0" } ] }, @@ -17,24 +17,28 @@ 1, 2 ], - "valid": true + "valid": true, + "schema_id": "minItems_0_0" }, { "description": "exact length is valid", "data": [ 1 ], - "valid": true + "valid": true, + "schema_id": "minItems_0_0" }, { "description": "too short is invalid", "data": [], - "valid": false + "valid": false, + "schema_id": "minItems_0_0" }, { "description": "ignores non-arrays", "data": "", - "valid": true + "valid": true, + "schema_id": "minItems_0_0" } ] }, @@ -43,9 +47,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "minItems": 1.0, - "extensible": true + "minItems": 1, + "extensible": true, + "$id": "minItems_1_0" } ] }, @@ -56,12 +60,14 @@ 1, 2 ], - "valid": true + "valid": true, + "schema_id": "minItems_1_0" }, { "description": "too short is invalid", "data": [], - "valid": false + "valid": false, + "schema_id": "minItems_1_0" } ] }, @@ -70,9 +76,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "minItems": 1, - "extensible": true + "extensible": true, + "$id": "minItems_2_0" } ] }, @@ -82,7 +88,8 @@ "data": [ 1 ], - "valid": true + "valid": true, + "schema_id": "minItems_2_0" } ] } diff --git a/tests/fixtures/minLength.json b/tests/fixtures/minLength.json index 1318eee..b1cfa72 100644 --- a/tests/fixtures/minLength.json +++ b/tests/fixtures/minLength.json @@ -4,8 +4,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "minLength": 2 + "minLength": 2, + "$id": "minLength_0_0" } ] }, @@ -13,27 +13,32 @@ { "description": "longer is valid", "data": "foo", - "valid": true + "valid": true, + "schema_id": "minLength_0_0" }, { "description": "exact length is valid", "data": "fo", - "valid": true + "valid": true, + "schema_id": "minLength_0_0" }, { "description": "too short is invalid", "data": "f", - "valid": false + "valid": false, + "schema_id": "minLength_0_0" }, { "description": "ignores non-strings", "data": 1, - "valid": true + "valid": true, + "schema_id": "minLength_0_0" }, { "description": "one grapheme is not long enough", - "data": "\uD83D\uDCA9", - "valid": false + "data": "💩", + "valid": false, + "schema_id": "minLength_0_0" } ] }, @@ -42,8 +47,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "minLength": 2.0 + "minLength": 2, + "$id": "minLength_1_0" } ] }, @@ -51,12 +56,14 @@ { "description": "longer is valid", "data": "foo", - "valid": true + "valid": true, + "schema_id": "minLength_1_0" }, { "description": "too short is invalid", "data": "f", - "valid": false + "valid": false, + "schema_id": "minLength_1_0" } ] } diff --git a/tests/fixtures/minProperties.json b/tests/fixtures/minProperties.json index 34723a1..94ace2b 100644 --- a/tests/fixtures/minProperties.json +++ b/tests/fixtures/minProperties.json @@ -4,9 +4,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "minProperties": 1, - "extensible": true + "extensible": true, + "$id": "minProperties_0_0" } ] }, @@ -17,34 +17,40 @@ "foo": 1, "bar": 2 }, - "valid": true + "valid": true, + "schema_id": "minProperties_0_0" }, { "description": "exact length is valid", "data": { "foo": 1 }, - "valid": true + "valid": true, + "schema_id": "minProperties_0_0" }, { "description": "too short is invalid", "data": {}, - "valid": false + "valid": false, + "schema_id": "minProperties_0_0" }, { "description": "ignores arrays", "data": [], - "valid": true + "valid": true, + "schema_id": "minProperties_0_0" }, { "description": "ignores strings", "data": "", - "valid": true + "valid": true, + "schema_id": "minProperties_0_0" }, { "description": "ignores other non-objects", "data": 12, - "valid": true + "valid": true, + "schema_id": "minProperties_0_0" } ] }, @@ -53,9 +59,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "minProperties": 1.0, - "extensible": true + "minProperties": 1, + "extensible": true, + "$id": "minProperties_1_0" } ] }, @@ -66,12 +72,14 @@ "foo": 1, "bar": 2 }, - "valid": true + "valid": true, + "schema_id": "minProperties_1_0" }, { "description": "too short is invalid", "data": {}, - "valid": false + "valid": false, + "schema_id": "minProperties_1_0" } ] }, @@ -80,9 +88,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "minProperties": 1, - "extensible": true + "extensible": true, + "$id": "minProperties_2_0" } ] }, @@ -92,7 +100,8 @@ "data": { "foo": 1 }, - "valid": true + "valid": true, + "schema_id": "minProperties_2_0" } ] } diff --git a/tests/fixtures/minimum.json b/tests/fixtures/minimum.json index 288aab3..3ec705a 100644 --- a/tests/fixtures/minimum.json +++ b/tests/fixtures/minimum.json @@ -4,8 +4,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "minimum": 1.1 + "minimum": 1.1, + "$id": "minimum_0_0" } ] }, @@ -13,22 +13,26 @@ { "description": "above the minimum is valid", "data": 2.6, - "valid": true + "valid": true, + "schema_id": "minimum_0_0" }, { "description": "boundary point is valid", "data": 1.1, - "valid": true + "valid": true, + "schema_id": "minimum_0_0" }, { "description": "below the minimum is invalid", "data": 0.6, - "valid": false + "valid": false, + "schema_id": "minimum_0_0" }, { "description": "ignores non-numbers", "data": "x", - "valid": true + "valid": true, + "schema_id": "minimum_0_0" } ] }, @@ -37,8 +41,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "minimum": -2 + "minimum": -2, + "$id": "minimum_1_0" } ] }, @@ -46,37 +50,44 @@ { "description": "negative above the minimum is valid", "data": -1, - "valid": true + "valid": true, + "schema_id": "minimum_1_0" }, { "description": "positive above the minimum is valid", "data": 0, - "valid": true + "valid": true, + "schema_id": "minimum_1_0" }, { "description": "boundary point is valid", "data": -2, - "valid": true + "valid": true, + "schema_id": "minimum_1_0" }, { "description": "boundary point with float is valid", - "data": -2.0, - "valid": true + "data": -2, + "valid": true, + "schema_id": "minimum_1_0" }, { "description": "float below the minimum is invalid", "data": -2.0001, - "valid": false + "valid": false, + "schema_id": "minimum_1_0" }, { "description": "int below the minimum is invalid", "data": -3, - "valid": false + "valid": false, + "schema_id": "minimum_1_0" }, { "description": "ignores non-numbers", "data": "x", - "valid": true + "valid": true, + "schema_id": "minimum_1_0" } ] } diff --git a/tests/fixtures/multipleOf.json b/tests/fixtures/multipleOf.json index c614d7b..324df97 100644 --- a/tests/fixtures/multipleOf.json +++ b/tests/fixtures/multipleOf.json @@ -4,8 +4,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "multipleOf": 2 + "multipleOf": 2, + "$id": "multipleOf_0_0" } ] }, @@ -13,17 +13,20 @@ { "description": "int by int", "data": 10, - "valid": true + "valid": true, + "schema_id": "multipleOf_0_0" }, { "description": "int by int fail", "data": 7, - "valid": false + "valid": false, + "schema_id": "multipleOf_0_0" }, { "description": "ignores non-numbers", "data": "foo", - "valid": true + "valid": true, + "schema_id": "multipleOf_0_0" } ] }, @@ -32,8 +35,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "multipleOf": 1.5 + "multipleOf": 1.5, + "$id": "multipleOf_1_0" } ] }, @@ -41,17 +44,20 @@ { "description": "zero is multiple of anything", "data": 0, - "valid": true + "valid": true, + "schema_id": "multipleOf_1_0" }, { "description": "4.5 is multiple of 1.5", "data": 4.5, - "valid": true + "valid": true, + "schema_id": "multipleOf_1_0" }, { "description": "35 is not multiple of 1.5", "data": 35, - "valid": false + "valid": false, + "schema_id": "multipleOf_1_0" } ] }, @@ -60,8 +66,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "multipleOf": 0.0001 + "multipleOf": 0.0001, + "$id": "multipleOf_2_0" } ] }, @@ -69,12 +75,14 @@ { "description": "0.0075 is multiple of 0.0001", "data": 0.0075, - "valid": true + "valid": true, + "schema_id": "multipleOf_2_0" }, { "description": "0.00751 is not multiple of 0.0001", "data": 0.00751, - "valid": false + "valid": false, + "schema_id": "multipleOf_2_0" } ] }, @@ -83,9 +91,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "integer", - "multipleOf": 1e-8 + "multipleOf": 1e-8, + "$id": "multipleOf_3_0" } ] }, @@ -93,7 +101,8 @@ { "description": "any integer is a multiple of 1e-8", "data": 12391239123, - "valid": true + "valid": true, + "schema_id": "multipleOf_3_0" } ] } diff --git a/tests/fixtures/not.json b/tests/fixtures/not.json index 33a9768..04735ce 100644 --- a/tests/fixtures/not.json +++ b/tests/fixtures/not.json @@ -4,10 +4,10 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "not": { "type": "integer" - } + }, + "$id": "not_0_0" } ] }, @@ -15,12 +15,14 @@ { "description": "allowed", "data": "foo", - "valid": true + "valid": true, + "schema_id": "not_0_0" }, { "description": "disallowed", "data": 1, - "valid": false + "valid": false, + "schema_id": "not_0_0" } ] }, @@ -29,13 +31,13 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "not": { "type": [ "integer", "boolean" ] - } + }, + "$id": "not_1_0" } ] }, @@ -43,17 +45,20 @@ { "description": "valid", "data": "foo", - "valid": true + "valid": true, + "schema_id": "not_1_0" }, { "description": "mismatch", "data": 1, - "valid": false + "valid": false, + "schema_id": "not_1_0" }, { "description": "other mismatch", "data": true, - "valid": false + "valid": false, + "schema_id": "not_1_0" } ] }, @@ -62,7 +67,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "not": { "type": "object", "properties": { @@ -71,7 +75,8 @@ } } }, - "extensible": true + "extensible": true, + "$id": "not_2_0" } ] }, @@ -79,21 +84,24 @@ { "description": "match", "data": 1, - "valid": true + "valid": true, + "schema_id": "not_2_0" }, { "description": "other match", "data": { "foo": 1 }, - "valid": true + "valid": true, + "schema_id": "not_2_0" }, { "description": "mismatch", "data": { "foo": "bar" }, - "valid": false + "valid": false, + "schema_id": "not_2_0" } ] }, @@ -102,12 +110,12 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "foo": { "not": {} } - } + }, + "$id": "not_3_0" } ] }, @@ -118,12 +126,14 @@ "foo": 1, "bar": 2 }, - "valid": false + "valid": false, + "schema_id": "not_3_0" }, { "description": "empty object is valid", "data": {}, - "valid": true + "valid": true, + "schema_id": "not_3_0" } ] }, @@ -132,8 +142,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "not": {} + "not": {}, + "$id": "not_4_0" } ] }, @@ -141,51 +151,60 @@ { "description": "number is invalid", "data": 1, - "valid": false + "valid": false, + "schema_id": "not_4_0" }, { "description": "string is invalid", "data": "foo", - "valid": false + "valid": false, + "schema_id": "not_4_0" }, { "description": "boolean true is invalid", "data": true, - "valid": false + "valid": false, + "schema_id": "not_4_0" }, { "description": "boolean false is invalid", "data": false, - "valid": false + "valid": false, + "schema_id": "not_4_0" }, { "description": "null is invalid", "data": null, - "valid": false + "valid": false, + "schema_id": "not_4_0" }, { "description": "object is invalid", "data": { "foo": "bar" }, - "valid": false + "valid": false, + "schema_id": "not_4_0" }, { "description": "empty object is invalid", "data": {}, - "valid": false + "valid": false, + "schema_id": "not_4_0" }, { "description": "array is invalid", "data": [ "foo" ], - "valid": false + "valid": false, + "schema_id": "not_4_0" }, { "description": "empty array is invalid", "data": [], - "valid": false + "valid": false, + "schema_id": "not_4_0" } ] }, @@ -194,8 +213,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "not": true + "not": true, + "$id": "not_5_0" } ] }, @@ -203,51 +222,60 @@ { "description": "number is invalid", "data": 1, - "valid": false + "valid": false, + "schema_id": "not_5_0" }, { "description": "string is invalid", "data": "foo", - "valid": false + "valid": false, + "schema_id": "not_5_0" }, { "description": "boolean true is invalid", "data": true, - "valid": false + "valid": false, + "schema_id": "not_5_0" }, { "description": "boolean false is invalid", "data": false, - "valid": false + "valid": false, + "schema_id": "not_5_0" }, { "description": "null is invalid", "data": null, - "valid": false + "valid": false, + "schema_id": "not_5_0" }, { "description": "object is invalid", "data": { "foo": "bar" }, - "valid": false + "valid": false, + "schema_id": "not_5_0" }, { "description": "empty object is invalid", "data": {}, - "valid": false + "valid": false, + "schema_id": "not_5_0" }, { "description": "array is invalid", "data": [ "foo" ], - "valid": false + "valid": false, + "schema_id": "not_5_0" }, { "description": "empty array is invalid", "data": [], - "valid": false + "valid": false, + "schema_id": "not_5_0" } ] }, @@ -256,9 +284,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "not": false, - "extensible": true + "extensible": true, + "$id": "not_6_0" } ] }, @@ -266,51 +294,60 @@ { "description": "number is valid", "data": 1, - "valid": true + "valid": true, + "schema_id": "not_6_0" }, { "description": "string is valid", "data": "foo", - "valid": true + "valid": true, + "schema_id": "not_6_0" }, { "description": "boolean true is valid", "data": true, - "valid": true + "valid": true, + "schema_id": "not_6_0" }, { "description": "boolean false is valid", "data": false, - "valid": true + "valid": true, + "schema_id": "not_6_0" }, { "description": "null is valid", "data": null, - "valid": true + "valid": true, + "schema_id": "not_6_0" }, { "description": "object is valid", "data": { "foo": "bar" }, - "valid": true + "valid": true, + "schema_id": "not_6_0" }, { "description": "empty object is valid", "data": {}, - "valid": true + "valid": true, + "schema_id": "not_6_0" }, { "description": "array is valid", "data": [ "foo" ], - "valid": true + "valid": true, + "schema_id": "not_6_0" }, { "description": "empty array is valid", "data": [], - "valid": true + "valid": true, + "schema_id": "not_6_0" } ] }, @@ -319,10 +356,10 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "not": { "not": {} - } + }, + "$id": "not_7_0" } ] }, @@ -330,7 +367,8 @@ { "description": "any value is valid", "data": "foo", - "valid": true + "valid": true, + "schema_id": "not_7_0" } ] }, @@ -339,11 +377,11 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "not": { "type": "integer" }, - "extensible": true + "extensible": true, + "$id": "not_8_0" } ] }, @@ -353,7 +391,8 @@ "data": { "foo": 1 }, - "valid": true + "valid": true, + "schema_id": "not_8_0" } ] }, @@ -362,10 +401,10 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "not": { "type": "integer" - } + }, + "$id": "not_9_0" } ] }, @@ -375,7 +414,8 @@ "data": { "foo": 1 }, - "valid": false + "valid": false, + "schema_id": "not_9_0" } ] }, @@ -384,7 +424,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "bar": { "type": "string" @@ -393,7 +432,8 @@ "not": { "type": "integer" }, - "extensible": true + "extensible": true, + "$id": "not_10_0" } ] }, @@ -404,7 +444,8 @@ "bar": "baz", "foo": 1 }, - "valid": true + "valid": true, + "schema_id": "not_10_0" } ] }, @@ -413,7 +454,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "bar": { "type": "string" @@ -421,7 +461,8 @@ }, "not": { "type": "integer" - } + }, + "$id": "not_11_0" } ] }, @@ -432,14 +473,16 @@ "bar": "baz", "foo": 1 }, - "valid": false + "valid": false, + "schema_id": "not_11_0" }, { "description": "defined property allowed", "data": { "bar": "baz" }, - "valid": true + "valid": true, + "schema_id": "not_11_0" } ] } diff --git a/tests/fixtures/oneOf.json b/tests/fixtures/oneOf.json index d10ce50..8801c1d 100644 --- a/tests/fixtures/oneOf.json +++ b/tests/fixtures/oneOf.json @@ -4,7 +4,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "oneOf": [ { "type": "integer" @@ -12,7 +11,8 @@ { "minimum": 2 } - ] + ], + "$id": "oneOf_0_0" } ] }, @@ -20,22 +20,26 @@ { "description": "first oneOf valid", "data": 1, - "valid": true + "valid": true, + "schema_id": "oneOf_0_0" }, { "description": "second oneOf valid", "data": 2.5, - "valid": true + "valid": true, + "schema_id": "oneOf_0_0" }, { "description": "both oneOf valid", "data": 3, - "valid": false + "valid": false, + "schema_id": "oneOf_0_0" }, { "description": "neither oneOf valid", "data": 1.5, - "valid": false + "valid": false, + "schema_id": "oneOf_0_0" } ] }, @@ -44,7 +48,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "string", "oneOf": [ { @@ -53,7 +56,8 @@ { "maxLength": 4 } - ] + ], + "$id": "oneOf_1_0" } ] }, @@ -61,17 +65,20 @@ { "description": "mismatch base schema", "data": 3, - "valid": false + "valid": false, + "schema_id": "oneOf_1_0" }, { "description": "one oneOf valid", "data": "foobar", - "valid": true + "valid": true, + "schema_id": "oneOf_1_0" }, { "description": "both oneOf valid", "data": "foo", - "valid": false + "valid": false, + "schema_id": "oneOf_1_0" } ] }, @@ -80,12 +87,12 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "oneOf": [ true, true, true - ] + ], + "$id": "oneOf_2_0" } ] }, @@ -93,7 +100,8 @@ { "description": "any value is invalid", "data": "foo", - "valid": false + "valid": false, + "schema_id": "oneOf_2_0" } ] }, @@ -102,12 +110,12 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "oneOf": [ true, false, false - ] + ], + "$id": "oneOf_3_0" } ] }, @@ -115,7 +123,8 @@ { "description": "any value is valid", "data": "foo", - "valid": true + "valid": true, + "schema_id": "oneOf_3_0" } ] }, @@ -124,12 +133,12 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "oneOf": [ true, true, false - ] + ], + "$id": "oneOf_4_0" } ] }, @@ -137,7 +146,8 @@ { "description": "any value is invalid", "data": "foo", - "valid": false + "valid": false, + "schema_id": "oneOf_4_0" } ] }, @@ -146,12 +156,12 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "oneOf": [ false, false, false - ] + ], + "$id": "oneOf_5_0" } ] }, @@ -159,7 +169,8 @@ { "description": "any value is invalid", "data": "foo", - "valid": false + "valid": false, + "schema_id": "oneOf_5_0" } ] }, @@ -168,332 +179,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "oneOf": [ - { - "properties": { - "bar": { - "type": "integer" - } - }, - "required": [ - "bar" - ] - }, - { - "properties": { - "foo": { - "type": "string" - } - }, - "required": [ - "foo" - ] - } - ] - } - ] - }, - "tests": [ - { - "description": "first oneOf valid (complex)", - "data": { - "bar": 2 - }, - "valid": true - }, - { - "description": "second oneOf valid (complex)", - "data": { - "foo": "baz" - }, - "valid": true - }, - { - "description": "both oneOf valid (complex)", - "data": { - "foo": "baz", - "bar": 2 - }, - "valid": false - }, - { - "description": "neither oneOf valid (complex)", - "data": { - "foo": 2, - "bar": "quux" - }, - "valid": false - } - ] - }, - { - "description": "oneOf with empty schema", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "oneOf": [ - { - "type": "number" - }, - {} - ] - } - ] - }, - "tests": [ - { - "description": "one valid - valid", - "data": "foo", - "valid": true - }, - { - "description": "both valid - invalid", - "data": 123, - "valid": false - } - ] - }, - { - "description": "oneOf with required", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "foo": true, - "bar": true, - "baz": true - }, - "oneOf": [ - { - "required": [ - "foo", - "bar" - ] - }, - { - "required": [ - "foo", - "baz" - ] - } - ] - } - ] - }, - "tests": [ - { - "description": "both invalid - invalid", - "data": { - "bar": 2 - }, - "valid": false - }, - { - "description": "first valid - valid", - "data": { - "foo": 1, - "bar": 2 - }, - "valid": true - }, - { - "description": "second valid - valid", - "data": { - "foo": 1, - "baz": 3 - }, - "valid": true - }, - { - "description": "both valid - invalid", - "data": { - "foo": 1, - "bar": 2, - "baz": 3 - }, - "valid": false - }, - { - "description": "extra property invalid (strict)", - "data": { - "foo": 1, - "bar": 2, - "extra": 3 - }, - "valid": false - } - ] - }, - { - "description": "oneOf with required (extensible)", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "extensible": true, - "oneOf": [ - { - "required": [ - "foo", - "bar" - ] - }, - { - "required": [ - "foo", - "baz" - ] - } - ] - } - ] - }, - "tests": [ - { - "description": "both invalid - invalid", - "data": { - "bar": 2 - }, - "valid": false - }, - { - "description": "first valid - valid", - "data": { - "foo": 1, - "bar": 2 - }, - "valid": true - }, - { - "description": "second valid - valid", - "data": { - "foo": 1, - "baz": 3 - }, - "valid": true - }, - { - "description": "both valid - invalid", - "data": { - "foo": 1, - "bar": 2, - "baz": 3 - }, - "valid": false - }, - { - "description": "extra properties are valid (extensible)", - "data": { - "foo": 1, - "bar": 2, - "extra": "value" - }, - "valid": true - } - ] - }, - { - "description": "oneOf with missing optional property", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "oneOf": [ - { - "properties": { - "bar": true, - "baz": true - }, - "required": [ - "bar" - ] - }, - { - "properties": { - "foo": true - }, - "required": [ - "foo" - ] - } - ] - } - ] - }, - "tests": [ - { - "description": "first oneOf valid", - "data": { - "bar": 8 - }, - "valid": true - }, - { - "description": "second oneOf valid", - "data": { - "foo": "foo" - }, - "valid": true - }, - { - "description": "both oneOf valid", - "data": { - "foo": "foo", - "bar": 8 - }, - "valid": false - }, - { - "description": "neither oneOf valid", - "data": { - "baz": "quux" - }, - "valid": false - } - ] - }, - { - "description": "nested oneOf, to check validation semantics", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "oneOf": [ - { - "oneOf": [ - { - "type": "null" - } - ] - } - ] - } - ] - }, - "tests": [ - { - "description": "null is valid", - "data": null, - "valid": true - }, - { - "description": "anything non-null is invalid", - "data": 123, - "valid": false - } - ] - }, - { - "description": "extensible: true allows extra properties in oneOf", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", "oneOf": [ { "properties": { @@ -516,7 +201,355 @@ ] } ], - "extensible": true + "$id": "oneOf_6_0" + } + ] + }, + "tests": [ + { + "description": "first oneOf valid (complex)", + "data": { + "bar": 2 + }, + "valid": true, + "schema_id": "oneOf_6_0" + }, + { + "description": "second oneOf valid (complex)", + "data": { + "foo": "baz" + }, + "valid": true, + "schema_id": "oneOf_6_0" + }, + { + "description": "both oneOf valid (complex)", + "data": { + "foo": "baz", + "bar": 2 + }, + "valid": false, + "schema_id": "oneOf_6_0" + }, + { + "description": "neither oneOf valid (complex)", + "data": { + "foo": 2, + "bar": "quux" + }, + "valid": false, + "schema_id": "oneOf_6_0" + } + ] + }, + { + "description": "oneOf with empty schema", + "database": { + "schemas": [ + { + "oneOf": [ + { + "type": "number" + }, + {} + ], + "$id": "oneOf_7_0" + } + ] + }, + "tests": [ + { + "description": "one valid - valid", + "data": "foo", + "valid": true, + "schema_id": "oneOf_7_0" + }, + { + "description": "both valid - invalid", + "data": 123, + "valid": false, + "schema_id": "oneOf_7_0" + } + ] + }, + { + "description": "oneOf with required", + "database": { + "schemas": [ + { + "type": "object", + "properties": { + "foo": true, + "bar": true, + "baz": true + }, + "oneOf": [ + { + "required": [ + "foo", + "bar" + ] + }, + { + "required": [ + "foo", + "baz" + ] + } + ], + "$id": "oneOf_8_0" + } + ] + }, + "tests": [ + { + "description": "both invalid - invalid", + "data": { + "bar": 2 + }, + "valid": false, + "schema_id": "oneOf_8_0" + }, + { + "description": "first valid - valid", + "data": { + "foo": 1, + "bar": 2 + }, + "valid": true, + "schema_id": "oneOf_8_0" + }, + { + "description": "second valid - valid", + "data": { + "foo": 1, + "baz": 3 + }, + "valid": true, + "schema_id": "oneOf_8_0" + }, + { + "description": "both valid - invalid", + "data": { + "foo": 1, + "bar": 2, + "baz": 3 + }, + "valid": false, + "schema_id": "oneOf_8_0" + }, + { + "description": "extra property invalid (strict)", + "data": { + "foo": 1, + "bar": 2, + "extra": 3 + }, + "valid": false, + "schema_id": "oneOf_8_0" + } + ] + }, + { + "description": "oneOf with required (extensible)", + "database": { + "schemas": [ + { + "type": "object", + "extensible": true, + "oneOf": [ + { + "required": [ + "foo", + "bar" + ] + }, + { + "required": [ + "foo", + "baz" + ] + } + ], + "$id": "oneOf_9_0" + } + ] + }, + "tests": [ + { + "description": "both invalid - invalid", + "data": { + "bar": 2 + }, + "valid": false, + "schema_id": "oneOf_9_0" + }, + { + "description": "first valid - valid", + "data": { + "foo": 1, + "bar": 2 + }, + "valid": true, + "schema_id": "oneOf_9_0" + }, + { + "description": "second valid - valid", + "data": { + "foo": 1, + "baz": 3 + }, + "valid": true, + "schema_id": "oneOf_9_0" + }, + { + "description": "both valid - invalid", + "data": { + "foo": 1, + "bar": 2, + "baz": 3 + }, + "valid": false, + "schema_id": "oneOf_9_0" + }, + { + "description": "extra properties are valid (extensible)", + "data": { + "foo": 1, + "bar": 2, + "extra": "value" + }, + "valid": true, + "schema_id": "oneOf_9_0" + } + ] + }, + { + "description": "oneOf with missing optional property", + "database": { + "schemas": [ + { + "oneOf": [ + { + "properties": { + "bar": true, + "baz": true + }, + "required": [ + "bar" + ] + }, + { + "properties": { + "foo": true + }, + "required": [ + "foo" + ] + } + ], + "$id": "oneOf_10_0" + } + ] + }, + "tests": [ + { + "description": "first oneOf valid", + "data": { + "bar": 8 + }, + "valid": true, + "schema_id": "oneOf_10_0" + }, + { + "description": "second oneOf valid", + "data": { + "foo": "foo" + }, + "valid": true, + "schema_id": "oneOf_10_0" + }, + { + "description": "both oneOf valid", + "data": { + "foo": "foo", + "bar": 8 + }, + "valid": false, + "schema_id": "oneOf_10_0" + }, + { + "description": "neither oneOf valid", + "data": { + "baz": "quux" + }, + "valid": false, + "schema_id": "oneOf_10_0" + } + ] + }, + { + "description": "nested oneOf, to check validation semantics", + "database": { + "schemas": [ + { + "oneOf": [ + { + "oneOf": [ + { + "type": "null" + } + ] + } + ], + "$id": "oneOf_11_0" + } + ] + }, + "tests": [ + { + "description": "null is valid", + "data": null, + "valid": true, + "schema_id": "oneOf_11_0" + }, + { + "description": "anything non-null is invalid", + "data": 123, + "valid": false, + "schema_id": "oneOf_11_0" + } + ] + }, + { + "description": "extensible: true allows extra properties in oneOf", + "database": { + "schemas": [ + { + "oneOf": [ + { + "properties": { + "bar": { + "type": "integer" + } + }, + "required": [ + "bar" + ] + }, + { + "properties": { + "foo": { + "type": "string" + } + }, + "required": [ + "foo" + ] + } + ], + "extensible": true, + "$id": "oneOf_12_0" } ] }, @@ -527,7 +560,8 @@ "bar": 2, "extra": "prop" }, - "valid": true + "valid": true, + "schema_id": "oneOf_12_0" } ] } diff --git a/tests/fixtures/pattern.json b/tests/fixtures/pattern.json index 0b731d7..c544cfd 100644 --- a/tests/fixtures/pattern.json +++ b/tests/fixtures/pattern.json @@ -4,8 +4,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "pattern": "^a*$" + "pattern": "^a*$", + "$id": "pattern_0_0" } ] }, @@ -13,42 +13,50 @@ { "description": "a matching pattern is valid", "data": "aaa", - "valid": true + "valid": true, + "schema_id": "pattern_0_0" }, { "description": "a non-matching pattern is invalid", "data": "abc", - "valid": false + "valid": false, + "schema_id": "pattern_0_0" }, { "description": "ignores booleans", "data": true, - "valid": true + "valid": true, + "schema_id": "pattern_0_0" }, { "description": "ignores integers", "data": 123, - "valid": true + "valid": true, + "schema_id": "pattern_0_0" }, { "description": "ignores floats", - "data": 1.0, - "valid": true + "data": 1, + "valid": true, + "schema_id": "pattern_0_0" }, { "description": "ignores objects", "data": {}, - "valid": true + "valid": true, + "schema_id": "pattern_0_0" }, { "description": "ignores arrays", "data": [], - "valid": true + "valid": true, + "schema_id": "pattern_0_0" }, { "description": "ignores null", "data": null, - "valid": true + "valid": true, + "schema_id": "pattern_0_0" } ] }, @@ -57,8 +65,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "pattern": "a+" + "pattern": "a+", + "$id": "pattern_1_0" } ] }, @@ -66,7 +74,8 @@ { "description": "matches a substring", "data": "xxaayy", - "valid": true + "valid": true, + "schema_id": "pattern_1_0" } ] } diff --git a/tests/fixtures/patternProperties.json b/tests/fixtures/patternProperties.json index 4a934a7..3b8dfa5 100644 --- a/tests/fixtures/patternProperties.json +++ b/tests/fixtures/patternProperties.json @@ -4,13 +4,13 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "patternProperties": { "f.*o": { "type": "integer" } }, - "items": {} + "items": {}, + "$id": "patternProperties_0_0" } ] }, @@ -20,7 +20,8 @@ "data": { "foo": 1 }, - "valid": true + "valid": true, + "schema_id": "patternProperties_0_0" }, { "description": "multiple valid matches is valid", @@ -28,7 +29,8 @@ "foo": 1, "foooooo": 2 }, - "valid": true + "valid": true, + "schema_id": "patternProperties_0_0" }, { "description": "a single invalid match is invalid", @@ -36,7 +38,8 @@ "foo": "bar", "fooooo": 2 }, - "valid": false + "valid": false, + "schema_id": "patternProperties_0_0" }, { "description": "multiple invalid matches is invalid", @@ -44,24 +47,28 @@ "foo": "bar", "foooooo": "baz" }, - "valid": false + "valid": false, + "schema_id": "patternProperties_0_0" }, { "description": "ignores arrays", "data": [ "foo" ], - "valid": true + "valid": true, + "schema_id": "patternProperties_0_0" }, { "description": "ignores strings", "data": "foo", - "valid": true + "valid": true, + "schema_id": "patternProperties_0_0" }, { "description": "ignores other non-objects", "data": 12, - "valid": true + "valid": true, + "schema_id": "patternProperties_0_0" }, { "description": "extra property not matching pattern is INVALID (strict by default)", @@ -69,7 +76,8 @@ "foo": 1, "extra": 2 }, - "valid": false + "valid": false, + "schema_id": "patternProperties_0_0" } ] }, @@ -78,7 +86,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "patternProperties": { "a*": { "type": "integer" @@ -86,7 +93,8 @@ "aaa*": { "maximum": 20 } - } + }, + "$id": "patternProperties_1_0" } ] }, @@ -96,14 +104,16 @@ "data": { "a": 21 }, - "valid": true + "valid": true, + "schema_id": "patternProperties_1_0" }, { "description": "a simultaneous match is valid", "data": { "aaaa": 18 }, - "valid": true + "valid": true, + "schema_id": "patternProperties_1_0" }, { "description": "multiple matches is valid", @@ -111,21 +121,24 @@ "a": 21, "aaaa": 18 }, - "valid": true + "valid": true, + "schema_id": "patternProperties_1_0" }, { "description": "an invalid due to one is invalid", "data": { "a": "bar" }, - "valid": false + "valid": false, + "schema_id": "patternProperties_1_0" }, { "description": "an invalid due to the other is invalid", "data": { "aaaa": 31 }, - "valid": false + "valid": false, + "schema_id": "patternProperties_1_0" }, { "description": "an invalid due to both is invalid", @@ -133,7 +146,8 @@ "aaa": "foo", "aaaa": 31 }, - "valid": false + "valid": false, + "schema_id": "patternProperties_1_0" } ] }, @@ -142,7 +156,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "patternProperties": { "[0-9]{2,}": { "type": "boolean" @@ -151,7 +164,8 @@ "type": "string" } }, - "extensible": true + "extensible": true, + "$id": "patternProperties_2_0" } ] }, @@ -161,28 +175,32 @@ "data": { "answer 1": "42" }, - "valid": true + "valid": true, + "schema_id": "patternProperties_2_0" }, { "description": "recognized members are accounted for", "data": { "a31b": null }, - "valid": false + "valid": false, + "schema_id": "patternProperties_2_0" }, { "description": "regexes are case sensitive", "data": { "a_x_3": 3 }, - "valid": true + "valid": true, + "schema_id": "patternProperties_2_0" }, { "description": "regexes are case sensitive, 2", "data": { "a_X_3": 3 }, - "valid": false + "valid": false, + "schema_id": "patternProperties_2_0" } ] }, @@ -191,11 +209,11 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "patternProperties": { "f.*": true, "b.*": false - } + }, + "$id": "patternProperties_3_0" } ] }, @@ -205,14 +223,16 @@ "data": { "foo": 1 }, - "valid": true + "valid": true, + "schema_id": "patternProperties_3_0" }, { "description": "object with property matching schema false is invalid", "data": { "bar": 2 }, - "valid": false + "valid": false, + "schema_id": "patternProperties_3_0" }, { "description": "object with both properties is invalid", @@ -220,19 +240,22 @@ "foo": 1, "bar": 2 }, - "valid": false + "valid": false, + "schema_id": "patternProperties_3_0" }, { "description": "object with a property matching both true and false is invalid", "data": { "foobar": 1 }, - "valid": false + "valid": false, + "schema_id": "patternProperties_3_0" }, { "description": "empty object is valid", "data": {}, - "valid": true + "valid": true, + "schema_id": "patternProperties_3_0" } ] }, @@ -241,12 +264,12 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "patternProperties": { "^.*bar$": { "type": "null" } - } + }, + "$id": "patternProperties_4_0" } ] }, @@ -256,7 +279,8 @@ "data": { "foobar": null }, - "valid": true + "valid": true, + "schema_id": "patternProperties_4_0" } ] }, @@ -265,13 +289,13 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "patternProperties": { "f.*o": { "type": "integer" } }, - "extensible": true + "extensible": true, + "$id": "patternProperties_5_0" } ] }, @@ -281,14 +305,16 @@ "data": { "bar": 1 }, - "valid": true + "valid": true, + "schema_id": "patternProperties_5_0" }, { "description": "property matching pattern MUST still be valid", "data": { "foo": "invalid string" }, - "valid": false + "valid": false, + "schema_id": "patternProperties_5_0" } ] } diff --git a/tests/fixtures/prefixItems.json b/tests/fixtures/prefixItems.json index 1a115e0..b02c664 100644 --- a/tests/fixtures/prefixItems.json +++ b/tests/fixtures/prefixItems.json @@ -4,7 +4,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "prefixItems": [ { "type": "integer" @@ -12,7 +11,8 @@ { "type": "string" } - ] + ], + "$id": "prefixItems_0_0" } ] }, @@ -23,7 +23,8 @@ 1, "foo" ], - "valid": true + "valid": true, + "schema_id": "prefixItems_0_0" }, { "description": "wrong types", @@ -31,14 +32,16 @@ "foo", 1 ], - "valid": false + "valid": false, + "schema_id": "prefixItems_0_0" }, { "description": "incomplete array of items", "data": [ 1 ], - "valid": true + "valid": true, + "schema_id": "prefixItems_0_0" }, { "description": "array with additional items (invalid due to strictness)", @@ -47,12 +50,14 @@ "foo", true ], - "valid": false + "valid": false, + "schema_id": "prefixItems_0_0" }, { "description": "empty array", "data": [], - "valid": true + "valid": true, + "schema_id": "prefixItems_0_0" }, { "description": "JavaScript pseudo-array is valid (invalid due to strict object validation)", @@ -61,7 +66,8 @@ "1": "valid", "length": 2 }, - "valid": false + "valid": false, + "schema_id": "prefixItems_0_0" } ] }, @@ -70,11 +76,11 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "prefixItems": [ true, false - ] + ], + "$id": "prefixItems_1_0" } ] }, @@ -84,7 +90,8 @@ "data": [ 1 ], - "valid": true + "valid": true, + "schema_id": "prefixItems_1_0" }, { "description": "array with two items is invalid", @@ -92,12 +99,14 @@ 1, "foo" ], - "valid": false + "valid": false, + "schema_id": "prefixItems_1_0" }, { "description": "empty array is valid", "data": [], - "valid": true + "valid": true, + "schema_id": "prefixItems_1_0" } ] }, @@ -106,13 +115,13 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "prefixItems": [ { "type": "integer" } ], - "extensible": true + "extensible": true, + "$id": "prefixItems_2_0" } ] }, @@ -124,7 +133,8 @@ "foo", false ], - "valid": true + "valid": true, + "schema_id": "prefixItems_2_0" } ] }, @@ -133,12 +143,12 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "prefixItems": [ { "type": "null" } - ] + ], + "$id": "prefixItems_3_0" } ] }, @@ -148,7 +158,8 @@ "data": [ null ], - "valid": true + "valid": true, + "schema_id": "prefixItems_3_0" } ] }, @@ -157,13 +168,13 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "prefixItems": [ { "type": "integer" } ], - "extensible": true + "extensible": true, + "$id": "prefixItems_4_0" } ] }, @@ -174,7 +185,8 @@ 1, "foo" ], - "valid": true + "valid": true, + "schema_id": "prefixItems_4_0" } ] } diff --git a/tests/fixtures/properties.json b/tests/fixtures/properties.json index 0a092fe..b04f106 100644 --- a/tests/fixtures/properties.json +++ b/tests/fixtures/properties.json @@ -4,7 +4,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "foo": { "type": "integer" @@ -12,7 +11,8 @@ "bar": { "type": "string" } - } + }, + "$id": "properties_0_0" } ] }, @@ -23,7 +23,8 @@ "foo": 1, "bar": "baz" }, - "valid": true + "valid": true, + "schema_id": "properties_0_0" }, { "description": "one property invalid is invalid", @@ -31,7 +32,8 @@ "foo": 1, "bar": {} }, - "valid": false + "valid": false, + "schema_id": "properties_0_0" }, { "description": "both properties invalid is invalid", @@ -39,22 +41,26 @@ "foo": [], "bar": {} }, - "valid": false + "valid": false, + "schema_id": "properties_0_0" }, { "description": "doesn't invalidate other properties", "data": {}, - "valid": true + "valid": true, + "schema_id": "properties_0_0" }, { "description": "ignores arrays", "data": [], - "valid": true + "valid": true, + "schema_id": "properties_0_0" }, { "description": "ignores other non-objects", "data": 12, - "valid": true + "valid": true, + "schema_id": "properties_0_0" } ] }, @@ -63,11 +69,11 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "foo": true, "bar": false - } + }, + "$id": "properties_1_0" } ] }, @@ -75,21 +81,24 @@ { "description": "no property present is valid", "data": {}, - "valid": true + "valid": true, + "schema_id": "properties_1_0" }, { "description": "only 'true' property present is valid", "data": { "foo": 1 }, - "valid": true + "valid": true, + "schema_id": "properties_1_0" }, { "description": "only 'false' property present is invalid", "data": { "bar": 2 }, - "valid": false + "valid": false, + "schema_id": "properties_1_0" }, { "description": "both properties present is invalid", @@ -97,7 +106,8 @@ "foo": 1, "bar": 2 }, - "valid": false + "valid": false, + "schema_id": "properties_1_0" } ] }, @@ -106,7 +116,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "foo\nbar": { "type": "number" @@ -126,7 +135,8 @@ "foo\fbar": { "type": "number" } - } + }, + "$id": "properties_2_0" } ] }, @@ -141,7 +151,8 @@ "foo\tbar": 1, "foo\fbar": 1 }, - "valid": true + "valid": true, + "schema_id": "properties_2_0" }, { "description": "object with strings is invalid", @@ -153,7 +164,8 @@ "foo\tbar": "1", "foo\fbar": "1" }, - "valid": false + "valid": false, + "schema_id": "properties_2_0" } ] }, @@ -162,12 +174,12 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "foo": { "type": "null" } - } + }, + "$id": "properties_3_0" } ] }, @@ -177,7 +189,8 @@ "data": { "foo": null }, - "valid": true + "valid": true, + "schema_id": "properties_3_0" } ] }, @@ -187,7 +200,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "__proto__": { "type": "number" @@ -202,7 +214,8 @@ "constructor": { "type": "number" } - } + }, + "$id": "properties_4_0" } ] }, @@ -210,24 +223,28 @@ { "description": "ignores arrays", "data": [], - "valid": true + "valid": true, + "schema_id": "properties_4_0" }, { "description": "ignores other non-objects", "data": 12, - "valid": true + "valid": true, + "schema_id": "properties_4_0" }, { "description": "none of the properties mentioned", "data": {}, - "valid": true + "valid": true, + "schema_id": "properties_4_0" }, { "description": "__proto__ not valid", "data": { "__proto__": "foo" }, - "valid": false + "valid": false, + "schema_id": "properties_4_0" }, { "description": "toString not valid", @@ -236,7 +253,8 @@ "length": 37 } }, - "valid": false + "valid": false, + "schema_id": "properties_4_0" }, { "description": "constructor not valid", @@ -245,7 +263,8 @@ "length": 37 } }, - "valid": false + "valid": false, + "schema_id": "properties_4_0" }, { "description": "all present and valid", @@ -256,7 +275,8 @@ }, "constructor": 37 }, - "valid": true + "valid": true, + "schema_id": "properties_4_0" } ] }, @@ -265,13 +285,13 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "foo": { "type": "integer" } }, - "extensible": true + "extensible": true, + "$id": "properties_5_0" } ] }, @@ -282,7 +302,8 @@ "foo": 1, "bar": "baz" }, - "valid": true + "valid": true, + "schema_id": "properties_5_0" } ] }, @@ -291,12 +312,12 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "foo": { "type": "string" } - } + }, + "$id": "properties_6_0" } ] }, @@ -307,7 +328,8 @@ "foo": "bar", "extra": 1 }, - "valid": false + "valid": false, + "schema_id": "properties_6_0" } ] }, @@ -316,7 +338,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "nested": { "properties": { @@ -325,7 +346,8 @@ } } } - } + }, + "$id": "properties_7_0" } ] }, @@ -338,7 +360,8 @@ "extra": 1 } }, - "valid": false + "valid": false, + "schema_id": "properties_7_0" } ] }, @@ -347,7 +370,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "nested": { "extensible": true, @@ -357,7 +379,8 @@ } } } - } + }, + "$id": "properties_8_0" } ] }, @@ -370,7 +393,8 @@ "extra": 1 } }, - "valid": true + "valid": true, + "schema_id": "properties_8_0" } ] }, @@ -379,7 +403,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "extensible": true, "properties": { "nested": { @@ -389,7 +412,8 @@ } } } - } + }, + "$id": "properties_9_0" } ] }, @@ -402,7 +426,8 @@ "extra": 1 } }, - "valid": true + "valid": true, + "schema_id": "properties_9_0" } ] }, @@ -411,7 +436,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "extensible": true, "properties": { "nested": { @@ -422,7 +446,8 @@ } } } - } + }, + "$id": "properties_10_0" } ] }, @@ -435,7 +460,8 @@ "extra": 1 } }, - "valid": false + "valid": false, + "schema_id": "properties_10_0" } ] }, @@ -444,7 +470,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "list": { "type": "array", @@ -456,7 +481,8 @@ } } } - } + }, + "$id": "properties_11_0" } ] }, @@ -471,7 +497,8 @@ } ] }, - "valid": false + "valid": false, + "schema_id": "properties_11_0" } ] }, @@ -480,7 +507,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "extensible": true, "properties": { "list": { @@ -493,7 +519,8 @@ } } } - } + }, + "$id": "properties_12_0" } ] }, @@ -508,7 +535,8 @@ } ] }, - "valid": true + "valid": true, + "schema_id": "properties_12_0" } ] } diff --git a/tests/fixtures/propertyNames.json b/tests/fixtures/propertyNames.json index 8d48dd3..047b0d7 100644 --- a/tests/fixtures/propertyNames.json +++ b/tests/fixtures/propertyNames.json @@ -4,11 +4,11 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "propertyNames": { "maxLength": 3 }, - "extensible": true + "extensible": true, + "$id": "propertyNames_0_0" } ] }, @@ -19,7 +19,8 @@ "f": {}, "foo": {} }, - "valid": true + "valid": true, + "schema_id": "propertyNames_0_0" }, { "description": "some property names invalid", @@ -27,12 +28,14 @@ "foo": {}, "foobar": {} }, - "valid": false + "valid": false, + "schema_id": "propertyNames_0_0" }, { "description": "object without properties is valid", "data": {}, - "valid": true + "valid": true, + "schema_id": "propertyNames_0_0" }, { "description": "ignores arrays", @@ -42,17 +45,20 @@ 3, 4 ], - "valid": true + "valid": true, + "schema_id": "propertyNames_0_0" }, { "description": "ignores strings", "data": "foobar", - "valid": true + "valid": true, + "schema_id": "propertyNames_0_0" }, { "description": "ignores other non-objects", "data": 12, - "valid": true + "valid": true, + "schema_id": "propertyNames_0_0" } ] }, @@ -61,11 +67,11 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "propertyNames": { "pattern": "^a+$" }, - "extensible": true + "extensible": true, + "$id": "propertyNames_1_0" } ] }, @@ -77,19 +83,22 @@ "aa": {}, "aaa": {} }, - "valid": true + "valid": true, + "schema_id": "propertyNames_1_0" }, { "description": "non-matching property name is invalid", "data": { "aaA": {} }, - "valid": false + "valid": false, + "schema_id": "propertyNames_1_0" }, { "description": "object without properties is valid", "data": {}, - "valid": true + "valid": true, + "schema_id": "propertyNames_1_0" } ] }, @@ -98,9 +107,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "propertyNames": true, - "extensible": true + "extensible": true, + "$id": "propertyNames_2_0" } ] }, @@ -110,12 +119,14 @@ "data": { "foo": 1 }, - "valid": true + "valid": true, + "schema_id": "propertyNames_2_0" }, { "description": "empty object is valid", "data": {}, - "valid": true + "valid": true, + "schema_id": "propertyNames_2_0" } ] }, @@ -124,9 +135,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "propertyNames": false, - "extensible": true + "extensible": true, + "$id": "propertyNames_3_0" } ] }, @@ -136,12 +147,14 @@ "data": { "foo": 1 }, - "valid": false + "valid": false, + "schema_id": "propertyNames_3_0" }, { "description": "empty object is valid", "data": {}, - "valid": true + "valid": true, + "schema_id": "propertyNames_3_0" } ] }, @@ -150,11 +163,11 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "propertyNames": { "const": "foo" }, - "extensible": true + "extensible": true, + "$id": "propertyNames_4_0" } ] }, @@ -164,19 +177,22 @@ "data": { "foo": 1 }, - "valid": true + "valid": true, + "schema_id": "propertyNames_4_0" }, { "description": "object with any other property is invalid", "data": { "bar": 1 }, - "valid": false + "valid": false, + "schema_id": "propertyNames_4_0" }, { "description": "empty object is valid", "data": {}, - "valid": true + "valid": true, + "schema_id": "propertyNames_4_0" } ] }, @@ -185,14 +201,14 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "propertyNames": { "enum": [ "foo", "bar" ] }, - "extensible": true + "extensible": true, + "$id": "propertyNames_5_0" } ] }, @@ -202,7 +218,8 @@ "data": { "foo": 1 }, - "valid": true + "valid": true, + "schema_id": "propertyNames_5_0" }, { "description": "object with property foo and bar is valid", @@ -210,19 +227,22 @@ "foo": 1, "bar": 1 }, - "valid": true + "valid": true, + "schema_id": "propertyNames_5_0" }, { "description": "object with any other property is invalid", "data": { "baz": 1 }, - "valid": false + "valid": false, + "schema_id": "propertyNames_5_0" }, { "description": "empty object is valid", "data": {}, - "valid": true + "valid": true, + "schema_id": "propertyNames_5_0" } ] }, @@ -231,11 +251,11 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "propertyNames": { "maxLength": 3 }, - "extensible": true + "extensible": true, + "$id": "propertyNames_6_0" } ] }, @@ -245,14 +265,16 @@ "data": { "foo": 1 }, - "valid": true + "valid": true, + "schema_id": "propertyNames_6_0" }, { "description": "extra property with invalid name is invalid", "data": { "foobar": 1 }, - "valid": false + "valid": false, + "schema_id": "propertyNames_6_0" } ] } diff --git a/tests/fixtures/ref.json b/tests/fixtures/ref.json index 48a67d0..e8aec54 100644 --- a/tests/fixtures/ref.json +++ b/tests/fixtures/ref.json @@ -1,218 +1,23 @@ [ - { - "description": "root pointer ref", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "properties": { - "foo": { - "$ref": "#" - } - }, - "additionalProperties": false - } - ] - }, - "tests": [ - { - "description": "match", - "data": { - "foo": false - }, - "valid": true - }, - { - "description": "recursive match", - "data": { - "foo": { - "foo": false - } - }, - "valid": true - }, - { - "description": "mismatch", - "data": { - "bar": false - }, - "valid": false - }, - { - "description": "recursive mismatch", - "data": { - "foo": { - "bar": false - } - }, - "valid": false - } - ] - }, - { - "description": "relative pointer ref to object", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "properties": { - "foo": { - "type": "integer" - }, - "bar": { - "$ref": "#/properties/foo" - } - } - } - ] - }, - "tests": [ - { - "description": "match", - "data": { - "bar": 3 - }, - "valid": true - }, - { - "description": "mismatch", - "data": { - "bar": true - }, - "valid": false - } - ] - }, - { - "description": "relative pointer ref to array", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "prefixItems": [ - { - "type": "integer" - }, - { - "$ref": "#/prefixItems/0" - } - ] - } - ] - }, - "tests": [ - { - "description": "match array", - "data": [ - 1, - 2 - ], - "valid": true - }, - { - "description": "mismatch array", - "data": [ - 1, - "foo" - ], - "valid": false - } - ] - }, - { - "description": "escaped pointer ref", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$defs": { - "tilde~field": { - "type": "integer" - }, - "slash/field": { - "type": "integer" - }, - "percent%field": { - "type": "integer" - } - }, - "properties": { - "tilde": { - "$ref": "#/$defs/tilde~0field" - }, - "slash": { - "$ref": "#/$defs/slash~1field" - }, - "percent": { - "$ref": "#/$defs/percent%25field" - } - } - } - ] - }, - "tests": [ - { - "description": "slash invalid", - "data": { - "slash": "aoeu" - }, - "valid": false - }, - { - "description": "tilde invalid", - "data": { - "tilde": "aoeu" - }, - "valid": false - }, - { - "description": "percent invalid", - "data": { - "percent": "aoeu" - }, - "valid": false - }, - { - "description": "slash valid", - "data": { - "slash": 123 - }, - "valid": true - }, - { - "description": "tilde valid", - "data": { - "tilde": 123 - }, - "valid": true - }, - { - "description": "percent valid", - "data": { - "percent": 123 - }, - "valid": true - } - ] - }, { "description": "nested refs", "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$defs": { - "a": { - "type": "integer" - }, - "b": { - "$ref": "#/$defs/a" - }, - "c": { - "$ref": "#/$defs/b" - } - }, - "$ref": "#/$defs/c" + "$ref": "c_212", + "$id": "ref_4_0" + }, + { + "$id": "a_212", + "type": "integer" + }, + { + "$id": "b_212", + "$ref": "a_212" + }, + { + "$id": "c_212", + "$ref": "b_212" } ] }, @@ -220,12 +25,14 @@ { "description": "nested ref valid", "data": 5, - "valid": true + "valid": true, + "schema_id": "ref_4_0" }, { "description": "nested ref invalid", "data": "a", - "valid": false + "valid": false, + "schema_id": "ref_4_0" } ] }, @@ -234,18 +41,17 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$defs": { - "reffed": { - "type": "array" - } - }, "properties": { "foo": { - "$ref": "#/$defs/reffed", + "$ref": "reffed_248", "maxItems": 2 } - } + }, + "$id": "ref_5_0" + }, + { + "$id": "reffed_248", + "type": "array" } ] }, @@ -255,7 +61,8 @@ "data": { "foo": [] }, - "valid": true + "valid": true, + "schema_id": "ref_5_0" }, { "description": "ref valid, maxItems invalid", @@ -266,14 +73,16 @@ 3 ] }, - "valid": false + "valid": false, + "schema_id": "ref_5_0" }, { "description": "ref invalid", "data": { "foo": "string" }, - "valid": false + "valid": false, + "schema_id": "ref_5_0" } ] }, @@ -282,12 +91,12 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "$ref": { "type": "string" } - } + }, + "$id": "ref_6_0" } ] }, @@ -297,14 +106,16 @@ "data": { "$ref": "a" }, - "valid": true + "valid": true, + "schema_id": "ref_6_0" }, { "description": "property named $ref invalid", "data": { "$ref": 2 }, - "valid": false + "valid": false, + "schema_id": "ref_6_0" } ] }, @@ -313,17 +124,16 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "$ref": { - "$ref": "#/$defs/is-string" + "$ref": "is-string_344" } }, - "$defs": { - "is-string": { - "type": "string" - } - } + "$id": "ref_7_0" + }, + { + "$id": "is-string_344", + "type": "string" } ] }, @@ -333,14 +143,16 @@ "data": { "$ref": "a" }, - "valid": true + "valid": true, + "schema_id": "ref_7_0" }, { "description": "property named $ref invalid", "data": { "$ref": 2 }, - "valid": false + "valid": false, + "schema_id": "ref_7_0" } ] }, @@ -349,11 +161,12 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$ref": "#/$defs/bool", - "$defs": { - "bool": true - } + "$ref": "bool_378", + "$id": "ref_8_0" + }, + { + "$id": "bool_378", + "extensible": true } ] }, @@ -361,7 +174,8 @@ { "description": "any value is valid", "data": "foo", - "valid": true + "valid": true, + "schema_id": "ref_8_0" } ] }, @@ -370,11 +184,13 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$ref": "#/$defs/bool", - "$defs": { - "bool": false - } + "$ref": "bool_400", + "$id": "ref_9_0" + }, + { + "$id": "bool_400", + "extensible": false, + "not": {} } ] }, @@ -382,129 +198,8 @@ { "description": "any value is invalid", "data": "foo", - "valid": false - } - ] - }, - { - "description": "Recursive references between schemas", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "http://localhost:1234/draft2020-12/tree", - "description": "tree of nodes", - "type": "object", - "properties": { - "meta": { - "type": "string" - }, - "nodes": { - "type": "array", - "items": { - "$ref": "node" - } - } - }, - "required": [ - "meta", - "nodes" - ], - "$defs": { - "node": { - "$id": "http://localhost:1234/draft2020-12/node", - "description": "node", - "type": "object", - "properties": { - "value": { - "type": "number" - }, - "subtree": { - "$ref": "tree" - } - }, - "required": [ - "value" - ] - } - } - } - ] - }, - "tests": [ - { - "description": "valid tree", - "data": { - "meta": "root", - "nodes": [ - { - "value": 1, - "subtree": { - "meta": "child", - "nodes": [ - { - "value": 1.1 - }, - { - "value": 1.2 - } - ] - } - }, - { - "value": 2, - "subtree": { - "meta": "child", - "nodes": [ - { - "value": 2.1 - }, - { - "value": 2.2 - } - ] - } - } - ] - }, - "valid": true - }, - { - "description": "invalid tree", - "data": { - "meta": "root", - "nodes": [ - { - "value": 1, - "subtree": { - "meta": "child", - "nodes": [ - { - "value": "string is invalid" - }, - { - "value": 1.2 - } - ] - } - }, - { - "value": 2, - "subtree": { - "meta": "child", - "nodes": [ - { - "value": 2.1 - }, - { - "value": 2.2 - } - ] - } - } - ] - }, - "valid": false + "valid": false, + "schema_id": "ref_9_0" } ] }, @@ -513,17 +208,16 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "foo\"bar": { - "$ref": "#/$defs/foo%22bar" + "$ref": "foo%22bar_550" } }, - "$defs": { - "foo\"bar": { - "type": "number" - } - } + "$id": "ref_11_0" + }, + { + "$id": "foo%22bar_550", + "type": "number" } ] }, @@ -533,871 +227,16 @@ "data": { "foo\"bar": 1 }, - "valid": true + "valid": true, + "schema_id": "ref_11_0" }, { "description": "object with strings is invalid", "data": { "foo\"bar": "1" }, - "valid": false - } - ] - }, - { - "description": "naive replacement of $ref with its destination is not correct", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "extensible": true, - "$defs": { - "a_string": { - "type": "string" - } - }, - "enum": [ - { - "$ref": "#/$defs/a_string" - } - ] - } - ] - }, - "tests": [ - { - "description": "do not evaluate the $ref inside the enum, matching any string", - "data": "this is a string", - "valid": false - }, - { - "description": "do not evaluate the $ref inside the enum, definition exact match", - "data": { - "type": "string" - }, - "valid": false - }, - { - "description": "match the enum exactly", - "data": { - "$ref": "#/$defs/a_string" - }, - "valid": true - } - ] - }, - { - "description": "refs with relative uris and defs", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "http://example.com/schema-relative-uri-defs1.json", - "properties": { - "foo": { - "$id": "schema-relative-uri-defs2.json", - "$defs": { - "inner": { - "properties": { - "bar": { - "type": "string" - } - } - } - }, - "$ref": "#/$defs/inner" - } - }, - "$ref": "schema-relative-uri-defs2.json" - } - ] - }, - "tests": [ - { - "description": "invalid on inner field", - "data": { - "foo": { - "bar": 1 - }, - "bar": "a" - }, - "valid": false - }, - { - "description": "invalid on outer field", - "data": { - "foo": { - "bar": "a" - }, - "bar": 1 - }, - "valid": false - }, - { - "description": "valid on both fields", - "data": { - "foo": { - "bar": "a" - }, - "bar": "a" - }, - "valid": true - } - ] - }, - { - "description": "refs with relative uris and defs (extensible)", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "http://example.com/schema-relative-uri-defs1-ext.json", - "properties": { - "foo": { - "$id": "schema-relative-uri-defs2-ext.json", - "$defs": { - "inner": { - "extensible": true, - "properties": { - "bar": { - "type": "string" - } - } - } - }, - "$ref": "#/$defs/inner" - } - }, - "$ref": "schema-relative-uri-defs2-ext.json" - } - ] - }, - "tests": [ - { - "description": "valid on both fields", - "data": { - "foo": { - "bar": "a" - }, - "bar": "a" - }, - "valid": true - } - ] - }, - { - "description": "relative refs with absolute uris and defs", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "http://example.com/schema-refs-absolute-uris-defs1.json", - "properties": { - "foo": { - "$id": "http://example.com/schema-refs-absolute-uris-defs2.json", - "$defs": { - "inner": { - "properties": { - "bar": { - "type": "string" - } - } - } - }, - "$ref": "#/$defs/inner" - } - }, - "$ref": "schema-refs-absolute-uris-defs2.json" - } - ] - }, - "tests": [ - { - "description": "invalid on inner field", - "data": { - "foo": { - "bar": 1 - }, - "bar": "a" - }, - "valid": false - }, - { - "description": "invalid on outer field", - "data": { - "foo": { - "bar": "a" - }, - "bar": 1 - }, - "valid": false - }, - { - "description": "valid on both fields", - "data": { - "foo": { - "bar": "a" - }, - "bar": "a" - }, - "valid": true - } - ] - }, - { - "description": "$id must be resolved against nearest parent, not just immediate parent", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "http://example.com/a.json", - "$defs": { - "x": { - "$id": "http://example.com/b/c.json", - "not": { - "$defs": { - "y": { - "$id": "d.json", - "type": "number" - } - } - } - } - }, - "allOf": [ - { - "$ref": "http://example.com/b/d.json" - } - ] - } - ] - }, - "tests": [ - { - "description": "number is valid", - "data": 1, - "valid": true - }, - { - "description": "non-number is invalid", - "data": "a", - "valid": false - } - ] - }, - { - "description": "order of evaluation: $id and $ref", - "database": { - "schemas": [ - { - "$comment": "$id must be evaluated before $ref to get the proper $ref destination", - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://example.com/draft2020-12/ref-and-id1/base.json", - "$ref": "int.json", - "$defs": { - "bigint": { - "$comment": "canonical uri: https://example.com/ref-and-id1/int.json", - "$id": "int.json", - "maximum": 10 - }, - "smallint": { - "$comment": "canonical uri: https://example.com/ref-and-id1-int.json", - "$id": "/draft2020-12/ref-and-id1-int.json", - "maximum": 2 - } - } - } - ] - }, - "tests": [ - { - "description": "data is valid against first definition", - "data": 5, - "valid": true - }, - { - "description": "data is invalid against first definition", - "data": 50, - "valid": false - } - ] - }, - { - "description": "order of evaluation: $id and $anchor and $ref", - "database": { - "schemas": [ - { - "$comment": "$id must be evaluated before $ref to get the proper $ref destination", - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://example.com/draft2020-12/ref-and-id2/base.json", - "$ref": "#bigint", - "$defs": { - "bigint": { - "$comment": "canonical uri: /ref-and-id2/base.json#/$defs/bigint; another valid uri for this location: /ref-and-id2/base.json#bigint", - "$anchor": "bigint", - "maximum": 10 - }, - "smallint": { - "$comment": "canonical uri: https://example.com/ref-and-id2#/$defs/smallint; another valid uri for this location: https://example.com/ref-and-id2/#bigint", - "$id": "https://example.com/draft2020-12/ref-and-id2/", - "$anchor": "bigint", - "maximum": 2 - } - } - } - ] - }, - "tests": [ - { - "description": "data is valid against first definition", - "data": 5, - "valid": true - }, - { - "description": "data is invalid against first definition", - "data": 50, - "valid": false - } - ] - }, - { - "description": "order of evaluation: $id and $ref on nested schema", - "database": { - "schemas": [ - { - "$comment": "$id must be evaluated before $ref to get the proper $ref destination", - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://example.com/draft2020-12/ref-and-id3/base.json", - "$ref": "nested/foo.json", - "$defs": { - "foo": { - "$comment": "canonical uri: https://example.com/draft2020-12/ref-and-id3/nested/foo.json", - "$id": "nested/foo.json", - "$ref": "./bar.json" - }, - "bar": { - "$comment": "canonical uri: https://example.com/draft2020-12/ref-and-id3/nested/bar.json", - "$id": "nested/bar.json", - "type": "number" - } - } - } - ] - }, - "tests": [ - { - "description": "data is valid against nested sibling", - "data": 5, - "valid": true - }, - { - "description": "data is invalid against nested sibling", - "data": "a", - "valid": false - } - ] - }, - { - "description": "simple URN base URI with $ref via the URN", - "database": { - "schemas": [ - { - "$comment": "URIs do not have to have HTTP(s) schemes", - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "urn:uuid:deadbeef-1234-ffff-ffff-4321feebdaed", - "minimum": 30, - "properties": { - "foo": { - "$ref": "urn:uuid:deadbeef-1234-ffff-ffff-4321feebdaed" - } - } - } - ] - }, - "tests": [ - { - "description": "valid under the URN IDed schema", - "data": { - "foo": 37 - }, - "valid": true - }, - { - "description": "invalid under the URN IDed schema", - "data": { - "foo": 12 - }, - "valid": false - } - ] - }, - { - "description": "simple URN base URI with JSON pointer", - "database": { - "schemas": [ - { - "$comment": "URIs do not have to have HTTP(s) schemes", - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "urn:uuid:deadbeef-1234-00ff-ff00-4321feebdaed", - "properties": { - "foo": { - "$ref": "#/$defs/bar" - } - }, - "$defs": { - "bar": { - "type": "string" - } - } - } - ] - }, - "tests": [ - { - "description": "a string is valid", - "data": { - "foo": "bar" - }, - "valid": true - }, - { - "description": "a non-string is invalid", - "data": { - "foo": 12 - }, - "valid": false - } - ] - }, - { - "description": "URN base URI with NSS", - "database": { - "schemas": [ - { - "$comment": "RFC 8141 §2.2", - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "urn:example:1/406/47452/2", - "properties": { - "foo": { - "$ref": "#/$defs/bar" - } - }, - "$defs": { - "bar": { - "type": "string" - } - } - } - ] - }, - "tests": [ - { - "description": "a string is valid", - "data": { - "foo": "bar" - }, - "valid": true - }, - { - "description": "a non-string is invalid", - "data": { - "foo": 12 - }, - "valid": false - } - ] - }, - { - "description": "URN base URI with r-component", - "database": { - "schemas": [ - { - "$comment": "RFC 8141 §2.3.1", - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "urn:example:foo-bar-baz-qux?+CCResolve:cc=uk", - "properties": { - "foo": { - "$ref": "#/$defs/bar" - } - }, - "$defs": { - "bar": { - "type": "string" - } - } - } - ] - }, - "tests": [ - { - "description": "a string is valid", - "data": { - "foo": "bar" - }, - "valid": true - }, - { - "description": "a non-string is invalid", - "data": { - "foo": 12 - }, - "valid": false - } - ] - }, - { - "description": "URN base URI with q-component", - "database": { - "schemas": [ - { - "$comment": "RFC 8141 §2.3.2", - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "urn:example:weather?=op=map&lat=39.56&lon=-104.85&datetime=1969-07-21T02:56:15Z", - "properties": { - "foo": { - "$ref": "#/$defs/bar" - } - }, - "$defs": { - "bar": { - "type": "string" - } - } - } - ] - }, - "tests": [ - { - "description": "a string is valid", - "data": { - "foo": "bar" - }, - "valid": true - }, - { - "description": "a non-string is invalid", - "data": { - "foo": 12 - }, - "valid": false - } - ] - }, - { - "description": "URN base URI with URN and JSON pointer ref", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "urn:uuid:deadbeef-1234-0000-0000-4321feebdaed", - "properties": { - "foo": { - "$ref": "urn:uuid:deadbeef-1234-0000-0000-4321feebdaed#/$defs/bar" - } - }, - "$defs": { - "bar": { - "type": "string" - } - } - } - ] - }, - "tests": [ - { - "description": "a string is valid", - "data": { - "foo": "bar" - }, - "valid": true - }, - { - "description": "a non-string is invalid", - "data": { - "foo": 12 - }, - "valid": false - } - ] - }, - { - "description": "URN base URI with URN and anchor ref", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "urn:uuid:deadbeef-1234-ff00-00ff-4321feebdaed", - "properties": { - "foo": { - "$ref": "urn:uuid:deadbeef-1234-ff00-00ff-4321feebdaed#something" - } - }, - "$defs": { - "bar": { - "$anchor": "something", - "type": "string" - } - } - } - ] - }, - "tests": [ - { - "description": "a string is valid", - "data": { - "foo": "bar" - }, - "valid": true - }, - { - "description": "a non-string is invalid", - "data": { - "foo": 12 - }, - "valid": false - } - ] - }, - { - "description": "URN ref with nested pointer ref", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$ref": "urn:uuid:deadbeef-4321-ffff-ffff-1234feebdaed", - "$defs": { - "foo": { - "$id": "urn:uuid:deadbeef-4321-ffff-ffff-1234feebdaed", - "$defs": { - "bar": { - "type": "string" - } - }, - "$ref": "#/$defs/bar" - } - } - } - ] - }, - "tests": [ - { - "description": "a string is valid", - "data": "bar", - "valid": true - }, - { - "description": "a non-string is invalid", - "data": 12, - "valid": false - } - ] - }, - { - "description": "ref to if", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$ref": "http://example.com/ref/if", - "if": { - "$id": "http://example.com/ref/if", - "type": "integer" - } - } - ] - }, - "tests": [ - { - "description": "a non-integer is invalid due to the $ref", - "data": "foo", - "valid": false - }, - { - "description": "an integer is valid", - "data": 12, - "valid": true - } - ] - }, - { - "description": "ref to then", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$ref": "http://example.com/ref/then", - "then": { - "$id": "http://example.com/ref/then", - "type": "integer" - } - } - ] - }, - "tests": [ - { - "description": "a non-integer is invalid due to the $ref", - "data": "foo", - "valid": false - }, - { - "description": "an integer is valid", - "data": 12, - "valid": true - } - ] - }, - { - "description": "ref to else", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$ref": "http://example.com/ref/else", - "else": { - "$id": "http://example.com/ref/else", - "type": "integer" - } - } - ] - }, - "tests": [ - { - "description": "a non-integer is invalid due to the $ref", - "data": "foo", - "valid": false - }, - { - "description": "an integer is valid", - "data": 12, - "valid": true - } - ] - }, - { - "description": "ref with absolute-path-reference", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "http://example.com/ref/absref.json", - "$defs": { - "a": { - "$id": "http://example.com/ref/absref/foobar.json", - "type": "number" - }, - "b": { - "$id": "http://example.com/absref/foobar.json", - "type": "string" - } - }, - "$ref": "/absref/foobar.json" - } - ] - }, - "tests": [ - { - "description": "a string is valid", - "data": "foo", - "valid": true - }, - { - "description": "an integer is invalid", - "data": 12, - "valid": false - } - ] - }, - { - "description": "$id with file URI still resolves pointers - *nix", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "file:///folder/file.json", - "$defs": { - "foo": { - "type": "number" - } - }, - "$ref": "#/$defs/foo" - } - ] - }, - "tests": [ - { - "description": "number is valid", - "data": 1, - "valid": true - }, - { - "description": "non-number is invalid", - "data": "a", - "valid": false - } - ] - }, - { - "description": "$id with file URI still resolves pointers - windows", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "file:///c:/folder/file.json", - "$defs": { - "foo": { - "type": "number" - } - }, - "$ref": "#/$defs/foo" - } - ] - }, - "tests": [ - { - "description": "number is valid", - "data": 1, - "valid": true - }, - { - "description": "non-number is invalid", - "data": "a", - "valid": false - } - ] - }, - { - "description": "empty tokens in $ref json-pointer", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$defs": { - "": { - "$defs": { - "": { - "type": "number" - } - } - } - }, - "allOf": [ - { - "$ref": "#/$defs//$defs/" - } - ] - } - ] - }, - "tests": [ - { - "description": "number is valid", - "data": 1, - "valid": true - }, - { - "description": "non-number is invalid", - "data": "a", - "valid": false + "valid": false, + "schema_id": "ref_11_0" } ] }, @@ -1406,17 +245,16 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$defs": { - "target": { - "properties": { - "foo": { - "type": "string" - } - } + "$ref": "target_1465", + "$id": "ref_35_0" + }, + { + "$id": "target_1465", + "properties": { + "foo": { + "type": "string" } - }, - "$ref": "#/$defs/target" + } } ] }, @@ -1427,7 +265,8 @@ "foo": "bar", "extra": 1 }, - "valid": false + "valid": false, + "schema_id": "ref_35_0" } ] }, @@ -1436,18 +275,17 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$defs": { - "target": { - "extensible": false, - "properties": { - "foo": { - "type": "string" - } - } + "$ref": "target_1496", + "$id": "ref_36_0" + }, + { + "$id": "target_1496", + "extensible": false, + "properties": { + "foo": { + "type": "string" } - }, - "$ref": "#/$defs/target" + } } ] }, @@ -1458,7 +296,8 @@ "foo": "bar", "extra": 1 }, - "valid": false + "valid": false, + "schema_id": "ref_36_0" } ] }, @@ -1477,27 +316,28 @@ } }, "ref_child": { - "$ref": "#/$defs/strict_node" + "$ref": "strict_node_1544" }, "extensible_ref_child": { - "$ref": "#/$defs/extensible_node" + "$ref": "extensible_node_1551" } }, - "$defs": { - "strict_node": { - "properties": { - "b": { - "type": "integer" - } - } - }, - "extensible_node": { - "extensible": true, - "properties": { - "c": { - "type": "integer" - } - } + "$id": "ref_37_0" + }, + { + "$id": "strict_node_1544", + "properties": { + "b": { + "type": "integer" + } + } + }, + { + "$id": "extensible_node_1551", + "extensible": true, + "properties": { + "c": { + "type": "integer" } } } @@ -1512,7 +352,8 @@ "extra": 2 } }, - "valid": true + "valid": true, + "schema_id": "ref_37_0" }, { "description": "ref child resets to strict (default)", @@ -1522,7 +363,8 @@ "extra": 2 } }, - "valid": false + "valid": false, + "schema_id": "ref_37_0" }, { "description": "ref child with explicit extensible=true is loose", @@ -1532,7 +374,8 @@ "extra": 2 } }, - "valid": true + "valid": true, + "schema_id": "ref_37_0" } ] }, @@ -1541,22 +384,21 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "list": { "type": "array", "items": { - "$ref": "#/$defs/strict_node" + "$ref": "strict_node_1614" } } }, - "$defs": { - "strict_node": { - "properties": { - "a": { - "type": "integer" - } - } + "$id": "ref_38_0" + }, + { + "$id": "strict_node_1614", + "properties": { + "a": { + "type": "integer" } } } @@ -1573,7 +415,8 @@ } ] }, - "valid": false + "valid": false, + "schema_id": "ref_38_0" } ] }, @@ -1582,26 +425,7 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$defs": { - "parent": { - "type": "object", - "properties": { - "type": { - "const": "parent" - }, - "age": { - "minimum": 10, - "maximum": 20 - } - }, - "required": [ - "type", - "age" - ] - } - }, - "$ref": "#/$defs/parent", + "$ref": "parent_1648", "properties": { "type": { "const": "child" @@ -1609,7 +433,25 @@ "age": { "minimum": 15 } - } + }, + "$id": "ref_39_0" + }, + { + "$id": "parent_1648", + "type": "object", + "properties": { + "type": { + "const": "parent" + }, + "age": { + "minimum": 10, + "maximum": 20 + } + }, + "required": [ + "type", + "age" + ] } ] }, @@ -1620,7 +462,8 @@ "type": "child", "age": 15 }, - "valid": true + "valid": true, + "schema_id": "ref_39_0" }, { "description": "parent type is now invalid (shadowed)", @@ -1628,7 +471,8 @@ "type": "parent", "age": 15 }, - "valid": false + "valid": false, + "schema_id": "ref_39_0" }, { "description": "child min age (15) is enforced", @@ -1636,7 +480,8 @@ "type": "child", "age": 12 }, - "valid": false + "valid": false, + "schema_id": "ref_39_0" }, { "description": "parent max age (20) is shadowed (replaced) by child definition", @@ -1644,7 +489,345 @@ "type": "child", "age": 21 }, + "valid": true, + "schema_id": "ref_39_0" + } + ] + }, + { + "description": "Entities extending entities (Physical Birth)", + "database": { + "types": [ + { + "name": "entity", + "hierarchy": [ + "entity" + ], + "schemas": [ + { + "$id": "entity", + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string" + } + } + } + ] + }, + { + "name": "organization", + "hierarchy": [ + "entity", + "organization" + ], + "schemas": [ + { + "$id": "organization", + "$ref": "entity", + "properties": { + "name": { + "type": "string" + } + } + } + ] + }, + { + "name": "person", + "hierarchy": [ + "entity", + "organization", + "person" + ], + "schemas": [ + { + "$id": "person", + "$ref": "organization", + "properties": { + "first_name": { + "type": "string" + } + } + } + ] + } + ], + "puncs": [ + { + "name": "save_org", + "schemas": [ + { + "$id": "save_org.request", + "$ref": "organization" + } + ] + } + ] + }, + "tests": [ + { + "description": "Valid person against organization schema (implicit type allowance from physical hierarchy)", + "schema_id": "save_org.request", + "data": { + "id": "1", + "type": "person", + "name": "ACME" + }, "valid": true + }, + { + "description": "Valid organization against organization schema", + "schema_id": "save_org.request", + "data": { + "id": "2", + "type": "organization", + "name": "ACME" + }, + "valid": true + }, + { + "description": "Invalid entity against organization schema (ancestor not allowed)", + "schema_id": "save_org.request", + "data": { + "id": "3", + "type": "entity" + }, + "valid": false, + "expect_errors": [ + { + "code": "TYPE_MISMATCH", + "path": "/type" + } + ] + } + ] + }, + { + "description": "Viral Infection: Ad-hocs inheriting entity boundaries via $ref", + "database": { + "types": [ + { + "name": "entity", + "hierarchy": [ + "entity" + ], + "schemas": [ + { + "$id": "entity", + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string" + } + } + } + ] + }, + { + "name": "person", + "hierarchy": [ + "entity", + "person" + ], + "schemas": [ + { + "$id": "person", + "$ref": "entity", + "properties": { + "first_name": { + "type": "string" + } + } + }, + { + "$id": "person.light", + "$ref": "entity", + "extensible": false, + "properties": { + "first_name": { + "type": "string" + } + } + } + ] + } + ], + "puncs": [ + { + "name": "save_person_light", + "schemas": [ + { + "$id": "save_person_light.request", + "$ref": "person.light", + "properties": { + "extra_request_field": { + "type": "string" + } + } + } + ] + } + ] + }, + "tests": [ + { + "description": "Valid person against ad-hoc request schema (request virally inherited person variations)", + "schema_id": "save_person_light.request", + "data": { + "id": "1", + "type": "person", + "first_name": "John", + "extra_request_field": "test" + }, + "valid": true + }, + { + "description": "Invalid entity against ad-hoc request schema (viral inheritance enforces person boundary)", + "schema_id": "save_person_light.request", + "data": { + "id": "1", + "type": "entity", + "first_name": "John" + }, + "valid": false, + "expect_errors": [ + { + "code": "TYPE_MISMATCH", + "path": "/type" + } + ] + } + ] + }, + { + "description": "Ad-hocs extending ad-hocs (No type property)", + "database": { + "puncs": [ + { + "name": "save_address", + "schemas": [ + { + "$id": "address", + "type": "object", + "properties": { + "street": { + "type": "string" + }, + "city": { + "type": "string" + } + } + }, + { + "$id": "us_address", + "$ref": "address", + "properties": { + "state": { + "type": "string" + }, + "zip": { + "type": "string" + } + } + }, + { + "$id": "save_address.request", + "$ref": "us_address" + } + ] + } + ] + }, + "tests": [ + { + "description": "Valid us_address", + "schema_id": "save_address.request", + "data": { + "street": "123 Main", + "city": "Anytown", + "state": "CA", + "zip": "12345" + }, + "valid": true + }, + { + "description": "Invalid base address against us_address", + "schema_id": "save_address.request", + "data": { + "street": "123 Main", + "city": "Anytown" + }, + "valid": true + } + ] + }, + { + "description": "Ad-hocs extending ad-hocs (with string type property, no magic)", + "database": { + "puncs": [ + { + "name": "save_config", + "schemas": [ + { + "$id": "config_base", + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "config_base" + }, + "setting": { + "type": "string" + } + } + }, + { + "$id": "config_advanced", + "$ref": "config_base", + "properties": { + "type": { + "type": "string", + "const": "config_advanced" + }, + "advanced_setting": { + "type": "string" + } + } + }, + { + "$id": "save_config.request", + "$ref": "config_base" + } + ] + } + ] + }, + "tests": [ + { + "description": "Valid config_base against config_base", + "schema_id": "save_config.request", + "data": { + "type": "config_base", + "setting": "on" + }, + "valid": true + }, + { + "description": "Invalid config_advanced against config_base (no type magic, const is strictly 'config_base')", + "schema_id": "save_config.request", + "data": { + "type": "config_advanced", + "setting": "on", + "advanced_setting": "off" + }, + "valid": false } ] } diff --git a/tests/fixtures/required.json b/tests/fixtures/required.json index a311b19..c44f087 100644 --- a/tests/fixtures/required.json +++ b/tests/fixtures/required.json @@ -4,14 +4,14 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "foo": {}, "bar": {} }, "required": [ "foo" - ] + ], + "$id": "required_0_0" } ] }, @@ -21,39 +21,46 @@ "data": { "foo": 1 }, - "valid": true + "valid": true, + "schema_id": "required_0_0" }, { "description": "non-present required property is invalid", "data": { "bar": 1 }, - "valid": false + "valid": false, + "schema_id": "required_0_0" }, { "description": "ignores arrays", "data": [], - "valid": true + "valid": true, + "schema_id": "required_0_0" }, { "description": "ignores strings", "data": "", - "valid": true + "valid": true, + "schema_id": "required_0_0" }, { "description": "ignores other non-objects", "data": 12, - "valid": true + "valid": true, + "schema_id": "required_0_0" }, { "description": "ignores null", "data": null, - "valid": true + "valid": true, + "schema_id": "required_0_0" }, { "description": "ignores boolean", "data": true, - "valid": true + "valid": true, + "schema_id": "required_0_0" } ] }, @@ -62,10 +69,10 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "foo": {} - } + }, + "$id": "required_1_0" } ] }, @@ -73,7 +80,8 @@ { "description": "not required by default", "data": {}, - "valid": true + "valid": true, + "schema_id": "required_1_0" } ] }, @@ -82,11 +90,11 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "foo": {} }, - "required": [] + "required": [], + "$id": "required_2_0" } ] }, @@ -94,7 +102,8 @@ { "description": "property not required", "data": {}, - "valid": true + "valid": true, + "schema_id": "required_2_0" } ] }, @@ -103,7 +112,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "required": [ "foo\nbar", "foo\"bar", @@ -112,7 +120,8 @@ "foo\tbar", "foo\fbar" ], - "extensible": true + "extensible": true, + "$id": "required_3_0" } ] }, @@ -127,7 +136,8 @@ "foo\tbar": 1, "foo\fbar": 1 }, - "valid": true + "valid": true, + "schema_id": "required_3_0" }, { "description": "object with some properties missing is invalid", @@ -135,7 +145,8 @@ "foo\nbar": "1", "foo\"bar": "1" }, - "valid": false + "valid": false, + "schema_id": "required_3_0" } ] }, @@ -145,13 +156,13 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "required": [ "__proto__", "toString", "constructor" ], - "extensible": true + "extensible": true, + "$id": "required_4_0" } ] }, @@ -159,24 +170,28 @@ { "description": "ignores arrays", "data": [], - "valid": true + "valid": true, + "schema_id": "required_4_0" }, { "description": "ignores other non-objects", "data": 12, - "valid": true + "valid": true, + "schema_id": "required_4_0" }, { "description": "none of the properties mentioned", "data": {}, - "valid": false + "valid": false, + "schema_id": "required_4_0" }, { "description": "__proto__ present", "data": { "__proto__": "foo" }, - "valid": false + "valid": false, + "schema_id": "required_4_0" }, { "description": "toString present", @@ -185,7 +200,8 @@ "length": 37 } }, - "valid": false + "valid": false, + "schema_id": "required_4_0" }, { "description": "constructor present", @@ -194,7 +210,8 @@ "length": 37 } }, - "valid": false + "valid": false, + "schema_id": "required_4_0" }, { "description": "all present", @@ -205,7 +222,8 @@ }, "constructor": 37 }, - "valid": true + "valid": true, + "schema_id": "required_4_0" } ] }, @@ -214,11 +232,11 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "required": [ "foo" ], - "extensible": true + "extensible": true, + "$id": "required_5_0" } ] }, @@ -229,7 +247,8 @@ "foo": 1, "bar": 2 }, - "valid": true + "valid": true, + "schema_id": "required_5_0" } ] } diff --git a/tests/fixtures/type.json b/tests/fixtures/type.json index c884d8b..1b0f626 100644 --- a/tests/fixtures/type.json +++ b/tests/fixtures/type.json @@ -4,8 +4,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "integer" + "type": "integer", + "$id": "type_0_0" } ] }, @@ -13,47 +13,56 @@ { "description": "an integer is an integer", "data": 1, - "valid": true + "valid": true, + "schema_id": "type_0_0" }, { "description": "a float with zero fractional part is an integer", - "data": 1.0, - "valid": true + "data": 1, + "valid": true, + "schema_id": "type_0_0" }, { "description": "a float is not an integer", "data": 1.1, - "valid": false + "valid": false, + "schema_id": "type_0_0" }, { "description": "a string is not an integer", "data": "foo", - "valid": false + "valid": false, + "schema_id": "type_0_0" }, { "description": "a string is still not an integer, even if it looks like one", "data": "1", - "valid": false + "valid": false, + "schema_id": "type_0_0" }, { "description": "an object is not an integer", "data": {}, - "valid": false + "valid": false, + "schema_id": "type_0_0" }, { "description": "an array is not an integer", "data": [], - "valid": false + "valid": false, + "schema_id": "type_0_0" }, { "description": "a boolean is not an integer", "data": true, - "valid": false + "valid": false, + "schema_id": "type_0_0" }, { "description": "null is not an integer", "data": null, - "valid": false + "valid": false, + "schema_id": "type_0_0" } ] }, @@ -62,8 +71,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "number" + "type": "number", + "$id": "type_1_0" } ] }, @@ -71,47 +80,56 @@ { "description": "an integer is a number", "data": 1, - "valid": true + "valid": true, + "schema_id": "type_1_0" }, { "description": "a float with zero fractional part is a number (and an integer)", - "data": 1.0, - "valid": true + "data": 1, + "valid": true, + "schema_id": "type_1_0" }, { "description": "a float is a number", "data": 1.1, - "valid": true + "valid": true, + "schema_id": "type_1_0" }, { "description": "a string is not a number", "data": "foo", - "valid": false + "valid": false, + "schema_id": "type_1_0" }, { "description": "a string is still not a number, even if it looks like one", "data": "1", - "valid": false + "valid": false, + "schema_id": "type_1_0" }, { "description": "an object is not a number", "data": {}, - "valid": false + "valid": false, + "schema_id": "type_1_0" }, { "description": "an array is not a number", "data": [], - "valid": false + "valid": false, + "schema_id": "type_1_0" }, { "description": "a boolean is not a number", "data": true, - "valid": false + "valid": false, + "schema_id": "type_1_0" }, { "description": "null is not a number", "data": null, - "valid": false + "valid": false, + "schema_id": "type_1_0" } ] }, @@ -120,8 +138,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "string" + "type": "string", + "$id": "type_2_0" } ] }, @@ -129,47 +147,56 @@ { "description": "1 is not a string", "data": 1, - "valid": false + "valid": false, + "schema_id": "type_2_0" }, { "description": "a float is not a string", "data": 1.1, - "valid": false + "valid": false, + "schema_id": "type_2_0" }, { "description": "a string is a string", "data": "foo", - "valid": true + "valid": true, + "schema_id": "type_2_0" }, { "description": "a string is still a string, even if it looks like a number", "data": "1", - "valid": true + "valid": true, + "schema_id": "type_2_0" }, { "description": "an empty string is still a string", "data": "", - "valid": true + "valid": true, + "schema_id": "type_2_0" }, { "description": "an object is not a string", "data": {}, - "valid": false + "valid": false, + "schema_id": "type_2_0" }, { "description": "an array is not a string", "data": [], - "valid": false + "valid": false, + "schema_id": "type_2_0" }, { "description": "a boolean is not a string", "data": true, - "valid": false + "valid": false, + "schema_id": "type_2_0" }, { "description": "null is not a string", "data": null, - "valid": false + "valid": false, + "schema_id": "type_2_0" } ] }, @@ -178,8 +205,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object" + "type": "object", + "$id": "type_3_0" } ] }, @@ -187,37 +214,44 @@ { "description": "an integer is not an object", "data": 1, - "valid": false + "valid": false, + "schema_id": "type_3_0" }, { "description": "a float is not an object", "data": 1.1, - "valid": false + "valid": false, + "schema_id": "type_3_0" }, { "description": "a string is not an object", "data": "foo", - "valid": false + "valid": false, + "schema_id": "type_3_0" }, { "description": "an object is an object", "data": {}, - "valid": true + "valid": true, + "schema_id": "type_3_0" }, { "description": "an array is not an object", "data": [], - "valid": false + "valid": false, + "schema_id": "type_3_0" }, { "description": "a boolean is not an object", "data": true, - "valid": false + "valid": false, + "schema_id": "type_3_0" }, { "description": "null is not an object", "data": null, - "valid": false + "valid": false, + "schema_id": "type_3_0" } ] }, @@ -226,8 +260,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "array" + "type": "array", + "$id": "type_4_0" } ] }, @@ -235,37 +269,44 @@ { "description": "an integer is not an array", "data": 1, - "valid": false + "valid": false, + "schema_id": "type_4_0" }, { "description": "a float is not an array", "data": 1.1, - "valid": false + "valid": false, + "schema_id": "type_4_0" }, { "description": "a string is not an array", "data": "foo", - "valid": false + "valid": false, + "schema_id": "type_4_0" }, { "description": "an object is not an array", "data": {}, - "valid": false + "valid": false, + "schema_id": "type_4_0" }, { "description": "an array is an array", "data": [], - "valid": true + "valid": true, + "schema_id": "type_4_0" }, { "description": "a boolean is not an array", "data": true, - "valid": false + "valid": false, + "schema_id": "type_4_0" }, { "description": "null is not an array", "data": null, - "valid": false + "valid": false, + "schema_id": "type_4_0" } ] }, @@ -274,8 +315,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "boolean" + "type": "boolean", + "$id": "type_5_0" } ] }, @@ -283,52 +324,62 @@ { "description": "an integer is not a boolean", "data": 1, - "valid": false + "valid": false, + "schema_id": "type_5_0" }, { "description": "zero is not a boolean", "data": 0, - "valid": false + "valid": false, + "schema_id": "type_5_0" }, { "description": "a float is not a boolean", "data": 1.1, - "valid": false + "valid": false, + "schema_id": "type_5_0" }, { "description": "a string is not a boolean", "data": "foo", - "valid": false + "valid": false, + "schema_id": "type_5_0" }, { "description": "an empty string is a null", "data": "", - "valid": true + "valid": true, + "schema_id": "type_5_0" }, { "description": "an object is not a boolean", "data": {}, - "valid": false + "valid": false, + "schema_id": "type_5_0" }, { "description": "an array is not a boolean", "data": [], - "valid": false + "valid": false, + "schema_id": "type_5_0" }, { "description": "true is a boolean", "data": true, - "valid": true + "valid": true, + "schema_id": "type_5_0" }, { "description": "false is a boolean", "data": false, - "valid": true + "valid": true, + "schema_id": "type_5_0" }, { "description": "null is not a boolean", "data": null, - "valid": false + "valid": false, + "schema_id": "type_5_0" } ] }, @@ -337,8 +388,8 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "null" + "type": "null", + "$id": "type_6_0" } ] }, @@ -346,52 +397,62 @@ { "description": "an integer is not null", "data": 1, - "valid": false + "valid": false, + "schema_id": "type_6_0" }, { "description": "a float is not null", "data": 1.1, - "valid": false + "valid": false, + "schema_id": "type_6_0" }, { "description": "zero is not null", "data": 0, - "valid": false + "valid": false, + "schema_id": "type_6_0" }, { "description": "a string is not null", "data": "foo", - "valid": false + "valid": false, + "schema_id": "type_6_0" }, { "description": "an empty string is null", "data": "", - "valid": true + "valid": true, + "schema_id": "type_6_0" }, { "description": "an object is not null", "data": {}, - "valid": false + "valid": false, + "schema_id": "type_6_0" }, { "description": "an array is not null", "data": [], - "valid": false + "valid": false, + "schema_id": "type_6_0" }, { "description": "true is not null", "data": true, - "valid": false + "valid": false, + "schema_id": "type_6_0" }, { "description": "false is not null", "data": false, - "valid": false + "valid": false, + "schema_id": "type_6_0" }, { "description": "null is null", "data": null, - "valid": true + "valid": true, + "schema_id": "type_6_0" } ] }, @@ -400,11 +461,11 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "type": [ "integer", "string" - ] + ], + "$id": "type_7_0" } ] }, @@ -412,37 +473,44 @@ { "description": "an integer is valid", "data": 1, - "valid": true + "valid": true, + "schema_id": "type_7_0" }, { "description": "a string is valid", "data": "foo", - "valid": true + "valid": true, + "schema_id": "type_7_0" }, { "description": "a float is invalid", "data": 1.1, - "valid": false + "valid": false, + "schema_id": "type_7_0" }, { "description": "an object is invalid", "data": {}, - "valid": false + "valid": false, + "schema_id": "type_7_0" }, { "description": "an array is invalid", "data": [], - "valid": false + "valid": false, + "schema_id": "type_7_0" }, { "description": "a boolean is invalid", "data": true, - "valid": false + "valid": false, + "schema_id": "type_7_0" }, { "description": "null is invalid", "data": null, - "valid": false + "valid": false, + "schema_id": "type_7_0" } ] }, @@ -451,10 +519,10 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "type": [ "string" - ] + ], + "$id": "type_8_0" } ] }, @@ -462,12 +530,14 @@ { "description": "string is valid", "data": "foo", - "valid": true + "valid": true, + "schema_id": "type_8_0" }, { "description": "number is invalid", "data": 123, - "valid": false + "valid": false, + "schema_id": "type_8_0" } ] }, @@ -476,12 +546,12 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "type": [ "array", "object" ], - "items": {} + "items": {}, + "$id": "type_9_0" } ] }, @@ -493,27 +563,32 @@ 2, 3 ], - "valid": true + "valid": true, + "schema_id": "type_9_0" }, { "description": "object is valid", "data": {}, - "valid": true + "valid": true, + "schema_id": "type_9_0" }, { "description": "number is invalid", "data": 123, - "valid": false + "valid": false, + "schema_id": "type_9_0" }, { "description": "string is invalid", "data": "foo", - "valid": false + "valid": false, + "schema_id": "type_9_0" }, { "description": "null is invalid", "data": null, - "valid": false + "valid": false, + "schema_id": "type_9_0" } ] }, @@ -522,13 +597,13 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "type": [ "array", "object", "null" ], - "items": {} + "items": {}, + "$id": "type_10_0" } ] }, @@ -540,27 +615,32 @@ 2, 3 ], - "valid": true + "valid": true, + "schema_id": "type_10_0" }, { "description": "object is valid", "data": {}, - "valid": true + "valid": true, + "schema_id": "type_10_0" }, { "description": "null is valid", "data": null, - "valid": true + "valid": true, + "schema_id": "type_10_0" }, { "description": "number is invalid", "data": 123, - "valid": false + "valid": false, + "schema_id": "type_10_0" }, { "description": "string is invalid", "data": "foo", - "valid": false + "valid": false, + "schema_id": "type_10_0" } ] }, @@ -569,9 +649,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", - "extensible": true + "extensible": true, + "$id": "type_11_0" } ] }, @@ -581,7 +661,8 @@ "data": { "foo": 1 }, - "valid": true + "valid": true, + "schema_id": "type_11_0" } ] } diff --git a/tests/fixtures/typedRefs.json b/tests/fixtures/typedRefs.json deleted file mode 100644 index f991d5d..0000000 --- a/tests/fixtures/typedRefs.json +++ /dev/null @@ -1,343 +0,0 @@ -[ - { - "description": "Entities extending entities", - "database": { - "types": [ - { - "name": "entity", - "hierarchy": [ - "entity" - ], - "schemas": [ - { - "$id": "entity", - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "type": { - "type": "string", - "const": "entity" - } - } - } - ] - }, - { - "name": "organization", - "hierarchy": [ - "entity", - "organization" - ], - "schemas": [ - { - "$id": "organization", - "$ref": "entity", - "properties": { - "name": { - "type": "string" - } - } - } - ] - }, - { - "name": "person", - "hierarchy": [ - "entity", - "organization", - "person" - ], - "schemas": [ - { - "$id": "person", - "$ref": "organization", - "properties": { - "first_name": { - "type": "string" - } - } - } - ] - } - ], - "puncs": [ - { - "name": "save_org", - "schemas": [ - { - "$id": "save_org.request", - "$ref": "organization" - } - ] - } - ] - }, - "tests": [ - { - "description": "Valid person against organization schema (implicit type allowance)", - "schema_id": "save_org.request", - "data": { - "id": "1", - "type": "person", - "name": "ACME" - }, - "valid": true - }, - { - "description": "Valid organization against organization schema", - "schema_id": "save_org.request", - "data": { - "id": "2", - "type": "organization", - "name": "ACME" - }, - "valid": true - }, - { - "description": "Invalid entity against organization schema (ancestor not allowed)", - "schema_id": "save_org.request", - "data": { - "id": "3", - "type": "entity" - }, - "valid": false - }, - { - "description": "Invalid generic type against organization schema", - "schema_id": "save_org.request", - "data": { - "id": "4", - "type": "generic_thing" - }, - "valid": false - } - ] - }, - { - "description": "Ad-hocs extending entities (still entities with type magic)", - "database": { - "types": [ - { - "name": "entity", - "hierarchy": [ - "entity" - ], - "schemas": [ - { - "$id": "entity", - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "type": { - "type": "string", - "const": "entity" - } - } - } - ] - }, - { - "name": "person", - "hierarchy": [ - "entity", - "person" - ], - "schemas": [ - { - "$id": "person", - "$ref": "entity", - "properties": { - "first_name": { - "type": "string" - } - } - } - ] - } - ], - "puncs": [ - { - "name": "save_person_light", - "schemas": [ - { - "$id": "person.light", - "$ref": "person", - "extensible": false, - "properties": { - "first_name": { - "type": "string" - } - } - }, - { - "$id": "save_person_light.request", - "$ref": "person.light" - } - ] - } - ] - }, - "tests": [ - { - "description": "Valid person against person.light ad-hoc schema", - "schema_id": "save_person_light.request", - "data": { - "id": "1", - "type": "person", - "first_name": "John" - }, - "valid": true - }, - { - "description": "Invalid person against person.light (strictness violation)", - "schema_id": "save_person_light.request", - "data": { - "id": "1", - "type": "person", - "first_name": "John", - "extra": "bad" - }, - "valid": false - }, - { - "description": "Invalid entity against person.light ad-hoc schema (ancestor not allowed)", - "schema_id": "save_person_light.request", - "data": { - "id": "1", - "type": "entity", - "first_name": "John" - }, - "valid": false - } - ] - }, - { - "description": "Ad-hocs extending ad-hocs (No type property)", - "database": { - "puncs": [ - { - "name": "save_address", - "schemas": [ - { - "$id": "address", - "type": "object", - "properties": { - "street": { - "type": "string" - }, - "city": { - "type": "string" - } - } - }, - { - "$id": "us_address", - "$ref": "address", - "properties": { - "state": { - "type": "string" - }, - "zip": { - "type": "string" - } - } - }, - { - "$id": "save_address.request", - "$ref": "us_address" - } - ] - } - ] - }, - "tests": [ - { - "description": "Valid us_address", - "schema_id": "save_address.request", - "data": { - "street": "123 Main", - "city": "Anytown", - "state": "CA", - "zip": "12345" - }, - "valid": true - }, - { - "description": "Invalid base address against us_address", - "schema_id": "save_address.request", - "data": { - "street": "123 Main", - "city": "Anytown" - }, - "valid": true - } - ] - }, - { - "description": "Ad-hocs extending ad-hocs (with string type property, no magic)", - "database": { - "puncs": [ - { - "name": "save_config", - "schemas": [ - { - "$id": "config_base", - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "config_base" - }, - "setting": { - "type": "string" - } - } - }, - { - "$id": "config_advanced", - "$ref": "config_base", - "properties": { - "type": { - "type": "string", - "const": "config_advanced" - }, - "advanced_setting": { - "type": "string" - } - } - }, - { - "$id": "save_config.request", - "$ref": "config_base" - } - ] - } - ] - }, - "tests": [ - { - "description": "Valid config_base against config_base", - "schema_id": "save_config.request", - "data": { - "type": "config_base", - "setting": "on" - }, - "valid": true - }, - { - "description": "Invalid config_advanced against config_base (no type magic, const is strictly 'config_base')", - "schema_id": "save_config.request", - "data": { - "type": "config_advanced", - "setting": "on", - "advanced_setting": "off" - }, - "valid": false - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/uniqueItems.json b/tests/fixtures/uniqueItems.json index 57fa866..c6bc510 100644 --- a/tests/fixtures/uniqueItems.json +++ b/tests/fixtures/uniqueItems.json @@ -4,9 +4,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "uniqueItems": true, - "extensible": true + "extensible": true, + "$id": "uniqueItems_0_0" } ] }, @@ -17,7 +17,8 @@ 1, 2 ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_0_0" }, { "description": "non-unique array of integers is invalid", @@ -25,7 +26,8 @@ 1, 1 ], - "valid": false + "valid": false, + "schema_id": "uniqueItems_0_0" }, { "description": "non-unique array of more than two integers is invalid", @@ -34,16 +36,18 @@ 2, 1 ], - "valid": false + "valid": false, + "schema_id": "uniqueItems_0_0" }, { "description": "numbers are unique if mathematically unequal", "data": [ - 1.0, - 1.00, + 1, + 1, 1 ], - "valid": false + "valid": false, + "schema_id": "uniqueItems_0_0" }, { "description": "false is not equal to zero", @@ -51,7 +55,8 @@ 0, false ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_0_0" }, { "description": "true is not equal to one", @@ -59,7 +64,8 @@ 1, true ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_0_0" }, { "description": "unique array of strings is valid", @@ -68,7 +74,8 @@ "bar", "baz" ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_0_0" }, { "description": "non-unique array of strings is invalid", @@ -77,7 +84,8 @@ "bar", "foo" ], - "valid": false + "valid": false, + "schema_id": "uniqueItems_0_0" }, { "description": "unique array of objects is valid", @@ -89,7 +97,8 @@ "foo": "baz" } ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_0_0" }, { "description": "non-unique array of objects is invalid", @@ -101,7 +110,8 @@ "foo": "bar" } ], - "valid": false + "valid": false, + "schema_id": "uniqueItems_0_0" }, { "description": "property order of array of objects is ignored", @@ -115,7 +125,8 @@ "foo": "bar" } ], - "valid": false + "valid": false, + "schema_id": "uniqueItems_0_0" }, { "description": "unique array of nested objects is valid", @@ -135,7 +146,8 @@ } } ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_0_0" }, { "description": "non-unique array of nested objects is invalid", @@ -155,7 +167,8 @@ } } ], - "valid": false + "valid": false, + "schema_id": "uniqueItems_0_0" }, { "description": "unique array of arrays is valid", @@ -167,7 +180,8 @@ "bar" ] ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_0_0" }, { "description": "non-unique array of arrays is invalid", @@ -179,7 +193,8 @@ "foo" ] ], - "valid": false + "valid": false, + "schema_id": "uniqueItems_0_0" }, { "description": "non-unique array of more than two arrays is invalid", @@ -194,7 +209,8 @@ "foo" ] ], - "valid": false + "valid": false, + "schema_id": "uniqueItems_0_0" }, { "description": "1 and true are unique", @@ -202,7 +218,8 @@ 1, true ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_0_0" }, { "description": "0 and false are unique", @@ -210,7 +227,8 @@ 0, false ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_0_0" }, { "description": "[1] and [true] are unique", @@ -222,7 +240,8 @@ true ] ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_0_0" }, { "description": "[0] and [false] are unique", @@ -234,7 +253,8 @@ false ] ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_0_0" }, { "description": "nested [1] and [true] are unique", @@ -252,7 +272,8 @@ "foo" ] ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_0_0" }, { "description": "nested [0] and [false] are unique", @@ -270,7 +291,8 @@ "foo" ] ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_0_0" }, { "description": "unique heterogeneous types are valid", @@ -284,7 +306,8 @@ 1, "{}" ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_0_0" }, { "description": "non-unique heterogeneous types are invalid", @@ -298,7 +321,8 @@ {}, 1 ], - "valid": false + "valid": false, + "schema_id": "uniqueItems_0_0" }, { "description": "different objects are unique", @@ -312,7 +336,8 @@ "b": 1 } ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_0_0" }, { "description": "objects are non-unique despite key order", @@ -326,7 +351,8 @@ "a": 1 } ], - "valid": false + "valid": false, + "schema_id": "uniqueItems_0_0" }, { "description": "{\"a\": false} and {\"a\": 0} are unique", @@ -338,7 +364,8 @@ "a": 0 } ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_0_0" }, { "description": "{\"a\": true} and {\"a\": 1} are unique", @@ -350,7 +377,8 @@ "a": 1 } ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_0_0" } ] }, @@ -359,7 +387,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "prefixItems": [ { "type": "boolean" @@ -369,7 +396,8 @@ } ], "uniqueItems": true, - "extensible": true + "extensible": true, + "$id": "uniqueItems_1_0" } ] }, @@ -380,7 +408,8 @@ false, true ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_1_0" }, { "description": "[true, false] from items array is valid", @@ -388,7 +417,8 @@ true, false ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_1_0" }, { "description": "[false, false] from items array is not valid", @@ -396,7 +426,8 @@ false, false ], - "valid": false + "valid": false, + "schema_id": "uniqueItems_1_0" }, { "description": "[true, true] from items array is not valid", @@ -404,7 +435,8 @@ true, true ], - "valid": false + "valid": false, + "schema_id": "uniqueItems_1_0" }, { "description": "unique array extended from [false, true] is valid", @@ -414,7 +446,8 @@ "foo", "bar" ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_1_0" }, { "description": "unique array extended from [true, false] is valid", @@ -424,7 +457,8 @@ "foo", "bar" ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_1_0" }, { "description": "non-unique array extended from [false, true] is not valid", @@ -434,7 +468,8 @@ "foo", "foo" ], - "valid": false + "valid": false, + "schema_id": "uniqueItems_1_0" }, { "description": "non-unique array extended from [true, false] is not valid", @@ -444,7 +479,8 @@ "foo", "foo" ], - "valid": false + "valid": false, + "schema_id": "uniqueItems_1_0" } ] }, @@ -453,7 +489,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "prefixItems": [ { "type": "boolean" @@ -463,7 +498,8 @@ } ], "uniqueItems": true, - "items": false + "items": false, + "$id": "uniqueItems_2_0" } ] }, @@ -474,7 +510,8 @@ false, true ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_2_0" }, { "description": "[true, false] from items array is valid", @@ -482,7 +519,8 @@ true, false ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_2_0" }, { "description": "[false, false] from items array is not valid", @@ -490,7 +528,8 @@ false, false ], - "valid": false + "valid": false, + "schema_id": "uniqueItems_2_0" }, { "description": "[true, true] from items array is not valid", @@ -498,7 +537,8 @@ true, true ], - "valid": false + "valid": false, + "schema_id": "uniqueItems_2_0" }, { "description": "extra items are invalid even if unique", @@ -507,7 +547,8 @@ true, null ], - "valid": false + "valid": false, + "schema_id": "uniqueItems_2_0" } ] }, @@ -516,9 +557,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "uniqueItems": false, - "extensible": true + "extensible": true, + "$id": "uniqueItems_3_0" } ] }, @@ -529,7 +570,8 @@ 1, 2 ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_3_0" }, { "description": "non-unique array of integers is valid", @@ -537,16 +579,18 @@ 1, 1 ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_3_0" }, { "description": "numbers are unique if mathematically unequal", "data": [ - 1.0, - 1.00, + 1, + 1, 1 ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_3_0" }, { "description": "false is not equal to zero", @@ -554,7 +598,8 @@ 0, false ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_3_0" }, { "description": "true is not equal to one", @@ -562,7 +607,8 @@ 1, true ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_3_0" }, { "description": "unique array of objects is valid", @@ -574,7 +620,8 @@ "foo": "baz" } ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_3_0" }, { "description": "non-unique array of objects is valid", @@ -586,7 +633,8 @@ "foo": "bar" } ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_3_0" }, { "description": "unique array of nested objects is valid", @@ -606,7 +654,8 @@ } } ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_3_0" }, { "description": "non-unique array of nested objects is valid", @@ -626,7 +675,8 @@ } } ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_3_0" }, { "description": "unique array of arrays is valid", @@ -638,7 +688,8 @@ "bar" ] ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_3_0" }, { "description": "non-unique array of arrays is valid", @@ -650,7 +701,8 @@ "foo" ] ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_3_0" }, { "description": "1 and true are unique", @@ -658,7 +710,8 @@ 1, true ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_3_0" }, { "description": "0 and false are unique", @@ -666,7 +719,8 @@ 0, false ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_3_0" }, { "description": "unique heterogeneous types are valid", @@ -679,7 +733,8 @@ null, 1 ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_3_0" }, { "description": "non-unique heterogeneous types are valid", @@ -693,7 +748,8 @@ {}, 1 ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_3_0" } ] }, @@ -702,7 +758,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "prefixItems": [ { "type": "boolean" @@ -712,7 +767,8 @@ } ], "uniqueItems": false, - "extensible": true + "extensible": true, + "$id": "uniqueItems_4_0" } ] }, @@ -723,7 +779,8 @@ false, true ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_4_0" }, { "description": "[true, false] from items array is valid", @@ -731,7 +788,8 @@ true, false ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_4_0" }, { "description": "[false, false] from items array is valid", @@ -739,7 +797,8 @@ false, false ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_4_0" }, { "description": "[true, true] from items array is valid", @@ -747,7 +806,8 @@ true, true ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_4_0" }, { "description": "unique array extended from [false, true] is valid", @@ -757,7 +817,8 @@ "foo", "bar" ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_4_0" }, { "description": "unique array extended from [true, false] is valid", @@ -767,7 +828,8 @@ "foo", "bar" ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_4_0" }, { "description": "non-unique array extended from [false, true] is valid", @@ -777,7 +839,8 @@ "foo", "foo" ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_4_0" }, { "description": "non-unique array extended from [true, false] is valid", @@ -787,7 +850,8 @@ "foo", "foo" ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_4_0" } ] }, @@ -796,7 +860,6 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "prefixItems": [ { "type": "boolean" @@ -806,7 +869,8 @@ } ], "uniqueItems": false, - "items": false + "items": false, + "$id": "uniqueItems_5_0" } ] }, @@ -817,7 +881,8 @@ false, true ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_5_0" }, { "description": "[true, false] from items array is valid", @@ -825,7 +890,8 @@ true, false ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_5_0" }, { "description": "[false, false] from items array is valid", @@ -833,7 +899,8 @@ false, false ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_5_0" }, { "description": "[true, true] from items array is valid", @@ -841,7 +908,8 @@ true, true ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_5_0" }, { "description": "extra items are invalid even if unique", @@ -850,7 +918,8 @@ true, null ], - "valid": false + "valid": false, + "schema_id": "uniqueItems_5_0" } ] }, @@ -859,9 +928,9 @@ "database": { "schemas": [ { - "$schema": "https://json-schema.org/draft/2020-12/schema", "uniqueItems": true, - "extensible": true + "extensible": true, + "$id": "uniqueItems_6_0" } ] }, @@ -872,7 +941,8 @@ 1, 1 ], - "valid": false + "valid": false, + "schema_id": "uniqueItems_6_0" }, { "description": "extra unique items valid", @@ -880,7 +950,8 @@ 1, 2 ], - "valid": true + "valid": true, + "schema_id": "uniqueItems_6_0" } ] } diff --git a/tests/lib.rs b/tests/lib.rs index 6406947..5437315 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -89,20 +89,7 @@ fn test_library_api() { }) ); - // 6. Mask Happy Path - let mask_drop = mask_json_schema( - "test_schema", - JsonB(json!({"name": "Neo", "extra": "data"})), - ); - assert_eq!( - mask_drop.0, - json!({ - "type": "drop", - "response": {"name": "Neo"} - }) - ); - - // 7. Clear Schemas + // 6. Clear Schemas let clear_drop = clear_json_schemas(); assert_eq!( clear_drop.0,