From 44be75f5d45fa0406d4405d33df666e7bd194b2e Mon Sep 17 00:00:00 2001 From: Alex Groleau Date: Wed, 11 Mar 2026 05:18:01 -0400 Subject: [PATCH] queryer merger test progress --- GEMINI.md | 46 +- build.rs | 44 +- fixtures/additionalProperties.json | 176 + fixtures/allOf.json | 677 ++ fixtures/booleanSchema.json | 197 + fixtures/const.json | 818 +++ fixtures/contains.json | 418 ++ fixtures/content.json | 232 + fixtures/dependencies.json | 748 +++ fixtures/emptyString.json | 163 + fixtures/enum.json | 736 +++ fixtures/exclusiveMaximum.json | 51 + fixtures/exclusiveMinimum.json | 51 + fixtures/families.json | 217 + fixtures/format.json | 5456 +++++++++++++++++ fixtures/if-then-else.json | 594 ++ fixtures/items.json | 966 +++ fixtures/maxContains.json | 235 + fixtures/maxItems.json | 126 + fixtures/maxLength.json | 91 + fixtures/maxProperties.json | 193 + fixtures/maximum.json | 100 + fixtures/merge.json | 274 + fixtures/merger.json | 149 + fixtures/minContains.json | 477 ++ fixtures/minItems.json | 117 + fixtures/minLength.json | 91 + fixtures/minProperties.json | 135 + fixtures/minimum.json | 127 + fixtures/multipleOf.json | 136 + fixtures/not.json | 618 ++ fixtures/oneOf.json | 670 ++ fixtures/pattern.json | 109 + fixtures/patternProperties.json | 399 ++ fixtures/prefixItems.json | 229 + fixtures/properties.json | 627 ++ fixtures/propertyNames.json | 347 ++ fixtures/queryer.json | 599 ++ fixtures/ref.json | 929 +++ fixtures/required.json | 312 + fixtures/type.json | 912 +++ fixtures/uniqueItems.json | 1171 ++++ migrate_fixtures.js | 58 - .../database/executors/mock.rs | 27 +- src/database/executors/mod.rs | 28 + .../{executor.rs => executors/pgrx.rs} | 17 +- src/database/mod.rs | 264 +- src/database/punc.rs | 10 - src/database/schema.rs | 16 +- src/database/stem.rs | 17 + src/jspg.rs | 8 +- src/lib.rs | 183 +- src/merger/mod.rs | 21 +- src/queryer/compiler.rs | 305 +- src/queryer/mod.rs | 50 +- src/tests/fixtures.rs | 1686 ++--- tests/lib.rs => src/tests/mod.rs | 13 +- src/tests/runner.rs | 113 + src/tests/types/case.rs | 167 + src/tests/types/expect.rs | 122 + src/tests/types/mod.rs | 7 + src/tests/types/suite.rs | 10 + src/validator/mod.rs | 39 +- src/validator/util.rs | 127 - tests/database/mod.rs | 1 - tests/fixtures.rs | 1669 ----- tests/fixtures/additionalProperties.json | 152 - tests/fixtures/allOf.json | 590 -- tests/fixtures/booleanSchema.json | 143 - tests/fixtures/const.json | 650 -- tests/fixtures/contains.json | 346 -- tests/fixtures/content.json | 178 - tests/fixtures/dependencies.json | 619 -- tests/fixtures/emptyString.json | 133 - tests/fixtures/enum.json | 595 -- tests/fixtures/exclusiveMaximum.json | 39 - tests/fixtures/exclusiveMinimum.json | 39 - tests/fixtures/families.json | 199 - tests/fixtures/format.json | 3770 ------------ tests/fixtures/if-then-else.json | 495 -- tests/fixtures/items.json | 843 --- tests/fixtures/maxContains.json | 196 - tests/fixtures/maxItems.json | 105 - tests/fixtures/maxLength.json | 70 - tests/fixtures/maxProperties.json | 157 - tests/fixtures/maximum.json | 76 - tests/fixtures/merge.json | 247 - tests/fixtures/minContains.json | 390 -- tests/fixtures/minItems.json | 96 - tests/fixtures/minLength.json | 70 - tests/fixtures/minProperties.json | 108 - tests/fixtures/minimum.json | 94 - tests/fixtures/multipleOf.json | 109 - tests/fixtures/not.json | 489 -- tests/fixtures/oneOf.json | 568 -- tests/fixtures/pattern.json | 82 - tests/fixtures/patternProperties.json | 321 - tests/fixtures/prefixItems.json | 193 - tests/fixtures/properties.json | 543 -- tests/fixtures/propertyNames.json | 281 - tests/fixtures/ref.json | 833 --- tests/fixtures/required.json | 255 - tests/fixtures/type.json | 669 -- tests/fixtures/uniqueItems.json | 958 --- 104 files changed, 22563 insertions(+), 18859 deletions(-) create mode 100644 fixtures/additionalProperties.json create mode 100644 fixtures/allOf.json create mode 100644 fixtures/booleanSchema.json create mode 100644 fixtures/const.json create mode 100644 fixtures/contains.json create mode 100644 fixtures/content.json create mode 100644 fixtures/dependencies.json create mode 100644 fixtures/emptyString.json create mode 100644 fixtures/enum.json create mode 100644 fixtures/exclusiveMaximum.json create mode 100644 fixtures/exclusiveMinimum.json create mode 100644 fixtures/families.json create mode 100644 fixtures/format.json create mode 100644 fixtures/if-then-else.json create mode 100644 fixtures/items.json create mode 100644 fixtures/maxContains.json create mode 100644 fixtures/maxItems.json create mode 100644 fixtures/maxLength.json create mode 100644 fixtures/maxProperties.json create mode 100644 fixtures/maximum.json create mode 100644 fixtures/merge.json create mode 100644 fixtures/merger.json create mode 100644 fixtures/minContains.json create mode 100644 fixtures/minItems.json create mode 100644 fixtures/minLength.json create mode 100644 fixtures/minProperties.json create mode 100644 fixtures/minimum.json create mode 100644 fixtures/multipleOf.json create mode 100644 fixtures/not.json create mode 100644 fixtures/oneOf.json create mode 100644 fixtures/pattern.json create mode 100644 fixtures/patternProperties.json create mode 100644 fixtures/prefixItems.json create mode 100644 fixtures/properties.json create mode 100644 fixtures/propertyNames.json create mode 100644 fixtures/queryer.json create mode 100644 fixtures/ref.json create mode 100644 fixtures/required.json create mode 100644 fixtures/type.json create mode 100644 fixtures/uniqueItems.json delete mode 100644 migrate_fixtures.js rename tests/database/executor.rs => src/database/executors/mock.rs (54%) create mode 100644 src/database/executors/mod.rs rename src/database/{executor.rs => executors/pgrx.rs} (80%) create mode 100644 src/database/stem.rs rename tests/lib.rs => src/tests/mod.rs (87%) create mode 100644 src/tests/runner.rs create mode 100644 src/tests/types/case.rs create mode 100644 src/tests/types/expect.rs create mode 100644 src/tests/types/mod.rs create mode 100644 src/tests/types/suite.rs delete mode 100644 src/validator/util.rs delete mode 100644 tests/database/mod.rs delete mode 100644 tests/fixtures.rs delete mode 100644 tests/fixtures/additionalProperties.json delete mode 100644 tests/fixtures/allOf.json delete mode 100644 tests/fixtures/booleanSchema.json delete mode 100644 tests/fixtures/const.json delete mode 100644 tests/fixtures/contains.json delete mode 100644 tests/fixtures/content.json delete mode 100644 tests/fixtures/dependencies.json delete mode 100644 tests/fixtures/emptyString.json delete mode 100644 tests/fixtures/enum.json delete mode 100644 tests/fixtures/exclusiveMaximum.json delete mode 100644 tests/fixtures/exclusiveMinimum.json delete mode 100644 tests/fixtures/families.json delete mode 100644 tests/fixtures/format.json delete mode 100644 tests/fixtures/if-then-else.json delete mode 100644 tests/fixtures/items.json delete mode 100644 tests/fixtures/maxContains.json delete mode 100644 tests/fixtures/maxItems.json delete mode 100644 tests/fixtures/maxLength.json delete mode 100644 tests/fixtures/maxProperties.json delete mode 100644 tests/fixtures/maximum.json delete mode 100644 tests/fixtures/merge.json delete mode 100644 tests/fixtures/minContains.json delete mode 100644 tests/fixtures/minItems.json delete mode 100644 tests/fixtures/minLength.json delete mode 100644 tests/fixtures/minProperties.json delete mode 100644 tests/fixtures/minimum.json delete mode 100644 tests/fixtures/multipleOf.json delete mode 100644 tests/fixtures/not.json delete mode 100644 tests/fixtures/oneOf.json delete mode 100644 tests/fixtures/pattern.json delete mode 100644 tests/fixtures/patternProperties.json delete mode 100644 tests/fixtures/prefixItems.json delete mode 100644 tests/fixtures/properties.json delete mode 100644 tests/fixtures/propertyNames.json delete mode 100644 tests/fixtures/ref.json delete mode 100644 tests/fixtures/required.json delete mode 100644 tests/fixtures/type.json delete mode 100644 tests/fixtures/uniqueItems.json diff --git a/GEMINI.md b/GEMINI.md index 324d473..a1a00a2 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -44,18 +44,22 @@ JSPG implements specific extensions to the Draft 2020-12 standard to support the * **Shape Polymorphism (`$family`)**: Auto-expands polymorphic API lists based on an abstract Descendants Graph. If `{"$family": "widget"}` is used, JSPG evaluates the JSON against every schema that `$ref`s widget. * **Strict Matches & Depth Heuristic**: Polymorphic structures MUST match exactly **one** schema permutation. If multiple inherited struct permutations pass, JSPG applies the **Depth Heuristic Tie-Breaker**, selecting the candidate deepest in the inheritance tree. -#### B. Strict by Default & Extensibility +#### B. Dot-Notation Schema Resolution & Database Mapping +* **The Dot Convention**: When a schema represents a specific variation or shape of an underlying physical database `Type` (e.g., a "summary" of a "person"), its `$id` must adhere to a dot-notation suffix convention (e.g., `summary.person` or `full.person`). +* **Entity Resolution**: The framework (Validator, Queryer, Merger) dynamically determines the backing PostgreSQL table structure by splitting the schema's `$id` (or `$ref`) by `.` and extracting the **last segment** (`next_back()`). If the last segment matches a known Database Type (like `person`), the framework natively applies that table's inheritance rules, variations, and physical foreign keys to the schema graph, regardless of the prefix. + +#### C. Strict by Default & Extensibility * **Strictness**: By default, any property not explicitly defined in the schema causes a validation error (effectively enforcing `additionalProperties: false` globally). * **Extensibility (`extensible: true`)**: To allow a free-for-all of undefined properties, schemas must explicitly declare `"extensible": true`. * **Structured Additional Properties**: If `additionalProperties: {...}` is defined as a schema, arbitrary keys are allowed so long as their values match the defined type constraint. * **Inheritance Boundaries**: Strictness resets when crossing `$ref` boundaries. A schema extending a strict parent remains strict unless it explicitly overrides with `"extensible": true`. -#### C. Implicit Keyword Shadowing +#### D. Implicit Keyword Shadowing * **Inheritance (`$ref` + properties)**: Unlike standard JSON Schema, when a schema uses `$ref` alongside local properties, JSPG implements **Smart Merge**. Local constraints natively take precedence over (shadow) inherited constraints for the same keyword. * *Example*: If `entity` has `type: {const: "entity"}`, but `person` defines `type: {const: "person"}`, the local `person` const cleanly overrides the inherited one. * **Composition (`allOf`)**: When evaluating `allOf`, standard intersection rules apply seamlessly. No shadowing occurs, meaning all constraints from all branches must pass. -#### D. Format Leniency for Empty Strings +#### E. Format Leniency for Empty Strings To simplify frontend form validation, format validators specifically for `uuid`, `date-time`, and `email` explicitly allow empty strings (`""`), treating them as "present but unset". --- @@ -85,10 +89,36 @@ The Merger provides an automated, high-performance graph synchronization engine The Queryer transforms Postgres into a pre-compiled Semantic Query Engine via the `jspg_query(schema_id text, cue jsonb)` API, designed to serve the exact shape of Punc responses directly via SQL. ### Core Features -* **Schema-to-SQL Compilation**: Compiles JSON Schema ASTs spanning deep arrays directly into static, pre-planned SQL multi-JOIN queries. +* **Schema-to-SQL Compilation**: Compiles JSON Schema ASTs spanning deep arrays directly into static, pre-planned SQL multi-JOIN queries. This explicitly features the `Smart Merge` evaluation engine which natively translates properties through `allOf` and `$ref` inheritances, mapping JSON fields specifically to their physical database table aliases during translation. * **DashMap SQL Caching**: Executes compiled SQL via Postgres SPI execution, securely caching the static string compilation templates per schema permutation inside the `GLOBAL_JSPG` application memory, drastically reducing repetitive schema crawling. * **Dynamic Filtering**: Binds parameters natively through `cue.filters` objects. Dynamically handles string formatting (e.g. parsing `uuid` or formatting date-times) and safely escapes complex combinations utilizing `ILIKE` operations correctly mapped to the originating structural table. -* **The Stem Engine**: Rather than over-fetching heavy Entity payloads and trimming them, Punc Framework Websockets depend on isolated subgraphs defined as **Stems**. - * During initialization, the generator auto-discovers graph boundaries (Stems) inside the schema tree. - * The Queryer prepares dedicated SQL execution templates tailored precisely for that exact `Stem` path (e.g. executing `get_dashboard` queried specifically for the `/owner` stem). - * These Stem outputs instantly hydrate targeted Go Bitsets, providing `O(1)` real-time routing for fractional data payloads without any application-layer overhead. \ No newline at end of file +### 4. The Stem Engine + +Rather than over-fetching heavy Entity payloads and trimming them, Punc Framework Websockets depend on isolated subgraphs defined as **Stems**. +A `Stem` is **not a JSON Pointer** or a physical path string (like `/properties/contacts/items/phone_number`). It is simply a declaration of an **Entity Type boundary** that exists somewhere within the compiled JSON Schema graph. + +Because `pg_notify` (Beats) fire rigidly from physical Postgres tables (e.g. `{"type": "phone_number"}`), the Go Framework only ever needs to know: "Does the schema `with_contacts.person` contain the `phone_number` Entity anywhere inside its tree?" + +* **Initialization:** During startup (`jspg_stems()`), the database crawls all Schemas and maps out every physical Entity Type it references. It builds a flat dictionary of `Schema ID -> [Entity Types]` (e.g. `with_contacts.person -> ["person", "contact", "phone_number", "email_address"]`). +* **Relationship Path Squashing:** When calculating nested string paths structurally to discover these boundaries, JSPG intentionally **omits** properties natively named `target` or `source` if they belong to a native database `relationship` table override. This ensures paths like `phone_numbers/contact/target` correctly register their beat resolution pattern as `phone_numbers/contact/phone_number`. +* **The Go Router**: The Golang Punc framework uses this exact mapping to register WebSocket Beat frequencies exclusively on the Entity types discovered. +* **The Queryer Execution**: When the Go framework asks JSPG to hydrate a partial `phone_number` stem for the `with_contacts.person` schema, instead of jumping through string paths, the SQL Compiler simply reaches into the Schema's AST using the `phone_number` Type string, pulls out exactly that entity's mapping rules, and returns a fully correlated `SELECT` block! This natively handles nested array properties injected via `oneOf` or array references efficiently bypassing runtime powerset expansion. +* **Performance:** These Stem execution structures are fully statically compiled via SPI and map perfectly to `O(1)` real-time routing logic on the application tier. + + +## 5. Testing & Execution Architecture + +JSPG implements a strict separation of concerns to bypass the need to boot a full PostgreSQL cluster for unit and integration testing. Because `pgrx::spi::Spi` directly links to PostgreSQL C-headers, building the library with `cargo test` on macOS natively normally results in fatal `dyld` crashes. + +To solve this, JSPG introduces the `DatabaseExecutor` trait inside `src/database/executors/`: + +* **`SpiExecutor` (`pgrx.rs`)**: The production evaluator that is conditionally compiled (`#[cfg(not(test))]`). It unwraps standard `pgrx::spi` connections to the database. +* **`MockExecutor` (`mock.rs`)**: The testing evaluator that is conditionally compiled (`#[cfg(test)]`). It absorbs SQL calls and captures parameter bindings in memory without executing them. + +### Universal Test Harness (`src/tests/`) +JSPG abandons the standard `cargo pgrx test` model in favor of native OS testing for a >1000x speed increase (`~0.05s` execution). + +1. **JSON Fixtures**: All core interactions are defined abstractly as JSON arrays in `fixtures/`. Each file contains suites of `TestCase` objects with an `action` flag (`validate`, `merge`, `query`). +2. **`build.rs` Generator**: The build script traverses the JSON fixtures, extracts their structural identities, and generates standard `#[test]` blocks into `src/tests/fixtures.rs`. +3. **Modular Test Dispatcher**: The `src/tests/types/` module deserializes the abstract JSON test payloads into `Suite`, `Case`, and `Expect` data structures. +4. **Unit Context Execution**: When `cargo test` executes, the `Runner` feeds the JSON payloads directly into `case.execute(db)`. Because the tests run natively inside the module via `#cfg(test)`, the Rust compiler globally erases `pgrx` C-linkage, instantiates the `MockExecutor`, and allows for pure structural evaluation of complex database logic completely in memory. diff --git a/build.rs b/build.rs index 4dfc464..e889c96 100644 --- a/build.rs +++ b/build.rs @@ -21,22 +21,15 @@ fn to_safe_identifier(name: &str) -> String { } fn main() { - println!("cargo:rerun-if-changed=tests/fixtures"); + println!("cargo:rerun-if-changed=fixtures"); println!("cargo:rerun-if-changed=Cargo.toml"); - // File 1: src/tests/fixtures.rs for #[pg_test] - let pg_dest_path = Path::new("src/tests/fixtures.rs"); - let mut pg_file = File::create(pg_dest_path).unwrap(); - - // File 2: tests/fixtures.rs for standard #[test] integration - let std_dest_path = Path::new("tests/fixtures.rs"); + // File: src/tests/fixtures.rs for standard #[test] integration + let std_dest_path = Path::new("src/tests/fixtures.rs"); let mut std_file = File::create(std_dest_path).unwrap(); - // Write headers - writeln!(std_file, "use jspg::validator::util;").unwrap(); - // Walk tests/fixtures directly - let fixtures_path = "tests/fixtures"; + let fixtures_path = "fixtures"; if Path::new(fixtures_path).exists() { for entry in fs::read_dir(fixtures_path).unwrap() { let entry = entry.unwrap(); @@ -72,13 +65,9 @@ fn main() { .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") - { + if !t_obj.contains_key("description") { panic!( - "File {} suite {} test {} is missing required case fields (description, data, valid, schema_id)", + "File {} suite {} test {} is missing required case fields (description)", file_name, i, t_idx ); } @@ -88,29 +77,14 @@ fn main() { let safe_filename = to_safe_identifier(file_name); let fn_name = format!("test_{}_{}", safe_filename, i); - // Write to src/tests.rs (PG Test) - // CARGO_MANIFEST_DIR is used to find the absolute path to fixtures at runtime - write!( - pg_file, - r#" -#[pg_test] -fn {}() {{ - let path = format!("{{}}/tests/fixtures/{}.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, {}).unwrap(); -}} -"#, - fn_name, file_name, i - ) - .unwrap(); - - // Write to tests/tests.rs (Std Test) + // Write to src/tests/fixtures.rs (Std Test) write!( std_file, r#" #[test] fn {}() {{ - let path = format!("{{}}/tests/fixtures/{}.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, {}).unwrap(); + let path = format!("{{}}/fixtures/{}.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, {}).unwrap(); }} "#, fn_name, file_name, i diff --git a/fixtures/additionalProperties.json b/fixtures/additionalProperties.json new file mode 100644 index 0000000..f7ed365 --- /dev/null +++ b/fixtures/additionalProperties.json @@ -0,0 +1,176 @@ +[ + { + "description": "additionalProperties validates properties not matched by properties", + "database": { + "schemas": [ + { + "$id": "schema1", + "properties": { + "foo": { + "type": "string" + }, + "bar": { + "type": "number" + } + }, + "additionalProperties": { + "type": "boolean" + } + } + ] + }, + "tests": [ + { + "description": "defined properties are valid", + "data": { + "foo": "value", + "bar": 123 + }, + "schema_id": "schema1", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "additional property matching schema is valid", + "data": { + "foo": "value", + "is_active": true, + "hidden": false + }, + "schema_id": "schema1", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "additional property not matching schema is invalid", + "data": { + "foo": "value", + "is_active": 1 + }, + "schema_id": "schema1", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "extensible: true with additionalProperties still validates structure", + "database": { + "schemas": [ + { + "properties": { + "foo": { + "type": "string" + } + }, + "extensible": true, + "additionalProperties": { + "type": "integer" + }, + "$id": "additionalProperties_1_0" + } + ] + }, + "tests": [ + { + "description": "additional property matching schema is valid", + "data": { + "foo": "hello", + "count": 5, + "age": 42 + }, + "schema_id": "additionalProperties_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "additional property not matching schema is invalid despite extensible: true", + "data": { + "foo": "hello", + "count": "five" + }, + "schema_id": "additionalProperties_1_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "complex additionalProperties with object and array items", + "database": { + "schemas": [ + { + "$id": "schema3", + "properties": { + "type": { + "type": "string" + } + }, + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + } + ] + }, + "tests": [ + { + "description": "valid array of strings", + "data": { + "type": "my_type", + "group_a": [ + "field1", + "field2" + ], + "group_b": [ + "field3" + ] + }, + "schema_id": "schema3", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "invalid array of integers", + "data": { + "type": "my_type", + "group_a": [ + 1, + 2 + ] + }, + "schema_id": "schema3", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid non-array type", + "data": { + "type": "my_type", + "group_a": "field1" + }, + "schema_id": "schema3", + "action": "validate", + "expect": { + "success": false + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/allOf.json b/fixtures/allOf.json new file mode 100644 index 0000000..9fdc012 --- /dev/null +++ b/fixtures/allOf.json @@ -0,0 +1,677 @@ +[ + { + "description": "allOf", + "database": { + "schemas": [ + { + "allOf": [ + { + "properties": { + "bar": { + "type": "integer" + } + }, + "required": [ + "bar" + ] + }, + { + "properties": { + "foo": { + "type": "string" + } + }, + "required": [ + "foo" + ] + } + ], + "$id": "allOf_0_0" + } + ] + }, + "tests": [ + { + "description": "allOf", + "data": { + "foo": "baz", + "bar": 2 + }, + "schema_id": "allOf_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "mismatch second", + "data": { + "foo": "baz" + }, + "schema_id": "allOf_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "mismatch first", + "data": { + "bar": 2 + }, + "schema_id": "allOf_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "wrong type", + "data": { + "foo": "baz", + "bar": "quux" + }, + "schema_id": "allOf_0_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "allOf with base schema", + "database": { + "schemas": [ + { + "properties": { + "bar": { + "type": "integer" + }, + "baz": {}, + "foo": { + "type": "string" + } + }, + "required": [ + "bar" + ], + "allOf": [ + { + "properties": { + "foo": { + "type": "string" + } + }, + "required": [ + "foo" + ] + }, + { + "properties": { + "baz": { + "type": "null" + } + }, + "required": [ + "baz" + ] + } + ], + "$id": "allOf_1_0" + } + ] + }, + "tests": [ + { + "description": "valid", + "data": { + "foo": "quux", + "bar": 2, + "baz": null + }, + "schema_id": "allOf_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "mismatch base schema", + "data": { + "foo": "quux", + "baz": null + }, + "schema_id": "allOf_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "mismatch first allOf", + "data": { + "bar": 2, + "baz": null + }, + "schema_id": "allOf_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "mismatch second allOf", + "data": { + "foo": "quux", + "bar": 2 + }, + "schema_id": "allOf_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "mismatch both", + "data": { + "bar": 2 + }, + "schema_id": "allOf_1_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "allOf simple types", + "database": { + "schemas": [ + { + "allOf": [ + { + "maximum": 30 + }, + { + "minimum": 20 + } + ], + "$id": "allOf_2_0" + } + ] + }, + "tests": [ + { + "description": "valid", + "data": 25, + "schema_id": "allOf_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "mismatch one", + "data": 35, + "schema_id": "allOf_2_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "allOf with boolean schemas, all true", + "database": { + "schemas": [ + { + "allOf": [ + true, + true + ], + "$id": "allOf_3_0" + } + ] + }, + "tests": [ + { + "description": "any value is valid", + "data": "foo", + "schema_id": "allOf_3_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "allOf with boolean schemas, some false", + "database": { + "schemas": [ + { + "allOf": [ + true, + false + ], + "$id": "allOf_4_0" + } + ] + }, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "schema_id": "allOf_4_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "allOf with boolean schemas, all false", + "database": { + "schemas": [ + { + "allOf": [ + false, + false + ], + "$id": "allOf_5_0" + } + ] + }, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "schema_id": "allOf_5_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "allOf with one empty schema", + "database": { + "schemas": [ + { + "allOf": [ + {} + ], + "$id": "allOf_6_0" + } + ] + }, + "tests": [ + { + "description": "any data is valid", + "data": 1, + "schema_id": "allOf_6_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "allOf with two empty schemas", + "database": { + "schemas": [ + { + "allOf": [ + {}, + {} + ], + "$id": "allOf_7_0" + } + ] + }, + "tests": [ + { + "description": "any data is valid", + "data": 1, + "schema_id": "allOf_7_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "allOf with the first empty schema", + "database": { + "schemas": [ + { + "allOf": [ + {}, + { + "type": "number" + } + ], + "$id": "allOf_8_0" + } + ] + }, + "tests": [ + { + "description": "number is valid", + "data": 1, + "schema_id": "allOf_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "string is invalid", + "data": "foo", + "schema_id": "allOf_8_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "allOf with the last empty schema", + "database": { + "schemas": [ + { + "allOf": [ + { + "type": "number" + }, + {} + ], + "$id": "allOf_9_0" + } + ] + }, + "tests": [ + { + "description": "number is valid", + "data": 1, + "schema_id": "allOf_9_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "string is invalid", + "data": "foo", + "schema_id": "allOf_9_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "nested allOf, to check validation semantics", + "database": { + "schemas": [ + { + "allOf": [ + { + "allOf": [ + { + "type": "null" + } + ] + } + ], + "$id": "allOf_10_0" + } + ] + }, + "tests": [ + { + "description": "null is valid", + "data": null, + "schema_id": "allOf_10_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "anything non-null is invalid", + "data": 123, + "schema_id": "allOf_10_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "extensible: true allows extra properties in allOf", + "database": { + "schemas": [ + { + "allOf": [ + { + "properties": { + "bar": { + "type": "integer" + } + }, + "required": [ + "bar" + ] + }, + { + "properties": { + "foo": { + "type": "string" + } + }, + "required": [ + "foo" + ] + } + ], + "extensible": true, + "$id": "allOf_12_0" + } + ] + }, + "tests": [ + { + "description": "extra property is valid", + "data": { + "foo": "baz", + "bar": 2, + "qux": 3 + }, + "schema_id": "allOf_12_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "strict by default with allOf properties", + "database": { + "schemas": [ + { + "allOf": [ + { + "properties": { + "foo": { + "const": 1 + } + } + }, + { + "properties": { + "bar": { + "const": 2 + } + } + } + ], + "$id": "allOf_13_0" + } + ] + }, + "tests": [ + { + "description": "validates merged properties", + "data": { + "foo": 1, + "bar": 2 + }, + "schema_id": "allOf_13_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "fails on extra property z explicitly", + "data": { + "foo": 1, + "bar": 2, + "z": 3 + }, + "schema_id": "allOf_13_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "allOf with nested extensible: true (partial looseness)", + "database": { + "schemas": [ + { + "allOf": [ + { + "properties": { + "foo": { + "const": 1 + } + } + }, + { + "extensible": true, + "properties": { + "bar": { + "const": 2 + } + } + } + ], + "$id": "allOf_14_0" + } + ] + }, + "tests": [ + { + "description": "extensible subschema doesn't make root extensible if root is strict", + "data": { + "foo": 1, + "bar": 2, + "z": 3 + }, + "schema_id": "allOf_14_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "strictness: allOf composition with strict refs", + "database": { + "schemas": [ + { + "allOf": [ + { + "$ref": "partA" + }, + { + "$ref": "partB" + } + ], + "$id": "allOf_15_0" + }, + { + "$id": "partA", + "properties": { + "id": { + "type": "string" + } + } + }, + { + "$id": "partB", + "properties": { + "name": { + "type": "string" + } + } + } + ] + }, + "tests": [ + { + "description": "merged instance is valid", + "data": { + "id": "1", + "name": "Me" + }, + "schema_id": "allOf_15_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "extra property is invalid (root is strict)", + "data": { + "id": "1", + "name": "Me", + "extra": 1 + }, + "schema_id": "allOf_15_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "partA mismatch is invalid", + "data": { + "id": 1, + "name": "Me" + }, + "schema_id": "allOf_15_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/booleanSchema.json b/fixtures/booleanSchema.json new file mode 100644 index 0000000..5eb5511 --- /dev/null +++ b/fixtures/booleanSchema.json @@ -0,0 +1,197 @@ +[ + { + "description": "boolean schema 'true'", + "database": { + "schemas": [ + { + "$id": "booleanSchema_0_0" + } + ] + }, + "tests": [ + { + "description": "number is valid", + "data": 1, + "schema_id": "booleanSchema_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "string is valid", + "data": "foo", + "schema_id": "booleanSchema_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "boolean true is valid", + "data": true, + "schema_id": "booleanSchema_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "boolean false is valid", + "data": false, + "schema_id": "booleanSchema_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "null is valid", + "data": null, + "schema_id": "booleanSchema_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "object is valid", + "data": { + "foo": "bar" + }, + "schema_id": "booleanSchema_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "empty object is valid", + "data": {}, + "schema_id": "booleanSchema_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "array is valid", + "data": [ + "foo" + ], + "schema_id": "booleanSchema_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "empty array is valid", + "data": [], + "schema_id": "booleanSchema_0_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "boolean schema 'false'", + "database": { + "schemas": [ + { + "not": {}, + "$id": "booleanSchema_1_0" + } + ] + }, + "tests": [ + { + "description": "number is invalid", + "data": 1, + "schema_id": "booleanSchema_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "string is invalid", + "data": "foo", + "schema_id": "booleanSchema_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "boolean true is invalid", + "data": true, + "schema_id": "booleanSchema_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "boolean false is invalid", + "data": false, + "schema_id": "booleanSchema_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "null is invalid", + "data": null, + "schema_id": "booleanSchema_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "object is invalid", + "data": { + "foo": "bar" + }, + "schema_id": "booleanSchema_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "empty object is invalid", + "data": {}, + "schema_id": "booleanSchema_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "array is invalid", + "data": [ + "foo" + ], + "schema_id": "booleanSchema_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "empty array is invalid", + "data": [], + "schema_id": "booleanSchema_1_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/const.json b/fixtures/const.json new file mode 100644 index 0000000..866c644 --- /dev/null +++ b/fixtures/const.json @@ -0,0 +1,818 @@ +[ + { + "description": "const validation", + "database": { + "schemas": [ + { + "const": 2, + "$id": "const_0_0" + } + ] + }, + "tests": [ + { + "description": "same value is valid", + "data": 2, + "schema_id": "const_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "another value is invalid", + "data": 5, + "schema_id": "const_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "another type is invalid", + "data": "a", + "schema_id": "const_0_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "const with object", + "database": { + "schemas": [ + { + "const": { + "foo": "bar", + "baz": "bax" + }, + "properties": { + "foo": {}, + "baz": {} + }, + "$id": "const_1_0" + } + ] + }, + "tests": [ + { + "description": "same object is valid", + "data": { + "foo": "bar", + "baz": "bax" + }, + "schema_id": "const_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "same object with different property order is valid", + "data": { + "baz": "bax", + "foo": "bar" + }, + "schema_id": "const_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "another object is invalid", + "data": { + "foo": "bar" + }, + "schema_id": "const_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "another type is invalid", + "data": [ + 1, + 2 + ], + "schema_id": "const_1_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "const with array", + "database": { + "schemas": [ + { + "const": [ + { + "foo": "bar" + } + ], + "$id": "const_2_0" + } + ] + }, + "tests": [ + { + "description": "same array is valid", + "data": [ + { + "foo": "bar" + } + ], + "schema_id": "const_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "another array item is invalid", + "data": [ + 2 + ], + "schema_id": "const_2_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "array with additional items is invalid", + "data": [ + 1, + 2, + 3 + ], + "schema_id": "const_2_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "const with null", + "database": { + "schemas": [ + { + "const": null, + "$id": "const_3_0" + } + ] + }, + "tests": [ + { + "description": "null is valid", + "data": null, + "schema_id": "const_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "not null is invalid", + "data": 0, + "schema_id": "const_3_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "const with false does not match 0", + "database": { + "schemas": [ + { + "const": false, + "$id": "const_4_0" + } + ] + }, + "tests": [ + { + "description": "false is valid", + "data": false, + "schema_id": "const_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "integer zero is invalid", + "data": 0, + "schema_id": "const_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "float zero is invalid", + "data": 0, + "schema_id": "const_4_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "const with true does not match 1", + "database": { + "schemas": [ + { + "const": true, + "$id": "const_5_0" + } + ] + }, + "tests": [ + { + "description": "true is valid", + "data": true, + "schema_id": "const_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "integer one is invalid", + "data": 1, + "schema_id": "const_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "float one is invalid", + "data": 1, + "schema_id": "const_5_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "const with [false] does not match [0]", + "database": { + "schemas": [ + { + "const": [ + false + ], + "$id": "const_6_0" + } + ] + }, + "tests": [ + { + "description": "[false] is valid", + "data": [ + false + ], + "schema_id": "const_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "[0] is invalid", + "data": [ + 0 + ], + "schema_id": "const_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "[0.0] is invalid", + "data": [ + 0 + ], + "schema_id": "const_6_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "const with [true] does not match [1]", + "database": { + "schemas": [ + { + "const": [ + true + ], + "$id": "const_7_0" + } + ] + }, + "tests": [ + { + "description": "[true] is valid", + "data": [ + true + ], + "schema_id": "const_7_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "[1] is invalid", + "data": [ + 1 + ], + "schema_id": "const_7_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "[1.0] is invalid", + "data": [ + 1 + ], + "schema_id": "const_7_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "const with {\"a\": false} does not match {\"a\": 0}", + "database": { + "schemas": [ + { + "const": { + "a": false + }, + "$id": "const_8_0" + } + ] + }, + "tests": [ + { + "description": "{\"a\": false} is valid", + "data": { + "a": false + }, + "schema_id": "const_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "{\"a\": 0} is invalid", + "data": { + "a": 0 + }, + "schema_id": "const_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "{\"a\": 0.0} is invalid", + "data": { + "a": 0 + }, + "schema_id": "const_8_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "const with {\"a\": true} does not match {\"a\": 1}", + "database": { + "schemas": [ + { + "const": { + "a": true + }, + "$id": "const_9_0" + } + ] + }, + "tests": [ + { + "description": "{\"a\": true} is valid", + "data": { + "a": true + }, + "schema_id": "const_9_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "{\"a\": 1} is invalid", + "data": { + "a": 1 + }, + "schema_id": "const_9_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "{\"a\": 1.0} is invalid", + "data": { + "a": 1 + }, + "schema_id": "const_9_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "const with 0 does not match other zero-like types", + "database": { + "schemas": [ + { + "const": 0, + "$id": "const_10_0" + } + ] + }, + "tests": [ + { + "description": "false is invalid", + "data": false, + "schema_id": "const_10_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "integer zero is valid", + "data": 0, + "schema_id": "const_10_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "float zero is valid", + "data": 0, + "schema_id": "const_10_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "empty object is invalid", + "data": {}, + "schema_id": "const_10_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "empty array is invalid", + "data": [], + "schema_id": "const_10_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "empty string is invalid", + "data": "", + "schema_id": "const_10_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "const with 1 does not match true", + "database": { + "schemas": [ + { + "const": 1, + "$id": "const_11_0" + } + ] + }, + "tests": [ + { + "description": "true is invalid", + "data": true, + "schema_id": "const_11_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "integer one is valid", + "data": 1, + "schema_id": "const_11_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "float one is valid", + "data": 1, + "schema_id": "const_11_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "const with -2.0 matches integer and float types", + "database": { + "schemas": [ + { + "const": -2, + "$id": "const_12_0" + } + ] + }, + "tests": [ + { + "description": "integer -2 is valid", + "data": -2, + "schema_id": "const_12_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "integer 2 is invalid", + "data": 2, + "schema_id": "const_12_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "float -2.0 is valid", + "data": -2, + "schema_id": "const_12_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "float 2.0 is invalid", + "data": 2, + "schema_id": "const_12_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "float -2.00001 is invalid", + "data": -2.00001, + "schema_id": "const_12_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "float and integers are equal up to 64-bit representation limits", + "database": { + "schemas": [ + { + "const": 9007199254740992, + "$id": "const_13_0" + } + ] + }, + "tests": [ + { + "description": "integer is valid", + "data": 9007199254740992, + "schema_id": "const_13_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "integer minus one is invalid", + "data": 9007199254740991, + "schema_id": "const_13_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "float is valid", + "data": 9007199254740992, + "schema_id": "const_13_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "float minus one is invalid", + "data": 9007199254740991, + "schema_id": "const_13_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "nul characters in strings", + "database": { + "schemas": [ + { + "const": "hello\u0000there", + "$id": "const_14_0" + } + ] + }, + "tests": [ + { + "description": "match string with nul", + "data": "hello\u0000there", + "schema_id": "const_14_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "do not match string lacking nul", + "data": "hellothere", + "schema_id": "const_14_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "characters with the same visual representation but different codepoint", + "database": { + "schemas": [ + { + "const": "μ", + "$comment": "U+03BC", + "$id": "const_15_0" + } + ] + }, + "tests": [ + { + "description": "character uses the same codepoint", + "data": "μ", + "comment": "U+03BC", + "schema_id": "const_15_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "character looks the same but uses a different codepoint", + "data": "µ", + "comment": "U+00B5", + "schema_id": "const_15_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "characters with the same visual representation, but different number of codepoints", + "database": { + "schemas": [ + { + "const": "ä", + "$comment": "U+00E4", + "$id": "const_16_0" + } + ] + }, + "tests": [ + { + "description": "character uses the same codepoint", + "data": "ä", + "comment": "U+00E4", + "schema_id": "const_16_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "character looks the same but uses combining marks", + "data": "ä", + "comment": "a, U+0308", + "schema_id": "const_16_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "extensible: true allows extra properties in const object match", + "database": { + "schemas": [ + { + "const": { + "a": 1 + }, + "extensible": true, + "$id": "const_17_0" + } + ] + }, + "tests": [ + { + "description": "extra property ignored during strict check, but const check still applies (mismatch)", + "data": { + "a": 1, + "b": 2 + }, + "schema_id": "const_17_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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 + }, + "schema_id": "const_17_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/contains.json b/fixtures/contains.json new file mode 100644 index 0000000..b8a36b8 --- /dev/null +++ b/fixtures/contains.json @@ -0,0 +1,418 @@ +[ + { + "description": "contains keyword validation", + "database": { + "schemas": [ + { + "contains": { + "minimum": 5 + }, + "items": true, + "$id": "contains_0_0" + } + ] + }, + "tests": [ + { + "description": "array with item matching schema (5) is valid (items: true)", + "data": [ + 3, + 4, + 5 + ], + "schema_id": "contains_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "array with item matching schema (6) is valid (items: true)", + "data": [ + 3, + 4, + 6 + ], + "schema_id": "contains_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "array with two items matching schema (5, 6) is valid (items: true)", + "data": [ + 3, + 4, + 5, + 6 + ], + "schema_id": "contains_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "array without items matching schema is invalid", + "data": [ + 2, + 3, + 4 + ], + "schema_id": "contains_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "empty array is invalid", + "data": [], + "schema_id": "contains_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "not array is valid", + "data": {}, + "schema_id": "contains_0_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "contains keyword with const keyword", + "database": { + "schemas": [ + { + "contains": { + "const": 5 + }, + "items": true, + "$id": "contains_1_0" + } + ] + }, + "tests": [ + { + "description": "array with item 5 is valid (items: true)", + "data": [ + 3, + 4, + 5 + ], + "schema_id": "contains_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "array with two items 5 is valid (items: true)", + "data": [ + 3, + 4, + 5, + 5 + ], + "schema_id": "contains_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "array without item 5 is invalid", + "data": [ + 1, + 2, + 3, + 4 + ], + "schema_id": "contains_1_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "contains keyword with boolean schema true", + "database": { + "schemas": [ + { + "contains": true, + "$id": "contains_2_0" + } + ] + }, + "tests": [ + { + "description": "any non-empty array is valid", + "data": [ + "foo" + ], + "schema_id": "contains_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "empty array is invalid", + "data": [], + "schema_id": "contains_2_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "contains keyword with boolean schema false", + "database": { + "schemas": [ + { + "contains": false, + "$id": "contains_3_0" + } + ] + }, + "tests": [ + { + "description": "any non-empty array is invalid", + "data": [ + "foo" + ], + "schema_id": "contains_3_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "empty array is invalid", + "data": [], + "schema_id": "contains_3_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "non-arrays are valid", + "data": "contains does not apply to strings", + "schema_id": "contains_3_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "items + contains", + "database": { + "schemas": [ + { + "items": { + "multipleOf": 2 + }, + "contains": { + "multipleOf": 3 + }, + "$id": "contains_4_0" + } + ] + }, + "tests": [ + { + "description": "matches items, does not match contains", + "data": [ + 2, + 4, + 8 + ], + "schema_id": "contains_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "does not match items, matches contains", + "data": [ + 3, + 6, + 9 + ], + "schema_id": "contains_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "matches both items and contains", + "data": [ + 6, + 12 + ], + "schema_id": "contains_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "matches neither items nor contains", + "data": [ + 1, + 5 + ], + "schema_id": "contains_4_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "contains with false if subschema", + "database": { + "schemas": [ + { + "contains": { + "if": false, + "else": true + }, + "$id": "contains_5_0" + } + ] + }, + "tests": [ + { + "description": "any non-empty array is valid", + "data": [ + "foo" + ], + "schema_id": "contains_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "empty array is invalid", + "data": [], + "schema_id": "contains_5_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "contains with null instance elements", + "database": { + "schemas": [ + { + "contains": { + "type": "null" + }, + "$id": "contains_6_0" + } + ] + }, + "tests": [ + { + "description": "allows null items", + "data": [ + null + ], + "schema_id": "contains_6_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "extensible: true allows non-matching items in contains", + "database": { + "schemas": [ + { + "contains": { + "const": 1 + }, + "extensible": true, + "$id": "contains_7_0" + } + ] + }, + "tests": [ + { + "description": "extra items acceptable", + "data": [ + 1, + 2 + ], + "schema_id": "contains_7_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "strict by default: non-matching items in contains are invalid", + "database": { + "schemas": [ + { + "contains": { + "const": 1 + }, + "$id": "contains_8_0" + } + ] + }, + "tests": [ + { + "description": "extra items cause failure", + "data": [ + 1, + 2 + ], + "schema_id": "contains_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "only matching items is valid", + "data": [ + 1, + 1 + ], + "schema_id": "contains_8_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/content.json b/fixtures/content.json new file mode 100644 index 0000000..6638382 --- /dev/null +++ b/fixtures/content.json @@ -0,0 +1,232 @@ +[ + { + "description": "validation of string-encoded content based on media type", + "database": { + "schemas": [ + { + "contentMediaType": "application/json", + "$id": "content_0_0" + } + ] + }, + "tests": [ + { + "description": "a valid JSON document", + "data": "{\"foo\": \"bar\"}", + "schema_id": "content_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an invalid JSON document; validates true", + "data": "{:}", + "schema_id": "content_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores non-strings", + "data": 100, + "schema_id": "content_0_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "validation of binary string-encoding", + "database": { + "schemas": [ + { + "contentEncoding": "base64", + "$id": "content_1_0" + } + ] + }, + "tests": [ + { + "description": "a valid base64 string", + "data": "eyJmb28iOiAiYmFyIn0K", + "schema_id": "content_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an invalid base64 string (% is not a valid character); validates true", + "data": "eyJmb28iOi%iYmFyIn0K", + "schema_id": "content_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores non-strings", + "data": 100, + "schema_id": "content_1_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "validation of binary-encoded media type documents", + "database": { + "schemas": [ + { + "contentMediaType": "application/json", + "contentEncoding": "base64", + "$id": "content_2_0" + } + ] + }, + "tests": [ + { + "description": "a valid base64-encoded JSON document", + "data": "eyJmb28iOiAiYmFyIn0K", + "schema_id": "content_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a validly-encoded invalid JSON document; validates true", + "data": "ezp9Cg==", + "schema_id": "content_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an invalid base64 string that is valid JSON; validates true", + "data": "{}", + "schema_id": "content_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores non-strings", + "data": 100, + "schema_id": "content_2_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "validation of binary-encoded media type documents with schema", + "database": { + "schemas": [ + { + "contentMediaType": "application/json", + "contentEncoding": "base64", + "contentSchema": { + "type": "object", + "required": [ + "foo" + ], + "properties": { + "foo": { + "type": "string" + }, + "boo": { + "type": "integer" + } + } + }, + "$id": "content_3_0" + } + ] + }, + "tests": [ + { + "description": "a valid base64-encoded JSON document", + "data": "eyJmb28iOiAiYmFyIn0K", + "schema_id": "content_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "another valid base64-encoded JSON document", + "data": "eyJib28iOiAyMCwgImZvbyI6ICJiYXoifQ==", + "schema_id": "content_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an invalid base64-encoded JSON document; validates true", + "data": "eyJib28iOiAyMH0=", + "schema_id": "content_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an empty object as a base64-encoded JSON document; validates true", + "data": "e30=", + "schema_id": "content_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an empty array as a base64-encoded JSON document", + "data": "W10=", + "schema_id": "content_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a validly-encoded invalid JSON document; validates true", + "data": "ezp9Cg==", + "schema_id": "content_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an invalid base64 string that is valid JSON; validates true", + "data": "{}", + "schema_id": "content_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores non-strings", + "data": 100, + "schema_id": "content_3_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/dependencies.json b/fixtures/dependencies.json new file mode 100644 index 0000000..5810b62 --- /dev/null +++ b/fixtures/dependencies.json @@ -0,0 +1,748 @@ +[ + { + "description": "single dependency (required)", + "database": { + "schemas": [ + { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "schema1", + "dependencies": { + "bar": [ + "foo" + ] + }, + "extensible": true + } + ] + }, + "tests": [ + { + "description": "neither", + "data": {}, + "schema_id": "schema1", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "nondependant", + "data": { + "foo": 1 + }, + "schema_id": "schema1", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "with dependency", + "data": { + "foo": 1, + "bar": 2 + }, + "schema_id": "schema1", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "missing dependency", + "data": { + "bar": 2 + }, + "schema_id": "schema1", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "ignores arrays", + "data": [ + "bar" + ], + "schema_id": "schema1", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores strings", + "data": "foobar", + "schema_id": "schema1", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores other non-objects", + "data": 12, + "schema_id": "schema1", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "empty dependents", + "database": { + "schemas": [ + { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "schema2", + "dependencies": { + "bar": [] + }, + "extensible": true + } + ] + }, + "tests": [ + { + "description": "empty object", + "data": {}, + "schema_id": "schema2", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "object with one property", + "data": { + "bar": 2 + }, + "schema_id": "schema2", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "non-object is valid", + "data": 1, + "schema_id": "schema2", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "multiple dependents required", + "database": { + "schemas": [ + { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "schema3", + "dependencies": { + "quux": [ + "foo", + "bar" + ] + }, + "extensible": true + } + ] + }, + "tests": [ + { + "description": "neither", + "data": {}, + "schema_id": "schema3", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "nondependants", + "data": { + "foo": 1, + "bar": 2 + }, + "schema_id": "schema3", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "with dependencies", + "data": { + "foo": 1, + "bar": 2, + "quux": 3 + }, + "schema_id": "schema3", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "missing dependency", + "data": { + "foo": 1, + "quux": 2 + }, + "schema_id": "schema3", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "missing other dependency", + "data": { + "bar": 1, + "quux": 2 + }, + "schema_id": "schema3", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "missing both dependencies", + "data": { + "quux": 1 + }, + "schema_id": "schema3", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "dependencies with escaped characters", + "database": { + "schemas": [ + { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "schema4", + "dependencies": { + "foo\nbar": [ + "foo\rbar" + ], + "foo\"bar": [ + "foo'bar" + ] + }, + "extensible": true + } + ] + }, + "tests": [ + { + "description": "CRLF", + "data": { + "foo\nbar": 1, + "foo\rbar": 2 + }, + "schema_id": "schema4", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "quoted quotes", + "data": { + "foo'bar": 1, + "foo\"bar": 2 + }, + "schema_id": "schema4", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "CRLF missing dependent", + "data": { + "foo\nbar": 1, + "foo": 2 + }, + "schema_id": "schema4", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "quoted quotes missing dependent", + "data": { + "foo\"bar": 2 + }, + "schema_id": "schema4", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "extensible: true allows extra properties in dependentRequired", + "database": { + "schemas": [ + { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "schema5", + "dependencies": { + "bar": [ + "foo" + ] + }, + "extensible": true + } + ] + }, + "tests": [ + { + "description": "extra property is valid", + "data": { + "foo": 1, + "bar": 2, + "baz": 3 + }, + "schema_id": "schema5", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "single dependency (schemas, STRICT)", + "database": { + "schemas": [ + { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "schema_schema1", + "properties": { + "foo": true, + "bar": true + }, + "dependencies": { + "bar": { + "properties": { + "foo": { + "type": "integer" + }, + "bar": { + "type": "integer" + } + } + } + } + } + ] + }, + "tests": [ + { + "description": "valid", + "data": { + "foo": 1, + "bar": 2 + }, + "schema_id": "schema_schema1", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "no dependency", + "data": { + "foo": "quux" + }, + "schema_id": "schema_schema1", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "wrong type", + "data": { + "foo": "quux", + "bar": 2 + }, + "schema_id": "schema_schema1", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "wrong type other", + "data": { + "foo": 2, + "bar": "quux" + }, + "schema_id": "schema_schema1", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "wrong type both", + "data": { + "foo": "quux", + "bar": "quux" + }, + "schema_id": "schema_schema1", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "ignores arrays (invalid in strict mode)", + "data": [ + "bar" + ], + "schema_id": "schema_schema1", + "action": "validate", + "expect": { + "success": false, + "errors": [ + { + "code": "STRICT_ITEM_VIOLATION" + } + ] + } + }, + { + "description": "ignores strings", + "data": "foobar", + "schema_id": "schema_schema1", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores other non-objects", + "data": 12, + "schema_id": "schema_schema1", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "single dependency (schemas, EXTENSIBLE)", + "database": { + "schemas": [ + { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "schema_schema2", + "properties": { + "foo": true, + "bar": true + }, + "dependencies": { + "bar": { + "properties": { + "foo": { + "type": "integer" + }, + "bar": { + "type": "integer" + } + } + } + }, + "extensible": true + } + ] + }, + "tests": [ + { + "description": "ignores arrays (valid in extensible mode)", + "data": [ + "bar" + ], + "schema_id": "schema_schema2", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "boolean subschemas", + "database": { + "schemas": [ + { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "schema_schema3", + "properties": { + "foo": true, + "bar": true + }, + "dependencies": { + "foo": true, + "bar": false + } + } + ] + }, + "tests": [ + { + "description": "object with property having schema true is valid", + "data": { + "foo": 1 + }, + "schema_id": "schema_schema3", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "object with property having schema false is invalid", + "data": { + "bar": 2 + }, + "schema_id": "schema_schema3", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "object with both properties is invalid", + "data": { + "foo": 1, + "bar": 2 + }, + "schema_id": "schema_schema3", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "empty object is valid", + "data": {}, + "schema_id": "schema_schema3", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "dependencies with escaped characters", + "database": { + "schemas": [ + { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "schema_schema4", + "properties": { + "foo\tbar": true, + "foo'bar": true, + "a": true, + "b": true, + "c": true + }, + "dependencies": { + "foo\tbar": { + "minProperties": 4, + "extensible": true + }, + "foo'bar": { + "required": [ + "foo\"bar" + ] + } + } + } + ] + }, + "tests": [ + { + "description": "quoted tab", + "data": { + "foo\tbar": 1, + "a": 2, + "b": 3, + "c": 4 + }, + "schema_id": "schema_schema4", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "quoted quote", + "data": { + "foo'bar": { + "foo\"bar": 1 + } + }, + "schema_id": "schema_schema4", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "quoted tab invalid under dependent schema", + "data": { + "foo\tbar": 1, + "a": 2 + }, + "schema_id": "schema_schema4", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "quoted quote invalid under dependent schema", + "data": { + "foo'bar": 1 + }, + "schema_id": "schema_schema4", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "dependent subschema incompatible with root (STRICT)", + "database": { + "schemas": [ + { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "schema_schema5", + "properties": { + "foo": {}, + "baz": true + }, + "dependencies": { + "foo": { + "properties": { + "bar": {} + } + } + } + } + ] + }, + "tests": [ + { + "description": "matches root", + "data": { + "foo": 1 + }, + "schema_id": "schema_schema5", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "matches dependency (invalid in strict mode - bar not allowed if foo missing)", + "data": { + "bar": 1 + }, + "schema_id": "schema_schema5", + "action": "validate", + "expect": { + "success": false, + "errors": [ + { + "code": "STRICT_PROPERTY_VIOLATION" + } + ] + } + }, + { + "description": "matches both", + "data": { + "foo": 1, + "bar": 2 + }, + "schema_id": "schema_schema5", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "no dependency", + "data": { + "baz": 1 + }, + "schema_id": "schema_schema5", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "dependent subschema incompatible with root (EXTENSIBLE)", + "database": { + "schemas": [ + { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "schema_schema6", + "properties": { + "foo": {}, + "baz": true + }, + "dependencies": { + "foo": { + "properties": { + "bar": {} + }, + "additionalProperties": false + } + }, + "extensible": true + } + ] + }, + "tests": [ + { + "description": "matches dependency (valid in extensible mode)", + "data": { + "bar": 1 + }, + "schema_id": "schema_schema6", + "action": "validate", + "expect": { + "success": true + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/emptyString.json b/fixtures/emptyString.json new file mode 100644 index 0000000..765089d --- /dev/null +++ b/fixtures/emptyString.json @@ -0,0 +1,163 @@ +[ + { + "description": "empty string is valid for all types (except const)", + "database": { + "schemas": [ + { + "properties": { + "obj": { + "type": "object" + }, + "arr": { + "type": "array" + }, + "str": { + "type": "string" + }, + "int": { + "type": "integer" + }, + "num": { + "type": "number" + }, + "bool": { + "type": "boolean" + }, + "nul": { + "type": "null" + }, + "fmt": { + "type": "string", + "format": "uuid" + }, + "con": { + "const": "value" + }, + "con_empty": { + "const": "" + } + }, + "$id": "emptyString_0_0" + } + ] + }, + "tests": [ + { + "description": "empty string valid for object", + "data": { + "obj": "" + }, + "schema_id": "emptyString_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "empty string valid for array", + "data": { + "arr": "" + }, + "schema_id": "emptyString_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "empty string valid for string", + "data": { + "str": "" + }, + "schema_id": "emptyString_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "empty string valid for integer", + "data": { + "int": "" + }, + "schema_id": "emptyString_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "empty string valid for number", + "data": { + "num": "" + }, + "schema_id": "emptyString_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "empty string valid for boolean", + "data": { + "bool": "" + }, + "schema_id": "emptyString_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "empty string valid for null", + "data": { + "nul": "" + }, + "schema_id": "emptyString_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "empty string valid for format", + "data": { + "fmt": "" + }, + "schema_id": "emptyString_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "empty string INVALID for const (unless const is empty string)", + "data": { + "con": "" + }, + "schema_id": "emptyString_0_0", + "action": "validate", + "expect": { + "success": false, + "errors": [ + { + "code": "CONST_VIOLATED", + "path": "/con" + } + ] + } + }, + { + "description": "empty string VALID for const if const IS empty string", + "data": { + "con_empty": "" + }, + "schema_id": "emptyString_0_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/enum.json b/fixtures/enum.json new file mode 100644 index 0000000..cfc0774 --- /dev/null +++ b/fixtures/enum.json @@ -0,0 +1,736 @@ +[ + { + "description": "simple enum validation", + "database": { + "schemas": [ + { + "enum": [ + 1, + 2, + 3 + ], + "$id": "enum_0_0" + } + ] + }, + "tests": [ + { + "description": "one of the enum is valid", + "data": 1, + "schema_id": "enum_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "something else is invalid", + "data": 4, + "schema_id": "enum_0_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "heterogeneous enum validation", + "database": { + "schemas": [ + { + "enum": [ + 6, + "foo", + [], + true, + { + "foo": 12 + } + ], + "properties": { + "foo": {} + }, + "$id": "enum_1_0" + } + ] + }, + "tests": [ + { + "description": "one of the enum is valid", + "data": [], + "schema_id": "enum_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "something else is invalid", + "data": null, + "schema_id": "enum_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "objects are deep compared", + "data": { + "foo": false + }, + "schema_id": "enum_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "valid object matches", + "data": { + "foo": 12 + }, + "schema_id": "enum_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "extra properties in object is invalid", + "data": { + "foo": 12, + "boo": 42 + }, + "schema_id": "enum_1_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "heterogeneous enum-with-null validation", + "database": { + "schemas": [ + { + "enum": [ + 6, + null + ], + "$id": "enum_2_0" + } + ] + }, + "tests": [ + { + "description": "null is valid", + "data": null, + "schema_id": "enum_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "number is valid", + "data": 6, + "schema_id": "enum_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "something else is invalid", + "data": "test", + "schema_id": "enum_2_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "enums in properties", + "database": { + "schemas": [ + { + "type": "object", + "properties": { + "foo": { + "enum": [ + "foo" + ] + }, + "bar": { + "enum": [ + "bar" + ] + } + }, + "required": [ + "bar" + ], + "$id": "enum_3_0" + } + ] + }, + "tests": [ + { + "description": "both properties are valid", + "data": { + "foo": "foo", + "bar": "bar" + }, + "schema_id": "enum_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "wrong foo value", + "data": { + "foo": "foot", + "bar": "bar" + }, + "schema_id": "enum_3_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "wrong bar value", + "data": { + "foo": "foo", + "bar": "bart" + }, + "schema_id": "enum_3_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "missing optional property is valid", + "data": { + "bar": "bar" + }, + "schema_id": "enum_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "missing required property is invalid", + "data": { + "foo": "foo" + }, + "schema_id": "enum_3_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "missing all properties is invalid", + "data": {}, + "schema_id": "enum_3_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "enum with escaped characters", + "database": { + "schemas": [ + { + "enum": [ + "foo\nbar", + "foo\rbar" + ], + "$id": "enum_4_0" + } + ] + }, + "tests": [ + { + "description": "member 1 is valid", + "data": "foo\nbar", + "schema_id": "enum_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "member 2 is valid", + "data": "foo\rbar", + "schema_id": "enum_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "another string is invalid", + "data": "abc", + "schema_id": "enum_4_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "enum with false does not match 0", + "database": { + "schemas": [ + { + "enum": [ + false + ], + "$id": "enum_5_0" + } + ] + }, + "tests": [ + { + "description": "false is valid", + "data": false, + "schema_id": "enum_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "integer zero is invalid", + "data": 0, + "schema_id": "enum_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "float zero is invalid", + "data": 0, + "schema_id": "enum_5_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "enum with [false] does not match [0]", + "database": { + "schemas": [ + { + "enum": [ + [ + false + ] + ], + "$id": "enum_6_0" + } + ] + }, + "tests": [ + { + "description": "[false] is valid", + "data": [ + false + ], + "schema_id": "enum_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "[0] is invalid", + "data": [ + 0 + ], + "schema_id": "enum_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "[0.0] is invalid", + "data": [ + 0 + ], + "schema_id": "enum_6_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "enum with true does not match 1", + "database": { + "schemas": [ + { + "enum": [ + true + ], + "$id": "enum_7_0" + } + ] + }, + "tests": [ + { + "description": "true is valid", + "data": true, + "schema_id": "enum_7_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "integer one is invalid", + "data": 1, + "schema_id": "enum_7_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "float one is invalid", + "data": 1, + "schema_id": "enum_7_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "enum with [true] does not match [1]", + "database": { + "schemas": [ + { + "enum": [ + [ + true + ] + ], + "$id": "enum_8_0" + } + ] + }, + "tests": [ + { + "description": "[true] is valid", + "data": [ + true + ], + "schema_id": "enum_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "[1] is invalid", + "data": [ + 1 + ], + "schema_id": "enum_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "[1.0] is invalid", + "data": [ + 1 + ], + "schema_id": "enum_8_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "enum with 0 does not match false", + "database": { + "schemas": [ + { + "enum": [ + 0 + ], + "$id": "enum_9_0" + } + ] + }, + "tests": [ + { + "description": "false is invalid", + "data": false, + "schema_id": "enum_9_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "integer zero is valid", + "data": 0, + "schema_id": "enum_9_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "float zero is valid", + "data": 0, + "schema_id": "enum_9_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "enum with [0] does not match [false]", + "database": { + "schemas": [ + { + "enum": [ + [ + 0 + ] + ], + "$id": "enum_10_0" + } + ] + }, + "tests": [ + { + "description": "[false] is invalid", + "data": [ + false + ], + "schema_id": "enum_10_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "[0] is valid", + "data": [ + 0 + ], + "schema_id": "enum_10_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "[0.0] is valid", + "data": [ + 0 + ], + "schema_id": "enum_10_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "enum with 1 does not match true", + "database": { + "schemas": [ + { + "enum": [ + 1 + ], + "$id": "enum_11_0" + } + ] + }, + "tests": [ + { + "description": "true is invalid", + "data": true, + "schema_id": "enum_11_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "integer one is valid", + "data": 1, + "schema_id": "enum_11_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "float one is valid", + "data": 1, + "schema_id": "enum_11_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "enum with [1] does not match [true]", + "database": { + "schemas": [ + { + "enum": [ + [ + 1 + ] + ], + "$id": "enum_12_0" + } + ] + }, + "tests": [ + { + "description": "[true] is invalid", + "data": [ + true + ], + "schema_id": "enum_12_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "[1] is valid", + "data": [ + 1 + ], + "schema_id": "enum_12_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "[1.0] is valid", + "data": [ + 1 + ], + "schema_id": "enum_12_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "nul characters in strings", + "database": { + "schemas": [ + { + "enum": [ + "hello\u0000there" + ], + "$id": "enum_13_0" + } + ] + }, + "tests": [ + { + "description": "match string with nul", + "data": "hello\u0000there", + "schema_id": "enum_13_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "do not match string lacking nul", + "data": "hellothere", + "schema_id": "enum_13_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "extensible: true allows extra properties in enum object match", + "database": { + "schemas": [ + { + "enum": [ + { + "foo": 1 + } + ], + "extensible": true, + "$id": "enum_14_0" + } + ] + }, + "tests": [ + { + "description": "extra property ignored during strict check, but enum check still applies (mismatch here)", + "data": { + "foo": 1, + "bar": 2 + }, + "schema_id": "enum_14_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "extra property ignored during strict check, enum match succeeds", + "data": { + "foo": 1 + }, + "schema_id": "enum_14_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/exclusiveMaximum.json b/fixtures/exclusiveMaximum.json new file mode 100644 index 0000000..e44aaf7 --- /dev/null +++ b/fixtures/exclusiveMaximum.json @@ -0,0 +1,51 @@ +[ + { + "description": "exclusiveMaximum validation", + "database": { + "schemas": [ + { + "exclusiveMaximum": 3, + "$id": "exclusiveMaximum_0_0" + } + ] + }, + "tests": [ + { + "description": "below the exclusiveMaximum is valid", + "data": 2.2, + "schema_id": "exclusiveMaximum_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "boundary point is invalid", + "data": 3, + "schema_id": "exclusiveMaximum_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "above the exclusiveMaximum is invalid", + "data": 3.5, + "schema_id": "exclusiveMaximum_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "ignores non-numbers", + "data": "x", + "schema_id": "exclusiveMaximum_0_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/exclusiveMinimum.json b/fixtures/exclusiveMinimum.json new file mode 100644 index 0000000..27bdd3f --- /dev/null +++ b/fixtures/exclusiveMinimum.json @@ -0,0 +1,51 @@ +[ + { + "description": "exclusiveMinimum validation", + "database": { + "schemas": [ + { + "exclusiveMinimum": 1.1, + "$id": "exclusiveMinimum_0_0" + } + ] + }, + "tests": [ + { + "description": "above the exclusiveMinimum is valid", + "data": 1.2, + "schema_id": "exclusiveMinimum_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "boundary point is invalid", + "data": 1.1, + "schema_id": "exclusiveMinimum_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "below the exclusiveMinimum is invalid", + "data": 0.6, + "schema_id": "exclusiveMinimum_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "ignores non-numbers", + "data": "x", + "schema_id": "exclusiveMinimum_0_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/families.json b/fixtures/families.json new file mode 100644 index 0000000..913244b --- /dev/null +++ b/fixtures/families.json @@ -0,0 +1,217 @@ +[ + { + "description": "Entity families via pure $ref graph", + "database": { + "types": [ + { + "name": "entity", + "variations": [ + "entity", + "organization", + "person" + ], + "schemas": [ + { + "$id": "entity", + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string" + } + } + }, + { + "$id": "light.entity", + "$ref": "entity" + } + ] + }, + { + "name": "organization", + "variations": [ + "organization", + "person" + ], + "schemas": [ + { + "$id": "organization", + "$ref": "entity", + "properties": { + "name": { + "type": "string" + } + } + } + ] + }, + { + "name": "person", + "variations": [ + "person" + ], + "schemas": [ + { + "$id": "person", + "$ref": "organization", + "properties": { + "first_name": { + "type": "string" + } + } + }, + { + "$id": "light.person", + "$ref": "light.entity" + } + ] + } + ], + "puncs": [ + { + "name": "get_entities", + "schemas": [ + { + "$id": "get_entities.response", + "$family": "entity" + } + ] + }, + { + "name": "get_light_entities", + "schemas": [ + { + "$id": "get_light_entities.response", + "$family": "light.entity" + } + ] + } + ] + }, + "tests": [ + { + "description": "Family matches base entity", + "schema_id": "get_entities.response", + "data": { + "id": "1", + "type": "entity" + }, + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "Family matches descendant person", + "schema_id": "get_entities.response", + "data": { + "id": "2", + "type": "person", + "name": "ACME", + "first_name": "John" + }, + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "Graph family matches light.entity", + "schema_id": "get_light_entities.response", + "data": { + "id": "3", + "type": "entity" + }, + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "Graph family matches light.person (because it $refs light.entity)", + "schema_id": "get_light_entities.response", + "data": { + "id": "4", + "type": "person" + }, + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "Graph family excludes organization (missing light. schema that $refs light.entity)", + "schema_id": "get_light_entities.response", + "data": { + "id": "5", + "type": "organization", + "name": "ACME" + }, + "action": "validate", + "expect": { + "success": false, + "errors": [ + { + "code": "FAMILY_MISMATCH", + "path": "" + } + ] + } + } + ] + }, + { + "description": "Ad-hoc non-entity families (using normal json-schema object structures)", + "database": { + "puncs": [ + { + "name": "get_widgets", + "schemas": [ + { + "$id": "widget", + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "widget_type": { + "type": "string" + } + } + }, + { + "$id": "special_widget", + "$ref": "widget", + "properties": { + "special_feature": { + "type": "string" + } + } + }, + { + "$id": "get_widgets.response", + "$family": "widget" + } + ] + } + ] + }, + "tests": [ + { + "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" + }, + "action": "validate", + "expect": { + "success": true + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/format.json b/fixtures/format.json new file mode 100644 index 0000000..b76f1c3 --- /dev/null +++ b/fixtures/format.json @@ -0,0 +1,5456 @@ +[ + { + "description": "validation of date-time strings", + "database": { + "schemas": [ + { + "format": "date-time", + "$id": "format_0_0" + } + ] + }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "schema_id": "format_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "schema_id": "format_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore objects", + "data": {}, + "schema_id": "format_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore arrays", + "data": [], + "schema_id": "format_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore booleans", + "data": false, + "schema_id": "format_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore nulls", + "data": null, + "schema_id": "format_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid date-time string", + "data": "1963-06-19T08:30:06.283185Z", + "schema_id": "format_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid date-time string without second fraction", + "data": "1963-06-19T08:30:06Z", + "schema_id": "format_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid date-time string with plus offset", + "data": "1937-01-01T12:00:27.87+00:20", + "schema_id": "format_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid date-time string with minus offset", + "data": "1990-12-31T15:59:50.123-08:00", + "schema_id": "format_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid date-time with a leap second, UTC", + "data": "1998-12-31T23:59:60Z", + "schema_id": "format_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid date-time with a leap second, with minus offset", + "data": "1998-12-31T15:59:60.123-08:00", + "schema_id": "format_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an invalid date-time past leap second, UTC", + "data": "1998-12-31T23:59:61Z", + "schema_id": "format_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid date-time with leap second on a wrong minute, UTC", + "data": "1998-12-31T23:58:60Z", + "schema_id": "format_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid date-time with leap second on a wrong hour, UTC", + "data": "1998-12-31T22:59:60Z", + "schema_id": "format_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid day in date-time string", + "data": "1990-02-31T15:59:59.123-08:00", + "schema_id": "format_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid offset in date-time string", + "data": "1990-12-31T15:59:59-24:00", + "schema_id": "format_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid closing Z after time-zone offset", + "data": "1963-06-19T08:30:06.28123+01:00Z", + "schema_id": "format_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid date-time string", + "data": "06/19/1963 08:30:06 PST", + "schema_id": "format_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "case-insensitive T and Z", + "data": "1963-06-19t08:30:06.283185z", + "schema_id": "format_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "only RFC3339 not all of ISO 8601 are valid", + "data": "2013-350T01:01:01", + "schema_id": "format_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid non-padded month dates", + "data": "1963-6-19T08:30:06.283185Z", + "schema_id": "format_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid non-padded day dates", + "data": "1963-06-1T08:30:06.283185Z", + "schema_id": "format_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid non-ASCII '৪' (a Bengali 4) in date portion", + "data": "1963-06-1৪T00:00:00Z", + "schema_id": "format_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid non-ASCII '৪' (a Bengali 4) in time portion", + "data": "1963-06-11T0৪:00:00Z", + "schema_id": "format_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid extended year", + "data": "+11963-06-19T08:30:06.283185Z", + "schema_id": "format_0_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "validation of date strings", + "database": { + "schemas": [ + { + "format": "date", + "$id": "format_1_0" + } + ] + }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore objects", + "data": {}, + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore arrays", + "data": [], + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore booleans", + "data": false, + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore nulls", + "data": null, + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid date string", + "data": "1963-06-19", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid date string with 31 days in January", + "data": "2020-01-31", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a invalid date string with 32 days in January", + "data": "2020-01-32", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a valid date string with 28 days in February (normal)", + "data": "2021-02-28", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a invalid date string with 29 days in February (normal)", + "data": "2021-02-29", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a valid date string with 29 days in February (leap)", + "data": "2020-02-29", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a invalid date string with 30 days in February (leap)", + "data": "2020-02-30", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a valid date string with 31 days in March", + "data": "2020-03-31", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a invalid date string with 32 days in March", + "data": "2020-03-32", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a valid date string with 30 days in April", + "data": "2020-04-30", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a invalid date string with 31 days in April", + "data": "2020-04-31", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a valid date string with 31 days in May", + "data": "2020-05-31", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a invalid date string with 32 days in May", + "data": "2020-05-32", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a valid date string with 30 days in June", + "data": "2020-06-30", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a invalid date string with 31 days in June", + "data": "2020-06-31", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a valid date string with 31 days in July", + "data": "2020-07-31", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a invalid date string with 32 days in July", + "data": "2020-07-32", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a valid date string with 31 days in August", + "data": "2020-08-31", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a invalid date string with 32 days in August", + "data": "2020-08-32", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a valid date string with 30 days in September", + "data": "2020-09-30", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a invalid date string with 31 days in September", + "data": "2020-09-31", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a valid date string with 31 days in October", + "data": "2020-10-31", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a invalid date string with 32 days in October", + "data": "2020-10-32", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a valid date string with 30 days in November", + "data": "2020-11-30", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a invalid date string with 31 days in November", + "data": "2020-11-31", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a valid date string with 31 days in December", + "data": "2020-12-31", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a invalid date string with 32 days in December", + "data": "2020-12-32", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a invalid date string with invalid month", + "data": "2020-13-01", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid date string", + "data": "06/19/1963", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "only RFC3339 not all of ISO 8601 are valid", + "data": "2013-350", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "non-padded month dates are not valid", + "data": "1998-1-20", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "non-padded day dates are not valid", + "data": "1998-01-1", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid month", + "data": "1998-13-01", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid month-day combination", + "data": "1998-04-31", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "2021 is not a leap year", + "data": "2021-02-29", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "2020 is a leap year", + "data": "2020-02-29", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "invalid non-ASCII '৪' (a Bengali 4)", + "data": "1963-06-1৪", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "ISO8601 / non-RFC3339: YYYYMMDD without dashes (2023-03-28)", + "data": "20230328", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "ISO8601 / non-RFC3339: week number implicit day of week (2023-01-02)", + "data": "2023-W01", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "ISO8601 / non-RFC3339: week number with day of week (2023-03-28)", + "data": "2023-W13-2", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "ISO8601 / non-RFC3339: week number rollover to next year (2023-01-01)", + "data": "2022W527", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid time string in date-time format", + "data": "2020-11-28T23:55:45Z", + "schema_id": "format_1_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "validation of duration strings", + "database": { + "schemas": [ + { + "format": "duration", + "$id": "format_2_0" + } + ] + }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "schema_id": "format_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "schema_id": "format_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore objects", + "data": {}, + "schema_id": "format_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore arrays", + "data": [], + "schema_id": "format_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore booleans", + "data": false, + "schema_id": "format_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore nulls", + "data": null, + "schema_id": "format_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid duration string", + "data": "P4DT12H30M5S", + "schema_id": "format_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an invalid duration string", + "data": "PT1D", + "schema_id": "format_2_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "must start with P", + "data": "4DT12H30M5S", + "schema_id": "format_2_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "no elements present", + "data": "P", + "schema_id": "format_2_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "no time elements present", + "data": "P1YT", + "schema_id": "format_2_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "no date or time elements present", + "data": "PT", + "schema_id": "format_2_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "elements out of order", + "data": "P2D1Y", + "schema_id": "format_2_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "missing time separator", + "data": "P1D2H", + "schema_id": "format_2_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "time element in the date position", + "data": "P2S", + "schema_id": "format_2_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "four years duration", + "data": "P4Y", + "schema_id": "format_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "zero time, in seconds", + "data": "PT0S", + "schema_id": "format_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "zero time, in days", + "data": "P0D", + "schema_id": "format_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "one month duration", + "data": "P1M", + "schema_id": "format_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "one minute duration", + "data": "PT1M", + "schema_id": "format_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "one and a half days, in hours", + "data": "PT36H", + "schema_id": "format_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "one and a half days, in days and hours", + "data": "P1DT12H", + "schema_id": "format_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "two weeks", + "data": "P2W", + "schema_id": "format_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "weeks cannot be combined with other units", + "data": "P1Y2W", + "schema_id": "format_2_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid non-ASCII '২' (a Bengali 2)", + "data": "P২Y", + "schema_id": "format_2_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "element without unit", + "data": "P1", + "schema_id": "format_2_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "\\a is not an ECMA 262 control escape", + "database": { + "schemas": [ + { + "format": "regex", + "$id": "format_3_0" + } + ] + }, + "tests": [ + { + "description": "when used as a pattern", + "data": "\\a", + "schema_id": "format_3_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "validation of e-mail addresses", + "database": { + "schemas": [ + { + "format": "email", + "$id": "format_4_0" + } + ] + }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "schema_id": "format_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "schema_id": "format_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore objects", + "data": {}, + "schema_id": "format_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore arrays", + "data": [], + "schema_id": "format_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore booleans", + "data": false, + "schema_id": "format_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore nulls", + "data": null, + "schema_id": "format_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid e-mail address", + "data": "joe.bloggs@example.com", + "schema_id": "format_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an invalid e-mail address", + "data": "2962", + "schema_id": "format_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "tilde in local part is valid", + "data": "te~st@example.com", + "schema_id": "format_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "tilde before local part is valid", + "data": "~test@example.com", + "schema_id": "format_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "tilde after local part is valid", + "data": "test~@example.com", + "schema_id": "format_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a quoted string with a space in the local part is valid", + "data": "\"joe bloggs\"@example.com", + "schema_id": "format_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a quoted string with a double dot in the local part is valid", + "data": "\"joe..bloggs\"@example.com", + "schema_id": "format_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a quoted string with a @ in the local part is valid", + "data": "\"joe@bloggs\"@example.com", + "schema_id": "format_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an IPv4-address-literal after the @ is valid", + "data": "joe.bloggs@[127.0.0.1]", + "schema_id": "format_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an IPv6-address-literal after the @ is valid", + "data": "joe.bloggs@[IPv6:::1]", + "schema_id": "format_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "dot before local part is not valid", + "data": ".test@example.com", + "schema_id": "format_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "dot after local part is not valid", + "data": "test.@example.com", + "schema_id": "format_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "two separated dots inside local part are valid", + "data": "te.s.t@example.com", + "schema_id": "format_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "two subsequent dots inside local part are not valid", + "data": "te..st@example.com", + "schema_id": "format_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid domain", + "data": "joe.bloggs@invalid=domain.com", + "schema_id": "format_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid IPv4-address-literal", + "data": "joe.bloggs@[127.0.0.300]", + "schema_id": "format_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "two email addresses is not valid", + "data": "user1@oceania.org, user2@oceania.org", + "schema_id": "format_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "full \"From\" header is invalid", + "data": "\"Winston Smith\" (Records Department)", + "schema_id": "format_4_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "validation of host names", + "database": { + "schemas": [ + { + "format": "hostname", + "$id": "format_5_0" + } + ] + }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "schema_id": "format_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "schema_id": "format_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore objects", + "data": {}, + "schema_id": "format_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore arrays", + "data": [], + "schema_id": "format_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore booleans", + "data": false, + "schema_id": "format_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore nulls", + "data": null, + "schema_id": "format_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid host name", + "data": "www.example.com", + "schema_id": "format_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "single label", + "data": "hostname", + "schema_id": "format_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "single label with digits", + "data": "h0stn4me", + "schema_id": "format_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "single label starting with digit", + "data": "1host", + "schema_id": "format_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "single label ending with digit", + "data": "hostnam3", + "schema_id": "format_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "empty string", + "data": "", + "schema_id": "format_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "single dot", + "data": ".", + "schema_id": "format_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "leading dot", + "data": ".example", + "schema_id": "format_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "trailing dot", + "data": "example.", + "schema_id": "format_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "IDN label separator", + "data": "example.com", + "schema_id": "format_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "single label with hyphen", + "data": "host-name", + "schema_id": "format_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "starts with hyphen", + "data": "-hostname", + "schema_id": "format_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "ends with hyphen", + "data": "hostname-", + "schema_id": "format_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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", + "schema_id": "format_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "contains underscore", + "data": "host_name", + "schema_id": "format_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "exceeds maximum overall length (256)", + "data": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.com", + "schema_id": "format_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "maximum label length (63)", + "data": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.com", + "schema_id": "format_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "exceeds maximum label length (63)", + "data": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl.com", + "schema_id": "format_5_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "validation of A-label (punycode) host names", + "database": { + "schemas": [ + { + "format": "hostname", + "$id": "format_6_0" + } + ] + }, + "tests": [ + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a valid host name (example.test in Hangul)", + "data": "xn--9n2bp8q.xn--9t4b11yi5a", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "contains illegal char U+302E Hangul single dot tone mark", + "data": "xn--07jt112bpxg.xn--9t4b11yi5a", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "Begins with a Spacing Combining Mark", + "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.2", + "data": "xn--hello-txk", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "Begins with a Nonspacing Mark", + "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.2", + "data": "xn--hello-zed", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "Begins with an Enclosing Mark", + "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.2", + "data": "xn--hello-6bf", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "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", + "schema_id": "format_6_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "validation of an internationalized e-mail addresses", + "database": { + "schemas": [ + { + "format": "idn-email", + "$id": "format_7_0" + } + ] + }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "schema_id": "format_7_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "schema_id": "format_7_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore objects", + "data": {}, + "schema_id": "format_7_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore arrays", + "data": [], + "schema_id": "format_7_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore booleans", + "data": false, + "schema_id": "format_7_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore nulls", + "data": null, + "schema_id": "format_7_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid idn e-mail (example@example.test in Hangul)", + "data": "실례@실례.테스트", + "schema_id": "format_7_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an invalid idn e-mail address", + "data": "2962", + "schema_id": "format_7_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a valid e-mail address", + "data": "joe.bloggs@example.com", + "schema_id": "format_7_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an invalid e-mail address", + "data": "2962", + "schema_id": "format_7_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "validation of internationalized host names", + "database": { + "schemas": [ + { + "format": "idn-hostname", + "$id": "format_8_0" + } + ] + }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore objects", + "data": {}, + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore arrays", + "data": [], + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore booleans", + "data": false, + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore nulls", + "data": null, + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid host name (example.test in Hangul)", + "data": "실례.테스트", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "illegal first char U+302E Hangul single dot tone mark", + "data": "〮실례.테스트", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "contains illegal char U+302E Hangul single dot tone mark", + "data": "실〮례.테스트", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a host name with a component too long", + "data": "실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실례례테스트례례례례례례례례례례례례례례례례례테스트례례례례례례례례례례례례례례례례례례례테스트례례례례례례례례례례례례테스트례례실례.테스트", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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 <--", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "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", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "U-label starts with a dash", + "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.1", + "data": "-hello", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "U-label ends with a dash", + "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.1", + "data": "hello-", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "U-label starts and ends with a dash", + "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.1", + "data": "-hello-", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "Begins with a Spacing Combining Mark", + "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.2", + "data": "ःhello", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "Begins with a Nonspacing Mark", + "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.2", + "data": "̀hello", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "Begins with an Enclosing Mark", + "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.2", + "data": "҈hello", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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": "ßς་〇", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "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": "۽۾", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "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": "ـߺ", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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": "〱〲〳〴〵〮〯〻", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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·", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "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", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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": "α͵", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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": "α͵β", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "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׳ב", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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": "׳ב", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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": "א׳ב", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "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״ב", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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": "״ב", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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": "א״ב", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "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", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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": "・", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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": "・ぁ", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "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": "・ァ", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "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": "・丈", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "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": "ب٠۰", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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": "ب٠ب", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "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", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "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": "क‍ष", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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": "‍ष", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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": "क्‍ष", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "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": "क्‌ष", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "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": "بي‌بي", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "single label", + "data": "hostname", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "single label with hyphen", + "data": "host-name", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "single label with digits", + "data": "h0stn4me", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "single label starting with digit", + "data": "1host", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "single label ending with digit", + "data": "hostnam3", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "empty string", + "data": "", + "schema_id": "format_8_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "validation of separators in internationalized host names", + "specification": [ + { + "rfc3490": "3.1", + "quote": "Whenever dots are used as label separators, the following characters MUST be recognized as dots: U+002E (full stop), U+3002 (ideographic full stop), U+FF0E (fullwidth full stop), U+FF61(halfwidth ideographic full stop)" + } + ], + "database": { + "schemas": [ + { + "format": "idn-hostname", + "$id": "format_9_0" + } + ] + }, + "tests": [ + { + "description": "single dot", + "data": ".", + "schema_id": "format_9_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "single ideographic full stop", + "data": "。", + "schema_id": "format_9_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "single fullwidth full stop", + "data": ".", + "schema_id": "format_9_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "single halfwidth ideographic full stop", + "data": "。", + "schema_id": "format_9_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "dot as label separator", + "data": "a.b", + "schema_id": "format_9_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ideographic full stop as label separator", + "data": "a。b", + "schema_id": "format_9_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "fullwidth full stop as label separator", + "data": "a.b", + "schema_id": "format_9_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "halfwidth ideographic full stop as label separator", + "data": "a。b", + "schema_id": "format_9_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "leading dot", + "data": ".example", + "schema_id": "format_9_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "leading ideographic full stop", + "data": "。example", + "schema_id": "format_9_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "leading fullwidth full stop", + "data": ".example", + "schema_id": "format_9_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "leading halfwidth ideographic full stop", + "data": "。example", + "schema_id": "format_9_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "trailing dot", + "data": "example.", + "schema_id": "format_9_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "trailing ideographic full stop", + "data": "example。", + "schema_id": "format_9_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "trailing fullwidth full stop", + "data": "example.", + "schema_id": "format_9_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "trailing halfwidth ideographic full stop", + "data": "example。", + "schema_id": "format_9_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "label too long if separator ignored (full stop)", + "data": "παράδειγμαπαράδειγμαπαράδειγμαπαράδειγμαπαράδειγμαπα.com", + "schema_id": "format_9_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "label too long if separator ignored (ideographic full stop)", + "data": "παράδειγμαπαράδειγμαπαράδειγμαπαράδειγμαπαράδειγμαπα。com", + "schema_id": "format_9_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "label too long if separator ignored (fullwidth full stop)", + "data": "παράδειγμαπαράδειγμαπαράδειγμαπαράδειγμαπαράδειγμαπα.com", + "schema_id": "format_9_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "label too long if separator ignored (halfwidth ideographic full stop)", + "data": "παράδειγμαπαράδειγμαπαράδειγμαπαράδειγμαπαράδειγμαπα。com", + "schema_id": "format_9_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "validation of IP addresses", + "database": { + "schemas": [ + { + "format": "ipv4", + "$id": "format_10_0" + } + ] + }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "schema_id": "format_10_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "schema_id": "format_10_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore objects", + "data": {}, + "schema_id": "format_10_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore arrays", + "data": [], + "schema_id": "format_10_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore booleans", + "data": false, + "schema_id": "format_10_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore nulls", + "data": null, + "schema_id": "format_10_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid IP address", + "data": "192.168.0.1", + "schema_id": "format_10_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an IP address with too many components", + "data": "127.0.0.0.1", + "schema_id": "format_10_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an IP address with out-of-range values", + "data": "256.256.256.256", + "schema_id": "format_10_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an IP address without 4 components", + "data": "127.0", + "schema_id": "format_10_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an IP address as an integer", + "data": "0x7f000001", + "schema_id": "format_10_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an IP address as an integer (decimal)", + "data": "2130706433", + "schema_id": "format_10_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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", + "schema_id": "format_10_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "value without leading zero is valid", + "data": "87.10.0.1", + "schema_id": "format_10_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "invalid non-ASCII '২' (a Bengali 2)", + "data": "1২7.0.0.1", + "schema_id": "format_10_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "netmask is not a part of ipv4 address", + "data": "192.168.1.0/24", + "schema_id": "format_10_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "validation of IPv6 addresses", + "database": { + "schemas": [ + { + "format": "ipv6", + "$id": "format_11_0" + } + ] + }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore objects", + "data": {}, + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore arrays", + "data": [], + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore booleans", + "data": false, + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore nulls", + "data": null, + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid IPv6 address", + "data": "::1", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an IPv6 address with out-of-range values", + "data": "12345::", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "trailing 4 hex symbols is valid", + "data": "::abef", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "trailing 5 hex symbols is invalid", + "data": "::abcef", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "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", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an IPv6 address containing illegal characters", + "data": "::laptop", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "no digits is valid", + "data": "::", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "leading colons is valid", + "data": "::42:ff:1", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "trailing colons is valid", + "data": "d6::", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "missing leading octet is invalid", + "data": ":2:3:4:5:6:7:8", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "missing trailing octet is invalid", + "data": "1:2:3:4:5:6:7:", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "missing leading octet with omitted octets later", + "data": ":2:3:4::8", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "single set of double colons in the middle is valid", + "data": "1:d6::42", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "two sets of double colons is invalid", + "data": "1::d6::42", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "mixed format with the ipv4 section as decimal octets", + "data": "1::d6:192.168.0.1", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "mixed format with double colons between the sections", + "data": "1:2::192.168.0.1", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "mixed format with ipv4 section with octet out of range", + "data": "1::2:192.168.256.1", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "mixed format with ipv4 section with a hex octet", + "data": "1::2:192.168.ff.1", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "mixed format with leading double colons (ipv4-mapped ipv6 address)", + "data": "::ffff:192.168.0.1", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "triple colons is invalid", + "data": "1:2:3:4:5:::8", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "8 octets", + "data": "1:2:3:4:5:6:7:8", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "insufficient octets without double colons", + "data": "1:2:3:4:5:6:7", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "no colons is invalid", + "data": "1", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "ipv4 is not ipv6", + "data": "127.0.0.1", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "ipv4 segment must have 4 octets", + "data": "1:2:3:4:1.2.3", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "leading whitespace is invalid", + "data": " ::1", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "trailing whitespace is invalid", + "data": "::1 ", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "netmask is not a part of ipv6 address", + "data": "fe80::/64", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "zone id is not a part of ipv6 address", + "data": "fe80::a%eth1", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a long valid ipv6", + "data": "1000:1000:1000:1000:1000:1000:255.255.255.255", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a long invalid ipv6, below length limit, first", + "data": "100:100:100:100:100:100:255.255.255.255.255", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a long invalid ipv6, below length limit, second", + "data": "100:100:100:100:100:100:100:255.255.255.255", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid non-ASCII '৪' (a Bengali 4)", + "data": "1:2:3:4:5:6:7:৪", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid non-ASCII '৪' (a Bengali 4) in the IPv4 portion", + "data": "1:2::192.16৪.0.1", + "schema_id": "format_11_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "validation of IRI References", + "database": { + "schemas": [ + { + "format": "iri-reference", + "$id": "format_12_0" + } + ] + }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "schema_id": "format_12_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "schema_id": "format_12_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore objects", + "data": {}, + "schema_id": "format_12_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore arrays", + "data": [], + "schema_id": "format_12_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore booleans", + "data": false, + "schema_id": "format_12_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore nulls", + "data": null, + "schema_id": "format_12_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid IRI", + "data": "http://ƒøø.ßår/?∂éœ=πîx#πîüx", + "schema_id": "format_12_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid protocol-relative IRI Reference", + "data": "//ƒøø.ßår/?∂éœ=πîx#πîüx", + "schema_id": "format_12_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid relative IRI Reference", + "data": "/âππ", + "schema_id": "format_12_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an invalid IRI Reference", + "data": "\\\\WINDOWS\\filëßåré", + "schema_id": "format_12_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a valid IRI Reference", + "data": "âππ", + "schema_id": "format_12_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid IRI fragment", + "data": "#ƒrägmênt", + "schema_id": "format_12_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an invalid IRI fragment", + "data": "#ƒräg\\mênt", + "schema_id": "format_12_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "validation of IRIs", + "database": { + "schemas": [ + { + "format": "iri", + "$id": "format_13_0" + } + ] + }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "schema_id": "format_13_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "schema_id": "format_13_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore objects", + "data": {}, + "schema_id": "format_13_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore arrays", + "data": [], + "schema_id": "format_13_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore booleans", + "data": false, + "schema_id": "format_13_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore nulls", + "data": null, + "schema_id": "format_13_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid IRI with anchor tag", + "data": "http://ƒøø.ßår/?∂éœ=πîx#πîüx", + "schema_id": "format_13_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid IRI with anchor tag and parentheses", + "data": "http://ƒøø.com/blah_(wîkïpédiå)_blah#ßité-1", + "schema_id": "format_13_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid IRI with URL-encoded stuff", + "data": "http://ƒøø.ßår/?q=Test%20URL-encoded%20stuff", + "schema_id": "format_13_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid IRI with many special characters", + "data": "http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com", + "schema_id": "format_13_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid IRI based on IPv6", + "data": "http://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]", + "schema_id": "format_13_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an invalid IRI based on IPv6", + "data": "http://2001:0db8:85a3:0000:0000:8a2e:0370:7334", + "schema_id": "format_13_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid relative IRI Reference", + "data": "/abc", + "schema_id": "format_13_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid IRI", + "data": "\\\\WINDOWS\\filëßåré", + "schema_id": "format_13_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid IRI though valid IRI reference", + "data": "âππ", + "schema_id": "format_13_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "validation of JSON-pointers (JSON String Representation)", + "database": { + "schemas": [ + { + "format": "json-pointer", + "$id": "format_14_0" + } + ] + }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore objects", + "data": {}, + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore arrays", + "data": [], + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore booleans", + "data": false, + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore nulls", + "data": null, + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid JSON-pointer", + "data": "/foo/bar~0/baz~1/%a", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "not a valid JSON-pointer (~ not escaped)", + "data": "/foo/bar~", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "valid JSON-pointer with empty segment", + "data": "/foo//bar", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "valid JSON-pointer with the last empty segment", + "data": "/foo/bar/", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #1", + "data": "", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #2", + "data": "/foo", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #3", + "data": "/foo/0", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #4", + "data": "/", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #5", + "data": "/a~1b", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #6", + "data": "/c%d", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #7", + "data": "/e^f", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #8", + "data": "/g|h", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #9", + "data": "/i\\j", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #10", + "data": "/k\"l", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #11", + "data": "/ ", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #12", + "data": "/m~0n", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "valid JSON-pointer used adding to the last array position", + "data": "/foo/-", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "valid JSON-pointer (- used as object member name)", + "data": "/foo/-/bar", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "valid JSON-pointer (multiple escaped characters)", + "data": "/~1~0~0~1~1", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "valid JSON-pointer (escaped with fraction part) #1", + "data": "/~1.1", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "valid JSON-pointer (escaped with fraction part) #2", + "data": "/~0.1", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "not a valid JSON-pointer (URI Fragment Identifier) #1", + "data": "#", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "not a valid JSON-pointer (URI Fragment Identifier) #2", + "data": "#/", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "not a valid JSON-pointer (URI Fragment Identifier) #3", + "data": "#a", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "not a valid JSON-pointer (some escaped, but not all) #1", + "data": "/~0~", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "not a valid JSON-pointer (some escaped, but not all) #2", + "data": "/~0/~", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "not a valid JSON-pointer (wrong escape character) #1", + "data": "/~2", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "not a valid JSON-pointer (wrong escape character) #2", + "data": "/~-1", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "not a valid JSON-pointer (multiple characters not escaped)", + "data": "/~~", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "not a valid JSON-pointer (isn't empty nor starts with /) #1", + "data": "a", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "not a valid JSON-pointer (isn't empty nor starts with /) #2", + "data": "0", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "not a valid JSON-pointer (isn't empty nor starts with /) #3", + "data": "a/a", + "schema_id": "format_14_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "validation of regular expressions", + "database": { + "schemas": [ + { + "format": "regex", + "$id": "format_15_0" + } + ] + }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "schema_id": "format_15_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "schema_id": "format_15_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore objects", + "data": {}, + "schema_id": "format_15_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore arrays", + "data": [], + "schema_id": "format_15_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore booleans", + "data": false, + "schema_id": "format_15_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore nulls", + "data": null, + "schema_id": "format_15_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid regular expression", + "data": "([abc])+\\s+$", + "schema_id": "format_15_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a regular expression with unclosed parens is invalid", + "data": "^(abc]", + "schema_id": "format_15_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "validation of Relative JSON Pointers (RJP)", + "database": { + "schemas": [ + { + "format": "relative-json-pointer", + "$id": "format_16_0" + } + ] + }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "schema_id": "format_16_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "schema_id": "format_16_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore objects", + "data": {}, + "schema_id": "format_16_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore arrays", + "data": [], + "schema_id": "format_16_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore booleans", + "data": false, + "schema_id": "format_16_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore nulls", + "data": null, + "schema_id": "format_16_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid upwards RJP", + "data": "1", + "schema_id": "format_16_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid downwards RJP", + "data": "0/foo/bar", + "schema_id": "format_16_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid up and then down RJP, with array index", + "data": "2/0/baz/1/zip", + "schema_id": "format_16_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid RJP taking the member or index name", + "data": "0#", + "schema_id": "format_16_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an invalid RJP that is a valid JSON Pointer", + "data": "/foo/bar", + "schema_id": "format_16_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "negative prefix", + "data": "-1/foo/bar", + "schema_id": "format_16_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "explicit positive prefix", + "data": "+1/foo/bar", + "schema_id": "format_16_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "## is not a valid json-pointer", + "data": "0##", + "schema_id": "format_16_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "zero cannot be followed by other digits, plus json-pointer", + "data": "01/a", + "schema_id": "format_16_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "zero cannot be followed by other digits, plus octothorpe", + "data": "01#", + "schema_id": "format_16_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "empty string", + "data": "", + "schema_id": "format_16_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "multi-digit integer prefix", + "data": "120/foo/bar", + "schema_id": "format_16_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "validation of time strings", + "database": { + "schemas": [ + { + "format": "time", + "$id": "format_17_0" + } + ] + }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore objects", + "data": {}, + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore arrays", + "data": [], + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore booleans", + "data": false, + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore nulls", + "data": null, + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid time string", + "data": "08:30:06Z", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "invalid time string with extra leading zeros", + "data": "008:030:006Z", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid time string with no leading zero for single digit", + "data": "8:3:6Z", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "hour, minute, second must be two digits", + "data": "8:0030:6Z", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a valid time string with leap second, Zulu", + "data": "23:59:60Z", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "invalid leap second, Zulu (wrong hour)", + "data": "22:59:60Z", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid leap second, Zulu (wrong minute)", + "data": "23:58:60Z", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "valid leap second, zero time-offset", + "data": "23:59:60+00:00", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "invalid leap second, zero time-offset (wrong hour)", + "data": "22:59:60+00:00", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid leap second, zero time-offset (wrong minute)", + "data": "23:58:60+00:00", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "valid leap second, positive time-offset", + "data": "01:29:60+01:30", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "valid leap second, large positive time-offset", + "data": "23:29:60+23:30", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "invalid leap second, positive time-offset (wrong hour)", + "data": "23:59:60+01:00", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid leap second, positive time-offset (wrong minute)", + "data": "23:59:60+00:30", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "valid leap second, negative time-offset", + "data": "15:59:60-08:00", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "valid leap second, large negative time-offset", + "data": "00:29:60-23:30", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "invalid leap second, negative time-offset (wrong hour)", + "data": "23:59:60-01:00", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid leap second, negative time-offset (wrong minute)", + "data": "23:59:60-00:30", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a valid time string with second fraction", + "data": "23:20:50.52Z", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid time string with precise second fraction", + "data": "08:30:06.283185Z", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid time string with plus offset", + "data": "08:30:06+00:20", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid time string with minus offset", + "data": "08:30:06-08:00", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "hour, minute in time-offset must be two digits", + "data": "08:30:06-8:000", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a valid time string with case-insensitive Z", + "data": "08:30:06z", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an invalid time string with invalid hour", + "data": "24:00:00Z", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid time string with invalid minute", + "data": "00:60:00Z", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid time string with invalid second", + "data": "00:00:61Z", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid time string with invalid leap second (wrong hour)", + "data": "22:59:60Z", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid time string with invalid leap second (wrong minute)", + "data": "23:58:60Z", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid time string with invalid time numoffset hour", + "data": "01:02:03+24:00", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid time string with invalid time numoffset minute", + "data": "01:02:03+00:60", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid time string with invalid time with both Z and numoffset", + "data": "01:02:03Z+00:30", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid offset indicator", + "data": "08:30:06 PST", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "only RFC3339 not all of ISO 8601 are valid", + "data": "01:01:01,1111", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "no time offset", + "data": "12:00:00", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "no time offset with second fraction", + "data": "12:00:00.52", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid non-ASCII '২' (a Bengali 2)", + "data": "1২:00:00Z", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "offset not starting with plus or minus", + "data": "08:30:06#00:20", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "contains letters", + "data": "ab:cd:ef", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid time string in date-time format", + "data": "2020-11-28T23:55:45Z", + "schema_id": "format_17_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "unknown format", + "database": { + "schemas": [ + { + "format": "unknown", + "$id": "format_18_0" + } + ] + }, + "tests": [ + { + "description": "unknown formats ignore integers", + "data": 12, + "schema_id": "format_18_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "unknown formats ignore floats", + "data": 13.7, + "schema_id": "format_18_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "unknown formats ignore objects", + "data": {}, + "schema_id": "format_18_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "unknown formats ignore arrays", + "data": [], + "schema_id": "format_18_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "unknown formats ignore booleans", + "data": false, + "schema_id": "format_18_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "unknown formats ignore nulls", + "data": null, + "schema_id": "format_18_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "unknown formats ignore strings", + "data": "string", + "schema_id": "format_18_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "validation of URI References", + "database": { + "schemas": [ + { + "format": "uri-reference", + "$id": "format_19_0" + } + ] + }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "schema_id": "format_19_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "schema_id": "format_19_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore objects", + "data": {}, + "schema_id": "format_19_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore arrays", + "data": [], + "schema_id": "format_19_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore booleans", + "data": false, + "schema_id": "format_19_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore nulls", + "data": null, + "schema_id": "format_19_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid URI", + "data": "http://foo.bar/?baz=qux#quux", + "schema_id": "format_19_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid protocol-relative URI Reference", + "data": "//foo.bar/?baz=qux#quux", + "schema_id": "format_19_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid relative URI Reference", + "data": "/abc", + "schema_id": "format_19_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an invalid URI Reference", + "data": "\\\\WINDOWS\\fileshare", + "schema_id": "format_19_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a valid URI Reference", + "data": "abc", + "schema_id": "format_19_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid URI fragment", + "data": "#fragment", + "schema_id": "format_19_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an invalid URI fragment", + "data": "#frag\\ment", + "schema_id": "format_19_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "unescaped non US-ASCII characters", + "data": "/foobar®.txt", + "schema_id": "format_19_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid backslash character", + "data": "https://example.org/foobar\\.txt", + "schema_id": "format_19_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "format: uri-template", + "database": { + "schemas": [ + { + "format": "uri-template", + "$id": "format_20_0" + } + ] + }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "schema_id": "format_20_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "schema_id": "format_20_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore objects", + "data": {}, + "schema_id": "format_20_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore arrays", + "data": [], + "schema_id": "format_20_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore booleans", + "data": false, + "schema_id": "format_20_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore nulls", + "data": null, + "schema_id": "format_20_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid uri-template", + "data": "http://example.com/dictionary/{term:1}/{term}", + "schema_id": "format_20_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an invalid uri-template", + "data": "http://example.com/dictionary/{term:1}/{term", + "schema_id": "format_20_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a valid uri-template without variables", + "data": "http://example.com/dictionary", + "schema_id": "format_20_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid relative uri-template", + "data": "dictionary/{term:1}/{term}", + "schema_id": "format_20_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "validation of URIs", + "database": { + "schemas": [ + { + "format": "uri", + "$id": "format_21_0" + } + ] + }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore objects", + "data": {}, + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore arrays", + "data": [], + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore booleans", + "data": false, + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore nulls", + "data": null, + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid URL with anchor tag", + "data": "http://foo.bar/?baz=qux#quux", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid URL with anchor tag and parentheses", + "data": "http://foo.com/blah_(wikipedia)_blah#cite-1", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid URL with URL-encoded stuff", + "data": "http://foo.bar/?q=Test%20URL-encoded%20stuff", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid puny-coded URL ", + "data": "http://xn--nw2a.xn--j6w193g/", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid URL with many special characters", + "data": "http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid URL based on IPv4", + "data": "http://223.255.255.254", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid URL with ftp scheme", + "data": "ftp://ftp.is.co.za/rfc/rfc1808.txt", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid URL for a simple text file", + "data": "http://www.ietf.org/rfc/rfc2396.txt", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid URL ", + "data": "ldap://[2001:db8::7]/c=GB?objectClass?one", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid mailto URI", + "data": "mailto:John.Doe@example.com", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid newsgroup URI", + "data": "news:comp.infosystems.www.servers.unix", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid tel URI", + "data": "tel:+1-816-555-1212", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a valid URN", + "data": "urn:oasis:names:specification:docbook:dtd:xml:4.1.2", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an invalid protocol-relative URI Reference", + "data": "//foo.bar/?baz=qux#quux", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid relative URI Reference", + "data": "/abc", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid URI", + "data": "\\\\WINDOWS\\fileshare", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid URI though valid URI reference", + "data": "abc", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid URI with spaces", + "data": "http:// shouldfail.com", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid URI with spaces and missing scheme", + "data": ":// should fail", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid URI with comma in scheme", + "data": "bar,baz:foo", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid userinfo", + "data": "https://[@example.org/test.txt", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "unescaped non US-ASCII characters", + "data": "https://example.org/foobar®.txt", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid backslash character", + "data": "https://example.org/foobar\\.txt", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid \" character", + "data": "https://example.org/foobar\".txt", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid <> characters", + "data": "https://example.org/foobar<>.txt", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid {} characters", + "data": "https://example.org/foobar{}.txt", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid ^ character", + "data": "https://example.org/foobar^.txt", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid ` character", + "data": "https://example.org/foobar`.txt", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid SPACE character", + "data": "https://example.org/foo bar.txt", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid | character", + "data": "https://example.org/foobar|.txt", + "schema_id": "format_21_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "uuid format", + "database": { + "schemas": [ + { + "format": "uuid", + "$id": "format_22_0" + } + ] + }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "schema_id": "format_22_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "schema_id": "format_22_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore objects", + "data": {}, + "schema_id": "format_22_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore arrays", + "data": [], + "schema_id": "format_22_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore booleans", + "data": false, + "schema_id": "format_22_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all string formats ignore nulls", + "data": null, + "schema_id": "format_22_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all upper-case", + "data": "2EB8AA08-AA98-11EA-B4AA-73B441D16380", + "schema_id": "format_22_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all lower-case", + "data": "2eb8aa08-aa98-11ea-b4aa-73b441d16380", + "schema_id": "format_22_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "mixed case", + "data": "2eb8aa08-AA98-11ea-B4Aa-73B441D16380", + "schema_id": "format_22_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all zeroes is valid", + "data": "00000000-0000-0000-0000-000000000000", + "schema_id": "format_22_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "wrong length", + "data": "2eb8aa08-aa98-11ea-b4aa-73b441d1638", + "schema_id": "format_22_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "missing section", + "data": "2eb8aa08-aa98-11ea-73b441d16380", + "schema_id": "format_22_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "bad characters (not hex)", + "data": "2eb8aa08-aa98-11ea-b4ga-73b441d16380", + "schema_id": "format_22_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "no dashes", + "data": "2eb8aa08aa9811eab4aa73b441d16380", + "schema_id": "format_22_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "too few dashes", + "data": "2eb8aa08aa98-11ea-b4aa73b441d16380", + "schema_id": "format_22_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "too many dashes", + "data": "2eb8-aa08-aa98-11ea-b4aa73b44-1d16380", + "schema_id": "format_22_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "dashes in the wrong spot", + "data": "2eb8aa08aa9811eab4aa73b441d16380----", + "schema_id": "format_22_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "shifted dashes", + "data": "2eb8aa0-8aa98-11e-ab4aa7-3b441d16380", + "schema_id": "format_22_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "valid version 4", + "data": "98d80576-482e-427f-8434-7f86890ab222", + "schema_id": "format_22_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "valid version 5", + "data": "99c17cbb-656f-564a-940f-1a4568f03487", + "schema_id": "format_22_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "hypothetical version 6", + "data": "99c17cbb-656f-664a-940f-1a4568f03487", + "schema_id": "format_22_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "hypothetical version 15", + "data": "99c17cbb-656f-f64a-940f-1a4568f03487", + "schema_id": "format_22_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "period format", + "database": { + "schemas": [ + { + "format": "period", + "$id": "format_23_0" + } + ] + }, + "tests": [ + { + "description": "valid period (start/duration)", + "data": "2020-01-01T00:00:00Z/P1Y", + "schema_id": "format_23_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "valid period (duration/end)", + "data": "P1Y/2021-01-01T00:00:00Z", + "schema_id": "format_23_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "valid period (start/end)", + "data": "2020-01-01T00:00:00Z/2021-01-01T00:00:00Z", + "schema_id": "format_23_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "invalid period (missing slash)", + "data": "2020-01-01T00:00:00ZP1Y", + "schema_id": "format_23_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "ignores non-strings", + "data": 123, + "schema_id": "format_23_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/if-then-else.json b/fixtures/if-then-else.json new file mode 100644 index 0000000..40a2e67 --- /dev/null +++ b/fixtures/if-then-else.json @@ -0,0 +1,594 @@ +[ + { + "description": "ignore if without then or else", + "database": { + "schemas": [ + { + "if": { + "const": 0 + }, + "$id": "if-then-else_0_0" + } + ] + }, + "tests": [ + { + "description": "valid when valid against lone if", + "data": 0, + "schema_id": "if-then-else_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "valid when invalid against lone if", + "data": "hello", + "schema_id": "if-then-else_0_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "ignore then without if", + "database": { + "schemas": [ + { + "then": { + "const": 0 + }, + "$id": "if-then-else_1_0" + } + ] + }, + "tests": [ + { + "description": "valid when valid against lone then", + "data": 0, + "schema_id": "if-then-else_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "valid when invalid against lone then", + "data": "hello", + "schema_id": "if-then-else_1_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "ignore else without if", + "database": { + "schemas": [ + { + "else": { + "const": 0 + }, + "$id": "if-then-else_2_0" + } + ] + }, + "tests": [ + { + "description": "valid when valid against lone else", + "data": 0, + "schema_id": "if-then-else_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "valid when invalid against lone else", + "data": "hello", + "schema_id": "if-then-else_2_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "if and then without else", + "database": { + "schemas": [ + { + "if": { + "exclusiveMaximum": 0 + }, + "then": { + "minimum": -10 + }, + "$id": "if-then-else_3_0" + } + ] + }, + "tests": [ + { + "description": "valid through then", + "data": -1, + "schema_id": "if-then-else_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "invalid through then", + "data": -100, + "schema_id": "if-then-else_3_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "valid when if test fails", + "data": 3, + "schema_id": "if-then-else_3_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "if and else without then", + "database": { + "schemas": [ + { + "if": { + "exclusiveMaximum": 0 + }, + "else": { + "multipleOf": 2 + }, + "$id": "if-then-else_4_0" + } + ] + }, + "tests": [ + { + "description": "valid when if test passes", + "data": -1, + "schema_id": "if-then-else_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "valid through else", + "data": 4, + "schema_id": "if-then-else_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "invalid through else", + "data": 3, + "schema_id": "if-then-else_4_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "validate against correct branch, then vs else", + "database": { + "schemas": [ + { + "if": { + "exclusiveMaximum": 0 + }, + "then": { + "minimum": -10 + }, + "else": { + "multipleOf": 2 + }, + "$id": "if-then-else_5_0" + } + ] + }, + "tests": [ + { + "description": "valid through then", + "data": -1, + "schema_id": "if-then-else_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "invalid through then", + "data": -100, + "schema_id": "if-then-else_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "valid through else", + "data": 4, + "schema_id": "if-then-else_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "invalid through else", + "data": 3, + "schema_id": "if-then-else_5_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "non-interference across combined schemas", + "database": { + "schemas": [ + { + "allOf": [ + { + "if": { + "exclusiveMaximum": 0 + } + }, + { + "then": { + "minimum": -10 + } + }, + { + "else": { + "multipleOf": 2 + } + } + ], + "$id": "if-then-else_6_0" + } + ] + }, + "tests": [ + { + "description": "valid, but would have been invalid through then", + "data": -100, + "schema_id": "if-then-else_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "valid, but would have been invalid through else", + "data": 3, + "schema_id": "if-then-else_6_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "if with boolean schema true", + "database": { + "schemas": [ + { + "if": true, + "then": { + "const": "then" + }, + "else": { + "const": "else" + }, + "$id": "if-then-else_7_0" + } + ] + }, + "tests": [ + { + "description": "boolean schema true in if always chooses the then path (valid)", + "data": "then", + "schema_id": "if-then-else_7_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "boolean schema true in if always chooses the then path (invalid)", + "data": "else", + "schema_id": "if-then-else_7_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "if with boolean schema false", + "database": { + "schemas": [ + { + "if": false, + "then": { + "const": "then" + }, + "else": { + "const": "else" + }, + "$id": "if-then-else_8_0" + } + ] + }, + "tests": [ + { + "description": "boolean schema false in if always chooses the else path (invalid)", + "data": "then", + "schema_id": "if-then-else_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "boolean schema false in if always chooses the else path (valid)", + "data": "else", + "schema_id": "if-then-else_8_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "if appears at the end when serialized (keyword processing sequence)", + "database": { + "schemas": [ + { + "then": { + "const": "yes" + }, + "else": { + "const": "other" + }, + "if": { + "maxLength": 4 + }, + "$id": "if-then-else_9_0" + } + ] + }, + "tests": [ + { + "description": "yes redirects to then and passes", + "data": "yes", + "schema_id": "if-then-else_9_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "other redirects to else and passes", + "data": "other", + "schema_id": "if-then-else_9_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "no redirects to then and fails", + "data": "no", + "schema_id": "if-then-else_9_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid redirects to else and fails", + "data": "invalid", + "schema_id": "if-then-else_9_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "then: false fails when condition matches", + "database": { + "schemas": [ + { + "if": { + "const": 1 + }, + "then": false, + "$id": "if-then-else_10_0" + } + ] + }, + "tests": [ + { + "description": "matches if → then=false → invalid", + "data": 1, + "schema_id": "if-then-else_10_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "does not match if → then ignored → valid", + "data": 2, + "schema_id": "if-then-else_10_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "else: false fails when condition does not match", + "database": { + "schemas": [ + { + "if": { + "const": 1 + }, + "else": false, + "$id": "if-then-else_11_0" + } + ] + }, + "tests": [ + { + "description": "matches if → else ignored → valid", + "data": 1, + "schema_id": "if-then-else_11_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "does not match if → else executes → invalid", + "data": 2, + "schema_id": "if-then-else_11_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "extensible: true allows extra properties in if-then-else", + "database": { + "schemas": [ + { + "if": { + "properties": { + "foo": { + "const": 1 + } + }, + "required": [ + "foo" + ] + }, + "then": { + "properties": { + "bar": { + "const": 2 + } + }, + "required": [ + "bar" + ] + }, + "extensible": true, + "$id": "if-then-else_12_0" + } + ] + }, + "tests": [ + { + "description": "extra property is valid (matches if and then)", + "data": { + "foo": 1, + "bar": 2, + "extra": "prop" + }, + "schema_id": "if-then-else_12_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "strict by default with if-then properties", + "database": { + "schemas": [ + { + "if": { + "properties": { + "foo": { + "const": 1 + } + }, + "required": [ + "foo" + ] + }, + "then": { + "properties": { + "bar": { + "const": 2 + } + } + }, + "$id": "if-then-else_13_0" + } + ] + }, + "tests": [ + { + "description": "valid match (foo + bar)", + "data": { + "foo": 1, + "bar": 2 + }, + "schema_id": "if-then-else_13_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "fails on extra property z explicitly", + "data": { + "foo": 1, + "bar": 2, + "z": 3 + }, + "schema_id": "if-then-else_13_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/items.json b/fixtures/items.json new file mode 100644 index 0000000..e3513b1 --- /dev/null +++ b/fixtures/items.json @@ -0,0 +1,966 @@ +[ + { + "description": "a schema given for items", + "database": { + "schemas": [ + { + "items": { + "type": "integer" + }, + "$id": "items_0_0" + } + ] + }, + "tests": [ + { + "description": "valid items", + "data": [ + 1, + 2, + 3 + ], + "schema_id": "items_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "wrong type of items", + "data": [ + 1, + "x" + ], + "schema_id": "items_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "non-arrays are invalid", + "data": { + "foo": "bar" + }, + "schema_id": "items_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "JavaScript pseudo-arrays are invalid", + "data": { + "0": "invalid", + "length": 1 + }, + "schema_id": "items_0_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "items with boolean schema (true)", + "database": { + "schemas": [ + { + "items": true, + "$id": "items_1_0" + } + ] + }, + "tests": [ + { + "description": "any array is valid", + "data": [ + 1, + "foo", + true + ], + "schema_id": "items_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "empty array is valid", + "data": [], + "schema_id": "items_1_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "items with boolean schema (false)", + "database": { + "schemas": [ + { + "items": false, + "$id": "items_2_0" + } + ] + }, + "tests": [ + { + "description": "any non-empty array is invalid", + "data": [ + 1, + "foo", + true + ], + "schema_id": "items_2_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "empty array is valid", + "data": [], + "schema_id": "items_2_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "items and subitems", + "database": { + "schemas": [ + { + "type": "array", + "items": false, + "prefixItems": [ + { + "$ref": "item" + }, + { + "$ref": "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" + ] + } + ] + }, + "tests": [ + { + "description": "valid items", + "data": [ + [ + { + "foo": null + }, + { + "foo": null + } + ], + [ + { + "foo": null + }, + { + "foo": null + } + ], + [ + { + "foo": null + }, + { + "foo": null + } + ] + ], + "schema_id": "items_3_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "too many items", + "data": [ + [ + { + "foo": null + }, + { + "foo": null + } + ], + [ + { + "foo": null + }, + { + "foo": null + } + ], + [ + { + "foo": null + }, + { + "foo": null + } + ], + [ + { + "foo": null + }, + { + "foo": null + } + ] + ], + "schema_id": "items_3_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "too many sub-items", + "data": [ + [ + { + "foo": null + }, + { + "foo": null + }, + { + "foo": null + } + ], + [ + { + "foo": null + }, + { + "foo": null + } + ], + [ + { + "foo": null + }, + { + "foo": null + } + ] + ], + "schema_id": "items_3_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "wrong item", + "data": [ + { + "foo": null + }, + [ + { + "foo": null + }, + { + "foo": null + } + ], + [ + { + "foo": null + }, + { + "foo": null + } + ] + ], + "schema_id": "items_3_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "wrong sub-item", + "data": [ + [ + {}, + { + "foo": null + } + ], + [ + { + "foo": null + }, + { + "foo": null + } + ], + [ + { + "foo": null + }, + { + "foo": null + } + ] + ], + "schema_id": "items_3_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "fewer items is invalid", + "data": [ + [ + { + "foo": null + } + ], + [ + { + "foo": null + } + ] + ], + "schema_id": "items_3_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "nested items", + "database": { + "schemas": [ + { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "number" + } + } + } + }, + "$id": "items_4_0" + } + ] + }, + "tests": [ + { + "description": "valid nested array", + "data": [ + [ + [ + [ + 1 + ] + ], + [ + [ + 2 + ], + [ + 3 + ] + ] + ], + [ + [ + [ + 4 + ], + [ + 5 + ], + [ + 6 + ] + ] + ] + ], + "schema_id": "items_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "nested array with invalid type", + "data": [ + [ + [ + [ + "1" + ] + ], + [ + [ + 2 + ], + [ + 3 + ] + ] + ], + [ + [ + [ + 4 + ], + [ + 5 + ], + [ + 6 + ] + ] + ] + ], + "schema_id": "items_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "not deep enough", + "data": [ + [ + [ + 1 + ], + [ + 2 + ], + [ + 3 + ] + ], + [ + [ + 4 + ], + [ + 5 + ], + [ + 6 + ] + ] + ], + "schema_id": "items_4_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "prefixItems with no additional items allowed", + "database": { + "schemas": [ + { + "prefixItems": [ + {}, + {}, + {} + ], + "items": false, + "$id": "items_5_0" + } + ] + }, + "tests": [ + { + "description": "empty array", + "data": [], + "schema_id": "items_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "fewer number of items present (1)", + "data": [ + 1 + ], + "schema_id": "items_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "fewer number of items present (2)", + "data": [ + 1, + 2 + ], + "schema_id": "items_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "equal number of items present", + "data": [ + 1, + 2, + 3 + ], + "schema_id": "items_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "additional items are not permitted", + "data": [ + 1, + 2, + 3, + 4 + ], + "schema_id": "items_5_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "items does not look in applicators, valid case", + "database": { + "schemas": [ + { + "allOf": [ + { + "prefixItems": [ + { + "minimum": 3 + } + ] + } + ], + "items": { + "minimum": 5 + }, + "$id": "items_6_0" + } + ] + }, + "tests": [ + { + "description": "prefixItems in allOf does not constrain items, invalid case", + "data": [ + 3, + 5 + ], + "schema_id": "items_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "prefixItems in allOf does not constrain items, valid case", + "data": [ + 5, + 5 + ], + "schema_id": "items_6_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "prefixItems validation adjusts the starting index for items", + "database": { + "schemas": [ + { + "prefixItems": [ + { + "type": "string" + } + ], + "items": { + "type": "integer" + }, + "$id": "items_7_0" + } + ] + }, + "tests": [ + { + "description": "valid items", + "data": [ + "x", + 2, + 3 + ], + "schema_id": "items_7_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "wrong type of second item", + "data": [ + "x", + "y" + ], + "schema_id": "items_7_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "items with heterogeneous array", + "database": { + "schemas": [ + { + "prefixItems": [ + {} + ], + "items": false, + "$id": "items_8_0" + } + ] + }, + "tests": [ + { + "description": "heterogeneous invalid instance", + "data": [ + "foo", + "bar", + 37 + ], + "schema_id": "items_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "valid instance", + "data": [ + null + ], + "schema_id": "items_8_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "items with null instance elements", + "database": { + "schemas": [ + { + "items": { + "type": "null" + }, + "$id": "items_9_0" + } + ] + }, + "tests": [ + { + "description": "allows null elements", + "data": [ + null + ], + "schema_id": "items_9_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "extensible: true allows extra items (when items is false)", + "database": { + "schemas": [ + { + "items": false, + "extensible": true, + "$id": "items_10_0" + } + ] + }, + "tests": [ + { + "description": "extra item is valid", + "data": [ + 1 + ], + "schema_id": "items_10_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "extensible: true allows extra properties for items", + "database": { + "schemas": [ + { + "items": { + "minimum": 5 + }, + "extensible": true, + "$id": "items_11_0" + } + ] + }, + "tests": [ + { + "description": "valid item is valid", + "data": [ + 5, + 6 + ], + "schema_id": "items_11_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "invalid item (less than min) is invalid even with extensible: true", + "data": [ + 4 + ], + "schema_id": "items_11_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "array: simple extensible array", + "database": { + "schemas": [ + { + "type": "array", + "extensible": true, + "$id": "items_12_0" + } + ] + }, + "tests": [ + { + "description": "empty array is valid", + "data": [], + "schema_id": "items_12_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "array with items is valid (extensible)", + "data": [ + 1, + "foo" + ], + "schema_id": "items_12_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "array: strict array", + "database": { + "schemas": [ + { + "type": "array", + "extensible": false, + "$id": "items_13_0" + } + ] + }, + "tests": [ + { + "description": "empty array is valid", + "data": [], + "schema_id": "items_13_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "array with items is invalid (strict)", + "data": [ + 1 + ], + "schema_id": "items_13_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "array: items extensible", + "database": { + "schemas": [ + { + "type": "array", + "items": { + "extensible": true + }, + "$id": "items_14_0" + } + ] + }, + "tests": [ + { + "description": "empty array is valid", + "data": [], + "schema_id": "items_14_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "array with items is valid (items explicitly allowed to be anything extensible)", + "data": [ + 1, + "foo", + {} + ], + "schema_id": "items_14_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "array: items strict", + "database": { + "schemas": [ + { + "type": "array", + "items": { + "type": "object", + "extensible": false + }, + "$id": "items_15_0" + } + ] + }, + "tests": [ + { + "description": "empty array is valid (empty objects)", + "data": [ + {} + ], + "schema_id": "items_15_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "array with strict object items is valid", + "data": [ + {} + ], + "schema_id": "items_15_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "array with invalid strict object items (extra property)", + "data": [ + { + "extra": 1 + } + ], + "schema_id": "items_15_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/maxContains.json b/fixtures/maxContains.json new file mode 100644 index 0000000..764825e --- /dev/null +++ b/fixtures/maxContains.json @@ -0,0 +1,235 @@ +[ + { + "description": "maxContains without contains is ignored", + "database": { + "schemas": [ + { + "maxContains": 1, + "extensible": true, + "$id": "maxContains_0_0" + } + ] + }, + "tests": [ + { + "description": "one item valid against lone maxContains", + "data": [ + 1 + ], + "schema_id": "maxContains_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "two items still valid against lone maxContains", + "data": [ + 1, + 2 + ], + "schema_id": "maxContains_0_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "maxContains with contains", + "database": { + "schemas": [ + { + "contains": { + "const": 1 + }, + "maxContains": 1, + "extensible": true, + "$id": "maxContains_1_0" + } + ] + }, + "tests": [ + { + "description": "empty data", + "data": [], + "schema_id": "maxContains_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "all elements match, valid maxContains", + "data": [ + 1 + ], + "schema_id": "maxContains_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all elements match, invalid maxContains", + "data": [ + 1, + 1 + ], + "schema_id": "maxContains_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "some elements match, valid maxContains", + "data": [ + 1, + 2 + ], + "schema_id": "maxContains_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "some elements match, invalid maxContains", + "data": [ + 1, + 2, + 1 + ], + "schema_id": "maxContains_1_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "maxContains with contains, value with a decimal", + "database": { + "schemas": [ + { + "contains": { + "const": 1 + }, + "maxContains": 1, + "extensible": true, + "$id": "maxContains_2_0" + } + ] + }, + "tests": [ + { + "description": "one element matches, valid maxContains", + "data": [ + 1 + ], + "schema_id": "maxContains_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "too many elements match, invalid maxContains", + "data": [ + 1, + 1 + ], + "schema_id": "maxContains_2_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "minContains < maxContains", + "database": { + "schemas": [ + { + "contains": { + "const": 1 + }, + "minContains": 1, + "maxContains": 3, + "extensible": true, + "$id": "maxContains_3_0" + } + ] + }, + "tests": [ + { + "description": "actual < minContains < maxContains", + "data": [], + "schema_id": "maxContains_3_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "minContains < actual < maxContains", + "data": [ + 1, + 1 + ], + "schema_id": "maxContains_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "minContains < maxContains < actual", + "data": [ + 1, + 1, + 1, + 1 + ], + "schema_id": "maxContains_3_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "extensible: true allows non-matching items in maxContains", + "database": { + "schemas": [ + { + "contains": { + "const": 1 + }, + "maxContains": 1, + "extensible": true, + "$id": "maxContains_4_0" + } + ] + }, + "tests": [ + { + "description": "extra items disregarded for maxContains", + "data": [ + 1, + 2 + ], + "schema_id": "maxContains_4_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/maxItems.json b/fixtures/maxItems.json new file mode 100644 index 0000000..a9771c9 --- /dev/null +++ b/fixtures/maxItems.json @@ -0,0 +1,126 @@ +[ + { + "description": "maxItems validation", + "database": { + "schemas": [ + { + "maxItems": 2, + "extensible": true, + "$id": "maxItems_0_0" + } + ] + }, + "tests": [ + { + "description": "shorter is valid", + "data": [ + 1 + ], + "schema_id": "maxItems_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "exact length is valid", + "data": [ + 1, + 2 + ], + "schema_id": "maxItems_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "too long is invalid", + "data": [ + 1, + 2, + 3 + ], + "schema_id": "maxItems_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "ignores non-arrays", + "data": "foobar", + "schema_id": "maxItems_0_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "maxItems validation with a decimal", + "database": { + "schemas": [ + { + "maxItems": 2, + "extensible": true, + "$id": "maxItems_1_0" + } + ] + }, + "tests": [ + { + "description": "shorter is valid", + "data": [ + 1 + ], + "schema_id": "maxItems_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "too long is invalid", + "data": [ + 1, + 2, + 3 + ], + "schema_id": "maxItems_1_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "extensible: true allows extra items in maxItems (but counted)", + "database": { + "schemas": [ + { + "maxItems": 2, + "extensible": true, + "$id": "maxItems_2_0" + } + ] + }, + "tests": [ + { + "description": "extra item counted towards maxItems", + "data": [ + 1, + 2, + 3 + ], + "schema_id": "maxItems_2_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/maxLength.json b/fixtures/maxLength.json new file mode 100644 index 0000000..56ffb24 --- /dev/null +++ b/fixtures/maxLength.json @@ -0,0 +1,91 @@ +[ + { + "description": "maxLength validation", + "database": { + "schemas": [ + { + "maxLength": 2, + "$id": "maxLength_0_0" + } + ] + }, + "tests": [ + { + "description": "shorter is valid", + "data": "f", + "schema_id": "maxLength_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "exact length is valid", + "data": "fo", + "schema_id": "maxLength_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "too long is invalid", + "data": "foo", + "schema_id": "maxLength_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "ignores non-strings", + "data": 100, + "schema_id": "maxLength_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "two graphemes is long enough", + "data": "💩💩", + "schema_id": "maxLength_0_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "maxLength validation with a decimal", + "database": { + "schemas": [ + { + "maxLength": 2, + "$id": "maxLength_1_0" + } + ] + }, + "tests": [ + { + "description": "shorter is valid", + "data": "f", + "schema_id": "maxLength_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "too long is invalid", + "data": "foo", + "schema_id": "maxLength_1_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/maxProperties.json b/fixtures/maxProperties.json new file mode 100644 index 0000000..8f97dc2 --- /dev/null +++ b/fixtures/maxProperties.json @@ -0,0 +1,193 @@ +[ + { + "description": "maxProperties validation", + "database": { + "schemas": [ + { + "maxProperties": 2, + "extensible": true, + "$id": "maxProperties_0_0" + } + ] + }, + "tests": [ + { + "description": "shorter is valid", + "data": { + "foo": 1 + }, + "schema_id": "maxProperties_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "exact length is valid", + "data": { + "foo": 1, + "bar": 2 + }, + "schema_id": "maxProperties_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "too long is invalid", + "data": { + "foo": 1, + "bar": 2, + "baz": 3 + }, + "schema_id": "maxProperties_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "ignores arrays", + "data": [ + 1, + 2, + 3 + ], + "schema_id": "maxProperties_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores strings", + "data": "foobar", + "schema_id": "maxProperties_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores other non-objects", + "data": 12, + "schema_id": "maxProperties_0_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "maxProperties validation with a decimal", + "database": { + "schemas": [ + { + "maxProperties": 2, + "extensible": true, + "$id": "maxProperties_1_0" + } + ] + }, + "tests": [ + { + "description": "shorter is valid", + "data": { + "foo": 1 + }, + "schema_id": "maxProperties_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "too long is invalid", + "data": { + "foo": 1, + "bar": 2, + "baz": 3 + }, + "schema_id": "maxProperties_1_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "maxProperties = 0 means the object is empty", + "database": { + "schemas": [ + { + "maxProperties": 0, + "extensible": true, + "$id": "maxProperties_2_0" + } + ] + }, + "tests": [ + { + "description": "no properties is valid", + "data": {}, + "schema_id": "maxProperties_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "one property is invalid", + "data": { + "foo": 1 + }, + "schema_id": "maxProperties_2_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "extensible: true allows extra properties in maxProperties (though maxProperties still counts them!)", + "database": { + "schemas": [ + { + "maxProperties": 2, + "extensible": true, + "$id": "maxProperties_3_0" + } + ] + }, + "tests": [ + { + "description": "extra property is counted towards maxProperties", + "data": { + "foo": 1, + "bar": 2, + "baz": 3 + }, + "schema_id": "maxProperties_3_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "extra property is valid if below maxProperties", + "data": { + "foo": 1 + }, + "schema_id": "maxProperties_3_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/maximum.json b/fixtures/maximum.json new file mode 100644 index 0000000..38ff88c --- /dev/null +++ b/fixtures/maximum.json @@ -0,0 +1,100 @@ +[ + { + "description": "maximum validation", + "database": { + "schemas": [ + { + "maximum": 3, + "$id": "maximum_0_0" + } + ] + }, + "tests": [ + { + "description": "below the maximum is valid", + "data": 2.6, + "schema_id": "maximum_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "boundary point is valid", + "data": 3, + "schema_id": "maximum_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "above the maximum is invalid", + "data": 3.5, + "schema_id": "maximum_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "ignores non-numbers", + "data": "x", + "schema_id": "maximum_0_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "maximum validation with unsigned integer", + "database": { + "schemas": [ + { + "maximum": 300, + "$id": "maximum_1_0" + } + ] + }, + "tests": [ + { + "description": "below the maximum is invalid", + "data": 299.97, + "schema_id": "maximum_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "boundary point integer is valid", + "data": 300, + "schema_id": "maximum_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "boundary point float is valid", + "data": 300, + "schema_id": "maximum_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "above the maximum is invalid", + "data": 300.5, + "schema_id": "maximum_1_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/merge.json b/fixtures/merge.json new file mode 100644 index 0000000..7281f6d --- /dev/null +++ b/fixtures/merge.json @@ -0,0 +1,274 @@ +[ + { + "description": "merging: properties accumulate", + "database": { + "schemas": [ + { + "$id": "base_0", + "properties": { + "base_prop": { + "type": "string" + } + } + }, + { + "$ref": "base_0", + "properties": { + "child_prop": { + "type": "string" + } + }, + "$id": "merge_0_0" + } + ] + }, + "tests": [ + { + "description": "valid with both properties", + "data": { + "base_prop": "a", + "child_prop": "b" + }, + "schema_id": "merge_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "invalid when base property has wrong type", + "data": { + "base_prop": 1, + "child_prop": "b" + }, + "schema_id": "merge_0_0", + "action": "validate", + "expect": { + "success": false, + "errors": [ + { + "code": "TYPE_MISMATCH", + "path": "/base_prop" + } + ] + } + } + ] + }, + { + "description": "merging: required fields accumulate", + "database": { + "schemas": [ + { + "$id": "base_1", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + { + "$ref": "base_1", + "properties": { + "b": { + "type": "string" + } + }, + "required": [ + "b" + ], + "$id": "merge_1_0" + } + ] + }, + "tests": [ + { + "description": "valid when both present", + "data": { + "a": "ok", + "b": "ok" + }, + "schema_id": "merge_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "invalid when base required missing", + "data": { + "b": "ok" + }, + "schema_id": "merge_1_0", + "action": "validate", + "expect": { + "success": false, + "errors": [ + { + "code": "REQUIRED_FIELD_MISSING", + "path": "/a" + } + ] + } + }, + { + "description": "invalid when child required missing", + "data": { + "a": "ok" + }, + "schema_id": "merge_1_0", + "action": "validate", + "expect": { + "success": false, + "errors": [ + { + "code": "REQUIRED_FIELD_MISSING", + "path": "/b" + } + ] + } + } + ] + }, + { + "description": "merging: dependencies accumulate", + "database": { + "schemas": [ + { + "$id": "base_2", + "properties": { + "trigger": { + "type": "string" + }, + "base_dep": { + "type": "string" + } + }, + "dependencies": { + "trigger": [ + "base_dep" + ] + } + }, + { + "$ref": "base_2", + "properties": { + "child_dep": { + "type": "string" + } + }, + "dependencies": { + "trigger": [ + "child_dep" + ] + }, + "$id": "merge_2_0" + } + ] + }, + "tests": [ + { + "description": "valid with all deps", + "data": { + "trigger": "go", + "base_dep": "ok", + "child_dep": "ok" + }, + "schema_id": "merge_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "invalid missing base dep", + "data": { + "trigger": "go", + "child_dep": "ok" + }, + "schema_id": "merge_2_0", + "action": "validate", + "expect": { + "success": false, + "errors": [ + { + "code": "DEPENDENCY_FAILED", + "path": "/base_dep" + } + ] + } + }, + { + "description": "invalid missing child dep", + "data": { + "trigger": "go", + "base_dep": "ok" + }, + "schema_id": "merge_2_0", + "action": "validate", + "expect": { + "success": false, + "errors": [ + { + "code": "DEPENDENCY_FAILED", + "path": "/child_dep" + } + ] + } + } + ] + }, + { + "description": "merging: form and display do NOT merge", + "database": { + "schemas": [ + { + "$id": "base_3", + "properties": { + "a": { + "type": "string" + }, + "b": { + "type": "string" + } + }, + "form": [ + "a", + "b" + ] + }, + { + "$ref": "base_3", + "properties": { + "c": { + "type": "string" + } + }, + "form": [ + "c" + ], + "$id": "merge_3_0" + } + ] + }, + "tests": [ + { + "description": "child schema validation", + "data": { + "a": "ok", + "b": "ok", + "c": "ok" + }, + "comment": "Verifies validator handles the unmerged metadata correctly (ignores it or handles replacement)", + "schema_id": "merge_3_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/merger.json b/fixtures/merger.json new file mode 100644 index 0000000..6f66c09 --- /dev/null +++ b/fixtures/merger.json @@ -0,0 +1,149 @@ +[ + { + "description": "Basic Merger Execution", + "database": { + "puncs": [], + "enums": [], + "relations": [], + "types": [ + { + "name": "entity", + "schemas": [ + { + "$id": "entity", + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string" + }, + "archived": { + "type": "boolean" + }, + "created_by": { + "type": "string" + }, + "modified_by": { + "type": "string" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "modified_at": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "id", + "type", + "created_by", + "created_at", + "modified_by", + "modified_at" + ] + } + ], + "hierarchy": [ + "entity" + ], + "fields": [ + "id", + "type", + "created_at", + "created_by", + "modified_at", + "modified_by", + "archived" + ], + "grouped_fields": { + "entity": [ + "id", + "type", + "created_at", + "created_by", + "modified_at", + "modified_by", + "archived" + ] + }, + "lookup_fields": [], + "historical": false, + "relationship": false + }, + { + "name": "simple_entity", + "schemas": [ + { + "$id": "simple_entity", + "$ref": "entity", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + ], + "hierarchy": [ + "simple_entity", + "entity" + ], + "fields": [ + "id", + "type", + "name", + "created_at", + "created_by", + "modified_at", + "modified_by" + ], + "grouped_fields": { + "simple_entity": [ + "id", + "type", + "name" + ], + "entity": [ + "id", + "type", + "created_at", + "created_by", + "modified_at", + "modified_by" + ] + }, + "lookup_fields": [], + "historical": false, + "relationship": false + } + ] + }, + "tests": [ + { + "description": "Should execute a standard UPSERT via the mock database", + "action": "merge", + "data": { + "id": "123", + "type": "simple_entity", + "name": "Jane" + }, + "expect": { + "success": true, + "sql": [ + "SELECT to_jsonb(t1.*) || to_jsonb(t2.*) FROM agreego.\"simple_entity\" t1 LEFT JOIN agreego.\"entity\" t2 ON t2.id = t1.id WHERE t1.id = '123'", + "INSERT INTO agreego.\"simple_entity\" (\"id\", \"name\", \"type\") VALUES ('123', 'Jane', 'simple_entity')", + "INSERT INTO agreego.\"entity\" (\"created_at\", \"created_by\", \"id\", \"modified_at\", \"modified_by\", \"type\") VALUES ('{{timestamp}}', '00000000-0000-0000-0000-000000000000', '123', '{{timestamp}}', '00000000-0000-0000-0000-000000000000', 'simple_entity')", + "INSERT INTO agreego.change (changes, entity_id, id, kind, modified_at, modified_by) VALUES ('{\"name\":\"Jane\",\"type\":\"simple_entity\"}', '123', '{{uuid}}', 'create', '{{timestamp}}', '00000000-0000-0000-0000-000000000000')", + "SELECT pg_notify('entity', '{\"complete\":{\"created_at\":\"{{timestamp}}\",\"created_by\":\"00000000-0000-0000-0000-000000000000\",\"id\":\"123\",\"modified_at\":\"{{timestamp}}\",\"modified_by\":\"00000000-0000-0000-0000-000000000000\",\"name\":\"Jane\",\"type\":\"simple_entity\"}}')" + ] + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/minContains.json b/fixtures/minContains.json new file mode 100644 index 0000000..5f39485 --- /dev/null +++ b/fixtures/minContains.json @@ -0,0 +1,477 @@ +[ + { + "description": "minContains without contains is ignored", + "database": { + "schemas": [ + { + "minContains": 1, + "extensible": true, + "$id": "minContains_0_0" + } + ] + }, + "tests": [ + { + "description": "one item valid against lone minContains", + "data": [ + 1 + ], + "schema_id": "minContains_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "zero items still valid against lone minContains", + "data": [], + "schema_id": "minContains_0_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "minContains=1 with contains", + "database": { + "schemas": [ + { + "contains": { + "const": 1 + }, + "minContains": 1, + "extensible": true, + "$id": "minContains_1_0" + } + ] + }, + "tests": [ + { + "description": "empty data", + "data": [], + "schema_id": "minContains_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "no elements match", + "data": [ + 2 + ], + "schema_id": "minContains_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "single element matches, valid minContains", + "data": [ + 1 + ], + "schema_id": "minContains_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "some elements match, valid minContains", + "data": [ + 1, + 2 + ], + "schema_id": "minContains_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all elements match, valid minContains", + "data": [ + 1, + 1 + ], + "schema_id": "minContains_1_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "minContains=2 with contains", + "database": { + "schemas": [ + { + "contains": { + "const": 1 + }, + "minContains": 2, + "extensible": true, + "$id": "minContains_2_0" + } + ] + }, + "tests": [ + { + "description": "empty data", + "data": [], + "schema_id": "minContains_2_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "all elements match, invalid minContains", + "data": [ + 1 + ], + "schema_id": "minContains_2_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "some elements match, invalid minContains", + "data": [ + 1, + 2 + ], + "schema_id": "minContains_2_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "all elements match, valid minContains (exactly as needed)", + "data": [ + 1, + 1 + ], + "schema_id": "minContains_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "all elements match, valid minContains (more than needed)", + "data": [ + 1, + 1, + 1 + ], + "schema_id": "minContains_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "some elements match, valid minContains", + "data": [ + 1, + 2, + 1 + ], + "schema_id": "minContains_2_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "minContains=2 with contains with a decimal value", + "database": { + "schemas": [ + { + "contains": { + "const": 1 + }, + "minContains": 2, + "extensible": true, + "$id": "minContains_3_0" + } + ] + }, + "tests": [ + { + "description": "one element matches, invalid minContains", + "data": [ + 1 + ], + "schema_id": "minContains_3_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "both elements match, valid minContains", + "data": [ + 1, + 1 + ], + "schema_id": "minContains_3_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "maxContains = minContains", + "database": { + "schemas": [ + { + "contains": { + "const": 1 + }, + "maxContains": 2, + "minContains": 2, + "extensible": true, + "$id": "minContains_4_0" + } + ] + }, + "tests": [ + { + "description": "empty data", + "data": [], + "schema_id": "minContains_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "all elements match, invalid minContains", + "data": [ + 1 + ], + "schema_id": "minContains_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "all elements match, invalid maxContains", + "data": [ + 1, + 1, + 1 + ], + "schema_id": "minContains_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "all elements match, valid maxContains and minContains", + "data": [ + 1, + 1 + ], + "schema_id": "minContains_4_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "maxContains < minContains", + "database": { + "schemas": [ + { + "contains": { + "const": 1 + }, + "maxContains": 1, + "minContains": 3, + "extensible": true, + "$id": "minContains_5_0" + } + ] + }, + "tests": [ + { + "description": "empty data", + "data": [], + "schema_id": "minContains_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid minContains", + "data": [ + 1 + ], + "schema_id": "minContains_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid maxContains", + "data": [ + 1, + 1, + 1 + ], + "schema_id": "minContains_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "invalid maxContains and minContains", + "data": [ + 1, + 1 + ], + "schema_id": "minContains_5_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "minContains = 0", + "database": { + "schemas": [ + { + "contains": { + "const": 1 + }, + "minContains": 0, + "extensible": true, + "$id": "minContains_6_0" + } + ] + }, + "tests": [ + { + "description": "empty data", + "data": [], + "schema_id": "minContains_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "minContains = 0 makes contains always pass", + "data": [ + 2 + ], + "schema_id": "minContains_6_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "minContains = 0 with maxContains", + "database": { + "schemas": [ + { + "contains": { + "const": 1 + }, + "minContains": 0, + "maxContains": 1, + "extensible": true, + "$id": "minContains_7_0" + } + ] + }, + "tests": [ + { + "description": "empty data", + "data": [], + "schema_id": "minContains_7_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "not more than maxContains", + "data": [ + 1 + ], + "schema_id": "minContains_7_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "too many", + "data": [ + 1, + 1 + ], + "schema_id": "minContains_7_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "extensible: true allows non-matching items in minContains", + "database": { + "schemas": [ + { + "contains": { + "const": 1 + }, + "minContains": 1, + "extensible": true, + "$id": "minContains_8_0" + } + ] + }, + "tests": [ + { + "description": "extra items disregarded for minContains", + "data": [ + 1, + 2 + ], + "schema_id": "minContains_8_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/minItems.json b/fixtures/minItems.json new file mode 100644 index 0000000..e5f03f5 --- /dev/null +++ b/fixtures/minItems.json @@ -0,0 +1,117 @@ +[ + { + "description": "minItems validation", + "database": { + "schemas": [ + { + "minItems": 1, + "extensible": true, + "$id": "minItems_0_0" + } + ] + }, + "tests": [ + { + "description": "longer is valid", + "data": [ + 1, + 2 + ], + "schema_id": "minItems_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "exact length is valid", + "data": [ + 1 + ], + "schema_id": "minItems_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "too short is invalid", + "data": [], + "schema_id": "minItems_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "ignores non-arrays", + "data": "", + "schema_id": "minItems_0_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "minItems validation with a decimal", + "database": { + "schemas": [ + { + "minItems": 1, + "extensible": true, + "$id": "minItems_1_0" + } + ] + }, + "tests": [ + { + "description": "longer is valid", + "data": [ + 1, + 2 + ], + "schema_id": "minItems_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "too short is invalid", + "data": [], + "schema_id": "minItems_1_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "extensible: true allows extra items in minItems", + "database": { + "schemas": [ + { + "minItems": 1, + "extensible": true, + "$id": "minItems_2_0" + } + ] + }, + "tests": [ + { + "description": "extra item counted towards minItems", + "data": [ + 1 + ], + "schema_id": "minItems_2_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/minLength.json b/fixtures/minLength.json new file mode 100644 index 0000000..3c6e10a --- /dev/null +++ b/fixtures/minLength.json @@ -0,0 +1,91 @@ +[ + { + "description": "minLength validation", + "database": { + "schemas": [ + { + "minLength": 2, + "$id": "minLength_0_0" + } + ] + }, + "tests": [ + { + "description": "longer is valid", + "data": "foo", + "schema_id": "minLength_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "exact length is valid", + "data": "fo", + "schema_id": "minLength_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "too short is invalid", + "data": "f", + "schema_id": "minLength_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "ignores non-strings", + "data": 1, + "schema_id": "minLength_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "one grapheme is not long enough", + "data": "💩", + "schema_id": "minLength_0_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "minLength validation with a decimal", + "database": { + "schemas": [ + { + "minLength": 2, + "$id": "minLength_1_0" + } + ] + }, + "tests": [ + { + "description": "longer is valid", + "data": "foo", + "schema_id": "minLength_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "too short is invalid", + "data": "f", + "schema_id": "minLength_1_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/minProperties.json b/fixtures/minProperties.json new file mode 100644 index 0000000..6e2da84 --- /dev/null +++ b/fixtures/minProperties.json @@ -0,0 +1,135 @@ +[ + { + "description": "minProperties validation", + "database": { + "schemas": [ + { + "minProperties": 1, + "extensible": true, + "$id": "minProperties_0_0" + } + ] + }, + "tests": [ + { + "description": "longer is valid", + "data": { + "foo": 1, + "bar": 2 + }, + "schema_id": "minProperties_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "exact length is valid", + "data": { + "foo": 1 + }, + "schema_id": "minProperties_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "too short is invalid", + "data": {}, + "schema_id": "minProperties_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "ignores arrays", + "data": [], + "schema_id": "minProperties_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores strings", + "data": "", + "schema_id": "minProperties_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores other non-objects", + "data": 12, + "schema_id": "minProperties_0_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "minProperties validation with a decimal", + "database": { + "schemas": [ + { + "minProperties": 1, + "extensible": true, + "$id": "minProperties_1_0" + } + ] + }, + "tests": [ + { + "description": "longer is valid", + "data": { + "foo": 1, + "bar": 2 + }, + "schema_id": "minProperties_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "too short is invalid", + "data": {}, + "schema_id": "minProperties_1_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "extensible: true allows extra properties in minProperties", + "database": { + "schemas": [ + { + "minProperties": 1, + "extensible": true, + "$id": "minProperties_2_0" + } + ] + }, + "tests": [ + { + "description": "extra property counts towards minProperties", + "data": { + "foo": 1 + }, + "schema_id": "minProperties_2_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/minimum.json b/fixtures/minimum.json new file mode 100644 index 0000000..f3b39dd --- /dev/null +++ b/fixtures/minimum.json @@ -0,0 +1,127 @@ +[ + { + "description": "minimum validation", + "database": { + "schemas": [ + { + "minimum": 1.1, + "$id": "minimum_0_0" + } + ] + }, + "tests": [ + { + "description": "above the minimum is valid", + "data": 2.6, + "schema_id": "minimum_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "boundary point is valid", + "data": 1.1, + "schema_id": "minimum_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "below the minimum is invalid", + "data": 0.6, + "schema_id": "minimum_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "ignores non-numbers", + "data": "x", + "schema_id": "minimum_0_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "minimum validation with signed integer", + "database": { + "schemas": [ + { + "minimum": -2, + "$id": "minimum_1_0" + } + ] + }, + "tests": [ + { + "description": "negative above the minimum is valid", + "data": -1, + "schema_id": "minimum_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "positive above the minimum is valid", + "data": 0, + "schema_id": "minimum_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "boundary point is valid", + "data": -2, + "schema_id": "minimum_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "boundary point with float is valid", + "data": -2, + "schema_id": "minimum_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "float below the minimum is invalid", + "data": -2.0001, + "schema_id": "minimum_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "int below the minimum is invalid", + "data": -3, + "schema_id": "minimum_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "ignores non-numbers", + "data": "x", + "schema_id": "minimum_1_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/multipleOf.json b/fixtures/multipleOf.json new file mode 100644 index 0000000..3a2163f --- /dev/null +++ b/fixtures/multipleOf.json @@ -0,0 +1,136 @@ +[ + { + "description": "by int", + "database": { + "schemas": [ + { + "multipleOf": 2, + "$id": "multipleOf_0_0" + } + ] + }, + "tests": [ + { + "description": "int by int", + "data": 10, + "schema_id": "multipleOf_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "int by int fail", + "data": 7, + "schema_id": "multipleOf_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "ignores non-numbers", + "data": "foo", + "schema_id": "multipleOf_0_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "by number", + "database": { + "schemas": [ + { + "multipleOf": 1.5, + "$id": "multipleOf_1_0" + } + ] + }, + "tests": [ + { + "description": "zero is multiple of anything", + "data": 0, + "schema_id": "multipleOf_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "4.5 is multiple of 1.5", + "data": 4.5, + "schema_id": "multipleOf_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "35 is not multiple of 1.5", + "data": 35, + "schema_id": "multipleOf_1_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "by small number", + "database": { + "schemas": [ + { + "multipleOf": 0.0001, + "$id": "multipleOf_2_0" + } + ] + }, + "tests": [ + { + "description": "0.0075 is multiple of 0.0001", + "data": 0.0075, + "schema_id": "multipleOf_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "0.00751 is not multiple of 0.0001", + "data": 0.00751, + "schema_id": "multipleOf_2_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "small multiple of large integer", + "database": { + "schemas": [ + { + "type": "integer", + "multipleOf": 1e-8, + "$id": "multipleOf_3_0" + } + ] + }, + "tests": [ + { + "description": "any integer is a multiple of 1e-8", + "data": 12391239123, + "schema_id": "multipleOf_3_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/not.json b/fixtures/not.json new file mode 100644 index 0000000..4ad9bf6 --- /dev/null +++ b/fixtures/not.json @@ -0,0 +1,618 @@ +[ + { + "description": "not", + "database": { + "schemas": [ + { + "not": { + "type": "integer" + }, + "$id": "not_0_0" + } + ] + }, + "tests": [ + { + "description": "allowed", + "data": "foo", + "schema_id": "not_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "disallowed", + "data": 1, + "schema_id": "not_0_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "not multiple types", + "database": { + "schemas": [ + { + "not": { + "type": [ + "integer", + "boolean" + ] + }, + "$id": "not_1_0" + } + ] + }, + "tests": [ + { + "description": "valid", + "data": "foo", + "schema_id": "not_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "mismatch", + "data": 1, + "schema_id": "not_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "other mismatch", + "data": true, + "schema_id": "not_1_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "not more complex schema", + "database": { + "schemas": [ + { + "not": { + "type": "object", + "properties": { + "foo": { + "type": "string" + } + } + }, + "extensible": true, + "$id": "not_2_0" + } + ] + }, + "tests": [ + { + "description": "match", + "data": 1, + "schema_id": "not_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "other match", + "data": { + "foo": 1 + }, + "schema_id": "not_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "mismatch", + "data": { + "foo": "bar" + }, + "schema_id": "not_2_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "forbidden property", + "database": { + "schemas": [ + { + "properties": { + "foo": { + "not": {} + } + }, + "$id": "not_3_0" + } + ] + }, + "tests": [ + { + "description": "property present", + "data": { + "foo": 1, + "bar": 2 + }, + "schema_id": "not_3_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "empty object is valid", + "data": {}, + "schema_id": "not_3_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "forbid everything with empty schema", + "database": { + "schemas": [ + { + "not": {}, + "$id": "not_4_0" + } + ] + }, + "tests": [ + { + "description": "number is invalid", + "data": 1, + "schema_id": "not_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "string is invalid", + "data": "foo", + "schema_id": "not_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "boolean true is invalid", + "data": true, + "schema_id": "not_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "boolean false is invalid", + "data": false, + "schema_id": "not_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "null is invalid", + "data": null, + "schema_id": "not_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "object is invalid", + "data": { + "foo": "bar" + }, + "schema_id": "not_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "empty object is invalid", + "data": {}, + "schema_id": "not_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "array is invalid", + "data": [ + "foo" + ], + "schema_id": "not_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "empty array is invalid", + "data": [], + "schema_id": "not_4_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "forbid everything with boolean schema true", + "database": { + "schemas": [ + { + "not": true, + "$id": "not_5_0" + } + ] + }, + "tests": [ + { + "description": "number is invalid", + "data": 1, + "schema_id": "not_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "string is invalid", + "data": "foo", + "schema_id": "not_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "boolean true is invalid", + "data": true, + "schema_id": "not_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "boolean false is invalid", + "data": false, + "schema_id": "not_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "null is invalid", + "data": null, + "schema_id": "not_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "object is invalid", + "data": { + "foo": "bar" + }, + "schema_id": "not_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "empty object is invalid", + "data": {}, + "schema_id": "not_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "array is invalid", + "data": [ + "foo" + ], + "schema_id": "not_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "empty array is invalid", + "data": [], + "schema_id": "not_5_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "allow everything with boolean schema false", + "database": { + "schemas": [ + { + "not": false, + "extensible": true, + "$id": "not_6_0" + } + ] + }, + "tests": [ + { + "description": "number is valid", + "data": 1, + "schema_id": "not_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "string is valid", + "data": "foo", + "schema_id": "not_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "boolean true is valid", + "data": true, + "schema_id": "not_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "boolean false is valid", + "data": false, + "schema_id": "not_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "null is valid", + "data": null, + "schema_id": "not_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "object is valid", + "data": { + "foo": "bar" + }, + "schema_id": "not_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "empty object is valid", + "data": {}, + "schema_id": "not_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "array is valid", + "data": [ + "foo" + ], + "schema_id": "not_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "empty array is valid", + "data": [], + "schema_id": "not_6_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "double negation", + "database": { + "schemas": [ + { + "not": { + "not": {} + }, + "$id": "not_7_0" + } + ] + }, + "tests": [ + { + "description": "any value is valid", + "data": "foo", + "schema_id": "not_7_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "extensible: true allows extra properties in not", + "database": { + "schemas": [ + { + "not": { + "type": "integer" + }, + "extensible": true, + "$id": "not_8_0" + } + ] + }, + "tests": [ + { + "description": "extra property is valid (not integer matches)", + "data": { + "foo": 1 + }, + "schema_id": "not_8_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "extensible: false (default) forbids extra properties in not", + "database": { + "schemas": [ + { + "not": { + "type": "integer" + }, + "$id": "not_9_0" + } + ] + }, + "tests": [ + { + "description": "extra property is invalid due to strictness", + "data": { + "foo": 1 + }, + "schema_id": "not_9_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "property next to not (extensible: true)", + "database": { + "schemas": [ + { + "properties": { + "bar": { + "type": "string" + } + }, + "not": { + "type": "integer" + }, + "extensible": true, + "$id": "not_10_0" + } + ] + }, + "tests": [ + { + "description": "extra property allowed", + "data": { + "bar": "baz", + "foo": 1 + }, + "schema_id": "not_10_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "property next to not (extensible: false)", + "database": { + "schemas": [ + { + "properties": { + "bar": { + "type": "string" + } + }, + "not": { + "type": "integer" + }, + "$id": "not_11_0" + } + ] + }, + "tests": [ + { + "description": "extra property forbidden", + "data": { + "bar": "baz", + "foo": 1 + }, + "schema_id": "not_11_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "defined property allowed", + "data": { + "bar": "baz" + }, + "schema_id": "not_11_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/oneOf.json b/fixtures/oneOf.json new file mode 100644 index 0000000..a410d95 --- /dev/null +++ b/fixtures/oneOf.json @@ -0,0 +1,670 @@ +[ + { + "description": "oneOf", + "database": { + "schemas": [ + { + "oneOf": [ + { + "type": "integer" + }, + { + "minimum": 2 + } + ], + "$id": "oneOf_0_0" + } + ] + }, + "tests": [ + { + "description": "first oneOf valid", + "data": 1, + "schema_id": "oneOf_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "second oneOf valid", + "data": 2.5, + "schema_id": "oneOf_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "both oneOf valid", + "data": 3, + "schema_id": "oneOf_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "neither oneOf valid", + "data": 1.5, + "schema_id": "oneOf_0_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "oneOf with base schema", + "database": { + "schemas": [ + { + "type": "string", + "oneOf": [ + { + "minLength": 2 + }, + { + "maxLength": 4 + } + ], + "$id": "oneOf_1_0" + } + ] + }, + "tests": [ + { + "description": "mismatch base schema", + "data": 3, + "schema_id": "oneOf_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "one oneOf valid", + "data": "foobar", + "schema_id": "oneOf_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "both oneOf valid", + "data": "foo", + "schema_id": "oneOf_1_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "oneOf with boolean schemas, all true", + "database": { + "schemas": [ + { + "oneOf": [ + true, + true, + true + ], + "$id": "oneOf_2_0" + } + ] + }, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "schema_id": "oneOf_2_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "oneOf with boolean schemas, one true", + "database": { + "schemas": [ + { + "oneOf": [ + true, + false, + false + ], + "$id": "oneOf_3_0" + } + ] + }, + "tests": [ + { + "description": "any value is valid", + "data": "foo", + "schema_id": "oneOf_3_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "oneOf with boolean schemas, more than one true", + "database": { + "schemas": [ + { + "oneOf": [ + true, + true, + false + ], + "$id": "oneOf_4_0" + } + ] + }, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "schema_id": "oneOf_4_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "oneOf with boolean schemas, all false", + "database": { + "schemas": [ + { + "oneOf": [ + false, + false, + false + ], + "$id": "oneOf_5_0" + } + ] + }, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "schema_id": "oneOf_5_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "oneOf complex types", + "database": { + "schemas": [ + { + "oneOf": [ + { + "properties": { + "bar": { + "type": "integer" + } + }, + "required": [ + "bar" + ] + }, + { + "properties": { + "foo": { + "type": "string" + } + }, + "required": [ + "foo" + ] + } + ], + "$id": "oneOf_6_0" + } + ] + }, + "tests": [ + { + "description": "first oneOf valid (complex)", + "data": { + "bar": 2 + }, + "schema_id": "oneOf_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "second oneOf valid (complex)", + "data": { + "foo": "baz" + }, + "schema_id": "oneOf_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "both oneOf valid (complex)", + "data": { + "foo": "baz", + "bar": 2 + }, + "schema_id": "oneOf_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "neither oneOf valid (complex)", + "data": { + "foo": 2, + "bar": "quux" + }, + "schema_id": "oneOf_6_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "oneOf with empty schema", + "database": { + "schemas": [ + { + "oneOf": [ + { + "type": "number" + }, + {} + ], + "$id": "oneOf_7_0" + } + ] + }, + "tests": [ + { + "description": "one valid - valid", + "data": "foo", + "schema_id": "oneOf_7_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "both valid - invalid", + "data": 123, + "schema_id": "oneOf_7_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "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 + }, + "schema_id": "oneOf_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "first valid - valid", + "data": { + "foo": 1, + "bar": 2 + }, + "schema_id": "oneOf_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "second valid - valid", + "data": { + "foo": 1, + "baz": 3 + }, + "schema_id": "oneOf_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "both valid - invalid", + "data": { + "foo": 1, + "bar": 2, + "baz": 3 + }, + "schema_id": "oneOf_8_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "extra property invalid (strict)", + "data": { + "foo": 1, + "bar": 2, + "extra": 3 + }, + "schema_id": "oneOf_8_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "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 + }, + "schema_id": "oneOf_9_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "first valid - valid", + "data": { + "foo": 1, + "bar": 2 + }, + "schema_id": "oneOf_9_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "second valid - valid", + "data": { + "foo": 1, + "baz": 3 + }, + "schema_id": "oneOf_9_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "both valid - invalid", + "data": { + "foo": 1, + "bar": 2, + "baz": 3 + }, + "schema_id": "oneOf_9_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "extra properties are valid (extensible)", + "data": { + "foo": 1, + "bar": 2, + "extra": "value" + }, + "schema_id": "oneOf_9_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "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 + }, + "schema_id": "oneOf_10_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "second oneOf valid", + "data": { + "foo": "foo" + }, + "schema_id": "oneOf_10_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "both oneOf valid", + "data": { + "foo": "foo", + "bar": 8 + }, + "schema_id": "oneOf_10_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "neither oneOf valid", + "data": { + "baz": "quux" + }, + "schema_id": "oneOf_10_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "nested oneOf, to check validation semantics", + "database": { + "schemas": [ + { + "oneOf": [ + { + "oneOf": [ + { + "type": "null" + } + ] + } + ], + "$id": "oneOf_11_0" + } + ] + }, + "tests": [ + { + "description": "null is valid", + "data": null, + "schema_id": "oneOf_11_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "anything non-null is invalid", + "data": 123, + "schema_id": "oneOf_11_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "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" + } + ] + }, + "tests": [ + { + "description": "extra property is valid (matches first option)", + "data": { + "bar": 2, + "extra": "prop" + }, + "schema_id": "oneOf_12_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/pattern.json b/fixtures/pattern.json new file mode 100644 index 0000000..264d7ab --- /dev/null +++ b/fixtures/pattern.json @@ -0,0 +1,109 @@ +[ + { + "description": "pattern validation", + "database": { + "schemas": [ + { + "pattern": "^a*$", + "$id": "pattern_0_0" + } + ] + }, + "tests": [ + { + "description": "a matching pattern is valid", + "data": "aaa", + "schema_id": "pattern_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a non-matching pattern is invalid", + "data": "abc", + "schema_id": "pattern_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "ignores booleans", + "data": true, + "schema_id": "pattern_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores integers", + "data": 123, + "schema_id": "pattern_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores floats", + "data": 1, + "schema_id": "pattern_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores objects", + "data": {}, + "schema_id": "pattern_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores arrays", + "data": [], + "schema_id": "pattern_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores null", + "data": null, + "schema_id": "pattern_0_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "pattern is not anchored", + "database": { + "schemas": [ + { + "pattern": "a+", + "$id": "pattern_1_0" + } + ] + }, + "tests": [ + { + "description": "matches a substring", + "data": "xxaayy", + "schema_id": "pattern_1_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/patternProperties.json b/fixtures/patternProperties.json new file mode 100644 index 0000000..ada1c83 --- /dev/null +++ b/fixtures/patternProperties.json @@ -0,0 +1,399 @@ +[ + { + "description": "patternProperties validates properties matching a regex", + "database": { + "schemas": [ + { + "patternProperties": { + "f.*o": { + "type": "integer" + } + }, + "items": {}, + "$id": "patternProperties_0_0" + } + ] + }, + "tests": [ + { + "description": "a single valid match is valid", + "data": { + "foo": 1 + }, + "schema_id": "patternProperties_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "multiple valid matches is valid", + "data": { + "foo": 1, + "foooooo": 2 + }, + "schema_id": "patternProperties_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a single invalid match is invalid", + "data": { + "foo": "bar", + "fooooo": 2 + }, + "schema_id": "patternProperties_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "multiple invalid matches is invalid", + "data": { + "foo": "bar", + "foooooo": "baz" + }, + "schema_id": "patternProperties_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "ignores arrays", + "data": [ + "foo" + ], + "schema_id": "patternProperties_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores strings", + "data": "foo", + "schema_id": "patternProperties_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores other non-objects", + "data": 12, + "schema_id": "patternProperties_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "extra property not matching pattern is INVALID (strict by default)", + "data": { + "foo": 1, + "extra": 2 + }, + "schema_id": "patternProperties_0_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "multiple simultaneous patternProperties are validated", + "database": { + "schemas": [ + { + "patternProperties": { + "a*": { + "type": "integer" + }, + "aaa*": { + "maximum": 20 + } + }, + "$id": "patternProperties_1_0" + } + ] + }, + "tests": [ + { + "description": "a single valid match is valid", + "data": { + "a": 21 + }, + "schema_id": "patternProperties_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a simultaneous match is valid", + "data": { + "aaaa": 18 + }, + "schema_id": "patternProperties_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "multiple matches is valid", + "data": { + "a": 21, + "aaaa": 18 + }, + "schema_id": "patternProperties_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an invalid due to one is invalid", + "data": { + "a": "bar" + }, + "schema_id": "patternProperties_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid due to the other is invalid", + "data": { + "aaaa": 31 + }, + "schema_id": "patternProperties_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an invalid due to both is invalid", + "data": { + "aaa": "foo", + "aaaa": 31 + }, + "schema_id": "patternProperties_1_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "regexes are not anchored by default and are case sensitive", + "database": { + "schemas": [ + { + "patternProperties": { + "[0-9]{2,}": { + "type": "boolean" + }, + "X_": { + "type": "string" + } + }, + "extensible": true, + "$id": "patternProperties_2_0" + } + ] + }, + "tests": [ + { + "description": "non recognized members are ignored", + "data": { + "answer 1": "42" + }, + "schema_id": "patternProperties_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "recognized members are accounted for", + "data": { + "a31b": null + }, + "schema_id": "patternProperties_2_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "regexes are case sensitive", + "data": { + "a_x_3": 3 + }, + "schema_id": "patternProperties_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "regexes are case sensitive, 2", + "data": { + "a_X_3": 3 + }, + "schema_id": "patternProperties_2_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "patternProperties with boolean schemas", + "database": { + "schemas": [ + { + "patternProperties": { + "f.*": true, + "b.*": false + }, + "$id": "patternProperties_3_0" + } + ] + }, + "tests": [ + { + "description": "object with property matching schema true is valid", + "data": { + "foo": 1 + }, + "schema_id": "patternProperties_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "object with property matching schema false is invalid", + "data": { + "bar": 2 + }, + "schema_id": "patternProperties_3_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "object with both properties is invalid", + "data": { + "foo": 1, + "bar": 2 + }, + "schema_id": "patternProperties_3_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "object with a property matching both true and false is invalid", + "data": { + "foobar": 1 + }, + "schema_id": "patternProperties_3_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "empty object is valid", + "data": {}, + "schema_id": "patternProperties_3_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "patternProperties with null valued instance properties", + "database": { + "schemas": [ + { + "patternProperties": { + "^.*bar$": { + "type": "null" + } + }, + "$id": "patternProperties_4_0" + } + ] + }, + "tests": [ + { + "description": "allows null values", + "data": { + "foobar": null + }, + "schema_id": "patternProperties_4_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "extensible: true allows extra properties NOT matching pattern", + "database": { + "schemas": [ + { + "patternProperties": { + "f.*o": { + "type": "integer" + } + }, + "extensible": true, + "$id": "patternProperties_5_0" + } + ] + }, + "tests": [ + { + "description": "extra property not matching pattern is valid", + "data": { + "bar": 1 + }, + "schema_id": "patternProperties_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "property matching pattern MUST still be valid", + "data": { + "foo": "invalid string" + }, + "schema_id": "patternProperties_5_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/prefixItems.json b/fixtures/prefixItems.json new file mode 100644 index 0000000..a3ce3c2 --- /dev/null +++ b/fixtures/prefixItems.json @@ -0,0 +1,229 @@ +[ + { + "description": "a schema given for prefixItems", + "database": { + "schemas": [ + { + "prefixItems": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "$id": "prefixItems_0_0" + } + ] + }, + "tests": [ + { + "description": "correct types", + "data": [ + 1, + "foo" + ], + "schema_id": "prefixItems_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "wrong types", + "data": [ + "foo", + 1 + ], + "schema_id": "prefixItems_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "incomplete array of items", + "data": [ + 1 + ], + "schema_id": "prefixItems_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "array with additional items (invalid due to strictness)", + "data": [ + 1, + "foo", + true + ], + "schema_id": "prefixItems_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "empty array", + "data": [], + "schema_id": "prefixItems_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "JavaScript pseudo-array is valid (invalid due to strict object validation)", + "data": { + "0": "invalid", + "1": "valid", + "length": 2 + }, + "schema_id": "prefixItems_0_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "prefixItems with boolean schemas", + "database": { + "schemas": [ + { + "prefixItems": [ + true, + false + ], + "$id": "prefixItems_1_0" + } + ] + }, + "tests": [ + { + "description": "array with one item is valid", + "data": [ + 1 + ], + "schema_id": "prefixItems_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "array with two items is invalid", + "data": [ + 1, + "foo" + ], + "schema_id": "prefixItems_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "empty array is valid", + "data": [], + "schema_id": "prefixItems_1_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "additional items are allowed by default", + "database": { + "schemas": [ + { + "prefixItems": [ + { + "type": "integer" + } + ], + "extensible": true, + "$id": "prefixItems_2_0" + } + ] + }, + "tests": [ + { + "description": "only the first item is validated", + "data": [ + 1, + "foo", + false + ], + "schema_id": "prefixItems_2_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "prefixItems with null instance elements", + "database": { + "schemas": [ + { + "prefixItems": [ + { + "type": "null" + } + ], + "$id": "prefixItems_3_0" + } + ] + }, + "tests": [ + { + "description": "allows null elements", + "data": [ + null + ], + "schema_id": "prefixItems_3_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "extensible: true allows extra items with prefixItems", + "database": { + "schemas": [ + { + "prefixItems": [ + { + "type": "integer" + } + ], + "extensible": true, + "$id": "prefixItems_4_0" + } + ] + }, + "tests": [ + { + "description": "extra item is valid", + "data": [ + 1, + "foo" + ], + "schema_id": "prefixItems_4_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/properties.json b/fixtures/properties.json new file mode 100644 index 0000000..6f8923e --- /dev/null +++ b/fixtures/properties.json @@ -0,0 +1,627 @@ +[ + { + "description": "object properties validation", + "database": { + "schemas": [ + { + "properties": { + "foo": { + "type": "integer" + }, + "bar": { + "type": "string" + } + }, + "$id": "properties_0_0" + } + ] + }, + "tests": [ + { + "description": "both properties present and valid is valid", + "data": { + "foo": 1, + "bar": "baz" + }, + "schema_id": "properties_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "one property invalid is invalid", + "data": { + "foo": 1, + "bar": {} + }, + "schema_id": "properties_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "both properties invalid is invalid", + "data": { + "foo": [], + "bar": {} + }, + "schema_id": "properties_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "doesn't invalidate other properties", + "data": {}, + "schema_id": "properties_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores arrays", + "data": [], + "schema_id": "properties_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores other non-objects", + "data": 12, + "schema_id": "properties_0_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "properties with boolean schema", + "database": { + "schemas": [ + { + "properties": { + "foo": true, + "bar": false + }, + "$id": "properties_1_0" + } + ] + }, + "tests": [ + { + "description": "no property present is valid", + "data": {}, + "schema_id": "properties_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "only 'true' property present is valid", + "data": { + "foo": 1 + }, + "schema_id": "properties_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "only 'false' property present is invalid", + "data": { + "bar": 2 + }, + "schema_id": "properties_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "both properties present is invalid", + "data": { + "foo": 1, + "bar": 2 + }, + "schema_id": "properties_1_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "properties with escaped characters", + "database": { + "schemas": [ + { + "properties": { + "foo\nbar": { + "type": "number" + }, + "foo\"bar": { + "type": "number" + }, + "foo\\bar": { + "type": "number" + }, + "foo\rbar": { + "type": "number" + }, + "foo\tbar": { + "type": "number" + }, + "foo\fbar": { + "type": "number" + } + }, + "$id": "properties_2_0" + } + ] + }, + "tests": [ + { + "description": "object with all numbers is valid", + "data": { + "foo\nbar": 1, + "foo\"bar": 1, + "foo\\bar": 1, + "foo\rbar": 1, + "foo\tbar": 1, + "foo\fbar": 1 + }, + "schema_id": "properties_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "object with strings is invalid", + "data": { + "foo\nbar": "1", + "foo\"bar": "1", + "foo\\bar": "1", + "foo\rbar": "1", + "foo\tbar": "1", + "foo\fbar": "1" + }, + "schema_id": "properties_2_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "properties with null valued instance properties", + "database": { + "schemas": [ + { + "properties": { + "foo": { + "type": "null" + } + }, + "$id": "properties_3_0" + } + ] + }, + "tests": [ + { + "description": "allows null values", + "data": { + "foo": null + }, + "schema_id": "properties_3_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "properties whose names are Javascript object property names", + "comment": "Ensure JS implementations don't universally consider e.g. __proto__ to always be present in an object.", + "database": { + "schemas": [ + { + "properties": { + "__proto__": { + "type": "number" + }, + "toString": { + "properties": { + "length": { + "type": "string" + } + } + }, + "constructor": { + "type": "number" + } + }, + "$id": "properties_4_0" + } + ] + }, + "tests": [ + { + "description": "ignores arrays", + "data": [], + "schema_id": "properties_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores other non-objects", + "data": 12, + "schema_id": "properties_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "none of the properties mentioned", + "data": {}, + "schema_id": "properties_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "__proto__ not valid", + "data": { + "__proto__": "foo" + }, + "schema_id": "properties_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "toString not valid", + "data": { + "toString": { + "length": 37 + } + }, + "schema_id": "properties_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "constructor not valid", + "data": { + "constructor": { + "length": 37 + } + }, + "schema_id": "properties_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "all present and valid", + "data": { + "__proto__": 12, + "toString": { + "length": "foo" + }, + "constructor": 37 + }, + "schema_id": "properties_4_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "extensible: true allows extra properties", + "database": { + "schemas": [ + { + "properties": { + "foo": { + "type": "integer" + } + }, + "extensible": true, + "$id": "properties_5_0" + } + ] + }, + "tests": [ + { + "description": "extra property is valid", + "data": { + "foo": 1, + "bar": "baz" + }, + "schema_id": "properties_5_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "strict by default: extra properties invalid", + "database": { + "schemas": [ + { + "properties": { + "foo": { + "type": "string" + } + }, + "$id": "properties_6_0" + } + ] + }, + "tests": [ + { + "description": "extra property is invalid", + "data": { + "foo": "bar", + "extra": 1 + }, + "schema_id": "properties_6_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "inheritance: nested object inherits strictness from strict parent", + "database": { + "schemas": [ + { + "properties": { + "nested": { + "properties": { + "foo": { + "type": "string" + } + } + } + }, + "$id": "properties_7_0" + } + ] + }, + "tests": [ + { + "description": "nested extra property is invalid", + "data": { + "nested": { + "foo": "bar", + "extra": 1 + } + }, + "schema_id": "properties_7_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "override: nested object allows extra properties if extensible: true", + "database": { + "schemas": [ + { + "properties": { + "nested": { + "extensible": true, + "properties": { + "foo": { + "type": "string" + } + } + } + }, + "$id": "properties_8_0" + } + ] + }, + "tests": [ + { + "description": "nested extra property is valid", + "data": { + "nested": { + "foo": "bar", + "extra": 1 + } + }, + "schema_id": "properties_8_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "inheritance: nested object inherits looseness from loose parent", + "database": { + "schemas": [ + { + "extensible": true, + "properties": { + "nested": { + "properties": { + "foo": { + "type": "string" + } + } + } + }, + "$id": "properties_9_0" + } + ] + }, + "tests": [ + { + "description": "nested extra property is valid", + "data": { + "nested": { + "foo": "bar", + "extra": 1 + } + }, + "schema_id": "properties_9_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "override: nested object enforces strictness if extensible: false", + "database": { + "schemas": [ + { + "extensible": true, + "properties": { + "nested": { + "extensible": false, + "properties": { + "foo": { + "type": "string" + } + } + } + }, + "$id": "properties_10_0" + } + ] + }, + "tests": [ + { + "description": "nested extra property is invalid", + "data": { + "nested": { + "foo": "bar", + "extra": 1 + } + }, + "schema_id": "properties_10_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "arrays: inline items inherit strictness from strict parent", + "database": { + "schemas": [ + { + "properties": { + "list": { + "type": "array", + "items": { + "properties": { + "foo": { + "type": "string" + } + } + } + } + }, + "$id": "properties_11_0" + } + ] + }, + "tests": [ + { + "description": "array item with extra property is invalid (strict parent)", + "data": { + "list": [ + { + "foo": "bar", + "extra": 1 + } + ] + }, + "schema_id": "properties_11_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "arrays: inline items inherit looseness from loose parent", + "database": { + "schemas": [ + { + "extensible": true, + "properties": { + "list": { + "type": "array", + "items": { + "properties": { + "foo": { + "type": "string" + } + } + } + } + }, + "$id": "properties_12_0" + } + ] + }, + "tests": [ + { + "description": "array item with extra property is valid (loose parent)", + "data": { + "list": [ + { + "foo": "bar", + "extra": 1 + } + ] + }, + "schema_id": "properties_12_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/propertyNames.json b/fixtures/propertyNames.json new file mode 100644 index 0000000..edf6a60 --- /dev/null +++ b/fixtures/propertyNames.json @@ -0,0 +1,347 @@ +[ + { + "description": "propertyNames validation", + "database": { + "schemas": [ + { + "propertyNames": { + "maxLength": 3 + }, + "extensible": true, + "$id": "propertyNames_0_0" + } + ] + }, + "tests": [ + { + "description": "all property names valid", + "data": { + "f": {}, + "foo": {} + }, + "schema_id": "propertyNames_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "some property names invalid", + "data": { + "foo": {}, + "foobar": {} + }, + "schema_id": "propertyNames_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "object without properties is valid", + "data": {}, + "schema_id": "propertyNames_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores arrays", + "data": [ + 1, + 2, + 3, + 4 + ], + "schema_id": "propertyNames_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores strings", + "data": "foobar", + "schema_id": "propertyNames_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores other non-objects", + "data": 12, + "schema_id": "propertyNames_0_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "propertyNames validation with pattern", + "database": { + "schemas": [ + { + "propertyNames": { + "pattern": "^a+$" + }, + "extensible": true, + "$id": "propertyNames_1_0" + } + ] + }, + "tests": [ + { + "description": "matching property names valid", + "data": { + "a": {}, + "aa": {}, + "aaa": {} + }, + "schema_id": "propertyNames_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "non-matching property name is invalid", + "data": { + "aaA": {} + }, + "schema_id": "propertyNames_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "object without properties is valid", + "data": {}, + "schema_id": "propertyNames_1_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "propertyNames with boolean schema true", + "database": { + "schemas": [ + { + "propertyNames": true, + "extensible": true, + "$id": "propertyNames_2_0" + } + ] + }, + "tests": [ + { + "description": "object with any properties is valid", + "data": { + "foo": 1 + }, + "schema_id": "propertyNames_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "empty object is valid", + "data": {}, + "schema_id": "propertyNames_2_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "propertyNames with boolean schema false", + "database": { + "schemas": [ + { + "propertyNames": false, + "extensible": true, + "$id": "propertyNames_3_0" + } + ] + }, + "tests": [ + { + "description": "object with any properties is invalid", + "data": { + "foo": 1 + }, + "schema_id": "propertyNames_3_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "empty object is valid", + "data": {}, + "schema_id": "propertyNames_3_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "propertyNames with const", + "database": { + "schemas": [ + { + "propertyNames": { + "const": "foo" + }, + "extensible": true, + "$id": "propertyNames_4_0" + } + ] + }, + "tests": [ + { + "description": "object with property foo is valid", + "data": { + "foo": 1 + }, + "schema_id": "propertyNames_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "object with any other property is invalid", + "data": { + "bar": 1 + }, + "schema_id": "propertyNames_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "empty object is valid", + "data": {}, + "schema_id": "propertyNames_4_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "propertyNames with enum", + "database": { + "schemas": [ + { + "propertyNames": { + "enum": [ + "foo", + "bar" + ] + }, + "extensible": true, + "$id": "propertyNames_5_0" + } + ] + }, + "tests": [ + { + "description": "object with property foo is valid", + "data": { + "foo": 1 + }, + "schema_id": "propertyNames_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "object with property foo and bar is valid", + "data": { + "foo": 1, + "bar": 1 + }, + "schema_id": "propertyNames_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "object with any other property is invalid", + "data": { + "baz": 1 + }, + "schema_id": "propertyNames_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "empty object is valid", + "data": {}, + "schema_id": "propertyNames_5_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "extensible: true allows extra properties (checked by propertyNames)", + "database": { + "schemas": [ + { + "propertyNames": { + "maxLength": 3 + }, + "extensible": true, + "$id": "propertyNames_6_0" + } + ] + }, + "tests": [ + { + "description": "extra property with valid name is valid", + "data": { + "foo": 1 + }, + "schema_id": "propertyNames_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "extra property with invalid name is invalid", + "data": { + "foobar": 1 + }, + "schema_id": "propertyNames_6_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/queryer.json b/fixtures/queryer.json new file mode 100644 index 0000000..6308f66 --- /dev/null +++ b/fixtures/queryer.json @@ -0,0 +1,599 @@ +[ + { + "description": "Basic Queryer Execution", + "database": { + "puncs": [], + "enums": [], + "relations": [], + "types": [ + { + "name": "entity", + "hierarchy": [ + "entity" + ], + "grouped_fields": { + "entity": [ + "id", + "name", + "archived", + "amount", + "created_at" + ] + }, + "field_types": { + "id": "uuid", + "name": "text", + "archived": "boolean", + "amount": "numeric", + "created_at": "timestamptz" + }, + "schemas": [ + { + "$id": "entity", + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "name": { + "type": "string" + }, + "archived": { + "type": "boolean" + }, + "amount": { + "type": "number" + }, + "created_at": { + "type": "string", + "format": "date-time" + } + } + } + ] + } + ] + }, + "tests": [ + { + "description": "Should execute a blanket SELECT query when no filters are present", + "action": "query", + "schema_id": "entity", + "expect": { + "success": true, + "sql": [ + "(SELECT jsonb_build_object('amount', t1_obj_t1.amount, 'archived', t1_obj_t1.archived, 'created_at', t1_obj_t1.created_at, 'id', t1_obj_t1.id, 'name', t1_obj_t1.name) FROM agreego.entity t1_obj_t1 WHERE NOT t1_obj_t1.archived)" + ] + } + }, + { + "description": "Should execute a blanket SELECT query isolating root stems directly", + "action": "query", + "schema_id": "entity", + "stem": "", + "expect": { + "success": true, + "sql": [ + "(SELECT jsonb_build_object('amount', t1_obj_t1.amount, 'archived', t1_obj_t1.archived, 'created_at', t1_obj_t1.created_at, 'id', t1_obj_t1.id, 'name', t1_obj_t1.name) FROM agreego.entity t1_obj_t1 WHERE NOT t1_obj_t1.archived)" + ] + } + }, + { + "description": "Should bind parameters with proper casting and ILIKE for generated generic SELECT string when using some filters", + "action": "query", + "schema_id": "entity", + "filters": { + "name": "Jane%", + "archived": false + }, + "expect": { + "success": true, + "sql": [ + "(SELECT jsonb_build_object('amount', t1_obj_t1.amount, 'archived', t1_obj_t1.archived, 'created_at', t1_obj_t1.created_at, 'id', t1_obj_t1.id, 'name', t1_obj_t1.name) FROM agreego.entity t1_obj_t1 WHERE NOT t1_obj_t1.archived AND t1_obj_t1.archived = ($1#>>'{}')::boolean AND t1_obj_t1.name ILIKE $2#>>'{}')" + ] + } + }, + { + "description": "Should bind all parameters with proper casting for complex generic SELECT string", + "action": "query", + "schema_id": "entity", + "filters": { + "id": "123e4567-e89b-12d3-a456-426614174000", + "name": "Jane%", + "amount": 100, + "created_at": "2023-01-01T00:00:00Z", + "archived": false + }, + "expect": { + "success": true, + "sql": [ + "(SELECT jsonb_build_object('amount', t1_obj_t1.amount, 'archived', t1_obj_t1.archived, 'created_at', t1_obj_t1.created_at, 'id', t1_obj_t1.id, 'name', t1_obj_t1.name) FROM agreego.entity t1_obj_t1 WHERE NOT t1_obj_t1.archived AND t1_obj_t1.amount = ($1#>>'{}')::numeric AND t1_obj_t1.archived = ($2#>>'{}')::boolean AND t1_obj_t1.created_at = ($3#>>'{}')::timestamptz AND t1_obj_t1.id = ($4#>>'{}')::uuid AND t1_obj_t1.name ILIKE $5#>>'{}')" + ] + } + } + ] + }, + { + "description": "Complex Nested Queryer Execution", + "database": { + "puncs": [], + "enums": [], + "relations": [ + { + "type": "relation", + "id": "00000000-0000-0000-0000-000000000001", + "constraint": "fk_contact_person", + "source_type": "contact", + "source_columns": [ + "source_id" + ], + "destination_type": "person", + "destination_columns": [ + "id" + ] + }, + { + "type": "relation", + "id": "00000000-0000-0000-0000-000000000002", + "constraint": "fk_contact_phone", + "source_type": "contact", + "source_columns": [ + "target_id" + ], + "destination_type": "phone_number", + "destination_columns": [ + "id" + ] + } + ], + "types": [ + { + "name": "entity", + "hierarchy": [ + "entity" + ], + "fields": [ + "id", + "type", + "archived" + ], + "grouped_fields": { + "entity": [ + "id", + "type", + "archived" + ] + }, + "field_types": { + "id": "uuid", + "type": "text", + "archived": "boolean" + }, + "schemas": [ + { + "$id": "entity", + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "type": { + "type": "string" + }, + "archived": { + "type": "boolean" + } + } + } + ] + }, + { + "name": "person", + "hierarchy": [ + "person", + "entity" + ], + "fields": [ + "id", + "type", + "archived", + "first_name", + "last_name" + ], + "grouped_fields": { + "entity": [ + "id", + "type", + "archived" + ], + "person": [ + "first_name", + "last_name" + ] + }, + "field_types": { + "id": "uuid", + "type": "text", + "archived": "boolean", + "first_name": "text", + "last_name": "text" + }, + "schemas": [ + { + "$id": "base.person", + "$ref": "entity", + "properties": { + "first_name": { + "type": "string" + }, + "last_name": { + "type": "string" + } + } + }, + { + "$id": "full.person", + "$ref": "base.person", + "properties": { + "phone_numbers": { + "type": "array", + "items": { + "$ref": "contact", + "properties": { + "target": { + "$ref": "phone_number" + } + } + } + }, + "email_addresses": { + "type": "array", + "items": { + "$ref": "contact", + "properties": { + "target": { + "$ref": "email_address" + } + } + } + }, + "addresses": { + "type": "array", + "items": { + "$ref": "contact", + "properties": { + "target": { + "$ref": "address" + } + } + } + }, + "contacts": { + "type": "array", + "items": { + "$ref": "contact", + "properties": { + "target": { + "oneOf": [ + { + "$ref": "phone_number" + }, + { + "$ref": "email_address" + }, + { + "$ref": "address" + } + ] + } + } + } + } + } + } + ] + }, + { + "name": "relationship", + "relationship": true, + "hierarchy": [ + "relationship", + "entity" + ], + "fields": [ + "id", + "type", + "archived", + "source_id", + "source_type", + "target_id", + "target_type" + ], + "grouped_fields": { + "entity": [ + "id", + "type", + "archived" + ], + "relationship": [ + "source_id", + "source_type", + "target_id", + "target_type" + ] + }, + "field_types": { + "id": "uuid", + "type": "text", + "archived": "boolean", + "source_id": "uuid", + "source_type": "text", + "target_id": "uuid", + "target_type": "text" + }, + "schemas": [ + { + "$id": "relationship", + "$ref": "entity", + "properties": {} + } + ] + }, + { + "name": "contact", + "relationship": true, + "hierarchy": [ + "contact", + "relationship", + "entity" + ], + "fields": [ + "id", + "type", + "archived", + "source_id", + "source_type", + "target_id", + "target_type", + "is_primary" + ], + "grouped_fields": { + "entity": [ + "id", + "type", + "archived" + ], + "relationship": [ + "source_id", + "source_type", + "target_id", + "target_type" + ], + "contact": [ + "is_primary" + ] + }, + "field_types": { + "id": "uuid", + "type": "text", + "archived": "boolean", + "source_id": "uuid", + "source_type": "text", + "target_id": "uuid", + "target_type": "text", + "is_primary": "boolean" + }, + "schemas": [ + { + "$id": "contact", + "$ref": "relationship", + "properties": { + "is_primary": { + "type": "boolean" + } + } + } + ] + }, + { + "name": "phone_number", + "hierarchy": [ + "phone_number", + "entity" + ], + "fields": [ + "id", + "type", + "archived", + "number" + ], + "grouped_fields": { + "entity": [ + "id", + "type", + "archived" + ], + "phone_number": [ + "number" + ] + }, + "field_types": { + "id": "uuid", + "type": "text", + "archived": "boolean", + "number": "text" + }, + "schemas": [ + { + "$id": "phone_number", + "$ref": "entity", + "properties": { + "number": { + "type": "string" + } + } + } + ] + }, + { + "name": "email_address", + "hierarchy": [ + "email_address", + "entity" + ], + "fields": [ + "id", + "type", + "archived", + "address" + ], + "grouped_fields": { + "entity": [ + "id", + "type", + "archived" + ], + "email_address": [ + "address" + ] + }, + "field_types": { + "id": "uuid", + "type": "text", + "archived": "boolean", + "address": "text" + }, + "schemas": [ + { + "$id": "email_address", + "$ref": "entity", + "properties": { + "address": { + "type": "string" + } + } + } + ] + }, + { + "name": "address", + "hierarchy": [ + "address", + "entity" + ], + "fields": [ + "id", + "type", + "archived", + "city" + ], + "grouped_fields": { + "entity": [ + "id", + "type", + "archived" + ], + "address": [ + "city" + ] + }, + "field_types": { + "id": "uuid", + "type": "text", + "archived": "boolean", + "city": "text" + }, + "schemas": [ + { + "$id": "address", + "$ref": "entity", + "properties": { + "city": { + "type": "string" + } + } + } + ] + } + ] + }, + "tests": [ + { + "description": "Should execute table multi-joins on inheritance for basic schema", + "action": "query", + "schema_id": "base.person", + "expect": { + "success": true, + "sql": [ + "(SELECT jsonb_build_object('archived', t1_obj_t2.archived, 'first_name', t1_obj_t1.first_name, 'id', t1_obj_t2.id, 'last_name', t1_obj_t1.last_name, 'type', t1_obj_t2.type) FROM agreego.person t1_obj_t1 JOIN agreego.entity t1_obj_t2 ON t1_obj_t2.id = t1_obj_t1.id WHERE NOT t1_obj_t1.archived)" + ] + } + }, + { + "description": "Should render a massive query handling full nested tree generation and JSON aggregation for complex relationships", + "action": "query", + "schema_id": "full.person", + "expect": { + "success": true, + "sql": [ + "(SELECT jsonb_build_object('addresses', (SELECT COALESCE(jsonb_agg(jsonb_build_object('archived', t1_obj_t2_addresses_t3.archived, 'id', t1_obj_t2_addresses_t3.id, 'is_primary', t1_obj_t2_addresses_t1.is_primary, 'target', (SELECT jsonb_build_object('archived', t1_obj_t2_addresses_t3_target_t2.archived, 'city', t1_obj_t2_addresses_t3_target_t1.city, 'id', t1_obj_t2_addresses_t3_target_t2.id, 'type', t1_obj_t2_addresses_t3_target_t2.type) FROM agreego.address t1_obj_t2_addresses_t3_target_t1 JOIN agreego.entity t1_obj_t2_addresses_t3_target_t2 ON t1_obj_t2_addresses_t3_target_t2.id = t1_obj_t2_addresses_t3_target_t1.id WHERE NOT t1_obj_t2_addresses_t3_target_t1.archived AND t1_obj_t2_addresses_t3_target_t1.parent_id = t1_obj_t2_addresses_t3.id), 'type', t1_obj_t2_addresses_t3.type)), '[]'::jsonb) FROM agreego.contact t1_obj_t2_addresses_t1 JOIN agreego.relationship t1_obj_t2_addresses_t2 ON t1_obj_t2_addresses_t2.id = t1_obj_t2_addresses_t1.id JOIN agreego.entity t1_obj_t2_addresses_t3 ON t1_obj_t2_addresses_t3.id = t1_obj_t2_addresses_t2.id WHERE NOT t1_obj_t2_addresses_t1.archived AND t1_obj_t2_addresses_t1.parent_id = t1_obj_t2.id), 'archived', t1_obj_t2.archived, 'contacts', (SELECT COALESCE(jsonb_agg(jsonb_build_object('archived', t1_obj_t2_contacts_t3.archived, 'id', t1_obj_t2_contacts_t3.id, 'is_primary', t1_obj_t2_contacts_t1.is_primary, 'target', t1_obj_t2_contacts_t3.target, 'type', t1_obj_t2_contacts_t3.type)), '[]'::jsonb) FROM agreego.contact t1_obj_t2_contacts_t1 JOIN agreego.relationship t1_obj_t2_contacts_t2 ON t1_obj_t2_contacts_t2.id = t1_obj_t2_contacts_t1.id JOIN agreego.entity t1_obj_t2_contacts_t3 ON t1_obj_t2_contacts_t3.id = t1_obj_t2_contacts_t2.id WHERE NOT t1_obj_t2_contacts_t1.archived AND t1_obj_t2_contacts_t1.parent_id = t1_obj_t2.id), 'email_addresses', (SELECT COALESCE(jsonb_agg(jsonb_build_object('archived', t1_obj_t2_email_addresses_t3.archived, 'id', t1_obj_t2_email_addresses_t3.id, 'is_primary', t1_obj_t2_email_addresses_t1.is_primary, 'target', (SELECT jsonb_build_object('address', t1_obj_t2_email_addresses_t3_target_t1.address, 'archived', t1_obj_t2_email_addresses_t3_target_t2.archived, 'id', t1_obj_t2_email_addresses_t3_target_t2.id, 'type', t1_obj_t2_email_addresses_t3_target_t2.type) FROM agreego.email_address t1_obj_t2_email_addresses_t3_target_t1 JOIN agreego.entity t1_obj_t2_email_addresses_t3_target_t2 ON t1_obj_t2_email_addresses_t3_target_t2.id = t1_obj_t2_email_addresses_t3_target_t1.id WHERE NOT t1_obj_t2_email_addresses_t3_target_t1.archived AND t1_obj_t2_email_addresses_t3_target_t1.parent_id = t1_obj_t2_email_addresses_t3.id), 'type', t1_obj_t2_email_addresses_t3.type)), '[]'::jsonb) FROM agreego.contact t1_obj_t2_email_addresses_t1 JOIN agreego.relationship t1_obj_t2_email_addresses_t2 ON t1_obj_t2_email_addresses_t2.id = t1_obj_t2_email_addresses_t1.id JOIN agreego.entity t1_obj_t2_email_addresses_t3 ON t1_obj_t2_email_addresses_t3.id = t1_obj_t2_email_addresses_t2.id WHERE NOT t1_obj_t2_email_addresses_t1.archived AND t1_obj_t2_email_addresses_t1.parent_id = t1_obj_t2.id), 'first_name', t1_obj_t1.first_name, 'id', t1_obj_t2.id, 'last_name', t1_obj_t1.last_name, 'phone_numbers', (SELECT COALESCE(jsonb_agg(jsonb_build_object('archived', t1_obj_t2_phone_numbers_t3.archived, 'id', t1_obj_t2_phone_numbers_t3.id, 'is_primary', t1_obj_t2_phone_numbers_t1.is_primary, 'target', (SELECT jsonb_build_object('archived', t1_obj_t2_phone_numbers_t3_target_t2.archived, 'id', t1_obj_t2_phone_numbers_t3_target_t2.id, 'number', t1_obj_t2_phone_numbers_t3_target_t1.number, 'type', t1_obj_t2_phone_numbers_t3_target_t2.type) FROM agreego.phone_number t1_obj_t2_phone_numbers_t3_target_t1 JOIN agreego.entity t1_obj_t2_phone_numbers_t3_target_t2 ON t1_obj_t2_phone_numbers_t3_target_t2.id = t1_obj_t2_phone_numbers_t3_target_t1.id WHERE NOT t1_obj_t2_phone_numbers_t3_target_t1.archived AND t1_obj_t2_phone_numbers_t3_target_t1.parent_id = t1_obj_t2_phone_numbers_t3.id), 'type', t1_obj_t2_phone_numbers_t3.type)), '[]'::jsonb) FROM agreego.contact t1_obj_t2_phone_numbers_t1 JOIN agreego.relationship t1_obj_t2_phone_numbers_t2 ON t1_obj_t2_phone_numbers_t2.id = t1_obj_t2_phone_numbers_t1.id JOIN agreego.entity t1_obj_t2_phone_numbers_t3 ON t1_obj_t2_phone_numbers_t3.id = t1_obj_t2_phone_numbers_t2.id WHERE NOT t1_obj_t2_phone_numbers_t1.archived AND t1_obj_t2_phone_numbers_t1.parent_id = t1_obj_t2.id), 'type', t1_obj_t2.type) FROM agreego.person t1_obj_t1 JOIN agreego.entity t1_obj_t2 ON t1_obj_t2.id = t1_obj_t1.id WHERE NOT t1_obj_t1.archived)" + ] + } + }, + { + "description": "Should attach structural filters against the root entity object regardless of how deep the select statement builds child join maps", + "action": "query", + "schema_id": "full.person", + "filters": { + "first_name": "Jane%", + "last_name": "%Doe%", + "archived": true + }, + "expect": { + "success": true, + "sql": [ + "(SELECT jsonb_build_object('addresses', (SELECT COALESCE(jsonb_agg(jsonb_build_object('archived', t1_obj_t2_addresses_t3.archived, 'id', t1_obj_t2_addresses_t3.id, 'is_primary', t1_obj_t2_addresses_t1.is_primary, 'target', (SELECT jsonb_build_object('archived', t1_obj_t2_addresses_t3_target_t2.archived, 'city', t1_obj_t2_addresses_t3_target_t1.city, 'id', t1_obj_t2_addresses_t3_target_t2.id, 'type', t1_obj_t2_addresses_t3_target_t2.type) FROM agreego.address t1_obj_t2_addresses_t3_target_t1 JOIN agreego.entity t1_obj_t2_addresses_t3_target_t2 ON t1_obj_t2_addresses_t3_target_t2.id = t1_obj_t2_addresses_t3_target_t1.id WHERE NOT t1_obj_t2_addresses_t3_target_t1.archived AND t1_obj_t2_addresses_t3_target_t1.parent_id = t1_obj_t2_addresses_t3.id), 'type', t1_obj_t2_addresses_t3.type)), '[]'::jsonb) FROM agreego.contact t1_obj_t2_addresses_t1 JOIN agreego.relationship t1_obj_t2_addresses_t2 ON t1_obj_t2_addresses_t2.id = t1_obj_t2_addresses_t1.id JOIN agreego.entity t1_obj_t2_addresses_t3 ON t1_obj_t2_addresses_t3.id = t1_obj_t2_addresses_t2.id WHERE NOT t1_obj_t2_addresses_t1.archived AND t1_obj_t2_addresses_t1.parent_id = t1_obj_t2.id), 'archived', t1_obj_t2.archived, 'contacts', (SELECT COALESCE(jsonb_agg(jsonb_build_object('archived', t1_obj_t2_contacts_t3.archived, 'id', t1_obj_t2_contacts_t3.id, 'is_primary', t1_obj_t2_contacts_t1.is_primary, 'target', t1_obj_t2_contacts_t3.target, 'type', t1_obj_t2_contacts_t3.type)), '[]'::jsonb) FROM agreego.contact t1_obj_t2_contacts_t1 JOIN agreego.relationship t1_obj_t2_contacts_t2 ON t1_obj_t2_contacts_t2.id = t1_obj_t2_contacts_t1.id JOIN agreego.entity t1_obj_t2_contacts_t3 ON t1_obj_t2_contacts_t3.id = t1_obj_t2_contacts_t2.id WHERE NOT t1_obj_t2_contacts_t1.archived AND t1_obj_t2_contacts_t1.parent_id = t1_obj_t2.id), 'email_addresses', (SELECT COALESCE(jsonb_agg(jsonb_build_object('archived', t1_obj_t2_email_addresses_t3.archived, 'id', t1_obj_t2_email_addresses_t3.id, 'is_primary', t1_obj_t2_email_addresses_t1.is_primary, 'target', (SELECT jsonb_build_object('address', t1_obj_t2_email_addresses_t3_target_t1.address, 'archived', t1_obj_t2_email_addresses_t3_target_t2.archived, 'id', t1_obj_t2_email_addresses_t3_target_t2.id, 'type', t1_obj_t2_email_addresses_t3_target_t2.type) FROM agreego.email_address t1_obj_t2_email_addresses_t3_target_t1 JOIN agreego.entity t1_obj_t2_email_addresses_t3_target_t2 ON t1_obj_t2_email_addresses_t3_target_t2.id = t1_obj_t2_email_addresses_t3_target_t1.id WHERE NOT t1_obj_t2_email_addresses_t3_target_t1.archived AND t1_obj_t2_email_addresses_t3_target_t1.parent_id = t1_obj_t2_email_addresses_t3.id), 'type', t1_obj_t2_email_addresses_t3.type)), '[]'::jsonb) FROM agreego.contact t1_obj_t2_email_addresses_t1 JOIN agreego.relationship t1_obj_t2_email_addresses_t2 ON t1_obj_t2_email_addresses_t2.id = t1_obj_t2_email_addresses_t1.id JOIN agreego.entity t1_obj_t2_email_addresses_t3 ON t1_obj_t2_email_addresses_t3.id = t1_obj_t2_email_addresses_t2.id WHERE NOT t1_obj_t2_email_addresses_t1.archived AND t1_obj_t2_email_addresses_t1.parent_id = t1_obj_t2.id), 'first_name', t1_obj_t1.first_name, 'id', t1_obj_t2.id, 'last_name', t1_obj_t1.last_name, 'phone_numbers', (SELECT COALESCE(jsonb_agg(jsonb_build_object('archived', t1_obj_t2_phone_numbers_t3.archived, 'id', t1_obj_t2_phone_numbers_t3.id, 'is_primary', t1_obj_t2_phone_numbers_t1.is_primary, 'target', (SELECT jsonb_build_object('archived', t1_obj_t2_phone_numbers_t3_target_t2.archived, 'id', t1_obj_t2_phone_numbers_t3_target_t2.id, 'number', t1_obj_t2_phone_numbers_t3_target_t1.number, 'type', t1_obj_t2_phone_numbers_t3_target_t2.type) FROM agreego.phone_number t1_obj_t2_phone_numbers_t3_target_t1 JOIN agreego.entity t1_obj_t2_phone_numbers_t3_target_t2 ON t1_obj_t2_phone_numbers_t3_target_t2.id = t1_obj_t2_phone_numbers_t3_target_t1.id WHERE NOT t1_obj_t2_phone_numbers_t3_target_t1.archived AND t1_obj_t2_phone_numbers_t3_target_t1.parent_id = t1_obj_t2_phone_numbers_t3.id), 'type', t1_obj_t2_phone_numbers_t3.type)), '[]'::jsonb) FROM agreego.contact t1_obj_t2_phone_numbers_t1 JOIN agreego.relationship t1_obj_t2_phone_numbers_t2 ON t1_obj_t2_phone_numbers_t2.id = t1_obj_t2_phone_numbers_t1.id JOIN agreego.entity t1_obj_t2_phone_numbers_t3 ON t1_obj_t2_phone_numbers_t3.id = t1_obj_t2_phone_numbers_t2.id WHERE NOT t1_obj_t2_phone_numbers_t1.archived AND t1_obj_t2_phone_numbers_t1.parent_id = t1_obj_t2.id), 'type', t1_obj_t2.type) FROM agreego.person t1_obj_t1 JOIN agreego.entity t1_obj_t2 ON t1_obj_t2.id = t1_obj_t1.id WHERE NOT t1_obj_t1.archived AND t1_obj_t2.archived = ($1#>>'{}')::boolean AND t1_obj_t1.first_name ILIKE $2#>>'{}' AND t1_obj_t1.last_name ILIKE $3#>>'{}')" + ] + } + }, + { + "description": "Should extract the targeted subset payload specifically for a high-level nested list", + "action": "query", + "schema_id": "full.person", + "stem": "phone_numbers/contact", + "expect": { + "success": true, + "sql": [ + "(SELECT jsonb_build_object('archived', t1_obj_t3.archived, 'id', t1_obj_t3.id, 'is_primary', t1_obj_t1.is_primary, 'type', t1_obj_t3.type) FROM agreego.contact t1_obj_t1 JOIN agreego.relationship t1_obj_t2 ON t1_obj_t2.id = t1_obj_t1.id JOIN agreego.entity t1_obj_t3 ON t1_obj_t3.id = t1_obj_t2.id WHERE NOT t1_obj_t1.archived)" + ] + } + }, + { + "description": "Should successfully execute nested path extraction for targeted root subgraphs on beats", + "action": "query", + "schema_id": "full.person", + "stem": "phone_numbers/contact/phone_number", + "expect": { + "success": true, + "sql": [ + "(SELECT jsonb_build_object('archived', t1_obj_t2.archived, 'id', t1_obj_t2.id, 'number', t1_obj_t1.number, 'type', t1_obj_t2.type) FROM agreego.phone_number t1_obj_t1 JOIN agreego.entity t1_obj_t2 ON t1_obj_t2.id = t1_obj_t1.id WHERE NOT t1_obj_t1.archived)" + ] + } + }, + { + "description": "Should successfully resolve unique execution plans across nested properties inside relationships containing oneOf configurations", + "action": "query", + "schema_id": "full.person", + "stem": "contacts/contact/email_address", + "expect": { + "success": true, + "sql": [ + "(SELECT jsonb_build_object('address', t1_obj_t1.address, 'archived', t1_obj_t2.archived, 'id', t1_obj_t2.id, 'type', t1_obj_t2.type) FROM agreego.email_address t1_obj_t1 JOIN agreego.entity t1_obj_t2 ON t1_obj_t2.id = t1_obj_t1.id WHERE NOT t1_obj_t1.archived)" + ] + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/ref.json b/fixtures/ref.json new file mode 100644 index 0000000..1010761 --- /dev/null +++ b/fixtures/ref.json @@ -0,0 +1,929 @@ +[ + { + "description": "nested refs", + "database": { + "schemas": [ + { + "$ref": "c_212", + "$id": "ref_4_0" + }, + { + "$id": "a_212", + "type": "integer" + }, + { + "$id": "b_212", + "$ref": "a_212" + }, + { + "$id": "c_212", + "$ref": "b_212" + } + ] + }, + "tests": [ + { + "description": "nested ref valid", + "data": 5, + "schema_id": "ref_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "nested ref invalid", + "data": "a", + "schema_id": "ref_4_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "ref applies alongside sibling keywords", + "database": { + "schemas": [ + { + "properties": { + "foo": { + "$ref": "reffed_248", + "maxItems": 2 + } + }, + "$id": "ref_5_0" + }, + { + "$id": "reffed_248", + "type": "array" + } + ] + }, + "tests": [ + { + "description": "ref valid, maxItems valid", + "data": { + "foo": [] + }, + "schema_id": "ref_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ref valid, maxItems invalid", + "data": { + "foo": [ + 1, + 2, + 3 + ] + }, + "schema_id": "ref_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "ref invalid", + "data": { + "foo": "string" + }, + "schema_id": "ref_5_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "property named $ref that is not a reference", + "database": { + "schemas": [ + { + "properties": { + "$ref": { + "type": "string" + } + }, + "$id": "ref_6_0" + } + ] + }, + "tests": [ + { + "description": "property named $ref valid", + "data": { + "$ref": "a" + }, + "schema_id": "ref_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "property named $ref invalid", + "data": { + "$ref": 2 + }, + "schema_id": "ref_6_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "property named $ref, containing an actual $ref", + "database": { + "schemas": [ + { + "properties": { + "$ref": { + "$ref": "is-string_344" + } + }, + "$id": "ref_7_0" + }, + { + "$id": "is-string_344", + "type": "string" + } + ] + }, + "tests": [ + { + "description": "property named $ref valid", + "data": { + "$ref": "a" + }, + "schema_id": "ref_7_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "property named $ref invalid", + "data": { + "$ref": 2 + }, + "schema_id": "ref_7_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "$ref to boolean schema true", + "database": { + "schemas": [ + { + "$ref": "bool_378", + "$id": "ref_8_0" + }, + { + "$id": "bool_378", + "extensible": true + } + ] + }, + "tests": [ + { + "description": "any value is valid", + "data": "foo", + "schema_id": "ref_8_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "$ref to boolean schema false", + "database": { + "schemas": [ + { + "$ref": "bool_400", + "$id": "ref_9_0" + }, + { + "$id": "bool_400", + "extensible": false, + "not": {} + } + ] + }, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "schema_id": "ref_9_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "refs with quote", + "database": { + "schemas": [ + { + "properties": { + "foo\"bar": { + "$ref": "foo%22bar_550" + } + }, + "$id": "ref_11_0" + }, + { + "$id": "foo%22bar_550", + "type": "number" + } + ] + }, + "tests": [ + { + "description": "object with numbers is valid", + "data": { + "foo\"bar": 1 + }, + "schema_id": "ref_11_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "object with strings is invalid", + "data": { + "foo\"bar": "1" + }, + "schema_id": "ref_11_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "$ref boundary resets to loose", + "database": { + "schemas": [ + { + "$ref": "target_1465", + "$id": "ref_35_0" + }, + { + "$id": "target_1465", + "properties": { + "foo": { + "type": "string" + } + } + } + ] + }, + "tests": [ + { + "description": "extra property in ref target is invalid (strict by default)", + "data": { + "foo": "bar", + "extra": 1 + }, + "schema_id": "ref_35_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "$ref target can enforce strictness", + "database": { + "schemas": [ + { + "$ref": "target_1496", + "$id": "ref_36_0" + }, + { + "$id": "target_1496", + "extensible": false, + "properties": { + "foo": { + "type": "string" + } + } + } + ] + }, + "tests": [ + { + "description": "extra property in ref target is invalid", + "data": { + "foo": "bar", + "extra": 1 + }, + "schema_id": "ref_36_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "strictness: boundary reset at $ref", + "database": { + "schemas": [ + { + "extensible": true, + "properties": { + "inline_child": { + "properties": { + "a": { + "type": "integer" + } + } + }, + "ref_child": { + "$ref": "strict_node_1544" + }, + "extensible_ref_child": { + "$ref": "extensible_node_1551" + } + }, + "$id": "ref_37_0" + }, + { + "$id": "strict_node_1544", + "properties": { + "b": { + "type": "integer" + } + } + }, + { + "$id": "extensible_node_1551", + "extensible": true, + "properties": { + "c": { + "type": "integer" + } + } + } + ] + }, + "tests": [ + { + "description": "inline child inherits looseness", + "data": { + "inline_child": { + "a": 1, + "extra": 2 + } + }, + "schema_id": "ref_37_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ref child resets to strict (default)", + "data": { + "ref_child": { + "b": 1, + "extra": 2 + } + }, + "schema_id": "ref_37_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "ref child with explicit extensible=true is loose", + "data": { + "extensible_ref_child": { + "c": 1, + "extra": 2 + } + }, + "schema_id": "ref_37_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "arrays: ref items inherit strictness (reset at boundary)", + "database": { + "schemas": [ + { + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "strict_node_1614" + } + } + }, + "$id": "ref_38_0" + }, + { + "$id": "strict_node_1614", + "properties": { + "a": { + "type": "integer" + } + } + } + ] + }, + "tests": [ + { + "description": "ref item with extra property is invalid (strict by default)", + "data": { + "list": [ + { + "a": 1, + "extra": 2 + } + ] + }, + "schema_id": "ref_38_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "implicit keyword shadowing", + "database": { + "schemas": [ + { + "$ref": "parent_1648", + "properties": { + "type": { + "const": "child" + }, + "age": { + "minimum": 15 + } + }, + "$id": "ref_39_0" + }, + { + "$id": "parent_1648", + "type": "object", + "properties": { + "type": { + "const": "parent" + }, + "age": { + "minimum": 10, + "maximum": 20 + } + }, + "required": [ + "type", + "age" + ] + } + ] + }, + "tests": [ + { + "description": "child type overrides parent type", + "data": { + "type": "child", + "age": 15 + }, + "schema_id": "ref_39_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "parent type is now invalid (shadowed)", + "data": { + "type": "parent", + "age": 15 + }, + "schema_id": "ref_39_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "child min age (15) is enforced", + "data": { + "type": "child", + "age": 12 + }, + "schema_id": "ref_39_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "parent max age (20) is shadowed (replaced) by child definition", + "data": { + "type": "child", + "age": 21 + }, + "schema_id": "ref_39_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "Entities extending entities (Physical Birth)", + "database": { + "types": [ + { + "name": "entity", + "variations": [ + "entity", + "organization", + "person" + ], + "schemas": [ + { + "$id": "entity", + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string" + } + } + } + ] + }, + { + "name": "organization", + "variations": [ + "organization", + "person" + ], + "schemas": [ + { + "$id": "organization", + "$ref": "entity", + "properties": { + "name": { + "type": "string" + } + } + } + ] + }, + { + "name": "person", + "variations": [ + "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" + }, + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "Valid organization against organization schema", + "schema_id": "save_org.request", + "data": { + "id": "2", + "type": "organization", + "name": "ACME" + }, + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "Invalid entity against organization schema (ancestor not allowed)", + "schema_id": "save_org.request", + "data": { + "id": "3", + "type": "entity" + }, + "action": "validate", + "expect": { + "success": false, + "errors": [ + { + "code": "TYPE_MISMATCH", + "path": "/type" + } + ] + } + } + ] + }, + { + "description": "Viral Infection: Ad-hocs inheriting entity boundaries via $ref", + "database": { + "types": [ + { + "name": "entity", + "variations": [ + "entity", + "person" + ], + "schemas": [ + { + "$id": "entity", + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string" + } + } + } + ] + }, + { + "name": "person", + "variations": [ + "person" + ], + "schemas": [ + { + "$id": "person", + "$ref": "entity", + "properties": { + "first_name": { + "type": "string" + } + } + }, + { + "$id": "light.person", + "$ref": "entity", + "properties": { + "first_name": { + "type": "string" + } + } + } + ] + } + ], + "puncs": [ + { + "name": "save_person_light", + "schemas": [ + { + "$id": "save_person_light.request", + "$ref": "light.person", + "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" + }, + "action": "validate", + "expect": { + "success": 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" + }, + "action": "validate", + "expect": { + "success": false, + "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" + }, + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "Invalid base address against us_address", + "schema_id": "save_address.request", + "data": { + "street": "123 Main", + "city": "Anytown" + }, + "action": "validate", + "expect": { + "success": 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" + }, + "action": "validate", + "expect": { + "success": 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" + }, + "action": "validate", + "expect": { + "success": false + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/required.json b/fixtures/required.json new file mode 100644 index 0000000..f8f918a --- /dev/null +++ b/fixtures/required.json @@ -0,0 +1,312 @@ +[ + { + "description": "required validation", + "database": { + "schemas": [ + { + "properties": { + "foo": {}, + "bar": {} + }, + "required": [ + "foo" + ], + "$id": "required_0_0" + } + ] + }, + "tests": [ + { + "description": "present required property is valid", + "data": { + "foo": 1 + }, + "schema_id": "required_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "non-present required property is invalid", + "data": { + "bar": 1 + }, + "schema_id": "required_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "ignores arrays", + "data": [], + "schema_id": "required_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores strings", + "data": "", + "schema_id": "required_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores other non-objects", + "data": 12, + "schema_id": "required_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores null", + "data": null, + "schema_id": "required_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores boolean", + "data": true, + "schema_id": "required_0_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "required default validation", + "database": { + "schemas": [ + { + "properties": { + "foo": {} + }, + "$id": "required_1_0" + } + ] + }, + "tests": [ + { + "description": "not required by default", + "data": {}, + "schema_id": "required_1_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "required with empty array", + "database": { + "schemas": [ + { + "properties": { + "foo": {} + }, + "required": [], + "$id": "required_2_0" + } + ] + }, + "tests": [ + { + "description": "property not required", + "data": {}, + "schema_id": "required_2_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "required with escaped characters", + "database": { + "schemas": [ + { + "required": [ + "foo\nbar", + "foo\"bar", + "foo\\bar", + "foo\rbar", + "foo\tbar", + "foo\fbar" + ], + "extensible": true, + "$id": "required_3_0" + } + ] + }, + "tests": [ + { + "description": "object with all properties present is valid", + "data": { + "foo\nbar": 1, + "foo\"bar": 1, + "foo\\bar": 1, + "foo\rbar": 1, + "foo\tbar": 1, + "foo\fbar": 1 + }, + "schema_id": "required_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "object with some properties missing is invalid", + "data": { + "foo\nbar": "1", + "foo\"bar": "1" + }, + "schema_id": "required_3_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "required properties whose names are Javascript object property names", + "comment": "Ensure JS implementations don't universally consider e.g. __proto__ to always be present in an object.", + "database": { + "schemas": [ + { + "required": [ + "__proto__", + "toString", + "constructor" + ], + "extensible": true, + "$id": "required_4_0" + } + ] + }, + "tests": [ + { + "description": "ignores arrays", + "data": [], + "schema_id": "required_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "ignores other non-objects", + "data": 12, + "schema_id": "required_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "none of the properties mentioned", + "data": {}, + "schema_id": "required_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "__proto__ present", + "data": { + "__proto__": "foo" + }, + "schema_id": "required_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "toString present", + "data": { + "toString": { + "length": 37 + } + }, + "schema_id": "required_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "constructor present", + "data": { + "constructor": { + "length": 37 + } + }, + "schema_id": "required_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "all present", + "data": { + "__proto__": 12, + "toString": { + "length": "foo" + }, + "constructor": 37 + }, + "schema_id": "required_4_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "extensible: true allows extra properties in required", + "database": { + "schemas": [ + { + "required": [ + "foo" + ], + "extensible": true, + "$id": "required_5_0" + } + ] + }, + "tests": [ + { + "description": "extra property is valid", + "data": { + "foo": 1, + "bar": 2 + }, + "schema_id": "required_5_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/type.json b/fixtures/type.json new file mode 100644 index 0000000..4a5eab3 --- /dev/null +++ b/fixtures/type.json @@ -0,0 +1,912 @@ +[ + { + "description": "integer type matches integers", + "database": { + "schemas": [ + { + "type": "integer", + "$id": "type_0_0" + } + ] + }, + "tests": [ + { + "description": "an integer is an integer", + "data": 1, + "schema_id": "type_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a float with zero fractional part is an integer", + "data": 1, + "schema_id": "type_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a float is not an integer", + "data": 1.1, + "schema_id": "type_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a string is not an integer", + "data": "foo", + "schema_id": "type_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a string is still not an integer, even if it looks like one", + "data": "1", + "schema_id": "type_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an object is not an integer", + "data": {}, + "schema_id": "type_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an array is not an integer", + "data": [], + "schema_id": "type_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a boolean is not an integer", + "data": true, + "schema_id": "type_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "null is not an integer", + "data": null, + "schema_id": "type_0_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "number type matches numbers", + "database": { + "schemas": [ + { + "type": "number", + "$id": "type_1_0" + } + ] + }, + "tests": [ + { + "description": "an integer is a number", + "data": 1, + "schema_id": "type_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a float with zero fractional part is a number (and an integer)", + "data": 1, + "schema_id": "type_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a float is a number", + "data": 1.1, + "schema_id": "type_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a string is not a number", + "data": "foo", + "schema_id": "type_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a string is still not a number, even if it looks like one", + "data": "1", + "schema_id": "type_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an object is not a number", + "data": {}, + "schema_id": "type_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an array is not a number", + "data": [], + "schema_id": "type_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a boolean is not a number", + "data": true, + "schema_id": "type_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "null is not a number", + "data": null, + "schema_id": "type_1_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "string type matches strings", + "database": { + "schemas": [ + { + "type": "string", + "$id": "type_2_0" + } + ] + }, + "tests": [ + { + "description": "1 is not a string", + "data": 1, + "schema_id": "type_2_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a float is not a string", + "data": 1.1, + "schema_id": "type_2_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a string is a string", + "data": "foo", + "schema_id": "type_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a string is still a string, even if it looks like a number", + "data": "1", + "schema_id": "type_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an empty string is still a string", + "data": "", + "schema_id": "type_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an object is not a string", + "data": {}, + "schema_id": "type_2_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an array is not a string", + "data": [], + "schema_id": "type_2_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a boolean is not a string", + "data": true, + "schema_id": "type_2_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "null is not a string", + "data": null, + "schema_id": "type_2_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "object type matches objects", + "database": { + "schemas": [ + { + "type": "object", + "$id": "type_3_0" + } + ] + }, + "tests": [ + { + "description": "an integer is not an object", + "data": 1, + "schema_id": "type_3_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a float is not an object", + "data": 1.1, + "schema_id": "type_3_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a string is not an object", + "data": "foo", + "schema_id": "type_3_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an object is an object", + "data": {}, + "schema_id": "type_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an array is not an object", + "data": [], + "schema_id": "type_3_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a boolean is not an object", + "data": true, + "schema_id": "type_3_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "null is not an object", + "data": null, + "schema_id": "type_3_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "array type matches arrays", + "database": { + "schemas": [ + { + "type": "array", + "$id": "type_4_0" + } + ] + }, + "tests": [ + { + "description": "an integer is not an array", + "data": 1, + "schema_id": "type_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a float is not an array", + "data": 1.1, + "schema_id": "type_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a string is not an array", + "data": "foo", + "schema_id": "type_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an object is not an array", + "data": {}, + "schema_id": "type_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an array is an array", + "data": [], + "schema_id": "type_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a boolean is not an array", + "data": true, + "schema_id": "type_4_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "null is not an array", + "data": null, + "schema_id": "type_4_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "boolean type matches booleans", + "database": { + "schemas": [ + { + "type": "boolean", + "$id": "type_5_0" + } + ] + }, + "tests": [ + { + "description": "an integer is not a boolean", + "data": 1, + "schema_id": "type_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "zero is not a boolean", + "data": 0, + "schema_id": "type_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a float is not a boolean", + "data": 1.1, + "schema_id": "type_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a string is not a boolean", + "data": "foo", + "schema_id": "type_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an empty string is a null", + "data": "", + "schema_id": "type_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an object is not a boolean", + "data": {}, + "schema_id": "type_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an array is not a boolean", + "data": [], + "schema_id": "type_5_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "true is a boolean", + "data": true, + "schema_id": "type_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "false is a boolean", + "data": false, + "schema_id": "type_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "null is not a boolean", + "data": null, + "schema_id": "type_5_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "null type matches only the null object", + "database": { + "schemas": [ + { + "type": "null", + "$id": "type_6_0" + } + ] + }, + "tests": [ + { + "description": "an integer is not null", + "data": 1, + "schema_id": "type_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a float is not null", + "data": 1.1, + "schema_id": "type_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "zero is not null", + "data": 0, + "schema_id": "type_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a string is not null", + "data": "foo", + "schema_id": "type_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an empty string is null", + "data": "", + "schema_id": "type_6_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "an object is not null", + "data": {}, + "schema_id": "type_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an array is not null", + "data": [], + "schema_id": "type_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "true is not null", + "data": true, + "schema_id": "type_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "false is not null", + "data": false, + "schema_id": "type_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "null is null", + "data": null, + "schema_id": "type_6_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "multiple types can be specified in an array", + "database": { + "schemas": [ + { + "type": [ + "integer", + "string" + ], + "$id": "type_7_0" + } + ] + }, + "tests": [ + { + "description": "an integer is valid", + "data": 1, + "schema_id": "type_7_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a string is valid", + "data": "foo", + "schema_id": "type_7_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "a float is invalid", + "data": 1.1, + "schema_id": "type_7_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an object is invalid", + "data": {}, + "schema_id": "type_7_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "an array is invalid", + "data": [], + "schema_id": "type_7_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "a boolean is invalid", + "data": true, + "schema_id": "type_7_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "null is invalid", + "data": null, + "schema_id": "type_7_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "type as array with one item", + "database": { + "schemas": [ + { + "type": [ + "string" + ], + "$id": "type_8_0" + } + ] + }, + "tests": [ + { + "description": "string is valid", + "data": "foo", + "schema_id": "type_8_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "number is invalid", + "data": 123, + "schema_id": "type_8_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "type: array or object", + "database": { + "schemas": [ + { + "type": [ + "array", + "object" + ], + "items": {}, + "$id": "type_9_0" + } + ] + }, + "tests": [ + { + "description": "array is valid", + "data": [ + 1, + 2, + 3 + ], + "schema_id": "type_9_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "object is valid", + "data": {}, + "schema_id": "type_9_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "number is invalid", + "data": 123, + "schema_id": "type_9_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "string is invalid", + "data": "foo", + "schema_id": "type_9_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "null is invalid", + "data": null, + "schema_id": "type_9_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "type: array, object or null", + "database": { + "schemas": [ + { + "type": [ + "array", + "object", + "null" + ], + "items": {}, + "$id": "type_10_0" + } + ] + }, + "tests": [ + { + "description": "array is valid", + "data": [ + 1, + 2, + 3 + ], + "schema_id": "type_10_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "object is valid", + "data": {}, + "schema_id": "type_10_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "null is valid", + "data": null, + "schema_id": "type_10_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "number is invalid", + "data": 123, + "schema_id": "type_10_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "string is invalid", + "data": "foo", + "schema_id": "type_10_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "extensible: true allows extra properties", + "database": { + "schemas": [ + { + "type": "object", + "extensible": true, + "$id": "type_11_0" + } + ] + }, + "tests": [ + { + "description": "extra property is valid", + "data": { + "foo": 1 + }, + "schema_id": "type_11_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + } +] \ No newline at end of file diff --git a/fixtures/uniqueItems.json b/fixtures/uniqueItems.json new file mode 100644 index 0000000..8b5af36 --- /dev/null +++ b/fixtures/uniqueItems.json @@ -0,0 +1,1171 @@ +[ + { + "description": "uniqueItems validation", + "database": { + "schemas": [ + { + "uniqueItems": true, + "extensible": true, + "$id": "uniqueItems_0_0" + } + ] + }, + "tests": [ + { + "description": "unique array of integers is valid", + "data": [ + 1, + 2 + ], + "schema_id": "uniqueItems_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "non-unique array of integers is invalid", + "data": [ + 1, + 1 + ], + "schema_id": "uniqueItems_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "non-unique array of more than two integers is invalid", + "data": [ + 1, + 2, + 1 + ], + "schema_id": "uniqueItems_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "numbers are unique if mathematically unequal", + "data": [ + 1, + 1, + 1 + ], + "schema_id": "uniqueItems_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "false is not equal to zero", + "data": [ + 0, + false + ], + "schema_id": "uniqueItems_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "true is not equal to one", + "data": [ + 1, + true + ], + "schema_id": "uniqueItems_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "unique array of strings is valid", + "data": [ + "foo", + "bar", + "baz" + ], + "schema_id": "uniqueItems_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "non-unique array of strings is invalid", + "data": [ + "foo", + "bar", + "foo" + ], + "schema_id": "uniqueItems_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "unique array of objects is valid", + "data": [ + { + "foo": "bar" + }, + { + "foo": "baz" + } + ], + "schema_id": "uniqueItems_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "non-unique array of objects is invalid", + "data": [ + { + "foo": "bar" + }, + { + "foo": "bar" + } + ], + "schema_id": "uniqueItems_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "property order of array of objects is ignored", + "data": [ + { + "foo": "bar", + "bar": "foo" + }, + { + "bar": "foo", + "foo": "bar" + } + ], + "schema_id": "uniqueItems_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "unique array of nested objects is valid", + "data": [ + { + "foo": { + "bar": { + "baz": true + } + } + }, + { + "foo": { + "bar": { + "baz": false + } + } + } + ], + "schema_id": "uniqueItems_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "non-unique array of nested objects is invalid", + "data": [ + { + "foo": { + "bar": { + "baz": true + } + } + }, + { + "foo": { + "bar": { + "baz": true + } + } + } + ], + "schema_id": "uniqueItems_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "unique array of arrays is valid", + "data": [ + [ + "foo" + ], + [ + "bar" + ] + ], + "schema_id": "uniqueItems_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "non-unique array of arrays is invalid", + "data": [ + [ + "foo" + ], + [ + "foo" + ] + ], + "schema_id": "uniqueItems_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "non-unique array of more than two arrays is invalid", + "data": [ + [ + "foo" + ], + [ + "bar" + ], + [ + "foo" + ] + ], + "schema_id": "uniqueItems_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "1 and true are unique", + "data": [ + 1, + true + ], + "schema_id": "uniqueItems_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "0 and false are unique", + "data": [ + 0, + false + ], + "schema_id": "uniqueItems_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "[1] and [true] are unique", + "data": [ + [ + 1 + ], + [ + true + ] + ], + "schema_id": "uniqueItems_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "[0] and [false] are unique", + "data": [ + [ + 0 + ], + [ + false + ] + ], + "schema_id": "uniqueItems_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "nested [1] and [true] are unique", + "data": [ + [ + [ + 1 + ], + "foo" + ], + [ + [ + true + ], + "foo" + ] + ], + "schema_id": "uniqueItems_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "nested [0] and [false] are unique", + "data": [ + [ + [ + 0 + ], + "foo" + ], + [ + [ + false + ], + "foo" + ] + ], + "schema_id": "uniqueItems_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "unique heterogeneous types are valid", + "data": [ + {}, + [ + 1 + ], + true, + null, + 1, + "{}" + ], + "schema_id": "uniqueItems_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "non-unique heterogeneous types are invalid", + "data": [ + {}, + [ + 1 + ], + true, + null, + {}, + 1 + ], + "schema_id": "uniqueItems_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "different objects are unique", + "data": [ + { + "a": 1, + "b": 2 + }, + { + "a": 2, + "b": 1 + } + ], + "schema_id": "uniqueItems_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "objects are non-unique despite key order", + "data": [ + { + "a": 1, + "b": 2 + }, + { + "b": 2, + "a": 1 + } + ], + "schema_id": "uniqueItems_0_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "{\"a\": false} and {\"a\": 0} are unique", + "data": [ + { + "a": false + }, + { + "a": 0 + } + ], + "schema_id": "uniqueItems_0_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "{\"a\": true} and {\"a\": 1} are unique", + "data": [ + { + "a": true + }, + { + "a": 1 + } + ], + "schema_id": "uniqueItems_0_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "uniqueItems with an array of items", + "database": { + "schemas": [ + { + "prefixItems": [ + { + "type": "boolean" + }, + { + "type": "boolean" + } + ], + "uniqueItems": true, + "extensible": true, + "$id": "uniqueItems_1_0" + } + ] + }, + "tests": [ + { + "description": "[false, true] from items array is valid", + "data": [ + false, + true + ], + "schema_id": "uniqueItems_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "[true, false] from items array is valid", + "data": [ + true, + false + ], + "schema_id": "uniqueItems_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "[false, false] from items array is not valid", + "data": [ + false, + false + ], + "schema_id": "uniqueItems_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "[true, true] from items array is not valid", + "data": [ + true, + true + ], + "schema_id": "uniqueItems_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "unique array extended from [false, true] is valid", + "data": [ + false, + true, + "foo", + "bar" + ], + "schema_id": "uniqueItems_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "unique array extended from [true, false] is valid", + "data": [ + true, + false, + "foo", + "bar" + ], + "schema_id": "uniqueItems_1_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "non-unique array extended from [false, true] is not valid", + "data": [ + false, + true, + "foo", + "foo" + ], + "schema_id": "uniqueItems_1_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "non-unique array extended from [true, false] is not valid", + "data": [ + true, + false, + "foo", + "foo" + ], + "schema_id": "uniqueItems_1_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "uniqueItems with an array of items and additionalItems=false", + "database": { + "schemas": [ + { + "prefixItems": [ + { + "type": "boolean" + }, + { + "type": "boolean" + } + ], + "uniqueItems": true, + "items": false, + "$id": "uniqueItems_2_0" + } + ] + }, + "tests": [ + { + "description": "[false, true] from items array is valid", + "data": [ + false, + true + ], + "schema_id": "uniqueItems_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "[true, false] from items array is valid", + "data": [ + true, + false + ], + "schema_id": "uniqueItems_2_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "[false, false] from items array is not valid", + "data": [ + false, + false + ], + "schema_id": "uniqueItems_2_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "[true, true] from items array is not valid", + "data": [ + true, + true + ], + "schema_id": "uniqueItems_2_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "extra items are invalid even if unique", + "data": [ + false, + true, + null + ], + "schema_id": "uniqueItems_2_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "uniqueItems=false validation", + "database": { + "schemas": [ + { + "uniqueItems": false, + "extensible": true, + "$id": "uniqueItems_3_0" + } + ] + }, + "tests": [ + { + "description": "unique array of integers is valid", + "data": [ + 1, + 2 + ], + "schema_id": "uniqueItems_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "non-unique array of integers is valid", + "data": [ + 1, + 1 + ], + "schema_id": "uniqueItems_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "numbers are unique if mathematically unequal", + "data": [ + 1, + 1, + 1 + ], + "schema_id": "uniqueItems_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "false is not equal to zero", + "data": [ + 0, + false + ], + "schema_id": "uniqueItems_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "true is not equal to one", + "data": [ + 1, + true + ], + "schema_id": "uniqueItems_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "unique array of objects is valid", + "data": [ + { + "foo": "bar" + }, + { + "foo": "baz" + } + ], + "schema_id": "uniqueItems_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "non-unique array of objects is valid", + "data": [ + { + "foo": "bar" + }, + { + "foo": "bar" + } + ], + "schema_id": "uniqueItems_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "unique array of nested objects is valid", + "data": [ + { + "foo": { + "bar": { + "baz": true + } + } + }, + { + "foo": { + "bar": { + "baz": false + } + } + } + ], + "schema_id": "uniqueItems_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "non-unique array of nested objects is valid", + "data": [ + { + "foo": { + "bar": { + "baz": true + } + } + }, + { + "foo": { + "bar": { + "baz": true + } + } + } + ], + "schema_id": "uniqueItems_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "unique array of arrays is valid", + "data": [ + [ + "foo" + ], + [ + "bar" + ] + ], + "schema_id": "uniqueItems_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "non-unique array of arrays is valid", + "data": [ + [ + "foo" + ], + [ + "foo" + ] + ], + "schema_id": "uniqueItems_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "1 and true are unique", + "data": [ + 1, + true + ], + "schema_id": "uniqueItems_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "0 and false are unique", + "data": [ + 0, + false + ], + "schema_id": "uniqueItems_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "unique heterogeneous types are valid", + "data": [ + {}, + [ + 1 + ], + true, + null, + 1 + ], + "schema_id": "uniqueItems_3_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "non-unique heterogeneous types are valid", + "data": [ + {}, + [ + 1 + ], + true, + null, + {}, + 1 + ], + "schema_id": "uniqueItems_3_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "uniqueItems=false with an array of items", + "database": { + "schemas": [ + { + "prefixItems": [ + { + "type": "boolean" + }, + { + "type": "boolean" + } + ], + "uniqueItems": false, + "extensible": true, + "$id": "uniqueItems_4_0" + } + ] + }, + "tests": [ + { + "description": "[false, true] from items array is valid", + "data": [ + false, + true + ], + "schema_id": "uniqueItems_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "[true, false] from items array is valid", + "data": [ + true, + false + ], + "schema_id": "uniqueItems_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "[false, false] from items array is valid", + "data": [ + false, + false + ], + "schema_id": "uniqueItems_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "[true, true] from items array is valid", + "data": [ + true, + true + ], + "schema_id": "uniqueItems_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "unique array extended from [false, true] is valid", + "data": [ + false, + true, + "foo", + "bar" + ], + "schema_id": "uniqueItems_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "unique array extended from [true, false] is valid", + "data": [ + true, + false, + "foo", + "bar" + ], + "schema_id": "uniqueItems_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "non-unique array extended from [false, true] is valid", + "data": [ + false, + true, + "foo", + "foo" + ], + "schema_id": "uniqueItems_4_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "non-unique array extended from [true, false] is valid", + "data": [ + true, + false, + "foo", + "foo" + ], + "schema_id": "uniqueItems_4_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + }, + { + "description": "uniqueItems=false with an array of items and additionalItems=false", + "database": { + "schemas": [ + { + "prefixItems": [ + { + "type": "boolean" + }, + { + "type": "boolean" + } + ], + "uniqueItems": false, + "items": false, + "$id": "uniqueItems_5_0" + } + ] + }, + "tests": [ + { + "description": "[false, true] from items array is valid", + "data": [ + false, + true + ], + "schema_id": "uniqueItems_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "[true, false] from items array is valid", + "data": [ + true, + false + ], + "schema_id": "uniqueItems_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "[false, false] from items array is valid", + "data": [ + false, + false + ], + "schema_id": "uniqueItems_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "[true, true] from items array is valid", + "data": [ + true, + true + ], + "schema_id": "uniqueItems_5_0", + "action": "validate", + "expect": { + "success": true + } + }, + { + "description": "extra items are invalid even if unique", + "data": [ + false, + true, + null + ], + "schema_id": "uniqueItems_5_0", + "action": "validate", + "expect": { + "success": false + } + } + ] + }, + { + "description": "extensible: true allows extra items in uniqueItems", + "database": { + "schemas": [ + { + "uniqueItems": true, + "extensible": true, + "$id": "uniqueItems_6_0" + } + ] + }, + "tests": [ + { + "description": "extra items must be unique", + "data": [ + 1, + 1 + ], + "schema_id": "uniqueItems_6_0", + "action": "validate", + "expect": { + "success": false + } + }, + { + "description": "extra unique items valid", + "data": [ + 1, + 2 + ], + "schema_id": "uniqueItems_6_0", + "action": "validate", + "expect": { + "success": true + } + } + ] + } +] \ No newline at end of file diff --git a/migrate_fixtures.js b/migrate_fixtures.js deleted file mode 100644 index dac1d77..0000000 --- a/migrate_fixtures.js +++ /dev/null @@ -1,58 +0,0 @@ -const fs = require('fs'); -const path = require('path'); - -const fixturesDir = path.join(__dirname, 'tests', 'fixtures'); - -function processFile(filePath) { - const content = fs.readFileSync(filePath, 'utf8'); - let data; - try { - data = JSON.parse(content); - } catch (e) { - console.error(`Skipping ${filePath} due to parse error`); - return; - } - - let modified = false; - - data.forEach(suite => { - if (suite.tests) { - suite.tests.forEach(test => { - if (test.valid !== undefined || test.expect_errors !== undefined) { - if (!test.expect) { - test.expect = {}; - } - if (test.valid !== undefined) { - test.expect.success = test.valid; - delete test.valid; - } - if (test.expect_errors !== undefined) { - test.expect.errors = test.expect_errors; - delete test.expect_errors; - } - modified = true; - } - }); - } - }); - - if (modified) { - fs.writeFileSync(filePath, JSON.stringify(data, null, 4)); - console.log(`Migrated ${filePath}`); - } -} - -function walkDir(dir) { - const files = fs.readdirSync(dir); - files.forEach(file => { - const fullPath = path.join(dir, file); - if (fs.statSync(fullPath).isDirectory()) { - walkDir(fullPath); - } else if (fullPath.endsWith('.json')) { - processFile(fullPath); - } - }); -} - -walkDir(fixturesDir); -console.log('Done migrating fixtures!'); diff --git a/tests/database/executor.rs b/src/database/executors/mock.rs similarity index 54% rename from tests/database/executor.rs rename to src/database/executors/mock.rs index d1fda4f..cec1de9 100644 --- a/tests/database/executor.rs +++ b/src/database/executors/mock.rs @@ -1,23 +1,32 @@ -use jspg::database::executor::DatabaseExecutor; +use crate::database::executors::DatabaseExecutor; use serde_json::Value; + +#[cfg(test)] use std::sync::Mutex; +#[cfg(test)] pub struct MockExecutor { pub query_responses: Mutex>>, pub execute_responses: Mutex>>, + pub captured_queries: Mutex>, } +#[cfg(test)] impl MockExecutor { pub fn new() -> Self { Self { query_responses: Mutex::new(Vec::new()), execute_responses: Mutex::new(Vec::new()), + captured_queries: Mutex::new(Vec::new()), } } } +#[cfg(test)] impl DatabaseExecutor for MockExecutor { - fn query(&self, _sql: &str, _args: Option<&[Value]>) -> Result { + fn query(&self, sql: &str, _args: Option<&[Value]>) -> Result { + println!("DEBUG SQL QUERY: {}", sql); + self.captured_queries.lock().unwrap().push(sql.to_string()); let mut responses = self.query_responses.lock().unwrap(); if responses.is_empty() { return Ok(Value::Array(vec![])); @@ -25,7 +34,9 @@ impl DatabaseExecutor for MockExecutor { responses.remove(0) } - fn execute(&self, _sql: &str, _args: Option<&[Value]>) -> Result<(), String> { + fn execute(&self, sql: &str, _args: Option<&[Value]>) -> Result<(), String> { + println!("DEBUG SQL EXECUTE: {}", sql); + self.captured_queries.lock().unwrap().push(sql.to_string()); let mut responses = self.execute_responses.lock().unwrap(); if responses.is_empty() { return Ok(()); @@ -40,4 +51,14 @@ impl DatabaseExecutor for MockExecutor { fn timestamp(&self) -> Result { Ok("2026-03-10T00:00:00Z".to_string()) } + + #[cfg(test)] + fn get_queries(&self) -> Vec { + self.captured_queries.lock().unwrap().clone() + } + + #[cfg(test)] + fn reset_mocks(&self) { + self.captured_queries.lock().unwrap().clear(); + } } diff --git a/src/database/executors/mod.rs b/src/database/executors/mod.rs new file mode 100644 index 0000000..80e294b --- /dev/null +++ b/src/database/executors/mod.rs @@ -0,0 +1,28 @@ +pub mod mock; + +#[cfg(not(test))] +pub mod pgrx; + +use serde_json::Value; + +/// An abstraction over database execution to allow for isolated unit testing +/// without a live Postgres SPI connection. +pub trait DatabaseExecutor: Send + Sync { + /// Executes a query expecting a single JSONB return, representing rows. + fn query(&self, sql: &str, args: Option<&[Value]>) -> Result; + + /// Executes an operation (INSERT, UPDATE, DELETE, or pg_notify) that does not return rows. + fn execute(&self, sql: &str, args: Option<&[Value]>) -> Result<(), String>; + + /// Returns the current authenticated user's ID + fn auth_user_id(&self) -> Result; + + /// Returns the current transaction timestamp + fn timestamp(&self) -> Result; + + #[cfg(test)] + fn get_queries(&self) -> Vec; + + #[cfg(test)] + fn reset_mocks(&self); +} diff --git a/src/database/executor.rs b/src/database/executors/pgrx.rs similarity index 80% rename from src/database/executor.rs rename to src/database/executors/pgrx.rs index cb458b7..4bbcc7f 100644 --- a/src/database/executor.rs +++ b/src/database/executors/pgrx.rs @@ -1,22 +1,7 @@ +use crate::database::executors::DatabaseExecutor; use pgrx::prelude::*; use serde_json::Value; -/// An abstraction over database execution to allow for isolated unit testing -/// without a live Postgres SPI connection. -pub trait DatabaseExecutor: Send + Sync { - /// Executes a query expecting a single JSONB return, representing rows. - fn query(&self, sql: &str, args: Option<&[Value]>) -> Result; - - /// Executes an operation (INSERT, UPDATE, DELETE, or pg_notify) that does not return rows. - fn execute(&self, sql: &str, args: Option<&[Value]>) -> Result<(), String>; - - /// Returns the current authenticated user's ID - fn auth_user_id(&self) -> Result; - - /// Returns the current transaction timestamp - fn timestamp(&self) -> Result; -} - /// The production executor that wraps `pgrx::spi::Spi`. pub struct SpiExecutor; diff --git a/src/database/mod.rs b/src/database/mod.rs index 95c8754..5331c02 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -1,5 +1,5 @@ pub mod r#enum; -pub mod executor; +pub mod executors; pub mod formats; pub mod page; pub mod punc; @@ -7,14 +7,26 @@ pub mod relation; pub mod schema; pub mod r#type; -use crate::database::r#enum::Enum; -use crate::database::executor::{DatabaseExecutor, SpiExecutor}; -use crate::database::punc::{Punc, Stem}; -use crate::database::relation::Relation; -use crate::database::schema::Schema; -use crate::database::r#type::Type; +// External mock exports inside the executor sub-folder + +use r#enum::Enum; +use executors::DatabaseExecutor; + +#[cfg(not(test))] +use executors::pgrx::SpiExecutor; + +#[cfg(test)] +use executors::mock::MockExecutor; + +pub mod stem; +use punc::Punc; +use relation::Relation; +use schema::Schema; use serde_json::Value; use std::collections::{HashMap, HashSet}; +use std::sync::Arc; +use stem::Stem; +use r#type::Type; pub struct Database { pub enums: HashMap, @@ -22,22 +34,28 @@ pub struct Database { pub puncs: HashMap, pub relations: HashMap, pub schemas: HashMap, + // Map of Schema ID -> { Entity Type -> Target Subschema Arc } + pub stems: HashMap>>, pub descendants: HashMap>, pub depths: HashMap, pub executor: Box, } impl Database { - pub fn new(val: &serde_json::Value) -> Self { + pub fn new(val: &serde_json::Value) -> Result { let mut db = Self { enums: HashMap::new(), types: HashMap::new(), relations: HashMap::new(), puncs: HashMap::new(), schemas: HashMap::new(), + stems: HashMap::new(), descendants: HashMap::new(), depths: HashMap::new(), + #[cfg(not(test))] executor: Box::new(SpiExecutor::new()), + #[cfg(test)] + executor: Box::new(MockExecutor::new()), }; if let Some(arr) = val.get("enums").and_then(|v| v.as_array()) { @@ -86,8 +104,8 @@ impl Database { } } - let _ = db.compile(); - db + db.compile()?; + Ok(db) } /// Override the default executor for unit testing @@ -117,12 +135,12 @@ impl Database { } /// Organizes the graph of the database, compiling regex, format functions, and caching relationships. - fn compile(&mut self) -> Result<(), String> { + pub fn compile(&mut self) -> Result<(), crate::drop::Drop> { self.collect_schemas(); self.collect_depths(); self.collect_descendants(); self.compile_schemas(); - self.collect_stems(); + self.collect_stems()?; Ok(()) } @@ -229,88 +247,78 @@ impl Database { } } - fn collect_stems(&mut self) { - let mut st_map: HashMap> = HashMap::new(); - for (name, _) in &self.puncs { - let mut stems = Vec::new(); - let response_id = format!("{}.response", name); - if let Some(resp_schema) = self.schemas.get(&response_id) { + fn collect_stems(&mut self) -> Result<(), crate::drop::Drop> { + let mut db_stems: HashMap>> = HashMap::new(); + let mut errors: Vec = Vec::new(); + + let schema_ids: Vec = self.schemas.keys().cloned().collect(); + for schema_id in schema_ids { + if let Some(schema) = self.schemas.get(&schema_id) { + let mut inner_map = HashMap::new(); Self::discover_stems( - &self.types, - &self.schemas, - &self.relations, - &response_id, - resp_schema, + self, + &schema_id, + schema, String::from(""), None, None, - &mut stems, + &mut inner_map, + &mut errors, ); - } - st_map.insert(name.clone(), stems); - } - for (name, stems) in st_map { - if let Some(p) = self.puncs.get_mut(&name) { - p.stems = stems; + if !inner_map.is_empty() { + println!("SCHEMA: {} STEMS: {:?}", schema_id, inner_map.keys()); + db_stems.insert(schema_id, inner_map); + } } } + + self.stems = db_stems; + + if !errors.is_empty() { + return Err(crate::drop::Drop::with_errors(errors)); + } + Ok(()) } fn discover_stems( - types: &HashMap, - schemas: &HashMap, - relations: &HashMap, - _schema_id: &str, + db: &Database, + root_schema_id: &str, schema: &Schema, - current_path: String, + mut current_path: String, parent_type: Option, property_name: Option, - stems: &mut Vec, + inner_map: &mut HashMap>, + errors: &mut Vec, ) { let mut is_entity = false; let mut entity_type = String::new(); - // Check if this schema resolves to an Entity - let mut current_ref = schema.obj.r#ref.clone(); - let mut depth = 0; - while let Some(r) = current_ref { - if types.contains_key(&r) { - is_entity = true; - entity_type = r.clone(); - break; - } - if let Some(s) = schemas.get(&r) { - current_ref = s.obj.r#ref.clone(); - } else { - break; - } - depth += 1; - if depth > 20 { - break; - } // prevent infinite loop + let mut examine_id = None; + if let Some(ref r) = schema.obj.r#ref { + examine_id = Some(r.clone()); + } else if let Some(ref id) = schema.obj.id { + examine_id = Some(id.clone()); } - if is_entity { - let final_path = if current_path.is_empty() { - "/".to_string() - } else { - current_path.clone() - }; + if let Some(target) = examine_id { + let parts: Vec<&str> = target.split('.').collect(); + if let Some(last_seg) = parts.last() { + if db.types.contains_key(*last_seg) { + is_entity = true; + entity_type = last_seg.to_string(); + } + } + } - let mut relation_col = None; + let mut relation_col = None; + if is_entity { if let (Some(pt), Some(prop)) = (&parent_type, &property_name) { let expected_col = format!("{}_id", prop); let mut found = false; - - // Try to find the exact relation from the database schema - for rel in relations.values() { - if rel.source_type == *pt && rel.destination_type == entity_type { - if rel.source_columns.contains(&expected_col) { - relation_col = Some(expected_col.clone()); - found = true; - break; - } - } else if rel.source_type == entity_type && rel.destination_type == *pt { + for rel in db.relations.values() { + if (rel.source_type == *pt && rel.destination_type == entity_type) + || (rel.source_type == entity_type && rel.destination_type == *pt) + { if rel.source_columns.contains(&expected_col) { relation_col = Some(expected_col.clone()); found = true; @@ -318,64 +326,128 @@ impl Database { } } } - if !found { - // Fallback guess if explicit matching fails relation_col = Some(expected_col); } } - stems.push(Stem { - path: final_path, + let stem = Stem { r#type: entity_type.clone(), relation: relation_col, - }); + schema: Arc::new(schema.clone()), + }; + + let mut branch_path = current_path.clone(); + if !current_path.is_empty() { + branch_path = format!("{}/{}", current_path, entity_type); + } + + if inner_map.contains_key(&branch_path) { + errors.push(crate::drop::Error { + code: "STEM_COLLISION".to_string(), + message: format!("The stem path `{}` resolves to multiple Entity boundaries. This usually occurs during un-wrapped $family or oneOf polymorphic schemas where multiple Entities are directly assigned to the same property. To fix this, encapsulate the polymorphic branch.", branch_path), + details: crate::drop::ErrorDetails { + path: root_schema_id.to_string(), + }, + }); + } + + inner_map.insert(branch_path.clone(), Arc::new(stem)); + + // Update current_path for structural children + current_path = branch_path; } - // Pass the new parent downwards let next_parent = if is_entity { Some(entity_type.clone()) } else { parent_type.clone() }; + // Properties branch if let Some(props) = &schema.obj.properties { for (k, v) in props { - let next_path = format!( - "{}/{}", - if current_path.is_empty() { - "" - } else { - ¤t_path - }, - k - ); + // Bypass target and source properties if we are in a relationship + if let Some(parent_str) = &next_parent { + if let Some(pt) = db.types.get(parent_str) { + if pt.relationship && (k == "target" || k == "source") { + Self::discover_stems( + db, + root_schema_id, + v, + current_path.clone(), + next_parent.clone(), + Some(k.clone()), + inner_map, + errors, + ); + continue; + } + } + } + + // Standard Property Pathing + let next_path = if current_path.is_empty() { + k.clone() + } else { + format!("{}/{}", current_path, k) + }; + Self::discover_stems( - types, - schemas, - relations, - "", + db, + root_schema_id, v, next_path, next_parent.clone(), Some(k.clone()), - stems, + inner_map, + errors, ); } } + // Array Item branch if let Some(items) = &schema.obj.items { Self::discover_stems( - types, - schemas, - relations, - "", + db, + root_schema_id, items, current_path.clone(), next_parent.clone(), property_name.clone(), - stems, + inner_map, + errors, ); } + + // Polymorphism branch + if let Some(arr) = &schema.obj.one_of { + for v in arr { + Self::discover_stems( + db, + root_schema_id, + v.as_ref(), + current_path.clone(), + next_parent.clone(), + property_name.clone(), + inner_map, + errors, + ); + } + } + if let Some(arr) = &schema.obj.all_of { + for v in arr { + Self::discover_stems( + db, + root_schema_id, + v.as_ref(), + current_path.clone(), + next_parent.clone(), + property_name.clone(), + inner_map, + errors, + ); + } + } } } diff --git a/src/database/punc.rs b/src/database/punc.rs index 3d0eda0..6cea891 100644 --- a/src/database/punc.rs +++ b/src/database/punc.rs @@ -2,14 +2,6 @@ use crate::database::page::Page; use crate::database::schema::Schema; use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Stem { - pub path: String, - pub r#type: String, - #[serde(skip_serializing_if = "Option::is_none")] - pub relation: Option, -} - #[derive(Debug, Clone, Serialize, Deserialize, Default)] #[serde(default)] pub struct Punc { @@ -25,6 +17,4 @@ pub struct Punc { pub page: Option, #[serde(default)] pub schemas: Vec, - #[serde(default)] - pub stems: Vec, } diff --git a/src/database/schema.rs b/src/database/schema.rs index 2878f91..f7ac5e4 100644 --- a/src/database/schema.rs +++ b/src/database/schema.rs @@ -5,6 +5,14 @@ use std::sync::Arc; // Schema mirrors the Go Punc Generator's schema struct for consistency. // It is an order-preserving representation of a JSON Schema. + +pub fn deserialize_some<'de, D>(deserializer: D) -> Result, D::Error> +where + D: serde::Deserializer<'de>, +{ + let v = Value::deserialize(deserializer)?; + Ok(Some(v)) +} #[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct SchemaObject { // Core Schema Keywords @@ -79,7 +87,7 @@ pub struct SchemaObject { #[serde( default, rename = "const", - deserialize_with = "crate::validator::util::deserialize_some" + deserialize_with = "crate::database::schema::deserialize_some" )] pub const_: Option, @@ -96,8 +104,6 @@ pub struct SchemaObject { // Combining Keywords #[serde(rename = "allOf")] pub all_of: Option>>, - #[serde(rename = "anyOf")] - pub any_of: Option>>, #[serde(rename = "oneOf")] pub one_of: Option>>, #[serde(rename = "not")] @@ -238,9 +244,6 @@ impl Schema { if let Some(arr) = &mut self.obj.all_of { map_arr(arr); } - if let Some(arr) = &mut self.obj.any_of { - map_arr(arr); - } if let Some(arr) = &mut self.obj.one_of { map_arr(arr); } @@ -300,7 +303,6 @@ impl<'de> Deserialize<'de> for Schema { && 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() diff --git a/src/database/stem.rs b/src/database/stem.rs new file mode 100644 index 0000000..9611edb --- /dev/null +++ b/src/database/stem.rs @@ -0,0 +1,17 @@ +use crate::database::schema::Schema; +use serde::{Deserialize, Serialize}; +use std::sync::Arc; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Stem { + pub r#type: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub relation: Option, + + // The actual database schema node mapping for + // O(1) jump table execution for queryer. + // + // Automatically skipped from `jspg_stems()` JSON payload output. + #[serde(skip)] + pub schema: Arc, +} diff --git a/src/jspg.rs b/src/jspg.rs index 3843358..fc616fe 100644 --- a/src/jspg.rs +++ b/src/jspg.rs @@ -12,18 +12,18 @@ pub struct Jspg { } impl Jspg { - pub fn new(database_val: &serde_json::Value) -> Self { - let database_instance = Database::new(database_val); + pub fn new(database_val: &serde_json::Value) -> Result { + let database_instance = Database::new(database_val)?; let database = Arc::new(database_instance); let validator = Validator::new(database.clone()); let queryer = Queryer::new(database.clone()); let merger = Merger::new(database.clone()); - Self { + Ok(Self { database, validator, queryer, merger, - } + }) } } diff --git a/src/lib.rs b/src/lib.rs index 03934d0..c5210c2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,12 @@ +#[cfg(not(test))] use pgrx::*; +#[cfg(not(test))] pg_module_magic!(); +#[cfg(test)] +pub struct JsonB(pub serde_json::Value); + pub mod database; pub mod drop; pub mod jspg; @@ -20,22 +25,38 @@ lazy_static::lazy_static! { static ref GLOBAL_JSPG: RwLock>> = RwLock::new(None); } -#[pg_extern(strict)] -pub fn jspg_setup(database: JsonB) -> JsonB { - let new_jspg = crate::jspg::Jspg::new(&database.0); - let new_arc = Arc::new(new_jspg); - - // 3. ATOMIC SWAP - { - let mut lock = GLOBAL_JSPG.write().unwrap(); - *lock = Some(new_arc); - } - - let drop = crate::drop::Drop::success(); +fn jspg_failure() -> JsonB { + let error = crate::drop::Error { + code: "ENGINE_NOT_INITIALIZED".to_string(), + message: "JSPG extension has not been initialized via jspg_setup".to_string(), + details: crate::drop::ErrorDetails { + path: "".to_string(), + }, + }; + let drop = crate::drop::Drop::with_errors(vec![error]); JsonB(serde_json::to_value(drop).unwrap()) } -#[pg_extern] +#[cfg_attr(not(test), pg_extern(strict))] +pub fn jspg_setup(database: JsonB) -> JsonB { + match crate::jspg::Jspg::new(&database.0) { + Ok(new_jspg) => { + let new_arc = Arc::new(new_jspg); + + // 3. ATOMIC SWAP + { + let mut lock = GLOBAL_JSPG.write().unwrap(); + *lock = Some(new_arc); + } + + let drop = crate::drop::Drop::success(); + JsonB(serde_json::to_value(drop).unwrap()) + } + Err(drop) => JsonB(serde_json::to_value(drop).unwrap()), + } +} + +#[cfg_attr(not(test), pg_extern)] pub fn jspg_merge(data: JsonB) -> JsonB { // Try to acquire a read lock to get a clone of the Engine Arc let engine_opt = { @@ -44,35 +65,15 @@ pub fn jspg_merge(data: JsonB) -> JsonB { }; match engine_opt { - Some(engine) => match engine.merger.merge(data.0) { - Ok(result) => JsonB(result), - Err(e) => { - let error = crate::drop::Error { - code: "MERGE_FAILED".to_string(), - message: e, - details: crate::drop::ErrorDetails { - path: "".to_string(), - }, - }; - let drop = crate::drop::Drop::with_errors(vec![error]); - JsonB(serde_json::to_value(drop).unwrap()) - } - }, - None => { - let error = crate::drop::Error { - code: "VALIDATOR_NOT_INITIALIZED".to_string(), - message: "The JSPG database has not been cached yet. Run jspg_setup()".to_string(), - details: crate::drop::ErrorDetails { - path: "".to_string(), - }, - }; - let drop = crate::drop::Drop::with_errors(vec![error]); + Some(engine) => { + let drop = engine.merger.merge(data.0); JsonB(serde_json::to_value(drop).unwrap()) } + None => jspg_failure(), } } -#[pg_extern] +#[cfg_attr(not(test), pg_extern)] pub fn jspg_query(schema_id: &str, stem: Option<&str>, filters: Option) -> JsonB { let engine_opt = { let lock = GLOBAL_JSPG.read().unwrap(); @@ -80,38 +81,19 @@ pub fn jspg_query(schema_id: &str, stem: Option<&str>, filters: Option) - }; match engine_opt { - Some(engine) => match engine - .queryer - .query(schema_id, stem, filters.as_ref().map(|f| &f.0)) - { - Ok(res) => JsonB(res), - Err(e) => { - let error = crate::drop::Error { - code: "QUERY_FAILED".to_string(), - message: e, - details: crate::drop::ErrorDetails { - path: schema_id.to_string(), - }, - }; - JsonB(serde_json::to_value(crate::drop::Drop::with_errors(vec![error])).unwrap()) - } - }, - None => { - let error = crate::drop::Error { - code: "ENGINE_NOT_INITIALIZED".to_string(), - message: "JSPG extension has not been initialized via jspg_setup".to_string(), - details: crate::drop::ErrorDetails { - path: "".to_string(), - }, - }; - JsonB(serde_json::to_value(crate::drop::Drop::with_errors(vec![error])).unwrap()) + Some(engine) => { + let drop = engine + .queryer + .query(schema_id, stem, filters.as_ref().map(|f| &f.0)); + JsonB(serde_json::to_value(drop).unwrap()) } + None => jspg_failure(), } } // `mask_json_schema` has been removed as the mask architecture is fully replaced by Spi string queries during DB interactions. -#[pg_extern(strict, parallel_safe)] +#[cfg_attr(not(test), pg_extern(strict, parallel_safe))] pub fn jspg_validate(schema_id: &str, instance: JsonB) -> JsonB { // 1. Acquire Snapshot let jspg_arc = { @@ -121,50 +103,17 @@ pub fn jspg_validate(schema_id: &str, instance: JsonB) -> JsonB { // 2. Validate (Lock-Free) if let Some(engine) = jspg_arc { - match engine.validator.validate(schema_id, &instance.0) { - Ok(result) => { - if result.is_valid() { - let drop = crate::drop::Drop::success(); - JsonB(serde_json::to_value(drop).unwrap()) - } else { - let errors: Vec = result - .errors - .into_iter() - .map(|e| crate::drop::Error { - code: e.code, - message: e.message, - details: crate::drop::ErrorDetails { path: e.path }, - }) - .collect(); - let drop = crate::drop::Drop::with_errors(errors); - JsonB(serde_json::to_value(drop).unwrap()) - } - } - Err(e) => { - let error = crate::drop::Error { - code: e.code, - message: e.message, - details: crate::drop::ErrorDetails { path: e.path }, - }; - let drop = crate::drop::Drop::with_errors(vec![error]); - JsonB(serde_json::to_value(drop).unwrap()) - } - } - } else { - let error = crate::drop::Error { - code: "VALIDATOR_NOT_INITIALIZED".to_string(), - message: "The JSPG database has not been cached yet. Run jspg_setup()".to_string(), - details: crate::drop::ErrorDetails { - path: "".to_string(), - }, - }; - let drop = crate::drop::Drop::with_errors(vec![error]); + let drop = engine.validator.validate(schema_id, &instance.0); JsonB(serde_json::to_value(drop).unwrap()) + } else { + jspg_failure() } } -#[pg_extern] -pub fn jspg_get_punc_stems(punc_name: &str) -> JsonB { +#[cfg_attr(not(test), pg_extern)] +pub fn jspg_stems() -> JsonB { + use serde_json::{Map, Value}; + let engine_opt = { let lock = GLOBAL_JSPG.read().unwrap(); lock.clone() @@ -172,17 +121,13 @@ pub fn jspg_get_punc_stems(punc_name: &str) -> JsonB { match engine_opt { Some(engine) => { - if let Some(punc) = engine.database.puncs.get(punc_name) { - JsonB(serde_json::to_value(&punc.stems).unwrap_or(serde_json::Value::Array(vec![]))) - } else { - JsonB(serde_json::Value::Array(vec![])) - } + JsonB(serde_json::to_value(&engine.database.stems).unwrap_or(Value::Object(Map::new()))) } - None => JsonB(serde_json::Value::Array(vec![])), + None => JsonB(Value::Object(Map::new())), } } -#[pg_extern(strict)] +#[cfg_attr(not(test), pg_extern(strict))] pub fn jspg_teardown() -> JsonB { let mut lock = GLOBAL_JSPG.write().unwrap(); *lock = None; @@ -190,21 +135,5 @@ pub fn jspg_teardown() -> JsonB { JsonB(serde_json::to_value(drop).unwrap()) } -#[cfg(any(test, feature = "pg_test"))] -#[pg_schema] -mod tests { - use pgrx::prelude::*; - include!("tests/fixtures.rs"); -} - #[cfg(test)] -pub mod pg_test { - pub fn setup(_options: Vec<&str>) { - // perform any initialization common to all tests - } - - pub fn postgresql_conf_options() -> Vec<&'static str> { - // return any postgresql.conf settings that are required for your tests - vec![] - } -} +pub mod tests; diff --git a/src/merger/mod.rs b/src/merger/mod.rs index 3f1843c..31d68ae 100644 --- a/src/merger/mod.rs +++ b/src/merger/mod.rs @@ -21,8 +21,21 @@ impl Merger { } } + pub fn merge(&self, data: Value) -> crate::drop::Drop { + match self.merge_internal(data) { + Ok(val) => crate::drop::Drop::success_with_val(val), + Err(msg) => crate::drop::Drop::with_errors(vec![crate::drop::Error { + code: "MERGE_FAILED".to_string(), + message: msg, + details: crate::drop::ErrorDetails { + path: "".to_string(), + }, + }]), + } + } + /// Primary recursive entrypoint that separates Array lists from Object branches - pub fn merge(&self, data: Value) -> Result { + pub(crate) fn merge_internal(&self, data: Value) -> Result { let result = match data { Value::Array(items) => self.merge_array(items)?, Value::Object(map) => self.merge_object(map)?, @@ -62,7 +75,7 @@ impl Merger { let mut resolved_items = Vec::new(); for item in items { // Recursively evaluate each object in the array - let resolved = self.merge(item)?; + let resolved = self.merge_internal(item)?; resolved_items.push(resolved); } Ok(Value::Array(resolved_items)) @@ -178,7 +191,7 @@ impl Merger { } // RECURSE: Merge the modified children - let merged_val = self.merge(child_val)?; + let merged_val = self.merge_internal(child_val)?; // Post-Process: Apply relations upwards if parent owns the FK if let Some((relation, parent_is_source, _child_is_source)) = relation_info { @@ -653,6 +666,8 @@ impl Merger { } } + my_changes.sort(); + if is_update { if my_changes.is_empty() { continue; diff --git a/src/queryer/compiler.rs b/src/queryer/compiler.rs index ac81a6b..c1b1953 100644 --- a/src/queryer/compiler.rs +++ b/src/queryer/compiler.rs @@ -23,86 +23,34 @@ impl SqlCompiler { .get(schema_id) .ok_or_else(|| format!("Schema not found: {}", schema_id))?; + let resolved_arc; let target_schema = if let Some(path) = stem_path.filter(|p| !p.is_empty() && *p != "/") { - self.resolve_stem(schema, path)? + if let Some(stems_map) = self.db.stems.get(schema_id) { + if let Some(stem) = stems_map.get(path) { + resolved_arc = stem.schema.clone(); + } else { + return Err(format!( + "Stem entity type '{}' not found in schema '{}'", + path, schema_id + )); + } + } else { + return Err(format!( + "Stem entity type '{}' not found in schema '{}'", + path, schema_id + )); + } + resolved_arc.as_ref() } else { schema }; - // 1. We expect the top level to typically be an Object or Array - let (sql, _) = self.walk_schema(target_schema, "t1", None, filter_keys)?; + // We expect the top level to typically be an Object or Array + let is_stem_query = stem_path.is_some(); + let (sql, _) = self.walk_schema(target_schema, "t1", None, filter_keys, is_stem_query, 0)?; Ok(sql) } - fn resolve_stem<'a>( - &'a self, - mut schema: &'a crate::database::schema::Schema, - path: &str, - ) -> Result<&'a crate::database::schema::Schema, String> { - let parts: Vec<&str> = path.trim_start_matches('/').split('/').collect(); - for part in parts { - let mut current = schema; - let mut depth = 0; - while let Some(r) = ¤t.obj.r#ref { - if let Some(s) = self.db.schemas.get(r) { - current = s; - } else { - break; - } - depth += 1; - if depth > 20 { - break; - } - } - - if current.obj.properties.is_none() && current.obj.items.is_some() { - if let Some(items) = ¤t.obj.items { - current = items; - let mut depth2 = 0; - while let Some(r) = ¤t.obj.r#ref { - if let Some(s) = self.db.schemas.get(r) { - current = s; - } else { - break; - } - depth2 += 1; - if depth2 > 20 { - break; - } - } - } - } - - if let Some(props) = ¤t.obj.properties { - if let Some(next_schema) = props.get(part) { - schema = next_schema; - } else { - return Err(format!("Stem part '{}' not found in schema", part)); - } - } else { - return Err(format!( - "Cannot resolve stem part '{}': not an object", - part - )); - } - } - - let mut current = schema; - let mut depth = 0; - while let Some(r) = ¤t.obj.r#ref { - if let Some(s) = self.db.schemas.get(r) { - current = s; - } else { - break; - } - depth += 1; - if depth > 20 { - break; - } - } - Ok(current) - } - /// Recursively walks the schema AST emitting native PostgreSQL jsonb mapping /// Returns a tuple of (SQL_String, Field_Type) fn walk_schema( @@ -111,6 +59,8 @@ impl SqlCompiler { parent_alias: &str, prop_name_context: Option<&str>, filter_keys: &[String], + is_stem_query: bool, + depth: usize, ) -> Result<(String, String), String> { // Determine the base schema type (could be an array, object, or literal) match &schema.obj.type_ { @@ -119,6 +69,9 @@ impl SqlCompiler { if let Some(items) = &schema.obj.items { if let Some(ref_id) = &items.obj.r#ref { if let Some(type_def) = self.db.types.get(ref_id) { + if is_stem_query && depth > 0 { + return Ok(("".to_string(), "abort".to_string())); + } return self.compile_entity_node( items, type_def, @@ -126,11 +79,19 @@ impl SqlCompiler { prop_name_context, true, filter_keys, + is_stem_query, + depth, ); } } - let (item_sql, _) = - self.walk_schema(items, parent_alias, prop_name_context, filter_keys)?; + let (item_sql, _) = self.walk_schema( + items, + parent_alias, + prop_name_context, + filter_keys, + is_stem_query, + depth + 1, + )?; return Ok(( format!("(SELECT jsonb_agg({}) FROM TODO)", item_sql), "array".to_string(), @@ -143,29 +104,57 @@ impl SqlCompiler { )) } _ => { - // Handle Objects & Direct Refs - if let Some(ref_id) = &schema.obj.r#ref { - // If it's a $ref, check if it points to an Entity Type - if let Some(type_def) = self.db.types.get(ref_id) { - return self.compile_entity_node( - schema, - type_def, - parent_alias, - prop_name_context, - false, - filter_keys, - ); + // Determine if this schema represents a Database Entity + let mut resolved_type = None; + + // Target is generally a specific schema (e.g. 'base.person'), but it tells us what physical + // database table hierarchy it maps to via the `schema.id` prefix/suffix convention. + if let Some(lookup_key) = schema.obj.id.as_ref().or(schema.obj.r#ref.as_ref()) { + let base_type_name = lookup_key.split('.').next_back().unwrap_or("").to_string(); + resolved_type = self.db.types.get(&base_type_name); + } + + if let Some(type_def) = resolved_type { + if is_stem_query && depth > 0 { + return Ok(("".to_string(), "abort".to_string())); } + return self.compile_entity_node( + schema, + type_def, + parent_alias, + prop_name_context, + false, + filter_keys, + is_stem_query, + depth, + ); + } + + // Handle Direct Refs + if let Some(ref_id) = &schema.obj.r#ref { // If it's just an ad-hoc struct ref, we should resolve it if let Some(target_schema) = self.db.schemas.get(ref_id) { - return self.walk_schema(target_schema, parent_alias, prop_name_context, filter_keys); + return self.walk_schema( + target_schema, + parent_alias, + prop_name_context, + filter_keys, + is_stem_query, + depth, + ); } return Err(format!("Unresolved $ref: {}", ref_id)); } // Just an inline object definition? if let Some(props) = &schema.obj.properties { - return self.compile_inline_object(props, parent_alias, filter_keys); + return self.compile_inline_object( + props, + parent_alias, + filter_keys, + is_stem_query, + depth, + ); } // Literal fallback @@ -181,6 +170,27 @@ impl SqlCompiler { } } + fn get_merged_properties( + &self, + schema: &crate::database::schema::Schema, + ) -> std::collections::BTreeMap> { + let mut props = std::collections::BTreeMap::new(); + + if let Some(ref_id) = &schema.obj.r#ref { + if let Some(parent_schema) = self.db.schemas.get(ref_id) { + props.extend(self.get_merged_properties(parent_schema)); + } + } + + if let Some(local_props) = &schema.obj.properties { + for (k, v) in local_props { + props.insert(k.clone(), v.clone()); + } + } + + props + } + fn compile_entity_node( &self, schema: &crate::database::schema::Schema, @@ -189,6 +199,8 @@ impl SqlCompiler { prop_name: Option<&str>, is_array: bool, filter_keys: &[String], + is_stem_query: bool, + depth: usize, ) -> Result<(String, String), String> { // We are compiling a query block for an Entity. let mut select_args = Vec::new(); @@ -220,35 +232,45 @@ impl SqlCompiler { // grouped_fields is { "person": ["first_name", ...], "user": ["password"], ... } let grouped_fields = type_def.grouped_fields.as_ref().and_then(|v| v.as_object()); - if let Some(props) = &schema.obj.properties { - for (prop_key, prop_schema) in props { - // Find which table owns this property - // Find which table owns this property - let mut owner_alias = table_aliases - .get("entity") - .cloned() - .unwrap_or_else(|| format!("{}_t_err", parent_alias)); + let merged_props = self.get_merged_properties(schema); + for (prop_key, prop_schema) in &merged_props { + // Find which table owns this property + // Find which table owns this property + let mut owner_alias = table_aliases + .get("entity") + .cloned() + .unwrap_or_else(|| format!("{}_t_err", parent_alias)); - if let Some(gf) = grouped_fields { - for (t_name, fields_val) in gf { - if let Some(fields_arr) = fields_val.as_array() { - if fields_arr.iter().any(|v| v.as_str() == Some(prop_key)) { - owner_alias = table_aliases - .get(t_name) - .cloned() - .unwrap_or_else(|| parent_alias.to_string()); - break; - } + if let Some(gf) = grouped_fields { + for (t_name, fields_val) in gf { + if let Some(fields_arr) = fields_val.as_array() { + if fields_arr.iter().any(|v| v.as_str() == Some(prop_key)) { + owner_alias = table_aliases + .get(t_name) + .cloned() + .unwrap_or_else(|| parent_alias.to_string()); + break; } } } - - // Now we know `owner_alias`, e.g., `parent_t1` or `parent_t3`. - // Walk the property to get its SQL value - let (val_sql, _) = - self.walk_schema(prop_schema, &owner_alias, Some(prop_key), filter_keys)?; - select_args.push(format!("'{}', {}", prop_key, val_sql)); } + + // Now we know `owner_alias`, e.g., `parent_t1` or `parent_t3`. + // Walk the property to get its SQL value + let (val_sql, val_type) = self.walk_schema( + prop_schema, + &owner_alias, + Some(prop_key), + filter_keys, + is_stem_query, + depth + 1, + )?; + + if val_type == "abort" { + continue; + } + + select_args.push(format!("'{}', {}", prop_key, val_sql)); } let jsonb_obj_sql = if select_args.is_empty() { @@ -266,7 +288,7 @@ impl SqlCompiler { where_clauses.push(format!("NOT {}.archived", base_alias)); // Filter Mapping - Only append filters if this is the ROOT table query (i.e. parent_alias is "t1") // Because cue.filters operates strictly on top-level root properties right now. - if parent_alias == "t1" && prop_name.is_none() { + if parent_alias == "t1" { for (i, filter_key) in filter_keys.iter().enumerate() { // Find which table owns this filter key let mut filter_alias = base_alias.clone(); // default to root table (e.g. t3 entity) @@ -288,23 +310,36 @@ impl SqlCompiler { let mut is_ilike = false; let mut cast = ""; - // Check schema for filter_key to determine datatype operation - if let Some(props) = &schema.obj.properties { - if let Some(ps) = props.get(filter_key) { - let is_enum = ps.obj.enum_.is_some(); - if let Some(crate::database::schema::SchemaTypeOrArray::Single(t)) = &ps.obj.type_ { - if t == "string" { - if ps.obj.format.as_deref() == Some("uuid") { - cast = "::uuid"; - } else if ps.obj.format.as_deref() == Some("date-time") { - cast = "::timestamptz"; - } else if !is_enum { + // Use PostgreSQL column type metadata for exact argument casting + if let Some(field_types) = type_def.field_types.as_ref().and_then(|v| v.as_object()) { + if let Some(pg_type_val) = field_types.get(filter_key) { + if let Some(pg_type) = pg_type_val.as_str() { + if pg_type == "uuid" { + cast = "::uuid"; + } else if pg_type == "boolean" || pg_type == "bool" { + cast = "::boolean"; + } else if pg_type.contains("timestamp") + || pg_type == "timestamptz" + || pg_type == "date" + { + cast = "::timestamptz"; + } else if pg_type == "numeric" + || pg_type.contains("int") + || pg_type == "real" + || pg_type == "double precision" + { + cast = "::numeric"; + } else if pg_type == "text" || pg_type.contains("char") { + // Determine if this is an enum in the schema locally to avoid ILIKE on strict enums + let mut is_enum = false; + if let Some(props) = &schema.obj.properties { + if let Some(ps) = props.get(filter_key) { + is_enum = ps.obj.enum_.is_some(); + } + } + if !is_enum { is_ilike = true; } - } else if t == "boolean" { - cast = "::boolean"; - } else if t == "integer" || t == "number" { - cast = "::numeric"; } } } @@ -357,10 +392,22 @@ impl SqlCompiler { props: &std::collections::BTreeMap>, parent_alias: &str, filter_keys: &[String], + is_stem_query: bool, + depth: usize, ) -> Result<(String, String), String> { let mut build_args = Vec::new(); for (k, v) in props { - let (child_sql, _) = self.walk_schema(v, parent_alias, Some(k), filter_keys)?; + let (child_sql, val_type) = self.walk_schema( + v, + parent_alias, + Some(k), + filter_keys, + is_stem_query, + depth + 1, + )?; + if val_type == "abort" { + continue; + } build_args.push(format!("'{}', {}", k, child_sql)); } let combined = format!("jsonb_build_object({})", build_args.join(", ")); diff --git a/src/queryer/mod.rs b/src/queryer/mod.rs index 87bf000..ac9113e 100644 --- a/src/queryer/mod.rs +++ b/src/queryer/mod.rs @@ -18,13 +18,12 @@ impl Queryer { } } - /// Entrypoint to execute a dynamically compiled query based on a schema pub fn query( &self, schema_id: &str, stem_opt: Option<&str>, filters: Option<&serde_json::Value>, - ) -> Result { + ) -> crate::drop::Drop { let filters_map: Option<&serde_json::Map> = filters.and_then(|f| f.as_object()); @@ -45,9 +44,21 @@ impl Queryer { } else { // Compile the massive base SQL string let compiler = compiler::SqlCompiler::new(self.db.clone()); - let compiled_sql = compiler.compile(schema_id, stem_opt, &filter_keys)?; - self.cache.insert(cache_key.clone(), compiled_sql.clone()); - compiled_sql + match compiler.compile(schema_id, stem_opt, &filter_keys) { + Ok(compiled_sql) => { + self.cache.insert(cache_key.clone(), compiled_sql.clone()); + compiled_sql + } + Err(e) => { + return crate::drop::Drop::with_errors(vec![crate::drop::Error { + code: "QUERY_COMPILATION_FAILED".to_string(), + message: e, + details: crate::drop::ErrorDetails { + path: schema_id.to_string(), + }, + }]); + } + } }; // 2. Prepare the execution arguments from the filters @@ -62,22 +73,29 @@ impl Queryer { } // 3. Execute via Database Executor - let fetched = match self.db.query(&sql, Some(&args)) { + match self.db.query(&sql, Some(&args)) { Ok(serde_json::Value::Array(table)) => { if table.is_empty() { - Ok(serde_json::Value::Null) + crate::drop::Drop::success_with_val(serde_json::Value::Null) } else { // We expect the query to return a single JSONB column, already unpacked from row[0] - Ok(table.first().unwrap().clone()) + crate::drop::Drop::success_with_val(table.first().unwrap().clone()) } } - Ok(other) => Err(format!( - "Expected array from generic query, got: {:?}", - other - )), - Err(e) => Err(format!("SPI error in queryer: {}", e)), - }?; - - Ok(fetched) + Ok(other) => crate::drop::Drop::with_errors(vec![crate::drop::Error { + code: "QUERY_FAILED".to_string(), + message: format!("Expected array from generic query, got: {:?}", other), + details: crate::drop::ErrorDetails { + path: schema_id.to_string(), + }, + }]), + Err(e) => crate::drop::Drop::with_errors(vec![crate::drop::Error { + code: "QUERY_FAILED".to_string(), + message: format!("SPI error in queryer: {}", e), + details: crate::drop::ErrorDetails { + path: schema_id.to_string(), + }, + }]), + } } } diff --git a/src/tests/fixtures.rs b/src/tests/fixtures.rs index d27650a..ca16641 100644 --- a/src/tests/fixtures.rs +++ b/src/tests/fixtures.rs @@ -1,1668 +1,1686 @@ -#[pg_test] +#[test] fn test_content_0() { - let path = format!("{}/tests/fixtures/content.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/content.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_content_1() { - let path = format!("{}/tests/fixtures/content.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/content.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_content_2() { - let path = format!("{}/tests/fixtures/content.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); + let path = format!("{}/fixtures/content.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 2).unwrap(); } -#[pg_test] +#[test] fn test_content_3() { - let path = format!("{}/tests/fixtures/content.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); + let path = format!("{}/fixtures/content.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 3).unwrap(); } -#[pg_test] +#[test] fn test_unique_items_0() { - let path = format!("{}/tests/fixtures/uniqueItems.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/uniqueItems.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_unique_items_1() { - let path = format!("{}/tests/fixtures/uniqueItems.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/uniqueItems.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_unique_items_2() { - let path = format!("{}/tests/fixtures/uniqueItems.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); + let path = format!("{}/fixtures/uniqueItems.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 2).unwrap(); } -#[pg_test] +#[test] fn test_unique_items_3() { - let path = format!("{}/tests/fixtures/uniqueItems.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); + let path = format!("{}/fixtures/uniqueItems.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 3).unwrap(); } -#[pg_test] +#[test] fn test_unique_items_4() { - let path = format!("{}/tests/fixtures/uniqueItems.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 4).unwrap(); + let path = format!("{}/fixtures/uniqueItems.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 4).unwrap(); } -#[pg_test] +#[test] fn test_unique_items_5() { - let path = format!("{}/tests/fixtures/uniqueItems.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 5).unwrap(); + let path = format!("{}/fixtures/uniqueItems.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 5).unwrap(); } -#[pg_test] +#[test] fn test_unique_items_6() { - let path = format!("{}/tests/fixtures/uniqueItems.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 6).unwrap(); + let path = format!("{}/fixtures/uniqueItems.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 6).unwrap(); } -#[pg_test] +#[test] fn test_min_items_0() { - let path = format!("{}/tests/fixtures/minItems.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/minItems.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_min_items_1() { - let path = format!("{}/tests/fixtures/minItems.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/minItems.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_min_items_2() { - let path = format!("{}/tests/fixtures/minItems.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); + let path = format!("{}/fixtures/minItems.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 2).unwrap(); } -#[pg_test] +#[test] fn test_additional_properties_0() { - let path = format!("{}/tests/fixtures/additionalProperties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/additionalProperties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_additional_properties_1() { - let path = format!("{}/tests/fixtures/additionalProperties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/additionalProperties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_additional_properties_2() { - let path = format!("{}/tests/fixtures/additionalProperties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); + let path = format!("{}/fixtures/additionalProperties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 2).unwrap(); } -#[pg_test] +#[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(); + let path = format!("{}/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[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(); + let path = format!("{}/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[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(); + let path = format!("{}/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 2).unwrap(); } -#[pg_test] +#[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(); + let path = format!("{}/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 3).unwrap(); } -#[pg_test] +#[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(); + let path = format!("{}/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 4).unwrap(); } -#[pg_test] +#[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(); + let path = format!("{}/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 5).unwrap(); } -#[pg_test] +#[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(); + let path = format!("{}/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 6).unwrap(); } -#[pg_test] +#[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(); + let path = format!("{}/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 7).unwrap(); } -#[pg_test] +#[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(); + let path = format!("{}/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 8).unwrap(); } -#[pg_test] +#[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(); + let path = format!("{}/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 9).unwrap(); } -#[pg_test] +#[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(); + let path = format!("{}/fixtures/dependencies.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 10).unwrap(); } -#[pg_test] +#[test] fn test_exclusive_minimum_0() { - let path = format!("{}/tests/fixtures/exclusiveMinimum.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/exclusiveMinimum.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_const_0() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_const_1() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_const_2() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); + let path = format!("{}/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 2).unwrap(); } -#[pg_test] +#[test] fn test_const_3() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); + let path = format!("{}/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 3).unwrap(); } -#[pg_test] +#[test] fn test_const_4() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 4).unwrap(); + let path = format!("{}/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 4).unwrap(); } -#[pg_test] +#[test] fn test_const_5() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 5).unwrap(); + let path = format!("{}/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 5).unwrap(); } -#[pg_test] +#[test] fn test_const_6() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 6).unwrap(); + let path = format!("{}/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 6).unwrap(); } -#[pg_test] +#[test] fn test_const_7() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 7).unwrap(); + let path = format!("{}/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 7).unwrap(); } -#[pg_test] +#[test] fn test_const_8() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 8).unwrap(); + let path = format!("{}/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 8).unwrap(); } -#[pg_test] +#[test] fn test_const_9() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 9).unwrap(); + let path = format!("{}/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 9).unwrap(); } -#[pg_test] +#[test] fn test_const_10() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 10).unwrap(); + let path = format!("{}/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 10).unwrap(); } -#[pg_test] +#[test] fn test_const_11() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 11).unwrap(); + let path = format!("{}/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 11).unwrap(); } -#[pg_test] +#[test] fn test_const_12() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 12).unwrap(); + let path = format!("{}/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 12).unwrap(); } -#[pg_test] +#[test] fn test_const_13() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 13).unwrap(); + let path = format!("{}/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 13).unwrap(); } -#[pg_test] +#[test] fn test_const_14() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 14).unwrap(); + let path = format!("{}/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 14).unwrap(); } -#[pg_test] +#[test] fn test_const_15() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 15).unwrap(); + let path = format!("{}/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 15).unwrap(); } -#[pg_test] +#[test] fn test_const_16() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 16).unwrap(); + let path = format!("{}/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 16).unwrap(); } -#[pg_test] +#[test] fn test_const_17() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 17).unwrap(); + let path = format!("{}/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 17).unwrap(); } -#[pg_test] +#[test] fn test_families_0() { - let path = format!("{}/tests/fixtures/families.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/families.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_families_1() { - let path = format!("{}/tests/fixtures/families.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/families.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_property_names_0() { - let path = format!("{}/tests/fixtures/propertyNames.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/propertyNames.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_property_names_1() { - let path = format!("{}/tests/fixtures/propertyNames.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/propertyNames.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_property_names_2() { - let path = format!("{}/tests/fixtures/propertyNames.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); + let path = format!("{}/fixtures/propertyNames.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 2).unwrap(); } -#[pg_test] +#[test] fn test_property_names_3() { - let path = format!("{}/tests/fixtures/propertyNames.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); + let path = format!("{}/fixtures/propertyNames.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 3).unwrap(); } -#[pg_test] +#[test] fn test_property_names_4() { - let path = format!("{}/tests/fixtures/propertyNames.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 4).unwrap(); + let path = format!("{}/fixtures/propertyNames.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 4).unwrap(); } -#[pg_test] +#[test] fn test_property_names_5() { - let path = format!("{}/tests/fixtures/propertyNames.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 5).unwrap(); + let path = format!("{}/fixtures/propertyNames.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 5).unwrap(); } -#[pg_test] +#[test] fn test_property_names_6() { - let path = format!("{}/tests/fixtures/propertyNames.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 6).unwrap(); + let path = format!("{}/fixtures/propertyNames.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 6).unwrap(); } -#[pg_test] +#[test] +fn test_queryer_0() { + let path = format!("{}/fixtures/queryer.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); +} + +#[test] +fn test_queryer_1() { + let path = format!("{}/fixtures/queryer.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); +} + +#[test] fn test_not_0() { - let path = format!("{}/tests/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_not_1() { - let path = format!("{}/tests/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_not_2() { - let path = format!("{}/tests/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); + let path = format!("{}/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 2).unwrap(); } -#[pg_test] +#[test] fn test_not_3() { - let path = format!("{}/tests/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); + let path = format!("{}/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 3).unwrap(); } -#[pg_test] +#[test] fn test_not_4() { - let path = format!("{}/tests/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 4).unwrap(); + let path = format!("{}/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 4).unwrap(); } -#[pg_test] +#[test] fn test_not_5() { - let path = format!("{}/tests/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 5).unwrap(); + let path = format!("{}/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 5).unwrap(); } -#[pg_test] +#[test] fn test_not_6() { - let path = format!("{}/tests/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 6).unwrap(); + let path = format!("{}/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 6).unwrap(); } -#[pg_test] +#[test] fn test_not_7() { - let path = format!("{}/tests/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 7).unwrap(); + let path = format!("{}/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 7).unwrap(); } -#[pg_test] +#[test] fn test_not_8() { - let path = format!("{}/tests/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 8).unwrap(); + let path = format!("{}/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 8).unwrap(); } -#[pg_test] +#[test] fn test_not_9() { - let path = format!("{}/tests/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 9).unwrap(); + let path = format!("{}/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 9).unwrap(); } -#[pg_test] +#[test] fn test_not_10() { - let path = format!("{}/tests/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 10).unwrap(); + let path = format!("{}/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 10).unwrap(); } -#[pg_test] +#[test] fn test_not_11() { - let path = format!("{}/tests/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 11).unwrap(); + let path = format!("{}/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 11).unwrap(); } -#[pg_test] +#[test] fn test_items_0() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_items_1() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_items_2() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); + let path = format!("{}/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 2).unwrap(); } -#[pg_test] +#[test] fn test_items_3() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); + let path = format!("{}/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 3).unwrap(); } -#[pg_test] +#[test] fn test_items_4() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 4).unwrap(); + let path = format!("{}/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 4).unwrap(); } -#[pg_test] +#[test] fn test_items_5() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 5).unwrap(); + let path = format!("{}/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 5).unwrap(); } -#[pg_test] +#[test] fn test_items_6() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 6).unwrap(); + let path = format!("{}/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 6).unwrap(); } -#[pg_test] +#[test] fn test_items_7() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 7).unwrap(); + let path = format!("{}/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 7).unwrap(); } -#[pg_test] +#[test] fn test_items_8() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 8).unwrap(); + let path = format!("{}/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 8).unwrap(); } -#[pg_test] +#[test] fn test_items_9() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 9).unwrap(); + let path = format!("{}/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 9).unwrap(); } -#[pg_test] +#[test] fn test_items_10() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 10).unwrap(); + let path = format!("{}/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 10).unwrap(); } -#[pg_test] +#[test] fn test_items_11() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 11).unwrap(); + let path = format!("{}/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 11).unwrap(); } -#[pg_test] +#[test] fn test_items_12() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 12).unwrap(); + let path = format!("{}/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 12).unwrap(); } -#[pg_test] +#[test] fn test_items_13() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 13).unwrap(); + let path = format!("{}/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 13).unwrap(); } -#[pg_test] +#[test] fn test_items_14() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 14).unwrap(); + let path = format!("{}/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 14).unwrap(); } -#[pg_test] +#[test] fn test_items_15() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 15).unwrap(); + let path = format!("{}/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 15).unwrap(); } -#[pg_test] +#[test] fn test_enum_0() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_enum_1() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_enum_2() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); + let path = format!("{}/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 2).unwrap(); } -#[pg_test] +#[test] fn test_enum_3() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); + let path = format!("{}/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 3).unwrap(); } -#[pg_test] +#[test] fn test_enum_4() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 4).unwrap(); + let path = format!("{}/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 4).unwrap(); } -#[pg_test] +#[test] fn test_enum_5() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 5).unwrap(); + let path = format!("{}/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 5).unwrap(); } -#[pg_test] +#[test] fn test_enum_6() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 6).unwrap(); + let path = format!("{}/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 6).unwrap(); } -#[pg_test] +#[test] fn test_enum_7() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 7).unwrap(); + let path = format!("{}/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 7).unwrap(); } -#[pg_test] +#[test] fn test_enum_8() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 8).unwrap(); + let path = format!("{}/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 8).unwrap(); } -#[pg_test] +#[test] fn test_enum_9() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 9).unwrap(); + let path = format!("{}/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 9).unwrap(); } -#[pg_test] +#[test] fn test_enum_10() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 10).unwrap(); + let path = format!("{}/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 10).unwrap(); } -#[pg_test] +#[test] fn test_enum_11() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 11).unwrap(); + let path = format!("{}/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 11).unwrap(); } -#[pg_test] +#[test] fn test_enum_12() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 12).unwrap(); + let path = format!("{}/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 12).unwrap(); } -#[pg_test] +#[test] fn test_enum_13() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 13).unwrap(); + let path = format!("{}/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 13).unwrap(); } -#[pg_test] +#[test] fn test_enum_14() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 14).unwrap(); + let path = format!("{}/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 14).unwrap(); } -#[pg_test] +#[test] fn test_min_properties_0() { - let path = format!("{}/tests/fixtures/minProperties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/minProperties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_min_properties_1() { - let path = format!("{}/tests/fixtures/minProperties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/minProperties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_min_properties_2() { - let path = format!("{}/tests/fixtures/minProperties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); + let path = format!("{}/fixtures/minProperties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 2).unwrap(); } -#[pg_test] +#[test] fn test_min_contains_0() { - let path = format!("{}/tests/fixtures/minContains.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/minContains.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_min_contains_1() { - let path = format!("{}/tests/fixtures/minContains.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/minContains.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_min_contains_2() { - let path = format!("{}/tests/fixtures/minContains.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); + let path = format!("{}/fixtures/minContains.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 2).unwrap(); } -#[pg_test] +#[test] fn test_min_contains_3() { - let path = format!("{}/tests/fixtures/minContains.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); + let path = format!("{}/fixtures/minContains.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 3).unwrap(); } -#[pg_test] +#[test] fn test_min_contains_4() { - let path = format!("{}/tests/fixtures/minContains.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 4).unwrap(); + let path = format!("{}/fixtures/minContains.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 4).unwrap(); } -#[pg_test] +#[test] fn test_min_contains_5() { - let path = format!("{}/tests/fixtures/minContains.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 5).unwrap(); + let path = format!("{}/fixtures/minContains.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 5).unwrap(); } -#[pg_test] +#[test] fn test_min_contains_6() { - let path = format!("{}/tests/fixtures/minContains.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 6).unwrap(); + let path = format!("{}/fixtures/minContains.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 6).unwrap(); } -#[pg_test] +#[test] fn test_min_contains_7() { - let path = format!("{}/tests/fixtures/minContains.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 7).unwrap(); + let path = format!("{}/fixtures/minContains.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 7).unwrap(); } -#[pg_test] +#[test] fn test_min_contains_8() { - let path = format!("{}/tests/fixtures/minContains.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 8).unwrap(); + let path = format!("{}/fixtures/minContains.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 8).unwrap(); } -#[pg_test] +#[test] fn test_properties_0() { - let path = format!("{}/tests/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_properties_1() { - let path = format!("{}/tests/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_properties_2() { - let path = format!("{}/tests/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); + let path = format!("{}/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 2).unwrap(); } -#[pg_test] +#[test] fn test_properties_3() { - let path = format!("{}/tests/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); + let path = format!("{}/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 3).unwrap(); } -#[pg_test] +#[test] fn test_properties_4() { - let path = format!("{}/tests/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 4).unwrap(); + let path = format!("{}/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 4).unwrap(); } -#[pg_test] +#[test] fn test_properties_5() { - let path = format!("{}/tests/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 5).unwrap(); + let path = format!("{}/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 5).unwrap(); } -#[pg_test] +#[test] fn test_properties_6() { - let path = format!("{}/tests/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 6).unwrap(); + let path = format!("{}/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 6).unwrap(); } -#[pg_test] +#[test] fn test_properties_7() { - let path = format!("{}/tests/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 7).unwrap(); + let path = format!("{}/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 7).unwrap(); } -#[pg_test] +#[test] fn test_properties_8() { - let path = format!("{}/tests/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 8).unwrap(); + let path = format!("{}/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 8).unwrap(); } -#[pg_test] +#[test] fn test_properties_9() { - let path = format!("{}/tests/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 9).unwrap(); + let path = format!("{}/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 9).unwrap(); } -#[pg_test] +#[test] fn test_properties_10() { - let path = format!("{}/tests/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 10).unwrap(); + let path = format!("{}/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 10).unwrap(); } -#[pg_test] +#[test] fn test_properties_11() { - let path = format!("{}/tests/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 11).unwrap(); + let path = format!("{}/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 11).unwrap(); } -#[pg_test] +#[test] fn test_properties_12() { - let path = format!("{}/tests/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 12).unwrap(); + let path = format!("{}/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 12).unwrap(); } -#[pg_test] +#[test] fn test_max_contains_0() { - let path = format!("{}/tests/fixtures/maxContains.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/maxContains.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_max_contains_1() { - let path = format!("{}/tests/fixtures/maxContains.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/maxContains.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_max_contains_2() { - let path = format!("{}/tests/fixtures/maxContains.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); + let path = format!("{}/fixtures/maxContains.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 2).unwrap(); } -#[pg_test] +#[test] fn test_max_contains_3() { - let path = format!("{}/tests/fixtures/maxContains.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); + let path = format!("{}/fixtures/maxContains.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 3).unwrap(); } -#[pg_test] +#[test] fn test_max_contains_4() { - let path = format!("{}/tests/fixtures/maxContains.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 4).unwrap(); + let path = format!("{}/fixtures/maxContains.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 4).unwrap(); } -#[pg_test] +#[test] fn test_max_length_0() { - let path = format!("{}/tests/fixtures/maxLength.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/maxLength.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_max_length_1() { - let path = format!("{}/tests/fixtures/maxLength.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/maxLength.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_exclusive_maximum_0() { - let path = format!("{}/tests/fixtures/exclusiveMaximum.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/exclusiveMaximum.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_prefix_items_0() { - let path = format!("{}/tests/fixtures/prefixItems.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/prefixItems.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_prefix_items_1() { - let path = format!("{}/tests/fixtures/prefixItems.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/prefixItems.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_prefix_items_2() { - let path = format!("{}/tests/fixtures/prefixItems.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); + let path = format!("{}/fixtures/prefixItems.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 2).unwrap(); } -#[pg_test] +#[test] fn test_prefix_items_3() { - let path = format!("{}/tests/fixtures/prefixItems.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); + let path = format!("{}/fixtures/prefixItems.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 3).unwrap(); } -#[pg_test] +#[test] fn test_prefix_items_4() { - let path = format!("{}/tests/fixtures/prefixItems.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 4).unwrap(); + let path = format!("{}/fixtures/prefixItems.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 4).unwrap(); } -#[pg_test] +#[test] fn test_minimum_0() { - let path = format!("{}/tests/fixtures/minimum.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/minimum.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_minimum_1() { - let path = format!("{}/tests/fixtures/minimum.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/minimum.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_one_of_0() { - let path = format!("{}/tests/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_one_of_1() { - let path = format!("{}/tests/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_one_of_2() { - let path = format!("{}/tests/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); + let path = format!("{}/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 2).unwrap(); } -#[pg_test] +#[test] fn test_one_of_3() { - let path = format!("{}/tests/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); + let path = format!("{}/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 3).unwrap(); } -#[pg_test] +#[test] fn test_one_of_4() { - let path = format!("{}/tests/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 4).unwrap(); + let path = format!("{}/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 4).unwrap(); } -#[pg_test] +#[test] fn test_one_of_5() { - let path = format!("{}/tests/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 5).unwrap(); + let path = format!("{}/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 5).unwrap(); } -#[pg_test] +#[test] fn test_one_of_6() { - let path = format!("{}/tests/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 6).unwrap(); + let path = format!("{}/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 6).unwrap(); } -#[pg_test] +#[test] fn test_one_of_7() { - let path = format!("{}/tests/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 7).unwrap(); + let path = format!("{}/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 7).unwrap(); } -#[pg_test] +#[test] fn test_one_of_8() { - let path = format!("{}/tests/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 8).unwrap(); + let path = format!("{}/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 8).unwrap(); } -#[pg_test] +#[test] fn test_one_of_9() { - let path = format!("{}/tests/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 9).unwrap(); + let path = format!("{}/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 9).unwrap(); } -#[pg_test] +#[test] fn test_one_of_10() { - let path = format!("{}/tests/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 10).unwrap(); + let path = format!("{}/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 10).unwrap(); } -#[pg_test] +#[test] fn test_one_of_11() { - let path = format!("{}/tests/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 11).unwrap(); + let path = format!("{}/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 11).unwrap(); } -#[pg_test] +#[test] fn test_one_of_12() { - let path = format!("{}/tests/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 12).unwrap(); + let path = format!("{}/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 12).unwrap(); } -#[pg_test] +#[test] fn test_boolean_schema_0() { - let path = format!("{}/tests/fixtures/booleanSchema.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/booleanSchema.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_boolean_schema_1() { - let path = format!("{}/tests/fixtures/booleanSchema.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/booleanSchema.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_if_then_else_0() { - let path = format!("{}/tests/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_if_then_else_1() { - let path = format!("{}/tests/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_if_then_else_2() { - let path = format!("{}/tests/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); + let path = format!("{}/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 2).unwrap(); } -#[pg_test] +#[test] fn test_if_then_else_3() { - let path = format!("{}/tests/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); + let path = format!("{}/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 3).unwrap(); } -#[pg_test] +#[test] fn test_if_then_else_4() { - let path = format!("{}/tests/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 4).unwrap(); + let path = format!("{}/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 4).unwrap(); } -#[pg_test] +#[test] fn test_if_then_else_5() { - let path = format!("{}/tests/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 5).unwrap(); + let path = format!("{}/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 5).unwrap(); } -#[pg_test] +#[test] fn test_if_then_else_6() { - let path = format!("{}/tests/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 6).unwrap(); + let path = format!("{}/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 6).unwrap(); } -#[pg_test] +#[test] fn test_if_then_else_7() { - let path = format!("{}/tests/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 7).unwrap(); + let path = format!("{}/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 7).unwrap(); } -#[pg_test] +#[test] fn test_if_then_else_8() { - let path = format!("{}/tests/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 8).unwrap(); + let path = format!("{}/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 8).unwrap(); } -#[pg_test] +#[test] fn test_if_then_else_9() { - let path = format!("{}/tests/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 9).unwrap(); + let path = format!("{}/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 9).unwrap(); } -#[pg_test] +#[test] fn test_if_then_else_10() { - let path = format!("{}/tests/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 10).unwrap(); + let path = format!("{}/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 10).unwrap(); } -#[pg_test] +#[test] fn test_if_then_else_11() { - let path = format!("{}/tests/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 11).unwrap(); + let path = format!("{}/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 11).unwrap(); } -#[pg_test] +#[test] fn test_if_then_else_12() { - let path = format!("{}/tests/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 12).unwrap(); + let path = format!("{}/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 12).unwrap(); } -#[pg_test] +#[test] fn test_if_then_else_13() { - let path = format!("{}/tests/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 13).unwrap(); + let path = format!("{}/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 13).unwrap(); } -#[pg_test] +#[test] fn test_empty_string_0() { - let path = format!("{}/tests/fixtures/emptyString.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/emptyString.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_pattern_0() { - let path = format!("{}/tests/fixtures/pattern.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/pattern.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_pattern_1() { - let path = format!("{}/tests/fixtures/pattern.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/pattern.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_max_properties_0() { - let path = format!("{}/tests/fixtures/maxProperties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/maxProperties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_max_properties_1() { - let path = format!("{}/tests/fixtures/maxProperties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/maxProperties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_max_properties_2() { - let path = format!("{}/tests/fixtures/maxProperties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); + let path = format!("{}/fixtures/maxProperties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 2).unwrap(); } -#[pg_test] +#[test] fn test_max_properties_3() { - let path = format!("{}/tests/fixtures/maxProperties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); + let path = format!("{}/fixtures/maxProperties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 3).unwrap(); } -#[pg_test] +#[test] fn test_required_0() { - let path = format!("{}/tests/fixtures/required.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/required.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_required_1() { - let path = format!("{}/tests/fixtures/required.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/required.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_required_2() { - let path = format!("{}/tests/fixtures/required.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); + let path = format!("{}/fixtures/required.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 2).unwrap(); } -#[pg_test] +#[test] fn test_required_3() { - let path = format!("{}/tests/fixtures/required.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); + let path = format!("{}/fixtures/required.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 3).unwrap(); } -#[pg_test] +#[test] fn test_required_4() { - let path = format!("{}/tests/fixtures/required.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 4).unwrap(); + let path = format!("{}/fixtures/required.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 4).unwrap(); } -#[pg_test] +#[test] fn test_required_5() { - let path = format!("{}/tests/fixtures/required.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 5).unwrap(); + let path = format!("{}/fixtures/required.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 5).unwrap(); } -#[pg_test] +#[test] fn test_type_0() { - let path = format!("{}/tests/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_type_1() { - let path = format!("{}/tests/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_type_2() { - let path = format!("{}/tests/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); + let path = format!("{}/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 2).unwrap(); } -#[pg_test] +#[test] fn test_type_3() { - let path = format!("{}/tests/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); + let path = format!("{}/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 3).unwrap(); } -#[pg_test] +#[test] fn test_type_4() { - let path = format!("{}/tests/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 4).unwrap(); + let path = format!("{}/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 4).unwrap(); } -#[pg_test] +#[test] fn test_type_5() { - let path = format!("{}/tests/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 5).unwrap(); + let path = format!("{}/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 5).unwrap(); } -#[pg_test] +#[test] fn test_type_6() { - let path = format!("{}/tests/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 6).unwrap(); + let path = format!("{}/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 6).unwrap(); } -#[pg_test] +#[test] fn test_type_7() { - let path = format!("{}/tests/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 7).unwrap(); + let path = format!("{}/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 7).unwrap(); } -#[pg_test] +#[test] fn test_type_8() { - let path = format!("{}/tests/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 8).unwrap(); + let path = format!("{}/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 8).unwrap(); } -#[pg_test] +#[test] fn test_type_9() { - let path = format!("{}/tests/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 9).unwrap(); + let path = format!("{}/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 9).unwrap(); } -#[pg_test] +#[test] fn test_type_10() { - let path = format!("{}/tests/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 10).unwrap(); + let path = format!("{}/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 10).unwrap(); } -#[pg_test] +#[test] fn test_type_11() { - let path = format!("{}/tests/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 11).unwrap(); + let path = format!("{}/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 11).unwrap(); } -#[pg_test] +#[test] fn test_multiple_of_0() { - let path = format!("{}/tests/fixtures/multipleOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/multipleOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_multiple_of_1() { - let path = format!("{}/tests/fixtures/multipleOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/multipleOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_multiple_of_2() { - let path = format!("{}/tests/fixtures/multipleOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); + let path = format!("{}/fixtures/multipleOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 2).unwrap(); } -#[pg_test] +#[test] fn test_multiple_of_3() { - let path = format!("{}/tests/fixtures/multipleOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); + let path = format!("{}/fixtures/multipleOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 3).unwrap(); } -#[pg_test] +#[test] fn test_pattern_properties_0() { - let path = format!("{}/tests/fixtures/patternProperties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/patternProperties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_pattern_properties_1() { - let path = format!("{}/tests/fixtures/patternProperties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/patternProperties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_pattern_properties_2() { - let path = format!("{}/tests/fixtures/patternProperties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); + let path = format!("{}/fixtures/patternProperties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 2).unwrap(); } -#[pg_test] +#[test] fn test_pattern_properties_3() { - let path = format!("{}/tests/fixtures/patternProperties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); + let path = format!("{}/fixtures/patternProperties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 3).unwrap(); } -#[pg_test] +#[test] fn test_pattern_properties_4() { - let path = format!("{}/tests/fixtures/patternProperties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 4).unwrap(); + let path = format!("{}/fixtures/patternProperties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 4).unwrap(); } -#[pg_test] +#[test] fn test_pattern_properties_5() { - let path = format!("{}/tests/fixtures/patternProperties.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 5).unwrap(); + let path = format!("{}/fixtures/patternProperties.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 5).unwrap(); } -#[pg_test] +#[test] fn test_merge_0() { - let path = format!("{}/tests/fixtures/merge.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/merge.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_merge_1() { - let path = format!("{}/tests/fixtures/merge.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/merge.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_merge_2() { - let path = format!("{}/tests/fixtures/merge.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); + let path = format!("{}/fixtures/merge.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 2).unwrap(); } -#[pg_test] +#[test] fn test_merge_3() { - let path = format!("{}/tests/fixtures/merge.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); + let path = format!("{}/fixtures/merge.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 3).unwrap(); } -#[pg_test] +#[test] fn test_all_of_0() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_all_of_1() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_all_of_2() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); + let path = format!("{}/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 2).unwrap(); } -#[pg_test] +#[test] fn test_all_of_3() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); + let path = format!("{}/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 3).unwrap(); } -#[pg_test] +#[test] fn test_all_of_4() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 4).unwrap(); + let path = format!("{}/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 4).unwrap(); } -#[pg_test] +#[test] fn test_all_of_5() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 5).unwrap(); + let path = format!("{}/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 5).unwrap(); } -#[pg_test] +#[test] fn test_all_of_6() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 6).unwrap(); + let path = format!("{}/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 6).unwrap(); } -#[pg_test] +#[test] fn test_all_of_7() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 7).unwrap(); + let path = format!("{}/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 7).unwrap(); } -#[pg_test] +#[test] fn test_all_of_8() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 8).unwrap(); + let path = format!("{}/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 8).unwrap(); } -#[pg_test] +#[test] fn test_all_of_9() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 9).unwrap(); + let path = format!("{}/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 9).unwrap(); } -#[pg_test] +#[test] fn test_all_of_10() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 10).unwrap(); + let path = format!("{}/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 10).unwrap(); } -#[pg_test] +#[test] fn test_all_of_11() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 11).unwrap(); + let path = format!("{}/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 11).unwrap(); } -#[pg_test] +#[test] fn test_all_of_12() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 12).unwrap(); + let path = format!("{}/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 12).unwrap(); } -#[pg_test] +#[test] fn test_all_of_13() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 13).unwrap(); + let path = format!("{}/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 13).unwrap(); } -#[pg_test] +#[test] fn test_all_of_14() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 14).unwrap(); + let path = format!("{}/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 14).unwrap(); } -#[pg_test] +#[test] fn test_format_0() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_format_1() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_format_2() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); + let path = format!("{}/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 2).unwrap(); } -#[pg_test] +#[test] fn test_format_3() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); + let path = format!("{}/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 3).unwrap(); } -#[pg_test] +#[test] fn test_format_4() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 4).unwrap(); + let path = format!("{}/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 4).unwrap(); } -#[pg_test] +#[test] fn test_format_5() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 5).unwrap(); + let path = format!("{}/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 5).unwrap(); } -#[pg_test] +#[test] fn test_format_6() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 6).unwrap(); + let path = format!("{}/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 6).unwrap(); } -#[pg_test] +#[test] fn test_format_7() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 7).unwrap(); + let path = format!("{}/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 7).unwrap(); } -#[pg_test] +#[test] fn test_format_8() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 8).unwrap(); + let path = format!("{}/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 8).unwrap(); } -#[pg_test] +#[test] fn test_format_9() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 9).unwrap(); + let path = format!("{}/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 9).unwrap(); } -#[pg_test] +#[test] fn test_format_10() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 10).unwrap(); + let path = format!("{}/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 10).unwrap(); } -#[pg_test] +#[test] fn test_format_11() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 11).unwrap(); + let path = format!("{}/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 11).unwrap(); } -#[pg_test] +#[test] fn test_format_12() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 12).unwrap(); + let path = format!("{}/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 12).unwrap(); } -#[pg_test] +#[test] fn test_format_13() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 13).unwrap(); + let path = format!("{}/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 13).unwrap(); } -#[pg_test] +#[test] fn test_format_14() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 14).unwrap(); + let path = format!("{}/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 14).unwrap(); } -#[pg_test] +#[test] fn test_format_15() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 15).unwrap(); + let path = format!("{}/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 15).unwrap(); } -#[pg_test] +#[test] fn test_format_16() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 16).unwrap(); + let path = format!("{}/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 16).unwrap(); } -#[pg_test] +#[test] fn test_format_17() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 17).unwrap(); + let path = format!("{}/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 17).unwrap(); } -#[pg_test] +#[test] fn test_format_18() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 18).unwrap(); + let path = format!("{}/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 18).unwrap(); } -#[pg_test] +#[test] fn test_format_19() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 19).unwrap(); + let path = format!("{}/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 19).unwrap(); } -#[pg_test] +#[test] fn test_format_20() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 20).unwrap(); + let path = format!("{}/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 20).unwrap(); } -#[pg_test] +#[test] fn test_format_21() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 21).unwrap(); + let path = format!("{}/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 21).unwrap(); } -#[pg_test] +#[test] fn test_format_22() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 22).unwrap(); + let path = format!("{}/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 22).unwrap(); } -#[pg_test] +#[test] fn test_format_23() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 23).unwrap(); + let path = format!("{}/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 23).unwrap(); } -#[pg_test] +#[test] fn test_ref_0() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_ref_1() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_ref_2() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); + let path = format!("{}/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 2).unwrap(); } -#[pg_test] +#[test] fn test_ref_3() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); + let path = format!("{}/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 3).unwrap(); } -#[pg_test] +#[test] fn test_ref_4() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 4).unwrap(); + let path = format!("{}/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 4).unwrap(); } -#[pg_test] +#[test] fn test_ref_5() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 5).unwrap(); + let path = format!("{}/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 5).unwrap(); } -#[pg_test] +#[test] fn test_ref_6() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 6).unwrap(); + let path = format!("{}/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 6).unwrap(); } -#[pg_test] +#[test] fn test_ref_7() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 7).unwrap(); + let path = format!("{}/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 7).unwrap(); } -#[pg_test] +#[test] fn test_ref_8() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 8).unwrap(); + let path = format!("{}/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 8).unwrap(); } -#[pg_test] +#[test] fn test_ref_9() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 9).unwrap(); + let path = format!("{}/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 9).unwrap(); } -#[pg_test] +#[test] fn test_ref_10() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 10).unwrap(); + let path = format!("{}/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 10).unwrap(); } -#[pg_test] +#[test] fn test_ref_11() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 11).unwrap(); + let path = format!("{}/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 11).unwrap(); } -#[pg_test] +#[test] fn test_ref_12() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 12).unwrap(); + let path = format!("{}/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 12).unwrap(); } -#[pg_test] +#[test] fn test_ref_13() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 13).unwrap(); + let path = format!("{}/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 13).unwrap(); } -#[pg_test] +#[test] fn test_ref_14() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 14).unwrap(); + let path = format!("{}/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 14).unwrap(); } -#[pg_test] +#[test] fn test_ref_15() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 15).unwrap(); + let path = format!("{}/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 15).unwrap(); } -#[pg_test] +#[test] fn test_maximum_0() { - let path = format!("{}/tests/fixtures/maximum.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/maximum.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_maximum_1() { - let path = format!("{}/tests/fixtures/maximum.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/maximum.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_min_length_0() { - let path = format!("{}/tests/fixtures/minLength.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/minLength.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_min_length_1() { - let path = format!("{}/tests/fixtures/minLength.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/minLength.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_max_items_0() { - let path = format!("{}/tests/fixtures/maxItems.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/maxItems.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_max_items_1() { - let path = format!("{}/tests/fixtures/maxItems.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/maxItems.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_max_items_2() { - let path = format!("{}/tests/fixtures/maxItems.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); + let path = format!("{}/fixtures/maxItems.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 2).unwrap(); } -#[pg_test] +#[test] fn test_contains_0() { - let path = format!("{}/tests/fixtures/contains.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 0).unwrap(); + let path = format!("{}/fixtures/contains.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } -#[pg_test] +#[test] fn test_contains_1() { - let path = format!("{}/tests/fixtures/contains.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 1).unwrap(); + let path = format!("{}/fixtures/contains.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 1).unwrap(); } -#[pg_test] +#[test] fn test_contains_2() { - let path = format!("{}/tests/fixtures/contains.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 2).unwrap(); + let path = format!("{}/fixtures/contains.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 2).unwrap(); } -#[pg_test] +#[test] fn test_contains_3() { - let path = format!("{}/tests/fixtures/contains.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 3).unwrap(); + let path = format!("{}/fixtures/contains.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 3).unwrap(); } -#[pg_test] +#[test] fn test_contains_4() { - let path = format!("{}/tests/fixtures/contains.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 4).unwrap(); + let path = format!("{}/fixtures/contains.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 4).unwrap(); } -#[pg_test] +#[test] fn test_contains_5() { - let path = format!("{}/tests/fixtures/contains.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 5).unwrap(); + let path = format!("{}/fixtures/contains.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 5).unwrap(); } -#[pg_test] +#[test] fn test_contains_6() { - let path = format!("{}/tests/fixtures/contains.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 6).unwrap(); + let path = format!("{}/fixtures/contains.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 6).unwrap(); } -#[pg_test] +#[test] fn test_contains_7() { - let path = format!("{}/tests/fixtures/contains.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 7).unwrap(); + let path = format!("{}/fixtures/contains.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 7).unwrap(); } -#[pg_test] +#[test] fn test_contains_8() { - let path = format!("{}/tests/fixtures/contains.json", env!("CARGO_MANIFEST_DIR")); - crate::validator::util::run_test_file_at_index(&path, 8).unwrap(); + let path = format!("{}/fixtures/contains.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 8).unwrap(); +} + +#[test] +fn test_merger_0() { + let path = format!("{}/fixtures/merger.json", env!("CARGO_MANIFEST_DIR")); + crate::tests::runner::run_test_file_at_index(&path, 0).unwrap(); } diff --git a/tests/lib.rs b/src/tests/mod.rs similarity index 87% rename from tests/lib.rs rename to src/tests/mod.rs index 5f73d01..48f03dc 100644 --- a/tests/lib.rs +++ b/src/tests/mod.rs @@ -1,8 +1,9 @@ -use ::jspg::*; -use pgrx::JsonB; +use crate::*; +pub mod runner; +pub mod types; use serde_json::json; -pub mod database; +// Database module tests moved to src/database/executors/mock.rs #[test] fn test_library_api() { @@ -15,8 +16,8 @@ fn test_library_api() { json!({ "type": "drop", "errors": [{ - "code": "VALIDATOR_NOT_INITIALIZED", - "message": "The JSPG database has not been cached yet. Run jspg_setup()", + "code": "ENGINE_NOT_INITIALIZED", + "message": "JSPG extension has not been initialized via jspg_setup", "details": { "path": "" } }] }) @@ -89,3 +90,5 @@ fn test_library_api() { }) ); } + +include!("fixtures.rs"); diff --git a/src/tests/runner.rs b/src/tests/runner.rs new file mode 100644 index 0000000..4460308 --- /dev/null +++ b/src/tests/runner.rs @@ -0,0 +1,113 @@ +use serde::Deserialize; +use std::fs; + +#[derive(Debug, Deserialize)] +struct TestSuite { + #[allow(dead_code)] + description: String, + database: serde_json::Value, + tests: Vec, +} + +use crate::tests::types::{ExpectBlock, TestCase}; + +use crate::validator::Validator; +use serde_json::Value; + +pub fn deserialize_some<'de, D>(deserializer: D) -> Result, D::Error> +where + D: serde::Deserializer<'de>, +{ + let v = Value::deserialize(deserializer)?; + Ok(Some(v)) +} + +pub fn run_test_file_at_index(path: &str, index: usize) -> Result<(), String> { + let content = + fs::read_to_string(path).unwrap_or_else(|_| panic!("Failed to read file: {}", path)); + let suite: Vec = serde_json::from_str(&content) + .unwrap_or_else(|e| panic!("Failed to parse JSON in {}: {}", path, e)); + + if index >= suite.len() { + panic!("Index {} out of bounds for file {}", index, path); + } + + let group = &suite[index]; + let mut failures = Vec::::new(); + + let db_json = group.database.clone(); + let db_result = crate::database::Database::new(&db_json); + if let Err(drop) = db_result { + let error_messages: Vec = drop + .errors + .into_iter() + .map(|e| format!("Error {} at path {}: {}", e.code, e.details.path, e.message)) + .collect(); + return Err(format!( + "System Setup Compilation failed:\n{}", + error_messages.join("\n") + )); + } + let db = db_result.unwrap(); + let validator = Validator::new(std::sync::Arc::new(db)); + + // 4. Run Tests + for test in group.tests.iter() { + // Provide fallback for legacy expectations if `expect` block was missing despite migration script + let expected_success = test + .expect + .as_ref() + .map(|e| e.success) + .unwrap_or(test.valid.unwrap_or(false)); + let _expected_errors = test + .expect + .as_ref() + .and_then(|e| e.errors.clone()) + .unwrap_or(test.expect_errors.clone().unwrap_or(vec![])); + + match test.action.as_str() { + "validate" => { + let result = test.run_validate(validator.db.clone()); + if let Err(e) = result { + println!("TEST VALIDATE ERROR FOR '{}': {}", test.description, e); + failures.push(format!( + "[{}] Validate Test '{}' failed. Error: {}", + group.description, test.description, e + )); + } + } + "merge" => { + let result = test.run_merge(validator.db.clone()); + if let Err(e) = result { + println!("TEST MERGE ERROR FOR '{}': {}", test.description, e); + failures.push(format!( + "[{}] Merge Test '{}' failed. Error: {}", + group.description, test.description, e + )); + } + } + "query" => { + let result = test.run_query(validator.db.clone()); + if let Err(e) = result { + println!("TEST QUERY ERROR FOR '{}': {}", test.description, e); + failures.push(format!( + "[{}] Query Test '{}' failed. Error: {}", + group.description, test.description, e + )); + } + } + _ => { + failures.push(format!( + "[{}] Unknown action '{}' for test '{}'", + group.description, test.action, test.description + )); + } + } + } + + if !failures.is_empty() { + return Err(failures.join("\n")); + } + + Ok(()) +} diff --git a/src/tests/types/case.rs b/src/tests/types/case.rs new file mode 100644 index 0000000..1354f25 --- /dev/null +++ b/src/tests/types/case.rs @@ -0,0 +1,167 @@ +use super::expect::ExpectBlock; +use crate::database::Database; +use serde::Deserialize; +use serde_json::Value; +use std::sync::Arc; + +#[derive(Debug, Deserialize)] +pub struct TestCase { + pub description: String, + + #[serde(default = "default_action")] + pub action: String, // "validate", "merge", or "query" + + // For Validate & Query + #[serde(default)] + pub schema_id: String, + + // For Query + #[serde(default)] + pub stem: Option, + + #[serde(default)] + pub filters: Option, + + // For Merge & Validate + #[serde(default)] + pub data: Option, + + // For Merge & Query mocks + #[serde(default)] + pub mocks: Option, + + pub expect: Option, + + // Legacy support for older tests to avoid migrating them all instantly + pub valid: Option, + pub expect_errors: Option>, +} + +fn default_action() -> String { + "validate".to_string() +} + +impl TestCase { + pub fn execute(&self, db: Arc) -> Result<(), String> { + match self.action.as_str() { + "validate" => self.run_validate(db), + "merge" => self.run_merge(db), + "query" => self.run_query(db), + _ => Err(format!( + "Unknown action '{}' for test '{}'", + self.action, self.description + )), + } + } + + pub fn run_validate(&self, db: Arc) -> Result<(), String> { + use crate::validator::Validator; + + let validator = Validator::new(db); + + let expected_success = self + .expect + .as_ref() + .map(|e| e.success) + .unwrap_or(self.valid.unwrap_or(false)); + + // _expected_errors is preserved for future diffing if needed + let _expected_errors = self + .expect + .as_ref() + .and_then(|e| e.errors.clone()) + .unwrap_or(self.expect_errors.clone().unwrap_or(vec![])); + + let schema_id = &self.schema_id; + if !validator.db.schemas.contains_key(schema_id) { + return Err(format!( + "Missing Schema: Cannot find schema ID '{}'", + schema_id + )); + } + + let test_data = self.data.clone().unwrap_or(Value::Null); + let result = validator.validate(schema_id, &test_data); + + let got_valid = result.errors.is_empty(); + + if got_valid != expected_success { + let error_msg = if result.errors.is_empty() { + "None".to_string() + } else { + format!("{:?}", result.errors) + }; + + return Err(format!( + "Expected: {}, Got: {}. Errors: {}", + expected_success, got_valid, error_msg + )); + } + + Ok(()) + } + + pub fn run_merge(&self, db: Arc) -> Result<(), String> { + use crate::merger::Merger; + let merger = Merger::new(db.clone()); + + let test_data = self.data.clone().unwrap_or(Value::Null); + let result = merger.merge(test_data); + + let expected_success = self.expect.as_ref().map(|e| e.success).unwrap_or(false); + let got_success = result.errors.is_empty(); + + let error_msg = if result.errors.is_empty() { + "None".to_string() + } else { + format!("{:?}", result.errors) + }; + + let return_val = if expected_success != got_success { + Err(format!( + "Merge Expected: {}, Got: {}. Errors: {}", + expected_success, got_success, error_msg + )) + } else if let Some(expect) = &self.expect { + let queries = db.executor.get_queries(); + expect.assert_sql(&queries) + } else { + Ok(()) + }; + + db.executor.reset_mocks(); + return_val + } + + pub fn run_query(&self, db: Arc) -> Result<(), String> { + use crate::queryer::Queryer; + let queryer = Queryer::new(db.clone()); + + let stem_opt = self.stem.as_deref(); + let result = queryer.query(&self.schema_id, stem_opt, self.filters.as_ref()); + + let expected_success = self.expect.as_ref().map(|e| e.success).unwrap_or(false); + let got_success = result.errors.is_empty(); + + let error_msg = if result.errors.is_empty() { + "None".to_string() + } else { + format!("{:?}", result.errors) + }; + + let return_val = if expected_success != got_success { + Err(format!( + "Query Expected: {}, Got: {}. Errors: {}", + expected_success, got_success, error_msg + )) + } else if let Some(expect) = &self.expect { + let queries = db.executor.get_queries(); + expect.assert_sql(&queries) + } else { + Ok(()) + }; + + db.executor.reset_mocks(); + return_val + } +} diff --git a/src/tests/types/expect.rs b/src/tests/types/expect.rs new file mode 100644 index 0000000..edac9be --- /dev/null +++ b/src/tests/types/expect.rs @@ -0,0 +1,122 @@ +use serde::Deserialize; + +#[derive(Debug, Deserialize)] +pub struct ExpectBlock { + pub success: bool, + pub result: Option, + pub errors: Option>, + #[serde(default)] + pub sql: Option>, +} + +impl ExpectBlock { + /// Advanced SQL execution assertion algorithm ported from `assert.go`. + /// This compares two arrays of strings, one containing {{uuid:name}} or {{timestamp}} placeholders, + /// and the other containing actual executed database queries. It ensures that placeholder UUIDs + /// are consistently mapped to the same actual UUIDs across all lines, and strictly validates line-by-line sequences. + pub fn assert_sql(&self, actual: &[String]) -> Result<(), String> { + let patterns = match &self.sql { + Some(s) => s, + None => return Ok(()), + }; + + if patterns.len() != actual.len() { + return Err(format!( + "Length mismatch: expected {} SQL executions, got {}.\nActual Execution Log:\n{}", + patterns.len(), + actual.len(), + actual.join("\n") + )); + } + + use regex::Regex; + use std::collections::HashMap; + + let types = HashMap::from([ + ( + "uuid", + r"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}", + ), + ( + "timestamp", + r"\d{4}-\d{2}-\d{2}(?:[ T])\d{2}:\d{2}:\d{2}(?:\.\d{1,6})?(?:Z|\+\d{2}(?::\d{2})?)?", + ), + ("integer", r"-?\d+"), + ("float", r"-?\d+\.\d+"), + ("text", r"(?:''|[^'])*"), + ("json", r"(?:''|[^'])*"), + ]); + + let mut seen: HashMap = HashMap::new(); + let system_uuid = "00000000-0000-0000-0000-000000000000"; + + // Placeholder regex: {{type:name}} or {{type}} + let ph_rx = Regex::new(r"\{\{([a-z]+)(?:[:]([^}]+))?\}\}").unwrap(); + + for (i, pattern_str) in patterns.iter().enumerate() { + let aline = &actual[i]; + let mut pp = regex::escape(pattern_str); + pp = pp.replace(r"\{\{", "{{").replace(r"\}\}", "}}"); + + let mut cap_names = HashMap::new(); // cg_X -> var_name + let mut group_idx = 0; + + let mut final_rx_str = String::new(); + let mut last_match = 0; + + let pp_clone = pp.clone(); + for caps in ph_rx.captures_iter(&pp_clone) { + let full_match = caps.get(0).unwrap(); + final_rx_str.push_str(&pp[last_match..full_match.start()]); + + let type_name = caps.get(1).unwrap().as_str(); + let var_name = caps.get(2).map(|m| m.as_str()); + + if let Some(name) = var_name { + if let Some(val) = seen.get(name) { + final_rx_str.push_str(®ex::escape(val)); + } else { + let type_pattern = types.get(type_name).unwrap_or(&".*?"); + let cg_name = format!("cg_{}", group_idx); + final_rx_str.push_str(&format!("(?P<{}>{})", cg_name, type_pattern)); + cap_names.insert(cg_name, name.to_string()); + group_idx += 1; + } + } else { + let type_pattern = types.get(type_name).unwrap_or(&".*?"); + final_rx_str.push_str(&format!("(?:{})", type_pattern)); + } + + last_match = full_match.end(); + } + final_rx_str.push_str(&pp[last_match..]); + + let final_rx = match Regex::new(&format!("^{}$", final_rx_str)) { + Ok(r) => r, + Err(e) => return Err(format!("Bad constructed regex: {} -> {}", final_rx_str, e)), + }; + + if let Some(captures) = final_rx.captures(aline) { + for (cg_name, var_name) in cap_names { + if let Some(m) = captures.name(&cg_name) { + let matched_str = m.as_str(); + if matched_str != system_uuid { + seen.insert(var_name, matched_str.to_string()); + } + } + } + } else { + return Err(format!( + "Line mismatched at execution sequence {}.\nExpected Pattern: {}\nActual SQL: {}\nRegex used: {}\nVariables Mapped: {:?}", + i + 1, + pattern_str, + aline, + final_rx_str, + seen + )); + } + } + + Ok(()) + } +} diff --git a/src/tests/types/mod.rs b/src/tests/types/mod.rs new file mode 100644 index 0000000..9b2513b --- /dev/null +++ b/src/tests/types/mod.rs @@ -0,0 +1,7 @@ +pub mod case; +pub mod expect; +pub mod suite; + +pub use case::TestCase; +pub use expect::ExpectBlock; +pub use suite::TestSuite; diff --git a/src/tests/types/suite.rs b/src/tests/types/suite.rs new file mode 100644 index 0000000..5aaee7b --- /dev/null +++ b/src/tests/types/suite.rs @@ -0,0 +1,10 @@ +use super::case::TestCase; +use serde::Deserialize; + +#[derive(Debug, Deserialize)] +pub struct TestSuite { + #[allow(dead_code)] + pub description: String, + pub database: serde_json::Value, + pub tests: Vec, +} diff --git a/src/validator/mod.rs b/src/validator/mod.rs index 04833a7..6755c89 100644 --- a/src/validator/mod.rs +++ b/src/validator/mod.rs @@ -4,7 +4,6 @@ pub mod context; pub mod error; pub mod result; pub mod rules; -pub mod util; pub use context::ValidationContext; pub use error::ValidationError; @@ -46,11 +45,7 @@ impl Validator { } } - pub fn validate( - &self, - schema_id: &str, - instance: &Value, - ) -> Result { + pub fn validate(&self, schema_id: &str, instance: &Value) -> crate::drop::Drop { if let Some(schema) = self.db.schemas.get(schema_id) { let ctx = ValidationContext::new( &self.db, @@ -61,13 +56,37 @@ impl Validator { false, false, ); - ctx.validate_scoped() + match ctx.validate_scoped() { + Ok(result) => { + if result.is_valid() { + crate::drop::Drop::success() + } else { + let errors: Vec = result + .errors + .into_iter() + .map(|e| crate::drop::Error { + code: e.code, + message: e.message, + details: crate::drop::ErrorDetails { path: e.path }, + }) + .collect(); + crate::drop::Drop::with_errors(errors) + } + } + Err(e) => crate::drop::Drop::with_errors(vec![crate::drop::Error { + code: e.code, + message: e.message, + details: crate::drop::ErrorDetails { path: e.path }, + }]), + } } else { - Err(ValidationError { + crate::drop::Drop::with_errors(vec![crate::drop::Error { code: "SCHEMA_NOT_FOUND".to_string(), message: format!("Schema {} not found", schema_id), - path: "".to_string(), - }) + details: crate::drop::ErrorDetails { + path: "".to_string(), + }, + }]) } } } diff --git a/src/validator/util.rs b/src/validator/util.rs deleted file mode 100644 index 656e87c..0000000 --- a/src/validator/util.rs +++ /dev/null @@ -1,127 +0,0 @@ -use serde::Deserialize; -use std::fs; - -#[derive(Debug, Deserialize)] -struct TestSuite { - #[allow(dead_code)] - description: String, - database: serde_json::Value, - tests: Vec, -} - -#[derive(Debug, Deserialize)] -pub struct TestCase { - pub description: String, - - #[serde(default = "default_action")] - pub action: String, // "validate", "merge", or "query" - - // For Validate & Query - #[serde(default)] - pub schema_id: String, - - // For Query - #[serde(default)] - pub stem: Option, - - #[serde(default)] - pub filters: Option, - - // For Merge & Validate - #[serde(default)] - pub data: Option, - - // For Merge & Query mocks - #[serde(default)] - pub mocks: Option, - - pub expect: Option, - - // Legacy support for older tests to avoid migrating them all instantly - pub valid: Option, - pub expect_errors: Option>, -} - -fn default_action() -> String { - "validate".to_string() -} - -#[derive(Debug, Deserialize)] -pub struct ExpectBlock { - pub success: bool, - pub result: Option, - pub errors: Option>, - pub sql_patterns: Option>, -} - -// use crate::validator::registry::REGISTRY; // No longer used directly for tests! -use crate::validator::Validator; -use serde_json::Value; - -pub fn deserialize_some<'de, D>(deserializer: D) -> Result, D::Error> -where - D: serde::Deserializer<'de>, -{ - let v = Value::deserialize(deserializer)?; - Ok(Some(v)) -} - -pub fn run_test_file_at_index(path: &str, index: usize) -> Result<(), String> { - let content = - fs::read_to_string(path).unwrap_or_else(|_| panic!("Failed to read file: {}", path)); - let suite: Vec = serde_json::from_str(&content) - .unwrap_or_else(|e| panic!("Failed to parse JSON in {}: {}", path, e)); - - if index >= suite.len() { - panic!("Index {} out of bounds for file {}", index, path); - } - - let group = &suite[index]; - let mut failures = Vec::::new(); - - let db_json = group.database.clone(); - let db = crate::database::Database::new(&db_json); - let validator = Validator::new(std::sync::Arc::new(db)); - - // 4. Run Tests - for test in group.tests.iter() { - let schema_id = &test.schema_id; - - if !validator.db.schemas.contains_key(schema_id) { - failures.push(format!( - "[{}] Missing Schema: Cannot find schema ID '{}'", - group.description, schema_id - )); - continue; - } - - 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![]) - } - }; - - 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 - )); - } - } - - if !failures.is_empty() { - return Err(failures.join("\n")); - } - - Ok(()) -} diff --git a/tests/database/mod.rs b/tests/database/mod.rs deleted file mode 100644 index 0c95fda..0000000 --- a/tests/database/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod executor; diff --git a/tests/fixtures.rs b/tests/fixtures.rs deleted file mode 100644 index a76c7b0..0000000 --- a/tests/fixtures.rs +++ /dev/null @@ -1,1669 +0,0 @@ -use jspg::validator::util; - -#[test] -fn test_content_0() { - let path = format!("{}/tests/fixtures/content.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_content_1() { - let path = format!("{}/tests/fixtures/content.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_content_2() { - let path = format!("{}/tests/fixtures/content.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_content_3() { - let path = format!("{}/tests/fixtures/content.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 3).unwrap(); -} - -#[test] -fn test_unique_items_0() { - let path = format!("{}/tests/fixtures/uniqueItems.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_unique_items_1() { - let path = format!("{}/tests/fixtures/uniqueItems.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_unique_items_2() { - let path = format!("{}/tests/fixtures/uniqueItems.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_unique_items_3() { - let path = format!("{}/tests/fixtures/uniqueItems.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 3).unwrap(); -} - -#[test] -fn test_unique_items_4() { - let path = format!("{}/tests/fixtures/uniqueItems.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 4).unwrap(); -} - -#[test] -fn test_unique_items_5() { - let path = format!("{}/tests/fixtures/uniqueItems.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 5).unwrap(); -} - -#[test] -fn test_unique_items_6() { - let path = format!("{}/tests/fixtures/uniqueItems.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 6).unwrap(); -} - -#[test] -fn test_min_items_0() { - let path = format!("{}/tests/fixtures/minItems.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_min_items_1() { - let path = format!("{}/tests/fixtures/minItems.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_min_items_2() { - let path = format!("{}/tests/fixtures/minItems.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_additional_properties_0() { - let path = format!("{}/tests/fixtures/additionalProperties.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_additional_properties_1() { - let path = format!("{}/tests/fixtures/additionalProperties.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_additional_properties_2() { - let path = format!("{}/tests/fixtures/additionalProperties.json", env!("CARGO_MANIFEST_DIR")); - 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")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_const_0() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_const_1() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_const_2() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_const_3() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 3).unwrap(); -} - -#[test] -fn test_const_4() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 4).unwrap(); -} - -#[test] -fn test_const_5() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 5).unwrap(); -} - -#[test] -fn test_const_6() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 6).unwrap(); -} - -#[test] -fn test_const_7() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 7).unwrap(); -} - -#[test] -fn test_const_8() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 8).unwrap(); -} - -#[test] -fn test_const_9() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 9).unwrap(); -} - -#[test] -fn test_const_10() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 10).unwrap(); -} - -#[test] -fn test_const_11() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 11).unwrap(); -} - -#[test] -fn test_const_12() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 12).unwrap(); -} - -#[test] -fn test_const_13() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 13).unwrap(); -} - -#[test] -fn test_const_14() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 14).unwrap(); -} - -#[test] -fn test_const_15() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 15).unwrap(); -} - -#[test] -fn test_const_16() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 16).unwrap(); -} - -#[test] -fn test_const_17() { - let path = format!("{}/tests/fixtures/const.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 17).unwrap(); -} - -#[test] -fn test_families_0() { - let path = format!("{}/tests/fixtures/families.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_families_1() { - let path = format!("{}/tests/fixtures/families.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_property_names_0() { - let path = format!("{}/tests/fixtures/propertyNames.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_property_names_1() { - let path = format!("{}/tests/fixtures/propertyNames.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_property_names_2() { - let path = format!("{}/tests/fixtures/propertyNames.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_property_names_3() { - let path = format!("{}/tests/fixtures/propertyNames.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 3).unwrap(); -} - -#[test] -fn test_property_names_4() { - let path = format!("{}/tests/fixtures/propertyNames.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 4).unwrap(); -} - -#[test] -fn test_property_names_5() { - let path = format!("{}/tests/fixtures/propertyNames.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 5).unwrap(); -} - -#[test] -fn test_property_names_6() { - let path = format!("{}/tests/fixtures/propertyNames.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 6).unwrap(); -} - -#[test] -fn test_not_0() { - let path = format!("{}/tests/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_not_1() { - let path = format!("{}/tests/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_not_2() { - let path = format!("{}/tests/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_not_3() { - let path = format!("{}/tests/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 3).unwrap(); -} - -#[test] -fn test_not_4() { - let path = format!("{}/tests/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 4).unwrap(); -} - -#[test] -fn test_not_5() { - let path = format!("{}/tests/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 5).unwrap(); -} - -#[test] -fn test_not_6() { - let path = format!("{}/tests/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 6).unwrap(); -} - -#[test] -fn test_not_7() { - let path = format!("{}/tests/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 7).unwrap(); -} - -#[test] -fn test_not_8() { - let path = format!("{}/tests/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 8).unwrap(); -} - -#[test] -fn test_not_9() { - let path = format!("{}/tests/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 9).unwrap(); -} - -#[test] -fn test_not_10() { - let path = format!("{}/tests/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 10).unwrap(); -} - -#[test] -fn test_not_11() { - let path = format!("{}/tests/fixtures/not.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 11).unwrap(); -} - -#[test] -fn test_items_0() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_items_1() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_items_2() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_items_3() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 3).unwrap(); -} - -#[test] -fn test_items_4() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 4).unwrap(); -} - -#[test] -fn test_items_5() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 5).unwrap(); -} - -#[test] -fn test_items_6() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 6).unwrap(); -} - -#[test] -fn test_items_7() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 7).unwrap(); -} - -#[test] -fn test_items_8() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 8).unwrap(); -} - -#[test] -fn test_items_9() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 9).unwrap(); -} - -#[test] -fn test_items_10() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 10).unwrap(); -} - -#[test] -fn test_items_11() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 11).unwrap(); -} - -#[test] -fn test_items_12() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 12).unwrap(); -} - -#[test] -fn test_items_13() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 13).unwrap(); -} - -#[test] -fn test_items_14() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 14).unwrap(); -} - -#[test] -fn test_items_15() { - let path = format!("{}/tests/fixtures/items.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 15).unwrap(); -} - -#[test] -fn test_enum_0() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_enum_1() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_enum_2() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_enum_3() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 3).unwrap(); -} - -#[test] -fn test_enum_4() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 4).unwrap(); -} - -#[test] -fn test_enum_5() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 5).unwrap(); -} - -#[test] -fn test_enum_6() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 6).unwrap(); -} - -#[test] -fn test_enum_7() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 7).unwrap(); -} - -#[test] -fn test_enum_8() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 8).unwrap(); -} - -#[test] -fn test_enum_9() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 9).unwrap(); -} - -#[test] -fn test_enum_10() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 10).unwrap(); -} - -#[test] -fn test_enum_11() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 11).unwrap(); -} - -#[test] -fn test_enum_12() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 12).unwrap(); -} - -#[test] -fn test_enum_13() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 13).unwrap(); -} - -#[test] -fn test_enum_14() { - let path = format!("{}/tests/fixtures/enum.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 14).unwrap(); -} - -#[test] -fn test_min_properties_0() { - let path = format!("{}/tests/fixtures/minProperties.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_min_properties_1() { - let path = format!("{}/tests/fixtures/minProperties.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_min_properties_2() { - let path = format!("{}/tests/fixtures/minProperties.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_min_contains_0() { - let path = format!("{}/tests/fixtures/minContains.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_min_contains_1() { - let path = format!("{}/tests/fixtures/minContains.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_min_contains_2() { - let path = format!("{}/tests/fixtures/minContains.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_min_contains_3() { - let path = format!("{}/tests/fixtures/minContains.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 3).unwrap(); -} - -#[test] -fn test_min_contains_4() { - let path = format!("{}/tests/fixtures/minContains.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 4).unwrap(); -} - -#[test] -fn test_min_contains_5() { - let path = format!("{}/tests/fixtures/minContains.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 5).unwrap(); -} - -#[test] -fn test_min_contains_6() { - let path = format!("{}/tests/fixtures/minContains.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 6).unwrap(); -} - -#[test] -fn test_min_contains_7() { - let path = format!("{}/tests/fixtures/minContains.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 7).unwrap(); -} - -#[test] -fn test_min_contains_8() { - let path = format!("{}/tests/fixtures/minContains.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 8).unwrap(); -} - -#[test] -fn test_properties_0() { - let path = format!("{}/tests/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_properties_1() { - let path = format!("{}/tests/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_properties_2() { - let path = format!("{}/tests/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_properties_3() { - let path = format!("{}/tests/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 3).unwrap(); -} - -#[test] -fn test_properties_4() { - let path = format!("{}/tests/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 4).unwrap(); -} - -#[test] -fn test_properties_5() { - let path = format!("{}/tests/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 5).unwrap(); -} - -#[test] -fn test_properties_6() { - let path = format!("{}/tests/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 6).unwrap(); -} - -#[test] -fn test_properties_7() { - let path = format!("{}/tests/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 7).unwrap(); -} - -#[test] -fn test_properties_8() { - let path = format!("{}/tests/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 8).unwrap(); -} - -#[test] -fn test_properties_9() { - let path = format!("{}/tests/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 9).unwrap(); -} - -#[test] -fn test_properties_10() { - let path = format!("{}/tests/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 10).unwrap(); -} - -#[test] -fn test_properties_11() { - let path = format!("{}/tests/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 11).unwrap(); -} - -#[test] -fn test_properties_12() { - let path = format!("{}/tests/fixtures/properties.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 12).unwrap(); -} - -#[test] -fn test_max_contains_0() { - let path = format!("{}/tests/fixtures/maxContains.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_max_contains_1() { - let path = format!("{}/tests/fixtures/maxContains.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_max_contains_2() { - let path = format!("{}/tests/fixtures/maxContains.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_max_contains_3() { - let path = format!("{}/tests/fixtures/maxContains.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 3).unwrap(); -} - -#[test] -fn test_max_contains_4() { - let path = format!("{}/tests/fixtures/maxContains.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 4).unwrap(); -} - -#[test] -fn test_max_length_0() { - let path = format!("{}/tests/fixtures/maxLength.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_max_length_1() { - let path = format!("{}/tests/fixtures/maxLength.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_exclusive_maximum_0() { - let path = format!("{}/tests/fixtures/exclusiveMaximum.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_prefix_items_0() { - let path = format!("{}/tests/fixtures/prefixItems.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_prefix_items_1() { - let path = format!("{}/tests/fixtures/prefixItems.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_prefix_items_2() { - let path = format!("{}/tests/fixtures/prefixItems.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_prefix_items_3() { - let path = format!("{}/tests/fixtures/prefixItems.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 3).unwrap(); -} - -#[test] -fn test_prefix_items_4() { - let path = format!("{}/tests/fixtures/prefixItems.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 4).unwrap(); -} - -#[test] -fn test_minimum_0() { - let path = format!("{}/tests/fixtures/minimum.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_minimum_1() { - let path = format!("{}/tests/fixtures/minimum.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_one_of_0() { - let path = format!("{}/tests/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_one_of_1() { - let path = format!("{}/tests/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_one_of_2() { - let path = format!("{}/tests/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_one_of_3() { - let path = format!("{}/tests/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 3).unwrap(); -} - -#[test] -fn test_one_of_4() { - let path = format!("{}/tests/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 4).unwrap(); -} - -#[test] -fn test_one_of_5() { - let path = format!("{}/tests/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 5).unwrap(); -} - -#[test] -fn test_one_of_6() { - let path = format!("{}/tests/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 6).unwrap(); -} - -#[test] -fn test_one_of_7() { - let path = format!("{}/tests/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 7).unwrap(); -} - -#[test] -fn test_one_of_8() { - let path = format!("{}/tests/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 8).unwrap(); -} - -#[test] -fn test_one_of_9() { - let path = format!("{}/tests/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 9).unwrap(); -} - -#[test] -fn test_one_of_10() { - let path = format!("{}/tests/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 10).unwrap(); -} - -#[test] -fn test_one_of_11() { - let path = format!("{}/tests/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 11).unwrap(); -} - -#[test] -fn test_one_of_12() { - let path = format!("{}/tests/fixtures/oneOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 12).unwrap(); -} - -#[test] -fn test_boolean_schema_0() { - let path = format!("{}/tests/fixtures/booleanSchema.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_boolean_schema_1() { - let path = format!("{}/tests/fixtures/booleanSchema.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_if_then_else_0() { - let path = format!("{}/tests/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_if_then_else_1() { - let path = format!("{}/tests/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_if_then_else_2() { - let path = format!("{}/tests/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_if_then_else_3() { - let path = format!("{}/tests/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 3).unwrap(); -} - -#[test] -fn test_if_then_else_4() { - let path = format!("{}/tests/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 4).unwrap(); -} - -#[test] -fn test_if_then_else_5() { - let path = format!("{}/tests/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 5).unwrap(); -} - -#[test] -fn test_if_then_else_6() { - let path = format!("{}/tests/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 6).unwrap(); -} - -#[test] -fn test_if_then_else_7() { - let path = format!("{}/tests/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 7).unwrap(); -} - -#[test] -fn test_if_then_else_8() { - let path = format!("{}/tests/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 8).unwrap(); -} - -#[test] -fn test_if_then_else_9() { - let path = format!("{}/tests/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 9).unwrap(); -} - -#[test] -fn test_if_then_else_10() { - let path = format!("{}/tests/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 10).unwrap(); -} - -#[test] -fn test_if_then_else_11() { - let path = format!("{}/tests/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 11).unwrap(); -} - -#[test] -fn test_if_then_else_12() { - let path = format!("{}/tests/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 12).unwrap(); -} - -#[test] -fn test_if_then_else_13() { - let path = format!("{}/tests/fixtures/if-then-else.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 13).unwrap(); -} - -#[test] -fn test_empty_string_0() { - let path = format!("{}/tests/fixtures/emptyString.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_pattern_0() { - let path = format!("{}/tests/fixtures/pattern.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_pattern_1() { - let path = format!("{}/tests/fixtures/pattern.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_max_properties_0() { - let path = format!("{}/tests/fixtures/maxProperties.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_max_properties_1() { - let path = format!("{}/tests/fixtures/maxProperties.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_max_properties_2() { - let path = format!("{}/tests/fixtures/maxProperties.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_max_properties_3() { - let path = format!("{}/tests/fixtures/maxProperties.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 3).unwrap(); -} - -#[test] -fn test_required_0() { - let path = format!("{}/tests/fixtures/required.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_required_1() { - let path = format!("{}/tests/fixtures/required.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_required_2() { - let path = format!("{}/tests/fixtures/required.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_required_3() { - let path = format!("{}/tests/fixtures/required.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 3).unwrap(); -} - -#[test] -fn test_required_4() { - let path = format!("{}/tests/fixtures/required.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 4).unwrap(); -} - -#[test] -fn test_required_5() { - let path = format!("{}/tests/fixtures/required.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 5).unwrap(); -} - -#[test] -fn test_type_0() { - let path = format!("{}/tests/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_type_1() { - let path = format!("{}/tests/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_type_2() { - let path = format!("{}/tests/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_type_3() { - let path = format!("{}/tests/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 3).unwrap(); -} - -#[test] -fn test_type_4() { - let path = format!("{}/tests/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 4).unwrap(); -} - -#[test] -fn test_type_5() { - let path = format!("{}/tests/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 5).unwrap(); -} - -#[test] -fn test_type_6() { - let path = format!("{}/tests/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 6).unwrap(); -} - -#[test] -fn test_type_7() { - let path = format!("{}/tests/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 7).unwrap(); -} - -#[test] -fn test_type_8() { - let path = format!("{}/tests/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 8).unwrap(); -} - -#[test] -fn test_type_9() { - let path = format!("{}/tests/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 9).unwrap(); -} - -#[test] -fn test_type_10() { - let path = format!("{}/tests/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 10).unwrap(); -} - -#[test] -fn test_type_11() { - let path = format!("{}/tests/fixtures/type.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 11).unwrap(); -} - -#[test] -fn test_multiple_of_0() { - let path = format!("{}/tests/fixtures/multipleOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_multiple_of_1() { - let path = format!("{}/tests/fixtures/multipleOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_multiple_of_2() { - let path = format!("{}/tests/fixtures/multipleOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_multiple_of_3() { - let path = format!("{}/tests/fixtures/multipleOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 3).unwrap(); -} - -#[test] -fn test_pattern_properties_0() { - let path = format!("{}/tests/fixtures/patternProperties.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_pattern_properties_1() { - let path = format!("{}/tests/fixtures/patternProperties.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_pattern_properties_2() { - let path = format!("{}/tests/fixtures/patternProperties.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_pattern_properties_3() { - let path = format!("{}/tests/fixtures/patternProperties.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 3).unwrap(); -} - -#[test] -fn test_pattern_properties_4() { - let path = format!("{}/tests/fixtures/patternProperties.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 4).unwrap(); -} - -#[test] -fn test_pattern_properties_5() { - let path = format!("{}/tests/fixtures/patternProperties.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 5).unwrap(); -} - -#[test] -fn test_merge_0() { - let path = format!("{}/tests/fixtures/merge.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_merge_1() { - let path = format!("{}/tests/fixtures/merge.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_merge_2() { - let path = format!("{}/tests/fixtures/merge.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_merge_3() { - let path = format!("{}/tests/fixtures/merge.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 3).unwrap(); -} - -#[test] -fn test_all_of_0() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_all_of_1() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_all_of_2() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_all_of_3() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 3).unwrap(); -} - -#[test] -fn test_all_of_4() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 4).unwrap(); -} - -#[test] -fn test_all_of_5() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 5).unwrap(); -} - -#[test] -fn test_all_of_6() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 6).unwrap(); -} - -#[test] -fn test_all_of_7() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 7).unwrap(); -} - -#[test] -fn test_all_of_8() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 8).unwrap(); -} - -#[test] -fn test_all_of_9() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 9).unwrap(); -} - -#[test] -fn test_all_of_10() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 10).unwrap(); -} - -#[test] -fn test_all_of_11() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 11).unwrap(); -} - -#[test] -fn test_all_of_12() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 12).unwrap(); -} - -#[test] -fn test_all_of_13() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 13).unwrap(); -} - -#[test] -fn test_all_of_14() { - let path = format!("{}/tests/fixtures/allOf.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 14).unwrap(); -} - -#[test] -fn test_format_0() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_format_1() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_format_2() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_format_3() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 3).unwrap(); -} - -#[test] -fn test_format_4() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 4).unwrap(); -} - -#[test] -fn test_format_5() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 5).unwrap(); -} - -#[test] -fn test_format_6() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 6).unwrap(); -} - -#[test] -fn test_format_7() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 7).unwrap(); -} - -#[test] -fn test_format_8() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 8).unwrap(); -} - -#[test] -fn test_format_9() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 9).unwrap(); -} - -#[test] -fn test_format_10() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 10).unwrap(); -} - -#[test] -fn test_format_11() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 11).unwrap(); -} - -#[test] -fn test_format_12() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 12).unwrap(); -} - -#[test] -fn test_format_13() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 13).unwrap(); -} - -#[test] -fn test_format_14() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 14).unwrap(); -} - -#[test] -fn test_format_15() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 15).unwrap(); -} - -#[test] -fn test_format_16() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 16).unwrap(); -} - -#[test] -fn test_format_17() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 17).unwrap(); -} - -#[test] -fn test_format_18() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 18).unwrap(); -} - -#[test] -fn test_format_19() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 19).unwrap(); -} - -#[test] -fn test_format_20() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 20).unwrap(); -} - -#[test] -fn test_format_21() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 21).unwrap(); -} - -#[test] -fn test_format_22() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 22).unwrap(); -} - -#[test] -fn test_format_23() { - let path = format!("{}/tests/fixtures/format.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 23).unwrap(); -} - -#[test] -fn test_ref_0() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_ref_1() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_ref_2() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_ref_3() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 3).unwrap(); -} - -#[test] -fn test_ref_4() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 4).unwrap(); -} - -#[test] -fn test_ref_5() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 5).unwrap(); -} - -#[test] -fn test_ref_6() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 6).unwrap(); -} - -#[test] -fn test_ref_7() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 7).unwrap(); -} - -#[test] -fn test_ref_8() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 8).unwrap(); -} - -#[test] -fn test_ref_9() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 9).unwrap(); -} - -#[test] -fn test_ref_10() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 10).unwrap(); -} - -#[test] -fn test_ref_11() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 11).unwrap(); -} - -#[test] -fn test_ref_12() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 12).unwrap(); -} - -#[test] -fn test_ref_13() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 13).unwrap(); -} - -#[test] -fn test_ref_14() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 14).unwrap(); -} - -#[test] -fn test_ref_15() { - let path = format!("{}/tests/fixtures/ref.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 15).unwrap(); -} - -#[test] -fn test_maximum_0() { - let path = format!("{}/tests/fixtures/maximum.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_maximum_1() { - let path = format!("{}/tests/fixtures/maximum.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_min_length_0() { - let path = format!("{}/tests/fixtures/minLength.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_min_length_1() { - let path = format!("{}/tests/fixtures/minLength.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_max_items_0() { - let path = format!("{}/tests/fixtures/maxItems.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_max_items_1() { - let path = format!("{}/tests/fixtures/maxItems.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_max_items_2() { - let path = format!("{}/tests/fixtures/maxItems.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_contains_0() { - let path = format!("{}/tests/fixtures/contains.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 0).unwrap(); -} - -#[test] -fn test_contains_1() { - let path = format!("{}/tests/fixtures/contains.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 1).unwrap(); -} - -#[test] -fn test_contains_2() { - let path = format!("{}/tests/fixtures/contains.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 2).unwrap(); -} - -#[test] -fn test_contains_3() { - let path = format!("{}/tests/fixtures/contains.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 3).unwrap(); -} - -#[test] -fn test_contains_4() { - let path = format!("{}/tests/fixtures/contains.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 4).unwrap(); -} - -#[test] -fn test_contains_5() { - let path = format!("{}/tests/fixtures/contains.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 5).unwrap(); -} - -#[test] -fn test_contains_6() { - let path = format!("{}/tests/fixtures/contains.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 6).unwrap(); -} - -#[test] -fn test_contains_7() { - let path = format!("{}/tests/fixtures/contains.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 7).unwrap(); -} - -#[test] -fn test_contains_8() { - let path = format!("{}/tests/fixtures/contains.json", env!("CARGO_MANIFEST_DIR")); - util::run_test_file_at_index(&path, 8).unwrap(); -} diff --git a/tests/fixtures/additionalProperties.json b/tests/fixtures/additionalProperties.json deleted file mode 100644 index 08b15fe..0000000 --- a/tests/fixtures/additionalProperties.json +++ /dev/null @@ -1,152 +0,0 @@ -[ - { - "description": "additionalProperties validates properties not matched by properties", - "database": { - "schemas": [ - { - "$id": "schema1", - "properties": { - "foo": { - "type": "string" - }, - "bar": { - "type": "number" - } - }, - "additionalProperties": { - "type": "boolean" - } - } - ] - }, - "tests": [ - { - "description": "defined properties are valid", - "data": { - "foo": "value", - "bar": 123 - }, - "valid": true, - "schema_id": "schema1" - }, - { - "description": "additional property matching schema is valid", - "data": { - "foo": "value", - "is_active": true, - "hidden": false - }, - "valid": true, - "schema_id": "schema1" - }, - { - "description": "additional property not matching schema is invalid", - "data": { - "foo": "value", - "is_active": 1 - }, - "valid": false, - "schema_id": "schema1" - } - ] - }, - { - "description": "extensible: true with additionalProperties still validates structure", - "database": { - "schemas": [ - { - "properties": { - "foo": { - "type": "string" - } - }, - "extensible": true, - "additionalProperties": { - "type": "integer" - }, - "$id": "additionalProperties_1_0" - } - ] - }, - "tests": [ - { - "description": "additional property matching schema is valid", - "data": { - "foo": "hello", - "count": 5, - "age": 42 - }, - "valid": true, - "schema_id": "additionalProperties_1_0" - }, - { - "description": "additional property not matching schema is invalid despite extensible: true", - "data": { - "foo": "hello", - "count": "five" - }, - "valid": false, - "schema_id": "additionalProperties_1_0" - } - ] - }, - { - "description": "complex additionalProperties with object and array items", - "database": { - "schemas": [ - { - "$id": "schema3", - "properties": { - "type": { - "type": "string" - } - }, - "additionalProperties": { - "type": "array", - "items": { - "type": "string" - } - } - } - ] - }, - "tests": [ - { - "description": "valid array of strings", - "data": { - "type": "my_type", - "group_a": [ - "field1", - "field2" - ], - "group_b": [ - "field3" - ] - }, - "valid": true, - "schema_id": "schema3" - }, - { - "description": "invalid array of integers", - "data": { - "type": "my_type", - "group_a": [ - 1, - 2 - ] - }, - "valid": false, - "schema_id": "schema3" - }, - { - "description": "invalid non-array type", - "data": { - "type": "my_type", - "group_a": "field1" - }, - "valid": false, - "schema_id": "schema3" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/allOf.json b/tests/fixtures/allOf.json deleted file mode 100644 index 0d08c85..0000000 --- a/tests/fixtures/allOf.json +++ /dev/null @@ -1,590 +0,0 @@ -[ - { - "description": "allOf", - "database": { - "schemas": [ - { - "allOf": [ - { - "properties": { - "bar": { - "type": "integer" - } - }, - "required": [ - "bar" - ] - }, - { - "properties": { - "foo": { - "type": "string" - } - }, - "required": [ - "foo" - ] - } - ], - "$id": "allOf_0_0" - } - ] - }, - "tests": [ - { - "description": "allOf", - "data": { - "foo": "baz", - "bar": 2 - }, - "valid": true, - "schema_id": "allOf_0_0" - }, - { - "description": "mismatch second", - "data": { - "foo": "baz" - }, - "valid": false, - "schema_id": "allOf_0_0" - }, - { - "description": "mismatch first", - "data": { - "bar": 2 - }, - "valid": false, - "schema_id": "allOf_0_0" - }, - { - "description": "wrong type", - "data": { - "foo": "baz", - "bar": "quux" - }, - "valid": false, - "schema_id": "allOf_0_0" - } - ] - }, - { - "description": "allOf with base schema", - "database": { - "schemas": [ - { - "properties": { - "bar": { - "type": "integer" - }, - "baz": {}, - "foo": { - "type": "string" - } - }, - "required": [ - "bar" - ], - "allOf": [ - { - "properties": { - "foo": { - "type": "string" - } - }, - "required": [ - "foo" - ] - }, - { - "properties": { - "baz": { - "type": "null" - } - }, - "required": [ - "baz" - ] - } - ], - "$id": "allOf_1_0" - } - ] - }, - "tests": [ - { - "description": "valid", - "data": { - "foo": "quux", - "bar": 2, - "baz": null - }, - "valid": true, - "schema_id": "allOf_1_0" - }, - { - "description": "mismatch base schema", - "data": { - "foo": "quux", - "baz": null - }, - "valid": false, - "schema_id": "allOf_1_0" - }, - { - "description": "mismatch first allOf", - "data": { - "bar": 2, - "baz": null - }, - "valid": false, - "schema_id": "allOf_1_0" - }, - { - "description": "mismatch second allOf", - "data": { - "foo": "quux", - "bar": 2 - }, - "valid": false, - "schema_id": "allOf_1_0" - }, - { - "description": "mismatch both", - "data": { - "bar": 2 - }, - "valid": false, - "schema_id": "allOf_1_0" - } - ] - }, - { - "description": "allOf simple types", - "database": { - "schemas": [ - { - "allOf": [ - { - "maximum": 30 - }, - { - "minimum": 20 - } - ], - "$id": "allOf_2_0" - } - ] - }, - "tests": [ - { - "description": "valid", - "data": 25, - "valid": true, - "schema_id": "allOf_2_0" - }, - { - "description": "mismatch one", - "data": 35, - "valid": false, - "schema_id": "allOf_2_0" - } - ] - }, - { - "description": "allOf with boolean schemas, all true", - "database": { - "schemas": [ - { - "allOf": [ - true, - true - ], - "$id": "allOf_3_0" - } - ] - }, - "tests": [ - { - "description": "any value is valid", - "data": "foo", - "valid": true, - "schema_id": "allOf_3_0" - } - ] - }, - { - "description": "allOf with boolean schemas, some false", - "database": { - "schemas": [ - { - "allOf": [ - true, - false - ], - "$id": "allOf_4_0" - } - ] - }, - "tests": [ - { - "description": "any value is invalid", - "data": "foo", - "valid": false, - "schema_id": "allOf_4_0" - } - ] - }, - { - "description": "allOf with boolean schemas, all false", - "database": { - "schemas": [ - { - "allOf": [ - false, - false - ], - "$id": "allOf_5_0" - } - ] - }, - "tests": [ - { - "description": "any value is invalid", - "data": "foo", - "valid": false, - "schema_id": "allOf_5_0" - } - ] - }, - { - "description": "allOf with one empty schema", - "database": { - "schemas": [ - { - "allOf": [ - {} - ], - "$id": "allOf_6_0" - } - ] - }, - "tests": [ - { - "description": "any data is valid", - "data": 1, - "valid": true, - "schema_id": "allOf_6_0" - } - ] - }, - { - "description": "allOf with two empty schemas", - "database": { - "schemas": [ - { - "allOf": [ - {}, - {} - ], - "$id": "allOf_7_0" - } - ] - }, - "tests": [ - { - "description": "any data is valid", - "data": 1, - "valid": true, - "schema_id": "allOf_7_0" - } - ] - }, - { - "description": "allOf with the first empty schema", - "database": { - "schemas": [ - { - "allOf": [ - {}, - { - "type": "number" - } - ], - "$id": "allOf_8_0" - } - ] - }, - "tests": [ - { - "description": "number is valid", - "data": 1, - "valid": true, - "schema_id": "allOf_8_0" - }, - { - "description": "string is invalid", - "data": "foo", - "valid": false, - "schema_id": "allOf_8_0" - } - ] - }, - { - "description": "allOf with the last empty schema", - "database": { - "schemas": [ - { - "allOf": [ - { - "type": "number" - }, - {} - ], - "$id": "allOf_9_0" - } - ] - }, - "tests": [ - { - "description": "number is valid", - "data": 1, - "valid": true, - "schema_id": "allOf_9_0" - }, - { - "description": "string is invalid", - "data": "foo", - "valid": false, - "schema_id": "allOf_9_0" - } - ] - }, - { - "description": "nested allOf, to check validation semantics", - "database": { - "schemas": [ - { - "allOf": [ - { - "allOf": [ - { - "type": "null" - } - ] - } - ], - "$id": "allOf_10_0" - } - ] - }, - "tests": [ - { - "description": "null is valid", - "data": null, - "valid": true, - "schema_id": "allOf_10_0" - }, - { - "description": "anything non-null is invalid", - "data": 123, - "valid": false, - "schema_id": "allOf_10_0" - } - ] - }, - { - "description": "extensible: true allows extra properties in allOf", - "database": { - "schemas": [ - { - "allOf": [ - { - "properties": { - "bar": { - "type": "integer" - } - }, - "required": [ - "bar" - ] - }, - { - "properties": { - "foo": { - "type": "string" - } - }, - "required": [ - "foo" - ] - } - ], - "extensible": true, - "$id": "allOf_12_0" - } - ] - }, - "tests": [ - { - "description": "extra property is valid", - "data": { - "foo": "baz", - "bar": 2, - "qux": 3 - }, - "valid": true, - "schema_id": "allOf_12_0" - } - ] - }, - { - "description": "strict by default with allOf properties", - "database": { - "schemas": [ - { - "allOf": [ - { - "properties": { - "foo": { - "const": 1 - } - } - }, - { - "properties": { - "bar": { - "const": 2 - } - } - } - ], - "$id": "allOf_13_0" - } - ] - }, - "tests": [ - { - "description": "validates merged properties", - "data": { - "foo": 1, - "bar": 2 - }, - "valid": true, - "schema_id": "allOf_13_0" - }, - { - "description": "fails on extra property z explicitly", - "data": { - "foo": 1, - "bar": 2, - "z": 3 - }, - "valid": false, - "schema_id": "allOf_13_0" - } - ] - }, - { - "description": "allOf with nested extensible: true (partial looseness)", - "database": { - "schemas": [ - { - "allOf": [ - { - "properties": { - "foo": { - "const": 1 - } - } - }, - { - "extensible": true, - "properties": { - "bar": { - "const": 2 - } - } - } - ], - "$id": "allOf_14_0" - } - ] - }, - "tests": [ - { - "description": "extensible subschema doesn't make root extensible if root is strict", - "data": { - "foo": 1, - "bar": 2, - "z": 3 - }, - "valid": true, - "schema_id": "allOf_14_0" - } - ] - }, - { - "description": "strictness: allOf composition with strict refs", - "database": { - "schemas": [ - { - "allOf": [ - { - "$ref": "partA" - }, - { - "$ref": "partB" - } - ], - "$id": "allOf_15_0" - }, - { - "$id": "partA", - "properties": { - "id": { - "type": "string" - } - } - }, - { - "$id": "partB", - "properties": { - "name": { - "type": "string" - } - } - } - ] - }, - "tests": [ - { - "description": "merged instance is valid", - "data": { - "id": "1", - "name": "Me" - }, - "valid": true, - "schema_id": "allOf_15_0" - }, - { - "description": "extra property is invalid (root is strict)", - "data": { - "id": "1", - "name": "Me", - "extra": 1 - }, - "valid": false, - "schema_id": "allOf_15_0" - }, - { - "description": "partA mismatch is invalid", - "data": { - "id": 1, - "name": "Me" - }, - "valid": false, - "schema_id": "allOf_15_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/booleanSchema.json b/tests/fixtures/booleanSchema.json deleted file mode 100644 index e526c81..0000000 --- a/tests/fixtures/booleanSchema.json +++ /dev/null @@ -1,143 +0,0 @@ -[ - { - "description": "boolean schema 'true'", - "database": { - "schemas": [ - { - "$id": "booleanSchema_0_0" - } - ] - }, - "tests": [ - { - "description": "number is valid", - "data": 1, - "valid": true, - "schema_id": "booleanSchema_0_0" - }, - { - "description": "string is valid", - "data": "foo", - "valid": true, - "schema_id": "booleanSchema_0_0" - }, - { - "description": "boolean true is valid", - "data": true, - "valid": true, - "schema_id": "booleanSchema_0_0" - }, - { - "description": "boolean false is valid", - "data": false, - "valid": true, - "schema_id": "booleanSchema_0_0" - }, - { - "description": "null is valid", - "data": null, - "valid": true, - "schema_id": "booleanSchema_0_0" - }, - { - "description": "object is valid", - "data": { - "foo": "bar" - }, - "valid": true, - "schema_id": "booleanSchema_0_0" - }, - { - "description": "empty object is valid", - "data": {}, - "valid": true, - "schema_id": "booleanSchema_0_0" - }, - { - "description": "array is valid", - "data": [ - "foo" - ], - "valid": true, - "schema_id": "booleanSchema_0_0" - }, - { - "description": "empty array is valid", - "data": [], - "valid": true, - "schema_id": "booleanSchema_0_0" - } - ] - }, - { - "description": "boolean schema 'false'", - "database": { - "schemas": [ - { - "not": {}, - "$id": "booleanSchema_1_0" - } - ] - }, - "tests": [ - { - "description": "number is invalid", - "data": 1, - "valid": false, - "schema_id": "booleanSchema_1_0" - }, - { - "description": "string is invalid", - "data": "foo", - "valid": false, - "schema_id": "booleanSchema_1_0" - }, - { - "description": "boolean true is invalid", - "data": true, - "valid": false, - "schema_id": "booleanSchema_1_0" - }, - { - "description": "boolean false is invalid", - "data": false, - "valid": false, - "schema_id": "booleanSchema_1_0" - }, - { - "description": "null is invalid", - "data": null, - "valid": false, - "schema_id": "booleanSchema_1_0" - }, - { - "description": "object is invalid", - "data": { - "foo": "bar" - }, - "valid": false, - "schema_id": "booleanSchema_1_0" - }, - { - "description": "empty object is invalid", - "data": {}, - "valid": false, - "schema_id": "booleanSchema_1_0" - }, - { - "description": "array is invalid", - "data": [ - "foo" - ], - "valid": false, - "schema_id": "booleanSchema_1_0" - }, - { - "description": "empty array is invalid", - "data": [], - "valid": false, - "schema_id": "booleanSchema_1_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/const.json b/tests/fixtures/const.json deleted file mode 100644 index 1ad183e..0000000 --- a/tests/fixtures/const.json +++ /dev/null @@ -1,650 +0,0 @@ -[ - { - "description": "const validation", - "database": { - "schemas": [ - { - "const": 2, - "$id": "const_0_0" - } - ] - }, - "tests": [ - { - "description": "same value is valid", - "data": 2, - "valid": true, - "schema_id": "const_0_0" - }, - { - "description": "another value is invalid", - "data": 5, - "valid": false, - "schema_id": "const_0_0" - }, - { - "description": "another type is invalid", - "data": "a", - "valid": false, - "schema_id": "const_0_0" - } - ] - }, - { - "description": "const with object", - "database": { - "schemas": [ - { - "const": { - "foo": "bar", - "baz": "bax" - }, - "properties": { - "foo": {}, - "baz": {} - }, - "$id": "const_1_0" - } - ] - }, - "tests": [ - { - "description": "same object is valid", - "data": { - "foo": "bar", - "baz": "bax" - }, - "valid": true, - "schema_id": "const_1_0" - }, - { - "description": "same object with different property order is valid", - "data": { - "baz": "bax", - "foo": "bar" - }, - "valid": true, - "schema_id": "const_1_0" - }, - { - "description": "another object is invalid", - "data": { - "foo": "bar" - }, - "valid": false, - "schema_id": "const_1_0" - }, - { - "description": "another type is invalid", - "data": [ - 1, - 2 - ], - "valid": false, - "schema_id": "const_1_0" - } - ] - }, - { - "description": "const with array", - "database": { - "schemas": [ - { - "const": [ - { - "foo": "bar" - } - ], - "$id": "const_2_0" - } - ] - }, - "tests": [ - { - "description": "same array is valid", - "data": [ - { - "foo": "bar" - } - ], - "valid": true, - "schema_id": "const_2_0" - }, - { - "description": "another array item is invalid", - "data": [ - 2 - ], - "valid": false, - "schema_id": "const_2_0" - }, - { - "description": "array with additional items is invalid", - "data": [ - 1, - 2, - 3 - ], - "valid": false, - "schema_id": "const_2_0" - } - ] - }, - { - "description": "const with null", - "database": { - "schemas": [ - { - "const": null, - "$id": "const_3_0" - } - ] - }, - "tests": [ - { - "description": "null is valid", - "data": null, - "valid": true, - "schema_id": "const_3_0" - }, - { - "description": "not null is invalid", - "data": 0, - "valid": false, - "schema_id": "const_3_0" - } - ] - }, - { - "description": "const with false does not match 0", - "database": { - "schemas": [ - { - "const": false, - "$id": "const_4_0" - } - ] - }, - "tests": [ - { - "description": "false is valid", - "data": false, - "valid": true, - "schema_id": "const_4_0" - }, - { - "description": "integer zero is invalid", - "data": 0, - "valid": false, - "schema_id": "const_4_0" - }, - { - "description": "float zero is invalid", - "data": 0, - "valid": false, - "schema_id": "const_4_0" - } - ] - }, - { - "description": "const with true does not match 1", - "database": { - "schemas": [ - { - "const": true, - "$id": "const_5_0" - } - ] - }, - "tests": [ - { - "description": "true is valid", - "data": true, - "valid": true, - "schema_id": "const_5_0" - }, - { - "description": "integer one is invalid", - "data": 1, - "valid": false, - "schema_id": "const_5_0" - }, - { - "description": "float one is invalid", - "data": 1, - "valid": false, - "schema_id": "const_5_0" - } - ] - }, - { - "description": "const with [false] does not match [0]", - "database": { - "schemas": [ - { - "const": [ - false - ], - "$id": "const_6_0" - } - ] - }, - "tests": [ - { - "description": "[false] is valid", - "data": [ - false - ], - "valid": true, - "schema_id": "const_6_0" - }, - { - "description": "[0] is invalid", - "data": [ - 0 - ], - "valid": false, - "schema_id": "const_6_0" - }, - { - "description": "[0.0] is invalid", - "data": [ - 0 - ], - "valid": false, - "schema_id": "const_6_0" - } - ] - }, - { - "description": "const with [true] does not match [1]", - "database": { - "schemas": [ - { - "const": [ - true - ], - "$id": "const_7_0" - } - ] - }, - "tests": [ - { - "description": "[true] is valid", - "data": [ - true - ], - "valid": true, - "schema_id": "const_7_0" - }, - { - "description": "[1] is invalid", - "data": [ - 1 - ], - "valid": false, - "schema_id": "const_7_0" - }, - { - "description": "[1.0] is invalid", - "data": [ - 1 - ], - "valid": false, - "schema_id": "const_7_0" - } - ] - }, - { - "description": "const with {\"a\": false} does not match {\"a\": 0}", - "database": { - "schemas": [ - { - "const": { - "a": false - }, - "$id": "const_8_0" - } - ] - }, - "tests": [ - { - "description": "{\"a\": false} is valid", - "data": { - "a": false - }, - "valid": true, - "schema_id": "const_8_0" - }, - { - "description": "{\"a\": 0} is invalid", - "data": { - "a": 0 - }, - "valid": false, - "schema_id": "const_8_0" - }, - { - "description": "{\"a\": 0.0} is invalid", - "data": { - "a": 0 - }, - "valid": false, - "schema_id": "const_8_0" - } - ] - }, - { - "description": "const with {\"a\": true} does not match {\"a\": 1}", - "database": { - "schemas": [ - { - "const": { - "a": true - }, - "$id": "const_9_0" - } - ] - }, - "tests": [ - { - "description": "{\"a\": true} is valid", - "data": { - "a": true - }, - "valid": true, - "schema_id": "const_9_0" - }, - { - "description": "{\"a\": 1} is invalid", - "data": { - "a": 1 - }, - "valid": false, - "schema_id": "const_9_0" - }, - { - "description": "{\"a\": 1.0} is invalid", - "data": { - "a": 1 - }, - "valid": false, - "schema_id": "const_9_0" - } - ] - }, - { - "description": "const with 0 does not match other zero-like types", - "database": { - "schemas": [ - { - "const": 0, - "$id": "const_10_0" - } - ] - }, - "tests": [ - { - "description": "false is invalid", - "data": false, - "valid": false, - "schema_id": "const_10_0" - }, - { - "description": "integer zero is valid", - "data": 0, - "valid": true, - "schema_id": "const_10_0" - }, - { - "description": "float zero is valid", - "data": 0, - "valid": true, - "schema_id": "const_10_0" - }, - { - "description": "empty object is invalid", - "data": {}, - "valid": false, - "schema_id": "const_10_0" - }, - { - "description": "empty array is invalid", - "data": [], - "valid": false, - "schema_id": "const_10_0" - }, - { - "description": "empty string is invalid", - "data": "", - "valid": false, - "schema_id": "const_10_0" - } - ] - }, - { - "description": "const with 1 does not match true", - "database": { - "schemas": [ - { - "const": 1, - "$id": "const_11_0" - } - ] - }, - "tests": [ - { - "description": "true is invalid", - "data": true, - "valid": false, - "schema_id": "const_11_0" - }, - { - "description": "integer one is valid", - "data": 1, - "valid": true, - "schema_id": "const_11_0" - }, - { - "description": "float one is valid", - "data": 1, - "valid": true, - "schema_id": "const_11_0" - } - ] - }, - { - "description": "const with -2.0 matches integer and float types", - "database": { - "schemas": [ - { - "const": -2, - "$id": "const_12_0" - } - ] - }, - "tests": [ - { - "description": "integer -2 is valid", - "data": -2, - "valid": true, - "schema_id": "const_12_0" - }, - { - "description": "integer 2 is invalid", - "data": 2, - "valid": false, - "schema_id": "const_12_0" - }, - { - "description": "float -2.0 is valid", - "data": -2, - "valid": true, - "schema_id": "const_12_0" - }, - { - "description": "float 2.0 is invalid", - "data": 2, - "valid": false, - "schema_id": "const_12_0" - }, - { - "description": "float -2.00001 is invalid", - "data": -2.00001, - "valid": false, - "schema_id": "const_12_0" - } - ] - }, - { - "description": "float and integers are equal up to 64-bit representation limits", - "database": { - "schemas": [ - { - "const": 9007199254740992, - "$id": "const_13_0" - } - ] - }, - "tests": [ - { - "description": "integer is valid", - "data": 9007199254740992, - "valid": true, - "schema_id": "const_13_0" - }, - { - "description": "integer minus one is invalid", - "data": 9007199254740991, - "valid": false, - "schema_id": "const_13_0" - }, - { - "description": "float is valid", - "data": 9007199254740992, - "valid": true, - "schema_id": "const_13_0" - }, - { - "description": "float minus one is invalid", - "data": 9007199254740991, - "valid": false, - "schema_id": "const_13_0" - } - ] - }, - { - "description": "nul characters in strings", - "database": { - "schemas": [ - { - "const": "hello\u0000there", - "$id": "const_14_0" - } - ] - }, - "tests": [ - { - "description": "match string with nul", - "data": "hello\u0000there", - "valid": true, - "schema_id": "const_14_0" - }, - { - "description": "do not match string lacking nul", - "data": "hellothere", - "valid": false, - "schema_id": "const_14_0" - } - ] - }, - { - "description": "characters with the same visual representation but different codepoint", - "database": { - "schemas": [ - { - "const": "μ", - "$comment": "U+03BC", - "$id": "const_15_0" - } - ] - }, - "tests": [ - { - "description": "character uses the same codepoint", - "data": "μ", - "comment": "U+03BC", - "valid": true, - "schema_id": "const_15_0" - }, - { - "description": "character looks the same but uses a different codepoint", - "data": "µ", - "comment": "U+00B5", - "valid": false, - "schema_id": "const_15_0" - } - ] - }, - { - "description": "characters with the same visual representation, but different number of codepoints", - "database": { - "schemas": [ - { - "const": "ä", - "$comment": "U+00E4", - "$id": "const_16_0" - } - ] - }, - "tests": [ - { - "description": "character uses the same codepoint", - "data": "ä", - "comment": "U+00E4", - "valid": true, - "schema_id": "const_16_0" - }, - { - "description": "character looks the same but uses combining marks", - "data": "ä", - "comment": "a, U+0308", - "valid": false, - "schema_id": "const_16_0" - } - ] - }, - { - "description": "extensible: true allows extra properties in const object match", - "database": { - "schemas": [ - { - "const": { - "a": 1 - }, - "extensible": true, - "$id": "const_17_0" - } - ] - }, - "tests": [ - { - "description": "extra property ignored during strict check, but const check still applies (mismatch)", - "data": { - "a": 1, - "b": 2 - }, - "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, - "schema_id": "const_17_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/contains.json b/tests/fixtures/contains.json deleted file mode 100644 index 5318063..0000000 --- a/tests/fixtures/contains.json +++ /dev/null @@ -1,346 +0,0 @@ -[ - { - "description": "contains keyword validation", - "database": { - "schemas": [ - { - "contains": { - "minimum": 5 - }, - "items": true, - "$id": "contains_0_0" - } - ] - }, - "tests": [ - { - "description": "array with item matching schema (5) is valid (items: true)", - "data": [ - 3, - 4, - 5 - ], - "valid": true, - "schema_id": "contains_0_0" - }, - { - "description": "array with item matching schema (6) is valid (items: true)", - "data": [ - 3, - 4, - 6 - ], - "valid": true, - "schema_id": "contains_0_0" - }, - { - "description": "array with two items matching schema (5, 6) is valid (items: true)", - "data": [ - 3, - 4, - 5, - 6 - ], - "valid": true, - "schema_id": "contains_0_0" - }, - { - "description": "array without items matching schema is invalid", - "data": [ - 2, - 3, - 4 - ], - "valid": false, - "schema_id": "contains_0_0" - }, - { - "description": "empty array is invalid", - "data": [], - "valid": false, - "schema_id": "contains_0_0" - }, - { - "description": "not array is valid", - "data": {}, - "valid": true, - "schema_id": "contains_0_0" - } - ] - }, - { - "description": "contains keyword with const keyword", - "database": { - "schemas": [ - { - "contains": { - "const": 5 - }, - "items": true, - "$id": "contains_1_0" - } - ] - }, - "tests": [ - { - "description": "array with item 5 is valid (items: true)", - "data": [ - 3, - 4, - 5 - ], - "valid": true, - "schema_id": "contains_1_0" - }, - { - "description": "array with two items 5 is valid (items: true)", - "data": [ - 3, - 4, - 5, - 5 - ], - "valid": true, - "schema_id": "contains_1_0" - }, - { - "description": "array without item 5 is invalid", - "data": [ - 1, - 2, - 3, - 4 - ], - "valid": false, - "schema_id": "contains_1_0" - } - ] - }, - { - "description": "contains keyword with boolean schema true", - "database": { - "schemas": [ - { - "contains": true, - "$id": "contains_2_0" - } - ] - }, - "tests": [ - { - "description": "any non-empty array is valid", - "data": [ - "foo" - ], - "valid": true, - "schema_id": "contains_2_0" - }, - { - "description": "empty array is invalid", - "data": [], - "valid": false, - "schema_id": "contains_2_0" - } - ] - }, - { - "description": "contains keyword with boolean schema false", - "database": { - "schemas": [ - { - "contains": false, - "$id": "contains_3_0" - } - ] - }, - "tests": [ - { - "description": "any non-empty array is invalid", - "data": [ - "foo" - ], - "valid": false, - "schema_id": "contains_3_0" - }, - { - "description": "empty array is invalid", - "data": [], - "valid": false, - "schema_id": "contains_3_0" - }, - { - "description": "non-arrays are valid", - "data": "contains does not apply to strings", - "valid": true, - "schema_id": "contains_3_0" - } - ] - }, - { - "description": "items + contains", - "database": { - "schemas": [ - { - "items": { - "multipleOf": 2 - }, - "contains": { - "multipleOf": 3 - }, - "$id": "contains_4_0" - } - ] - }, - "tests": [ - { - "description": "matches items, does not match contains", - "data": [ - 2, - 4, - 8 - ], - "valid": false, - "schema_id": "contains_4_0" - }, - { - "description": "does not match items, matches contains", - "data": [ - 3, - 6, - 9 - ], - "valid": false, - "schema_id": "contains_4_0" - }, - { - "description": "matches both items and contains", - "data": [ - 6, - 12 - ], - "valid": true, - "schema_id": "contains_4_0" - }, - { - "description": "matches neither items nor contains", - "data": [ - 1, - 5 - ], - "valid": false, - "schema_id": "contains_4_0" - } - ] - }, - { - "description": "contains with false if subschema", - "database": { - "schemas": [ - { - "contains": { - "if": false, - "else": true - }, - "$id": "contains_5_0" - } - ] - }, - "tests": [ - { - "description": "any non-empty array is valid", - "data": [ - "foo" - ], - "valid": true, - "schema_id": "contains_5_0" - }, - { - "description": "empty array is invalid", - "data": [], - "valid": false, - "schema_id": "contains_5_0" - } - ] - }, - { - "description": "contains with null instance elements", - "database": { - "schemas": [ - { - "contains": { - "type": "null" - }, - "$id": "contains_6_0" - } - ] - }, - "tests": [ - { - "description": "allows null items", - "data": [ - null - ], - "valid": true, - "schema_id": "contains_6_0" - } - ] - }, - { - "description": "extensible: true allows non-matching items in contains", - "database": { - "schemas": [ - { - "contains": { - "const": 1 - }, - "extensible": true, - "$id": "contains_7_0" - } - ] - }, - "tests": [ - { - "description": "extra items acceptable", - "data": [ - 1, - 2 - ], - "valid": true, - "schema_id": "contains_7_0" - } - ] - }, - { - "description": "strict by default: non-matching items in contains are invalid", - "database": { - "schemas": [ - { - "contains": { - "const": 1 - }, - "$id": "contains_8_0" - } - ] - }, - "tests": [ - { - "description": "extra items cause failure", - "data": [ - 1, - 2 - ], - "valid": false, - "schema_id": "contains_8_0" - }, - { - "description": "only matching items is valid", - "data": [ - 1, - 1 - ], - "valid": true, - "schema_id": "contains_8_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/content.json b/tests/fixtures/content.json deleted file mode 100644 index 6ab669d..0000000 --- a/tests/fixtures/content.json +++ /dev/null @@ -1,178 +0,0 @@ -[ - { - "description": "validation of string-encoded content based on media type", - "database": { - "schemas": [ - { - "contentMediaType": "application/json", - "$id": "content_0_0" - } - ] - }, - "tests": [ - { - "description": "a valid JSON document", - "data": "{\"foo\": \"bar\"}", - "valid": true, - "schema_id": "content_0_0" - }, - { - "description": "an invalid JSON document; validates true", - "data": "{:}", - "valid": true, - "schema_id": "content_0_0" - }, - { - "description": "ignores non-strings", - "data": 100, - "valid": true, - "schema_id": "content_0_0" - } - ] - }, - { - "description": "validation of binary string-encoding", - "database": { - "schemas": [ - { - "contentEncoding": "base64", - "$id": "content_1_0" - } - ] - }, - "tests": [ - { - "description": "a valid base64 string", - "data": "eyJmb28iOiAiYmFyIn0K", - "valid": true, - "schema_id": "content_1_0" - }, - { - "description": "an invalid base64 string (% is not a valid character); validates true", - "data": "eyJmb28iOi%iYmFyIn0K", - "valid": true, - "schema_id": "content_1_0" - }, - { - "description": "ignores non-strings", - "data": 100, - "valid": true, - "schema_id": "content_1_0" - } - ] - }, - { - "description": "validation of binary-encoded media type documents", - "database": { - "schemas": [ - { - "contentMediaType": "application/json", - "contentEncoding": "base64", - "$id": "content_2_0" - } - ] - }, - "tests": [ - { - "description": "a valid base64-encoded JSON document", - "data": "eyJmb28iOiAiYmFyIn0K", - "valid": true, - "schema_id": "content_2_0" - }, - { - "description": "a validly-encoded invalid JSON document; validates true", - "data": "ezp9Cg==", - "valid": true, - "schema_id": "content_2_0" - }, - { - "description": "an invalid base64 string that is valid JSON; validates true", - "data": "{}", - "valid": true, - "schema_id": "content_2_0" - }, - { - "description": "ignores non-strings", - "data": 100, - "valid": true, - "schema_id": "content_2_0" - } - ] - }, - { - "description": "validation of binary-encoded media type documents with schema", - "database": { - "schemas": [ - { - "contentMediaType": "application/json", - "contentEncoding": "base64", - "contentSchema": { - "type": "object", - "required": [ - "foo" - ], - "properties": { - "foo": { - "type": "string" - }, - "boo": { - "type": "integer" - } - } - }, - "$id": "content_3_0" - } - ] - }, - "tests": [ - { - "description": "a valid base64-encoded JSON document", - "data": "eyJmb28iOiAiYmFyIn0K", - "valid": true, - "schema_id": "content_3_0" - }, - { - "description": "another valid base64-encoded JSON document", - "data": "eyJib28iOiAyMCwgImZvbyI6ICJiYXoifQ==", - "valid": true, - "schema_id": "content_3_0" - }, - { - "description": "an invalid base64-encoded JSON document; validates true", - "data": "eyJib28iOiAyMH0=", - "valid": true, - "schema_id": "content_3_0" - }, - { - "description": "an empty object as a base64-encoded JSON document; validates true", - "data": "e30=", - "valid": true, - "schema_id": "content_3_0" - }, - { - "description": "an empty array as a base64-encoded JSON document", - "data": "W10=", - "valid": true, - "schema_id": "content_3_0" - }, - { - "description": "a validly-encoded invalid JSON document; validates true", - "data": "ezp9Cg==", - "valid": true, - "schema_id": "content_3_0" - }, - { - "description": "an invalid base64 string that is valid JSON; validates true", - "data": "{}", - "valid": true, - "schema_id": "content_3_0" - }, - { - "description": "ignores non-strings", - "data": 100, - "valid": true, - "schema_id": "content_3_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/dependencies.json b/tests/fixtures/dependencies.json deleted file mode 100644 index 6b497b3..0000000 --- a/tests/fixtures/dependencies.json +++ /dev/null @@ -1,619 +0,0 @@ -[ - { - "description": "single dependency (required)", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "schema1", - "dependencies": { - "bar": [ - "foo" - ] - }, - "extensible": true - } - ] - }, - "tests": [ - { - "description": "neither", - "data": {}, - "valid": true, - "schema_id": "schema1" - }, - { - "description": "nondependant", - "data": { - "foo": 1 - }, - "valid": true, - "schema_id": "schema1" - }, - { - "description": "with dependency", - "data": { - "foo": 1, - "bar": 2 - }, - "valid": true, - "schema_id": "schema1" - }, - { - "description": "missing dependency", - "data": { - "bar": 2 - }, - "valid": false, - "schema_id": "schema1" - }, - { - "description": "ignores arrays", - "data": [ - "bar" - ], - "valid": true, - "schema_id": "schema1" - }, - { - "description": "ignores strings", - "data": "foobar", - "valid": true, - "schema_id": "schema1" - }, - { - "description": "ignores other non-objects", - "data": 12, - "valid": true, - "schema_id": "schema1" - } - ] - }, - { - "description": "empty dependents", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "schema2", - "dependencies": { - "bar": [] - }, - "extensible": true - } - ] - }, - "tests": [ - { - "description": "empty object", - "data": {}, - "valid": true, - "schema_id": "schema2" - }, - { - "description": "object with one property", - "data": { - "bar": 2 - }, - "valid": true, - "schema_id": "schema2" - }, - { - "description": "non-object is valid", - "data": 1, - "valid": true, - "schema_id": "schema2" - } - ] - }, - { - "description": "multiple dependents required", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "schema3", - "dependencies": { - "quux": [ - "foo", - "bar" - ] - }, - "extensible": true - } - ] - }, - "tests": [ - { - "description": "neither", - "data": {}, - "valid": true, - "schema_id": "schema3" - }, - { - "description": "nondependants", - "data": { - "foo": 1, - "bar": 2 - }, - "valid": true, - "schema_id": "schema3" - }, - { - "description": "with dependencies", - "data": { - "foo": 1, - "bar": 2, - "quux": 3 - }, - "valid": true, - "schema_id": "schema3" - }, - { - "description": "missing dependency", - "data": { - "foo": 1, - "quux": 2 - }, - "valid": false, - "schema_id": "schema3" - }, - { - "description": "missing other dependency", - "data": { - "bar": 1, - "quux": 2 - }, - "valid": false, - "schema_id": "schema3" - }, - { - "description": "missing both dependencies", - "data": { - "quux": 1 - }, - "valid": false, - "schema_id": "schema3" - } - ] - }, - { - "description": "dependencies with escaped characters", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "schema4", - "dependencies": { - "foo\nbar": [ - "foo\rbar" - ], - "foo\"bar": [ - "foo'bar" - ] - }, - "extensible": true - } - ] - }, - "tests": [ - { - "description": "CRLF", - "data": { - "foo\nbar": 1, - "foo\rbar": 2 - }, - "valid": true, - "schema_id": "schema4" - }, - { - "description": "quoted quotes", - "data": { - "foo'bar": 1, - "foo\"bar": 2 - }, - "valid": true, - "schema_id": "schema4" - }, - { - "description": "CRLF missing dependent", - "data": { - "foo\nbar": 1, - "foo": 2 - }, - "valid": false, - "schema_id": "schema4" - }, - { - "description": "quoted quotes missing dependent", - "data": { - "foo\"bar": 2 - }, - "valid": false, - "schema_id": "schema4" - } - ] - }, - { - "description": "extensible: true allows extra properties in dependentRequired", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "schema5", - "dependencies": { - "bar": [ - "foo" - ] - }, - "extensible": true - } - ] - }, - "tests": [ - { - "description": "extra property is valid", - "data": { - "foo": 1, - "bar": 2, - "baz": 3 - }, - "valid": true, - "schema_id": "schema5" - } - ] - }, - { - "description": "single dependency (schemas, STRICT)", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "schema_schema1", - "properties": { - "foo": true, - "bar": true - }, - "dependencies": { - "bar": { - "properties": { - "foo": { - "type": "integer" - }, - "bar": { - "type": "integer" - } - } - } - } - } - ] - }, - "tests": [ - { - "description": "valid", - "data": { - "foo": 1, - "bar": 2 - }, - "valid": true, - "schema_id": "schema_schema1" - }, - { - "description": "no dependency", - "data": { - "foo": "quux" - }, - "valid": true, - "schema_id": "schema_schema1" - }, - { - "description": "wrong type", - "data": { - "foo": "quux", - "bar": 2 - }, - "valid": false, - "schema_id": "schema_schema1" - }, - { - "description": "wrong type other", - "data": { - "foo": 2, - "bar": "quux" - }, - "valid": false, - "schema_id": "schema_schema1" - }, - { - "description": "wrong type both", - "data": { - "foo": "quux", - "bar": "quux" - }, - "valid": false, - "schema_id": "schema_schema1" - }, - { - "description": "ignores arrays (invalid in strict mode)", - "data": [ - "bar" - ], - "valid": false, - "expect_errors": [ - { - "code": "STRICT_ITEM_VIOLATION" - } - ], - "schema_id": "schema_schema1" - }, - { - "description": "ignores strings", - "data": "foobar", - "valid": true, - "schema_id": "schema_schema1" - }, - { - "description": "ignores other non-objects", - "data": 12, - "valid": true, - "schema_id": "schema_schema1" - } - ] - }, - { - "description": "single dependency (schemas, EXTENSIBLE)", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "schema_schema2", - "properties": { - "foo": true, - "bar": true - }, - "dependencies": { - "bar": { - "properties": { - "foo": { - "type": "integer" - }, - "bar": { - "type": "integer" - } - } - } - }, - "extensible": true - } - ] - }, - "tests": [ - { - "description": "ignores arrays (valid in extensible mode)", - "data": [ - "bar" - ], - "valid": true, - "schema_id": "schema_schema2" - } - ] - }, - { - "description": "boolean subschemas", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "schema_schema3", - "properties": { - "foo": true, - "bar": true - }, - "dependencies": { - "foo": true, - "bar": false - } - } - ] - }, - "tests": [ - { - "description": "object with property having schema true is valid", - "data": { - "foo": 1 - }, - "valid": true, - "schema_id": "schema_schema3" - }, - { - "description": "object with property having schema false is invalid", - "data": { - "bar": 2 - }, - "valid": false, - "schema_id": "schema_schema3" - }, - { - "description": "object with both properties is invalid", - "data": { - "foo": 1, - "bar": 2 - }, - "valid": false, - "schema_id": "schema_schema3" - }, - { - "description": "empty object is valid", - "data": {}, - "valid": true, - "schema_id": "schema_schema3" - } - ] - }, - { - "description": "dependencies with escaped characters", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "schema_schema4", - "properties": { - "foo\tbar": true, - "foo'bar": true, - "a": true, - "b": true, - "c": true - }, - "dependencies": { - "foo\tbar": { - "minProperties": 4, - "extensible": true - }, - "foo'bar": { - "required": [ - "foo\"bar" - ] - } - } - } - ] - }, - "tests": [ - { - "description": "quoted tab", - "data": { - "foo\tbar": 1, - "a": 2, - "b": 3, - "c": 4 - }, - "valid": true, - "schema_id": "schema_schema4" - }, - { - "description": "quoted quote", - "data": { - "foo'bar": { - "foo\"bar": 1 - } - }, - "valid": false, - "schema_id": "schema_schema4" - }, - { - "description": "quoted tab invalid under dependent schema", - "data": { - "foo\tbar": 1, - "a": 2 - }, - "valid": false, - "schema_id": "schema_schema4" - }, - { - "description": "quoted quote invalid under dependent schema", - "data": { - "foo'bar": 1 - }, - "valid": false, - "schema_id": "schema_schema4" - } - ] - }, - { - "description": "dependent subschema incompatible with root (STRICT)", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "schema_schema5", - "properties": { - "foo": {}, - "baz": true - }, - "dependencies": { - "foo": { - "properties": { - "bar": {} - } - } - } - } - ] - }, - "tests": [ - { - "description": "matches root", - "data": { - "foo": 1 - }, - "valid": false, - "schema_id": "schema_schema5" - }, - { - "description": "matches dependency (invalid in strict mode - bar not allowed if foo missing)", - "data": { - "bar": 1 - }, - "valid": false, - "expect_errors": [ - { - "code": "STRICT_PROPERTY_VIOLATION" - } - ], - "schema_id": "schema_schema5" - }, - { - "description": "matches both", - "data": { - "foo": 1, - "bar": 2 - }, - "valid": false, - "schema_id": "schema_schema5" - }, - { - "description": "no dependency", - "data": { - "baz": 1 - }, - "valid": true, - "schema_id": "schema_schema5" - } - ] - }, - { - "description": "dependent subschema incompatible with root (EXTENSIBLE)", - "database": { - "schemas": [ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "schema_schema6", - "properties": { - "foo": {}, - "baz": true - }, - "dependencies": { - "foo": { - "properties": { - "bar": {} - }, - "additionalProperties": false - } - }, - "extensible": true - } - ] - }, - "tests": [ - { - "description": "matches dependency (valid in extensible mode)", - "data": { - "bar": 1 - }, - "valid": true, - "schema_id": "schema_schema6" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/emptyString.json b/tests/fixtures/emptyString.json deleted file mode 100644 index 85d1584..0000000 --- a/tests/fixtures/emptyString.json +++ /dev/null @@ -1,133 +0,0 @@ -[ - { - "description": "empty string is valid for all types (except const)", - "database": { - "schemas": [ - { - "properties": { - "obj": { - "type": "object" - }, - "arr": { - "type": "array" - }, - "str": { - "type": "string" - }, - "int": { - "type": "integer" - }, - "num": { - "type": "number" - }, - "bool": { - "type": "boolean" - }, - "nul": { - "type": "null" - }, - "fmt": { - "type": "string", - "format": "uuid" - }, - "con": { - "const": "value" - }, - "con_empty": { - "const": "" - } - }, - "$id": "emptyString_0_0" - } - ] - }, - "tests": [ - { - "description": "empty string valid for object", - "data": { - "obj": "" - }, - "valid": true, - "schema_id": "emptyString_0_0" - }, - { - "description": "empty string valid for array", - "data": { - "arr": "" - }, - "valid": true, - "schema_id": "emptyString_0_0" - }, - { - "description": "empty string valid for string", - "data": { - "str": "" - }, - "valid": true, - "schema_id": "emptyString_0_0" - }, - { - "description": "empty string valid for integer", - "data": { - "int": "" - }, - "valid": true, - "schema_id": "emptyString_0_0" - }, - { - "description": "empty string valid for number", - "data": { - "num": "" - }, - "valid": true, - "schema_id": "emptyString_0_0" - }, - { - "description": "empty string valid for boolean", - "data": { - "bool": "" - }, - "valid": true, - "schema_id": "emptyString_0_0" - }, - { - "description": "empty string valid for null", - "data": { - "nul": "" - }, - "valid": true, - "schema_id": "emptyString_0_0" - }, - { - "description": "empty string valid for format", - "data": { - "fmt": "" - }, - "valid": true, - "schema_id": "emptyString_0_0" - }, - { - "description": "empty string INVALID for const (unless const is empty string)", - "data": { - "con": "" - }, - "valid": false, - "expect_errors": [ - { - "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, - "schema_id": "emptyString_0_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/enum.json b/tests/fixtures/enum.json deleted file mode 100644 index 7b6b679..0000000 --- a/tests/fixtures/enum.json +++ /dev/null @@ -1,595 +0,0 @@ -[ - { - "description": "simple enum validation", - "database": { - "schemas": [ - { - "enum": [ - 1, - 2, - 3 - ], - "$id": "enum_0_0" - } - ] - }, - "tests": [ - { - "description": "one of the enum is valid", - "data": 1, - "valid": true, - "schema_id": "enum_0_0" - }, - { - "description": "something else is invalid", - "data": 4, - "valid": false, - "schema_id": "enum_0_0" - } - ] - }, - { - "description": "heterogeneous enum validation", - "database": { - "schemas": [ - { - "enum": [ - 6, - "foo", - [], - true, - { - "foo": 12 - } - ], - "properties": { - "foo": {} - }, - "$id": "enum_1_0" - } - ] - }, - "tests": [ - { - "description": "one of the enum is valid", - "data": [], - "valid": true, - "schema_id": "enum_1_0" - }, - { - "description": "something else is invalid", - "data": null, - "valid": false, - "schema_id": "enum_1_0" - }, - { - "description": "objects are deep compared", - "data": { - "foo": false - }, - "valid": false, - "schema_id": "enum_1_0" - }, - { - "description": "valid object matches", - "data": { - "foo": 12 - }, - "valid": true, - "schema_id": "enum_1_0" - }, - { - "description": "extra properties in object is invalid", - "data": { - "foo": 12, - "boo": 42 - }, - "valid": false, - "schema_id": "enum_1_0" - } - ] - }, - { - "description": "heterogeneous enum-with-null validation", - "database": { - "schemas": [ - { - "enum": [ - 6, - null - ], - "$id": "enum_2_0" - } - ] - }, - "tests": [ - { - "description": "null is valid", - "data": null, - "valid": true, - "schema_id": "enum_2_0" - }, - { - "description": "number is valid", - "data": 6, - "valid": true, - "schema_id": "enum_2_0" - }, - { - "description": "something else is invalid", - "data": "test", - "valid": false, - "schema_id": "enum_2_0" - } - ] - }, - { - "description": "enums in properties", - "database": { - "schemas": [ - { - "type": "object", - "properties": { - "foo": { - "enum": [ - "foo" - ] - }, - "bar": { - "enum": [ - "bar" - ] - } - }, - "required": [ - "bar" - ], - "$id": "enum_3_0" - } - ] - }, - "tests": [ - { - "description": "both properties are valid", - "data": { - "foo": "foo", - "bar": "bar" - }, - "valid": true, - "schema_id": "enum_3_0" - }, - { - "description": "wrong foo value", - "data": { - "foo": "foot", - "bar": "bar" - }, - "valid": false, - "schema_id": "enum_3_0" - }, - { - "description": "wrong bar value", - "data": { - "foo": "foo", - "bar": "bart" - }, - "valid": false, - "schema_id": "enum_3_0" - }, - { - "description": "missing optional property is valid", - "data": { - "bar": "bar" - }, - "valid": true, - "schema_id": "enum_3_0" - }, - { - "description": "missing required property is invalid", - "data": { - "foo": "foo" - }, - "valid": false, - "schema_id": "enum_3_0" - }, - { - "description": "missing all properties is invalid", - "data": {}, - "valid": false, - "schema_id": "enum_3_0" - } - ] - }, - { - "description": "enum with escaped characters", - "database": { - "schemas": [ - { - "enum": [ - "foo\nbar", - "foo\rbar" - ], - "$id": "enum_4_0" - } - ] - }, - "tests": [ - { - "description": "member 1 is valid", - "data": "foo\nbar", - "valid": true, - "schema_id": "enum_4_0" - }, - { - "description": "member 2 is valid", - "data": "foo\rbar", - "valid": true, - "schema_id": "enum_4_0" - }, - { - "description": "another string is invalid", - "data": "abc", - "valid": false, - "schema_id": "enum_4_0" - } - ] - }, - { - "description": "enum with false does not match 0", - "database": { - "schemas": [ - { - "enum": [ - false - ], - "$id": "enum_5_0" - } - ] - }, - "tests": [ - { - "description": "false is valid", - "data": false, - "valid": true, - "schema_id": "enum_5_0" - }, - { - "description": "integer zero is invalid", - "data": 0, - "valid": false, - "schema_id": "enum_5_0" - }, - { - "description": "float zero is invalid", - "data": 0, - "valid": false, - "schema_id": "enum_5_0" - } - ] - }, - { - "description": "enum with [false] does not match [0]", - "database": { - "schemas": [ - { - "enum": [ - [ - false - ] - ], - "$id": "enum_6_0" - } - ] - }, - "tests": [ - { - "description": "[false] is valid", - "data": [ - false - ], - "valid": true, - "schema_id": "enum_6_0" - }, - { - "description": "[0] is invalid", - "data": [ - 0 - ], - "valid": false, - "schema_id": "enum_6_0" - }, - { - "description": "[0.0] is invalid", - "data": [ - 0 - ], - "valid": false, - "schema_id": "enum_6_0" - } - ] - }, - { - "description": "enum with true does not match 1", - "database": { - "schemas": [ - { - "enum": [ - true - ], - "$id": "enum_7_0" - } - ] - }, - "tests": [ - { - "description": "true is valid", - "data": true, - "valid": true, - "schema_id": "enum_7_0" - }, - { - "description": "integer one is invalid", - "data": 1, - "valid": false, - "schema_id": "enum_7_0" - }, - { - "description": "float one is invalid", - "data": 1, - "valid": false, - "schema_id": "enum_7_0" - } - ] - }, - { - "description": "enum with [true] does not match [1]", - "database": { - "schemas": [ - { - "enum": [ - [ - true - ] - ], - "$id": "enum_8_0" - } - ] - }, - "tests": [ - { - "description": "[true] is valid", - "data": [ - true - ], - "valid": true, - "schema_id": "enum_8_0" - }, - { - "description": "[1] is invalid", - "data": [ - 1 - ], - "valid": false, - "schema_id": "enum_8_0" - }, - { - "description": "[1.0] is invalid", - "data": [ - 1 - ], - "valid": false, - "schema_id": "enum_8_0" - } - ] - }, - { - "description": "enum with 0 does not match false", - "database": { - "schemas": [ - { - "enum": [ - 0 - ], - "$id": "enum_9_0" - } - ] - }, - "tests": [ - { - "description": "false is invalid", - "data": false, - "valid": false, - "schema_id": "enum_9_0" - }, - { - "description": "integer zero is valid", - "data": 0, - "valid": true, - "schema_id": "enum_9_0" - }, - { - "description": "float zero is valid", - "data": 0, - "valid": true, - "schema_id": "enum_9_0" - } - ] - }, - { - "description": "enum with [0] does not match [false]", - "database": { - "schemas": [ - { - "enum": [ - [ - 0 - ] - ], - "$id": "enum_10_0" - } - ] - }, - "tests": [ - { - "description": "[false] is invalid", - "data": [ - false - ], - "valid": false, - "schema_id": "enum_10_0" - }, - { - "description": "[0] is valid", - "data": [ - 0 - ], - "valid": true, - "schema_id": "enum_10_0" - }, - { - "description": "[0.0] is valid", - "data": [ - 0 - ], - "valid": true, - "schema_id": "enum_10_0" - } - ] - }, - { - "description": "enum with 1 does not match true", - "database": { - "schemas": [ - { - "enum": [ - 1 - ], - "$id": "enum_11_0" - } - ] - }, - "tests": [ - { - "description": "true is invalid", - "data": true, - "valid": false, - "schema_id": "enum_11_0" - }, - { - "description": "integer one is valid", - "data": 1, - "valid": true, - "schema_id": "enum_11_0" - }, - { - "description": "float one is valid", - "data": 1, - "valid": true, - "schema_id": "enum_11_0" - } - ] - }, - { - "description": "enum with [1] does not match [true]", - "database": { - "schemas": [ - { - "enum": [ - [ - 1 - ] - ], - "$id": "enum_12_0" - } - ] - }, - "tests": [ - { - "description": "[true] is invalid", - "data": [ - true - ], - "valid": false, - "schema_id": "enum_12_0" - }, - { - "description": "[1] is valid", - "data": [ - 1 - ], - "valid": true, - "schema_id": "enum_12_0" - }, - { - "description": "[1.0] is valid", - "data": [ - 1 - ], - "valid": true, - "schema_id": "enum_12_0" - } - ] - }, - { - "description": "nul characters in strings", - "database": { - "schemas": [ - { - "enum": [ - "hello\u0000there" - ], - "$id": "enum_13_0" - } - ] - }, - "tests": [ - { - "description": "match string with nul", - "data": "hello\u0000there", - "valid": true, - "schema_id": "enum_13_0" - }, - { - "description": "do not match string lacking nul", - "data": "hellothere", - "valid": false, - "schema_id": "enum_13_0" - } - ] - }, - { - "description": "extensible: true allows extra properties in enum object match", - "database": { - "schemas": [ - { - "enum": [ - { - "foo": 1 - } - ], - "extensible": true, - "$id": "enum_14_0" - } - ] - }, - "tests": [ - { - "description": "extra property ignored during strict check, but enum check still applies (mismatch here)", - "data": { - "foo": 1, - "bar": 2 - }, - "valid": false, - "schema_id": "enum_14_0" - }, - { - "description": "extra property ignored during strict check, enum match succeeds", - "data": { - "foo": 1 - }, - "valid": true, - "schema_id": "enum_14_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/exclusiveMaximum.json b/tests/fixtures/exclusiveMaximum.json deleted file mode 100644 index bea5f68..0000000 --- a/tests/fixtures/exclusiveMaximum.json +++ /dev/null @@ -1,39 +0,0 @@ -[ - { - "description": "exclusiveMaximum validation", - "database": { - "schemas": [ - { - "exclusiveMaximum": 3, - "$id": "exclusiveMaximum_0_0" - } - ] - }, - "tests": [ - { - "description": "below the exclusiveMaximum is valid", - "data": 2.2, - "valid": true, - "schema_id": "exclusiveMaximum_0_0" - }, - { - "description": "boundary point is invalid", - "data": 3, - "valid": false, - "schema_id": "exclusiveMaximum_0_0" - }, - { - "description": "above the exclusiveMaximum is invalid", - "data": 3.5, - "valid": false, - "schema_id": "exclusiveMaximum_0_0" - }, - { - "description": "ignores non-numbers", - "data": "x", - "valid": true, - "schema_id": "exclusiveMaximum_0_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/exclusiveMinimum.json b/tests/fixtures/exclusiveMinimum.json deleted file mode 100644 index 2ed42ab..0000000 --- a/tests/fixtures/exclusiveMinimum.json +++ /dev/null @@ -1,39 +0,0 @@ -[ - { - "description": "exclusiveMinimum validation", - "database": { - "schemas": [ - { - "exclusiveMinimum": 1.1, - "$id": "exclusiveMinimum_0_0" - } - ] - }, - "tests": [ - { - "description": "above the exclusiveMinimum is valid", - "data": 1.2, - "valid": true, - "schema_id": "exclusiveMinimum_0_0" - }, - { - "description": "boundary point is invalid", - "data": 1.1, - "valid": false, - "schema_id": "exclusiveMinimum_0_0" - }, - { - "description": "below the exclusiveMinimum is invalid", - "data": 0.6, - "valid": false, - "schema_id": "exclusiveMinimum_0_0" - }, - { - "description": "ignores non-numbers", - "data": "x", - "valid": true, - "schema_id": "exclusiveMinimum_0_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/families.json b/tests/fixtures/families.json deleted file mode 100644 index a1d0810..0000000 --- a/tests/fixtures/families.json +++ /dev/null @@ -1,199 +0,0 @@ -[ - { - "description": "Entity families via pure $ref graph", - "database": { - "types": [ - { - "name": "entity", - "variations": [ - "entity", - "organization", - "person" - ], - "schemas": [ - { - "$id": "entity", - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - { - "$id": "light.entity", - "$ref": "entity" - } - ] - }, - { - "name": "organization", - "variations": [ - "organization", - "person" - ], - "schemas": [ - { - "$id": "organization", - "$ref": "entity", - "properties": { - "name": { - "type": "string" - } - } - } - ] - }, - { - "name": "person", - "variations": [ - "person" - ], - "schemas": [ - { - "$id": "person", - "$ref": "organization", - "properties": { - "first_name": { - "type": "string" - } - } - }, - { - "$id": "light.person", - "$ref": "light.entity" - } - ] - } - ], - "puncs": [ - { - "name": "get_entities", - "schemas": [ - { - "$id": "get_entities.response", - "$family": "entity" - } - ] - }, - { - "name": "get_light_entities", - "schemas": [ - { - "$id": "get_light_entities.response", - "$family": "light.entity" - } - ] - } - ] - }, - "tests": [ - { - "description": "Family matches base entity", - "schema_id": "get_entities.response", - "data": { - "id": "1", - "type": "entity" - }, - "valid": true - }, - { - "description": "Family matches descendant person", - "schema_id": "get_entities.response", - "data": { - "id": "2", - "type": "person", - "name": "ACME", - "first_name": "John" - }, - "valid": true - }, - { - "description": "Graph family matches light.entity", - "schema_id": "get_light_entities.response", - "data": { - "id": "3", - "type": "entity" - }, - "valid": true - }, - { - "description": "Graph family matches light.person (because it $refs light.entity)", - "schema_id": "get_light_entities.response", - "data": { - "id": "4", - "type": "person" - }, - "valid": true - }, - { - "description": "Graph family excludes organization (missing light. schema that $refs light.entity)", - "schema_id": "get_light_entities.response", - "data": { - "id": "5", - "type": "organization", - "name": "ACME" - }, - "valid": false, - "expect_errors": [ - { - "code": "FAMILY_MISMATCH", - "path": "" - } - ] - } - ] - }, - { - "description": "Ad-hoc non-entity families (using normal json-schema object structures)", - "database": { - "puncs": [ - { - "name": "get_widgets", - "schemas": [ - { - "$id": "widget", - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "widget_type": { - "type": "string" - } - } - }, - { - "$id": "special_widget", - "$ref": "widget", - "properties": { - "special_feature": { - "type": "string" - } - } - }, - { - "$id": "get_widgets.response", - "$family": "widget" - } - ] - } - ] - }, - "tests": [ - { - "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": true - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/format.json b/tests/fixtures/format.json deleted file mode 100644 index a5bf55c..0000000 --- a/tests/fixtures/format.json +++ /dev/null @@ -1,3770 +0,0 @@ -[ - { - "description": "validation of date-time strings", - "database": { - "schemas": [ - { - "format": "date-time", - "$id": "format_0_0" - } - ] - }, - "tests": [ - { - "description": "all string formats ignore integers", - "data": 12, - "valid": true, - "schema_id": "format_0_0" - }, - { - "description": "all string formats ignore floats", - "data": 13.7, - "valid": true, - "schema_id": "format_0_0" - }, - { - "description": "all string formats ignore objects", - "data": {}, - "valid": true, - "schema_id": "format_0_0" - }, - { - "description": "all string formats ignore arrays", - "data": [], - "valid": true, - "schema_id": "format_0_0" - }, - { - "description": "all string formats ignore booleans", - "data": false, - "valid": true, - "schema_id": "format_0_0" - }, - { - "description": "all string formats ignore nulls", - "data": null, - "valid": true, - "schema_id": "format_0_0" - }, - { - "description": "a valid date-time string", - "data": "1963-06-19T08:30:06.283185Z", - "valid": true, - "schema_id": "format_0_0" - }, - { - "description": "a valid date-time string without second fraction", - "data": "1963-06-19T08:30:06Z", - "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, - "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, - "schema_id": "format_0_0" - }, - { - "description": "a valid date-time with a leap second, UTC", - "data": "1998-12-31T23:59:60Z", - "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, - "schema_id": "format_0_0" - }, - { - "description": "an invalid date-time past leap second, UTC", - "data": "1998-12-31T23:59:61Z", - "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, - "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, - "schema_id": "format_0_0" - }, - { - "description": "an invalid day in date-time string", - "data": "1990-02-31T15:59:59.123-08:00", - "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, - "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, - "schema_id": "format_0_0" - }, - { - "description": "an invalid date-time string", - "data": "06/19/1963 08:30:06 PST", - "valid": false, - "schema_id": "format_0_0" - }, - { - "description": "case-insensitive T and Z", - "data": "1963-06-19t08:30:06.283185z", - "valid": true, - "schema_id": "format_0_0" - }, - { - "description": "only RFC3339 not all of ISO 8601 are valid", - "data": "2013-350T01:01:01", - "valid": false, - "schema_id": "format_0_0" - }, - { - "description": "invalid non-padded month dates", - "data": "1963-6-19T08:30:06.283185Z", - "valid": false, - "schema_id": "format_0_0" - }, - { - "description": "invalid non-padded day dates", - "data": "1963-06-1T08:30:06.283185Z", - "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, - "schema_id": "format_0_0" - }, - { - "description": "invalid non-ASCII '৪' (a Bengali 4) in time portion", - "data": "1963-06-11T0৪:00:00Z", - "valid": false, - "schema_id": "format_0_0" - }, - { - "description": "invalid extended year", - "data": "+11963-06-19T08:30:06.283185Z", - "valid": false, - "schema_id": "format_0_0" - } - ] - }, - { - "description": "validation of date strings", - "database": { - "schemas": [ - { - "format": "date", - "$id": "format_1_0" - } - ] - }, - "tests": [ - { - "description": "all string formats ignore integers", - "data": 12, - "valid": true, - "schema_id": "format_1_0" - }, - { - "description": "all string formats ignore floats", - "data": 13.7, - "valid": true, - "schema_id": "format_1_0" - }, - { - "description": "all string formats ignore objects", - "data": {}, - "valid": true, - "schema_id": "format_1_0" - }, - { - "description": "all string formats ignore arrays", - "data": [], - "valid": true, - "schema_id": "format_1_0" - }, - { - "description": "all string formats ignore booleans", - "data": false, - "valid": true, - "schema_id": "format_1_0" - }, - { - "description": "all string formats ignore nulls", - "data": null, - "valid": true, - "schema_id": "format_1_0" - }, - { - "description": "a valid date string", - "data": "1963-06-19", - "valid": true, - "schema_id": "format_1_0" - }, - { - "description": "a valid date string with 31 days in January", - "data": "2020-01-31", - "valid": true, - "schema_id": "format_1_0" - }, - { - "description": "a invalid date string with 32 days in January", - "data": "2020-01-32", - "valid": false, - "schema_id": "format_1_0" - }, - { - "description": "a valid date string with 28 days in February (normal)", - "data": "2021-02-28", - "valid": true, - "schema_id": "format_1_0" - }, - { - "description": "a invalid date string with 29 days in February (normal)", - "data": "2021-02-29", - "valid": false, - "schema_id": "format_1_0" - }, - { - "description": "a valid date string with 29 days in February (leap)", - "data": "2020-02-29", - "valid": true, - "schema_id": "format_1_0" - }, - { - "description": "a invalid date string with 30 days in February (leap)", - "data": "2020-02-30", - "valid": false, - "schema_id": "format_1_0" - }, - { - "description": "a valid date string with 31 days in March", - "data": "2020-03-31", - "valid": true, - "schema_id": "format_1_0" - }, - { - "description": "a invalid date string with 32 days in March", - "data": "2020-03-32", - "valid": false, - "schema_id": "format_1_0" - }, - { - "description": "a valid date string with 30 days in April", - "data": "2020-04-30", - "valid": true, - "schema_id": "format_1_0" - }, - { - "description": "a invalid date string with 31 days in April", - "data": "2020-04-31", - "valid": false, - "schema_id": "format_1_0" - }, - { - "description": "a valid date string with 31 days in May", - "data": "2020-05-31", - "valid": true, - "schema_id": "format_1_0" - }, - { - "description": "a invalid date string with 32 days in May", - "data": "2020-05-32", - "valid": false, - "schema_id": "format_1_0" - }, - { - "description": "a valid date string with 30 days in June", - "data": "2020-06-30", - "valid": true, - "schema_id": "format_1_0" - }, - { - "description": "a invalid date string with 31 days in June", - "data": "2020-06-31", - "valid": false, - "schema_id": "format_1_0" - }, - { - "description": "a valid date string with 31 days in July", - "data": "2020-07-31", - "valid": true, - "schema_id": "format_1_0" - }, - { - "description": "a invalid date string with 32 days in July", - "data": "2020-07-32", - "valid": false, - "schema_id": "format_1_0" - }, - { - "description": "a valid date string with 31 days in August", - "data": "2020-08-31", - "valid": true, - "schema_id": "format_1_0" - }, - { - "description": "a invalid date string with 32 days in August", - "data": "2020-08-32", - "valid": false, - "schema_id": "format_1_0" - }, - { - "description": "a valid date string with 30 days in September", - "data": "2020-09-30", - "valid": true, - "schema_id": "format_1_0" - }, - { - "description": "a invalid date string with 31 days in September", - "data": "2020-09-31", - "valid": false, - "schema_id": "format_1_0" - }, - { - "description": "a valid date string with 31 days in October", - "data": "2020-10-31", - "valid": true, - "schema_id": "format_1_0" - }, - { - "description": "a invalid date string with 32 days in October", - "data": "2020-10-32", - "valid": false, - "schema_id": "format_1_0" - }, - { - "description": "a valid date string with 30 days in November", - "data": "2020-11-30", - "valid": true, - "schema_id": "format_1_0" - }, - { - "description": "a invalid date string with 31 days in November", - "data": "2020-11-31", - "valid": false, - "schema_id": "format_1_0" - }, - { - "description": "a valid date string with 31 days in December", - "data": "2020-12-31", - "valid": true, - "schema_id": "format_1_0" - }, - { - "description": "a invalid date string with 32 days in December", - "data": "2020-12-32", - "valid": false, - "schema_id": "format_1_0" - }, - { - "description": "a invalid date string with invalid month", - "data": "2020-13-01", - "valid": false, - "schema_id": "format_1_0" - }, - { - "description": "an invalid date string", - "data": "06/19/1963", - "valid": false, - "schema_id": "format_1_0" - }, - { - "description": "only RFC3339 not all of ISO 8601 are valid", - "data": "2013-350", - "valid": false, - "schema_id": "format_1_0" - }, - { - "description": "non-padded month dates are not valid", - "data": "1998-1-20", - "valid": false, - "schema_id": "format_1_0" - }, - { - "description": "non-padded day dates are not valid", - "data": "1998-01-1", - "valid": false, - "schema_id": "format_1_0" - }, - { - "description": "invalid month", - "data": "1998-13-01", - "valid": false, - "schema_id": "format_1_0" - }, - { - "description": "invalid month-day combination", - "data": "1998-04-31", - "valid": false, - "schema_id": "format_1_0" - }, - { - "description": "2021 is not a leap year", - "data": "2021-02-29", - "valid": false, - "schema_id": "format_1_0" - }, - { - "description": "2020 is a leap year", - "data": "2020-02-29", - "valid": true, - "schema_id": "format_1_0" - }, - { - "description": "invalid non-ASCII '৪' (a Bengali 4)", - "data": "1963-06-1৪", - "valid": false, - "schema_id": "format_1_0" - }, - { - "description": "ISO8601 / non-RFC3339: YYYYMMDD without dashes (2023-03-28)", - "data": "20230328", - "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, - "schema_id": "format_1_0" - }, - { - "description": "ISO8601 / non-RFC3339: week number with day of week (2023-03-28)", - "data": "2023-W13-2", - "valid": false, - "schema_id": "format_1_0" - }, - { - "description": "ISO8601 / non-RFC3339: week number rollover to next year (2023-01-01)", - "data": "2022W527", - "valid": false, - "schema_id": "format_1_0" - }, - { - "description": "an invalid time string in date-time format", - "data": "2020-11-28T23:55:45Z", - "valid": false, - "schema_id": "format_1_0" - } - ] - }, - { - "description": "validation of duration strings", - "database": { - "schemas": [ - { - "format": "duration", - "$id": "format_2_0" - } - ] - }, - "tests": [ - { - "description": "all string formats ignore integers", - "data": 12, - "valid": true, - "schema_id": "format_2_0" - }, - { - "description": "all string formats ignore floats", - "data": 13.7, - "valid": true, - "schema_id": "format_2_0" - }, - { - "description": "all string formats ignore objects", - "data": {}, - "valid": true, - "schema_id": "format_2_0" - }, - { - "description": "all string formats ignore arrays", - "data": [], - "valid": true, - "schema_id": "format_2_0" - }, - { - "description": "all string formats ignore booleans", - "data": false, - "valid": true, - "schema_id": "format_2_0" - }, - { - "description": "all string formats ignore nulls", - "data": null, - "valid": true, - "schema_id": "format_2_0" - }, - { - "description": "a valid duration string", - "data": "P4DT12H30M5S", - "valid": true, - "schema_id": "format_2_0" - }, - { - "description": "an invalid duration string", - "data": "PT1D", - "valid": false, - "schema_id": "format_2_0" - }, - { - "description": "must start with P", - "data": "4DT12H30M5S", - "valid": false, - "schema_id": "format_2_0" - }, - { - "description": "no elements present", - "data": "P", - "valid": false, - "schema_id": "format_2_0" - }, - { - "description": "no time elements present", - "data": "P1YT", - "valid": false, - "schema_id": "format_2_0" - }, - { - "description": "no date or time elements present", - "data": "PT", - "valid": false, - "schema_id": "format_2_0" - }, - { - "description": "elements out of order", - "data": "P2D1Y", - "valid": false, - "schema_id": "format_2_0" - }, - { - "description": "missing time separator", - "data": "P1D2H", - "valid": false, - "schema_id": "format_2_0" - }, - { - "description": "time element in the date position", - "data": "P2S", - "valid": false, - "schema_id": "format_2_0" - }, - { - "description": "four years duration", - "data": "P4Y", - "valid": true, - "schema_id": "format_2_0" - }, - { - "description": "zero time, in seconds", - "data": "PT0S", - "valid": true, - "schema_id": "format_2_0" - }, - { - "description": "zero time, in days", - "data": "P0D", - "valid": true, - "schema_id": "format_2_0" - }, - { - "description": "one month duration", - "data": "P1M", - "valid": true, - "schema_id": "format_2_0" - }, - { - "description": "one minute duration", - "data": "PT1M", - "valid": true, - "schema_id": "format_2_0" - }, - { - "description": "one and a half days, in hours", - "data": "PT36H", - "valid": true, - "schema_id": "format_2_0" - }, - { - "description": "one and a half days, in days and hours", - "data": "P1DT12H", - "valid": true, - "schema_id": "format_2_0" - }, - { - "description": "two weeks", - "data": "P2W", - "valid": true, - "schema_id": "format_2_0" - }, - { - "description": "weeks cannot be combined with other units", - "data": "P1Y2W", - "valid": false, - "schema_id": "format_2_0" - }, - { - "description": "invalid non-ASCII '২' (a Bengali 2)", - "data": "P২Y", - "valid": false, - "schema_id": "format_2_0" - }, - { - "description": "element without unit", - "data": "P1", - "valid": false, - "schema_id": "format_2_0" - } - ] - }, - { - "description": "\\a is not an ECMA 262 control escape", - "database": { - "schemas": [ - { - "format": "regex", - "$id": "format_3_0" - } - ] - }, - "tests": [ - { - "description": "when used as a pattern", - "data": "\\a", - "valid": true, - "schema_id": "format_3_0" - } - ] - }, - { - "description": "validation of e-mail addresses", - "database": { - "schemas": [ - { - "format": "email", - "$id": "format_4_0" - } - ] - }, - "tests": [ - { - "description": "all string formats ignore integers", - "data": 12, - "valid": true, - "schema_id": "format_4_0" - }, - { - "description": "all string formats ignore floats", - "data": 13.7, - "valid": true, - "schema_id": "format_4_0" - }, - { - "description": "all string formats ignore objects", - "data": {}, - "valid": true, - "schema_id": "format_4_0" - }, - { - "description": "all string formats ignore arrays", - "data": [], - "valid": true, - "schema_id": "format_4_0" - }, - { - "description": "all string formats ignore booleans", - "data": false, - "valid": true, - "schema_id": "format_4_0" - }, - { - "description": "all string formats ignore nulls", - "data": null, - "valid": true, - "schema_id": "format_4_0" - }, - { - "description": "a valid e-mail address", - "data": "joe.bloggs@example.com", - "valid": true, - "schema_id": "format_4_0" - }, - { - "description": "an invalid e-mail address", - "data": "2962", - "valid": false, - "schema_id": "format_4_0" - }, - { - "description": "tilde in local part is valid", - "data": "te~st@example.com", - "valid": true, - "schema_id": "format_4_0" - }, - { - "description": "tilde before local part is valid", - "data": "~test@example.com", - "valid": true, - "schema_id": "format_4_0" - }, - { - "description": "tilde after local part is valid", - "data": "test~@example.com", - "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, - "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, - "schema_id": "format_4_0" - }, - { - "description": "a quoted string with a @ in the local part is valid", - "data": "\"joe@bloggs\"@example.com", - "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, - "schema_id": "format_4_0" - }, - { - "description": "an IPv6-address-literal after the @ is valid", - "data": "joe.bloggs@[IPv6:::1]", - "valid": true, - "schema_id": "format_4_0" - }, - { - "description": "dot before local part is not valid", - "data": ".test@example.com", - "valid": false, - "schema_id": "format_4_0" - }, - { - "description": "dot after local part is not valid", - "data": "test.@example.com", - "valid": false, - "schema_id": "format_4_0" - }, - { - "description": "two separated dots inside local part are valid", - "data": "te.s.t@example.com", - "valid": true, - "schema_id": "format_4_0" - }, - { - "description": "two subsequent dots inside local part are not valid", - "data": "te..st@example.com", - "valid": false, - "schema_id": "format_4_0" - }, - { - "description": "an invalid domain", - "data": "joe.bloggs@invalid=domain.com", - "valid": false, - "schema_id": "format_4_0" - }, - { - "description": "an invalid IPv4-address-literal", - "data": "joe.bloggs@[127.0.0.300]", - "valid": false, - "schema_id": "format_4_0" - }, - { - "description": "two email addresses is not valid", - "data": "user1@oceania.org, user2@oceania.org", - "valid": false, - "schema_id": "format_4_0" - }, - { - "description": "full \"From\" header is invalid", - "data": "\"Winston Smith\" (Records Department)", - "valid": false, - "schema_id": "format_4_0" - } - ] - }, - { - "description": "validation of host names", - "database": { - "schemas": [ - { - "format": "hostname", - "$id": "format_5_0" - } - ] - }, - "tests": [ - { - "description": "all string formats ignore integers", - "data": 12, - "valid": true, - "schema_id": "format_5_0" - }, - { - "description": "all string formats ignore floats", - "data": 13.7, - "valid": true, - "schema_id": "format_5_0" - }, - { - "description": "all string formats ignore objects", - "data": {}, - "valid": true, - "schema_id": "format_5_0" - }, - { - "description": "all string formats ignore arrays", - "data": [], - "valid": true, - "schema_id": "format_5_0" - }, - { - "description": "all string formats ignore booleans", - "data": false, - "valid": true, - "schema_id": "format_5_0" - }, - { - "description": "all string formats ignore nulls", - "data": null, - "valid": true, - "schema_id": "format_5_0" - }, - { - "description": "a valid host name", - "data": "www.example.com", - "valid": true, - "schema_id": "format_5_0" - }, - { - "description": "single label", - "data": "hostname", - "valid": true, - "schema_id": "format_5_0" - }, - { - "description": "single label with digits", - "data": "h0stn4me", - "valid": true, - "schema_id": "format_5_0" - }, - { - "description": "single label starting with digit", - "data": "1host", - "valid": true, - "schema_id": "format_5_0" - }, - { - "description": "single label ending with digit", - "data": "hostnam3", - "valid": true, - "schema_id": "format_5_0" - }, - { - "description": "empty string", - "data": "", - "valid": true, - "schema_id": "format_5_0" - }, - { - "description": "single dot", - "data": ".", - "valid": false, - "schema_id": "format_5_0" - }, - { - "description": "leading dot", - "data": ".example", - "valid": false, - "schema_id": "format_5_0" - }, - { - "description": "trailing dot", - "data": "example.", - "valid": false, - "schema_id": "format_5_0" - }, - { - "description": "IDN label separator", - "data": "example.com", - "valid": false, - "schema_id": "format_5_0" - }, - { - "description": "single label with hyphen", - "data": "host-name", - "valid": true, - "schema_id": "format_5_0" - }, - { - "description": "starts with hyphen", - "data": "-hostname", - "valid": false, - "schema_id": "format_5_0" - }, - { - "description": "ends with hyphen", - "data": "hostname-", - "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, - "schema_id": "format_5_0" - }, - { - "description": "contains underscore", - "data": "host_name", - "valid": false, - "schema_id": "format_5_0" - }, - { - "description": "exceeds maximum overall length (256)", - "data": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.com", - "valid": false, - "schema_id": "format_5_0" - }, - { - "description": "maximum label length (63)", - "data": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.com", - "valid": true, - "schema_id": "format_5_0" - }, - { - "description": "exceeds maximum label length (63)", - "data": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl.com", - "valid": false, - "schema_id": "format_5_0" - } - ] - }, - { - "description": "validation of A-label (punycode) host names", - "database": { - "schemas": [ - { - "format": "hostname", - "$id": "format_6_0" - } - ] - }, - "tests": [ - { - "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, - "schema_id": "format_6_0" - }, - { - "description": "a valid host name (example.test in Hangul)", - "data": "xn--9n2bp8q.xn--9t4b11yi5a", - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "schema_id": "format_6_0" - } - ] - }, - { - "description": "validation of an internationalized e-mail addresses", - "database": { - "schemas": [ - { - "format": "idn-email", - "$id": "format_7_0" - } - ] - }, - "tests": [ - { - "description": "all string formats ignore integers", - "data": 12, - "valid": true, - "schema_id": "format_7_0" - }, - { - "description": "all string formats ignore floats", - "data": 13.7, - "valid": true, - "schema_id": "format_7_0" - }, - { - "description": "all string formats ignore objects", - "data": {}, - "valid": true, - "schema_id": "format_7_0" - }, - { - "description": "all string formats ignore arrays", - "data": [], - "valid": true, - "schema_id": "format_7_0" - }, - { - "description": "all string formats ignore booleans", - "data": false, - "valid": true, - "schema_id": "format_7_0" - }, - { - "description": "all string formats ignore nulls", - "data": null, - "valid": true, - "schema_id": "format_7_0" - }, - { - "description": "a valid idn e-mail (example@example.test in Hangul)", - "data": "실례@실례.테스트", - "valid": true, - "schema_id": "format_7_0" - }, - { - "description": "an invalid idn e-mail address", - "data": "2962", - "valid": false, - "schema_id": "format_7_0" - }, - { - "description": "a valid e-mail address", - "data": "joe.bloggs@example.com", - "valid": true, - "schema_id": "format_7_0" - }, - { - "description": "an invalid e-mail address", - "data": "2962", - "valid": false, - "schema_id": "format_7_0" - } - ] - }, - { - "description": "validation of internationalized host names", - "database": { - "schemas": [ - { - "format": "idn-hostname", - "$id": "format_8_0" - } - ] - }, - "tests": [ - { - "description": "all string formats ignore integers", - "data": 12, - "valid": true, - "schema_id": "format_8_0" - }, - { - "description": "all string formats ignore floats", - "data": 13.7, - "valid": true, - "schema_id": "format_8_0" - }, - { - "description": "all string formats ignore objects", - "data": {}, - "valid": true, - "schema_id": "format_8_0" - }, - { - "description": "all string formats ignore arrays", - "data": [], - "valid": true, - "schema_id": "format_8_0" - }, - { - "description": "all string formats ignore booleans", - "data": false, - "valid": true, - "schema_id": "format_8_0" - }, - { - "description": "all string formats ignore nulls", - "data": null, - "valid": true, - "schema_id": "format_8_0" - }, - { - "description": "a valid host name (example.test in Hangul)", - "data": "실례.테스트", - "valid": true, - "schema_id": "format_8_0" - }, - { - "description": "illegal first char U+302E Hangul single dot tone mark", - "data": "〮실례.테스트", - "valid": false, - "schema_id": "format_8_0" - }, - { - "description": "contains illegal char U+302E Hangul single dot tone mark", - "data": "실〮례.테스트", - "valid": false, - "schema_id": "format_8_0" - }, - { - "description": "a host name with a component too long", - "data": "실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실례례테스트례례례례례례례례례례례례례례례례례테스트례례례례례례례례례례례례례례례례례례례테스트례례례례례례례례례례례례테스트례례실례.테스트", - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "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, - "schema_id": "format_8_0" - }, - { - "description": "single label", - "data": "hostname", - "valid": true, - "schema_id": "format_8_0" - }, - { - "description": "single label with hyphen", - "data": "host-name", - "valid": true, - "schema_id": "format_8_0" - }, - { - "description": "single label with digits", - "data": "h0stn4me", - "valid": true, - "schema_id": "format_8_0" - }, - { - "description": "single label starting with digit", - "data": "1host", - "valid": true, - "schema_id": "format_8_0" - }, - { - "description": "single label ending with digit", - "data": "hostnam3", - "valid": true, - "schema_id": "format_8_0" - }, - { - "description": "empty string", - "data": "", - "valid": true, - "schema_id": "format_8_0" - } - ] - }, - { - "description": "validation of separators in internationalized host names", - "specification": [ - { - "rfc3490": "3.1", - "quote": "Whenever dots are used as label separators, the following characters MUST be recognized as dots: U+002E (full stop), U+3002 (ideographic full stop), U+FF0E (fullwidth full stop), U+FF61(halfwidth ideographic full stop)" - } - ], - "database": { - "schemas": [ - { - "format": "idn-hostname", - "$id": "format_9_0" - } - ] - }, - "tests": [ - { - "description": "single dot", - "data": ".", - "valid": false, - "schema_id": "format_9_0" - }, - { - "description": "single ideographic full stop", - "data": "。", - "valid": false, - "schema_id": "format_9_0" - }, - { - "description": "single fullwidth full stop", - "data": ".", - "valid": false, - "schema_id": "format_9_0" - }, - { - "description": "single halfwidth ideographic full stop", - "data": "。", - "valid": false, - "schema_id": "format_9_0" - }, - { - "description": "dot as label separator", - "data": "a.b", - "valid": true, - "schema_id": "format_9_0" - }, - { - "description": "ideographic full stop as label separator", - "data": "a。b", - "valid": true, - "schema_id": "format_9_0" - }, - { - "description": "fullwidth full stop as label separator", - "data": "a.b", - "valid": true, - "schema_id": "format_9_0" - }, - { - "description": "halfwidth ideographic full stop as label separator", - "data": "a。b", - "valid": true, - "schema_id": "format_9_0" - }, - { - "description": "leading dot", - "data": ".example", - "valid": false, - "schema_id": "format_9_0" - }, - { - "description": "leading ideographic full stop", - "data": "。example", - "valid": false, - "schema_id": "format_9_0" - }, - { - "description": "leading fullwidth full stop", - "data": ".example", - "valid": false, - "schema_id": "format_9_0" - }, - { - "description": "leading halfwidth ideographic full stop", - "data": "。example", - "valid": false, - "schema_id": "format_9_0" - }, - { - "description": "trailing dot", - "data": "example.", - "valid": false, - "schema_id": "format_9_0" - }, - { - "description": "trailing ideographic full stop", - "data": "example。", - "valid": false, - "schema_id": "format_9_0" - }, - { - "description": "trailing fullwidth full stop", - "data": "example.", - "valid": false, - "schema_id": "format_9_0" - }, - { - "description": "trailing halfwidth ideographic full stop", - "data": "example。", - "valid": false, - "schema_id": "format_9_0" - }, - { - "description": "label too long if separator ignored (full stop)", - "data": "παράδειγμαπαράδειγμαπαράδειγμαπαράδειγμαπαράδειγμαπα.com", - "valid": true, - "schema_id": "format_9_0" - }, - { - "description": "label too long if separator ignored (ideographic full stop)", - "data": "παράδειγμαπαράδειγμαπαράδειγμαπαράδειγμαπαράδειγμαπα。com", - "valid": true, - "schema_id": "format_9_0" - }, - { - "description": "label too long if separator ignored (fullwidth full stop)", - "data": "παράδειγμαπαράδειγμαπαράδειγμαπαράδειγμαπαράδειγμαπα.com", - "valid": true, - "schema_id": "format_9_0" - }, - { - "description": "label too long if separator ignored (halfwidth ideographic full stop)", - "data": "παράδειγμαπαράδειγμαπαράδειγμαπαράδειγμαπαράδειγμαπα。com", - "valid": true, - "schema_id": "format_9_0" - } - ] - }, - { - "description": "validation of IP addresses", - "database": { - "schemas": [ - { - "format": "ipv4", - "$id": "format_10_0" - } - ] - }, - "tests": [ - { - "description": "all string formats ignore integers", - "data": 12, - "valid": true, - "schema_id": "format_10_0" - }, - { - "description": "all string formats ignore floats", - "data": 13.7, - "valid": true, - "schema_id": "format_10_0" - }, - { - "description": "all string formats ignore objects", - "data": {}, - "valid": true, - "schema_id": "format_10_0" - }, - { - "description": "all string formats ignore arrays", - "data": [], - "valid": true, - "schema_id": "format_10_0" - }, - { - "description": "all string formats ignore booleans", - "data": false, - "valid": true, - "schema_id": "format_10_0" - }, - { - "description": "all string formats ignore nulls", - "data": null, - "valid": true, - "schema_id": "format_10_0" - }, - { - "description": "a valid IP address", - "data": "192.168.0.1", - "valid": true, - "schema_id": "format_10_0" - }, - { - "description": "an IP address with too many components", - "data": "127.0.0.0.1", - "valid": false, - "schema_id": "format_10_0" - }, - { - "description": "an IP address with out-of-range values", - "data": "256.256.256.256", - "valid": false, - "schema_id": "format_10_0" - }, - { - "description": "an IP address without 4 components", - "data": "127.0", - "valid": false, - "schema_id": "format_10_0" - }, - { - "description": "an IP address as an integer", - "data": "0x7f000001", - "valid": false, - "schema_id": "format_10_0" - }, - { - "description": "an IP address as an integer (decimal)", - "data": "2130706433", - "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, - "schema_id": "format_10_0" - }, - { - "description": "value without leading zero is valid", - "data": "87.10.0.1", - "valid": true, - "schema_id": "format_10_0" - }, - { - "description": "invalid non-ASCII '২' (a Bengali 2)", - "data": "1২7.0.0.1", - "valid": false, - "schema_id": "format_10_0" - }, - { - "description": "netmask is not a part of ipv4 address", - "data": "192.168.1.0/24", - "valid": false, - "schema_id": "format_10_0" - } - ] - }, - { - "description": "validation of IPv6 addresses", - "database": { - "schemas": [ - { - "format": "ipv6", - "$id": "format_11_0" - } - ] - }, - "tests": [ - { - "description": "all string formats ignore integers", - "data": 12, - "valid": true, - "schema_id": "format_11_0" - }, - { - "description": "all string formats ignore floats", - "data": 13.7, - "valid": true, - "schema_id": "format_11_0" - }, - { - "description": "all string formats ignore objects", - "data": {}, - "valid": true, - "schema_id": "format_11_0" - }, - { - "description": "all string formats ignore arrays", - "data": [], - "valid": true, - "schema_id": "format_11_0" - }, - { - "description": "all string formats ignore booleans", - "data": false, - "valid": true, - "schema_id": "format_11_0" - }, - { - "description": "all string formats ignore nulls", - "data": null, - "valid": true, - "schema_id": "format_11_0" - }, - { - "description": "a valid IPv6 address", - "data": "::1", - "valid": true, - "schema_id": "format_11_0" - }, - { - "description": "an IPv6 address with out-of-range values", - "data": "12345::", - "valid": false, - "schema_id": "format_11_0" - }, - { - "description": "trailing 4 hex symbols is valid", - "data": "::abef", - "valid": true, - "schema_id": "format_11_0" - }, - { - "description": "trailing 5 hex symbols is invalid", - "data": "::abcef", - "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, - "schema_id": "format_11_0" - }, - { - "description": "an IPv6 address containing illegal characters", - "data": "::laptop", - "valid": false, - "schema_id": "format_11_0" - }, - { - "description": "no digits is valid", - "data": "::", - "valid": true, - "schema_id": "format_11_0" - }, - { - "description": "leading colons is valid", - "data": "::42:ff:1", - "valid": true, - "schema_id": "format_11_0" - }, - { - "description": "trailing colons is valid", - "data": "d6::", - "valid": true, - "schema_id": "format_11_0" - }, - { - "description": "missing leading octet is invalid", - "data": ":2:3:4:5:6:7:8", - "valid": false, - "schema_id": "format_11_0" - }, - { - "description": "missing trailing octet is invalid", - "data": "1:2:3:4:5:6:7:", - "valid": false, - "schema_id": "format_11_0" - }, - { - "description": "missing leading octet with omitted octets later", - "data": ":2:3:4::8", - "valid": false, - "schema_id": "format_11_0" - }, - { - "description": "single set of double colons in the middle is valid", - "data": "1:d6::42", - "valid": true, - "schema_id": "format_11_0" - }, - { - "description": "two sets of double colons is invalid", - "data": "1::d6::42", - "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, - "schema_id": "format_11_0" - }, - { - "description": "mixed format with double colons between the sections", - "data": "1:2::192.168.0.1", - "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, - "schema_id": "format_11_0" - }, - { - "description": "mixed format with ipv4 section with a hex octet", - "data": "1::2:192.168.ff.1", - "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, - "schema_id": "format_11_0" - }, - { - "description": "triple colons is invalid", - "data": "1:2:3:4:5:::8", - "valid": false, - "schema_id": "format_11_0" - }, - { - "description": "8 octets", - "data": "1:2:3:4:5:6:7:8", - "valid": true, - "schema_id": "format_11_0" - }, - { - "description": "insufficient octets without double colons", - "data": "1:2:3:4:5:6:7", - "valid": false, - "schema_id": "format_11_0" - }, - { - "description": "no colons is invalid", - "data": "1", - "valid": false, - "schema_id": "format_11_0" - }, - { - "description": "ipv4 is not ipv6", - "data": "127.0.0.1", - "valid": false, - "schema_id": "format_11_0" - }, - { - "description": "ipv4 segment must have 4 octets", - "data": "1:2:3:4:1.2.3", - "valid": false, - "schema_id": "format_11_0" - }, - { - "description": "leading whitespace is invalid", - "data": " ::1", - "valid": false, - "schema_id": "format_11_0" - }, - { - "description": "trailing whitespace is invalid", - "data": "::1 ", - "valid": false, - "schema_id": "format_11_0" - }, - { - "description": "netmask is not a part of ipv6 address", - "data": "fe80::/64", - "valid": false, - "schema_id": "format_11_0" - }, - { - "description": "zone id is not a part of ipv6 address", - "data": "fe80::a%eth1", - "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, - "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, - "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, - "schema_id": "format_11_0" - }, - { - "description": "invalid non-ASCII '৪' (a Bengali 4)", - "data": "1:2:3:4:5:6:7:৪", - "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, - "schema_id": "format_11_0" - } - ] - }, - { - "description": "validation of IRI References", - "database": { - "schemas": [ - { - "format": "iri-reference", - "$id": "format_12_0" - } - ] - }, - "tests": [ - { - "description": "all string formats ignore integers", - "data": 12, - "valid": true, - "schema_id": "format_12_0" - }, - { - "description": "all string formats ignore floats", - "data": 13.7, - "valid": true, - "schema_id": "format_12_0" - }, - { - "description": "all string formats ignore objects", - "data": {}, - "valid": true, - "schema_id": "format_12_0" - }, - { - "description": "all string formats ignore arrays", - "data": [], - "valid": true, - "schema_id": "format_12_0" - }, - { - "description": "all string formats ignore booleans", - "data": false, - "valid": true, - "schema_id": "format_12_0" - }, - { - "description": "all string formats ignore nulls", - "data": null, - "valid": true, - "schema_id": "format_12_0" - }, - { - "description": "a valid IRI", - "data": "http://ƒøø.ßår/?∂éœ=πîx#πîüx", - "valid": true, - "schema_id": "format_12_0" - }, - { - "description": "a valid protocol-relative IRI Reference", - "data": "//ƒøø.ßår/?∂éœ=πîx#πîüx", - "valid": true, - "schema_id": "format_12_0" - }, - { - "description": "a valid relative IRI Reference", - "data": "/âππ", - "valid": true, - "schema_id": "format_12_0" - }, - { - "description": "an invalid IRI Reference", - "data": "\\\\WINDOWS\\filëßåré", - "valid": false, - "schema_id": "format_12_0" - }, - { - "description": "a valid IRI Reference", - "data": "âππ", - "valid": true, - "schema_id": "format_12_0" - }, - { - "description": "a valid IRI fragment", - "data": "#ƒrägmênt", - "valid": true, - "schema_id": "format_12_0" - }, - { - "description": "an invalid IRI fragment", - "data": "#ƒräg\\mênt", - "valid": false, - "schema_id": "format_12_0" - } - ] - }, - { - "description": "validation of IRIs", - "database": { - "schemas": [ - { - "format": "iri", - "$id": "format_13_0" - } - ] - }, - "tests": [ - { - "description": "all string formats ignore integers", - "data": 12, - "valid": true, - "schema_id": "format_13_0" - }, - { - "description": "all string formats ignore floats", - "data": 13.7, - "valid": true, - "schema_id": "format_13_0" - }, - { - "description": "all string formats ignore objects", - "data": {}, - "valid": true, - "schema_id": "format_13_0" - }, - { - "description": "all string formats ignore arrays", - "data": [], - "valid": true, - "schema_id": "format_13_0" - }, - { - "description": "all string formats ignore booleans", - "data": false, - "valid": true, - "schema_id": "format_13_0" - }, - { - "description": "all string formats ignore nulls", - "data": null, - "valid": true, - "schema_id": "format_13_0" - }, - { - "description": "a valid IRI with anchor tag", - "data": "http://ƒøø.ßår/?∂éœ=πîx#πîüx", - "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, - "schema_id": "format_13_0" - }, - { - "description": "a valid IRI with URL-encoded stuff", - "data": "http://ƒøø.ßår/?q=Test%20URL-encoded%20stuff", - "valid": true, - "schema_id": "format_13_0" - }, - { - "description": "a valid IRI with many special characters", - "data": "http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com", - "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, - "schema_id": "format_13_0" - }, - { - "description": "an invalid IRI based on IPv6", - "data": "http://2001:0db8:85a3:0000:0000:8a2e:0370:7334", - "valid": false, - "schema_id": "format_13_0" - }, - { - "description": "an invalid relative IRI Reference", - "data": "/abc", - "valid": false, - "schema_id": "format_13_0" - }, - { - "description": "an invalid IRI", - "data": "\\\\WINDOWS\\filëßåré", - "valid": false, - "schema_id": "format_13_0" - }, - { - "description": "an invalid IRI though valid IRI reference", - "data": "âππ", - "valid": false, - "schema_id": "format_13_0" - } - ] - }, - { - "description": "validation of JSON-pointers (JSON String Representation)", - "database": { - "schemas": [ - { - "format": "json-pointer", - "$id": "format_14_0" - } - ] - }, - "tests": [ - { - "description": "all string formats ignore integers", - "data": 12, - "valid": true, - "schema_id": "format_14_0" - }, - { - "description": "all string formats ignore floats", - "data": 13.7, - "valid": true, - "schema_id": "format_14_0" - }, - { - "description": "all string formats ignore objects", - "data": {}, - "valid": true, - "schema_id": "format_14_0" - }, - { - "description": "all string formats ignore arrays", - "data": [], - "valid": true, - "schema_id": "format_14_0" - }, - { - "description": "all string formats ignore booleans", - "data": false, - "valid": true, - "schema_id": "format_14_0" - }, - { - "description": "all string formats ignore nulls", - "data": null, - "valid": true, - "schema_id": "format_14_0" - }, - { - "description": "a valid JSON-pointer", - "data": "/foo/bar~0/baz~1/%a", - "valid": true, - "schema_id": "format_14_0" - }, - { - "description": "not a valid JSON-pointer (~ not escaped)", - "data": "/foo/bar~", - "valid": false, - "schema_id": "format_14_0" - }, - { - "description": "valid JSON-pointer with empty segment", - "data": "/foo//bar", - "valid": true, - "schema_id": "format_14_0" - }, - { - "description": "valid JSON-pointer with the last empty segment", - "data": "/foo/bar/", - "valid": true, - "schema_id": "format_14_0" - }, - { - "description": "valid JSON-pointer as stated in RFC 6901 #1", - "data": "", - "valid": true, - "schema_id": "format_14_0" - }, - { - "description": "valid JSON-pointer as stated in RFC 6901 #2", - "data": "/foo", - "valid": true, - "schema_id": "format_14_0" - }, - { - "description": "valid JSON-pointer as stated in RFC 6901 #3", - "data": "/foo/0", - "valid": true, - "schema_id": "format_14_0" - }, - { - "description": "valid JSON-pointer as stated in RFC 6901 #4", - "data": "/", - "valid": true, - "schema_id": "format_14_0" - }, - { - "description": "valid JSON-pointer as stated in RFC 6901 #5", - "data": "/a~1b", - "valid": true, - "schema_id": "format_14_0" - }, - { - "description": "valid JSON-pointer as stated in RFC 6901 #6", - "data": "/c%d", - "valid": true, - "schema_id": "format_14_0" - }, - { - "description": "valid JSON-pointer as stated in RFC 6901 #7", - "data": "/e^f", - "valid": true, - "schema_id": "format_14_0" - }, - { - "description": "valid JSON-pointer as stated in RFC 6901 #8", - "data": "/g|h", - "valid": true, - "schema_id": "format_14_0" - }, - { - "description": "valid JSON-pointer as stated in RFC 6901 #9", - "data": "/i\\j", - "valid": true, - "schema_id": "format_14_0" - }, - { - "description": "valid JSON-pointer as stated in RFC 6901 #10", - "data": "/k\"l", - "valid": true, - "schema_id": "format_14_0" - }, - { - "description": "valid JSON-pointer as stated in RFC 6901 #11", - "data": "/ ", - "valid": true, - "schema_id": "format_14_0" - }, - { - "description": "valid JSON-pointer as stated in RFC 6901 #12", - "data": "/m~0n", - "valid": true, - "schema_id": "format_14_0" - }, - { - "description": "valid JSON-pointer used adding to the last array position", - "data": "/foo/-", - "valid": true, - "schema_id": "format_14_0" - }, - { - "description": "valid JSON-pointer (- used as object member name)", - "data": "/foo/-/bar", - "valid": true, - "schema_id": "format_14_0" - }, - { - "description": "valid JSON-pointer (multiple escaped characters)", - "data": "/~1~0~0~1~1", - "valid": true, - "schema_id": "format_14_0" - }, - { - "description": "valid JSON-pointer (escaped with fraction part) #1", - "data": "/~1.1", - "valid": true, - "schema_id": "format_14_0" - }, - { - "description": "valid JSON-pointer (escaped with fraction part) #2", - "data": "/~0.1", - "valid": true, - "schema_id": "format_14_0" - }, - { - "description": "not a valid JSON-pointer (URI Fragment Identifier) #1", - "data": "#", - "valid": false, - "schema_id": "format_14_0" - }, - { - "description": "not a valid JSON-pointer (URI Fragment Identifier) #2", - "data": "#/", - "valid": false, - "schema_id": "format_14_0" - }, - { - "description": "not a valid JSON-pointer (URI Fragment Identifier) #3", - "data": "#a", - "valid": false, - "schema_id": "format_14_0" - }, - { - "description": "not a valid JSON-pointer (some escaped, but not all) #1", - "data": "/~0~", - "valid": false, - "schema_id": "format_14_0" - }, - { - "description": "not a valid JSON-pointer (some escaped, but not all) #2", - "data": "/~0/~", - "valid": false, - "schema_id": "format_14_0" - }, - { - "description": "not a valid JSON-pointer (wrong escape character) #1", - "data": "/~2", - "valid": false, - "schema_id": "format_14_0" - }, - { - "description": "not a valid JSON-pointer (wrong escape character) #2", - "data": "/~-1", - "valid": false, - "schema_id": "format_14_0" - }, - { - "description": "not a valid JSON-pointer (multiple characters not escaped)", - "data": "/~~", - "valid": false, - "schema_id": "format_14_0" - }, - { - "description": "not a valid JSON-pointer (isn't empty nor starts with /) #1", - "data": "a", - "valid": false, - "schema_id": "format_14_0" - }, - { - "description": "not a valid JSON-pointer (isn't empty nor starts with /) #2", - "data": "0", - "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, - "schema_id": "format_14_0" - } - ] - }, - { - "description": "validation of regular expressions", - "database": { - "schemas": [ - { - "format": "regex", - "$id": "format_15_0" - } - ] - }, - "tests": [ - { - "description": "all string formats ignore integers", - "data": 12, - "valid": true, - "schema_id": "format_15_0" - }, - { - "description": "all string formats ignore floats", - "data": 13.7, - "valid": true, - "schema_id": "format_15_0" - }, - { - "description": "all string formats ignore objects", - "data": {}, - "valid": true, - "schema_id": "format_15_0" - }, - { - "description": "all string formats ignore arrays", - "data": [], - "valid": true, - "schema_id": "format_15_0" - }, - { - "description": "all string formats ignore booleans", - "data": false, - "valid": true, - "schema_id": "format_15_0" - }, - { - "description": "all string formats ignore nulls", - "data": null, - "valid": true, - "schema_id": "format_15_0" - }, - { - "description": "a valid regular expression", - "data": "([abc])+\\s+$", - "valid": true, - "schema_id": "format_15_0" - }, - { - "description": "a regular expression with unclosed parens is invalid", - "data": "^(abc]", - "valid": true, - "schema_id": "format_15_0" - } - ] - }, - { - "description": "validation of Relative JSON Pointers (RJP)", - "database": { - "schemas": [ - { - "format": "relative-json-pointer", - "$id": "format_16_0" - } - ] - }, - "tests": [ - { - "description": "all string formats ignore integers", - "data": 12, - "valid": true, - "schema_id": "format_16_0" - }, - { - "description": "all string formats ignore floats", - "data": 13.7, - "valid": true, - "schema_id": "format_16_0" - }, - { - "description": "all string formats ignore objects", - "data": {}, - "valid": true, - "schema_id": "format_16_0" - }, - { - "description": "all string formats ignore arrays", - "data": [], - "valid": true, - "schema_id": "format_16_0" - }, - { - "description": "all string formats ignore booleans", - "data": false, - "valid": true, - "schema_id": "format_16_0" - }, - { - "description": "all string formats ignore nulls", - "data": null, - "valid": true, - "schema_id": "format_16_0" - }, - { - "description": "a valid upwards RJP", - "data": "1", - "valid": true, - "schema_id": "format_16_0" - }, - { - "description": "a valid downwards RJP", - "data": "0/foo/bar", - "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, - "schema_id": "format_16_0" - }, - { - "description": "a valid RJP taking the member or index name", - "data": "0#", - "valid": true, - "schema_id": "format_16_0" - }, - { - "description": "an invalid RJP that is a valid JSON Pointer", - "data": "/foo/bar", - "valid": false, - "schema_id": "format_16_0" - }, - { - "description": "negative prefix", - "data": "-1/foo/bar", - "valid": false, - "schema_id": "format_16_0" - }, - { - "description": "explicit positive prefix", - "data": "+1/foo/bar", - "valid": false, - "schema_id": "format_16_0" - }, - { - "description": "## is not a valid json-pointer", - "data": "0##", - "valid": false, - "schema_id": "format_16_0" - }, - { - "description": "zero cannot be followed by other digits, plus json-pointer", - "data": "01/a", - "valid": false, - "schema_id": "format_16_0" - }, - { - "description": "zero cannot be followed by other digits, plus octothorpe", - "data": "01#", - "valid": false, - "schema_id": "format_16_0" - }, - { - "description": "empty string", - "data": "", - "valid": true, - "schema_id": "format_16_0" - }, - { - "description": "multi-digit integer prefix", - "data": "120/foo/bar", - "valid": true, - "schema_id": "format_16_0" - } - ] - }, - { - "description": "validation of time strings", - "database": { - "schemas": [ - { - "format": "time", - "$id": "format_17_0" - } - ] - }, - "tests": [ - { - "description": "all string formats ignore integers", - "data": 12, - "valid": true, - "schema_id": "format_17_0" - }, - { - "description": "all string formats ignore floats", - "data": 13.7, - "valid": true, - "schema_id": "format_17_0" - }, - { - "description": "all string formats ignore objects", - "data": {}, - "valid": true, - "schema_id": "format_17_0" - }, - { - "description": "all string formats ignore arrays", - "data": [], - "valid": true, - "schema_id": "format_17_0" - }, - { - "description": "all string formats ignore booleans", - "data": false, - "valid": true, - "schema_id": "format_17_0" - }, - { - "description": "all string formats ignore nulls", - "data": null, - "valid": true, - "schema_id": "format_17_0" - }, - { - "description": "a valid time string", - "data": "08:30:06Z", - "valid": true, - "schema_id": "format_17_0" - }, - { - "description": "invalid time string with extra leading zeros", - "data": "008:030:006Z", - "valid": false, - "schema_id": "format_17_0" - }, - { - "description": "invalid time string with no leading zero for single digit", - "data": "8:3:6Z", - "valid": false, - "schema_id": "format_17_0" - }, - { - "description": "hour, minute, second must be two digits", - "data": "8:0030:6Z", - "valid": false, - "schema_id": "format_17_0" - }, - { - "description": "a valid time string with leap second, Zulu", - "data": "23:59:60Z", - "valid": true, - "schema_id": "format_17_0" - }, - { - "description": "invalid leap second, Zulu (wrong hour)", - "data": "22:59:60Z", - "valid": false, - "schema_id": "format_17_0" - }, - { - "description": "invalid leap second, Zulu (wrong minute)", - "data": "23:58:60Z", - "valid": false, - "schema_id": "format_17_0" - }, - { - "description": "valid leap second, zero time-offset", - "data": "23:59:60+00:00", - "valid": true, - "schema_id": "format_17_0" - }, - { - "description": "invalid leap second, zero time-offset (wrong hour)", - "data": "22:59:60+00:00", - "valid": false, - "schema_id": "format_17_0" - }, - { - "description": "invalid leap second, zero time-offset (wrong minute)", - "data": "23:58:60+00:00", - "valid": false, - "schema_id": "format_17_0" - }, - { - "description": "valid leap second, positive time-offset", - "data": "01:29:60+01:30", - "valid": true, - "schema_id": "format_17_0" - }, - { - "description": "valid leap second, large positive time-offset", - "data": "23:29:60+23:30", - "valid": true, - "schema_id": "format_17_0" - }, - { - "description": "invalid leap second, positive time-offset (wrong hour)", - "data": "23:59:60+01:00", - "valid": false, - "schema_id": "format_17_0" - }, - { - "description": "invalid leap second, positive time-offset (wrong minute)", - "data": "23:59:60+00:30", - "valid": false, - "schema_id": "format_17_0" - }, - { - "description": "valid leap second, negative time-offset", - "data": "15:59:60-08:00", - "valid": true, - "schema_id": "format_17_0" - }, - { - "description": "valid leap second, large negative time-offset", - "data": "00:29:60-23:30", - "valid": true, - "schema_id": "format_17_0" - }, - { - "description": "invalid leap second, negative time-offset (wrong hour)", - "data": "23:59:60-01:00", - "valid": false, - "schema_id": "format_17_0" - }, - { - "description": "invalid leap second, negative time-offset (wrong minute)", - "data": "23:59:60-00:30", - "valid": false, - "schema_id": "format_17_0" - }, - { - "description": "a valid time string with second fraction", - "data": "23:20:50.52Z", - "valid": true, - "schema_id": "format_17_0" - }, - { - "description": "a valid time string with precise second fraction", - "data": "08:30:06.283185Z", - "valid": true, - "schema_id": "format_17_0" - }, - { - "description": "a valid time string with plus offset", - "data": "08:30:06+00:20", - "valid": true, - "schema_id": "format_17_0" - }, - { - "description": "a valid time string with minus offset", - "data": "08:30:06-08:00", - "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, - "schema_id": "format_17_0" - }, - { - "description": "a valid time string with case-insensitive Z", - "data": "08:30:06z", - "valid": true, - "schema_id": "format_17_0" - }, - { - "description": "an invalid time string with invalid hour", - "data": "24:00:00Z", - "valid": false, - "schema_id": "format_17_0" - }, - { - "description": "an invalid time string with invalid minute", - "data": "00:60:00Z", - "valid": false, - "schema_id": "format_17_0" - }, - { - "description": "an invalid time string with invalid second", - "data": "00:00:61Z", - "valid": false, - "schema_id": "format_17_0" - }, - { - "description": "an invalid time string with invalid leap second (wrong hour)", - "data": "22:59:60Z", - "valid": false, - "schema_id": "format_17_0" - }, - { - "description": "an invalid time string with invalid leap second (wrong minute)", - "data": "23:58:60Z", - "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, - "schema_id": "format_17_0" - }, - { - "description": "an invalid time string with invalid time numoffset minute", - "data": "01:02:03+00:60", - "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, - "schema_id": "format_17_0" - }, - { - "description": "an invalid offset indicator", - "data": "08:30:06 PST", - "valid": false, - "schema_id": "format_17_0" - }, - { - "description": "only RFC3339 not all of ISO 8601 are valid", - "data": "01:01:01,1111", - "valid": false, - "schema_id": "format_17_0" - }, - { - "description": "no time offset", - "data": "12:00:00", - "valid": false, - "schema_id": "format_17_0" - }, - { - "description": "no time offset with second fraction", - "data": "12:00:00.52", - "valid": false, - "schema_id": "format_17_0" - }, - { - "description": "invalid non-ASCII '২' (a Bengali 2)", - "data": "1২:00:00Z", - "valid": false, - "schema_id": "format_17_0" - }, - { - "description": "offset not starting with plus or minus", - "data": "08:30:06#00:20", - "valid": false, - "schema_id": "format_17_0" - }, - { - "description": "contains letters", - "data": "ab:cd:ef", - "valid": false, - "schema_id": "format_17_0" - }, - { - "description": "an invalid time string in date-time format", - "data": "2020-11-28T23:55:45Z", - "valid": false, - "schema_id": "format_17_0" - } - ] - }, - { - "description": "unknown format", - "database": { - "schemas": [ - { - "format": "unknown", - "$id": "format_18_0" - } - ] - }, - "tests": [ - { - "description": "unknown formats ignore integers", - "data": 12, - "valid": true, - "schema_id": "format_18_0" - }, - { - "description": "unknown formats ignore floats", - "data": 13.7, - "valid": true, - "schema_id": "format_18_0" - }, - { - "description": "unknown formats ignore objects", - "data": {}, - "valid": true, - "schema_id": "format_18_0" - }, - { - "description": "unknown formats ignore arrays", - "data": [], - "valid": true, - "schema_id": "format_18_0" - }, - { - "description": "unknown formats ignore booleans", - "data": false, - "valid": true, - "schema_id": "format_18_0" - }, - { - "description": "unknown formats ignore nulls", - "data": null, - "valid": true, - "schema_id": "format_18_0" - }, - { - "description": "unknown formats ignore strings", - "data": "string", - "valid": true, - "schema_id": "format_18_0" - } - ] - }, - { - "description": "validation of URI References", - "database": { - "schemas": [ - { - "format": "uri-reference", - "$id": "format_19_0" - } - ] - }, - "tests": [ - { - "description": "all string formats ignore integers", - "data": 12, - "valid": true, - "schema_id": "format_19_0" - }, - { - "description": "all string formats ignore floats", - "data": 13.7, - "valid": true, - "schema_id": "format_19_0" - }, - { - "description": "all string formats ignore objects", - "data": {}, - "valid": true, - "schema_id": "format_19_0" - }, - { - "description": "all string formats ignore arrays", - "data": [], - "valid": true, - "schema_id": "format_19_0" - }, - { - "description": "all string formats ignore booleans", - "data": false, - "valid": true, - "schema_id": "format_19_0" - }, - { - "description": "all string formats ignore nulls", - "data": null, - "valid": true, - "schema_id": "format_19_0" - }, - { - "description": "a valid URI", - "data": "http://foo.bar/?baz=qux#quux", - "valid": true, - "schema_id": "format_19_0" - }, - { - "description": "a valid protocol-relative URI Reference", - "data": "//foo.bar/?baz=qux#quux", - "valid": true, - "schema_id": "format_19_0" - }, - { - "description": "a valid relative URI Reference", - "data": "/abc", - "valid": true, - "schema_id": "format_19_0" - }, - { - "description": "an invalid URI Reference", - "data": "\\\\WINDOWS\\fileshare", - "valid": false, - "schema_id": "format_19_0" - }, - { - "description": "a valid URI Reference", - "data": "abc", - "valid": true, - "schema_id": "format_19_0" - }, - { - "description": "a valid URI fragment", - "data": "#fragment", - "valid": true, - "schema_id": "format_19_0" - }, - { - "description": "an invalid URI fragment", - "data": "#frag\\ment", - "valid": false, - "schema_id": "format_19_0" - }, - { - "description": "unescaped non US-ASCII characters", - "data": "/foobar®.txt", - "valid": false, - "schema_id": "format_19_0" - }, - { - "description": "invalid backslash character", - "data": "https://example.org/foobar\\.txt", - "valid": false, - "schema_id": "format_19_0" - } - ] - }, - { - "description": "format: uri-template", - "database": { - "schemas": [ - { - "format": "uri-template", - "$id": "format_20_0" - } - ] - }, - "tests": [ - { - "description": "all string formats ignore integers", - "data": 12, - "valid": true, - "schema_id": "format_20_0" - }, - { - "description": "all string formats ignore floats", - "data": 13.7, - "valid": true, - "schema_id": "format_20_0" - }, - { - "description": "all string formats ignore objects", - "data": {}, - "valid": true, - "schema_id": "format_20_0" - }, - { - "description": "all string formats ignore arrays", - "data": [], - "valid": true, - "schema_id": "format_20_0" - }, - { - "description": "all string formats ignore booleans", - "data": false, - "valid": true, - "schema_id": "format_20_0" - }, - { - "description": "all string formats ignore nulls", - "data": null, - "valid": true, - "schema_id": "format_20_0" - }, - { - "description": "a valid uri-template", - "data": "http://example.com/dictionary/{term:1}/{term}", - "valid": true, - "schema_id": "format_20_0" - }, - { - "description": "an invalid uri-template", - "data": "http://example.com/dictionary/{term:1}/{term", - "valid": false, - "schema_id": "format_20_0" - }, - { - "description": "a valid uri-template without variables", - "data": "http://example.com/dictionary", - "valid": true, - "schema_id": "format_20_0" - }, - { - "description": "a valid relative uri-template", - "data": "dictionary/{term:1}/{term}", - "valid": true, - "schema_id": "format_20_0" - } - ] - }, - { - "description": "validation of URIs", - "database": { - "schemas": [ - { - "format": "uri", - "$id": "format_21_0" - } - ] - }, - "tests": [ - { - "description": "all string formats ignore integers", - "data": 12, - "valid": true, - "schema_id": "format_21_0" - }, - { - "description": "all string formats ignore floats", - "data": 13.7, - "valid": true, - "schema_id": "format_21_0" - }, - { - "description": "all string formats ignore objects", - "data": {}, - "valid": true, - "schema_id": "format_21_0" - }, - { - "description": "all string formats ignore arrays", - "data": [], - "valid": true, - "schema_id": "format_21_0" - }, - { - "description": "all string formats ignore booleans", - "data": false, - "valid": true, - "schema_id": "format_21_0" - }, - { - "description": "all string formats ignore nulls", - "data": null, - "valid": true, - "schema_id": "format_21_0" - }, - { - "description": "a valid URL with anchor tag", - "data": "http://foo.bar/?baz=qux#quux", - "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, - "schema_id": "format_21_0" - }, - { - "description": "a valid URL with URL-encoded stuff", - "data": "http://foo.bar/?q=Test%20URL-encoded%20stuff", - "valid": true, - "schema_id": "format_21_0" - }, - { - "description": "a valid puny-coded URL ", - "data": "http://xn--nw2a.xn--j6w193g/", - "valid": true, - "schema_id": "format_21_0" - }, - { - "description": "a valid URL with many special characters", - "data": "http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com", - "valid": true, - "schema_id": "format_21_0" - }, - { - "description": "a valid URL based on IPv4", - "data": "http://223.255.255.254", - "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, - "schema_id": "format_21_0" - }, - { - "description": "a valid URL for a simple text file", - "data": "http://www.ietf.org/rfc/rfc2396.txt", - "valid": true, - "schema_id": "format_21_0" - }, - { - "description": "a valid URL ", - "data": "ldap://[2001:db8::7]/c=GB?objectClass?one", - "valid": true, - "schema_id": "format_21_0" - }, - { - "description": "a valid mailto URI", - "data": "mailto:John.Doe@example.com", - "valid": true, - "schema_id": "format_21_0" - }, - { - "description": "a valid newsgroup URI", - "data": "news:comp.infosystems.www.servers.unix", - "valid": true, - "schema_id": "format_21_0" - }, - { - "description": "a valid tel URI", - "data": "tel:+1-816-555-1212", - "valid": true, - "schema_id": "format_21_0" - }, - { - "description": "a valid URN", - "data": "urn:oasis:names:specification:docbook:dtd:xml:4.1.2", - "valid": true, - "schema_id": "format_21_0" - }, - { - "description": "an invalid protocol-relative URI Reference", - "data": "//foo.bar/?baz=qux#quux", - "valid": false, - "schema_id": "format_21_0" - }, - { - "description": "an invalid relative URI Reference", - "data": "/abc", - "valid": false, - "schema_id": "format_21_0" - }, - { - "description": "an invalid URI", - "data": "\\\\WINDOWS\\fileshare", - "valid": false, - "schema_id": "format_21_0" - }, - { - "description": "an invalid URI though valid URI reference", - "data": "abc", - "valid": false, - "schema_id": "format_21_0" - }, - { - "description": "an invalid URI with spaces", - "data": "http:// shouldfail.com", - "valid": false, - "schema_id": "format_21_0" - }, - { - "description": "an invalid URI with spaces and missing scheme", - "data": ":// should fail", - "valid": false, - "schema_id": "format_21_0" - }, - { - "description": "an invalid URI with comma in scheme", - "data": "bar,baz:foo", - "valid": false, - "schema_id": "format_21_0" - }, - { - "description": "invalid userinfo", - "data": "https://[@example.org/test.txt", - "valid": false, - "schema_id": "format_21_0" - }, - { - "description": "unescaped non US-ASCII characters", - "data": "https://example.org/foobar®.txt", - "valid": false, - "schema_id": "format_21_0" - }, - { - "description": "invalid backslash character", - "data": "https://example.org/foobar\\.txt", - "valid": false, - "schema_id": "format_21_0" - }, - { - "description": "invalid \" character", - "data": "https://example.org/foobar\".txt", - "valid": false, - "schema_id": "format_21_0" - }, - { - "description": "invalid <> characters", - "data": "https://example.org/foobar<>.txt", - "valid": false, - "schema_id": "format_21_0" - }, - { - "description": "invalid {} characters", - "data": "https://example.org/foobar{}.txt", - "valid": false, - "schema_id": "format_21_0" - }, - { - "description": "invalid ^ character", - "data": "https://example.org/foobar^.txt", - "valid": false, - "schema_id": "format_21_0" - }, - { - "description": "invalid ` character", - "data": "https://example.org/foobar`.txt", - "valid": false, - "schema_id": "format_21_0" - }, - { - "description": "invalid SPACE character", - "data": "https://example.org/foo bar.txt", - "valid": false, - "schema_id": "format_21_0" - }, - { - "description": "invalid | character", - "data": "https://example.org/foobar|.txt", - "valid": false, - "schema_id": "format_21_0" - } - ] - }, - { - "description": "uuid format", - "database": { - "schemas": [ - { - "format": "uuid", - "$id": "format_22_0" - } - ] - }, - "tests": [ - { - "description": "all string formats ignore integers", - "data": 12, - "valid": true, - "schema_id": "format_22_0" - }, - { - "description": "all string formats ignore floats", - "data": 13.7, - "valid": true, - "schema_id": "format_22_0" - }, - { - "description": "all string formats ignore objects", - "data": {}, - "valid": true, - "schema_id": "format_22_0" - }, - { - "description": "all string formats ignore arrays", - "data": [], - "valid": true, - "schema_id": "format_22_0" - }, - { - "description": "all string formats ignore booleans", - "data": false, - "valid": true, - "schema_id": "format_22_0" - }, - { - "description": "all string formats ignore nulls", - "data": null, - "valid": true, - "schema_id": "format_22_0" - }, - { - "description": "all upper-case", - "data": "2EB8AA08-AA98-11EA-B4AA-73B441D16380", - "valid": true, - "schema_id": "format_22_0" - }, - { - "description": "all lower-case", - "data": "2eb8aa08-aa98-11ea-b4aa-73b441d16380", - "valid": true, - "schema_id": "format_22_0" - }, - { - "description": "mixed case", - "data": "2eb8aa08-AA98-11ea-B4Aa-73B441D16380", - "valid": true, - "schema_id": "format_22_0" - }, - { - "description": "all zeroes is valid", - "data": "00000000-0000-0000-0000-000000000000", - "valid": true, - "schema_id": "format_22_0" - }, - { - "description": "wrong length", - "data": "2eb8aa08-aa98-11ea-b4aa-73b441d1638", - "valid": false, - "schema_id": "format_22_0" - }, - { - "description": "missing section", - "data": "2eb8aa08-aa98-11ea-73b441d16380", - "valid": false, - "schema_id": "format_22_0" - }, - { - "description": "bad characters (not hex)", - "data": "2eb8aa08-aa98-11ea-b4ga-73b441d16380", - "valid": false, - "schema_id": "format_22_0" - }, - { - "description": "no dashes", - "data": "2eb8aa08aa9811eab4aa73b441d16380", - "valid": false, - "schema_id": "format_22_0" - }, - { - "description": "too few dashes", - "data": "2eb8aa08aa98-11ea-b4aa73b441d16380", - "valid": false, - "schema_id": "format_22_0" - }, - { - "description": "too many dashes", - "data": "2eb8-aa08-aa98-11ea-b4aa73b44-1d16380", - "valid": false, - "schema_id": "format_22_0" - }, - { - "description": "dashes in the wrong spot", - "data": "2eb8aa08aa9811eab4aa73b441d16380----", - "valid": false, - "schema_id": "format_22_0" - }, - { - "description": "shifted dashes", - "data": "2eb8aa0-8aa98-11e-ab4aa7-3b441d16380", - "valid": false, - "schema_id": "format_22_0" - }, - { - "description": "valid version 4", - "data": "98d80576-482e-427f-8434-7f86890ab222", - "valid": true, - "schema_id": "format_22_0" - }, - { - "description": "valid version 5", - "data": "99c17cbb-656f-564a-940f-1a4568f03487", - "valid": true, - "schema_id": "format_22_0" - }, - { - "description": "hypothetical version 6", - "data": "99c17cbb-656f-664a-940f-1a4568f03487", - "valid": true, - "schema_id": "format_22_0" - }, - { - "description": "hypothetical version 15", - "data": "99c17cbb-656f-f64a-940f-1a4568f03487", - "valid": true, - "schema_id": "format_22_0" - } - ] - }, - { - "description": "period format", - "database": { - "schemas": [ - { - "format": "period", - "$id": "format_23_0" - } - ] - }, - "tests": [ - { - "description": "valid period (start/duration)", - "data": "2020-01-01T00:00:00Z/P1Y", - "valid": true, - "schema_id": "format_23_0" - }, - { - "description": "valid period (duration/end)", - "data": "P1Y/2021-01-01T00:00:00Z", - "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, - "schema_id": "format_23_0" - }, - { - "description": "invalid period (missing slash)", - "data": "2020-01-01T00:00:00ZP1Y", - "valid": false, - "schema_id": "format_23_0" - }, - { - "description": "ignores non-strings", - "data": 123, - "valid": true, - "schema_id": "format_23_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/if-then-else.json b/tests/fixtures/if-then-else.json deleted file mode 100644 index 5f724d2..0000000 --- a/tests/fixtures/if-then-else.json +++ /dev/null @@ -1,495 +0,0 @@ -[ - { - "description": "ignore if without then or else", - "database": { - "schemas": [ - { - "if": { - "const": 0 - }, - "$id": "if-then-else_0_0" - } - ] - }, - "tests": [ - { - "description": "valid when valid against lone if", - "data": 0, - "valid": true, - "schema_id": "if-then-else_0_0" - }, - { - "description": "valid when invalid against lone if", - "data": "hello", - "valid": true, - "schema_id": "if-then-else_0_0" - } - ] - }, - { - "description": "ignore then without if", - "database": { - "schemas": [ - { - "then": { - "const": 0 - }, - "$id": "if-then-else_1_0" - } - ] - }, - "tests": [ - { - "description": "valid when valid against lone then", - "data": 0, - "valid": true, - "schema_id": "if-then-else_1_0" - }, - { - "description": "valid when invalid against lone then", - "data": "hello", - "valid": true, - "schema_id": "if-then-else_1_0" - } - ] - }, - { - "description": "ignore else without if", - "database": { - "schemas": [ - { - "else": { - "const": 0 - }, - "$id": "if-then-else_2_0" - } - ] - }, - "tests": [ - { - "description": "valid when valid against lone else", - "data": 0, - "valid": true, - "schema_id": "if-then-else_2_0" - }, - { - "description": "valid when invalid against lone else", - "data": "hello", - "valid": true, - "schema_id": "if-then-else_2_0" - } - ] - }, - { - "description": "if and then without else", - "database": { - "schemas": [ - { - "if": { - "exclusiveMaximum": 0 - }, - "then": { - "minimum": -10 - }, - "$id": "if-then-else_3_0" - } - ] - }, - "tests": [ - { - "description": "valid through then", - "data": -1, - "valid": true, - "schema_id": "if-then-else_3_0" - }, - { - "description": "invalid through then", - "data": -100, - "valid": false, - "schema_id": "if-then-else_3_0" - }, - { - "description": "valid when if test fails", - "data": 3, - "valid": true, - "schema_id": "if-then-else_3_0" - } - ] - }, - { - "description": "if and else without then", - "database": { - "schemas": [ - { - "if": { - "exclusiveMaximum": 0 - }, - "else": { - "multipleOf": 2 - }, - "$id": "if-then-else_4_0" - } - ] - }, - "tests": [ - { - "description": "valid when if test passes", - "data": -1, - "valid": true, - "schema_id": "if-then-else_4_0" - }, - { - "description": "valid through else", - "data": 4, - "valid": true, - "schema_id": "if-then-else_4_0" - }, - { - "description": "invalid through else", - "data": 3, - "valid": false, - "schema_id": "if-then-else_4_0" - } - ] - }, - { - "description": "validate against correct branch, then vs else", - "database": { - "schemas": [ - { - "if": { - "exclusiveMaximum": 0 - }, - "then": { - "minimum": -10 - }, - "else": { - "multipleOf": 2 - }, - "$id": "if-then-else_5_0" - } - ] - }, - "tests": [ - { - "description": "valid through then", - "data": -1, - "valid": true, - "schema_id": "if-then-else_5_0" - }, - { - "description": "invalid through then", - "data": -100, - "valid": false, - "schema_id": "if-then-else_5_0" - }, - { - "description": "valid through else", - "data": 4, - "valid": true, - "schema_id": "if-then-else_5_0" - }, - { - "description": "invalid through else", - "data": 3, - "valid": false, - "schema_id": "if-then-else_5_0" - } - ] - }, - { - "description": "non-interference across combined schemas", - "database": { - "schemas": [ - { - "allOf": [ - { - "if": { - "exclusiveMaximum": 0 - } - }, - { - "then": { - "minimum": -10 - } - }, - { - "else": { - "multipleOf": 2 - } - } - ], - "$id": "if-then-else_6_0" - } - ] - }, - "tests": [ - { - "description": "valid, but would have been invalid through then", - "data": -100, - "valid": true, - "schema_id": "if-then-else_6_0" - }, - { - "description": "valid, but would have been invalid through else", - "data": 3, - "valid": true, - "schema_id": "if-then-else_6_0" - } - ] - }, - { - "description": "if with boolean schema true", - "database": { - "schemas": [ - { - "if": true, - "then": { - "const": "then" - }, - "else": { - "const": "else" - }, - "$id": "if-then-else_7_0" - } - ] - }, - "tests": [ - { - "description": "boolean schema true in if always chooses the then path (valid)", - "data": "then", - "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, - "schema_id": "if-then-else_7_0" - } - ] - }, - { - "description": "if with boolean schema false", - "database": { - "schemas": [ - { - "if": false, - "then": { - "const": "then" - }, - "else": { - "const": "else" - }, - "$id": "if-then-else_8_0" - } - ] - }, - "tests": [ - { - "description": "boolean schema false in if always chooses the else path (invalid)", - "data": "then", - "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, - "schema_id": "if-then-else_8_0" - } - ] - }, - { - "description": "if appears at the end when serialized (keyword processing sequence)", - "database": { - "schemas": [ - { - "then": { - "const": "yes" - }, - "else": { - "const": "other" - }, - "if": { - "maxLength": 4 - }, - "$id": "if-then-else_9_0" - } - ] - }, - "tests": [ - { - "description": "yes redirects to then and passes", - "data": "yes", - "valid": true, - "schema_id": "if-then-else_9_0" - }, - { - "description": "other redirects to else and passes", - "data": "other", - "valid": true, - "schema_id": "if-then-else_9_0" - }, - { - "description": "no redirects to then and fails", - "data": "no", - "valid": false, - "schema_id": "if-then-else_9_0" - }, - { - "description": "invalid redirects to else and fails", - "data": "invalid", - "valid": false, - "schema_id": "if-then-else_9_0" - } - ] - }, - { - "description": "then: false fails when condition matches", - "database": { - "schemas": [ - { - "if": { - "const": 1 - }, - "then": false, - "$id": "if-then-else_10_0" - } - ] - }, - "tests": [ - { - "description": "matches if → then=false → invalid", - "data": 1, - "valid": false, - "schema_id": "if-then-else_10_0" - }, - { - "description": "does not match if → then ignored → valid", - "data": 2, - "valid": true, - "schema_id": "if-then-else_10_0" - } - ] - }, - { - "description": "else: false fails when condition does not match", - "database": { - "schemas": [ - { - "if": { - "const": 1 - }, - "else": false, - "$id": "if-then-else_11_0" - } - ] - }, - "tests": [ - { - "description": "matches if → else ignored → valid", - "data": 1, - "valid": true, - "schema_id": "if-then-else_11_0" - }, - { - "description": "does not match if → else executes → invalid", - "data": 2, - "valid": false, - "schema_id": "if-then-else_11_0" - } - ] - }, - { - "description": "extensible: true allows extra properties in if-then-else", - "database": { - "schemas": [ - { - "if": { - "properties": { - "foo": { - "const": 1 - } - }, - "required": [ - "foo" - ] - }, - "then": { - "properties": { - "bar": { - "const": 2 - } - }, - "required": [ - "bar" - ] - }, - "extensible": true, - "$id": "if-then-else_12_0" - } - ] - }, - "tests": [ - { - "description": "extra property is valid (matches if and then)", - "data": { - "foo": 1, - "bar": 2, - "extra": "prop" - }, - "valid": true, - "schema_id": "if-then-else_12_0" - } - ] - }, - { - "description": "strict by default with if-then properties", - "database": { - "schemas": [ - { - "if": { - "properties": { - "foo": { - "const": 1 - } - }, - "required": [ - "foo" - ] - }, - "then": { - "properties": { - "bar": { - "const": 2 - } - } - }, - "$id": "if-then-else_13_0" - } - ] - }, - "tests": [ - { - "description": "valid match (foo + bar)", - "data": { - "foo": 1, - "bar": 2 - }, - "valid": true, - "schema_id": "if-then-else_13_0" - }, - { - "description": "fails on extra property z explicitly", - "data": { - "foo": 1, - "bar": 2, - "z": 3 - }, - "valid": false, - "schema_id": "if-then-else_13_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/items.json b/tests/fixtures/items.json deleted file mode 100644 index fa5479c..0000000 --- a/tests/fixtures/items.json +++ /dev/null @@ -1,843 +0,0 @@ -[ - { - "description": "a schema given for items", - "database": { - "schemas": [ - { - "items": { - "type": "integer" - }, - "$id": "items_0_0" - } - ] - }, - "tests": [ - { - "description": "valid items", - "data": [ - 1, - 2, - 3 - ], - "valid": true, - "schema_id": "items_0_0" - }, - { - "description": "wrong type of items", - "data": [ - 1, - "x" - ], - "valid": false, - "schema_id": "items_0_0" - }, - { - "description": "non-arrays are invalid", - "data": { - "foo": "bar" - }, - "valid": false, - "schema_id": "items_0_0" - }, - { - "description": "JavaScript pseudo-arrays are invalid", - "data": { - "0": "invalid", - "length": 1 - }, - "valid": false, - "schema_id": "items_0_0" - } - ] - }, - { - "description": "items with boolean schema (true)", - "database": { - "schemas": [ - { - "items": true, - "$id": "items_1_0" - } - ] - }, - "tests": [ - { - "description": "any array is valid", - "data": [ - 1, - "foo", - true - ], - "valid": true, - "schema_id": "items_1_0" - }, - { - "description": "empty array is valid", - "data": [], - "valid": true, - "schema_id": "items_1_0" - } - ] - }, - { - "description": "items with boolean schema (false)", - "database": { - "schemas": [ - { - "items": false, - "$id": "items_2_0" - } - ] - }, - "tests": [ - { - "description": "any non-empty array is invalid", - "data": [ - 1, - "foo", - true - ], - "valid": false, - "schema_id": "items_2_0" - }, - { - "description": "empty array is valid", - "data": [], - "valid": true, - "schema_id": "items_2_0" - } - ] - }, - { - "description": "items and subitems", - "database": { - "schemas": [ - { - "type": "array", - "items": false, - "prefixItems": [ - { - "$ref": "item" - }, - { - "$ref": "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" - ] - } - ] - }, - "tests": [ - { - "description": "valid items", - "data": [ - [ - { - "foo": null - }, - { - "foo": null - } - ], - [ - { - "foo": null - }, - { - "foo": null - } - ], - [ - { - "foo": null - }, - { - "foo": null - } - ] - ], - "valid": false, - "schema_id": "items_3_0" - }, - { - "description": "too many items", - "data": [ - [ - { - "foo": null - }, - { - "foo": null - } - ], - [ - { - "foo": null - }, - { - "foo": null - } - ], - [ - { - "foo": null - }, - { - "foo": null - } - ], - [ - { - "foo": null - }, - { - "foo": null - } - ] - ], - "valid": false, - "schema_id": "items_3_0" - }, - { - "description": "too many sub-items", - "data": [ - [ - { - "foo": null - }, - { - "foo": null - }, - { - "foo": null - } - ], - [ - { - "foo": null - }, - { - "foo": null - } - ], - [ - { - "foo": null - }, - { - "foo": null - } - ] - ], - "valid": false, - "schema_id": "items_3_0" - }, - { - "description": "wrong item", - "data": [ - { - "foo": null - }, - [ - { - "foo": null - }, - { - "foo": null - } - ], - [ - { - "foo": null - }, - { - "foo": null - } - ] - ], - "valid": false, - "schema_id": "items_3_0" - }, - { - "description": "wrong sub-item", - "data": [ - [ - {}, - { - "foo": null - } - ], - [ - { - "foo": null - }, - { - "foo": null - } - ], - [ - { - "foo": null - }, - { - "foo": null - } - ] - ], - "valid": false, - "schema_id": "items_3_0" - }, - { - "description": "fewer items is invalid", - "data": [ - [ - { - "foo": null - } - ], - [ - { - "foo": null - } - ] - ], - "valid": false, - "schema_id": "items_3_0" - } - ] - }, - { - "description": "nested items", - "database": { - "schemas": [ - { - "type": "array", - "items": { - "type": "array", - "items": { - "type": "array", - "items": { - "type": "array", - "items": { - "type": "number" - } - } - } - }, - "$id": "items_4_0" - } - ] - }, - "tests": [ - { - "description": "valid nested array", - "data": [ - [ - [ - [ - 1 - ] - ], - [ - [ - 2 - ], - [ - 3 - ] - ] - ], - [ - [ - [ - 4 - ], - [ - 5 - ], - [ - 6 - ] - ] - ] - ], - "valid": true, - "schema_id": "items_4_0" - }, - { - "description": "nested array with invalid type", - "data": [ - [ - [ - [ - "1" - ] - ], - [ - [ - 2 - ], - [ - 3 - ] - ] - ], - [ - [ - [ - 4 - ], - [ - 5 - ], - [ - 6 - ] - ] - ] - ], - "valid": false, - "schema_id": "items_4_0" - }, - { - "description": "not deep enough", - "data": [ - [ - [ - 1 - ], - [ - 2 - ], - [ - 3 - ] - ], - [ - [ - 4 - ], - [ - 5 - ], - [ - 6 - ] - ] - ], - "valid": false, - "schema_id": "items_4_0" - } - ] - }, - { - "description": "prefixItems with no additional items allowed", - "database": { - "schemas": [ - { - "prefixItems": [ - {}, - {}, - {} - ], - "items": false, - "$id": "items_5_0" - } - ] - }, - "tests": [ - { - "description": "empty array", - "data": [], - "valid": true, - "schema_id": "items_5_0" - }, - { - "description": "fewer number of items present (1)", - "data": [ - 1 - ], - "valid": true, - "schema_id": "items_5_0" - }, - { - "description": "fewer number of items present (2)", - "data": [ - 1, - 2 - ], - "valid": true, - "schema_id": "items_5_0" - }, - { - "description": "equal number of items present", - "data": [ - 1, - 2, - 3 - ], - "valid": true, - "schema_id": "items_5_0" - }, - { - "description": "additional items are not permitted", - "data": [ - 1, - 2, - 3, - 4 - ], - "valid": false, - "schema_id": "items_5_0" - } - ] - }, - { - "description": "items does not look in applicators, valid case", - "database": { - "schemas": [ - { - "allOf": [ - { - "prefixItems": [ - { - "minimum": 3 - } - ] - } - ], - "items": { - "minimum": 5 - }, - "$id": "items_6_0" - } - ] - }, - "tests": [ - { - "description": "prefixItems in allOf does not constrain items, invalid case", - "data": [ - 3, - 5 - ], - "valid": false, - "schema_id": "items_6_0" - }, - { - "description": "prefixItems in allOf does not constrain items, valid case", - "data": [ - 5, - 5 - ], - "valid": true, - "schema_id": "items_6_0" - } - ] - }, - { - "description": "prefixItems validation adjusts the starting index for items", - "database": { - "schemas": [ - { - "prefixItems": [ - { - "type": "string" - } - ], - "items": { - "type": "integer" - }, - "$id": "items_7_0" - } - ] - }, - "tests": [ - { - "description": "valid items", - "data": [ - "x", - 2, - 3 - ], - "valid": true, - "schema_id": "items_7_0" - }, - { - "description": "wrong type of second item", - "data": [ - "x", - "y" - ], - "valid": false, - "schema_id": "items_7_0" - } - ] - }, - { - "description": "items with heterogeneous array", - "database": { - "schemas": [ - { - "prefixItems": [ - {} - ], - "items": false, - "$id": "items_8_0" - } - ] - }, - "tests": [ - { - "description": "heterogeneous invalid instance", - "data": [ - "foo", - "bar", - 37 - ], - "valid": false, - "schema_id": "items_8_0" - }, - { - "description": "valid instance", - "data": [ - null - ], - "valid": true, - "schema_id": "items_8_0" - } - ] - }, - { - "description": "items with null instance elements", - "database": { - "schemas": [ - { - "items": { - "type": "null" - }, - "$id": "items_9_0" - } - ] - }, - "tests": [ - { - "description": "allows null elements", - "data": [ - null - ], - "valid": true, - "schema_id": "items_9_0" - } - ] - }, - { - "description": "extensible: true allows extra items (when items is false)", - "database": { - "schemas": [ - { - "items": false, - "extensible": true, - "$id": "items_10_0" - } - ] - }, - "tests": [ - { - "description": "extra item is valid", - "data": [ - 1 - ], - "valid": false, - "schema_id": "items_10_0" - } - ] - }, - { - "description": "extensible: true allows extra properties for items", - "database": { - "schemas": [ - { - "items": { - "minimum": 5 - }, - "extensible": true, - "$id": "items_11_0" - } - ] - }, - "tests": [ - { - "description": "valid item is valid", - "data": [ - 5, - 6 - ], - "valid": true, - "schema_id": "items_11_0" - }, - { - "description": "invalid item (less than min) is invalid even with extensible: true", - "data": [ - 4 - ], - "valid": false, - "schema_id": "items_11_0" - } - ] - }, - { - "description": "array: simple extensible array", - "database": { - "schemas": [ - { - "type": "array", - "extensible": true, - "$id": "items_12_0" - } - ] - }, - "tests": [ - { - "description": "empty array is valid", - "data": [], - "valid": true, - "schema_id": "items_12_0" - }, - { - "description": "array with items is valid (extensible)", - "data": [ - 1, - "foo" - ], - "valid": true, - "schema_id": "items_12_0" - } - ] - }, - { - "description": "array: strict array", - "database": { - "schemas": [ - { - "type": "array", - "extensible": false, - "$id": "items_13_0" - } - ] - }, - "tests": [ - { - "description": "empty array is valid", - "data": [], - "valid": true, - "schema_id": "items_13_0" - }, - { - "description": "array with items is invalid (strict)", - "data": [ - 1 - ], - "valid": false, - "schema_id": "items_13_0" - } - ] - }, - { - "description": "array: items extensible", - "database": { - "schemas": [ - { - "type": "array", - "items": { - "extensible": true - }, - "$id": "items_14_0" - } - ] - }, - "tests": [ - { - "description": "empty array is valid", - "data": [], - "valid": true, - "schema_id": "items_14_0" - }, - { - "description": "array with items is valid (items explicitly allowed to be anything extensible)", - "data": [ - 1, - "foo", - {} - ], - "valid": true, - "schema_id": "items_14_0" - } - ] - }, - { - "description": "array: items strict", - "database": { - "schemas": [ - { - "type": "array", - "items": { - "type": "object", - "extensible": false - }, - "$id": "items_15_0" - } - ] - }, - "tests": [ - { - "description": "empty array is valid (empty objects)", - "data": [ - {} - ], - "valid": true, - "schema_id": "items_15_0" - }, - { - "description": "array with strict object items is valid", - "data": [ - {} - ], - "valid": true, - "schema_id": "items_15_0" - }, - { - "description": "array with invalid strict object items (extra property)", - "data": [ - { - "extra": 1 - } - ], - "valid": false, - "schema_id": "items_15_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/maxContains.json b/tests/fixtures/maxContains.json deleted file mode 100644 index dffcfb3..0000000 --- a/tests/fixtures/maxContains.json +++ /dev/null @@ -1,196 +0,0 @@ -[ - { - "description": "maxContains without contains is ignored", - "database": { - "schemas": [ - { - "maxContains": 1, - "extensible": true, - "$id": "maxContains_0_0" - } - ] - }, - "tests": [ - { - "description": "one item valid against lone maxContains", - "data": [ - 1 - ], - "valid": true, - "schema_id": "maxContains_0_0" - }, - { - "description": "two items still valid against lone maxContains", - "data": [ - 1, - 2 - ], - "valid": true, - "schema_id": "maxContains_0_0" - } - ] - }, - { - "description": "maxContains with contains", - "database": { - "schemas": [ - { - "contains": { - "const": 1 - }, - "maxContains": 1, - "extensible": true, - "$id": "maxContains_1_0" - } - ] - }, - "tests": [ - { - "description": "empty data", - "data": [], - "valid": false, - "schema_id": "maxContains_1_0" - }, - { - "description": "all elements match, valid maxContains", - "data": [ - 1 - ], - "valid": true, - "schema_id": "maxContains_1_0" - }, - { - "description": "all elements match, invalid maxContains", - "data": [ - 1, - 1 - ], - "valid": false, - "schema_id": "maxContains_1_0" - }, - { - "description": "some elements match, valid maxContains", - "data": [ - 1, - 2 - ], - "valid": true, - "schema_id": "maxContains_1_0" - }, - { - "description": "some elements match, invalid maxContains", - "data": [ - 1, - 2, - 1 - ], - "valid": false, - "schema_id": "maxContains_1_0" - } - ] - }, - { - "description": "maxContains with contains, value with a decimal", - "database": { - "schemas": [ - { - "contains": { - "const": 1 - }, - "maxContains": 1, - "extensible": true, - "$id": "maxContains_2_0" - } - ] - }, - "tests": [ - { - "description": "one element matches, valid maxContains", - "data": [ - 1 - ], - "valid": true, - "schema_id": "maxContains_2_0" - }, - { - "description": "too many elements match, invalid maxContains", - "data": [ - 1, - 1 - ], - "valid": false, - "schema_id": "maxContains_2_0" - } - ] - }, - { - "description": "minContains < maxContains", - "database": { - "schemas": [ - { - "contains": { - "const": 1 - }, - "minContains": 1, - "maxContains": 3, - "extensible": true, - "$id": "maxContains_3_0" - } - ] - }, - "tests": [ - { - "description": "actual < minContains < maxContains", - "data": [], - "valid": false, - "schema_id": "maxContains_3_0" - }, - { - "description": "minContains < actual < maxContains", - "data": [ - 1, - 1 - ], - "valid": true, - "schema_id": "maxContains_3_0" - }, - { - "description": "minContains < maxContains < actual", - "data": [ - 1, - 1, - 1, - 1 - ], - "valid": false, - "schema_id": "maxContains_3_0" - } - ] - }, - { - "description": "extensible: true allows non-matching items in maxContains", - "database": { - "schemas": [ - { - "contains": { - "const": 1 - }, - "maxContains": 1, - "extensible": true, - "$id": "maxContains_4_0" - } - ] - }, - "tests": [ - { - "description": "extra items disregarded for maxContains", - "data": [ - 1, - 2 - ], - "valid": true, - "schema_id": "maxContains_4_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/maxItems.json b/tests/fixtures/maxItems.json deleted file mode 100644 index c09ccab..0000000 --- a/tests/fixtures/maxItems.json +++ /dev/null @@ -1,105 +0,0 @@ -[ - { - "description": "maxItems validation", - "database": { - "schemas": [ - { - "maxItems": 2, - "extensible": true, - "$id": "maxItems_0_0" - } - ] - }, - "tests": [ - { - "description": "shorter is valid", - "data": [ - 1 - ], - "valid": true, - "schema_id": "maxItems_0_0" - }, - { - "description": "exact length is valid", - "data": [ - 1, - 2 - ], - "valid": true, - "schema_id": "maxItems_0_0" - }, - { - "description": "too long is invalid", - "data": [ - 1, - 2, - 3 - ], - "valid": false, - "schema_id": "maxItems_0_0" - }, - { - "description": "ignores non-arrays", - "data": "foobar", - "valid": true, - "schema_id": "maxItems_0_0" - } - ] - }, - { - "description": "maxItems validation with a decimal", - "database": { - "schemas": [ - { - "maxItems": 2, - "extensible": true, - "$id": "maxItems_1_0" - } - ] - }, - "tests": [ - { - "description": "shorter is valid", - "data": [ - 1 - ], - "valid": true, - "schema_id": "maxItems_1_0" - }, - { - "description": "too long is invalid", - "data": [ - 1, - 2, - 3 - ], - "valid": false, - "schema_id": "maxItems_1_0" - } - ] - }, - { - "description": "extensible: true allows extra items in maxItems (but counted)", - "database": { - "schemas": [ - { - "maxItems": 2, - "extensible": true, - "$id": "maxItems_2_0" - } - ] - }, - "tests": [ - { - "description": "extra item counted towards maxItems", - "data": [ - 1, - 2, - 3 - ], - "valid": false, - "schema_id": "maxItems_2_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/maxLength.json b/tests/fixtures/maxLength.json deleted file mode 100644 index b92a51b..0000000 --- a/tests/fixtures/maxLength.json +++ /dev/null @@ -1,70 +0,0 @@ -[ - { - "description": "maxLength validation", - "database": { - "schemas": [ - { - "maxLength": 2, - "$id": "maxLength_0_0" - } - ] - }, - "tests": [ - { - "description": "shorter is valid", - "data": "f", - "valid": true, - "schema_id": "maxLength_0_0" - }, - { - "description": "exact length is valid", - "data": "fo", - "valid": true, - "schema_id": "maxLength_0_0" - }, - { - "description": "too long is invalid", - "data": "foo", - "valid": false, - "schema_id": "maxLength_0_0" - }, - { - "description": "ignores non-strings", - "data": 100, - "valid": true, - "schema_id": "maxLength_0_0" - }, - { - "description": "two graphemes is long enough", - "data": "💩💩", - "valid": true, - "schema_id": "maxLength_0_0" - } - ] - }, - { - "description": "maxLength validation with a decimal", - "database": { - "schemas": [ - { - "maxLength": 2, - "$id": "maxLength_1_0" - } - ] - }, - "tests": [ - { - "description": "shorter is valid", - "data": "f", - "valid": true, - "schema_id": "maxLength_1_0" - }, - { - "description": "too long is invalid", - "data": "foo", - "valid": false, - "schema_id": "maxLength_1_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/maxProperties.json b/tests/fixtures/maxProperties.json deleted file mode 100644 index de91855..0000000 --- a/tests/fixtures/maxProperties.json +++ /dev/null @@ -1,157 +0,0 @@ -[ - { - "description": "maxProperties validation", - "database": { - "schemas": [ - { - "maxProperties": 2, - "extensible": true, - "$id": "maxProperties_0_0" - } - ] - }, - "tests": [ - { - "description": "shorter is valid", - "data": { - "foo": 1 - }, - "valid": true, - "schema_id": "maxProperties_0_0" - }, - { - "description": "exact length is valid", - "data": { - "foo": 1, - "bar": 2 - }, - "valid": true, - "schema_id": "maxProperties_0_0" - }, - { - "description": "too long is invalid", - "data": { - "foo": 1, - "bar": 2, - "baz": 3 - }, - "valid": false, - "schema_id": "maxProperties_0_0" - }, - { - "description": "ignores arrays", - "data": [ - 1, - 2, - 3 - ], - "valid": true, - "schema_id": "maxProperties_0_0" - }, - { - "description": "ignores strings", - "data": "foobar", - "valid": true, - "schema_id": "maxProperties_0_0" - }, - { - "description": "ignores other non-objects", - "data": 12, - "valid": true, - "schema_id": "maxProperties_0_0" - } - ] - }, - { - "description": "maxProperties validation with a decimal", - "database": { - "schemas": [ - { - "maxProperties": 2, - "extensible": true, - "$id": "maxProperties_1_0" - } - ] - }, - "tests": [ - { - "description": "shorter is valid", - "data": { - "foo": 1 - }, - "valid": true, - "schema_id": "maxProperties_1_0" - }, - { - "description": "too long is invalid", - "data": { - "foo": 1, - "bar": 2, - "baz": 3 - }, - "valid": false, - "schema_id": "maxProperties_1_0" - } - ] - }, - { - "description": "maxProperties = 0 means the object is empty", - "database": { - "schemas": [ - { - "maxProperties": 0, - "extensible": true, - "$id": "maxProperties_2_0" - } - ] - }, - "tests": [ - { - "description": "no properties is valid", - "data": {}, - "valid": true, - "schema_id": "maxProperties_2_0" - }, - { - "description": "one property is invalid", - "data": { - "foo": 1 - }, - "valid": false, - "schema_id": "maxProperties_2_0" - } - ] - }, - { - "description": "extensible: true allows extra properties in maxProperties (though maxProperties still counts them!)", - "database": { - "schemas": [ - { - "maxProperties": 2, - "extensible": true, - "$id": "maxProperties_3_0" - } - ] - }, - "tests": [ - { - "description": "extra property is counted towards maxProperties", - "data": { - "foo": 1, - "bar": 2, - "baz": 3 - }, - "valid": false, - "schema_id": "maxProperties_3_0" - }, - { - "description": "extra property is valid if below maxProperties", - "data": { - "foo": 1 - }, - "valid": true, - "schema_id": "maxProperties_3_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/maximum.json b/tests/fixtures/maximum.json deleted file mode 100644 index ebbdc46..0000000 --- a/tests/fixtures/maximum.json +++ /dev/null @@ -1,76 +0,0 @@ -[ - { - "description": "maximum validation", - "database": { - "schemas": [ - { - "maximum": 3, - "$id": "maximum_0_0" - } - ] - }, - "tests": [ - { - "description": "below the maximum is valid", - "data": 2.6, - "valid": true, - "schema_id": "maximum_0_0" - }, - { - "description": "boundary point is valid", - "data": 3, - "valid": true, - "schema_id": "maximum_0_0" - }, - { - "description": "above the maximum is invalid", - "data": 3.5, - "valid": false, - "schema_id": "maximum_0_0" - }, - { - "description": "ignores non-numbers", - "data": "x", - "valid": true, - "schema_id": "maximum_0_0" - } - ] - }, - { - "description": "maximum validation with unsigned integer", - "database": { - "schemas": [ - { - "maximum": 300, - "$id": "maximum_1_0" - } - ] - }, - "tests": [ - { - "description": "below the maximum is invalid", - "data": 299.97, - "valid": true, - "schema_id": "maximum_1_0" - }, - { - "description": "boundary point integer is valid", - "data": 300, - "valid": true, - "schema_id": "maximum_1_0" - }, - { - "description": "boundary point float is valid", - "data": 300, - "valid": true, - "schema_id": "maximum_1_0" - }, - { - "description": "above the maximum is invalid", - "data": 300.5, - "valid": false, - "schema_id": "maximum_1_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/merge.json b/tests/fixtures/merge.json deleted file mode 100644 index d437931..0000000 --- a/tests/fixtures/merge.json +++ /dev/null @@ -1,247 +0,0 @@ -[ - { - "description": "merging: properties accumulate", - "database": { - "schemas": [ - { - "$id": "base_0", - "properties": { - "base_prop": { - "type": "string" - } - } - }, - { - "$ref": "base_0", - "properties": { - "child_prop": { - "type": "string" - } - }, - "$id": "merge_0_0" - } - ] - }, - "tests": [ - { - "description": "valid with both properties", - "data": { - "base_prop": "a", - "child_prop": "b" - }, - "valid": true, - "schema_id": "merge_0_0" - }, - { - "description": "invalid when base property has wrong type", - "data": { - "base_prop": 1, - "child_prop": "b" - }, - "valid": false, - "expect_errors": [ - { - "code": "TYPE_MISMATCH", - "path": "/base_prop" - } - ], - "schema_id": "merge_0_0" - } - ] - }, - { - "description": "merging: required fields accumulate", - "database": { - "schemas": [ - { - "$id": "base_1", - "properties": { - "a": { - "type": "string" - } - }, - "required": [ - "a" - ] - }, - { - "$ref": "base_1", - "properties": { - "b": { - "type": "string" - } - }, - "required": [ - "b" - ], - "$id": "merge_1_0" - } - ] - }, - "tests": [ - { - "description": "valid when both present", - "data": { - "a": "ok", - "b": "ok" - }, - "valid": true, - "schema_id": "merge_1_0" - }, - { - "description": "invalid when base required missing", - "data": { - "b": "ok" - }, - "valid": false, - "expect_errors": [ - { - "code": "REQUIRED_FIELD_MISSING", - "path": "/a" - } - ], - "schema_id": "merge_1_0" - }, - { - "description": "invalid when child required missing", - "data": { - "a": "ok" - }, - "valid": false, - "expect_errors": [ - { - "code": "REQUIRED_FIELD_MISSING", - "path": "/b" - } - ], - "schema_id": "merge_1_0" - } - ] - }, - { - "description": "merging: dependencies accumulate", - "database": { - "schemas": [ - { - "$id": "base_2", - "properties": { - "trigger": { - "type": "string" - }, - "base_dep": { - "type": "string" - } - }, - "dependencies": { - "trigger": [ - "base_dep" - ] - } - }, - { - "$ref": "base_2", - "properties": { - "child_dep": { - "type": "string" - } - }, - "dependencies": { - "trigger": [ - "child_dep" - ] - }, - "$id": "merge_2_0" - } - ] - }, - "tests": [ - { - "description": "valid with all deps", - "data": { - "trigger": "go", - "base_dep": "ok", - "child_dep": "ok" - }, - "valid": true, - "schema_id": "merge_2_0" - }, - { - "description": "invalid missing base dep", - "data": { - "trigger": "go", - "child_dep": "ok" - }, - "valid": false, - "expect_errors": [ - { - "code": "DEPENDENCY_FAILED", - "path": "/base_dep" - } - ], - "schema_id": "merge_2_0" - }, - { - "description": "invalid missing child dep", - "data": { - "trigger": "go", - "base_dep": "ok" - }, - "valid": false, - "expect_errors": [ - { - "code": "DEPENDENCY_FAILED", - "path": "/child_dep" - } - ], - "schema_id": "merge_2_0" - } - ] - }, - { - "description": "merging: form and display do NOT merge", - "database": { - "schemas": [ - { - "$id": "base_3", - "properties": { - "a": { - "type": "string" - }, - "b": { - "type": "string" - } - }, - "form": [ - "a", - "b" - ] - }, - { - "$ref": "base_3", - "properties": { - "c": { - "type": "string" - } - }, - "form": [ - "c" - ], - "$id": "merge_3_0" - } - ] - }, - "tests": [ - { - "description": "child schema validation", - "data": { - "a": "ok", - "b": "ok", - "c": "ok" - }, - "valid": true, - "comment": "Verifies validator handles the unmerged metadata correctly (ignores it or handles replacement)", - "schema_id": "merge_3_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/minContains.json b/tests/fixtures/minContains.json deleted file mode 100644 index 3d21dc0..0000000 --- a/tests/fixtures/minContains.json +++ /dev/null @@ -1,390 +0,0 @@ -[ - { - "description": "minContains without contains is ignored", - "database": { - "schemas": [ - { - "minContains": 1, - "extensible": true, - "$id": "minContains_0_0" - } - ] - }, - "tests": [ - { - "description": "one item valid against lone minContains", - "data": [ - 1 - ], - "valid": true, - "schema_id": "minContains_0_0" - }, - { - "description": "zero items still valid against lone minContains", - "data": [], - "valid": true, - "schema_id": "minContains_0_0" - } - ] - }, - { - "description": "minContains=1 with contains", - "database": { - "schemas": [ - { - "contains": { - "const": 1 - }, - "minContains": 1, - "extensible": true, - "$id": "minContains_1_0" - } - ] - }, - "tests": [ - { - "description": "empty data", - "data": [], - "valid": false, - "schema_id": "minContains_1_0" - }, - { - "description": "no elements match", - "data": [ - 2 - ], - "valid": false, - "schema_id": "minContains_1_0" - }, - { - "description": "single element matches, valid minContains", - "data": [ - 1 - ], - "valid": true, - "schema_id": "minContains_1_0" - }, - { - "description": "some elements match, valid minContains", - "data": [ - 1, - 2 - ], - "valid": true, - "schema_id": "minContains_1_0" - }, - { - "description": "all elements match, valid minContains", - "data": [ - 1, - 1 - ], - "valid": true, - "schema_id": "minContains_1_0" - } - ] - }, - { - "description": "minContains=2 with contains", - "database": { - "schemas": [ - { - "contains": { - "const": 1 - }, - "minContains": 2, - "extensible": true, - "$id": "minContains_2_0" - } - ] - }, - "tests": [ - { - "description": "empty data", - "data": [], - "valid": false, - "schema_id": "minContains_2_0" - }, - { - "description": "all elements match, invalid minContains", - "data": [ - 1 - ], - "valid": false, - "schema_id": "minContains_2_0" - }, - { - "description": "some elements match, invalid minContains", - "data": [ - 1, - 2 - ], - "valid": false, - "schema_id": "minContains_2_0" - }, - { - "description": "all elements match, valid minContains (exactly as needed)", - "data": [ - 1, - 1 - ], - "valid": true, - "schema_id": "minContains_2_0" - }, - { - "description": "all elements match, valid minContains (more than needed)", - "data": [ - 1, - 1, - 1 - ], - "valid": true, - "schema_id": "minContains_2_0" - }, - { - "description": "some elements match, valid minContains", - "data": [ - 1, - 2, - 1 - ], - "valid": true, - "schema_id": "minContains_2_0" - } - ] - }, - { - "description": "minContains=2 with contains with a decimal value", - "database": { - "schemas": [ - { - "contains": { - "const": 1 - }, - "minContains": 2, - "extensible": true, - "$id": "minContains_3_0" - } - ] - }, - "tests": [ - { - "description": "one element matches, invalid minContains", - "data": [ - 1 - ], - "valid": false, - "schema_id": "minContains_3_0" - }, - { - "description": "both elements match, valid minContains", - "data": [ - 1, - 1 - ], - "valid": true, - "schema_id": "minContains_3_0" - } - ] - }, - { - "description": "maxContains = minContains", - "database": { - "schemas": [ - { - "contains": { - "const": 1 - }, - "maxContains": 2, - "minContains": 2, - "extensible": true, - "$id": "minContains_4_0" - } - ] - }, - "tests": [ - { - "description": "empty data", - "data": [], - "valid": false, - "schema_id": "minContains_4_0" - }, - { - "description": "all elements match, invalid minContains", - "data": [ - 1 - ], - "valid": false, - "schema_id": "minContains_4_0" - }, - { - "description": "all elements match, invalid maxContains", - "data": [ - 1, - 1, - 1 - ], - "valid": false, - "schema_id": "minContains_4_0" - }, - { - "description": "all elements match, valid maxContains and minContains", - "data": [ - 1, - 1 - ], - "valid": true, - "schema_id": "minContains_4_0" - } - ] - }, - { - "description": "maxContains < minContains", - "database": { - "schemas": [ - { - "contains": { - "const": 1 - }, - "maxContains": 1, - "minContains": 3, - "extensible": true, - "$id": "minContains_5_0" - } - ] - }, - "tests": [ - { - "description": "empty data", - "data": [], - "valid": false, - "schema_id": "minContains_5_0" - }, - { - "description": "invalid minContains", - "data": [ - 1 - ], - "valid": false, - "schema_id": "minContains_5_0" - }, - { - "description": "invalid maxContains", - "data": [ - 1, - 1, - 1 - ], - "valid": false, - "schema_id": "minContains_5_0" - }, - { - "description": "invalid maxContains and minContains", - "data": [ - 1, - 1 - ], - "valid": false, - "schema_id": "minContains_5_0" - } - ] - }, - { - "description": "minContains = 0", - "database": { - "schemas": [ - { - "contains": { - "const": 1 - }, - "minContains": 0, - "extensible": true, - "$id": "minContains_6_0" - } - ] - }, - "tests": [ - { - "description": "empty data", - "data": [], - "valid": true, - "schema_id": "minContains_6_0" - }, - { - "description": "minContains = 0 makes contains always pass", - "data": [ - 2 - ], - "valid": true, - "schema_id": "minContains_6_0" - } - ] - }, - { - "description": "minContains = 0 with maxContains", - "database": { - "schemas": [ - { - "contains": { - "const": 1 - }, - "minContains": 0, - "maxContains": 1, - "extensible": true, - "$id": "minContains_7_0" - } - ] - }, - "tests": [ - { - "description": "empty data", - "data": [], - "valid": true, - "schema_id": "minContains_7_0" - }, - { - "description": "not more than maxContains", - "data": [ - 1 - ], - "valid": true, - "schema_id": "minContains_7_0" - }, - { - "description": "too many", - "data": [ - 1, - 1 - ], - "valid": false, - "schema_id": "minContains_7_0" - } - ] - }, - { - "description": "extensible: true allows non-matching items in minContains", - "database": { - "schemas": [ - { - "contains": { - "const": 1 - }, - "minContains": 1, - "extensible": true, - "$id": "minContains_8_0" - } - ] - }, - "tests": [ - { - "description": "extra items disregarded for minContains", - "data": [ - 1, - 2 - ], - "valid": true, - "schema_id": "minContains_8_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/minItems.json b/tests/fixtures/minItems.json deleted file mode 100644 index 2cb5a2b..0000000 --- a/tests/fixtures/minItems.json +++ /dev/null @@ -1,96 +0,0 @@ -[ - { - "description": "minItems validation", - "database": { - "schemas": [ - { - "minItems": 1, - "extensible": true, - "$id": "minItems_0_0" - } - ] - }, - "tests": [ - { - "description": "longer is valid", - "data": [ - 1, - 2 - ], - "valid": true, - "schema_id": "minItems_0_0" - }, - { - "description": "exact length is valid", - "data": [ - 1 - ], - "valid": true, - "schema_id": "minItems_0_0" - }, - { - "description": "too short is invalid", - "data": [], - "valid": false, - "schema_id": "minItems_0_0" - }, - { - "description": "ignores non-arrays", - "data": "", - "valid": true, - "schema_id": "minItems_0_0" - } - ] - }, - { - "description": "minItems validation with a decimal", - "database": { - "schemas": [ - { - "minItems": 1, - "extensible": true, - "$id": "minItems_1_0" - } - ] - }, - "tests": [ - { - "description": "longer is valid", - "data": [ - 1, - 2 - ], - "valid": true, - "schema_id": "minItems_1_0" - }, - { - "description": "too short is invalid", - "data": [], - "valid": false, - "schema_id": "minItems_1_0" - } - ] - }, - { - "description": "extensible: true allows extra items in minItems", - "database": { - "schemas": [ - { - "minItems": 1, - "extensible": true, - "$id": "minItems_2_0" - } - ] - }, - "tests": [ - { - "description": "extra item counted towards minItems", - "data": [ - 1 - ], - "valid": true, - "schema_id": "minItems_2_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/minLength.json b/tests/fixtures/minLength.json deleted file mode 100644 index b1cfa72..0000000 --- a/tests/fixtures/minLength.json +++ /dev/null @@ -1,70 +0,0 @@ -[ - { - "description": "minLength validation", - "database": { - "schemas": [ - { - "minLength": 2, - "$id": "minLength_0_0" - } - ] - }, - "tests": [ - { - "description": "longer is valid", - "data": "foo", - "valid": true, - "schema_id": "minLength_0_0" - }, - { - "description": "exact length is valid", - "data": "fo", - "valid": true, - "schema_id": "minLength_0_0" - }, - { - "description": "too short is invalid", - "data": "f", - "valid": false, - "schema_id": "minLength_0_0" - }, - { - "description": "ignores non-strings", - "data": 1, - "valid": true, - "schema_id": "minLength_0_0" - }, - { - "description": "one grapheme is not long enough", - "data": "💩", - "valid": false, - "schema_id": "minLength_0_0" - } - ] - }, - { - "description": "minLength validation with a decimal", - "database": { - "schemas": [ - { - "minLength": 2, - "$id": "minLength_1_0" - } - ] - }, - "tests": [ - { - "description": "longer is valid", - "data": "foo", - "valid": true, - "schema_id": "minLength_1_0" - }, - { - "description": "too short is invalid", - "data": "f", - "valid": false, - "schema_id": "minLength_1_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/minProperties.json b/tests/fixtures/minProperties.json deleted file mode 100644 index 94ace2b..0000000 --- a/tests/fixtures/minProperties.json +++ /dev/null @@ -1,108 +0,0 @@ -[ - { - "description": "minProperties validation", - "database": { - "schemas": [ - { - "minProperties": 1, - "extensible": true, - "$id": "minProperties_0_0" - } - ] - }, - "tests": [ - { - "description": "longer is valid", - "data": { - "foo": 1, - "bar": 2 - }, - "valid": true, - "schema_id": "minProperties_0_0" - }, - { - "description": "exact length is valid", - "data": { - "foo": 1 - }, - "valid": true, - "schema_id": "minProperties_0_0" - }, - { - "description": "too short is invalid", - "data": {}, - "valid": false, - "schema_id": "minProperties_0_0" - }, - { - "description": "ignores arrays", - "data": [], - "valid": true, - "schema_id": "minProperties_0_0" - }, - { - "description": "ignores strings", - "data": "", - "valid": true, - "schema_id": "minProperties_0_0" - }, - { - "description": "ignores other non-objects", - "data": 12, - "valid": true, - "schema_id": "minProperties_0_0" - } - ] - }, - { - "description": "minProperties validation with a decimal", - "database": { - "schemas": [ - { - "minProperties": 1, - "extensible": true, - "$id": "minProperties_1_0" - } - ] - }, - "tests": [ - { - "description": "longer is valid", - "data": { - "foo": 1, - "bar": 2 - }, - "valid": true, - "schema_id": "minProperties_1_0" - }, - { - "description": "too short is invalid", - "data": {}, - "valid": false, - "schema_id": "minProperties_1_0" - } - ] - }, - { - "description": "extensible: true allows extra properties in minProperties", - "database": { - "schemas": [ - { - "minProperties": 1, - "extensible": true, - "$id": "minProperties_2_0" - } - ] - }, - "tests": [ - { - "description": "extra property counts towards minProperties", - "data": { - "foo": 1 - }, - "valid": true, - "schema_id": "minProperties_2_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/minimum.json b/tests/fixtures/minimum.json deleted file mode 100644 index 3ec705a..0000000 --- a/tests/fixtures/minimum.json +++ /dev/null @@ -1,94 +0,0 @@ -[ - { - "description": "minimum validation", - "database": { - "schemas": [ - { - "minimum": 1.1, - "$id": "minimum_0_0" - } - ] - }, - "tests": [ - { - "description": "above the minimum is valid", - "data": 2.6, - "valid": true, - "schema_id": "minimum_0_0" - }, - { - "description": "boundary point is valid", - "data": 1.1, - "valid": true, - "schema_id": "minimum_0_0" - }, - { - "description": "below the minimum is invalid", - "data": 0.6, - "valid": false, - "schema_id": "minimum_0_0" - }, - { - "description": "ignores non-numbers", - "data": "x", - "valid": true, - "schema_id": "minimum_0_0" - } - ] - }, - { - "description": "minimum validation with signed integer", - "database": { - "schemas": [ - { - "minimum": -2, - "$id": "minimum_1_0" - } - ] - }, - "tests": [ - { - "description": "negative above the minimum is valid", - "data": -1, - "valid": true, - "schema_id": "minimum_1_0" - }, - { - "description": "positive above the minimum is valid", - "data": 0, - "valid": true, - "schema_id": "minimum_1_0" - }, - { - "description": "boundary point is valid", - "data": -2, - "valid": true, - "schema_id": "minimum_1_0" - }, - { - "description": "boundary point with float is valid", - "data": -2, - "valid": true, - "schema_id": "minimum_1_0" - }, - { - "description": "float below the minimum is invalid", - "data": -2.0001, - "valid": false, - "schema_id": "minimum_1_0" - }, - { - "description": "int below the minimum is invalid", - "data": -3, - "valid": false, - "schema_id": "minimum_1_0" - }, - { - "description": "ignores non-numbers", - "data": "x", - "valid": true, - "schema_id": "minimum_1_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/multipleOf.json b/tests/fixtures/multipleOf.json deleted file mode 100644 index 324df97..0000000 --- a/tests/fixtures/multipleOf.json +++ /dev/null @@ -1,109 +0,0 @@ -[ - { - "description": "by int", - "database": { - "schemas": [ - { - "multipleOf": 2, - "$id": "multipleOf_0_0" - } - ] - }, - "tests": [ - { - "description": "int by int", - "data": 10, - "valid": true, - "schema_id": "multipleOf_0_0" - }, - { - "description": "int by int fail", - "data": 7, - "valid": false, - "schema_id": "multipleOf_0_0" - }, - { - "description": "ignores non-numbers", - "data": "foo", - "valid": true, - "schema_id": "multipleOf_0_0" - } - ] - }, - { - "description": "by number", - "database": { - "schemas": [ - { - "multipleOf": 1.5, - "$id": "multipleOf_1_0" - } - ] - }, - "tests": [ - { - "description": "zero is multiple of anything", - "data": 0, - "valid": true, - "schema_id": "multipleOf_1_0" - }, - { - "description": "4.5 is multiple of 1.5", - "data": 4.5, - "valid": true, - "schema_id": "multipleOf_1_0" - }, - { - "description": "35 is not multiple of 1.5", - "data": 35, - "valid": false, - "schema_id": "multipleOf_1_0" - } - ] - }, - { - "description": "by small number", - "database": { - "schemas": [ - { - "multipleOf": 0.0001, - "$id": "multipleOf_2_0" - } - ] - }, - "tests": [ - { - "description": "0.0075 is multiple of 0.0001", - "data": 0.0075, - "valid": true, - "schema_id": "multipleOf_2_0" - }, - { - "description": "0.00751 is not multiple of 0.0001", - "data": 0.00751, - "valid": false, - "schema_id": "multipleOf_2_0" - } - ] - }, - { - "description": "small multiple of large integer", - "database": { - "schemas": [ - { - "type": "integer", - "multipleOf": 1e-8, - "$id": "multipleOf_3_0" - } - ] - }, - "tests": [ - { - "description": "any integer is a multiple of 1e-8", - "data": 12391239123, - "valid": true, - "schema_id": "multipleOf_3_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/not.json b/tests/fixtures/not.json deleted file mode 100644 index 04735ce..0000000 --- a/tests/fixtures/not.json +++ /dev/null @@ -1,489 +0,0 @@ -[ - { - "description": "not", - "database": { - "schemas": [ - { - "not": { - "type": "integer" - }, - "$id": "not_0_0" - } - ] - }, - "tests": [ - { - "description": "allowed", - "data": "foo", - "valid": true, - "schema_id": "not_0_0" - }, - { - "description": "disallowed", - "data": 1, - "valid": false, - "schema_id": "not_0_0" - } - ] - }, - { - "description": "not multiple types", - "database": { - "schemas": [ - { - "not": { - "type": [ - "integer", - "boolean" - ] - }, - "$id": "not_1_0" - } - ] - }, - "tests": [ - { - "description": "valid", - "data": "foo", - "valid": true, - "schema_id": "not_1_0" - }, - { - "description": "mismatch", - "data": 1, - "valid": false, - "schema_id": "not_1_0" - }, - { - "description": "other mismatch", - "data": true, - "valid": false, - "schema_id": "not_1_0" - } - ] - }, - { - "description": "not more complex schema", - "database": { - "schemas": [ - { - "not": { - "type": "object", - "properties": { - "foo": { - "type": "string" - } - } - }, - "extensible": true, - "$id": "not_2_0" - } - ] - }, - "tests": [ - { - "description": "match", - "data": 1, - "valid": true, - "schema_id": "not_2_0" - }, - { - "description": "other match", - "data": { - "foo": 1 - }, - "valid": true, - "schema_id": "not_2_0" - }, - { - "description": "mismatch", - "data": { - "foo": "bar" - }, - "valid": false, - "schema_id": "not_2_0" - } - ] - }, - { - "description": "forbidden property", - "database": { - "schemas": [ - { - "properties": { - "foo": { - "not": {} - } - }, - "$id": "not_3_0" - } - ] - }, - "tests": [ - { - "description": "property present", - "data": { - "foo": 1, - "bar": 2 - }, - "valid": false, - "schema_id": "not_3_0" - }, - { - "description": "empty object is valid", - "data": {}, - "valid": true, - "schema_id": "not_3_0" - } - ] - }, - { - "description": "forbid everything with empty schema", - "database": { - "schemas": [ - { - "not": {}, - "$id": "not_4_0" - } - ] - }, - "tests": [ - { - "description": "number is invalid", - "data": 1, - "valid": false, - "schema_id": "not_4_0" - }, - { - "description": "string is invalid", - "data": "foo", - "valid": false, - "schema_id": "not_4_0" - }, - { - "description": "boolean true is invalid", - "data": true, - "valid": false, - "schema_id": "not_4_0" - }, - { - "description": "boolean false is invalid", - "data": false, - "valid": false, - "schema_id": "not_4_0" - }, - { - "description": "null is invalid", - "data": null, - "valid": false, - "schema_id": "not_4_0" - }, - { - "description": "object is invalid", - "data": { - "foo": "bar" - }, - "valid": false, - "schema_id": "not_4_0" - }, - { - "description": "empty object is invalid", - "data": {}, - "valid": false, - "schema_id": "not_4_0" - }, - { - "description": "array is invalid", - "data": [ - "foo" - ], - "valid": false, - "schema_id": "not_4_0" - }, - { - "description": "empty array is invalid", - "data": [], - "valid": false, - "schema_id": "not_4_0" - } - ] - }, - { - "description": "forbid everything with boolean schema true", - "database": { - "schemas": [ - { - "not": true, - "$id": "not_5_0" - } - ] - }, - "tests": [ - { - "description": "number is invalid", - "data": 1, - "valid": false, - "schema_id": "not_5_0" - }, - { - "description": "string is invalid", - "data": "foo", - "valid": false, - "schema_id": "not_5_0" - }, - { - "description": "boolean true is invalid", - "data": true, - "valid": false, - "schema_id": "not_5_0" - }, - { - "description": "boolean false is invalid", - "data": false, - "valid": false, - "schema_id": "not_5_0" - }, - { - "description": "null is invalid", - "data": null, - "valid": false, - "schema_id": "not_5_0" - }, - { - "description": "object is invalid", - "data": { - "foo": "bar" - }, - "valid": false, - "schema_id": "not_5_0" - }, - { - "description": "empty object is invalid", - "data": {}, - "valid": false, - "schema_id": "not_5_0" - }, - { - "description": "array is invalid", - "data": [ - "foo" - ], - "valid": false, - "schema_id": "not_5_0" - }, - { - "description": "empty array is invalid", - "data": [], - "valid": false, - "schema_id": "not_5_0" - } - ] - }, - { - "description": "allow everything with boolean schema false", - "database": { - "schemas": [ - { - "not": false, - "extensible": true, - "$id": "not_6_0" - } - ] - }, - "tests": [ - { - "description": "number is valid", - "data": 1, - "valid": true, - "schema_id": "not_6_0" - }, - { - "description": "string is valid", - "data": "foo", - "valid": true, - "schema_id": "not_6_0" - }, - { - "description": "boolean true is valid", - "data": true, - "valid": true, - "schema_id": "not_6_0" - }, - { - "description": "boolean false is valid", - "data": false, - "valid": true, - "schema_id": "not_6_0" - }, - { - "description": "null is valid", - "data": null, - "valid": true, - "schema_id": "not_6_0" - }, - { - "description": "object is valid", - "data": { - "foo": "bar" - }, - "valid": true, - "schema_id": "not_6_0" - }, - { - "description": "empty object is valid", - "data": {}, - "valid": true, - "schema_id": "not_6_0" - }, - { - "description": "array is valid", - "data": [ - "foo" - ], - "valid": true, - "schema_id": "not_6_0" - }, - { - "description": "empty array is valid", - "data": [], - "valid": true, - "schema_id": "not_6_0" - } - ] - }, - { - "description": "double negation", - "database": { - "schemas": [ - { - "not": { - "not": {} - }, - "$id": "not_7_0" - } - ] - }, - "tests": [ - { - "description": "any value is valid", - "data": "foo", - "valid": true, - "schema_id": "not_7_0" - } - ] - }, - { - "description": "extensible: true allows extra properties in not", - "database": { - "schemas": [ - { - "not": { - "type": "integer" - }, - "extensible": true, - "$id": "not_8_0" - } - ] - }, - "tests": [ - { - "description": "extra property is valid (not integer matches)", - "data": { - "foo": 1 - }, - "valid": true, - "schema_id": "not_8_0" - } - ] - }, - { - "description": "extensible: false (default) forbids extra properties in not", - "database": { - "schemas": [ - { - "not": { - "type": "integer" - }, - "$id": "not_9_0" - } - ] - }, - "tests": [ - { - "description": "extra property is invalid due to strictness", - "data": { - "foo": 1 - }, - "valid": false, - "schema_id": "not_9_0" - } - ] - }, - { - "description": "property next to not (extensible: true)", - "database": { - "schemas": [ - { - "properties": { - "bar": { - "type": "string" - } - }, - "not": { - "type": "integer" - }, - "extensible": true, - "$id": "not_10_0" - } - ] - }, - "tests": [ - { - "description": "extra property allowed", - "data": { - "bar": "baz", - "foo": 1 - }, - "valid": true, - "schema_id": "not_10_0" - } - ] - }, - { - "description": "property next to not (extensible: false)", - "database": { - "schemas": [ - { - "properties": { - "bar": { - "type": "string" - } - }, - "not": { - "type": "integer" - }, - "$id": "not_11_0" - } - ] - }, - "tests": [ - { - "description": "extra property forbidden", - "data": { - "bar": "baz", - "foo": 1 - }, - "valid": false, - "schema_id": "not_11_0" - }, - { - "description": "defined property allowed", - "data": { - "bar": "baz" - }, - "valid": true, - "schema_id": "not_11_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/oneOf.json b/tests/fixtures/oneOf.json deleted file mode 100644 index 8801c1d..0000000 --- a/tests/fixtures/oneOf.json +++ /dev/null @@ -1,568 +0,0 @@ -[ - { - "description": "oneOf", - "database": { - "schemas": [ - { - "oneOf": [ - { - "type": "integer" - }, - { - "minimum": 2 - } - ], - "$id": "oneOf_0_0" - } - ] - }, - "tests": [ - { - "description": "first oneOf valid", - "data": 1, - "valid": true, - "schema_id": "oneOf_0_0" - }, - { - "description": "second oneOf valid", - "data": 2.5, - "valid": true, - "schema_id": "oneOf_0_0" - }, - { - "description": "both oneOf valid", - "data": 3, - "valid": false, - "schema_id": "oneOf_0_0" - }, - { - "description": "neither oneOf valid", - "data": 1.5, - "valid": false, - "schema_id": "oneOf_0_0" - } - ] - }, - { - "description": "oneOf with base schema", - "database": { - "schemas": [ - { - "type": "string", - "oneOf": [ - { - "minLength": 2 - }, - { - "maxLength": 4 - } - ], - "$id": "oneOf_1_0" - } - ] - }, - "tests": [ - { - "description": "mismatch base schema", - "data": 3, - "valid": false, - "schema_id": "oneOf_1_0" - }, - { - "description": "one oneOf valid", - "data": "foobar", - "valid": true, - "schema_id": "oneOf_1_0" - }, - { - "description": "both oneOf valid", - "data": "foo", - "valid": false, - "schema_id": "oneOf_1_0" - } - ] - }, - { - "description": "oneOf with boolean schemas, all true", - "database": { - "schemas": [ - { - "oneOf": [ - true, - true, - true - ], - "$id": "oneOf_2_0" - } - ] - }, - "tests": [ - { - "description": "any value is invalid", - "data": "foo", - "valid": false, - "schema_id": "oneOf_2_0" - } - ] - }, - { - "description": "oneOf with boolean schemas, one true", - "database": { - "schemas": [ - { - "oneOf": [ - true, - false, - false - ], - "$id": "oneOf_3_0" - } - ] - }, - "tests": [ - { - "description": "any value is valid", - "data": "foo", - "valid": true, - "schema_id": "oneOf_3_0" - } - ] - }, - { - "description": "oneOf with boolean schemas, more than one true", - "database": { - "schemas": [ - { - "oneOf": [ - true, - true, - false - ], - "$id": "oneOf_4_0" - } - ] - }, - "tests": [ - { - "description": "any value is invalid", - "data": "foo", - "valid": false, - "schema_id": "oneOf_4_0" - } - ] - }, - { - "description": "oneOf with boolean schemas, all false", - "database": { - "schemas": [ - { - "oneOf": [ - false, - false, - false - ], - "$id": "oneOf_5_0" - } - ] - }, - "tests": [ - { - "description": "any value is invalid", - "data": "foo", - "valid": false, - "schema_id": "oneOf_5_0" - } - ] - }, - { - "description": "oneOf complex types", - "database": { - "schemas": [ - { - "oneOf": [ - { - "properties": { - "bar": { - "type": "integer" - } - }, - "required": [ - "bar" - ] - }, - { - "properties": { - "foo": { - "type": "string" - } - }, - "required": [ - "foo" - ] - } - ], - "$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" - } - ] - }, - "tests": [ - { - "description": "extra property is valid (matches first option)", - "data": { - "bar": 2, - "extra": "prop" - }, - "valid": true, - "schema_id": "oneOf_12_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/pattern.json b/tests/fixtures/pattern.json deleted file mode 100644 index c544cfd..0000000 --- a/tests/fixtures/pattern.json +++ /dev/null @@ -1,82 +0,0 @@ -[ - { - "description": "pattern validation", - "database": { - "schemas": [ - { - "pattern": "^a*$", - "$id": "pattern_0_0" - } - ] - }, - "tests": [ - { - "description": "a matching pattern is valid", - "data": "aaa", - "valid": true, - "schema_id": "pattern_0_0" - }, - { - "description": "a non-matching pattern is invalid", - "data": "abc", - "valid": false, - "schema_id": "pattern_0_0" - }, - { - "description": "ignores booleans", - "data": true, - "valid": true, - "schema_id": "pattern_0_0" - }, - { - "description": "ignores integers", - "data": 123, - "valid": true, - "schema_id": "pattern_0_0" - }, - { - "description": "ignores floats", - "data": 1, - "valid": true, - "schema_id": "pattern_0_0" - }, - { - "description": "ignores objects", - "data": {}, - "valid": true, - "schema_id": "pattern_0_0" - }, - { - "description": "ignores arrays", - "data": [], - "valid": true, - "schema_id": "pattern_0_0" - }, - { - "description": "ignores null", - "data": null, - "valid": true, - "schema_id": "pattern_0_0" - } - ] - }, - { - "description": "pattern is not anchored", - "database": { - "schemas": [ - { - "pattern": "a+", - "$id": "pattern_1_0" - } - ] - }, - "tests": [ - { - "description": "matches a substring", - "data": "xxaayy", - "valid": true, - "schema_id": "pattern_1_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/patternProperties.json b/tests/fixtures/patternProperties.json deleted file mode 100644 index 3b8dfa5..0000000 --- a/tests/fixtures/patternProperties.json +++ /dev/null @@ -1,321 +0,0 @@ -[ - { - "description": "patternProperties validates properties matching a regex", - "database": { - "schemas": [ - { - "patternProperties": { - "f.*o": { - "type": "integer" - } - }, - "items": {}, - "$id": "patternProperties_0_0" - } - ] - }, - "tests": [ - { - "description": "a single valid match is valid", - "data": { - "foo": 1 - }, - "valid": true, - "schema_id": "patternProperties_0_0" - }, - { - "description": "multiple valid matches is valid", - "data": { - "foo": 1, - "foooooo": 2 - }, - "valid": true, - "schema_id": "patternProperties_0_0" - }, - { - "description": "a single invalid match is invalid", - "data": { - "foo": "bar", - "fooooo": 2 - }, - "valid": false, - "schema_id": "patternProperties_0_0" - }, - { - "description": "multiple invalid matches is invalid", - "data": { - "foo": "bar", - "foooooo": "baz" - }, - "valid": false, - "schema_id": "patternProperties_0_0" - }, - { - "description": "ignores arrays", - "data": [ - "foo" - ], - "valid": true, - "schema_id": "patternProperties_0_0" - }, - { - "description": "ignores strings", - "data": "foo", - "valid": true, - "schema_id": "patternProperties_0_0" - }, - { - "description": "ignores other non-objects", - "data": 12, - "valid": true, - "schema_id": "patternProperties_0_0" - }, - { - "description": "extra property not matching pattern is INVALID (strict by default)", - "data": { - "foo": 1, - "extra": 2 - }, - "valid": false, - "schema_id": "patternProperties_0_0" - } - ] - }, - { - "description": "multiple simultaneous patternProperties are validated", - "database": { - "schemas": [ - { - "patternProperties": { - "a*": { - "type": "integer" - }, - "aaa*": { - "maximum": 20 - } - }, - "$id": "patternProperties_1_0" - } - ] - }, - "tests": [ - { - "description": "a single valid match is valid", - "data": { - "a": 21 - }, - "valid": true, - "schema_id": "patternProperties_1_0" - }, - { - "description": "a simultaneous match is valid", - "data": { - "aaaa": 18 - }, - "valid": true, - "schema_id": "patternProperties_1_0" - }, - { - "description": "multiple matches is valid", - "data": { - "a": 21, - "aaaa": 18 - }, - "valid": true, - "schema_id": "patternProperties_1_0" - }, - { - "description": "an invalid due to one is invalid", - "data": { - "a": "bar" - }, - "valid": false, - "schema_id": "patternProperties_1_0" - }, - { - "description": "an invalid due to the other is invalid", - "data": { - "aaaa": 31 - }, - "valid": false, - "schema_id": "patternProperties_1_0" - }, - { - "description": "an invalid due to both is invalid", - "data": { - "aaa": "foo", - "aaaa": 31 - }, - "valid": false, - "schema_id": "patternProperties_1_0" - } - ] - }, - { - "description": "regexes are not anchored by default and are case sensitive", - "database": { - "schemas": [ - { - "patternProperties": { - "[0-9]{2,}": { - "type": "boolean" - }, - "X_": { - "type": "string" - } - }, - "extensible": true, - "$id": "patternProperties_2_0" - } - ] - }, - "tests": [ - { - "description": "non recognized members are ignored", - "data": { - "answer 1": "42" - }, - "valid": true, - "schema_id": "patternProperties_2_0" - }, - { - "description": "recognized members are accounted for", - "data": { - "a31b": null - }, - "valid": false, - "schema_id": "patternProperties_2_0" - }, - { - "description": "regexes are case sensitive", - "data": { - "a_x_3": 3 - }, - "valid": true, - "schema_id": "patternProperties_2_0" - }, - { - "description": "regexes are case sensitive, 2", - "data": { - "a_X_3": 3 - }, - "valid": false, - "schema_id": "patternProperties_2_0" - } - ] - }, - { - "description": "patternProperties with boolean schemas", - "database": { - "schemas": [ - { - "patternProperties": { - "f.*": true, - "b.*": false - }, - "$id": "patternProperties_3_0" - } - ] - }, - "tests": [ - { - "description": "object with property matching schema true is valid", - "data": { - "foo": 1 - }, - "valid": true, - "schema_id": "patternProperties_3_0" - }, - { - "description": "object with property matching schema false is invalid", - "data": { - "bar": 2 - }, - "valid": false, - "schema_id": "patternProperties_3_0" - }, - { - "description": "object with both properties is invalid", - "data": { - "foo": 1, - "bar": 2 - }, - "valid": false, - "schema_id": "patternProperties_3_0" - }, - { - "description": "object with a property matching both true and false is invalid", - "data": { - "foobar": 1 - }, - "valid": false, - "schema_id": "patternProperties_3_0" - }, - { - "description": "empty object is valid", - "data": {}, - "valid": true, - "schema_id": "patternProperties_3_0" - } - ] - }, - { - "description": "patternProperties with null valued instance properties", - "database": { - "schemas": [ - { - "patternProperties": { - "^.*bar$": { - "type": "null" - } - }, - "$id": "patternProperties_4_0" - } - ] - }, - "tests": [ - { - "description": "allows null values", - "data": { - "foobar": null - }, - "valid": true, - "schema_id": "patternProperties_4_0" - } - ] - }, - { - "description": "extensible: true allows extra properties NOT matching pattern", - "database": { - "schemas": [ - { - "patternProperties": { - "f.*o": { - "type": "integer" - } - }, - "extensible": true, - "$id": "patternProperties_5_0" - } - ] - }, - "tests": [ - { - "description": "extra property not matching pattern is valid", - "data": { - "bar": 1 - }, - "valid": true, - "schema_id": "patternProperties_5_0" - }, - { - "description": "property matching pattern MUST still be valid", - "data": { - "foo": "invalid string" - }, - "valid": false, - "schema_id": "patternProperties_5_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/prefixItems.json b/tests/fixtures/prefixItems.json deleted file mode 100644 index b02c664..0000000 --- a/tests/fixtures/prefixItems.json +++ /dev/null @@ -1,193 +0,0 @@ -[ - { - "description": "a schema given for prefixItems", - "database": { - "schemas": [ - { - "prefixItems": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "$id": "prefixItems_0_0" - } - ] - }, - "tests": [ - { - "description": "correct types", - "data": [ - 1, - "foo" - ], - "valid": true, - "schema_id": "prefixItems_0_0" - }, - { - "description": "wrong types", - "data": [ - "foo", - 1 - ], - "valid": false, - "schema_id": "prefixItems_0_0" - }, - { - "description": "incomplete array of items", - "data": [ - 1 - ], - "valid": true, - "schema_id": "prefixItems_0_0" - }, - { - "description": "array with additional items (invalid due to strictness)", - "data": [ - 1, - "foo", - true - ], - "valid": false, - "schema_id": "prefixItems_0_0" - }, - { - "description": "empty array", - "data": [], - "valid": true, - "schema_id": "prefixItems_0_0" - }, - { - "description": "JavaScript pseudo-array is valid (invalid due to strict object validation)", - "data": { - "0": "invalid", - "1": "valid", - "length": 2 - }, - "valid": false, - "schema_id": "prefixItems_0_0" - } - ] - }, - { - "description": "prefixItems with boolean schemas", - "database": { - "schemas": [ - { - "prefixItems": [ - true, - false - ], - "$id": "prefixItems_1_0" - } - ] - }, - "tests": [ - { - "description": "array with one item is valid", - "data": [ - 1 - ], - "valid": true, - "schema_id": "prefixItems_1_0" - }, - { - "description": "array with two items is invalid", - "data": [ - 1, - "foo" - ], - "valid": false, - "schema_id": "prefixItems_1_0" - }, - { - "description": "empty array is valid", - "data": [], - "valid": true, - "schema_id": "prefixItems_1_0" - } - ] - }, - { - "description": "additional items are allowed by default", - "database": { - "schemas": [ - { - "prefixItems": [ - { - "type": "integer" - } - ], - "extensible": true, - "$id": "prefixItems_2_0" - } - ] - }, - "tests": [ - { - "description": "only the first item is validated", - "data": [ - 1, - "foo", - false - ], - "valid": true, - "schema_id": "prefixItems_2_0" - } - ] - }, - { - "description": "prefixItems with null instance elements", - "database": { - "schemas": [ - { - "prefixItems": [ - { - "type": "null" - } - ], - "$id": "prefixItems_3_0" - } - ] - }, - "tests": [ - { - "description": "allows null elements", - "data": [ - null - ], - "valid": true, - "schema_id": "prefixItems_3_0" - } - ] - }, - { - "description": "extensible: true allows extra items with prefixItems", - "database": { - "schemas": [ - { - "prefixItems": [ - { - "type": "integer" - } - ], - "extensible": true, - "$id": "prefixItems_4_0" - } - ] - }, - "tests": [ - { - "description": "extra item is valid", - "data": [ - 1, - "foo" - ], - "valid": true, - "schema_id": "prefixItems_4_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/properties.json b/tests/fixtures/properties.json deleted file mode 100644 index b04f106..0000000 --- a/tests/fixtures/properties.json +++ /dev/null @@ -1,543 +0,0 @@ -[ - { - "description": "object properties validation", - "database": { - "schemas": [ - { - "properties": { - "foo": { - "type": "integer" - }, - "bar": { - "type": "string" - } - }, - "$id": "properties_0_0" - } - ] - }, - "tests": [ - { - "description": "both properties present and valid is valid", - "data": { - "foo": 1, - "bar": "baz" - }, - "valid": true, - "schema_id": "properties_0_0" - }, - { - "description": "one property invalid is invalid", - "data": { - "foo": 1, - "bar": {} - }, - "valid": false, - "schema_id": "properties_0_0" - }, - { - "description": "both properties invalid is invalid", - "data": { - "foo": [], - "bar": {} - }, - "valid": false, - "schema_id": "properties_0_0" - }, - { - "description": "doesn't invalidate other properties", - "data": {}, - "valid": true, - "schema_id": "properties_0_0" - }, - { - "description": "ignores arrays", - "data": [], - "valid": true, - "schema_id": "properties_0_0" - }, - { - "description": "ignores other non-objects", - "data": 12, - "valid": true, - "schema_id": "properties_0_0" - } - ] - }, - { - "description": "properties with boolean schema", - "database": { - "schemas": [ - { - "properties": { - "foo": true, - "bar": false - }, - "$id": "properties_1_0" - } - ] - }, - "tests": [ - { - "description": "no property present is valid", - "data": {}, - "valid": true, - "schema_id": "properties_1_0" - }, - { - "description": "only 'true' property present is valid", - "data": { - "foo": 1 - }, - "valid": true, - "schema_id": "properties_1_0" - }, - { - "description": "only 'false' property present is invalid", - "data": { - "bar": 2 - }, - "valid": false, - "schema_id": "properties_1_0" - }, - { - "description": "both properties present is invalid", - "data": { - "foo": 1, - "bar": 2 - }, - "valid": false, - "schema_id": "properties_1_0" - } - ] - }, - { - "description": "properties with escaped characters", - "database": { - "schemas": [ - { - "properties": { - "foo\nbar": { - "type": "number" - }, - "foo\"bar": { - "type": "number" - }, - "foo\\bar": { - "type": "number" - }, - "foo\rbar": { - "type": "number" - }, - "foo\tbar": { - "type": "number" - }, - "foo\fbar": { - "type": "number" - } - }, - "$id": "properties_2_0" - } - ] - }, - "tests": [ - { - "description": "object with all numbers is valid", - "data": { - "foo\nbar": 1, - "foo\"bar": 1, - "foo\\bar": 1, - "foo\rbar": 1, - "foo\tbar": 1, - "foo\fbar": 1 - }, - "valid": true, - "schema_id": "properties_2_0" - }, - { - "description": "object with strings is invalid", - "data": { - "foo\nbar": "1", - "foo\"bar": "1", - "foo\\bar": "1", - "foo\rbar": "1", - "foo\tbar": "1", - "foo\fbar": "1" - }, - "valid": false, - "schema_id": "properties_2_0" - } - ] - }, - { - "description": "properties with null valued instance properties", - "database": { - "schemas": [ - { - "properties": { - "foo": { - "type": "null" - } - }, - "$id": "properties_3_0" - } - ] - }, - "tests": [ - { - "description": "allows null values", - "data": { - "foo": null - }, - "valid": true, - "schema_id": "properties_3_0" - } - ] - }, - { - "description": "properties whose names are Javascript object property names", - "comment": "Ensure JS implementations don't universally consider e.g. __proto__ to always be present in an object.", - "database": { - "schemas": [ - { - "properties": { - "__proto__": { - "type": "number" - }, - "toString": { - "properties": { - "length": { - "type": "string" - } - } - }, - "constructor": { - "type": "number" - } - }, - "$id": "properties_4_0" - } - ] - }, - "tests": [ - { - "description": "ignores arrays", - "data": [], - "valid": true, - "schema_id": "properties_4_0" - }, - { - "description": "ignores other non-objects", - "data": 12, - "valid": true, - "schema_id": "properties_4_0" - }, - { - "description": "none of the properties mentioned", - "data": {}, - "valid": true, - "schema_id": "properties_4_0" - }, - { - "description": "__proto__ not valid", - "data": { - "__proto__": "foo" - }, - "valid": false, - "schema_id": "properties_4_0" - }, - { - "description": "toString not valid", - "data": { - "toString": { - "length": 37 - } - }, - "valid": false, - "schema_id": "properties_4_0" - }, - { - "description": "constructor not valid", - "data": { - "constructor": { - "length": 37 - } - }, - "valid": false, - "schema_id": "properties_4_0" - }, - { - "description": "all present and valid", - "data": { - "__proto__": 12, - "toString": { - "length": "foo" - }, - "constructor": 37 - }, - "valid": true, - "schema_id": "properties_4_0" - } - ] - }, - { - "description": "extensible: true allows extra properties", - "database": { - "schemas": [ - { - "properties": { - "foo": { - "type": "integer" - } - }, - "extensible": true, - "$id": "properties_5_0" - } - ] - }, - "tests": [ - { - "description": "extra property is valid", - "data": { - "foo": 1, - "bar": "baz" - }, - "valid": true, - "schema_id": "properties_5_0" - } - ] - }, - { - "description": "strict by default: extra properties invalid", - "database": { - "schemas": [ - { - "properties": { - "foo": { - "type": "string" - } - }, - "$id": "properties_6_0" - } - ] - }, - "tests": [ - { - "description": "extra property is invalid", - "data": { - "foo": "bar", - "extra": 1 - }, - "valid": false, - "schema_id": "properties_6_0" - } - ] - }, - { - "description": "inheritance: nested object inherits strictness from strict parent", - "database": { - "schemas": [ - { - "properties": { - "nested": { - "properties": { - "foo": { - "type": "string" - } - } - } - }, - "$id": "properties_7_0" - } - ] - }, - "tests": [ - { - "description": "nested extra property is invalid", - "data": { - "nested": { - "foo": "bar", - "extra": 1 - } - }, - "valid": false, - "schema_id": "properties_7_0" - } - ] - }, - { - "description": "override: nested object allows extra properties if extensible: true", - "database": { - "schemas": [ - { - "properties": { - "nested": { - "extensible": true, - "properties": { - "foo": { - "type": "string" - } - } - } - }, - "$id": "properties_8_0" - } - ] - }, - "tests": [ - { - "description": "nested extra property is valid", - "data": { - "nested": { - "foo": "bar", - "extra": 1 - } - }, - "valid": true, - "schema_id": "properties_8_0" - } - ] - }, - { - "description": "inheritance: nested object inherits looseness from loose parent", - "database": { - "schemas": [ - { - "extensible": true, - "properties": { - "nested": { - "properties": { - "foo": { - "type": "string" - } - } - } - }, - "$id": "properties_9_0" - } - ] - }, - "tests": [ - { - "description": "nested extra property is valid", - "data": { - "nested": { - "foo": "bar", - "extra": 1 - } - }, - "valid": true, - "schema_id": "properties_9_0" - } - ] - }, - { - "description": "override: nested object enforces strictness if extensible: false", - "database": { - "schemas": [ - { - "extensible": true, - "properties": { - "nested": { - "extensible": false, - "properties": { - "foo": { - "type": "string" - } - } - } - }, - "$id": "properties_10_0" - } - ] - }, - "tests": [ - { - "description": "nested extra property is invalid", - "data": { - "nested": { - "foo": "bar", - "extra": 1 - } - }, - "valid": false, - "schema_id": "properties_10_0" - } - ] - }, - { - "description": "arrays: inline items inherit strictness from strict parent", - "database": { - "schemas": [ - { - "properties": { - "list": { - "type": "array", - "items": { - "properties": { - "foo": { - "type": "string" - } - } - } - } - }, - "$id": "properties_11_0" - } - ] - }, - "tests": [ - { - "description": "array item with extra property is invalid (strict parent)", - "data": { - "list": [ - { - "foo": "bar", - "extra": 1 - } - ] - }, - "valid": false, - "schema_id": "properties_11_0" - } - ] - }, - { - "description": "arrays: inline items inherit looseness from loose parent", - "database": { - "schemas": [ - { - "extensible": true, - "properties": { - "list": { - "type": "array", - "items": { - "properties": { - "foo": { - "type": "string" - } - } - } - } - }, - "$id": "properties_12_0" - } - ] - }, - "tests": [ - { - "description": "array item with extra property is valid (loose parent)", - "data": { - "list": [ - { - "foo": "bar", - "extra": 1 - } - ] - }, - "valid": true, - "schema_id": "properties_12_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/propertyNames.json b/tests/fixtures/propertyNames.json deleted file mode 100644 index 047b0d7..0000000 --- a/tests/fixtures/propertyNames.json +++ /dev/null @@ -1,281 +0,0 @@ -[ - { - "description": "propertyNames validation", - "database": { - "schemas": [ - { - "propertyNames": { - "maxLength": 3 - }, - "extensible": true, - "$id": "propertyNames_0_0" - } - ] - }, - "tests": [ - { - "description": "all property names valid", - "data": { - "f": {}, - "foo": {} - }, - "valid": true, - "schema_id": "propertyNames_0_0" - }, - { - "description": "some property names invalid", - "data": { - "foo": {}, - "foobar": {} - }, - "valid": false, - "schema_id": "propertyNames_0_0" - }, - { - "description": "object without properties is valid", - "data": {}, - "valid": true, - "schema_id": "propertyNames_0_0" - }, - { - "description": "ignores arrays", - "data": [ - 1, - 2, - 3, - 4 - ], - "valid": true, - "schema_id": "propertyNames_0_0" - }, - { - "description": "ignores strings", - "data": "foobar", - "valid": true, - "schema_id": "propertyNames_0_0" - }, - { - "description": "ignores other non-objects", - "data": 12, - "valid": true, - "schema_id": "propertyNames_0_0" - } - ] - }, - { - "description": "propertyNames validation with pattern", - "database": { - "schemas": [ - { - "propertyNames": { - "pattern": "^a+$" - }, - "extensible": true, - "$id": "propertyNames_1_0" - } - ] - }, - "tests": [ - { - "description": "matching property names valid", - "data": { - "a": {}, - "aa": {}, - "aaa": {} - }, - "valid": true, - "schema_id": "propertyNames_1_0" - }, - { - "description": "non-matching property name is invalid", - "data": { - "aaA": {} - }, - "valid": false, - "schema_id": "propertyNames_1_0" - }, - { - "description": "object without properties is valid", - "data": {}, - "valid": true, - "schema_id": "propertyNames_1_0" - } - ] - }, - { - "description": "propertyNames with boolean schema true", - "database": { - "schemas": [ - { - "propertyNames": true, - "extensible": true, - "$id": "propertyNames_2_0" - } - ] - }, - "tests": [ - { - "description": "object with any properties is valid", - "data": { - "foo": 1 - }, - "valid": true, - "schema_id": "propertyNames_2_0" - }, - { - "description": "empty object is valid", - "data": {}, - "valid": true, - "schema_id": "propertyNames_2_0" - } - ] - }, - { - "description": "propertyNames with boolean schema false", - "database": { - "schemas": [ - { - "propertyNames": false, - "extensible": true, - "$id": "propertyNames_3_0" - } - ] - }, - "tests": [ - { - "description": "object with any properties is invalid", - "data": { - "foo": 1 - }, - "valid": false, - "schema_id": "propertyNames_3_0" - }, - { - "description": "empty object is valid", - "data": {}, - "valid": true, - "schema_id": "propertyNames_3_0" - } - ] - }, - { - "description": "propertyNames with const", - "database": { - "schemas": [ - { - "propertyNames": { - "const": "foo" - }, - "extensible": true, - "$id": "propertyNames_4_0" - } - ] - }, - "tests": [ - { - "description": "object with property foo is valid", - "data": { - "foo": 1 - }, - "valid": true, - "schema_id": "propertyNames_4_0" - }, - { - "description": "object with any other property is invalid", - "data": { - "bar": 1 - }, - "valid": false, - "schema_id": "propertyNames_4_0" - }, - { - "description": "empty object is valid", - "data": {}, - "valid": true, - "schema_id": "propertyNames_4_0" - } - ] - }, - { - "description": "propertyNames with enum", - "database": { - "schemas": [ - { - "propertyNames": { - "enum": [ - "foo", - "bar" - ] - }, - "extensible": true, - "$id": "propertyNames_5_0" - } - ] - }, - "tests": [ - { - "description": "object with property foo is valid", - "data": { - "foo": 1 - }, - "valid": true, - "schema_id": "propertyNames_5_0" - }, - { - "description": "object with property foo and bar is valid", - "data": { - "foo": 1, - "bar": 1 - }, - "valid": true, - "schema_id": "propertyNames_5_0" - }, - { - "description": "object with any other property is invalid", - "data": { - "baz": 1 - }, - "valid": false, - "schema_id": "propertyNames_5_0" - }, - { - "description": "empty object is valid", - "data": {}, - "valid": true, - "schema_id": "propertyNames_5_0" - } - ] - }, - { - "description": "extensible: true allows extra properties (checked by propertyNames)", - "database": { - "schemas": [ - { - "propertyNames": { - "maxLength": 3 - }, - "extensible": true, - "$id": "propertyNames_6_0" - } - ] - }, - "tests": [ - { - "description": "extra property with valid name is valid", - "data": { - "foo": 1 - }, - "valid": true, - "schema_id": "propertyNames_6_0" - }, - { - "description": "extra property with invalid name is invalid", - "data": { - "foobar": 1 - }, - "valid": false, - "schema_id": "propertyNames_6_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/ref.json b/tests/fixtures/ref.json deleted file mode 100644 index 1a621d6..0000000 --- a/tests/fixtures/ref.json +++ /dev/null @@ -1,833 +0,0 @@ -[ - { - "description": "nested refs", - "database": { - "schemas": [ - { - "$ref": "c_212", - "$id": "ref_4_0" - }, - { - "$id": "a_212", - "type": "integer" - }, - { - "$id": "b_212", - "$ref": "a_212" - }, - { - "$id": "c_212", - "$ref": "b_212" - } - ] - }, - "tests": [ - { - "description": "nested ref valid", - "data": 5, - "valid": true, - "schema_id": "ref_4_0" - }, - { - "description": "nested ref invalid", - "data": "a", - "valid": false, - "schema_id": "ref_4_0" - } - ] - }, - { - "description": "ref applies alongside sibling keywords", - "database": { - "schemas": [ - { - "properties": { - "foo": { - "$ref": "reffed_248", - "maxItems": 2 - } - }, - "$id": "ref_5_0" - }, - { - "$id": "reffed_248", - "type": "array" - } - ] - }, - "tests": [ - { - "description": "ref valid, maxItems valid", - "data": { - "foo": [] - }, - "valid": true, - "schema_id": "ref_5_0" - }, - { - "description": "ref valid, maxItems invalid", - "data": { - "foo": [ - 1, - 2, - 3 - ] - }, - "valid": false, - "schema_id": "ref_5_0" - }, - { - "description": "ref invalid", - "data": { - "foo": "string" - }, - "valid": false, - "schema_id": "ref_5_0" - } - ] - }, - { - "description": "property named $ref that is not a reference", - "database": { - "schemas": [ - { - "properties": { - "$ref": { - "type": "string" - } - }, - "$id": "ref_6_0" - } - ] - }, - "tests": [ - { - "description": "property named $ref valid", - "data": { - "$ref": "a" - }, - "valid": true, - "schema_id": "ref_6_0" - }, - { - "description": "property named $ref invalid", - "data": { - "$ref": 2 - }, - "valid": false, - "schema_id": "ref_6_0" - } - ] - }, - { - "description": "property named $ref, containing an actual $ref", - "database": { - "schemas": [ - { - "properties": { - "$ref": { - "$ref": "is-string_344" - } - }, - "$id": "ref_7_0" - }, - { - "$id": "is-string_344", - "type": "string" - } - ] - }, - "tests": [ - { - "description": "property named $ref valid", - "data": { - "$ref": "a" - }, - "valid": true, - "schema_id": "ref_7_0" - }, - { - "description": "property named $ref invalid", - "data": { - "$ref": 2 - }, - "valid": false, - "schema_id": "ref_7_0" - } - ] - }, - { - "description": "$ref to boolean schema true", - "database": { - "schemas": [ - { - "$ref": "bool_378", - "$id": "ref_8_0" - }, - { - "$id": "bool_378", - "extensible": true - } - ] - }, - "tests": [ - { - "description": "any value is valid", - "data": "foo", - "valid": true, - "schema_id": "ref_8_0" - } - ] - }, - { - "description": "$ref to boolean schema false", - "database": { - "schemas": [ - { - "$ref": "bool_400", - "$id": "ref_9_0" - }, - { - "$id": "bool_400", - "extensible": false, - "not": {} - } - ] - }, - "tests": [ - { - "description": "any value is invalid", - "data": "foo", - "valid": false, - "schema_id": "ref_9_0" - } - ] - }, - { - "description": "refs with quote", - "database": { - "schemas": [ - { - "properties": { - "foo\"bar": { - "$ref": "foo%22bar_550" - } - }, - "$id": "ref_11_0" - }, - { - "$id": "foo%22bar_550", - "type": "number" - } - ] - }, - "tests": [ - { - "description": "object with numbers is valid", - "data": { - "foo\"bar": 1 - }, - "valid": true, - "schema_id": "ref_11_0" - }, - { - "description": "object with strings is invalid", - "data": { - "foo\"bar": "1" - }, - "valid": false, - "schema_id": "ref_11_0" - } - ] - }, - { - "description": "$ref boundary resets to loose", - "database": { - "schemas": [ - { - "$ref": "target_1465", - "$id": "ref_35_0" - }, - { - "$id": "target_1465", - "properties": { - "foo": { - "type": "string" - } - } - } - ] - }, - "tests": [ - { - "description": "extra property in ref target is invalid (strict by default)", - "data": { - "foo": "bar", - "extra": 1 - }, - "valid": false, - "schema_id": "ref_35_0" - } - ] - }, - { - "description": "$ref target can enforce strictness", - "database": { - "schemas": [ - { - "$ref": "target_1496", - "$id": "ref_36_0" - }, - { - "$id": "target_1496", - "extensible": false, - "properties": { - "foo": { - "type": "string" - } - } - } - ] - }, - "tests": [ - { - "description": "extra property in ref target is invalid", - "data": { - "foo": "bar", - "extra": 1 - }, - "valid": false, - "schema_id": "ref_36_0" - } - ] - }, - { - "description": "strictness: boundary reset at $ref", - "database": { - "schemas": [ - { - "extensible": true, - "properties": { - "inline_child": { - "properties": { - "a": { - "type": "integer" - } - } - }, - "ref_child": { - "$ref": "strict_node_1544" - }, - "extensible_ref_child": { - "$ref": "extensible_node_1551" - } - }, - "$id": "ref_37_0" - }, - { - "$id": "strict_node_1544", - "properties": { - "b": { - "type": "integer" - } - } - }, - { - "$id": "extensible_node_1551", - "extensible": true, - "properties": { - "c": { - "type": "integer" - } - } - } - ] - }, - "tests": [ - { - "description": "inline child inherits looseness", - "data": { - "inline_child": { - "a": 1, - "extra": 2 - } - }, - "valid": true, - "schema_id": "ref_37_0" - }, - { - "description": "ref child resets to strict (default)", - "data": { - "ref_child": { - "b": 1, - "extra": 2 - } - }, - "valid": false, - "schema_id": "ref_37_0" - }, - { - "description": "ref child with explicit extensible=true is loose", - "data": { - "extensible_ref_child": { - "c": 1, - "extra": 2 - } - }, - "valid": true, - "schema_id": "ref_37_0" - } - ] - }, - { - "description": "arrays: ref items inherit strictness (reset at boundary)", - "database": { - "schemas": [ - { - "properties": { - "list": { - "type": "array", - "items": { - "$ref": "strict_node_1614" - } - } - }, - "$id": "ref_38_0" - }, - { - "$id": "strict_node_1614", - "properties": { - "a": { - "type": "integer" - } - } - } - ] - }, - "tests": [ - { - "description": "ref item with extra property is invalid (strict by default)", - "data": { - "list": [ - { - "a": 1, - "extra": 2 - } - ] - }, - "valid": false, - "schema_id": "ref_38_0" - } - ] - }, - { - "description": "implicit keyword shadowing", - "database": { - "schemas": [ - { - "$ref": "parent_1648", - "properties": { - "type": { - "const": "child" - }, - "age": { - "minimum": 15 - } - }, - "$id": "ref_39_0" - }, - { - "$id": "parent_1648", - "type": "object", - "properties": { - "type": { - "const": "parent" - }, - "age": { - "minimum": 10, - "maximum": 20 - } - }, - "required": [ - "type", - "age" - ] - } - ] - }, - "tests": [ - { - "description": "child type overrides parent type", - "data": { - "type": "child", - "age": 15 - }, - "valid": true, - "schema_id": "ref_39_0" - }, - { - "description": "parent type is now invalid (shadowed)", - "data": { - "type": "parent", - "age": 15 - }, - "valid": false, - "schema_id": "ref_39_0" - }, - { - "description": "child min age (15) is enforced", - "data": { - "type": "child", - "age": 12 - }, - "valid": false, - "schema_id": "ref_39_0" - }, - { - "description": "parent max age (20) is shadowed (replaced) by child definition", - "data": { - "type": "child", - "age": 21 - }, - "valid": true, - "schema_id": "ref_39_0" - } - ] - }, - { - "description": "Entities extending entities (Physical Birth)", - "database": { - "types": [ - { - "name": "entity", - "variations": [ - "entity", - "organization", - "person" - ], - "schemas": [ - { - "$id": "entity", - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "type": { - "type": "string" - } - } - } - ] - }, - { - "name": "organization", - "variations": [ - "organization", - "person" - ], - "schemas": [ - { - "$id": "organization", - "$ref": "entity", - "properties": { - "name": { - "type": "string" - } - } - } - ] - }, - { - "name": "person", - "variations": [ - "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", - "variations": [ - "entity", - "person" - ], - "schemas": [ - { - "$id": "entity", - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "type": { - "type": "string" - } - } - } - ] - }, - { - "name": "person", - "variations": [ - "person" - ], - "schemas": [ - { - "$id": "person", - "$ref": "entity", - "properties": { - "first_name": { - "type": "string" - } - } - }, - { - "$id": "light.person", - "$ref": "entity", - "properties": { - "first_name": { - "type": "string" - } - } - } - ] - } - ], - "puncs": [ - { - "name": "save_person_light", - "schemas": [ - { - "$id": "save_person_light.request", - "$ref": "light.person", - "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 - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/required.json b/tests/fixtures/required.json deleted file mode 100644 index c44f087..0000000 --- a/tests/fixtures/required.json +++ /dev/null @@ -1,255 +0,0 @@ -[ - { - "description": "required validation", - "database": { - "schemas": [ - { - "properties": { - "foo": {}, - "bar": {} - }, - "required": [ - "foo" - ], - "$id": "required_0_0" - } - ] - }, - "tests": [ - { - "description": "present required property is valid", - "data": { - "foo": 1 - }, - "valid": true, - "schema_id": "required_0_0" - }, - { - "description": "non-present required property is invalid", - "data": { - "bar": 1 - }, - "valid": false, - "schema_id": "required_0_0" - }, - { - "description": "ignores arrays", - "data": [], - "valid": true, - "schema_id": "required_0_0" - }, - { - "description": "ignores strings", - "data": "", - "valid": true, - "schema_id": "required_0_0" - }, - { - "description": "ignores other non-objects", - "data": 12, - "valid": true, - "schema_id": "required_0_0" - }, - { - "description": "ignores null", - "data": null, - "valid": true, - "schema_id": "required_0_0" - }, - { - "description": "ignores boolean", - "data": true, - "valid": true, - "schema_id": "required_0_0" - } - ] - }, - { - "description": "required default validation", - "database": { - "schemas": [ - { - "properties": { - "foo": {} - }, - "$id": "required_1_0" - } - ] - }, - "tests": [ - { - "description": "not required by default", - "data": {}, - "valid": true, - "schema_id": "required_1_0" - } - ] - }, - { - "description": "required with empty array", - "database": { - "schemas": [ - { - "properties": { - "foo": {} - }, - "required": [], - "$id": "required_2_0" - } - ] - }, - "tests": [ - { - "description": "property not required", - "data": {}, - "valid": true, - "schema_id": "required_2_0" - } - ] - }, - { - "description": "required with escaped characters", - "database": { - "schemas": [ - { - "required": [ - "foo\nbar", - "foo\"bar", - "foo\\bar", - "foo\rbar", - "foo\tbar", - "foo\fbar" - ], - "extensible": true, - "$id": "required_3_0" - } - ] - }, - "tests": [ - { - "description": "object with all properties present is valid", - "data": { - "foo\nbar": 1, - "foo\"bar": 1, - "foo\\bar": 1, - "foo\rbar": 1, - "foo\tbar": 1, - "foo\fbar": 1 - }, - "valid": true, - "schema_id": "required_3_0" - }, - { - "description": "object with some properties missing is invalid", - "data": { - "foo\nbar": "1", - "foo\"bar": "1" - }, - "valid": false, - "schema_id": "required_3_0" - } - ] - }, - { - "description": "required properties whose names are Javascript object property names", - "comment": "Ensure JS implementations don't universally consider e.g. __proto__ to always be present in an object.", - "database": { - "schemas": [ - { - "required": [ - "__proto__", - "toString", - "constructor" - ], - "extensible": true, - "$id": "required_4_0" - } - ] - }, - "tests": [ - { - "description": "ignores arrays", - "data": [], - "valid": true, - "schema_id": "required_4_0" - }, - { - "description": "ignores other non-objects", - "data": 12, - "valid": true, - "schema_id": "required_4_0" - }, - { - "description": "none of the properties mentioned", - "data": {}, - "valid": false, - "schema_id": "required_4_0" - }, - { - "description": "__proto__ present", - "data": { - "__proto__": "foo" - }, - "valid": false, - "schema_id": "required_4_0" - }, - { - "description": "toString present", - "data": { - "toString": { - "length": 37 - } - }, - "valid": false, - "schema_id": "required_4_0" - }, - { - "description": "constructor present", - "data": { - "constructor": { - "length": 37 - } - }, - "valid": false, - "schema_id": "required_4_0" - }, - { - "description": "all present", - "data": { - "__proto__": 12, - "toString": { - "length": "foo" - }, - "constructor": 37 - }, - "valid": true, - "schema_id": "required_4_0" - } - ] - }, - { - "description": "extensible: true allows extra properties in required", - "database": { - "schemas": [ - { - "required": [ - "foo" - ], - "extensible": true, - "$id": "required_5_0" - } - ] - }, - "tests": [ - { - "description": "extra property is valid", - "data": { - "foo": 1, - "bar": 2 - }, - "valid": true, - "schema_id": "required_5_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/type.json b/tests/fixtures/type.json deleted file mode 100644 index 1b0f626..0000000 --- a/tests/fixtures/type.json +++ /dev/null @@ -1,669 +0,0 @@ -[ - { - "description": "integer type matches integers", - "database": { - "schemas": [ - { - "type": "integer", - "$id": "type_0_0" - } - ] - }, - "tests": [ - { - "description": "an integer is an integer", - "data": 1, - "valid": true, - "schema_id": "type_0_0" - }, - { - "description": "a float with zero fractional part is an integer", - "data": 1, - "valid": true, - "schema_id": "type_0_0" - }, - { - "description": "a float is not an integer", - "data": 1.1, - "valid": false, - "schema_id": "type_0_0" - }, - { - "description": "a string is not an integer", - "data": "foo", - "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, - "schema_id": "type_0_0" - }, - { - "description": "an object is not an integer", - "data": {}, - "valid": false, - "schema_id": "type_0_0" - }, - { - "description": "an array is not an integer", - "data": [], - "valid": false, - "schema_id": "type_0_0" - }, - { - "description": "a boolean is not an integer", - "data": true, - "valid": false, - "schema_id": "type_0_0" - }, - { - "description": "null is not an integer", - "data": null, - "valid": false, - "schema_id": "type_0_0" - } - ] - }, - { - "description": "number type matches numbers", - "database": { - "schemas": [ - { - "type": "number", - "$id": "type_1_0" - } - ] - }, - "tests": [ - { - "description": "an integer is a number", - "data": 1, - "valid": true, - "schema_id": "type_1_0" - }, - { - "description": "a float with zero fractional part is a number (and an integer)", - "data": 1, - "valid": true, - "schema_id": "type_1_0" - }, - { - "description": "a float is a number", - "data": 1.1, - "valid": true, - "schema_id": "type_1_0" - }, - { - "description": "a string is not a number", - "data": "foo", - "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, - "schema_id": "type_1_0" - }, - { - "description": "an object is not a number", - "data": {}, - "valid": false, - "schema_id": "type_1_0" - }, - { - "description": "an array is not a number", - "data": [], - "valid": false, - "schema_id": "type_1_0" - }, - { - "description": "a boolean is not a number", - "data": true, - "valid": false, - "schema_id": "type_1_0" - }, - { - "description": "null is not a number", - "data": null, - "valid": false, - "schema_id": "type_1_0" - } - ] - }, - { - "description": "string type matches strings", - "database": { - "schemas": [ - { - "type": "string", - "$id": "type_2_0" - } - ] - }, - "tests": [ - { - "description": "1 is not a string", - "data": 1, - "valid": false, - "schema_id": "type_2_0" - }, - { - "description": "a float is not a string", - "data": 1.1, - "valid": false, - "schema_id": "type_2_0" - }, - { - "description": "a string is a string", - "data": "foo", - "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, - "schema_id": "type_2_0" - }, - { - "description": "an empty string is still a string", - "data": "", - "valid": true, - "schema_id": "type_2_0" - }, - { - "description": "an object is not a string", - "data": {}, - "valid": false, - "schema_id": "type_2_0" - }, - { - "description": "an array is not a string", - "data": [], - "valid": false, - "schema_id": "type_2_0" - }, - { - "description": "a boolean is not a string", - "data": true, - "valid": false, - "schema_id": "type_2_0" - }, - { - "description": "null is not a string", - "data": null, - "valid": false, - "schema_id": "type_2_0" - } - ] - }, - { - "description": "object type matches objects", - "database": { - "schemas": [ - { - "type": "object", - "$id": "type_3_0" - } - ] - }, - "tests": [ - { - "description": "an integer is not an object", - "data": 1, - "valid": false, - "schema_id": "type_3_0" - }, - { - "description": "a float is not an object", - "data": 1.1, - "valid": false, - "schema_id": "type_3_0" - }, - { - "description": "a string is not an object", - "data": "foo", - "valid": false, - "schema_id": "type_3_0" - }, - { - "description": "an object is an object", - "data": {}, - "valid": true, - "schema_id": "type_3_0" - }, - { - "description": "an array is not an object", - "data": [], - "valid": false, - "schema_id": "type_3_0" - }, - { - "description": "a boolean is not an object", - "data": true, - "valid": false, - "schema_id": "type_3_0" - }, - { - "description": "null is not an object", - "data": null, - "valid": false, - "schema_id": "type_3_0" - } - ] - }, - { - "description": "array type matches arrays", - "database": { - "schemas": [ - { - "type": "array", - "$id": "type_4_0" - } - ] - }, - "tests": [ - { - "description": "an integer is not an array", - "data": 1, - "valid": false, - "schema_id": "type_4_0" - }, - { - "description": "a float is not an array", - "data": 1.1, - "valid": false, - "schema_id": "type_4_0" - }, - { - "description": "a string is not an array", - "data": "foo", - "valid": false, - "schema_id": "type_4_0" - }, - { - "description": "an object is not an array", - "data": {}, - "valid": false, - "schema_id": "type_4_0" - }, - { - "description": "an array is an array", - "data": [], - "valid": true, - "schema_id": "type_4_0" - }, - { - "description": "a boolean is not an array", - "data": true, - "valid": false, - "schema_id": "type_4_0" - }, - { - "description": "null is not an array", - "data": null, - "valid": false, - "schema_id": "type_4_0" - } - ] - }, - { - "description": "boolean type matches booleans", - "database": { - "schemas": [ - { - "type": "boolean", - "$id": "type_5_0" - } - ] - }, - "tests": [ - { - "description": "an integer is not a boolean", - "data": 1, - "valid": false, - "schema_id": "type_5_0" - }, - { - "description": "zero is not a boolean", - "data": 0, - "valid": false, - "schema_id": "type_5_0" - }, - { - "description": "a float is not a boolean", - "data": 1.1, - "valid": false, - "schema_id": "type_5_0" - }, - { - "description": "a string is not a boolean", - "data": "foo", - "valid": false, - "schema_id": "type_5_0" - }, - { - "description": "an empty string is a null", - "data": "", - "valid": true, - "schema_id": "type_5_0" - }, - { - "description": "an object is not a boolean", - "data": {}, - "valid": false, - "schema_id": "type_5_0" - }, - { - "description": "an array is not a boolean", - "data": [], - "valid": false, - "schema_id": "type_5_0" - }, - { - "description": "true is a boolean", - "data": true, - "valid": true, - "schema_id": "type_5_0" - }, - { - "description": "false is a boolean", - "data": false, - "valid": true, - "schema_id": "type_5_0" - }, - { - "description": "null is not a boolean", - "data": null, - "valid": false, - "schema_id": "type_5_0" - } - ] - }, - { - "description": "null type matches only the null object", - "database": { - "schemas": [ - { - "type": "null", - "$id": "type_6_0" - } - ] - }, - "tests": [ - { - "description": "an integer is not null", - "data": 1, - "valid": false, - "schema_id": "type_6_0" - }, - { - "description": "a float is not null", - "data": 1.1, - "valid": false, - "schema_id": "type_6_0" - }, - { - "description": "zero is not null", - "data": 0, - "valid": false, - "schema_id": "type_6_0" - }, - { - "description": "a string is not null", - "data": "foo", - "valid": false, - "schema_id": "type_6_0" - }, - { - "description": "an empty string is null", - "data": "", - "valid": true, - "schema_id": "type_6_0" - }, - { - "description": "an object is not null", - "data": {}, - "valid": false, - "schema_id": "type_6_0" - }, - { - "description": "an array is not null", - "data": [], - "valid": false, - "schema_id": "type_6_0" - }, - { - "description": "true is not null", - "data": true, - "valid": false, - "schema_id": "type_6_0" - }, - { - "description": "false is not null", - "data": false, - "valid": false, - "schema_id": "type_6_0" - }, - { - "description": "null is null", - "data": null, - "valid": true, - "schema_id": "type_6_0" - } - ] - }, - { - "description": "multiple types can be specified in an array", - "database": { - "schemas": [ - { - "type": [ - "integer", - "string" - ], - "$id": "type_7_0" - } - ] - }, - "tests": [ - { - "description": "an integer is valid", - "data": 1, - "valid": true, - "schema_id": "type_7_0" - }, - { - "description": "a string is valid", - "data": "foo", - "valid": true, - "schema_id": "type_7_0" - }, - { - "description": "a float is invalid", - "data": 1.1, - "valid": false, - "schema_id": "type_7_0" - }, - { - "description": "an object is invalid", - "data": {}, - "valid": false, - "schema_id": "type_7_0" - }, - { - "description": "an array is invalid", - "data": [], - "valid": false, - "schema_id": "type_7_0" - }, - { - "description": "a boolean is invalid", - "data": true, - "valid": false, - "schema_id": "type_7_0" - }, - { - "description": "null is invalid", - "data": null, - "valid": false, - "schema_id": "type_7_0" - } - ] - }, - { - "description": "type as array with one item", - "database": { - "schemas": [ - { - "type": [ - "string" - ], - "$id": "type_8_0" - } - ] - }, - "tests": [ - { - "description": "string is valid", - "data": "foo", - "valid": true, - "schema_id": "type_8_0" - }, - { - "description": "number is invalid", - "data": 123, - "valid": false, - "schema_id": "type_8_0" - } - ] - }, - { - "description": "type: array or object", - "database": { - "schemas": [ - { - "type": [ - "array", - "object" - ], - "items": {}, - "$id": "type_9_0" - } - ] - }, - "tests": [ - { - "description": "array is valid", - "data": [ - 1, - 2, - 3 - ], - "valid": true, - "schema_id": "type_9_0" - }, - { - "description": "object is valid", - "data": {}, - "valid": true, - "schema_id": "type_9_0" - }, - { - "description": "number is invalid", - "data": 123, - "valid": false, - "schema_id": "type_9_0" - }, - { - "description": "string is invalid", - "data": "foo", - "valid": false, - "schema_id": "type_9_0" - }, - { - "description": "null is invalid", - "data": null, - "valid": false, - "schema_id": "type_9_0" - } - ] - }, - { - "description": "type: array, object or null", - "database": { - "schemas": [ - { - "type": [ - "array", - "object", - "null" - ], - "items": {}, - "$id": "type_10_0" - } - ] - }, - "tests": [ - { - "description": "array is valid", - "data": [ - 1, - 2, - 3 - ], - "valid": true, - "schema_id": "type_10_0" - }, - { - "description": "object is valid", - "data": {}, - "valid": true, - "schema_id": "type_10_0" - }, - { - "description": "null is valid", - "data": null, - "valid": true, - "schema_id": "type_10_0" - }, - { - "description": "number is invalid", - "data": 123, - "valid": false, - "schema_id": "type_10_0" - }, - { - "description": "string is invalid", - "data": "foo", - "valid": false, - "schema_id": "type_10_0" - } - ] - }, - { - "description": "extensible: true allows extra properties", - "database": { - "schemas": [ - { - "type": "object", - "extensible": true, - "$id": "type_11_0" - } - ] - }, - "tests": [ - { - "description": "extra property is valid", - "data": { - "foo": 1 - }, - "valid": true, - "schema_id": "type_11_0" - } - ] - } -] \ No newline at end of file diff --git a/tests/fixtures/uniqueItems.json b/tests/fixtures/uniqueItems.json deleted file mode 100644 index c6bc510..0000000 --- a/tests/fixtures/uniqueItems.json +++ /dev/null @@ -1,958 +0,0 @@ -[ - { - "description": "uniqueItems validation", - "database": { - "schemas": [ - { - "uniqueItems": true, - "extensible": true, - "$id": "uniqueItems_0_0" - } - ] - }, - "tests": [ - { - "description": "unique array of integers is valid", - "data": [ - 1, - 2 - ], - "valid": true, - "schema_id": "uniqueItems_0_0" - }, - { - "description": "non-unique array of integers is invalid", - "data": [ - 1, - 1 - ], - "valid": false, - "schema_id": "uniqueItems_0_0" - }, - { - "description": "non-unique array of more than two integers is invalid", - "data": [ - 1, - 2, - 1 - ], - "valid": false, - "schema_id": "uniqueItems_0_0" - }, - { - "description": "numbers are unique if mathematically unequal", - "data": [ - 1, - 1, - 1 - ], - "valid": false, - "schema_id": "uniqueItems_0_0" - }, - { - "description": "false is not equal to zero", - "data": [ - 0, - false - ], - "valid": true, - "schema_id": "uniqueItems_0_0" - }, - { - "description": "true is not equal to one", - "data": [ - 1, - true - ], - "valid": true, - "schema_id": "uniqueItems_0_0" - }, - { - "description": "unique array of strings is valid", - "data": [ - "foo", - "bar", - "baz" - ], - "valid": true, - "schema_id": "uniqueItems_0_0" - }, - { - "description": "non-unique array of strings is invalid", - "data": [ - "foo", - "bar", - "foo" - ], - "valid": false, - "schema_id": "uniqueItems_0_0" - }, - { - "description": "unique array of objects is valid", - "data": [ - { - "foo": "bar" - }, - { - "foo": "baz" - } - ], - "valid": true, - "schema_id": "uniqueItems_0_0" - }, - { - "description": "non-unique array of objects is invalid", - "data": [ - { - "foo": "bar" - }, - { - "foo": "bar" - } - ], - "valid": false, - "schema_id": "uniqueItems_0_0" - }, - { - "description": "property order of array of objects is ignored", - "data": [ - { - "foo": "bar", - "bar": "foo" - }, - { - "bar": "foo", - "foo": "bar" - } - ], - "valid": false, - "schema_id": "uniqueItems_0_0" - }, - { - "description": "unique array of nested objects is valid", - "data": [ - { - "foo": { - "bar": { - "baz": true - } - } - }, - { - "foo": { - "bar": { - "baz": false - } - } - } - ], - "valid": true, - "schema_id": "uniqueItems_0_0" - }, - { - "description": "non-unique array of nested objects is invalid", - "data": [ - { - "foo": { - "bar": { - "baz": true - } - } - }, - { - "foo": { - "bar": { - "baz": true - } - } - } - ], - "valid": false, - "schema_id": "uniqueItems_0_0" - }, - { - "description": "unique array of arrays is valid", - "data": [ - [ - "foo" - ], - [ - "bar" - ] - ], - "valid": true, - "schema_id": "uniqueItems_0_0" - }, - { - "description": "non-unique array of arrays is invalid", - "data": [ - [ - "foo" - ], - [ - "foo" - ] - ], - "valid": false, - "schema_id": "uniqueItems_0_0" - }, - { - "description": "non-unique array of more than two arrays is invalid", - "data": [ - [ - "foo" - ], - [ - "bar" - ], - [ - "foo" - ] - ], - "valid": false, - "schema_id": "uniqueItems_0_0" - }, - { - "description": "1 and true are unique", - "data": [ - 1, - true - ], - "valid": true, - "schema_id": "uniqueItems_0_0" - }, - { - "description": "0 and false are unique", - "data": [ - 0, - false - ], - "valid": true, - "schema_id": "uniqueItems_0_0" - }, - { - "description": "[1] and [true] are unique", - "data": [ - [ - 1 - ], - [ - true - ] - ], - "valid": true, - "schema_id": "uniqueItems_0_0" - }, - { - "description": "[0] and [false] are unique", - "data": [ - [ - 0 - ], - [ - false - ] - ], - "valid": true, - "schema_id": "uniqueItems_0_0" - }, - { - "description": "nested [1] and [true] are unique", - "data": [ - [ - [ - 1 - ], - "foo" - ], - [ - [ - true - ], - "foo" - ] - ], - "valid": true, - "schema_id": "uniqueItems_0_0" - }, - { - "description": "nested [0] and [false] are unique", - "data": [ - [ - [ - 0 - ], - "foo" - ], - [ - [ - false - ], - "foo" - ] - ], - "valid": true, - "schema_id": "uniqueItems_0_0" - }, - { - "description": "unique heterogeneous types are valid", - "data": [ - {}, - [ - 1 - ], - true, - null, - 1, - "{}" - ], - "valid": true, - "schema_id": "uniqueItems_0_0" - }, - { - "description": "non-unique heterogeneous types are invalid", - "data": [ - {}, - [ - 1 - ], - true, - null, - {}, - 1 - ], - "valid": false, - "schema_id": "uniqueItems_0_0" - }, - { - "description": "different objects are unique", - "data": [ - { - "a": 1, - "b": 2 - }, - { - "a": 2, - "b": 1 - } - ], - "valid": true, - "schema_id": "uniqueItems_0_0" - }, - { - "description": "objects are non-unique despite key order", - "data": [ - { - "a": 1, - "b": 2 - }, - { - "b": 2, - "a": 1 - } - ], - "valid": false, - "schema_id": "uniqueItems_0_0" - }, - { - "description": "{\"a\": false} and {\"a\": 0} are unique", - "data": [ - { - "a": false - }, - { - "a": 0 - } - ], - "valid": true, - "schema_id": "uniqueItems_0_0" - }, - { - "description": "{\"a\": true} and {\"a\": 1} are unique", - "data": [ - { - "a": true - }, - { - "a": 1 - } - ], - "valid": true, - "schema_id": "uniqueItems_0_0" - } - ] - }, - { - "description": "uniqueItems with an array of items", - "database": { - "schemas": [ - { - "prefixItems": [ - { - "type": "boolean" - }, - { - "type": "boolean" - } - ], - "uniqueItems": true, - "extensible": true, - "$id": "uniqueItems_1_0" - } - ] - }, - "tests": [ - { - "description": "[false, true] from items array is valid", - "data": [ - false, - true - ], - "valid": true, - "schema_id": "uniqueItems_1_0" - }, - { - "description": "[true, false] from items array is valid", - "data": [ - true, - false - ], - "valid": true, - "schema_id": "uniqueItems_1_0" - }, - { - "description": "[false, false] from items array is not valid", - "data": [ - false, - false - ], - "valid": false, - "schema_id": "uniqueItems_1_0" - }, - { - "description": "[true, true] from items array is not valid", - "data": [ - true, - true - ], - "valid": false, - "schema_id": "uniqueItems_1_0" - }, - { - "description": "unique array extended from [false, true] is valid", - "data": [ - false, - true, - "foo", - "bar" - ], - "valid": true, - "schema_id": "uniqueItems_1_0" - }, - { - "description": "unique array extended from [true, false] is valid", - "data": [ - true, - false, - "foo", - "bar" - ], - "valid": true, - "schema_id": "uniqueItems_1_0" - }, - { - "description": "non-unique array extended from [false, true] is not valid", - "data": [ - false, - true, - "foo", - "foo" - ], - "valid": false, - "schema_id": "uniqueItems_1_0" - }, - { - "description": "non-unique array extended from [true, false] is not valid", - "data": [ - true, - false, - "foo", - "foo" - ], - "valid": false, - "schema_id": "uniqueItems_1_0" - } - ] - }, - { - "description": "uniqueItems with an array of items and additionalItems=false", - "database": { - "schemas": [ - { - "prefixItems": [ - { - "type": "boolean" - }, - { - "type": "boolean" - } - ], - "uniqueItems": true, - "items": false, - "$id": "uniqueItems_2_0" - } - ] - }, - "tests": [ - { - "description": "[false, true] from items array is valid", - "data": [ - false, - true - ], - "valid": true, - "schema_id": "uniqueItems_2_0" - }, - { - "description": "[true, false] from items array is valid", - "data": [ - true, - false - ], - "valid": true, - "schema_id": "uniqueItems_2_0" - }, - { - "description": "[false, false] from items array is not valid", - "data": [ - false, - false - ], - "valid": false, - "schema_id": "uniqueItems_2_0" - }, - { - "description": "[true, true] from items array is not valid", - "data": [ - true, - true - ], - "valid": false, - "schema_id": "uniqueItems_2_0" - }, - { - "description": "extra items are invalid even if unique", - "data": [ - false, - true, - null - ], - "valid": false, - "schema_id": "uniqueItems_2_0" - } - ] - }, - { - "description": "uniqueItems=false validation", - "database": { - "schemas": [ - { - "uniqueItems": false, - "extensible": true, - "$id": "uniqueItems_3_0" - } - ] - }, - "tests": [ - { - "description": "unique array of integers is valid", - "data": [ - 1, - 2 - ], - "valid": true, - "schema_id": "uniqueItems_3_0" - }, - { - "description": "non-unique array of integers is valid", - "data": [ - 1, - 1 - ], - "valid": true, - "schema_id": "uniqueItems_3_0" - }, - { - "description": "numbers are unique if mathematically unequal", - "data": [ - 1, - 1, - 1 - ], - "valid": true, - "schema_id": "uniqueItems_3_0" - }, - { - "description": "false is not equal to zero", - "data": [ - 0, - false - ], - "valid": true, - "schema_id": "uniqueItems_3_0" - }, - { - "description": "true is not equal to one", - "data": [ - 1, - true - ], - "valid": true, - "schema_id": "uniqueItems_3_0" - }, - { - "description": "unique array of objects is valid", - "data": [ - { - "foo": "bar" - }, - { - "foo": "baz" - } - ], - "valid": true, - "schema_id": "uniqueItems_3_0" - }, - { - "description": "non-unique array of objects is valid", - "data": [ - { - "foo": "bar" - }, - { - "foo": "bar" - } - ], - "valid": true, - "schema_id": "uniqueItems_3_0" - }, - { - "description": "unique array of nested objects is valid", - "data": [ - { - "foo": { - "bar": { - "baz": true - } - } - }, - { - "foo": { - "bar": { - "baz": false - } - } - } - ], - "valid": true, - "schema_id": "uniqueItems_3_0" - }, - { - "description": "non-unique array of nested objects is valid", - "data": [ - { - "foo": { - "bar": { - "baz": true - } - } - }, - { - "foo": { - "bar": { - "baz": true - } - } - } - ], - "valid": true, - "schema_id": "uniqueItems_3_0" - }, - { - "description": "unique array of arrays is valid", - "data": [ - [ - "foo" - ], - [ - "bar" - ] - ], - "valid": true, - "schema_id": "uniqueItems_3_0" - }, - { - "description": "non-unique array of arrays is valid", - "data": [ - [ - "foo" - ], - [ - "foo" - ] - ], - "valid": true, - "schema_id": "uniqueItems_3_0" - }, - { - "description": "1 and true are unique", - "data": [ - 1, - true - ], - "valid": true, - "schema_id": "uniqueItems_3_0" - }, - { - "description": "0 and false are unique", - "data": [ - 0, - false - ], - "valid": true, - "schema_id": "uniqueItems_3_0" - }, - { - "description": "unique heterogeneous types are valid", - "data": [ - {}, - [ - 1 - ], - true, - null, - 1 - ], - "valid": true, - "schema_id": "uniqueItems_3_0" - }, - { - "description": "non-unique heterogeneous types are valid", - "data": [ - {}, - [ - 1 - ], - true, - null, - {}, - 1 - ], - "valid": true, - "schema_id": "uniqueItems_3_0" - } - ] - }, - { - "description": "uniqueItems=false with an array of items", - "database": { - "schemas": [ - { - "prefixItems": [ - { - "type": "boolean" - }, - { - "type": "boolean" - } - ], - "uniqueItems": false, - "extensible": true, - "$id": "uniqueItems_4_0" - } - ] - }, - "tests": [ - { - "description": "[false, true] from items array is valid", - "data": [ - false, - true - ], - "valid": true, - "schema_id": "uniqueItems_4_0" - }, - { - "description": "[true, false] from items array is valid", - "data": [ - true, - false - ], - "valid": true, - "schema_id": "uniqueItems_4_0" - }, - { - "description": "[false, false] from items array is valid", - "data": [ - false, - false - ], - "valid": true, - "schema_id": "uniqueItems_4_0" - }, - { - "description": "[true, true] from items array is valid", - "data": [ - true, - true - ], - "valid": true, - "schema_id": "uniqueItems_4_0" - }, - { - "description": "unique array extended from [false, true] is valid", - "data": [ - false, - true, - "foo", - "bar" - ], - "valid": true, - "schema_id": "uniqueItems_4_0" - }, - { - "description": "unique array extended from [true, false] is valid", - "data": [ - true, - false, - "foo", - "bar" - ], - "valid": true, - "schema_id": "uniqueItems_4_0" - }, - { - "description": "non-unique array extended from [false, true] is valid", - "data": [ - false, - true, - "foo", - "foo" - ], - "valid": true, - "schema_id": "uniqueItems_4_0" - }, - { - "description": "non-unique array extended from [true, false] is valid", - "data": [ - true, - false, - "foo", - "foo" - ], - "valid": true, - "schema_id": "uniqueItems_4_0" - } - ] - }, - { - "description": "uniqueItems=false with an array of items and additionalItems=false", - "database": { - "schemas": [ - { - "prefixItems": [ - { - "type": "boolean" - }, - { - "type": "boolean" - } - ], - "uniqueItems": false, - "items": false, - "$id": "uniqueItems_5_0" - } - ] - }, - "tests": [ - { - "description": "[false, true] from items array is valid", - "data": [ - false, - true - ], - "valid": true, - "schema_id": "uniqueItems_5_0" - }, - { - "description": "[true, false] from items array is valid", - "data": [ - true, - false - ], - "valid": true, - "schema_id": "uniqueItems_5_0" - }, - { - "description": "[false, false] from items array is valid", - "data": [ - false, - false - ], - "valid": true, - "schema_id": "uniqueItems_5_0" - }, - { - "description": "[true, true] from items array is valid", - "data": [ - true, - true - ], - "valid": true, - "schema_id": "uniqueItems_5_0" - }, - { - "description": "extra items are invalid even if unique", - "data": [ - false, - true, - null - ], - "valid": false, - "schema_id": "uniqueItems_5_0" - } - ] - }, - { - "description": "extensible: true allows extra items in uniqueItems", - "database": { - "schemas": [ - { - "uniqueItems": true, - "extensible": true, - "$id": "uniqueItems_6_0" - } - ] - }, - "tests": [ - { - "description": "extra items must be unique", - "data": [ - 1, - 1 - ], - "valid": false, - "schema_id": "uniqueItems_6_0" - }, - { - "description": "extra unique items valid", - "data": [ - 1, - 2 - ], - "valid": true, - "schema_id": "uniqueItems_6_0" - } - ] - } -] \ No newline at end of file