From 55a3c05cbe30fcd004264f27b72d1a1f09c22151 Mon Sep 17 00:00:00 2001 From: Tom Ray Date: Thu, 2 Apr 2026 00:07:49 +0200 Subject: [PATCH] Ajout du validateur json + correctif factory metadata --- CMakeLists.txt | 19 + lib/All/json-schema-validator/.clang-format | 14 + .../.distro/.fmf/version | 1 + .../.distro/json-schema-validator.spec | 61 + .../.distro/plans/import.fmf | 12 + .../.distro/plans/main.fmf.dist-git | 10 + .../.distro/plans/smoke.fmf | 7 + .../tests/import/FetchContent/CMakeLists.txt | 15 + .../tests/import/find_package/CMakeLists.txt | 11 + .../.distro/tests/import/main.fmf | 11 + .../.distro/tests/import/test_FetchContent.sh | 4 + .../.distro/tests/import/test_find_package.sh | 4 + .../.distro/tests/smoke.fmf | 9 + .../.github/workflows/release.yaml | 46 + .../.github/workflows/test.yaml | 94 + lib/All/json-schema-validator/.gitignore | 7 + lib/All/json-schema-validator/.packit.yaml | 68 + .../.pre-commit-config.yaml | 33 + lib/All/json-schema-validator/CMakeLists.txt | 220 +++ .../json-schema-validator/CMakePresets.json | 7 + lib/All/json-schema-validator/ChangeLog.md | 13 + lib/All/json-schema-validator/LICENSE | 22 + lib/All/json-schema-validator/README.md | 366 ++++ .../cmake/CMakePresets-CI.json | 281 +++ .../cmake/CMakePresets-defaults.json | 50 + ...hmann_json_schema_validatorConfig.cmake.in | 9 + lib/All/json-schema-validator/conanfile.py | 93 + .../example/CMakeLists.txt | 10 + .../json-schema-validator/example/format.cpp | 54 + .../json-schema-validator/example/readme.cpp | 100 ++ .../lib/include/nlohmann/json-schema.hpp | 198 +++ .../lib/libnlohmann_json_schema_validator.a | Bin 0 -> 1653322 bytes lib/All/json-schema-validator/schema | 168 ++ .../json-schema-validator/src/CMakeLists.txt | 64 + .../json-schema-validator/src/json-patch.cpp | 115 ++ .../json-schema-validator/src/json-patch.hpp | 41 + .../src/json-schema-draft7.json.cpp | 185 ++ .../json-schema-validator/src/json-uri.cpp | 159 ++ .../src/json-validator.cpp | 1520 +++++++++++++++++ .../src/nlohmann/json-schema.hpp | 198 +++ .../src/smtp-address-validator.cpp | 792 +++++++++ .../src/smtp-address-validator.hpp | 34 + .../src/string-format-check.cpp | 414 +++++ .../json-schema-validator/test/CMakeLists.txt | 98 ++ .../JSON-Schema-Test-Suite/CMakeLists.txt | 70 + .../json-schema-test.cpp | 154 ++ .../remotes/baseUriChange/folderInteger.json | 3 + .../baseUriChangeFolder/folderInteger.json | 3 + .../folderInteger.json | 3 + .../remotes/folder/folderInteger.json | 3 + .../remotes/integer.json | 3 + .../remotes/name-defs.json | 15 + .../JSON-Schema-Test-Suite/remotes/name.json | 15 + .../remotes/ref-and-definitions.json | 11 + .../remotes/ref-and-defs.json | 11 + .../remotes/subSchemas-defs.json | 10 + .../remotes/subSchemas.json | 8 + .../tests/draft7/additionalItems.json | 149 ++ .../tests/draft7/additionalProperties.json | 133 ++ .../tests/draft7/allOf.json | 294 ++++ .../tests/draft7/anyOf.json | 215 +++ .../tests/draft7/boolean_schema.json | 104 ++ .../tests/draft7/const.json | 342 ++++ .../tests/draft7/contains.json | 150 ++ .../tests/draft7/default.json | 79 + .../tests/draft7/definitions.json | 26 + .../tests/draft7/dependencies.json | 248 +++ .../tests/draft7/enum.json | 236 +++ .../tests/draft7/exclusiveMaximum.json | 30 + .../tests/draft7/exclusiveMinimum.json | 30 + .../tests/draft7/format.json | 614 +++++++ .../tests/draft7/id.json | 53 + .../tests/draft7/if-then-else.json | 258 +++ .../tests/draft7/infinite-loop-detection.json | 36 + .../tests/draft7/items.json | 250 +++ .../tests/draft7/maxItems.json | 28 + .../tests/draft7/maxLength.json | 33 + .../tests/draft7/maxProperties.json | 54 + .../tests/draft7/maximum.json | 54 + .../tests/draft7/minItems.json | 28 + .../tests/draft7/minLength.json | 33 + .../tests/draft7/minProperties.json | 38 + .../tests/draft7/minimum.json | 69 + .../tests/draft7/multipleOf.json | 71 + .../tests/draft7/not.json | 117 ++ .../tests/draft7/oneOf.json | 274 +++ .../tests/draft7/optional/bignum.json | 93 + .../tests/draft7/optional/content.json | 77 + .../draft7/optional/ecmascript-regex.json | 292 ++++ .../tests/draft7/optional/float-overflow.json | 13 + .../draft7/optional/format/date-time.json | 73 + .../tests/draft7/optional/format/date.json | 193 +++ .../tests/draft7/optional/format/email.json | 53 + .../draft7/optional/format/hostname.json | 68 + .../draft7/optional/format/idn-email.json | 28 + .../draft7/optional/format/idn-hostname.json | 274 +++ .../tests/draft7/optional/format/ipv4.json | 54 + .../tests/draft7/optional/format/ipv6.json | 163 ++ .../draft7/optional/format/iri-reference.json | 43 + .../tests/draft7/optional/format/iri.json | 53 + .../draft7/optional/format/json-pointer.json | 168 ++ .../tests/draft7/optional/format/regex.json | 18 + .../format/relative-json-pointer.json | 53 + .../tests/draft7/optional/format/time.json | 168 ++ .../draft7/optional/format/uri-reference.json | 43 + .../draft7/optional/format/uri-template.json | 28 + .../tests/draft7/optional/format/uri.json | 108 ++ .../tests/draft7/optional/format/uuid.json | 85 + .../tests/draft7/optional/non-bmp-regex.json | 82 + .../tests/draft7/optional/unicode.json | 146 ++ .../tests/draft7/pattern.json | 59 + .../tests/draft7/patternProperties.json | 156 ++ .../tests/draft7/properties.json | 167 ++ .../tests/draft7/propertyNames.json | 107 ++ .../tests/draft7/ref.json | 612 +++++++ .../tests/draft7/refRemote.json | 196 +++ .../tests/draft7/required.json | 105 ++ .../tests/draft7/type.json | 469 +++++ .../tests/draft7/uniqueItems.json | 384 +++++ .../tests/draft7/unknownKeyword.json | 56 + .../test/binary-validation.cpp | 175 ++ lib/All/json-schema-validator/test/errors.cpp | 130 ++ lib/All/json-schema-validator/test/id-ref.cpp | 146 ++ .../test/issue-100/CMakeLists.txt | 6 + .../test/issue-100/instance.json | 4 + .../test/issue-100/schema.json | 15 + .../test/issue-101/CMakeLists.txt | 6 + .../test/issue-101/instance.json | 1 + .../test/issue-101/schema.json | 12 + .../issue-105-verbose-combination-errors.cpp | 321 ++++ .../test/issue-117-format-error.cpp | 69 + .../test/issue-12/CMakeLists.txt | 3 + .../test/issue-12/instance.json | 3 + .../test/issue-12/schema.json | 10 + .../test/issue-143/CMakeLists.txt | 13 + .../test/issue-143/instance-fail-1.json | 4 + .../test/issue-143/instance-fail-a.json | 4 + .../test/issue-143/instance.json | 4 + .../test/issue-143/schema.json | 21 + .../test/issue-149-entry-selection.cpp | 93 + .../test/issue-189-default-values.cpp | 109 ++ .../test/issue-209/CMakeLists.txt | 3 + .../test/issue-209/color.schema.json | 8 + .../test/issue-209/entities.schema.json | 16 + .../test/issue-209/instance.json | 10 + .../test/issue-229-oneof-default-values.cpp | 69 + .../test/issue-243-root-default-values.cpp | 48 + .../test/issue-25-default-values.cpp | 174 ++ ...ssue-255-error-message-limit-precision.cpp | 41 + .../test/issue-27/CMakeLists.txt | 6 + .../test/issue-27/README | 1 + .../test/issue-27/instance.json | 1 + .../test/issue-27/schema.json | 13 + .../json-schema-validator/test/issue-293.cpp | 32 + .../test/issue-311/CMakeLists.txt | 3 + .../test/issue-311/instance.json | 4 + .../test/issue-311/schema.json | 26 + .../test/issue-48/CMakeLists.txt | 3 + .../test/issue-48/instance.json | 1 + .../test/issue-48/schema.json | 3 + .../test/issue-54/CMakeLists.txt | 3 + .../test/issue-54/instance.json | 1 + .../test/issue-54/schema.json | 4 + .../test/issue-70-root-schema-constructor.cpp | 123 ++ .../json-schema-validator/test/issue-70.cpp | 44 + .../test/issue-75/CMakeLists.txt | 3 + .../test/issue-75/TypeId.json | 10 + .../test/issue-75/instance.json | 1 + .../test/issue-75/schema.json | 6 + .../test/issue-9/CMakeLists.txt | 3 + .../test/issue-9/bar.json | 13 + .../test/issue-9/base.json | 9 + .../test/issue-9/foo/baz/baz.json | 5 + .../test/issue-9/foo/baz/qux/qux.json | 13 + .../test/issue-9/foo/foo.json | 5 + .../test/issue-9/instance.json | 3 + .../test/issue-93/CMakeLists.txt | 7 + .../test/issue-93/blueprints.schema.json | 11 + .../test/issue-93/components.schema.json | 13 + .../test/issue-93/issue-93.cpp | 55 + .../test/issue-93/types/color.schema.json | 4 + .../test/issue-96/CMakeLists.txt | 6 + .../test/issue-96/instance.json | 1 + .../test/issue-96/schema.json | 23 + .../json-schema-validator/test/issue-98.cpp | 16 + .../json-schema-validator/test/json-patch.cpp | 48 + .../test/json-schema-validate.cpp | 100 ++ .../test/string-format-check-test.cpp | 102 ++ .../test/test-pipe-in.sh | 13 + lib/All/json-schema-validator/test/uri.cpp | 106 ++ lib/CMake/Linux/JsonValidatorConfig.cmake | 3 + src/Engine/Core/Kernel/CKernel.cpp | 31 +- src/Engine/Core/Kernel/CKernel.hpp | 68 +- src/Engine/Core/Physics/CTangibleWorld.cpp | 1 + .../Core/Resource/CAbstractResource.cpp | 17 - .../Core/Resource/CAbstractResource.hpp | 25 - .../Model/Material/CAbstractMaterial.cpp | 6 - .../Model/Material/CAbstractMaterial.hpp | 13 - .../Resource/Model/Mesh/CAbstractMesh.cpp | 9 - .../Resource/Model/Mesh/CAbstractMesh.hpp | 13 - src/Engine/Core/Scene/CScene.cpp | 13 - src/Engine/Core/Utils/File/CFileManager.cpp | 62 - src/Engine/Core/Utils/File/CFileManager.hpp | 74 - src/Engine/Utils/Factory/CEntityFactory.cpp | 1 + src/Engine/Utils/Factory/ComponentFactory.cpp | 9 + src/Engine/Utils/Factory/ComponentFactory.hpp | 4 +- 206 files changed, 17070 insertions(+), 320 deletions(-) create mode 100644 lib/All/json-schema-validator/.clang-format create mode 100644 lib/All/json-schema-validator/.distro/.fmf/version create mode 100644 lib/All/json-schema-validator/.distro/json-schema-validator.spec create mode 100644 lib/All/json-schema-validator/.distro/plans/import.fmf create mode 100644 lib/All/json-schema-validator/.distro/plans/main.fmf.dist-git create mode 100644 lib/All/json-schema-validator/.distro/plans/smoke.fmf create mode 100644 lib/All/json-schema-validator/.distro/tests/import/FetchContent/CMakeLists.txt create mode 100644 lib/All/json-schema-validator/.distro/tests/import/find_package/CMakeLists.txt create mode 100644 lib/All/json-schema-validator/.distro/tests/import/main.fmf create mode 100644 lib/All/json-schema-validator/.distro/tests/import/test_FetchContent.sh create mode 100644 lib/All/json-schema-validator/.distro/tests/import/test_find_package.sh create mode 100644 lib/All/json-schema-validator/.distro/tests/smoke.fmf create mode 100644 lib/All/json-schema-validator/.github/workflows/release.yaml create mode 100644 lib/All/json-schema-validator/.github/workflows/test.yaml create mode 100644 lib/All/json-schema-validator/.gitignore create mode 100644 lib/All/json-schema-validator/.packit.yaml create mode 100644 lib/All/json-schema-validator/.pre-commit-config.yaml create mode 100644 lib/All/json-schema-validator/CMakeLists.txt create mode 100644 lib/All/json-schema-validator/CMakePresets.json create mode 100644 lib/All/json-schema-validator/ChangeLog.md create mode 100644 lib/All/json-schema-validator/LICENSE create mode 100644 lib/All/json-schema-validator/README.md create mode 100644 lib/All/json-schema-validator/cmake/CMakePresets-CI.json create mode 100644 lib/All/json-schema-validator/cmake/CMakePresets-defaults.json create mode 100644 lib/All/json-schema-validator/cmake/nlohmann_json_schema_validatorConfig.cmake.in create mode 100644 lib/All/json-schema-validator/conanfile.py create mode 100644 lib/All/json-schema-validator/example/CMakeLists.txt create mode 100644 lib/All/json-schema-validator/example/format.cpp create mode 100644 lib/All/json-schema-validator/example/readme.cpp create mode 100644 lib/All/json-schema-validator/lib/include/nlohmann/json-schema.hpp create mode 100644 lib/All/json-schema-validator/lib/libnlohmann_json_schema_validator.a create mode 100644 lib/All/json-schema-validator/schema create mode 100644 lib/All/json-schema-validator/src/CMakeLists.txt create mode 100644 lib/All/json-schema-validator/src/json-patch.cpp create mode 100644 lib/All/json-schema-validator/src/json-patch.hpp create mode 100644 lib/All/json-schema-validator/src/json-schema-draft7.json.cpp create mode 100644 lib/All/json-schema-validator/src/json-uri.cpp create mode 100644 lib/All/json-schema-validator/src/json-validator.cpp create mode 100644 lib/All/json-schema-validator/src/nlohmann/json-schema.hpp create mode 100644 lib/All/json-schema-validator/src/smtp-address-validator.cpp create mode 100644 lib/All/json-schema-validator/src/smtp-address-validator.hpp create mode 100644 lib/All/json-schema-validator/src/string-format-check.cpp create mode 100644 lib/All/json-schema-validator/test/CMakeLists.txt create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/CMakeLists.txt create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/json-schema-test.cpp create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/baseUriChange/folderInteger.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/baseUriChangeFolder/folderInteger.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/baseUriChangeFolderInSubschema/folderInteger.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/folder/folderInteger.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/integer.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/name-defs.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/name.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/ref-and-definitions.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/ref-and-defs.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/subSchemas-defs.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/subSchemas.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/additionalItems.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/additionalProperties.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/allOf.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/anyOf.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/boolean_schema.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/const.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/contains.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/default.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/definitions.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/dependencies.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/enum.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/exclusiveMaximum.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/exclusiveMinimum.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/format.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/id.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/if-then-else.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/infinite-loop-detection.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/items.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/maxItems.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/maxLength.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/maxProperties.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/maximum.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/minItems.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/minLength.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/minProperties.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/minimum.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/multipleOf.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/not.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/oneOf.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/bignum.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/content.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/ecmascript-regex.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/float-overflow.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/date-time.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/date.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/email.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/hostname.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/idn-email.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/idn-hostname.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/ipv4.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/ipv6.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/iri-reference.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/iri.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/json-pointer.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/regex.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/relative-json-pointer.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/time.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/uri-reference.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/uri-template.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/uri.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/uuid.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/non-bmp-regex.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/unicode.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/pattern.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/patternProperties.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/properties.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/propertyNames.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/ref.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/refRemote.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/required.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/type.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/uniqueItems.json create mode 100644 lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/unknownKeyword.json create mode 100644 lib/All/json-schema-validator/test/binary-validation.cpp create mode 100644 lib/All/json-schema-validator/test/errors.cpp create mode 100644 lib/All/json-schema-validator/test/id-ref.cpp create mode 100644 lib/All/json-schema-validator/test/issue-100/CMakeLists.txt create mode 100644 lib/All/json-schema-validator/test/issue-100/instance.json create mode 100644 lib/All/json-schema-validator/test/issue-100/schema.json create mode 100644 lib/All/json-schema-validator/test/issue-101/CMakeLists.txt create mode 100644 lib/All/json-schema-validator/test/issue-101/instance.json create mode 100644 lib/All/json-schema-validator/test/issue-101/schema.json create mode 100644 lib/All/json-schema-validator/test/issue-105-verbose-combination-errors.cpp create mode 100644 lib/All/json-schema-validator/test/issue-117-format-error.cpp create mode 100644 lib/All/json-schema-validator/test/issue-12/CMakeLists.txt create mode 100644 lib/All/json-schema-validator/test/issue-12/instance.json create mode 100644 lib/All/json-schema-validator/test/issue-12/schema.json create mode 100644 lib/All/json-schema-validator/test/issue-143/CMakeLists.txt create mode 100644 lib/All/json-schema-validator/test/issue-143/instance-fail-1.json create mode 100644 lib/All/json-schema-validator/test/issue-143/instance-fail-a.json create mode 100644 lib/All/json-schema-validator/test/issue-143/instance.json create mode 100644 lib/All/json-schema-validator/test/issue-143/schema.json create mode 100644 lib/All/json-schema-validator/test/issue-149-entry-selection.cpp create mode 100644 lib/All/json-schema-validator/test/issue-189-default-values.cpp create mode 100644 lib/All/json-schema-validator/test/issue-209/CMakeLists.txt create mode 100644 lib/All/json-schema-validator/test/issue-209/color.schema.json create mode 100644 lib/All/json-schema-validator/test/issue-209/entities.schema.json create mode 100644 lib/All/json-schema-validator/test/issue-209/instance.json create mode 100644 lib/All/json-schema-validator/test/issue-229-oneof-default-values.cpp create mode 100644 lib/All/json-schema-validator/test/issue-243-root-default-values.cpp create mode 100644 lib/All/json-schema-validator/test/issue-25-default-values.cpp create mode 100644 lib/All/json-schema-validator/test/issue-255-error-message-limit-precision.cpp create mode 100644 lib/All/json-schema-validator/test/issue-27/CMakeLists.txt create mode 100644 lib/All/json-schema-validator/test/issue-27/README create mode 100644 lib/All/json-schema-validator/test/issue-27/instance.json create mode 100644 lib/All/json-schema-validator/test/issue-27/schema.json create mode 100644 lib/All/json-schema-validator/test/issue-293.cpp create mode 100644 lib/All/json-schema-validator/test/issue-311/CMakeLists.txt create mode 100644 lib/All/json-schema-validator/test/issue-311/instance.json create mode 100644 lib/All/json-schema-validator/test/issue-311/schema.json create mode 100644 lib/All/json-schema-validator/test/issue-48/CMakeLists.txt create mode 100644 lib/All/json-schema-validator/test/issue-48/instance.json create mode 100644 lib/All/json-schema-validator/test/issue-48/schema.json create mode 100644 lib/All/json-schema-validator/test/issue-54/CMakeLists.txt create mode 100644 lib/All/json-schema-validator/test/issue-54/instance.json create mode 100644 lib/All/json-schema-validator/test/issue-54/schema.json create mode 100644 lib/All/json-schema-validator/test/issue-70-root-schema-constructor.cpp create mode 100644 lib/All/json-schema-validator/test/issue-70.cpp create mode 100644 lib/All/json-schema-validator/test/issue-75/CMakeLists.txt create mode 100644 lib/All/json-schema-validator/test/issue-75/TypeId.json create mode 100644 lib/All/json-schema-validator/test/issue-75/instance.json create mode 100644 lib/All/json-schema-validator/test/issue-75/schema.json create mode 100644 lib/All/json-schema-validator/test/issue-9/CMakeLists.txt create mode 100644 lib/All/json-schema-validator/test/issue-9/bar.json create mode 100644 lib/All/json-schema-validator/test/issue-9/base.json create mode 100644 lib/All/json-schema-validator/test/issue-9/foo/baz/baz.json create mode 100644 lib/All/json-schema-validator/test/issue-9/foo/baz/qux/qux.json create mode 100644 lib/All/json-schema-validator/test/issue-9/foo/foo.json create mode 100644 lib/All/json-schema-validator/test/issue-9/instance.json create mode 100644 lib/All/json-schema-validator/test/issue-93/CMakeLists.txt create mode 100644 lib/All/json-schema-validator/test/issue-93/blueprints.schema.json create mode 100644 lib/All/json-schema-validator/test/issue-93/components.schema.json create mode 100644 lib/All/json-schema-validator/test/issue-93/issue-93.cpp create mode 100644 lib/All/json-schema-validator/test/issue-93/types/color.schema.json create mode 100644 lib/All/json-schema-validator/test/issue-96/CMakeLists.txt create mode 100644 lib/All/json-schema-validator/test/issue-96/instance.json create mode 100644 lib/All/json-schema-validator/test/issue-96/schema.json create mode 100644 lib/All/json-schema-validator/test/issue-98.cpp create mode 100644 lib/All/json-schema-validator/test/json-patch.cpp create mode 100644 lib/All/json-schema-validator/test/json-schema-validate.cpp create mode 100644 lib/All/json-schema-validator/test/string-format-check-test.cpp create mode 100755 lib/All/json-schema-validator/test/test-pipe-in.sh create mode 100644 lib/All/json-schema-validator/test/uri.cpp create mode 100644 lib/CMake/Linux/JsonValidatorConfig.cmake delete mode 100644 src/Engine/Core/Resource/CAbstractResource.cpp delete mode 100644 src/Engine/Core/Resource/CAbstractResource.hpp delete mode 100644 src/Engine/Core/Resource/Model/Material/CAbstractMaterial.cpp delete mode 100644 src/Engine/Core/Resource/Model/Material/CAbstractMaterial.hpp delete mode 100644 src/Engine/Core/Resource/Model/Mesh/CAbstractMesh.cpp delete mode 100644 src/Engine/Core/Resource/Model/Mesh/CAbstractMesh.hpp delete mode 100644 src/Engine/Core/Utils/File/CFileManager.cpp delete mode 100644 src/Engine/Core/Utils/File/CFileManager.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ac14ca..52e9e97 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -359,6 +359,23 @@ endif() endif() # --------------------------------------- +# ------- Inclusion de JSON-Schema-Validator -------- +# JSON-Schema-Validator Lib pour valider les fichier JSON, en mode header only. +if(WIN32) + set(JsonValidator_DIR ./lib/CMake/Windows) +else() + set(JsonValidator_DIR ./lib/CMake/Linux) +endif() + +find_package(JsonValidator REQUIRED) + +if(JsonValidator_FOUND) + message("lib JSON_Schema_Validator Trouvé") +else() + message("lib JSON_Schema_Validator Introuvable") +endif() +# --------------------------------------- + endif() @@ -451,6 +468,7 @@ include_directories(${JOLT_INCLUDE_DIRS}) #include_directories(${SNDFILE_INCLUDE_DIRS}) # OPENAL #include_directories(${OPENAL_INCLUDE_DIRS}) +include_directories(${JSONVALIDATOR_INCLUDE_DIRS}) # Fichier lib # OpenGL @@ -484,6 +502,7 @@ target_link_libraries(Engine spirv-reflect) # ASSIMP target_link_libraries(Engine ${ASSIMP_LIBRARIES}) +target_link_libraries(Engine ${JSONVALIDATOR_LIBRARIES}) # ODE #target_link_libraries(Engine ${ODE_LIBRARIES}) diff --git a/lib/All/json-schema-validator/.clang-format b/lib/All/json-schema-validator/.clang-format new file mode 100644 index 0000000..93126fb --- /dev/null +++ b/lib/All/json-schema-validator/.clang-format @@ -0,0 +1,14 @@ +BasedOnStyle: LLVM +#AlignConsecutiveAssignments: true +#AlignConsecutiveDeclarations: true +AllowShortFunctionsOnASingleLine: Inline +BreakBeforeBraces: Linux +ColumnLimit: 0 +ConstructorInitializerAllOnOneLineOrOnePerLine: true +IndentWidth: 4 +IndentPPDirectives: AfterHash +ObjCBlockIndentWidth: 0 +SpaceAfterCStyleCast: true +TabWidth: 4 +AccessModifierOffset: -4 +UseTab: ForIndentation diff --git a/lib/All/json-schema-validator/.distro/.fmf/version b/lib/All/json-schema-validator/.distro/.fmf/version new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/lib/All/json-schema-validator/.distro/.fmf/version @@ -0,0 +1 @@ +1 diff --git a/lib/All/json-schema-validator/.distro/json-schema-validator.spec b/lib/All/json-schema-validator/.distro/json-schema-validator.spec new file mode 100644 index 0000000..9dc56a6 --- /dev/null +++ b/lib/All/json-schema-validator/.distro/json-schema-validator.spec @@ -0,0 +1,61 @@ +Name: json-schema-validator +Summary: JSON schema validator for JSON for Modern C++ +Version: 0.0.0 +Release: %autorelease +License: MIT +URL: https://github.com/pboettch/json-schema-validator + +Source: https://github.com/pboettch/json-schema-validator/archive/refs/tags/v%{version}.tar.gz + +BuildRequires: ninja-build +BuildRequires: cmake +BuildRequires: gcc-c++ +BuildRequires: json-devel + +%description +Json schema validator library for C++ projects using nlohmann/json + +%package devel +Summary: Development files for JSON schema validator +Requires: json-schema-validator%{?_isa} = %{version}-%{release} +Requires: json-devel + +%description devel +Json schema validator development files for C++ projects using nlohmann/json + + +%prep +%autosetup -n json-schema-validator-%{version} + + +%build +%cmake \ + -DJSON_VALIDATOR_SHARED_LIBS=ON \ + -DJSON_VALIDATOR_INSTALL=ON \ + -DJSON_VALIDATOR_BUILD_EXAMPLES=OFF \ + -DJSON_VALIDATOR_BUILD_TESTS=ON + +%cmake_build + + +%install +%cmake_install + + +%check +%ctest + + +%files +%doc README.md +%license LICENSE +%{_libdir}/libnlohmann_json_schema_validator.so.* + +%files devel +%{_libdir}/libnlohmann_json_schema_validator.so +%{_includedir}/nlohmann/json-schema.hpp +%{_libdir}/cmake/nlohmann_json_schema_validator + + +%changelog +%autochangelog diff --git a/lib/All/json-schema-validator/.distro/plans/import.fmf b/lib/All/json-schema-validator/.distro/plans/import.fmf new file mode 100644 index 0000000..e23e798 --- /dev/null +++ b/lib/All/json-schema-validator/.distro/plans/import.fmf @@ -0,0 +1,12 @@ +summary: + Basic importing tests +prepare+: + - name: Include minimum fetching packages + how: install + package: + - git +discover+: + how: fmf + filter: "tag: import" +execute: + how: tmt diff --git a/lib/All/json-schema-validator/.distro/plans/main.fmf.dist-git b/lib/All/json-schema-validator/.distro/plans/main.fmf.dist-git new file mode 100644 index 0000000..62c6a13 --- /dev/null +++ b/lib/All/json-schema-validator/.distro/plans/main.fmf.dist-git @@ -0,0 +1,10 @@ +discover: + how: fmf + path: . + +adjust+: + # Cannot use initiator: fedora-ci reliably yet + when: initiator is not defined or initiator != packit + discover+: + dist-git-source: true + dist-git-extract: json-schema-validator-*/ diff --git a/lib/All/json-schema-validator/.distro/plans/smoke.fmf b/lib/All/json-schema-validator/.distro/plans/smoke.fmf new file mode 100644 index 0000000..0f486b6 --- /dev/null +++ b/lib/All/json-schema-validator/.distro/plans/smoke.fmf @@ -0,0 +1,7 @@ +summary: + Basic smoke tests +discover+: + how: fmf + filter: "tag: smoke" +execute: + how: tmt diff --git a/lib/All/json-schema-validator/.distro/tests/import/FetchContent/CMakeLists.txt b/lib/All/json-schema-validator/.distro/tests/import/FetchContent/CMakeLists.txt new file mode 100644 index 0000000..1d8bf95 --- /dev/null +++ b/lib/All/json-schema-validator/.distro/tests/import/FetchContent/CMakeLists.txt @@ -0,0 +1,15 @@ +# This is a simple project that tests using cmake to load the installed libraries +cmake_minimum_required(VERSION 3.14) + +project(test_fetch_content LANGUAGES CXX) + + +FetchContent_Declare(nlohmann_json_schema_validator + GIT_REPOSITORY https://github.com/pboettch/json-schema-validator + GIT_TAG main + ) +FetchContent_MakeAvailable(nlohmann_json_schema_validator) + +if (NOT TARGET nlohmann_json_schema_validator::validator) + message(FATAL_ERROR "Missing target nlohmann_json_schema_validator::validator") +endif () diff --git a/lib/All/json-schema-validator/.distro/tests/import/find_package/CMakeLists.txt b/lib/All/json-schema-validator/.distro/tests/import/find_package/CMakeLists.txt new file mode 100644 index 0000000..b7f7b19 --- /dev/null +++ b/lib/All/json-schema-validator/.distro/tests/import/find_package/CMakeLists.txt @@ -0,0 +1,11 @@ +# This is a simple project that tests using cmake to load the installed libraries +cmake_minimum_required(VERSION 3.14) + +project(test_find_package LANGUAGES CXX) + +set(CMAKE_FIND_DEBUG_MODE ON) +find_package(nlohmann_json_schema_validator REQUIRED) + +if (NOT TARGET nlohmann_json_schema_validator::validator) + message(FATAL_ERROR "Missing target nlohmann_json_schema_validator::validator") +endif () diff --git a/lib/All/json-schema-validator/.distro/tests/import/main.fmf b/lib/All/json-schema-validator/.distro/tests/import/main.fmf new file mode 100644 index 0000000..f4a88d2 --- /dev/null +++ b/lib/All/json-schema-validator/.distro/tests/import/main.fmf @@ -0,0 +1,11 @@ +# Common test variables +tag: + - import +tier: 0 +path: /tests/import + +# Define tests +/find_package: + test: ./test_find_package.sh +/FetchContent: + test: ./test_FetchContent.sh diff --git a/lib/All/json-schema-validator/.distro/tests/import/test_FetchContent.sh b/lib/All/json-schema-validator/.distro/tests/import/test_FetchContent.sh new file mode 100644 index 0000000..c39c9ac --- /dev/null +++ b/lib/All/json-schema-validator/.distro/tests/import/test_FetchContent.sh @@ -0,0 +1,4 @@ +#!/bin/bash -eux + +tmp_dir=$(mktemp -d) +cmake -S ./FetchContent -B ${tmp_dir} diff --git a/lib/All/json-schema-validator/.distro/tests/import/test_find_package.sh b/lib/All/json-schema-validator/.distro/tests/import/test_find_package.sh new file mode 100644 index 0000000..f717857 --- /dev/null +++ b/lib/All/json-schema-validator/.distro/tests/import/test_find_package.sh @@ -0,0 +1,4 @@ +#!/bin/bash -eux + +tmp_dir=$(mktemp -d) +cmake -S ./find_package -B ${tmp_dir} diff --git a/lib/All/json-schema-validator/.distro/tests/smoke.fmf b/lib/All/json-schema-validator/.distro/tests/smoke.fmf new file mode 100644 index 0000000..713ff90 --- /dev/null +++ b/lib/All/json-schema-validator/.distro/tests/smoke.fmf @@ -0,0 +1,9 @@ +# Common test variables +tag: + - smoke +tier: 0 +path: / + +# Define tests +/version: + test: echo "TODO: Write a minimum working example" diff --git a/lib/All/json-schema-validator/.github/workflows/release.yaml b/lib/All/json-schema-validator/.github/workflows/release.yaml new file mode 100644 index 0000000..89e9a34 --- /dev/null +++ b/lib/All/json-schema-validator/.github/workflows/release.yaml @@ -0,0 +1,46 @@ +name: release +run-name: Release + +on: + push: + tags: + - "v[0-9]+.[0-9]+.[0-9]+" + - "v[0-9]+.[0-9]+.[0-9]+-rc[0-9]+" + +jobs: + tests: + uses: ./.github/workflows/test.yaml + secrets: inherit + + publish-release: + needs: [tests] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + name: "json-schema-validator ${{ github.ref }}" + prerelease: false + draft: false + generate_release_notes: true + + build_conan: + needs: [tests] + runs-on: ubuntu-latest + container: ghcr.io/nlohmann/json-ci:v2.4.0 + steps: + - run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event." + - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub." + - run: echo "🔎 Branch name is ${{ github.ref }} and repository is ${{ github.repository }}." + - name: Clone json-schema-validator + uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: '3.10' + - run: python -m pip install --upgrade conan + - run: conan config init + - run: conan profile update settings.compiler.libcxx=libstdc++11 default + - name: conan create package + run: conan create . diff --git a/lib/All/json-schema-validator/.github/workflows/test.yaml b/lib/All/json-schema-validator/.github/workflows/test.yaml new file mode 100644 index 0000000..892ba21 --- /dev/null +++ b/lib/All/json-schema-validator/.github/workflows/test.yaml @@ -0,0 +1,94 @@ +name: test +run-name: Tests + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + # Make it able to be used in other workflows + workflow_call: + +defaults: + run: + shell: bash + +jobs: + pre-commit: + name: Check pre-commit + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + - uses: pre-commit/action@v3.0.0 + + test: + name: Run ctests + needs: [ pre-commit ] + continue-on-error: ${{ matrix.experimental }} + strategy: + fail-fast: false + matrix: + toolchain: [ gcc, llvm, intel ] + json_version: [ develop, v3.12.0, v3.8.0 ] + experimental: [ false ] + include: + - toolchain: llvm + compiler_version: 15 + - toolchain: gcc + compiler_version: latest + env: + NLOHMANN_JSON_VERSION: ${{ matrix.json_version }} + runs-on: ubuntu-latest + container: ghcr.io/nlohmann/json-ci:v2.4.0 + steps: + - name: Activate Intel compilers + # Not elegant, it will propagate all environment variable. + # Intel does not provide a way to output the environment variables to a file + # Note: PATH needs to be exported to GITHUB_PATH otherwise it can be overwritten + run: | + source /opt/intel/oneapi/setvars.sh + printenv >> $GITHUB_ENV + echo $PATH >> $GITHUB_PATH + if: matrix.toolchain == 'intel' + - name: Setup gcc toolchain + run: | + update-alternatives --install /usr/bin/g++ g++ $(which g++-${{ matrix.compiler_version }}) 999 + if: matrix.compiler_version && matrix.toolchain == 'gcc' + - name: Setup llvm toolchain + run: | + update-alternatives --install /usr/bin/clang++ clang++ $(which clang++-${{ matrix.compiler_version }}) 999 + if: matrix.compiler_version && matrix.toolchain == 'llvm' + - uses: actions/checkout@v3 + # container version is < 3.25 which does not have workflows + - name: Get a working cmake version + uses: lukka/get-cmake@v3.25.2 + - name: Run CMake ${{ matrix.toolchain }}-ci workflow with nlohmann/json version ${{ matrix.json_version }} + uses: lukka/run-cmake@v10.5 + with: + workflowPreset: "${{ matrix.toolchain }}-ci" + coverage: + name: Run coverage tests + needs: [ test ] + runs-on: ubuntu-latest + container: ghcr.io/nlohmann/json-ci:v2.4.0 + if: ${{ github.event_name == 'push' || github.event_name == 'pull_request' }} + steps: + - uses: actions/checkout@v3 + - name: Get latest cmake version + uses: lukka/get-cmake@latest + - name: Get test coverage + uses: lukka/run-cmake@v10.5 + with: + workflowPreset: ci-coverage + - name: Get lcov data + uses: danielealbano/lcov-action@v3 + with: + # Note lcov-action prepends and appends wild-cards *. Account for those + # https://github.com/danielealbano/lcov-action/issues/11 + remove_patterns: /test/,/cmake-build*/ + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3 + with: + files: coverage.info + verbose: true diff --git a/lib/All/json-schema-validator/.gitignore b/lib/All/json-schema-validator/.gitignore new file mode 100644 index 0000000..bc9dd9f --- /dev/null +++ b/lib/All/json-schema-validator/.gitignore @@ -0,0 +1,7 @@ +build*/ +*.sw? +cmake-build-* +venv +env +compile_commands.json +.vs/* diff --git a/lib/All/json-schema-validator/.packit.yaml b/lib/All/json-schema-validator/.packit.yaml new file mode 100644 index 0000000..8ca7fdf --- /dev/null +++ b/lib/All/json-schema-validator/.packit.yaml @@ -0,0 +1,68 @@ +files_to_sync: + - src: .distro/ + dest: ./ + delete: true + filters: + - "protect .git*" + - "protect sources" + - "protect changelog" + - "protect gating.yaml" + # Temporary workaround until + # https://github.com/packit/packit/pull/2573 + - "- json-schema-validator.spec" + - .packit.yaml + +upstream_package_name: json-schema-validator +specfile_path: .distro/json-schema-validator.spec +downstream_package_name: json-schema-validator +update_release: false + +targets: &targets + - fedora-all-x86_64 + # TODO: aarch64 is failing at test + # JSON-Suite::Optional::Format::idn-email + # - fedora-all-aarch64 + +_: + # Job templates + - &build-in-packit + job: copr_build + - &build-in-lecris + <<: *build-in-packit + owner: "@scikit-build" + - &tests + job: tests + fmf_path: .distro + identifier: downstream + +jobs: + # Upstream jobs + - <<: *build-in-lecris + trigger: release + project: release +# - <<: *tests +# trigger: release + - <<: *build-in-lecris + trigger: commit + branch: main + project: nightly +# - <<: *tests +# trigger: commit +# branch: main + - <<: *build-in-packit + trigger: pull_request +# - <<: *tests +# trigger: pull_request + # Downstream jobs + - job: propose_downstream + trigger: release + dist_git_branches: + - fedora-rawhide + - job: koji_build + trigger: commit + dist_git_branches: + - fedora-all + - job: bodhi_update + trigger: commit + dist_git_branches: + - fedora-branched diff --git a/lib/All/json-schema-validator/.pre-commit-config.yaml b/lib/All/json-schema-validator/.pre-commit-config.yaml new file mode 100644 index 0000000..80dc756 --- /dev/null +++ b/lib/All/json-schema-validator/.pre-commit-config.yaml @@ -0,0 +1,33 @@ +repos: + - repo: https://github.com/Takishima/cmake-pre-commit-hooks + rev: v1.9.6 + hooks: + - id: clang-format + args: + - '-i' + - id: clang-tidy + args: + # TODO: Remove when upstream issue is fixed + # https://gitlab.kitware.com/cmake/cmake/-/issues/24827 + # https://github.com/Takishima/cmake-pre-commit-hooks/issues/63 + - '-Bcmake-build-pre-commit' + - '--preset' + - 'pre-commit' + stages: [ manual ] + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - repo: https://github.com/executablebooks/mdformat + rev: 0.7.22 + hooks: + - id: mdformat + additional_dependencies: + - mdformat-gfm + - mdformat-tables + - repo: https://github.com/python-jsonschema/check-jsonschema + rev: 0.34.0 + hooks: + - id: check-github-workflows diff --git a/lib/All/json-schema-validator/CMakeLists.txt b/lib/All/json-schema-validator/CMakeLists.txt new file mode 100644 index 0000000..e9df8a2 --- /dev/null +++ b/lib/All/json-schema-validator/CMakeLists.txt @@ -0,0 +1,220 @@ +cmake_minimum_required(VERSION 3.14) +# CMake version compatibility +# TODO: Remove when bumping cmake >= 3.25 +if (POLICY CMP0140) + # Enables: return(PROPAGATE) + cmake_policy(SET CMP0140 NEW) +endif () + +#[==============================================================================================[ +# Basic project definition # +]==============================================================================================] + +# TODO: CMake >= 3.19 can use string(JSON VERSION GET "${METADATA}" "version") to load from JSON +set(PROJECT_VERSION 2.4.0) + +# TODO: Version 3, rename the project and namespace to something more compact +project(nlohmann_json_schema_validator + VERSION ${PROJECT_VERSION} + DESCRIPTION "Json validator for nlohmann::json library" + HOMEPAGE_URL "https://github.com/pboettch/json-schema-validator" + LANGUAGES CXX) +# TODO: Remove when bumping cmake >= 3.21 +if (NOT DEFINED nlohmann_json_schema_validator_IS_TOP_LEVEL) + if (CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) + set(PROJECT_IS_TOP_LEVEL ON) + else () + set(PROJECT_IS_TOP_LEVEL OFF) + endif () +endif () + +#[==============================================================================================[ +# Options # +]==============================================================================================] + +option(JSON_VALIDATOR_INSTALL "JsonValidator: Install targets" ${PROJECT_IS_TOP_LEVEL}) +option(JSON_VALIDATOR_BUILD_TESTS "JsonValidator: Build tests" ${PROJECT_IS_TOP_LEVEL}) +option(JSON_VALIDATOR_BUILD_EXAMPLES "JsonValidator: Build examples" ${PROJECT_IS_TOP_LEVEL}) +option(JSON_VALIDATOR_SHARED_LIBS "JsonValidator: Build as shared library" ${PROJECT_IS_TOP_LEVEL}) +option(JSON_VALIDATOR_TEST_COVERAGE "JsonValidator: Build with test coverage" OFF) +mark_as_advanced(JSON_VALIDATOR_TEST_COVERAGE) +# Get a default JSON_FETCH_VERSION from environment variables to workaround the CI +if (DEFINED ENV{NLOHMANN_JSON_VERSION}) + set(JSON_FETCH_VERSION_DEFAULT $ENV{NLOHMANN_JSON_VERSION}) +else () + set(JSON_FETCH_VERSION_DEFAULT v3.12.0) +endif () +set(JSON_FETCH_VERSION ${JSON_FETCH_VERSION_DEFAULT} CACHE STRING "Fetch nlohmann::json version") + +#[==============================================================================================[ +# Project configuration # +]==============================================================================================] + +# Include cmake modules +include(FetchContent) +if (JSON_VALIDATOR_INSTALL) + include(GNUInstallDirs) + include(CMakePackageConfigHelpers) +endif () + +# Default to release build +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif () + +# Enable cmake's BUILD_SHARED_LIBS +set(BUILD_SHARED_LIBS ${nlohmann_json_schema_validator_SHARED_LIBS}) + +if (JSON_VALIDATOR_TEST_COVERAGE) + if (CMAKE_CXX_COMPILER_ID STREQUAL Clang) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-instr-generate -fcoverage-mapping") + elseif (CMAKE_CXX_COMPILER_ID STREQUAL GNU) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") + else () + message(WARNING + "JsonValidator: Other toolchain coverage flags unknown.\n" + "Using --coverage as default") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") + endif () +endif () + +#[==============================================================================================[ +# External packages # +]==============================================================================================] + +set(fetch_packages "") +if (NOT TARGET nlohmann_json) + # Fetch/Find nlohmann_json + # TODO: Remove when bumping cmake >= 3.24 + if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.24) + FetchContent_Declare(nlohmann_json + GIT_REPOSITORY https://github.com/nlohmann/json + GIT_TAG ${JSON_FETCH_VERSION} + FIND_PACKAGE_ARGS + ) + list(APPEND fetch_packages nlohmann_json) + else () + # Try to get system installed version + find_package(nlohmann_json QUIET) + if (NOT nlohmann_json_FOUND) + # If failed fetch the desired version + FetchContent_Declare(nlohmann_json + GIT_REPOSITORY https://github.com/nlohmann/json + GIT_TAG ${JSON_FETCH_VERSION} + ) + list(APPEND fetch_packages nlohmann_json) + endif () + endif () +endif () + +# Handle configure flags +if (JSON_VALIDATOR_INSTALL) + # TODO: This is not ideal, this package should not be installing nlohmann::json + # Currently required in order to satisfy cmake exporter + set(JSON_Install ON CACHE BOOL "") +endif () + +# Get all dependencies +FetchContent_MakeAvailable(${fetch_packages}) +if (JSON_VALIDATOR_INSTALL AND NOT nlohmann_json_FOUND AND JSON_Install) + # TODO: This is not ideal + message(WARNING + "JsonValidator: No nlohmann::json found on the system and nlohmann_json_schema_validator will be installed\n" + "This will also install nlohmann::json in its typical installation path\n" + "This is not ideal because it might overwrite system installed") +endif () + +#[==============================================================================================[ +# Main definition # +]==============================================================================================] + +message(STATUS "JsonValidator: Configured for ${CMAKE_BUILD_TYPE}") +if (DEFINED nlohmann_json_VERSION) + message(STATUS "JsonValidator: Using nlohmann/json version: ${nlohmann_json_VERSION}") +else () + message(STATUS "JsonValidator: nlohmann_json_VERSION is not set. Possible value: ${JSON_FETCH_VERSION}") +endif () + +## Main targets +add_library(nlohmann_json_schema_validator) +add_library(nlohmann_json_schema_validator::validator ALIAS nlohmann_json_schema_validator) +set_target_properties(nlohmann_json_schema_validator PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} + EXPORT_NAME validator + # TODO: Version 3, simplify the library name +# OUTPUT_NAME nlohmann_json_validator + ) + +# Main definitions in here +add_subdirectory(src) + +# Enable examples + +# Enable testings +if (JSON_VALIDATOR_BUILD_TESTS) + enable_testing() + add_subdirectory(test) +endif () + +if (JSON_VALIDATOR_BUILD_EXAMPLES) + add_subdirectory(example) +endif () + + +#[==============================================================================================[ +# Install or Export # +]==============================================================================================] + +if (JSON_VALIDATOR_INSTALL) + # Note other install targets found in subdirectories + # Here mostly the cmake boilerplate are set + write_basic_package_version_file(nlohmann_json_schema_validatorConfigVersion.cmake + VERSION ${PROJECT_VERSION} + COMPATIBILITY SameMajorVersion + ) + configure_package_config_file(cmake/nlohmann_json_schema_validatorConfig.cmake.in + nlohmann_json_schema_validatorConfig.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/nlohmann_json_schema_validator + ) + + # Install Targets files + export(EXPORT nlohmann_json_schema_validatorTargets + NAMESPACE nlohmann_json_schema_validator:: + FILE nlohmann_json_schema_validatorTargets.cmake + ) + install(EXPORT nlohmann_json_schema_validatorTargets + FILE nlohmann_json_schema_validatorTargets.cmake + NAMESPACE nlohmann_json_schema_validator:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/nlohmann_json_schema_validator + COMPONENT nlohmann_json_schema_validator_Development + ) + # Install cmake export files + install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/nlohmann_json_schema_validatorConfig.cmake + ${CMAKE_CURRENT_BINARY_DIR}/nlohmann_json_schema_validatorConfigVersion.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/nlohmann_json_schema_validator + COMPONENT nlohmann_json_schema_validator_Development + ) +endif () + +# Handle the project being included externally (e.g. FetchContent) +if (NOT PROJECT_IS_TOP_LEVEL) + # Export variables set in nlohmann_json_schema_validatorConfig.cmake + # TODO: Remove when bumping cmake >= 3.25 + if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.25) + return(PROPAGATE + nlohmann_json_schema_validator_VERSION + nlohmann_json_schema_validator_VERSION_MAJOR + nlohmann_json_schema_validator_VERSION_MINOR + nlohmann_json_schema_validator_VERSION_PATCH + nlohmann_json_schema_validator_VERSION_TWEAK + ) + else () + set(nlohmann_json_schema_validator_VERSION ${nlohmann_json_schema_validator_VERSION} PARENT_SCOPE) + set(nlohmann_json_schema_validator_VERSION_MAJOR ${nlohmann_json_schema_validator_VERSION_MAJOR} PARENT_SCOPE) + set(nlohmann_json_schema_validator_VERSION_MINOR ${nlohmann_json_schema_validator_VERSION_MINOR} PARENT_SCOPE) + set(nlohmann_json_schema_validator_VERSION_PATCH ${nlohmann_json_schema_validator_VERSION_PATCH} PARENT_SCOPE) + set(nlohmann_json_schema_validator_VERSION_TWEAK ${nlohmann_json_schema_validator_VERSION_TWEAK} PARENT_SCOPE) + endif () +endif () diff --git a/lib/All/json-schema-validator/CMakePresets.json b/lib/All/json-schema-validator/CMakePresets.json new file mode 100644 index 0000000..51696d4 --- /dev/null +++ b/lib/All/json-schema-validator/CMakePresets.json @@ -0,0 +1,7 @@ +{ + "version": 6, + "include": [ + "cmake/CMakePresets-defaults.json", + "cmake/CMakePresets-CI.json" + ] +} diff --git a/lib/All/json-schema-validator/ChangeLog.md b/lib/All/json-schema-validator/ChangeLog.md new file mode 100644 index 0000000..0acd8a0 --- /dev/null +++ b/lib/All/json-schema-validator/ChangeLog.md @@ -0,0 +1,13 @@ +## Release 2.4.0 + +- Added CI job to publish GitHub release by @JohanMabille in +- Maintenance to Fedora CI infrastructure by @LecrisUT and @JohanMabille in +- Reference validation using contains() result rather than exception handling by @BalrogOfHell in +- add support for $defs instead of definitions by rpatters1 in +- Apply clang-format / fix "test / Check pre-commit" failures by @serge-s in +- Adding verbose error messages for logical combinations by Csaba Imre Zempleni in +- fix: issue-311 by andrejlevkovitch +- Fix cmake install target on windows by @barts-of in +- error-messages: Numeric limit errors should show maximum precision by @pboettch +- Add Fedora packaging by @LecrisUT in +- Improve and fix bugs in Conanfile by Jacob Crabill diff --git a/lib/All/json-schema-validator/LICENSE b/lib/All/json-schema-validator/LICENSE new file mode 100644 index 0000000..f660b34 --- /dev/null +++ b/lib/All/json-schema-validator/LICENSE @@ -0,0 +1,22 @@ +Modern C++ JSON schema validator is licensed under the MIT License +: + +Copyright (c) 2016 Patrick Boettcher + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/lib/All/json-schema-validator/README.md b/lib/All/json-schema-validator/README.md new file mode 100644 index 0000000..93751e7 --- /dev/null +++ b/lib/All/json-schema-validator/README.md @@ -0,0 +1,366 @@ +[![Build Status](https://travis-ci.org/pboettch/json-schema-validator.svg?branch=master)](https://travis-ci.org/pboettch/json-schema-validator) + +# JSON schema validator for JSON for Modern C++ + +# What is it? + +This is a C++ library for validating JSON documents based on a +[JSON Schema](http://json-schema.org/) which itself should validate with +[draft-7 of JSON Schema Validation](http://json-schema.org/schema). + +First a disclaimer: *It is work in progress and +contributions or hints or discussions are welcome.* + +Niels Lohmann et al develop a great JSON parser for C++ called [JSON for Modern +C++](https://github.com/nlohmann/json). This validator is based on this +library, hence the name. + +External documentation is missing as well. However the API of the validator +is rather simple. + +# New in version 2 + +Although significant changes have been done for the 2nd version +(a complete rewrite) the API is compatible with the 1.0.0 release. Except for +the namespace which is now `nlohmann::json_schema`. + +Version **2** supports JSON schema draft 7, whereas 1 was supporting draft 4 +only. Please update your schemas. + +The primary change in 2 is the way a schema is used. While in version 1 the schema was +kept as a JSON-document and used again and again during validation, in version 2 the schema +is parsed into compiled C++ objects which are then used during validation. There are surely +still optimizations to be done, but validation speed has improved by factor 100 +or more. + +# Design goals + +The main goal of this validator is to produce *human-comprehensible* error +messages if a JSON-document/instance does not comply to its schema. + +By default this is done with exceptions thrown at the users with a helpful +message telling what's wrong with the document while validating. + +Starting with **2.0.0** the user can pass a `json_schema::basic_error_handler`-derived +object along with the instance to validate to receive a callback each time +a validation error occurs and decide what to do (throwing, counting, collecting). + +Another goal was to use Niels Lohmann's JSON-library. This is why the validator +lives in his namespace. + +# Thread-safety + +Instance validation is thread-safe and the same validator-object can be used by +different threads: + +The validate method is `const` which indicates the object is not modified when +being called: + +```C++ + json json_validator::validate(const json &) const; +``` + +Validator-object creation however is not thread-safe. A validator has to be +created in one (main?) thread once. + +# Weaknesses + +Numerical validation uses nlohmann-json's integer, unsigned and floating point +types, depending on if the schema type is "integer" or "number". Bignum +(i.e. arbitrary precision and range) is not supported at this time. + +# Building + +This library is based on Niels Lohmann's JSON-library and thus has +a build-dependency to it. + +Currently at least version **3.8.0** of NLohmann's JSON library +is required. + +Various methods using CMake can be used to build this project. + +## Build out-of-source + +Do not run cmake inside the source-dir. Rather create a dedicated build-dir: + +```Bash +git clone https://github.com/pboettch/json-schema-validator.git +cd json-schema-validator +mkdir build +cd build +cmake [..] +make +make install # if needed +ctest # run unit, non-regression and test-suite tests +``` + +## Building as shared library + +By default a static library is built. Shared libraries can be generated by using +the `BUILD_SHARED_LIBS`-cmake variable: + +In your initial call to cmake simply add: + +```bash +cmake [..] -DBUILD_SHARED_LIBS=ON [..] +``` + +## nlohmann-json integration + +As nlohmann-json is a dependency, this library tries find it. + +The cmake-configuration first checks if nlohmann-json is available as a cmake-target. This may be the case, because it is used as a submodule in a super-project which already provides and uses nlohmann-json. +Otherwise, it calls `find_package` for nlohmann-json and requires nlohmann-json to be installed on the system. + +### Building with Hunter package manager + +To enable access to nlohmann json library, Hunter can be used. Just run with `JSON_VALIDATOR_HUNTER=ON` option. No further dependencies needed + +```bash +cmake [..] -DJSON_VALIDATOR_HUNTER=ON [..] +``` + +### Building as a CMake-subdirectory from within another project + +Adding this library as a subdirectory to a parent project is one way of +building it. + +If the parent project already used `find_package()` to find the CMake-package of nlohmann_json or includes it as a submodule likewise. + +### Building directly, finding a CMake-package. (short) + +When nlohmann-json has been installed, it provides files which allows +CMake's `find_package()` to be used. + +This library is using this mechanism if `nlohmann_json::nlohmann_json`-target +does not exist. + +### Install + +Since version 2.1.0 this library can be installed and CMake-package-files will be +created accordingly. If the installation of nlohmann-json and this library +is done into default unix-system-paths CMake will be able to find this +library by simply doing: + +```CMake +find_package(nlohmann_json_schema_validator REQUIRED) +``` + +and + +```CMake +target_link_libraries( [..] nlohmann_json_schema_validator) +``` + +to build and link. + +## Code + +See also `app/json-schema-validate.cpp`. + +```C++ +#include +#include + +#include + +using nlohmann::json; +using nlohmann::json_schema::json_validator; + +// The schema is defined based upon a string literal +static json person_schema = R"( +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "A person", + "properties": { + "name": { + "description": "Name", + "type": "string" + }, + "age": { + "description": "Age of the person", + "type": "number", + "minimum": 2, + "maximum": 200 + } + }, + "required": [ + "name", + "age" + ], + "type": "object" +} + +)"_json; + +// The people are defined with brace initialization +static json bad_person = {{"age", 42}}; +static json good_person = {{"name", "Albert"}, {"age", 42}}; + +int main() +{ + /* json-parse the schema */ + + json_validator validator; // create validator + + try { + validator.set_root_schema(person_schema); // insert root-schema + } catch (const std::exception &e) { + std::cerr << "Validation of schema failed, here is why: " << e.what() << "\n"; + return EXIT_FAILURE; + } + + /* json-parse the people - API of 1.0.0, default throwing error handler */ + + for (auto &person : {bad_person, good_person}) { + std::cout << "About to validate this person:\n" + << std::setw(2) << person << std::endl; + try { + validator.validate(person); // validate the document - uses the default throwing error-handler + std::cout << "Validation succeeded\n"; + } catch (const std::exception &e) { + std::cerr << "Validation failed, here is why: " << e.what() << "\n"; + } + } + + /* json-parse the people - with custom error handler */ + class custom_error_handler : public nlohmann::json_schema::basic_error_handler + { + void error(const nlohmann::json_pointer> &pointer, const json &instance, + const std::string &message) override + { + nlohmann::json_schema::basic_error_handler::error(pointer, instance, message); + std::cerr << "ERROR: '" << pointer << "' - '" << instance << "': " << message << "\n"; + } + }; + + + for (auto &person : {bad_person, good_person}) { + std::cout << "About to validate this person:\n" + << std::setw(2) << person << std::endl; + + custom_error_handler err; + validator.validate(person, err); // validate the document + + if (err) + std::cerr << "Validation failed\n"; + else + std::cout << "Validation succeeded\n"; + } + + return EXIT_SUCCESS; +} +``` + +# Compliance + +There is an application which can be used for testing the validator with the +[JSON-Schema-Test-Suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite). +In order to simplify the testing, the test-suite is included in the repository. + +If you have cloned this repository providing a path the repository-root via the +cmake-variable `JSON_SCHEMA_TEST_SUITE_PATH` will enable the test-target(s). + +All required tests are **OK**. + +# Format + +Optionally JSON-schema-validator can validate predefined or user-defined formats. +Therefore a format-checker-function can be provided by the user which is called by +the validator when a format-check is required (ie. the schema contains a format-field). + +This is how the prototype looks like and how it can be passed to the validation-instance: + +```C++ +static void my_format_checker(const std::string &format, const std::string &value) +{ + if (format == "something") { + if (!check_value_for_something(value)) + throw std::invalid_argument("value is not a good something"); + } else + throw std::logic_error("Don't know how to validate " + format); +} + +// when creating the validator + +json_validator validator(nullptr, // or loader-callback + my_format_checker); // create validator +``` + +## Default Checker + +The library contains a default-checker, which does some checks. It needs to be +provided manually to the constructor of the validator: + +```C++ +json_validator validator(loader, // or nullptr for no loader + nlohmann::json_schema::default_string_format_check); +``` + +Supported formats: `date-time, date, time, email, hostname, ipv4, ipv6, uuid, regex` + +More formats can be added in `src/string-format-check.cpp`. Please contribute implementions for missing json schema draft formats. + +## Default value processing + +As a result of the validation, the library returns a json patch including the default values of the specified schema. + +```C++ +#include +#include + +using nlohmann::json; +using nlohmann::json_schema::json_validator; + +static const json rectangle_schema = R"( +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "A rectangle", + "properties": { + "width": { + "$ref": "#/definitions/length", + "default": 20 + }, + "height": { + "$ref": "#/definitions/length" + } + }, + "definitions": { + "length": { + "type": "integer", + "minimum": 1, + "default": 10 + } + } +})"_json; + +int main() +{ + try { + json_validator validator{rectangle_schema}; + /* validate empty json -> will be expanded by the default values defined in the schema */ + json rectangle = "{}"_json; + const auto default_patch = validator.validate(rectangle); + rectangle = rectangle.patch(default_patch); + std::cout << rectangle.dump() << std::endl; // {"height":10,"width":20} + } catch (const std::exception &e) { + std::cerr << "Validation of schema failed: " << e.what() << "\n"; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} +``` + +The example above will output the specified default values `{"height":10,"width":20}` to stdout. + +> Note that the default value specified in a `$ref` may be overridden by the current instance location. Also note that this behavior will break draft-7, but it is compliant to newer drafts (e.g. `2019-09` or `2020-12`). + +# Contributing + +This project uses [`pre-commit`](https://pre-commit.com/) to enforce style-checks. Please install and run it before +creating commits and making pull requests. + +```console +$ pip install pre-commit +$ pre-commit install +``` diff --git a/lib/All/json-schema-validator/cmake/CMakePresets-CI.json b/lib/All/json-schema-validator/cmake/CMakePresets-CI.json new file mode 100644 index 0000000..8173d22 --- /dev/null +++ b/lib/All/json-schema-validator/cmake/CMakePresets-CI.json @@ -0,0 +1,281 @@ +{ + "version": 6, + "include": [ + "CMakePresets-defaults.json" + ], + "configurePresets": [ + { + "name": "ci-base", + "hidden": true, + "generator": "Ninja", + "inherits": [ + "default" + ], + "cacheVariables": { + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Debug" + }, + "JSON_VALIDATOR_BUILD_TESTS": { + "type": "BOOL", + "value": true + }, + "JSON_VALIDATOR_INSTALL": { + "type": "BOOL", + "value": false + }, + "JSON_BuildTests": { + "type": "BOOL", + "value": false + } + }, + "errors": { + "deprecated": true + } + }, + { + "name": "gcc-ci", + "displayName": "Configure preset for GCC toolchain", + "inherits": [ + "ci-base" + ], + "binaryDir": "cmake-build-ci-gcc", + "cacheVariables": { + "CMAKE_CXX_COMPILER": { + "type": "FILEPATH", + "value": "g++" + }, + "CMAKE_LINKER": { + "type": "FILEPATH", + "value": "ld" + } + } + }, + { + "name": "intel-ci", + "displayName": "Configure preset for Intel toolchain", + "inherits": [ + "ci-base" + ], + "binaryDir": "cmake-build-ci-intel", + "cacheVariables": { + "CMAKE_CXX_COMPILER": { + "type": "FILEPATH", + "value": "icpx" + } + } + }, + { + "name": "llvm-ci", + "displayName": "Configure preset for LLVM toolchain", + "inherits": [ + "ci-base" + ], + "binaryDir": "cmake-build-ci-llvm", + "cacheVariables": { + "CMAKE_CXX_COMPILER": { + "type": "FILEPATH", + "value": "clang++" + }, + "CMAKE_LINKER": { + "type": "FILEPATH", + "value": "lld" + } + } + }, + { + "name": "ci-coverage", + "displayName": "Configure preset for test coverage", + "inherits": [ + "gcc-ci" + ], + "binaryDir": "cmake-build-ci-coverage", + "errors": { + "deprecated": false + }, + "cacheVariables": { + "JSON_VALIDATOR_TEST_COVERAGE": { + "type": "BOOL", + "value": true + } + } + }, + { + "name": "pre-commit", + "displayName": "Configure preset for pre-commit checks", + "inherits": [ + "default" + ], + "binaryDir": "cmake-build-pre-commit", + "cacheVariables": { + "JSON_VALIDATOR_TEST_COVERAGE": { + "type": "BOOL", + "value": true + }, + "JSON_VALIDATOR_INSTALL": { + "type": "BOOL", + "value": false + } + } + } + ], + "buildPresets": [ + { + "name": "ci-base", + "hidden": true, + "inherits": [ + "default" + ], + "cleanFirst": true + }, + { + "name": "ci-coverage", + "displayName": "Build preset for test coverage", + "inherits": [ + "ci-base" + ], + "configurePreset": "ci-coverage" + }, + { + "name": "gcc-ci", + "displayName": "Build preset for GCC toolchain", + "inherits": [ + "ci-base" + ], + "configurePreset": "gcc-ci" + }, + { + "name": "intel-ci", + "displayName": "Build preset for Intel toolchain", + "inherits": [ + "ci-base" + ], + "configurePreset": "intel-ci" + }, + { + "name": "llvm-ci", + "displayName": "Build preset for LLVM toolchain", + "inherits": [ + "ci-base" + ], + "configurePreset": "llvm-ci" + } + ], + "testPresets": [ + { + "name": "ci-base", + "hidden": true, + "inherits": [ + "default" + ], + "output": { + "outputOnFailure": true + } + }, + { + "name": "ci-coverage", + "inherits": [ + "default" + ], + "configurePreset": "ci-coverage" + }, + { + "name": "gcc-ci", + "displayName": "Test preset for GCC toolchain", + "inherits": [ + "ci-base" + ], + "configurePreset": "gcc-ci" + }, + { + "name": "intel-ci", + "displayName": "Test preset for Intel toolchain", + "inherits": [ + "ci-base" + ], + "configurePreset": "intel-ci" + }, + { + "name": "llvm-ci", + "displayName": "Test preset for LLVM toolchain", + "inherits": [ + "ci-base" + ], + "configurePreset": "llvm-ci" + } + ], + "workflowPresets": [ + { + "name": "gcc-ci", + "displayName": "CI test for GCC toolchain", + "steps": [ + { + "type": "configure", + "name": "gcc-ci" + }, + { + "type": "build", + "name": "gcc-ci" + }, + { + "type": "test", + "name": "gcc-ci" + } + ] + }, + { + "name": "intel-ci", + "displayName": "CI test for Intel toolchain", + "steps": [ + { + "type": "configure", + "name": "intel-ci" + }, + { + "type": "build", + "name": "intel-ci" + }, + { + "type": "test", + "name": "intel-ci" + } + ] + }, + { + "name": "llvm-ci", + "displayName": "CI test for LLVM toolchain", + "steps": [ + { + "type": "configure", + "name": "llvm-ci" + }, + { + "type": "build", + "name": "llvm-ci" + }, + { + "type": "test", + "name": "llvm-ci" + } + ] + }, + { + "name": "ci-coverage", + "displayName": "Coverage tests", + "steps": [ + { + "type": "configure", + "name": "ci-coverage" + }, + { + "type": "build", + "name": "ci-coverage" + }, + { + "type": "test", + "name": "ci-coverage" + } + ] + } + ] +} diff --git a/lib/All/json-schema-validator/cmake/CMakePresets-defaults.json b/lib/All/json-schema-validator/cmake/CMakePresets-defaults.json new file mode 100644 index 0000000..bfc642c --- /dev/null +++ b/lib/All/json-schema-validator/cmake/CMakePresets-defaults.json @@ -0,0 +1,50 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "default", + "displayName": "Default configuration preset", + "binaryDir": "cmake-build-release", + "cacheVariables": { + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Release" + } + } + } + ], + "buildPresets": [ + { + "name": "default", + "displayName": "Default build preset", + "configurePreset": "default" + } + ], + "testPresets": [ + { + "name": "default", + "displayName": "Default test preset", + "configurePreset": "default" + } + ], + "workflowPresets": [ + { + "name": "default", + "displayName": "Default workflow", + "steps": [ + { + "type": "configure", + "name": "default" + }, + { + "type": "build", + "name": "default" + }, + { + "type": "test", + "name": "default" + } + ] + } + ] +} diff --git a/lib/All/json-schema-validator/cmake/nlohmann_json_schema_validatorConfig.cmake.in b/lib/All/json-schema-validator/cmake/nlohmann_json_schema_validatorConfig.cmake.in new file mode 100644 index 0000000..88960cc --- /dev/null +++ b/lib/All/json-schema-validator/cmake/nlohmann_json_schema_validatorConfig.cmake.in @@ -0,0 +1,9 @@ +@PACKAGE_INIT@ + +include(CMakeFindDependencyMacro) +find_dependency(nlohmann_json) + +include("${CMAKE_CURRENT_LIST_DIR}/nlohmann_json_schema_validatorTargets.cmake") +check_required_components( + "nlohmann_json_schema_validator" + ) diff --git a/lib/All/json-schema-validator/conanfile.py b/lib/All/json-schema-validator/conanfile.py new file mode 100644 index 0000000..fb6c85e --- /dev/null +++ b/lib/All/json-schema-validator/conanfile.py @@ -0,0 +1,93 @@ +import os +import re + +from conan import ConanFile +from conan.tools.cmake import cmake_layout, CMake, CMakeToolchain +from conans.tools import load +from conans import tools as ctools + +def get_version(): + try: + version = os.getenv('PROJECT_VERSION', None) + if version: + return version + + content = load('CMakeLists.txt') + version = re.search('set\(PROJECT_VERSION (.*)\)', content).group(1) + return version.strip() + except: + return None + +class JsonSchemaValidatorConan(ConanFile): + name = 'JsonSchemaValidator' + version = get_version() + url = 'https://github.com/pboettch/json-schema-validator' + license = 'MIT' + + settings = 'os', 'compiler', 'build_type', 'arch' + + options = { + 'shared': [True, False], + 'fPIC': [True, False], + 'build_examples': [True, False], + 'build_tests': [True, False], + 'test_coverage': [True, False], + } + + default_options = { + 'shared': False, + 'fPIC': True, + 'build_examples': True, + 'build_tests': False, + 'test_coverage': False, + } + + generators = 'CMakeDeps', 'CMakeToolchain', 'VirtualBuildEnv', 'VirtualRunEnv' + + exports_sources = [ + 'CMakeLists.txt', + 'conanfile.py', + 'cmake/*', + 'src/*', + 'example/*', + 'test/*', + ] + + requires = [ + 'nlohmann_json/3.11.2' + ] + + def generate(self): + tc = CMakeToolchain(self) + tc.variables['JSON_VALIDATOR_BUILD_EXAMPLES'] = self.options.build_examples + tc.variables['JSON_VALIDATOR_BUILD_TESTS'] = self.options.build_tests + tc.variables['JSON_VALIDATOR_SHARED_LIBS '] = self.options.shared + tc.variables['JSON_VALIDATOR_TEST_COVERAGE '] = self.options.test_coverage + tc.generate() + + def layout(self): + cmake_layout(self) + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.verbose = True + cmake.build() + + def package(self): + cmake = CMake(self) + cmake.install() + + def package_info(self): + includedir = os.path.join(self.package_folder, "include") + self.cpp_info.includedirs = [includedir] + + libdir = os.path.join(self.package_folder, "lib") + self.cpp_info.libdirs = [libdir] + self.cpp_info.libs += ctools.collect_libs(self, libdir) + + bindir = os.path.join(self.package_folder, "bin") + self.output.info("Appending PATH environment variable: {}".format(bindir)) + self.env_info.PATH.append(bindir) + + self.user_info.VERSION = self.version diff --git a/lib/All/json-schema-validator/example/CMakeLists.txt b/lib/All/json-schema-validator/example/CMakeLists.txt new file mode 100644 index 0000000..6daf9ee --- /dev/null +++ b/lib/All/json-schema-validator/example/CMakeLists.txt @@ -0,0 +1,10 @@ +add_executable(readme-json-schema readme.cpp) +target_link_libraries(readme-json-schema nlohmann_json_schema_validator) + +add_executable(format-json-schema format.cpp) +target_link_libraries(format-json-schema nlohmann_json_schema_validator) + +if (JSON_VALIDATOR_INSTALL) + install(TARGETS readme-json-schema format-json-schema + DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif () diff --git a/lib/All/json-schema-validator/example/format.cpp b/lib/All/json-schema-validator/example/format.cpp new file mode 100644 index 0000000..40e6445 --- /dev/null +++ b/lib/All/json-schema-validator/example/format.cpp @@ -0,0 +1,54 @@ +#include + +#include + +using nlohmann::json; +using nlohmann::json_schema::json_validator; + +// The schema is defined based upon a string literal +static json uri_schema = R"( +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "myUri": { + "type":"string", + "format": "uri" + } + } +})"_json; + +// The people are defined with brace initialization +static json good_uri = {{"myUri", "http://hostname.com/"}}; +static json bad_uri = {{"myUri", "http:/hostname.com/"}}; + +static void uri_format_checker(const std::string &format, const std::string &value) +{ + if (format == "uri") { + if (value.find("://") == std::string::npos) + throw std::invalid_argument("URI does not contain :// - invalid"); + } else + throw std::logic_error("Don't know how to validate " + format); +} + +int main() +{ + json_validator validator(nullptr, uri_format_checker); // create validator + + try { + validator.set_root_schema(uri_schema); // insert root-schema + } catch (const std::exception &e) { + std::cerr << "Validation of schema failed, here is why: " << e.what() << "\n"; + return EXIT_FAILURE; + } + + validator.validate(good_uri); + + try { + validator.validate(bad_uri); + } catch (const std::exception &e) { + std::cerr << "Validation expectedly failed, here is why: " << e.what() << "\n"; + } + + return EXIT_SUCCESS; +} diff --git a/lib/All/json-schema-validator/example/readme.cpp b/lib/All/json-schema-validator/example/readme.cpp new file mode 100644 index 0000000..45f4d35 --- /dev/null +++ b/lib/All/json-schema-validator/example/readme.cpp @@ -0,0 +1,100 @@ +#include +#include + +#include + +using nlohmann::json; +using nlohmann::json_schema::json_validator; + +// The schema is defined based upon a string literal +static json person_schema = R"( +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "A person", + "properties": { + "name": { + "description": "Name", + "type": "string" + }, + "age": { + "description": "Age of the person", + "type": "number", + "minimum": 2, + "maximum": 200 + }, + "address":{ + "type": "object", + "properties":{ + "street":{ + "type": "string", + "default": "Abbey Road" + } + } + } + }, + "required": [ + "name", + "age" + ], + "type": "object" +} + +)"_json; + +// The people are defined with brace initialization +static json bad_person = {{"age", 42}}; +static json good_person = {{"name", "Albert"}, {"age", 42}, {"address", {{"street", "Main Street"}}}}; +static json good_defaulted_person = {{"name", "Knut"}, {"age", 69}, {"address", {}}}; + +int main() +{ + /* json-parse the schema */ + + json_validator validator; // create validator + + try { + validator.set_root_schema(person_schema); // insert root-schema + } catch (const std::exception &e) { + std::cerr << "Validation of schema failed, here is why: " << e.what() << "\n"; + return EXIT_FAILURE; + } + + /* json-parse the people - API of 1.0.0, default throwing error handler */ + + for (auto &person : {bad_person, good_person, good_defaulted_person}) { + std::cout << "About to validate this person:\n" + << std::setw(2) << person << std::endl; + try { + auto defaultPatch = validator.validate(person); // validate the document - uses the default throwing error-handler + std::cout << "Validation succeeded\n"; + std::cout << "Patch with defaults: " << defaultPatch.dump(2) << std::endl; + } catch (const std::exception &e) { + std::cerr << "Validation failed, here is why: " << e.what() << "\n"; + } + } + + /* json-parse the people - with custom error handler */ + class custom_error_handler : public nlohmann::json_schema::basic_error_handler + { + void error(const nlohmann::json::json_pointer &ptr, const json &instance, const std::string &message) override + { + nlohmann::json_schema::basic_error_handler::error(ptr, instance, message); + std::cerr << "ERROR: '" << ptr << "' - '" << instance << "': " << message << "\n"; + } + }; + + for (auto &person : {bad_person, good_person}) { + std::cout << "About to validate this person:\n" + << std::setw(2) << person << std::endl; + + custom_error_handler err; + validator.validate(person, err); // validate the document + + if (err) + std::cerr << "Validation failed\n"; + else + std::cout << "Validation succeeded\n"; + } + + return EXIT_SUCCESS; +} diff --git a/lib/All/json-schema-validator/lib/include/nlohmann/json-schema.hpp b/lib/All/json-schema-validator/lib/include/nlohmann/json-schema.hpp new file mode 100644 index 0000000..07befd3 --- /dev/null +++ b/lib/All/json-schema-validator/lib/include/nlohmann/json-schema.hpp @@ -0,0 +1,198 @@ +/* + * JSON schema validator for JSON for modern C++ + * + * Copyright (c) 2016-2019 Patrick Boettcher . + * + * SPDX-License-Identifier: MIT + * + */ +#ifndef NLOHMANN_JSON_SCHEMA_HPP__ +#define NLOHMANN_JSON_SCHEMA_HPP__ + +#ifdef _WIN32 +# if defined(JSON_SCHEMA_VALIDATOR_EXPORTS) +# define JSON_SCHEMA_VALIDATOR_API __declspec(dllexport) +# elif defined(JSON_SCHEMA_VALIDATOR_IMPORTS) +# define JSON_SCHEMA_VALIDATOR_API __declspec(dllimport) +# else +# define JSON_SCHEMA_VALIDATOR_API +# endif +#else +# define JSON_SCHEMA_VALIDATOR_API +#endif + +#include + +#ifdef NLOHMANN_JSON_VERSION_MAJOR +# if (NLOHMANN_JSON_VERSION_MAJOR * 10000 + NLOHMANN_JSON_VERSION_MINOR * 100 + NLOHMANN_JSON_VERSION_PATCH) < 30800 +# error "Please use this library with NLohmann's JSON version 3.8.0 or higher" +# endif +#else +# error "expected existing NLOHMANN_JSON_VERSION_MAJOR preproc variable, please update to NLohmann's JSON 3.8.0" +#endif + +// make yourself a home - welcome to nlohmann's namespace +namespace nlohmann +{ + +// A class representing a JSON-URI for schemas derived from +// section 8 of JSON Schema: A Media Type for Describing JSON Documents +// draft-wright-json-schema-00 +// +// New URIs can be derived from it using the derive()-method. +// This is useful for resolving refs or subschema-IDs in json-schemas. +// +// This is done implement the requirements described in section 8.2. +// +class JSON_SCHEMA_VALIDATOR_API json_uri +{ + std::string urn_; + + std::string scheme_; + std::string authority_; + std::string path_; + + json::json_pointer pointer_; // fragment part if JSON-Pointer + std::string identifier_; // fragment part if Locatation Independent ID + +protected: + // decodes a JSON uri and replaces all or part of the currently stored values + void update(const std::string &uri); + + std::tuple as_tuple() const + { + return std::make_tuple(urn_, scheme_, authority_, path_, identifier_ != "" ? identifier_ : pointer_.to_string()); + } + +public: + json_uri(const std::string &uri) + { + update(uri); + } + + const std::string &scheme() const { return scheme_; } + const std::string &authority() const { return authority_; } + const std::string &path() const { return path_; } + + const json::json_pointer &pointer() const { return pointer_; } + const std::string &identifier() const { return identifier_; } + + std::string fragment() const + { + if (identifier_ == "") + return pointer_.to_string(); + else + return identifier_; + } + + std::string url() const { return location(); } + std::string location() const; + + static std::string escape(const std::string &); + + // create a new json_uri based in this one and the given uri + // resolves relative changes (pathes or pointers) and resets part if proto or hostname changes + json_uri derive(const std::string &uri) const + { + json_uri u = *this; + u.update(uri); + return u; + } + + // append a pointer-field to the pointer-part of this uri + json_uri append(const std::string &field) const + { + if (identifier_ != "") + return *this; + + json_uri u = *this; + u.pointer_ /= field; + return u; + } + + std::string to_string() const; + + friend bool operator<(const json_uri &l, const json_uri &r) + { + return l.as_tuple() < r.as_tuple(); + } + + friend bool operator==(const json_uri &l, const json_uri &r) + { + return l.as_tuple() == r.as_tuple(); + } + + friend std::ostream &operator<<(std::ostream &os, const json_uri &u); +}; + +namespace json_schema +{ + +extern json draft7_schema_builtin; + +typedef std::function schema_loader; +typedef std::function format_checker; +typedef std::function content_checker; + +// Interface for validation error handlers +class JSON_SCHEMA_VALIDATOR_API error_handler +{ +public: + virtual ~error_handler() {} + virtual void error(const json::json_pointer & /*ptr*/, const json & /*instance*/, const std::string & /*message*/) = 0; +}; + +class JSON_SCHEMA_VALIDATOR_API basic_error_handler : public error_handler +{ + bool error_{false}; + +public: + void error(const json::json_pointer & /*ptr*/, const json & /*instance*/, const std::string & /*message*/) override + { + error_ = true; + } + + virtual void reset() { error_ = false; } + operator bool() const { return error_; } +}; + +/** + * Checks validity of JSON schema built-in string format specifiers like 'date-time', 'ipv4', ... + */ +void JSON_SCHEMA_VALIDATOR_API default_string_format_check(const std::string &format, const std::string &value); + +class root_schema; + +class JSON_SCHEMA_VALIDATOR_API json_validator +{ + std::unique_ptr root_; + +public: + json_validator(schema_loader = nullptr, format_checker = nullptr, content_checker = nullptr); + + json_validator(const json &, schema_loader = nullptr, format_checker = nullptr, content_checker = nullptr); + json_validator(json &&, schema_loader = nullptr, format_checker = nullptr, content_checker = nullptr); + + json_validator(json_validator &&); + json_validator &operator=(json_validator &&); + + json_validator(json_validator const &) = delete; + json_validator &operator=(json_validator const &) = delete; + + ~json_validator(); + + // insert and set the root-schema + void set_root_schema(const json &); + void set_root_schema(json &&); + + // validate a json-document based on the root-schema + json validate(const json &) const; + + // validate a json-document based on the root-schema with a custom error-handler + json validate(const json &, error_handler &, const json_uri &initial_uri = json_uri("#")) const; +}; + +} // namespace json_schema +} // namespace nlohmann + +#endif /* NLOHMANN_JSON_SCHEMA_HPP__ */ diff --git a/lib/All/json-schema-validator/lib/libnlohmann_json_schema_validator.a b/lib/All/json-schema-validator/lib/libnlohmann_json_schema_validator.a new file mode 100644 index 0000000000000000000000000000000000000000..89a6ed777ec86d2d3763808d0c03f6063a0a416d GIT binary patch literal 1653322 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

ImhG-lCK6)Q?e_lkw%V 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 literal 0 HcmV?d00001 diff --git a/lib/All/json-schema-validator/schema b/lib/All/json-schema-validator/schema new file mode 100644 index 0000000..5bee90e --- /dev/null +++ b/lib/All/json-schema-validator/schema @@ -0,0 +1,168 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "http://json-schema.org/draft-07/schema#", + "title": "Core schema meta-schema", + "definitions": { + "schemaArray": { + "type": "array", + "minItems": 1, + "items": { "$ref": "#" } + }, + "nonNegativeInteger": { + "type": "integer", + "minimum": 0 + }, + "nonNegativeIntegerDefault0": { + "allOf": [ + { "$ref": "#/definitions/nonNegativeInteger" }, + { "default": 0 } + ] + }, + "simpleTypes": { + "enum": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ] + }, + "stringArray": { + "type": "array", + "items": { "type": "string" }, + "uniqueItems": true, + "default": [] + } + }, + "type": ["object", "boolean"], + "properties": { + "$id": { + "type": "string", + "format": "uri-reference" + }, + "$schema": { + "type": "string", + "format": "uri" + }, + "$ref": { + "type": "string", + "format": "uri-reference" + }, + "$comment": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "default": true, + "readOnly": { + "type": "boolean", + "default": false + }, + "examples": { + "type": "array", + "items": true + }, + "multipleOf": { + "type": "number", + "exclusiveMinimum": 0 + }, + "maximum": { + "type": "number" + }, + "exclusiveMaximum": { + "type": "number" + }, + "minimum": { + "type": "number" + }, + "exclusiveMinimum": { + "type": "number" + }, + "maxLength": { "$ref": "#/definitions/nonNegativeInteger" }, + "minLength": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, + "pattern": { + "type": "string", + "format": "regex" + }, + "additionalItems": { "$ref": "#" }, + "items": { + "anyOf": [ + { "$ref": "#" }, + { "$ref": "#/definitions/schemaArray" } + ], + "default": true + }, + "maxItems": { "$ref": "#/definitions/nonNegativeInteger" }, + "minItems": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, + "uniqueItems": { + "type": "boolean", + "default": false + }, + "contains": { "$ref": "#" }, + "maxProperties": { "$ref": "#/definitions/nonNegativeInteger" }, + "minProperties": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, + "required": { "$ref": "#/definitions/stringArray" }, + "additionalProperties": { "$ref": "#" }, + "definitions": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "default": {} + }, + "properties": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "default": {} + }, + "patternProperties": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "propertyNames": { "format": "regex" }, + "default": {} + }, + "dependencies": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { "$ref": "#" }, + { "$ref": "#/definitions/stringArray" } + ] + } + }, + "propertyNames": { "$ref": "#" }, + "const": true, + "enum": { + "type": "array", + "items": true, + "minItems": 1, + "uniqueItems": true + }, + "type": { + "anyOf": [ + { "$ref": "#/definitions/simpleTypes" }, + { + "type": "array", + "items": { "$ref": "#/definitions/simpleTypes" }, + "minItems": 1, + "uniqueItems": true + } + ] + }, + "format": { "type": "string" }, + "contentMediaType": { "type": "string" }, + "contentEncoding": { "type": "string" }, + "if": {"$ref": "#"}, + "then": {"$ref": "#"}, + "else": {"$ref": "#"}, + "allOf": { "$ref": "#/definitions/schemaArray" }, + "anyOf": { "$ref": "#/definitions/schemaArray" }, + "oneOf": { "$ref": "#/definitions/schemaArray" }, + "not": { "$ref": "#" } + }, + "default": true +} diff --git a/lib/All/json-schema-validator/src/CMakeLists.txt b/lib/All/json-schema-validator/src/CMakeLists.txt new file mode 100644 index 0000000..7848554 --- /dev/null +++ b/lib/All/json-schema-validator/src/CMakeLists.txt @@ -0,0 +1,64 @@ +target_sources(nlohmann_json_schema_validator PRIVATE + smtp-address-validator.cpp + json-schema-draft7.json.cpp + json-uri.cpp + json-validator.cpp + json-patch.cpp + string-format-check.cpp + ) +target_include_directories(nlohmann_json_schema_validator PUBLIC + $ + $ + ) + +set_target_properties(nlohmann_json_schema_validator PROPERTIES + PUBLIC_HEADER nlohmann/json-schema.hpp) + +# TODO: Why would this need to be if guarded? +if (JSON_VALIDATOR_SHARED_LIBS) + target_compile_definitions(nlohmann_json_schema_validator PRIVATE + -DJSON_SCHEMA_VALIDATOR_EXPORTS) +endif () + +# TODO: Consider setting minimum cxx standard instead +target_compile_features(nlohmann_json_schema_validator PUBLIC + cxx_range_for) # for C++11 - flags + +# TODO: This should be handled by the CI/presets, not the cmake +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR + "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + target_compile_options(nlohmann_json_schema_validator + PRIVATE + -Wall -Wextra -Wshadow) +endif () + +# TODO: gcc support for <4.9 should be removed +# regex with boost if gcc < 4.9 - default is std::regex +if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.9.0") + find_package(Boost COMPONENTS regex) + if (NOT Boost_FOUND) + message(STATUS "GCC less then 4.9 and boost-regex NOT found - no regex used") + target_compile_definitions(nlohmann_json_schema_validator PRIVATE -DJSON_SCHEMA_NO_REGEX) + else () + message(STATUS "GCC less then 4.9 and boost-regex FOUND - using boost::regex") + target_compile_definitions(nlohmann_json_schema_validator PRIVATE -DJSON_SCHEMA_BOOST_REGEX) + target_include_directories(nlohmann_json_schema_validator PRIVATE ${Boost_INCLUDE_DIRS}) + target_link_libraries(nlohmann_json_schema_validator PRIVATE ${Boost_LIBRARIES}) + endif () + endif () +endif () + +target_link_libraries(nlohmann_json_schema_validator PUBLIC + nlohmann_json::nlohmann_json) + +if (JSON_VALIDATOR_INSTALL) + # Normal installation target to system. When using scikit-build check python subdirectory + install(TARGETS nlohmann_json_schema_validator + EXPORT nlohmann_json_schema_validatorTargets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT nlohmann_json_schema_validator_Runtime + NAMELINK_COMPONENT nlohmann_json_schema_validator_Development + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT nlohmann_json_schema_validator_Development + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/nlohmann COMPONENT nlohmann_json_schema_validator_Development + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT nlohmann_json_schema_validator_Runtime) +endif () diff --git a/lib/All/json-schema-validator/src/json-patch.cpp b/lib/All/json-schema-validator/src/json-patch.cpp new file mode 100644 index 0000000..3203543 --- /dev/null +++ b/lib/All/json-schema-validator/src/json-patch.cpp @@ -0,0 +1,115 @@ +#include "json-patch.hpp" + +#include + +namespace +{ + +// originally from http://jsonpatch.com/, http://json.schemastore.org/json-patch +// with fixes +const nlohmann::json patch_schema = R"patch({ + "title": "JSON schema for JSONPatch files", + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "array", + + "items": { + "oneOf": [ + { + "additionalProperties": false, + "required": [ "value", "op", "path"], + "properties": { + "path" : { "$ref": "#/definitions/path" }, + "op": { + "description": "The operation to perform.", + "type": "string", + "enum": [ "add", "replace", "test" ] + }, + "value": { + "description": "The value to add, replace or test." + } + } + }, + { + "additionalProperties": false, + "required": [ "op", "path"], + "properties": { + "path" : { "$ref": "#/definitions/path" }, + "op": { + "description": "The operation to perform.", + "type": "string", + "enum": [ "remove" ] + } + } + }, + { + "additionalProperties": false, + "required": [ "from", "op", "path" ], + "properties": { + "path" : { "$ref": "#/definitions/path" }, + "op": { + "description": "The operation to perform.", + "type": "string", + "enum": [ "move", "copy" ] + }, + "from": { + "$ref": "#/definitions/path", + "description": "A JSON Pointer path pointing to the location to move/copy from." + } + } + } + ] + }, + "definitions": { + "path": { + "description": "A JSON Pointer path.", + "type": "string" + } + } +})patch"_json; +} // namespace + +namespace nlohmann +{ + +json_patch::json_patch(json &&patch) + : j_(std::move(patch)) +{ + validateJsonPatch(j_); +} + +json_patch::json_patch(const json &patch) + : j_(std::move(patch)) +{ + validateJsonPatch(j_); +} + +json_patch &json_patch::add(const json::json_pointer &ptr, json value) +{ + j_.push_back(json{{"op", "add"}, {"path", ptr.to_string()}, {"value", std::move(value)}}); + return *this; +} + +json_patch &json_patch::replace(const json::json_pointer &ptr, json value) +{ + j_.push_back(json{{"op", "replace"}, {"path", ptr.to_string()}, {"value", std::move(value)}}); + return *this; +} + +json_patch &json_patch::remove(const json::json_pointer &ptr) +{ + j_.push_back(json{{"op", "remove"}, {"path", ptr.to_string()}}); + return *this; +} + +void json_patch::validateJsonPatch(json const &patch) +{ + // static put here to have it created at the first usage of validateJsonPatch + static nlohmann::json_schema::json_validator patch_validator(patch_schema); + + patch_validator.validate(patch); + + for (auto const &op : patch) + json::json_pointer(op["path"].get()); +} + +} // namespace nlohmann diff --git a/lib/All/json-schema-validator/src/json-patch.hpp b/lib/All/json-schema-validator/src/json-patch.hpp new file mode 100644 index 0000000..39a579b --- /dev/null +++ b/lib/All/json-schema-validator/src/json-patch.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include +#include + +namespace nlohmann +{ +class JsonPatchFormatException : public std::exception +{ +public: + explicit JsonPatchFormatException(std::string msg) + : ex_{std::move(msg)} {} + + inline const char *what() const noexcept override final { return ex_.c_str(); } + +private: + std::string ex_; +}; + +class json_patch +{ +public: + json_patch() = default; + json_patch(json &&patch); + json_patch(const json &patch); + + json_patch &add(const json::json_pointer &, json value); + json_patch &replace(const json::json_pointer &, json value); + json_patch &remove(const json::json_pointer &); + + json &get_json() { return j_; } + const json &get_json() const { return j_; } + + operator json() const { return j_; } + +private: + json j_ = nlohmann::json::array(); + + static void validateJsonPatch(json const &patch); +}; +} // namespace nlohmann diff --git a/lib/All/json-schema-validator/src/json-schema-draft7.json.cpp b/lib/All/json-schema-validator/src/json-schema-draft7.json.cpp new file mode 100644 index 0000000..b680e2c --- /dev/null +++ b/lib/All/json-schema-validator/src/json-schema-draft7.json.cpp @@ -0,0 +1,185 @@ +/* + * JSON schema validator for JSON for modern C++ + * + * Copyright (c) 2016-2019 Patrick Boettcher . + * + * SPDX-License-Identifier: MIT + * + */ +#include + +namespace nlohmann +{ +namespace json_schema +{ + +json draft7_schema_builtin = R"( { + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "http://json-schema.org/draft-07/schema#", + "title": "Core schema meta-schema", + "definitions": { + "schemaArray": { + "type": "array", + "minItems": 1, + "items": { "$ref": "#" } + }, + "nonNegativeInteger": { + "type": "integer", + "minimum": 0 + }, + "nonNegativeIntegerDefault0": { + "allOf": [ + { "$ref": "#/definitions/nonNegativeInteger" }, + { "default": 0 } + ] + }, + "simpleTypes": { + "enum": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ] + }, + "stringArray": { + "type": "array", + "items": { "type": "string" }, + "uniqueItems": true, + "default": [] + } + }, + "type": ["object", "boolean"], + "properties": { + "$id": { + "type": "string", + "format": "uri-reference" + }, + "$schema": { + "type": "string", + "format": "uri" + }, + "$ref": { + "type": "string", + "format": "uri-reference" + }, + "$comment": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "default": true, + "readOnly": { + "type": "boolean", + "default": false + }, + "examples": { + "type": "array", + "items": true + }, + "multipleOf": { + "type": "number", + "exclusiveMinimum": 0 + }, + "maximum": { + "type": "number" + }, + "exclusiveMaximum": { + "type": "number" + }, + "minimum": { + "type": "number" + }, + "exclusiveMinimum": { + "type": "number" + }, + "maxLength": { "$ref": "#/definitions/nonNegativeInteger" }, + "minLength": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, + "pattern": { + "type": "string", + "format": "regex" + }, + "additionalItems": { "$ref": "#" }, + "items": { + "anyOf": [ + { "$ref": "#" }, + { "$ref": "#/definitions/schemaArray" } + ], + "default": true + }, + "maxItems": { "$ref": "#/definitions/nonNegativeInteger" }, + "minItems": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, + "uniqueItems": { + "type": "boolean", + "default": false + }, + "contains": { "$ref": "#" }, + "maxProperties": { "$ref": "#/definitions/nonNegativeInteger" }, + "minProperties": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, + "required": { "$ref": "#/definitions/stringArray" }, + "additionalProperties": { "$ref": "#" }, + "definitions": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "default": {} + }, + "properties": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "default": {} + }, + "patternProperties": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "propertyNames": { "format": "regex" }, + "default": {} + }, + "dependencies": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { "$ref": "#" }, + { "$ref": "#/definitions/stringArray" } + ] + } + }, + "propertyNames": { "$ref": "#" }, + "const": true, + "enum": { + "type": "array", + "items": true, + "minItems": 1, + "uniqueItems": true + }, + "type": { + "anyOf": [ + { "$ref": "#/definitions/simpleTypes" }, + { + "type": "array", + "items": { "$ref": "#/definitions/simpleTypes" }, + "minItems": 1, + "uniqueItems": true + } + ] + }, + "format": { "type": "string" }, + "contentMediaType": { "type": "string" }, + "contentEncoding": { "type": "string" }, + "if": { "$ref": "#" }, + "then": { "$ref": "#" }, + "else": { "$ref": "#" }, + "allOf": { "$ref": "#/definitions/schemaArray" }, + "anyOf": { "$ref": "#/definitions/schemaArray" }, + "oneOf": { "$ref": "#/definitions/schemaArray" }, + "not": { "$ref": "#" } + }, + "default": true +} )"_json; +} +} // namespace nlohmann diff --git a/lib/All/json-schema-validator/src/json-uri.cpp b/lib/All/json-schema-validator/src/json-uri.cpp new file mode 100644 index 0000000..2602556 --- /dev/null +++ b/lib/All/json-schema-validator/src/json-uri.cpp @@ -0,0 +1,159 @@ +/* + * JSON schema validator for JSON for modern C++ + * + * Copyright (c) 2016-2019 Patrick Boettcher . + * + * SPDX-License-Identifier: MIT + * + */ +#include + +#include + +namespace nlohmann +{ + +void json_uri::update(const std::string &uri) +{ + std::string pointer = ""; // default pointer is document-root + + // first split the URI into location and pointer + auto pointer_separator = uri.find('#'); + if (pointer_separator != std::string::npos) { // and extract the pointer-string if found + pointer = uri.substr(pointer_separator + 1); // remove # + + // unescape %-values IOW, decode JSON-URI-formatted JSON-pointer + std::size_t pos = pointer.size() - 1; + do { + pos = pointer.rfind('%', pos); + if (pos == std::string::npos) + break; + + if (pos >= pointer.size() - 2) { + pos--; + continue; + } + + std::string hex = pointer.substr(pos + 1, 2); + char ascii = static_cast(std::strtoul(hex.c_str(), nullptr, 16)); + pointer.replace(pos, 3, 1, ascii); + + pos--; + } while (1); + } + + auto location = uri.substr(0, pointer_separator); + + if (location.size()) { // a location part has been found + + // if it is an URN take it as it is + if (location.find("urn:") == 0) { + urn_ = location; + + // and clear URL members + scheme_ = ""; + authority_ = ""; + path_ = ""; + + } else { // it is an URL + + // split URL in protocol, hostname and path + std::size_t pos = 0; + auto proto = location.find("://", pos); + if (proto != std::string::npos) { // extract the protocol + + urn_ = ""; // clear URN-member if URL is parsed + + scheme_ = location.substr(pos, proto - pos); + pos = 3 + proto; // 3 == "://" + + auto authority = location.find("/", pos); + if (authority != std::string::npos) { // and the hostname (no proto without hostname) + authority_ = location.substr(pos, authority - pos); + pos = authority; + } + } + + auto path = location.substr(pos); + + // URNs cannot of have paths + if (urn_.size() && path.size()) + throw std::invalid_argument("Cannot add a path (" + path + ") to an URN URI (" + urn_ + ")"); + + if (path[0] == '/') // if it starts with a / it is root-path + path_ = path; + else if (pos == 0) { // the URL contained only a path and the current path has no / at the end, strip last element until / and append + auto last_slash = path_.rfind('/'); + path_ = path_.substr(0, last_slash) + '/' + path; + } else // otherwise it is a subfolder + path_.append(path); + } + } + + pointer_ = ""_json_pointer; + identifier_ = ""; + + if (pointer[0] == '/') + pointer_ = json::json_pointer(pointer); + else + identifier_ = pointer; +} + +std::string json_uri::location() const +{ + if (urn_.size()) + return urn_; + + std::stringstream s; + + if (scheme_.size() > 0) + s << scheme_ << "://"; + + s << authority_ + << path_; + + return s.str(); +} + +std::string json_uri::to_string() const +{ + std::stringstream s; + + s << location() << " # "; + + if (identifier_ == "") + s << pointer_.to_string(); + else + s << identifier_; + + return s.str(); +} + +std::ostream &operator<<(std::ostream &os, const json_uri &u) +{ + return os << u.to_string(); +} + +std::string json_uri::escape(const std::string &src) +{ + std::vector> chars = { + {"~", "~0"}, + {"/", "~1"}}; + + std::string l = src; + + for (const auto &c : chars) { + std::size_t pos = 0; + do { + pos = l.find(c.first, pos); + if (pos == std::string::npos) + break; + l.replace(pos, 1, c.second); + pos += c.second.size(); + } while (1); + } + + return l; +} + +} // namespace nlohmann diff --git a/lib/All/json-schema-validator/src/json-validator.cpp b/lib/All/json-schema-validator/src/json-validator.cpp new file mode 100644 index 0000000..62ce97c --- /dev/null +++ b/lib/All/json-schema-validator/src/json-validator.cpp @@ -0,0 +1,1520 @@ +/* + * JSON schema validator for JSON for modern C++ + * + * Copyright (c) 2016-2019 Patrick Boettcher . + * + * SPDX-License-Identifier: MIT + * + */ +#include + +#include "json-patch.hpp" + +#include +#include +#include +#include +#include + +using nlohmann::json; +using nlohmann::json_patch; +using nlohmann::json_uri; +using nlohmann::json_schema::root_schema; +using namespace nlohmann::json_schema; + +#ifdef JSON_SCHEMA_BOOST_REGEX +# include +# define REGEX_NAMESPACE boost +#elif defined(JSON_SCHEMA_NO_REGEX) +# define NO_STD_REGEX +#else +# include +# define REGEX_NAMESPACE std +#endif + +namespace +{ + +class schema +{ +protected: + root_schema *root_; + json default_value_ = nullptr; + +protected: + virtual std::shared_ptr make_for_default_( + std::shared_ptr<::schema> & /* sch */, + root_schema * /* root */, + std::vector & /* uris */, + nlohmann::json & /* default_value */) const + { + return nullptr; + }; + +public: + virtual ~schema() = default; + + schema(root_schema *root) + : root_(root) {} + + virtual void validate(const json::json_pointer &ptr, const json &instance, json_patch &patch, error_handler &e) const = 0; + + virtual const json &default_value(const json::json_pointer &, const json &, error_handler &) const + { + return default_value_; + } + + void set_default_value(const json &v) { default_value_ = v; } + + static std::shared_ptr make(json &schema, + root_schema *root, + const std::vector &key, + std::vector uris); +}; + +class schema_ref : public schema +{ + const std::string id_; + std::weak_ptr target_; + std::shared_ptr target_strong_; // for references to references keep also the shared_ptr because + // no one else might use it after resolving + + void validate(const json::json_pointer &ptr, const json &instance, json_patch &patch, error_handler &e) const final + { + auto target = target_.lock(); + + if (target) + target->validate(ptr, instance, patch, e); + else + e.error(ptr, instance, "unresolved or freed schema-reference " + id_); + } + + const json &default_value(const json::json_pointer &ptr, const json &instance, error_handler &e) const override final + { + if (!default_value_.is_null()) + return default_value_; + + auto target = target_.lock(); + if (target) + return target->default_value(ptr, instance, e); + + e.error(ptr, instance, "unresolved or freed schema-reference " + id_); + + return default_value_; + } + +protected: + virtual std::shared_ptr make_for_default_( + std::shared_ptr<::schema> &sch, + root_schema *root, + std::vector &uris, + nlohmann::json &default_value) const override + { + // create a new reference schema using the original reference (which will be resolved later) + // to store this overloaded default value #209 + auto result = std::make_shared(uris[0].to_string(), root); + result->set_target(sch, true); + result->set_default_value(default_value); + return result; + }; + +public: + schema_ref(const std::string &id, root_schema *root) + : schema(root), id_(id) {} + + const std::string &id() const { return id_; } + + void set_target(const std::shared_ptr &target, bool strong = false) + { + target_ = target; + if (strong) + target_strong_ = target; + } +}; + +} // namespace + +namespace nlohmann +{ +namespace json_schema +{ + +class root_schema +{ + schema_loader loader_; + format_checker format_check_; + content_checker content_check_; + + std::shared_ptr root_; + + struct schema_file { + std::map> schemas; + std::map> unresolved; // contains all unresolved references from any other file seen during parsing + json unknown_keywords; + }; + + // location as key + std::map files_; + + schema_file &get_or_create_file(const std::string &loc) + { + auto file = files_.lower_bound(loc); + if (file != files_.end() && !(files_.key_comp()(loc, file->first))) + return file->second; + else + return files_.insert(file, {loc, {}})->second; + } + +public: + root_schema(schema_loader &&loader, + format_checker &&format, + content_checker &&content) + + : loader_(std::move(loader)), + format_check_(std::move(format)), + content_check_(std::move(content)) + { + } + + format_checker &format_check() { return format_check_; } + content_checker &content_check() { return content_check_; } + + void insert(const json_uri &uri, const std::shared_ptr &s) + { + auto &file = get_or_create_file(uri.location()); + auto sch = file.schemas.lower_bound(uri.fragment()); + if (sch != file.schemas.end() && !(file.schemas.key_comp()(uri.fragment(), sch->first))) { + throw std::invalid_argument("schema with " + uri.to_string() + " already inserted"); + return; + } + + file.schemas.insert({uri.fragment(), s}); + + // was someone referencing this newly inserted schema? + auto unresolved = file.unresolved.find(uri.fragment()); + if (unresolved != file.unresolved.end()) { + unresolved->second->set_target(s); + file.unresolved.erase(unresolved); + } + } + + void insert_unknown_keyword(const json_uri &uri, const std::string &key, json &value) + { + auto &file = get_or_create_file(uri.location()); + auto new_uri = uri.append(key); + auto fragment = new_uri.pointer(); + + // is there a reference looking for this unknown-keyword, which is thus no longer a unknown keyword but a schema + auto unresolved = file.unresolved.find(fragment.to_string()); + if (unresolved != file.unresolved.end()) + schema::make(value, this, {}, {{new_uri}}); + else { // no, nothing ref'd it, keep for later + + // need to create an object for each reference-token in the + // JSON-Pointer When not existing, a stringified integer reference + // token (e.g. "123") in the middle of the pointer will be + // interpreted a an array-index and an array will be created. + + // json_pointer's reference_tokens is private - get them + std::deque ref_tokens; + auto uri_pointer = uri.pointer(); + while (!uri_pointer.empty()) { + ref_tokens.push_front(uri_pointer.back()); + uri_pointer.pop_back(); + } + + // for each token create an object, if not already existing + auto unk_kw = &file.unknown_keywords; + for (auto &rt : ref_tokens) { + // create a json_pointer from rt as rt can be an stringified integer doing find on an array won't work + json::json_pointer rt_ptr{"/" + rt}; + if (unk_kw->contains(rt_ptr) == false) + (*unk_kw)[rt] = json::object(); + unk_kw = &(*unk_kw)[rt_ptr]; + } + (*unk_kw)[key] = value; + } + + // recursively add possible subschemas of unknown keywords + if (value.type() == json::value_t::object) + for (auto &subsch : value.items()) + insert_unknown_keyword(new_uri, subsch.key(), subsch.value()); + } + + std::shared_ptr get_or_create_ref(const json_uri &uri) + { + auto &file = get_or_create_file(uri.location()); + + // existing schema + auto sch = file.schemas.find(uri.fragment()); + if (sch != file.schemas.end()) + return sch->second; + + // referencing an unknown keyword, turn it into schema + // + // an unknown keyword can only be referenced by a json-pointer, + // not by a plain name fragment + if (!uri.pointer().to_string().empty()) { + bool contains_pointer = file.unknown_keywords.contains(uri.pointer()); + if (contains_pointer) { + auto &subschema = file.unknown_keywords.at(uri.pointer()); + auto s = schema::make(subschema, this, {}, {{uri}}); + if (s) { // if schema is valid (non-null) + file.unknown_keywords.erase(uri.fragment()); + return s; + } + } + } + + // get or create a schema_ref + auto r = file.unresolved.lower_bound(uri.fragment()); + if (r != file.unresolved.end() && !(file.unresolved.key_comp()(uri.fragment(), r->first))) { + return r->second; // unresolved, already seen previously - use existing reference + } else { + return file.unresolved.insert(r, + {uri.fragment(), std::make_shared(uri.to_string(), this)}) + ->second; // unresolved, create reference + } + } + + void set_root_schema(json sch) + { + files_.clear(); + root_ = schema::make(sch, this, {}, {{"#"}}); + + // load all files which have not yet been loaded + do { + bool new_schema_loaded = false; + + // files_ is modified during parsing, iterators are invalidated + std::vector locations; + for (auto &file : files_) + locations.push_back(file.first); + + for (auto &loc : locations) { + if (files_[loc].schemas.size() == 0) { // nothing has been loaded for this file + if (loader_) { + json loaded_schema; + + loader_(loc, loaded_schema); + + schema::make(loaded_schema, this, {}, {{loc}}); + new_schema_loaded = true; + } else { + throw std::invalid_argument("external schema reference '" + loc + "' needs loading, but no loader callback given"); + } + } + } + + if (!new_schema_loaded) // if no new schema loaded, no need to try again + break; + } while (1); + + for (const auto &file : files_) { + if (file.second.unresolved.size() != 0) { + // Build a representation of the undefined + // references as a list of comma-separated strings. + auto n_urefs = file.second.unresolved.size(); + std::string urefs = "["; + + decltype(n_urefs) counter = 0; + for (const auto &p : file.second.unresolved) { + urefs += p.first; + + if (counter != n_urefs - 1u) { + urefs += ", "; + } + + ++counter; + } + + urefs += "]"; + + throw std::invalid_argument("after all files have been parsed, '" + + (file.first == "" ? "" : file.first) + + "' has still the following undefined references: " + urefs); + } + } + } + + void validate(const json::json_pointer &ptr, + const json &instance, + json_patch &patch, + error_handler &e, + const json_uri &initial) const + { + if (!root_) { + e.error(ptr, "", "no root schema has yet been set for validating an instance"); + return; + } + + auto file_entry = files_.find(initial.location()); + if (file_entry == files_.end()) { + e.error(ptr, "", "no file found serving requested root-URI. " + initial.location()); + return; + } + + auto &file = file_entry->second; + auto sch = file.schemas.find(initial.fragment()); + if (sch == file.schemas.end()) { + e.error(ptr, "", "no schema find for request initial URI: " + initial.to_string()); + return; + } + + sch->second->validate(ptr, instance, patch, e); + } +}; + +} // namespace json_schema +} // namespace nlohmann + +namespace +{ + +class first_error_handler : public error_handler +{ +public: + bool error_{false}; + json::json_pointer ptr_; + json instance_; + std::string message_; + + void error(const json::json_pointer &ptr, const json &instance, const std::string &message) override + { + if (*this) + return; + error_ = true; + ptr_ = ptr; + instance_ = instance; + message_ = message; + } + + operator bool() const { return error_; } +}; + +class logical_not : public schema +{ + std::shared_ptr subschema_; + + void validate(const json::json_pointer &ptr, const json &instance, json_patch &patch, error_handler &e) const final + { + first_error_handler esub; + subschema_->validate(ptr, instance, patch, esub); + + if (!esub) + e.error(ptr, instance, "the subschema has succeeded, but it is required to not validate"); + } + + const json &default_value(const json::json_pointer &ptr, const json &instance, error_handler &e) const override + { + return subschema_->default_value(ptr, instance, e); + } + +public: + logical_not(json &sch, + root_schema *root, + const std::vector &uris) + : schema(root) + { + subschema_ = schema::make(sch, root, {"not"}, uris); + } +}; + +enum logical_combination_types { + allOf, + anyOf, + oneOf +}; + +class logical_combination_error_handler : public error_handler +{ +public: + struct error_entry { + json::json_pointer ptr_; + json instance_; + std::string message_; + }; + + std::vector error_entry_list_; + + void error(const json::json_pointer &ptr, const json &instance, const std::string &message) override + { + error_entry_list_.push_back(error_entry{ptr, instance, message}); + } + + void propagate(error_handler &e, const std::string &prefix) const + { + for (const error_entry &entry : error_entry_list_) + e.error(entry.ptr_, entry.instance_, prefix + entry.message_); + } + + operator bool() const { return !error_entry_list_.empty(); } +}; + +template +class logical_combination : public schema +{ + std::vector> subschemata_; + + void validate(const json::json_pointer &ptr, const json &instance, json_patch &patch, error_handler &e) const final + { + size_t count = 0; + logical_combination_error_handler error_summary; + + for (std::size_t index = 0; index < subschemata_.size(); ++index) { + const std::shared_ptr &s = subschemata_[index]; + logical_combination_error_handler esub; + auto oldPatchSize = patch.get_json().size(); + s->validate(ptr, instance, patch, esub); + if (!esub) + count++; + else { + patch.get_json().get_ref().resize(oldPatchSize); + esub.propagate(error_summary, "case#" + std::to_string(index) + "] "); + } + + if (is_validate_complete(instance, ptr, e, esub, count, index)) + return; + } + + if (count == 0) { + e.error(ptr, instance, "no subschema has succeeded, but one of them is required to validate. Type: " + key + ", number of failed subschemas: " + std::to_string(subschemata_.size())); + error_summary.propagate(e, "[combination: " + key + " / "); + } + } + + // specialized for each of the logical_combination_types + static const std::string key; + static bool is_validate_complete(const json &, const json::json_pointer &, error_handler &, const logical_combination_error_handler &, size_t, size_t); + +public: + logical_combination(json &sch, + root_schema *root, + const std::vector &uris) + : schema(root) + { + size_t c = 0; + for (auto &subschema : sch) + subschemata_.push_back(schema::make(subschema, root, {key, std::to_string(c++)}, uris)); + + // value of allOf, anyOf, and oneOf "MUST be a non-empty array" + // TODO error/throw? when subschemata_.empty() + } +}; + +template <> +const std::string logical_combination::key = "allOf"; +template <> +const std::string logical_combination::key = "anyOf"; +template <> +const std::string logical_combination::key = "oneOf"; + +template <> +bool logical_combination::is_validate_complete(const json &, const json::json_pointer &, error_handler &e, const logical_combination_error_handler &esub, size_t, size_t current_schema_index) +{ + if (esub) { + e.error(esub.error_entry_list_.front().ptr_, esub.error_entry_list_.front().instance_, "at least one subschema has failed, but all of them are required to validate - " + esub.error_entry_list_.front().message_); + esub.propagate(e, "[combination: allOf / case#" + std::to_string(current_schema_index) + "] "); + } + return esub; +} + +template <> +bool logical_combination::is_validate_complete(const json &, const json::json_pointer &, error_handler &, const logical_combination_error_handler &, size_t count, size_t) +{ + return count == 1; +} + +template <> +bool logical_combination::is_validate_complete(const json &instance, const json::json_pointer &ptr, error_handler &e, const logical_combination_error_handler &, size_t count, size_t) +{ + if (count > 1) + e.error(ptr, instance, "more than one subschema has succeeded, but exactly one of them is required to validate"); + return count > 1; +} + +class type_schema : public schema +{ + std::vector> type_; + std::pair enum_, const_; + std::vector> logic_; + + static std::shared_ptr make(json &schema, + json::value_t type, + root_schema *, + const std::vector &, + std::set &); + + std::shared_ptr if_, then_, else_; + + void validate(const json::json_pointer &ptr, const json &instance, json_patch &patch, error_handler &e) const override final + { + // depending on the type of instance run the type specific validator - if present + auto type = type_[static_cast(instance.type())]; + + if (type) + type->validate(ptr, instance, patch, e); + else + e.error(ptr, instance, "unexpected instance type"); + + if (enum_.first) { + bool seen_in_enum = false; + for (auto &v : enum_.second) + if (instance == v) { + seen_in_enum = true; + break; + } + + if (!seen_in_enum) + e.error(ptr, instance, "instance not found in required enum"); + } + + if (const_.first && + const_.second != instance) + e.error(ptr, instance, "instance not const"); + + for (auto l : logic_) + l->validate(ptr, instance, patch, e); + + if (if_) { + first_error_handler err; + + if_->validate(ptr, instance, patch, err); + if (!err) { + if (then_) + then_->validate(ptr, instance, patch, e); + } else { + if (else_) + else_->validate(ptr, instance, patch, e); + } + } + if (instance.is_null()) { + patch.add(nlohmann::json::json_pointer{}, default_value_); + } + } + +protected: + virtual std::shared_ptr make_for_default_( + std::shared_ptr<::schema> & /* sch */, + root_schema * /* root */, + std::vector & /* uris */, + nlohmann::json &default_value) const override + { + auto result = std::make_shared(*this); + result->set_default_value(default_value); + return result; + }; + +public: + type_schema(json &sch, + root_schema *root, + const std::vector &uris) + : schema(root), type_(static_cast(json::value_t::discarded) + 1) + { + // association between JSON-schema-type and NLohmann-types + static const std::vector> schema_types = { + {"null", json::value_t::null}, + {"object", json::value_t::object}, + {"array", json::value_t::array}, + {"string", json::value_t::string}, + {"boolean", json::value_t::boolean}, + {"integer", json::value_t::number_integer}, + {"number", json::value_t::number_float}, + }; + + std::set known_keywords; + + auto attr = sch.find("type"); + if (attr == sch.end()) // no type field means all sub-types possible + for (auto &t : schema_types) + type_[static_cast(t.second)] = type_schema::make(sch, t.second, root, uris, known_keywords); + else { + switch (attr.value().type()) { // "type": "type" + + case json::value_t::string: { + auto schema_type = attr.value().get(); + for (auto &t : schema_types) + if (t.first == schema_type) + type_[static_cast(t.second)] = type_schema::make(sch, t.second, root, uris, known_keywords); + } break; + + case json::value_t::array: // "type": ["type1", "type2"] + for (auto &array_value : attr.value()) { + auto schema_type = array_value.get(); + for (auto &t : schema_types) + if (t.first == schema_type) + type_[static_cast(t.second)] = type_schema::make(sch, t.second, root, uris, known_keywords); + } + break; + + default: + break; + } + + sch.erase(attr); + } + + attr = sch.find("default"); + if (attr != sch.end()) { + set_default_value(attr.value()); + sch.erase(attr); + } + + for (auto &key : known_keywords) + sch.erase(key); + + // with nlohmann::json float instance (but number in schema-definition) can be seen as unsigned or integer - + // reuse the number-validator for integer values as well, if they have not been specified explicitly + if (type_[static_cast(json::value_t::number_float)] && !type_[static_cast(json::value_t::number_integer)]) + type_[static_cast(json::value_t::number_integer)] = type_[static_cast(json::value_t::number_float)]; + + // #54: JSON-schema does not differentiate between unsigned and signed integer - nlohmann::json does + // we stick with JSON-schema: use the integer-validator if instance-value is unsigned + type_[static_cast(json::value_t::number_unsigned)] = type_[static_cast(json::value_t::number_integer)]; + + // special for binary types + if (type_[static_cast(json::value_t::string)]) { + type_[static_cast(json::value_t::binary)] = type_[static_cast(json::value_t::string)]; + } + + attr = sch.find("enum"); + if (attr != sch.end()) { + enum_ = {true, attr.value()}; + sch.erase(attr); + } + + attr = sch.find("const"); + if (attr != sch.end()) { + const_ = {true, attr.value()}; + sch.erase(attr); + } + + attr = sch.find("not"); + if (attr != sch.end()) { + logic_.push_back(std::make_shared(attr.value(), root, uris)); + sch.erase(attr); + } + + attr = sch.find("allOf"); + if (attr != sch.end()) { + logic_.push_back(std::make_shared>(attr.value(), root, uris)); + sch.erase(attr); + } + + attr = sch.find("anyOf"); + if (attr != sch.end()) { + logic_.push_back(std::make_shared>(attr.value(), root, uris)); + sch.erase(attr); + } + + attr = sch.find("oneOf"); + if (attr != sch.end()) { + logic_.push_back(std::make_shared>(attr.value(), root, uris)); + sch.erase(attr); + } + + attr = sch.find("if"); + if (attr != sch.end()) { + auto attr_then = sch.find("then"); + auto attr_else = sch.find("else"); + + if (attr_then != sch.end() || attr_else != sch.end()) { + if_ = schema::make(attr.value(), root, {"if"}, uris); + + if (attr_then != sch.end()) { + then_ = schema::make(attr_then.value(), root, {"then"}, uris); + sch.erase(attr_then); + } + + if (attr_else != sch.end()) { + else_ = schema::make(attr_else.value(), root, {"else"}, uris); + sch.erase(attr_else); + } + } + sch.erase(attr); + } + } +}; + +class string : public schema +{ + std::pair maxLength_{false, 0}; + std::pair minLength_{false, 0}; + +#ifndef NO_STD_REGEX + std::pair pattern_{false, REGEX_NAMESPACE::regex()}; + std::string patternString_; +#endif + + std::pair format_; + std::tuple content_{false, "", ""}; + + std::size_t utf8_length(const std::string &s) const + { + size_t len = 0; + for (auto c : s) + if ((c & 0xc0) != 0x80) + len++; + return len; + } + + void validate(const json::json_pointer &ptr, const json &instance, json_patch &, error_handler &e) const override + { + if (minLength_.first) { + if (utf8_length(instance.get()) < minLength_.second) { + std::ostringstream s; + s << "instance is too short as per minLength:" << minLength_.second; + e.error(ptr, instance, s.str()); + } + } + + if (maxLength_.first) { + if (utf8_length(instance.get()) > maxLength_.second) { + std::ostringstream s; + s << "instance is too long as per maxLength: " << maxLength_.second; + e.error(ptr, instance, s.str()); + } + } + + if (std::get<0>(content_)) { + if (root_->content_check() == nullptr) + e.error(ptr, instance, std::string("a content checker was not provided but a contentEncoding or contentMediaType for this string have been present: '") + std::get<1>(content_) + "' '" + std::get<2>(content_) + "'"); + else { + try { + root_->content_check()(std::get<1>(content_), std::get<2>(content_), instance); + } catch (const std::exception &ex) { + e.error(ptr, instance, std::string("content-checking failed: ") + ex.what()); + } + } + } else if (instance.type() == json::value_t::binary) { + e.error(ptr, instance, "expected string, but get binary data"); + } + + if (instance.type() != json::value_t::string) { + return; // next checks only for strings + } + +#ifndef NO_STD_REGEX + if (pattern_.first && + !REGEX_NAMESPACE::regex_search(instance.get(), pattern_.second)) + e.error(ptr, instance, "instance does not match regex pattern: " + patternString_); +#endif + + if (format_.first) { + if (root_->format_check() == nullptr) + e.error(ptr, instance, std::string("a format checker was not provided but a format keyword for this string is present: ") + format_.second); + else { + try { + root_->format_check()(format_.second, instance.get()); + } catch (const std::exception &ex) { + e.error(ptr, instance, std::string("format-checking failed: ") + ex.what()); + } + } + } + } + +public: + string(json &sch, root_schema *root) + : schema(root) + { + auto attr = sch.find("maxLength"); + if (attr != sch.end()) { + maxLength_ = {true, attr.value().get()}; + sch.erase(attr); + } + + attr = sch.find("minLength"); + if (attr != sch.end()) { + minLength_ = {true, attr.value().get()}; + sch.erase(attr); + } + + attr = sch.find("contentEncoding"); + if (attr != sch.end()) { + std::get<0>(content_) = true; + std::get<1>(content_) = attr.value().get(); + + // special case for nlohmann::json-binary-types + // + // https://github.com/pboettch/json-schema-validator/pull/114 + // + // We cannot use explicitly in a schema: {"type": "binary"} or + // "type": ["binary", "number"] we have to be implicit. For a + // schema where "contentEncoding" is set to "binary", an instance + // of type json::value_t::binary is accepted. If a + // contentEncoding-callback has to be provided and is called + // accordingly. For encoding=binary, no other type validations are done + + sch.erase(attr); + } + + attr = sch.find("contentMediaType"); + if (attr != sch.end()) { + std::get<0>(content_) = true; + std::get<2>(content_) = attr.value().get(); + + sch.erase(attr); + } + + if (std::get<0>(content_) == true && root_->content_check() == nullptr) { + throw std::invalid_argument{"schema contains contentEncoding/contentMediaType but content checker was not set"}; + } + +#ifndef NO_STD_REGEX + attr = sch.find("pattern"); + if (attr != sch.end()) { + patternString_ = attr.value().get(); + pattern_ = {true, REGEX_NAMESPACE::regex(attr.value().get(), + REGEX_NAMESPACE::regex::ECMAScript)}; + sch.erase(attr); + } +#endif + + attr = sch.find("format"); + if (attr != sch.end()) { + if (root_->format_check() == nullptr) + throw std::invalid_argument{"a format checker was not provided but a format keyword for this string is present: " + format_.second}; + + format_ = {true, attr.value().get()}; + sch.erase(attr); + } + } +}; + +template +class numeric : public schema +{ + std::pair maximum_{false, 0}; + std::pair minimum_{false, 0}; + + bool exclusiveMaximum_ = false; + bool exclusiveMinimum_ = false; + + std::pair multipleOf_{false, 0}; + + // multipleOf - if the remainder of the division is 0 -> OK + bool violates_multiple_of(T x) const + { + double res = std::remainder(x, multipleOf_.second); + double multiple = std::fabs(x / multipleOf_.second); + if (multiple > 1) { + res = res / multiple; + } + double eps = std::nextafter(x, 0) - static_cast(x); + + return std::fabs(res) > std::fabs(eps); + } + + void validate(const json::json_pointer &ptr, const json &instance, json_patch &, error_handler &e) const override + { + T value = instance; // conversion of json to value_type + + std::ostringstream oss; + + if (multipleOf_.first && value != 0) // zero is multiple of everything + if (violates_multiple_of(value)) + oss << "instance is not a multiple of " << json(multipleOf_.second); + + if (maximum_.first) { + if (exclusiveMaximum_ && value >= maximum_.second) + oss << "instance exceeds or equals maximum of " << json(maximum_.second); + else if (value > maximum_.second) + oss << "instance exceeds maximum of " << json(maximum_.second); + } + + if (minimum_.first) { + if (exclusiveMinimum_ && value <= minimum_.second) + oss << "instance is below or equals minimum of " << json(minimum_.second); + else if (value < minimum_.second) + oss << "instance is below minimum of " << json(minimum_.second); + } + + oss.seekp(0, std::ios::end); + auto size = oss.tellp(); + if (size != 0) { + oss.seekp(0, std::ios::beg); + e.error(ptr, instance, oss.str()); + } + } + +public: + numeric(const json &sch, root_schema *root, std::set &kw) + : schema(root) + { + auto attr = sch.find("maximum"); + if (attr != sch.end()) { + maximum_ = {true, attr.value().get()}; + kw.insert("maximum"); + } + + attr = sch.find("minimum"); + if (attr != sch.end()) { + minimum_ = {true, attr.value().get()}; + kw.insert("minimum"); + } + + attr = sch.find("exclusiveMaximum"); + if (attr != sch.end()) { + exclusiveMaximum_ = true; + maximum_ = {true, attr.value().get()}; + kw.insert("exclusiveMaximum"); + } + + attr = sch.find("exclusiveMinimum"); + if (attr != sch.end()) { + exclusiveMinimum_ = true; + minimum_ = {true, attr.value().get()}; + kw.insert("exclusiveMinimum"); + } + + attr = sch.find("multipleOf"); + if (attr != sch.end()) { + multipleOf_ = {true, attr.value().get()}; + kw.insert("multipleOf"); + } + } +}; + +class null : public schema +{ + void validate(const json::json_pointer &ptr, const json &instance, json_patch &, error_handler &e) const override + { + if (!instance.is_null()) + e.error(ptr, instance, "expected to be null"); + } + +public: + null(json &, root_schema *root) + : schema(root) {} +}; + +class boolean_type : public schema +{ + void validate(const json::json_pointer &, const json &, json_patch &, error_handler &) const override {} + +public: + boolean_type(json &, root_schema *root) + : schema(root) {} +}; + +class boolean : public schema +{ + bool true_; + void validate(const json::json_pointer &ptr, const json &instance, json_patch &, error_handler &e) const override + { + if (!true_) { // false schema + // empty array + // switch (instance.type()) { + // case json::value_t::array: + // if (instance.size() != 0) // valid false-schema + // e.error(ptr, instance, "false-schema required empty array"); + // return; + //} + + e.error(ptr, instance, "instance invalid as per false-schema"); + } + } + +public: + boolean(json &sch, root_schema *root) + : schema(root), true_(sch) {} +}; + +class required : public schema +{ + const std::vector required_; + + void validate(const json::json_pointer &ptr, const json &instance, json_patch &, error_handler &e) const override final + { + for (auto &r : required_) + if (instance.find(r) == instance.end()) + e.error(ptr, instance, "required property '" + r + "' not found in object as a dependency"); + } + +public: + required(const std::vector &r, root_schema *root) + : schema(root), required_(r) {} +}; + +class object : public schema +{ + std::pair maxProperties_{false, 0}; + std::pair minProperties_{false, 0}; + std::vector required_; + + std::map> properties_; +#ifndef NO_STD_REGEX + std::vector>> patternProperties_; +#endif + std::shared_ptr additionalProperties_; + + std::map> dependencies_; + + std::shared_ptr propertyNames_; + + void validate(const json::json_pointer &ptr, const json &instance, json_patch &patch, error_handler &e) const override + { + if (maxProperties_.first && instance.size() > maxProperties_.second) + e.error(ptr, instance, "too many properties"); + + if (minProperties_.first && instance.size() < minProperties_.second) + e.error(ptr, instance, "too few properties"); + + for (auto &r : required_) + if (instance.find(r) == instance.end()) + e.error(ptr, instance, "required property '" + r + "' not found in object"); + + // for each property in instance + for (auto &p : instance.items()) { + if (propertyNames_) + propertyNames_->validate(ptr, p.key(), patch, e); + + bool a_prop_or_pattern_matched = false; + auto schema_p = properties_.find(p.key()); + // check if it is in "properties" + if (schema_p != properties_.end()) { + a_prop_or_pattern_matched = true; + schema_p->second->validate(ptr / p.key(), p.value(), patch, e); + } + +#ifndef NO_STD_REGEX + // check all matching patternProperties + for (auto &schema_pp : patternProperties_) + if (REGEX_NAMESPACE::regex_search(p.key(), schema_pp.first)) { + a_prop_or_pattern_matched = true; + schema_pp.second->validate(ptr / p.key(), p.value(), patch, e); + } +#endif + + // check additionalProperties as a last resort + if (!a_prop_or_pattern_matched && additionalProperties_) { + first_error_handler additional_prop_err; + additionalProperties_->validate(ptr / p.key(), p.value(), patch, additional_prop_err); + if (additional_prop_err) + e.error(ptr, instance, "validation failed for additional property '" + p.key() + "': " + additional_prop_err.message_); + } + } + + // reverse search + for (auto const &prop : properties_) { + const auto finding = instance.find(prop.first); + if (instance.end() == finding) { // if the prop is not in the instance + const auto &default_value = prop.second->default_value(ptr, instance, e); + if (!default_value.is_null()) { // if default value is available + patch.add((ptr / prop.first), default_value); + } + } + } + + for (auto &dep : dependencies_) { + auto prop = instance.find(dep.first); + if (prop != instance.end()) // if dependency-property is present in instance + dep.second->validate(ptr / dep.first, instance, patch, e); // validate + } + } + +public: + object(json &sch, + root_schema *root, + const std::vector &uris) + : schema(root) + { + auto attr = sch.find("maxProperties"); + if (attr != sch.end()) { + maxProperties_ = {true, attr.value().get()}; + sch.erase(attr); + } + + attr = sch.find("minProperties"); + if (attr != sch.end()) { + minProperties_ = {true, attr.value().get()}; + sch.erase(attr); + } + + attr = sch.find("required"); + if (attr != sch.end()) { + required_ = attr.value().get>(); + sch.erase(attr); + } + + attr = sch.find("properties"); + if (attr != sch.end()) { + for (auto prop : attr.value().items()) + properties_.insert( + std::make_pair( + prop.key(), + schema::make(prop.value(), root, {"properties", prop.key()}, uris))); + sch.erase(attr); + } + +#ifndef NO_STD_REGEX + attr = sch.find("patternProperties"); + if (attr != sch.end()) { + for (auto prop : attr.value().items()) + patternProperties_.push_back( + std::make_pair( + REGEX_NAMESPACE::regex(prop.key(), REGEX_NAMESPACE::regex::ECMAScript), + schema::make(prop.value(), root, {prop.key()}, uris))); + sch.erase(attr); + } +#endif + + attr = sch.find("additionalProperties"); + if (attr != sch.end()) { + additionalProperties_ = schema::make(attr.value(), root, {"additionalProperties"}, uris); + sch.erase(attr); + } + + attr = sch.find("dependencies"); + if (attr != sch.end()) { + for (auto &dep : attr.value().items()) + switch (dep.value().type()) { + case json::value_t::array: + dependencies_.emplace(dep.key(), + std::make_shared( + dep.value().get>(), root)); + break; + + default: + dependencies_.emplace(dep.key(), + schema::make(dep.value(), root, {"dependencies", dep.key()}, uris)); + break; + } + sch.erase(attr); + } + + attr = sch.find("propertyNames"); + if (attr != sch.end()) { + propertyNames_ = schema::make(attr.value(), root, {"propertyNames"}, uris); + sch.erase(attr); + } + + attr = sch.find("default"); + if (attr != sch.end()) { + set_default_value(*attr); + } + } +}; + +class array : public schema +{ + std::pair maxItems_{false, 0}; + std::pair minItems_{false, 0}; + bool uniqueItems_ = false; + + std::shared_ptr items_schema_; + + std::vector> items_; + std::shared_ptr additionalItems_; + + std::shared_ptr contains_; + + void validate(const json::json_pointer &ptr, const json &instance, json_patch &patch, error_handler &e) const override + { + if (maxItems_.first && instance.size() > maxItems_.second) + e.error(ptr, instance, "array has too many items"); + + if (minItems_.first && instance.size() < minItems_.second) + e.error(ptr, instance, "array has too few items"); + + if (uniqueItems_) { + for (auto it = instance.cbegin(); it != instance.cend(); ++it) { + auto v = std::find(it + 1, instance.end(), *it); + if (v != instance.end()) + e.error(ptr, instance, "items have to be unique for this array"); + } + } + + size_t index = 0; + if (items_schema_) + for (auto &i : instance) { + items_schema_->validate(ptr / index, i, patch, e); + index++; + } + else { + auto item = items_.cbegin(); + for (auto &i : instance) { + std::shared_ptr item_validator; + if (item == items_.cend()) + item_validator = additionalItems_; + else { + item_validator = *item; + item++; + } + + if (!item_validator) + break; + + item_validator->validate(ptr / index, i, patch, e); + } + } + + if (contains_) { + bool contained = false; + for (auto &item : instance) { + first_error_handler local_e; + contains_->validate(ptr, item, patch, local_e); + if (!local_e) { + contained = true; + break; + } + } + if (!contained) + e.error(ptr, instance, "array does not contain required element as per 'contains'"); + } + } + +public: + array(json &sch, root_schema *root, const std::vector &uris) + : schema(root) + { + auto attr = sch.find("maxItems"); + if (attr != sch.end()) { + maxItems_ = {true, attr.value().get()}; + sch.erase(attr); + } + + attr = sch.find("minItems"); + if (attr != sch.end()) { + minItems_ = {true, attr.value().get()}; + sch.erase(attr); + } + + attr = sch.find("uniqueItems"); + if (attr != sch.end()) { + uniqueItems_ = attr.value().get(); + sch.erase(attr); + } + + attr = sch.find("items"); + if (attr != sch.end()) { + + if (attr.value().type() == json::value_t::array) { + size_t c = 0; + for (auto &subsch : attr.value()) + items_.push_back(schema::make(subsch, root, {"items", std::to_string(c++)}, uris)); + + auto attr_add = sch.find("additionalItems"); + if (attr_add != sch.end()) { + additionalItems_ = schema::make(attr_add.value(), root, {"additionalItems"}, uris); + sch.erase(attr_add); + } + + } else if (attr.value().type() == json::value_t::object || + attr.value().type() == json::value_t::boolean) + items_schema_ = schema::make(attr.value(), root, {"items"}, uris); + + sch.erase(attr); + } + + attr = sch.find("contains"); + if (attr != sch.end()) { + contains_ = schema::make(attr.value(), root, {"contains"}, uris); + sch.erase(attr); + } + } +}; + +std::shared_ptr type_schema::make(json &schema, + json::value_t type, + root_schema *root, + const std::vector &uris, + std::set &kw) +{ + switch (type) { + case json::value_t::null: + return std::make_shared(schema, root); + + case json::value_t::number_unsigned: + case json::value_t::number_integer: + return std::make_shared>(schema, root, kw); + case json::value_t::number_float: + return std::make_shared>(schema, root, kw); + case json::value_t::string: + return std::make_shared(schema, root); + case json::value_t::boolean: + return std::make_shared(schema, root); + case json::value_t::object: + return std::make_shared(schema, root, uris); + case json::value_t::array: + return std::make_shared(schema, root, uris); + + case json::value_t::discarded: // not a real type - silence please + break; + + case json::value_t::binary: + break; + } + return nullptr; +} +} // namespace + +namespace +{ + +std::shared_ptr schema::make(json &schema, + root_schema *root, + const std::vector &keys, + std::vector uris) +{ + // remove URIs which contain plain name identifiers, as sub-schemas cannot be referenced + for (auto uri = uris.begin(); uri != uris.end();) + if (uri->identifier() != "") + uri = uris.erase(uri); + else + uri++; + + // append to all URIs the keys for this sub-schema + for (auto &key : keys) + for (auto &uri : uris) + uri = uri.append(key); + + std::shared_ptr<::schema> sch; + + // boolean schema + if (schema.type() == json::value_t::boolean) + sch = std::make_shared(schema, root); + else if (schema.type() == json::value_t::object) { + + auto attr = schema.find("$id"); // if $id is present, this schema can be referenced by this ID + // as an additional URI + if (attr != schema.end()) { + if (std::find(uris.begin(), + uris.end(), + attr.value().get()) == uris.end()) + uris.push_back(uris.back().derive(attr.value().get())); // so add it to the list if it is not there already + schema.erase(attr); + } + + auto findDefinitions = [&](const std::string &defs) -> bool { + attr = schema.find(defs); + if (attr != schema.end()) { + for (auto &def : attr.value().items()) + schema::make(def.value(), root, {defs, def.key()}, uris); + schema.erase(attr); + return true; + } + return false; + }; + if (!findDefinitions("$defs")) { + findDefinitions("definitions"); + } + + attr = schema.find("$ref"); + if (attr != schema.end()) { // this schema is a reference + // the last one on the uri-stack is the last id seen before coming here, + // so this is the origial URI for this reference, the $ref-value has thus be resolved from it + auto id = uris.back().derive(attr.value().get()); + sch = root->get_or_create_ref(id); + + schema.erase(attr); + + // special case where we break draft-7 and allow overriding of properties when a $ref is used + attr = schema.find("default"); + if (attr != schema.end()) { + // copy the referenced schema depending on the underlying type and modify the default value + if (auto new_sch = sch->make_for_default_(sch, root, uris, attr.value())) { + sch = new_sch; + } + schema.erase(attr); + } + } else { + sch = std::make_shared(schema, root, uris); + } + + schema.erase("$schema"); + schema.erase("title"); + schema.erase("description"); + } else { + throw std::invalid_argument("invalid JSON-type for a schema for " + uris[0].to_string() + ", expected: boolean or object"); + } + + for (auto &uri : uris) { // for all URIs this schema is referenced by + root->insert(uri, sch); + + if (schema.type() == json::value_t::object) + for (auto &u : schema.items()) + root->insert_unknown_keyword(uri, u.key(), u.value()); // insert unknown keywords for later reference + } + return sch; +} + +class throwing_error_handler : public error_handler +{ + void error(const json::json_pointer &ptr, const json &instance, const std::string &message) override + { + throw std::invalid_argument(std::string("At ") + ptr.to_string() + " of " + instance.dump() + " - " + message + "\n"); + } +}; + +} // namespace + +namespace nlohmann +{ +namespace json_schema +{ + +json_validator::json_validator(schema_loader loader, + format_checker format, + content_checker content) + : root_(std::unique_ptr(new root_schema(std::move(loader), + std::move(format), + std::move(content)))) +{ +} + +json_validator::json_validator(const json &schema, + schema_loader loader, + format_checker format, + content_checker content) + : json_validator(std::move(loader), + std::move(format), + std::move(content)) +{ + set_root_schema(schema); +} + +json_validator::json_validator(json &&schema, + schema_loader loader, + format_checker format, + content_checker content) + + : json_validator(std::move(loader), + std::move(format), + std::move(content)) +{ + set_root_schema(std::move(schema)); +} + +// move constructor, destructor and move assignment operator can be defaulted here +// where root_schema is a complete type +json_validator::json_validator(json_validator &&) = default; +json_validator::~json_validator() = default; +json_validator &json_validator::operator=(json_validator &&) = default; + +void json_validator::set_root_schema(const json &schema) +{ + root_->set_root_schema(schema); +} + +void json_validator::set_root_schema(json &&schema) +{ + root_->set_root_schema(std::move(schema)); +} + +json json_validator::validate(const json &instance) const +{ + throwing_error_handler err; + return validate(instance, err); +} + +json json_validator::validate(const json &instance, error_handler &err, const json_uri &initial_uri) const +{ + json::json_pointer ptr; + json_patch patch; + root_->validate(ptr, instance, patch, err, initial_uri); + return patch; +} + +} // namespace json_schema +} // namespace nlohmann diff --git a/lib/All/json-schema-validator/src/nlohmann/json-schema.hpp b/lib/All/json-schema-validator/src/nlohmann/json-schema.hpp new file mode 100644 index 0000000..07befd3 --- /dev/null +++ b/lib/All/json-schema-validator/src/nlohmann/json-schema.hpp @@ -0,0 +1,198 @@ +/* + * JSON schema validator for JSON for modern C++ + * + * Copyright (c) 2016-2019 Patrick Boettcher . + * + * SPDX-License-Identifier: MIT + * + */ +#ifndef NLOHMANN_JSON_SCHEMA_HPP__ +#define NLOHMANN_JSON_SCHEMA_HPP__ + +#ifdef _WIN32 +# if defined(JSON_SCHEMA_VALIDATOR_EXPORTS) +# define JSON_SCHEMA_VALIDATOR_API __declspec(dllexport) +# elif defined(JSON_SCHEMA_VALIDATOR_IMPORTS) +# define JSON_SCHEMA_VALIDATOR_API __declspec(dllimport) +# else +# define JSON_SCHEMA_VALIDATOR_API +# endif +#else +# define JSON_SCHEMA_VALIDATOR_API +#endif + +#include + +#ifdef NLOHMANN_JSON_VERSION_MAJOR +# if (NLOHMANN_JSON_VERSION_MAJOR * 10000 + NLOHMANN_JSON_VERSION_MINOR * 100 + NLOHMANN_JSON_VERSION_PATCH) < 30800 +# error "Please use this library with NLohmann's JSON version 3.8.0 or higher" +# endif +#else +# error "expected existing NLOHMANN_JSON_VERSION_MAJOR preproc variable, please update to NLohmann's JSON 3.8.0" +#endif + +// make yourself a home - welcome to nlohmann's namespace +namespace nlohmann +{ + +// A class representing a JSON-URI for schemas derived from +// section 8 of JSON Schema: A Media Type for Describing JSON Documents +// draft-wright-json-schema-00 +// +// New URIs can be derived from it using the derive()-method. +// This is useful for resolving refs or subschema-IDs in json-schemas. +// +// This is done implement the requirements described in section 8.2. +// +class JSON_SCHEMA_VALIDATOR_API json_uri +{ + std::string urn_; + + std::string scheme_; + std::string authority_; + std::string path_; + + json::json_pointer pointer_; // fragment part if JSON-Pointer + std::string identifier_; // fragment part if Locatation Independent ID + +protected: + // decodes a JSON uri and replaces all or part of the currently stored values + void update(const std::string &uri); + + std::tuple as_tuple() const + { + return std::make_tuple(urn_, scheme_, authority_, path_, identifier_ != "" ? identifier_ : pointer_.to_string()); + } + +public: + json_uri(const std::string &uri) + { + update(uri); + } + + const std::string &scheme() const { return scheme_; } + const std::string &authority() const { return authority_; } + const std::string &path() const { return path_; } + + const json::json_pointer &pointer() const { return pointer_; } + const std::string &identifier() const { return identifier_; } + + std::string fragment() const + { + if (identifier_ == "") + return pointer_.to_string(); + else + return identifier_; + } + + std::string url() const { return location(); } + std::string location() const; + + static std::string escape(const std::string &); + + // create a new json_uri based in this one and the given uri + // resolves relative changes (pathes or pointers) and resets part if proto or hostname changes + json_uri derive(const std::string &uri) const + { + json_uri u = *this; + u.update(uri); + return u; + } + + // append a pointer-field to the pointer-part of this uri + json_uri append(const std::string &field) const + { + if (identifier_ != "") + return *this; + + json_uri u = *this; + u.pointer_ /= field; + return u; + } + + std::string to_string() const; + + friend bool operator<(const json_uri &l, const json_uri &r) + { + return l.as_tuple() < r.as_tuple(); + } + + friend bool operator==(const json_uri &l, const json_uri &r) + { + return l.as_tuple() == r.as_tuple(); + } + + friend std::ostream &operator<<(std::ostream &os, const json_uri &u); +}; + +namespace json_schema +{ + +extern json draft7_schema_builtin; + +typedef std::function schema_loader; +typedef std::function format_checker; +typedef std::function content_checker; + +// Interface for validation error handlers +class JSON_SCHEMA_VALIDATOR_API error_handler +{ +public: + virtual ~error_handler() {} + virtual void error(const json::json_pointer & /*ptr*/, const json & /*instance*/, const std::string & /*message*/) = 0; +}; + +class JSON_SCHEMA_VALIDATOR_API basic_error_handler : public error_handler +{ + bool error_{false}; + +public: + void error(const json::json_pointer & /*ptr*/, const json & /*instance*/, const std::string & /*message*/) override + { + error_ = true; + } + + virtual void reset() { error_ = false; } + operator bool() const { return error_; } +}; + +/** + * Checks validity of JSON schema built-in string format specifiers like 'date-time', 'ipv4', ... + */ +void JSON_SCHEMA_VALIDATOR_API default_string_format_check(const std::string &format, const std::string &value); + +class root_schema; + +class JSON_SCHEMA_VALIDATOR_API json_validator +{ + std::unique_ptr root_; + +public: + json_validator(schema_loader = nullptr, format_checker = nullptr, content_checker = nullptr); + + json_validator(const json &, schema_loader = nullptr, format_checker = nullptr, content_checker = nullptr); + json_validator(json &&, schema_loader = nullptr, format_checker = nullptr, content_checker = nullptr); + + json_validator(json_validator &&); + json_validator &operator=(json_validator &&); + + json_validator(json_validator const &) = delete; + json_validator &operator=(json_validator const &) = delete; + + ~json_validator(); + + // insert and set the root-schema + void set_root_schema(const json &); + void set_root_schema(json &&); + + // validate a json-document based on the root-schema + json validate(const json &) const; + + // validate a json-document based on the root-schema with a custom error-handler + json validate(const json &, error_handler &, const json_uri &initial_uri = json_uri("#")) const; +}; + +} // namespace json_schema +} // namespace nlohmann + +#endif /* NLOHMANN_JSON_SCHEMA_HPP__ */ diff --git a/lib/All/json-schema-validator/src/smtp-address-validator.cpp b/lib/All/json-schema-validator/src/smtp-address-validator.cpp new file mode 100644 index 0000000..3b4a461 --- /dev/null +++ b/lib/All/json-schema-validator/src/smtp-address-validator.cpp @@ -0,0 +1,792 @@ +/* + +Snarfed from + +: + +Copyright (c) 2021 Gene Hightower + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +#include "smtp-address-validator.hpp" + +static const signed char _address_actions[] = { + 0, 1, 0, 1, 1, 0}; + +static const short _address_key_offsets[] = { + 0, 0, 24, 26, 50, 52, 54, 56, + 58, 60, 62, 86, 103, 105, 107, 109, + 111, 113, 115, 117, 134, 150, 161, 168, + 176, 180, 181, 190, 195, 196, 201, 202, + 207, 210, 213, 219, 222, 225, 228, 234, + 237, 240, 243, 249, 252, 261, 270, 282, + 293, 302, 311, 320, 328, 345, 353, 360, + 367, 368, 375, 382, 389, 396, 397, 404, + 411, 418, 425, 426, 433, 440, 447, 454, + 455, 462, 469, 476, 483, 484, 491, 498, + 505, 512, 513, 523, 531, 538, 545, 546, + 552, 559, 566, 573, 581, 589, 597, 608, + 618, 626, 634, 641, 649, 657, 665, 667, + 673, 681, 689, 697, 699, 705, 713, 721, + 729, 731, 737, 745, 753, 761, 763, 769, + 777, 785, 793, 795, 802, 812, 821, 829, + 837, 839, 848, 857, 865, 873, 875, 884, + 893, 901, 909, 911, 920, 929, 937, 945, + 947, 956, 965, 974, 983, 992, 1004, 1015, + 1024, 1033, 1042, 1051, 1060, 1072, 1083, 1092, + 1101, 1109, 1118, 1127, 1136, 1148, 1159, 1168, + 1177, 1185, 1194, 1203, 1212, 1224, 1235, 1244, + 1253, 1261, 1270, 1279, 1288, 1300, 1311, 1320, + 1329, 1337, 1339, 1353, 1355, 1357, 1359, 1361, + 1363, 1365, 1367, 1368, 1370, 1388, 0}; + +static const signed char _address_trans_keys[] = { + -32, -19, -16, -12, 34, 45, 61, 63, + -62, -33, -31, -17, -15, -13, 33, 39, + 42, 43, 47, 57, 65, 90, 94, 126, + -128, -65, -32, -19, -16, -12, 33, 46, + 61, 64, -62, -33, -31, -17, -15, -13, + 35, 39, 42, 43, 45, 57, 63, 90, + 94, 126, -96, -65, -128, -65, -128, -97, + -112, -65, -128, -65, -128, -113, -32, -19, + -16, -12, 33, 45, 61, 63, -62, -33, + -31, -17, -15, -13, 35, 39, 42, 43, + 47, 57, 65, 90, 94, 126, -32, -19, + -16, -12, 91, -62, -33, -31, -17, -15, + -13, 48, 57, 65, 90, 97, 122, -128, + -65, -96, -65, -128, -65, -128, -97, -112, + -65, -128, -65, -128, -113, -32, -19, -16, + -12, 45, -62, -33, -31, -17, -15, -13, + 48, 57, 65, 90, 97, 122, -32, -19, + -16, -12, -62, -33, -31, -17, -15, -13, + 48, 57, 65, 90, 97, 122, 45, 48, + 49, 50, 73, 51, 57, 65, 90, 97, + 122, 45, 48, 57, 65, 90, 97, 122, + 45, 58, 48, 57, 65, 90, 97, 122, + 33, 90, 94, 126, 93, 45, 46, 58, + 48, 57, 65, 90, 97, 122, 48, 49, + 50, 51, 57, 46, 48, 49, 50, 51, + 57, 46, 48, 49, 50, 51, 57, 93, + 48, 57, 93, 48, 57, 53, 93, 48, + 52, 54, 57, 93, 48, 53, 46, 48, + 57, 46, 48, 57, 46, 53, 48, 52, + 54, 57, 46, 48, 53, 46, 48, 57, + 46, 48, 57, 46, 53, 48, 52, 54, + 57, 46, 48, 53, 45, 46, 58, 48, + 57, 65, 90, 97, 122, 45, 46, 58, + 48, 57, 65, 90, 97, 122, 45, 46, + 53, 58, 48, 52, 54, 57, 65, 90, + 97, 122, 45, 46, 58, 48, 53, 54, + 57, 65, 90, 97, 122, 45, 58, 80, + 48, 57, 65, 90, 97, 122, 45, 58, + 118, 48, 57, 65, 90, 97, 122, 45, + 54, 58, 48, 57, 65, 90, 97, 122, + 45, 58, 48, 57, 65, 90, 97, 122, + 58, 33, 47, 48, 57, 59, 64, 65, + 70, 71, 90, 94, 96, 97, 102, 103, + 126, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 48, 57, 65, 70, 97, 102, + 58, 48, 57, 65, 70, 97, 102, 58, + 58, 48, 57, 65, 70, 97, 102, 58, + 48, 57, 65, 70, 97, 102, 58, 48, + 57, 65, 70, 97, 102, 58, 48, 57, + 65, 70, 97, 102, 58, 58, 48, 57, + 65, 70, 97, 102, 58, 48, 57, 65, + 70, 97, 102, 58, 48, 57, 65, 70, + 97, 102, 58, 48, 57, 65, 70, 97, + 102, 58, 58, 48, 57, 65, 70, 97, + 102, 58, 48, 57, 65, 70, 97, 102, + 58, 48, 57, 65, 70, 97, 102, 58, + 48, 57, 65, 70, 97, 102, 58, 58, + 48, 57, 65, 70, 97, 102, 58, 48, + 57, 65, 70, 97, 102, 58, 48, 57, + 65, 70, 97, 102, 58, 48, 57, 65, + 70, 97, 102, 58, 58, 48, 57, 65, + 70, 97, 102, 58, 48, 57, 65, 70, + 97, 102, 58, 48, 57, 65, 70, 97, + 102, 58, 48, 57, 65, 70, 97, 102, + 58, 48, 49, 50, 58, 51, 57, 65, + 70, 97, 102, 46, 58, 48, 57, 65, + 70, 97, 102, 58, 48, 57, 65, 70, + 97, 102, 58, 48, 57, 65, 70, 97, + 102, 58, 48, 57, 65, 70, 97, 102, + 93, 48, 57, 65, 70, 97, 102, 93, + 48, 57, 65, 70, 97, 102, 93, 48, + 57, 65, 70, 97, 102, 46, 58, 48, + 57, 65, 70, 97, 102, 46, 58, 48, + 57, 65, 70, 97, 102, 46, 58, 48, + 57, 65, 70, 97, 102, 46, 53, 58, + 48, 52, 54, 57, 65, 70, 97, 102, + 46, 58, 48, 53, 54, 57, 65, 70, + 97, 102, 46, 58, 48, 57, 65, 70, + 97, 102, 46, 58, 48, 57, 65, 70, + 97, 102, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 58, 48, 57, 65, 70, + 97, 102, 48, 49, 50, 93, 51, 57, + 65, 70, 97, 102, 46, 58, 93, 48, + 57, 65, 70, 97, 102, 58, 93, 48, + 57, 65, 70, 97, 102, 58, 93, 48, + 57, 65, 70, 97, 102, 58, 93, 48, + 49, 50, 51, 57, 65, 70, 97, 102, + 46, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 49, 50, 51, 57, + 65, 70, 97, 102, 46, 58, 93, 48, + 57, 65, 70, 97, 102, 58, 93, 48, + 57, 65, 70, 97, 102, 58, 93, 48, + 57, 65, 70, 97, 102, 58, 93, 48, + 49, 50, 51, 57, 65, 70, 97, 102, + 46, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 49, 50, 51, 57, + 65, 70, 97, 102, 46, 58, 93, 48, + 57, 65, 70, 97, 102, 46, 58, 93, + 48, 57, 65, 70, 97, 102, 46, 58, + 93, 48, 57, 65, 70, 97, 102, 46, + 58, 93, 48, 57, 65, 70, 97, 102, + 46, 53, 58, 93, 48, 52, 54, 57, + 65, 70, 97, 102, 46, 58, 93, 48, + 53, 54, 57, 65, 70, 97, 102, 46, + 58, 93, 48, 57, 65, 70, 97, 102, + 46, 58, 93, 48, 57, 65, 70, 97, + 102, 46, 58, 93, 48, 57, 65, 70, + 97, 102, 46, 58, 93, 48, 57, 65, + 70, 97, 102, 46, 58, 93, 48, 57, + 65, 70, 97, 102, 46, 53, 58, 93, + 48, 52, 54, 57, 65, 70, 97, 102, + 46, 58, 93, 48, 53, 54, 57, 65, + 70, 97, 102, 46, 58, 93, 48, 57, + 65, 70, 97, 102, 46, 58, 93, 48, + 57, 65, 70, 97, 102, 58, 93, 48, + 57, 65, 70, 97, 102, 46, 58, 93, + 48, 57, 65, 70, 97, 102, 46, 58, + 93, 48, 57, 65, 70, 97, 102, 46, + 58, 93, 48, 57, 65, 70, 97, 102, + 46, 53, 58, 93, 48, 52, 54, 57, + 65, 70, 97, 102, 46, 58, 93, 48, + 53, 54, 57, 65, 70, 97, 102, 46, + 58, 93, 48, 57, 65, 70, 97, 102, + 46, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 46, 58, 93, 48, 57, 65, 70, + 97, 102, 46, 58, 93, 48, 57, 65, + 70, 97, 102, 46, 58, 93, 48, 57, + 65, 70, 97, 102, 46, 53, 58, 93, + 48, 52, 54, 57, 65, 70, 97, 102, + 46, 58, 93, 48, 53, 54, 57, 65, + 70, 97, 102, 46, 58, 93, 48, 57, + 65, 70, 97, 102, 46, 58, 93, 48, + 57, 65, 70, 97, 102, 58, 93, 48, + 57, 65, 70, 97, 102, 46, 58, 93, + 48, 57, 65, 70, 97, 102, 46, 58, + 93, 48, 57, 65, 70, 97, 102, 46, + 58, 93, 48, 57, 65, 70, 97, 102, + 46, 53, 58, 93, 48, 52, 54, 57, + 65, 70, 97, 102, 46, 58, 93, 48, + 53, 54, 57, 65, 70, 97, 102, 46, + 58, 93, 48, 57, 65, 70, 97, 102, + 46, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, 48, 57, 65, 70, 97, + 102, 58, 93, -32, -19, -16, -12, 34, + 92, -62, -33, -31, -17, -15, -13, 32, + 126, -128, -65, -96, -65, -128, -65, -128, + -97, -112, -65, -128, -65, -128, -113, 64, + 32, 126, -32, -19, -16, -12, 45, 46, + -62, -33, -31, -17, -15, -13, 48, 57, + 65, 90, 97, 122, 0}; + +static const signed char _address_single_lengths[] = { + 0, 8, 0, 8, 0, 0, 0, 0, + 0, 0, 8, 5, 0, 0, 0, 0, + 0, 0, 0, 5, 4, 5, 1, 2, + 0, 1, 3, 3, 1, 3, 1, 3, + 1, 1, 2, 1, 1, 1, 2, 1, + 1, 1, 2, 1, 3, 3, 4, 3, + 3, 3, 3, 2, 1, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 4, 2, 1, 1, 1, 0, + 1, 1, 1, 2, 2, 2, 3, 2, + 2, 2, 1, 2, 2, 2, 2, 0, + 2, 2, 2, 2, 0, 2, 2, 2, + 2, 0, 2, 2, 2, 2, 0, 2, + 2, 2, 2, 1, 4, 3, 2, 2, + 2, 3, 3, 2, 2, 2, 3, 3, + 2, 2, 2, 3, 3, 2, 2, 2, + 3, 3, 3, 3, 3, 4, 3, 3, + 3, 3, 3, 3, 4, 3, 3, 3, + 2, 3, 3, 3, 4, 3, 3, 3, + 2, 3, 3, 3, 4, 3, 3, 3, + 2, 3, 3, 3, 4, 3, 3, 3, + 2, 2, 6, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 6, 0, 0}; + +static const signed char _address_range_lengths[] = { + 0, 8, 1, 8, 1, 1, 1, 1, + 1, 1, 8, 6, 1, 1, 1, 1, + 1, 1, 1, 6, 6, 3, 3, 3, + 2, 0, 3, 1, 0, 1, 0, 1, + 1, 1, 2, 1, 1, 1, 2, 1, + 1, 1, 2, 1, 3, 3, 4, 4, + 3, 3, 3, 3, 8, 3, 3, 3, + 0, 3, 3, 3, 3, 0, 3, 3, + 3, 3, 0, 3, 3, 3, 3, 0, + 3, 3, 3, 3, 0, 3, 3, 3, + 3, 0, 3, 3, 3, 3, 0, 3, + 3, 3, 3, 3, 3, 3, 4, 4, + 3, 3, 3, 3, 3, 3, 0, 3, + 3, 3, 3, 0, 3, 3, 3, 3, + 0, 3, 3, 3, 3, 0, 3, 3, + 3, 3, 0, 3, 3, 3, 3, 3, + 0, 3, 3, 3, 3, 0, 3, 3, + 3, 3, 0, 3, 3, 3, 3, 0, + 3, 3, 3, 3, 3, 4, 4, 3, + 3, 3, 3, 3, 4, 4, 3, 3, + 3, 3, 3, 3, 4, 4, 3, 3, + 3, 3, 3, 3, 4, 4, 3, 3, + 3, 3, 3, 3, 4, 4, 3, 3, + 3, 0, 4, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 6, 0, 0}; + +static const short _address_index_offsets[] = { + 0, 0, 17, 19, 36, 38, 40, 42, + 44, 46, 48, 65, 77, 79, 81, 83, + 85, 87, 89, 91, 103, 114, 123, 128, + 134, 137, 139, 146, 151, 153, 158, 160, + 165, 168, 171, 176, 179, 182, 185, 190, + 193, 196, 199, 204, 207, 214, 221, 230, + 238, 245, 252, 259, 265, 275, 281, 286, + 291, 293, 298, 303, 308, 313, 315, 320, + 325, 330, 335, 337, 342, 347, 352, 357, + 359, 364, 369, 374, 379, 381, 386, 391, + 396, 401, 403, 411, 417, 422, 427, 429, + 433, 438, 443, 448, 454, 460, 466, 474, + 481, 487, 493, 498, 504, 510, 516, 519, + 523, 529, 535, 541, 544, 548, 554, 560, + 566, 569, 573, 579, 585, 591, 594, 598, + 604, 610, 616, 619, 624, 632, 639, 645, + 651, 654, 661, 668, 674, 680, 683, 690, + 697, 703, 709, 712, 719, 726, 732, 738, + 741, 748, 755, 762, 769, 776, 785, 793, + 800, 807, 814, 821, 828, 837, 845, 852, + 859, 865, 872, 879, 886, 895, 903, 910, + 917, 923, 930, 937, 944, 953, 961, 968, + 975, 981, 988, 995, 1002, 1011, 1019, 1026, + 1033, 1039, 1042, 1053, 1055, 1057, 1059, 1061, + 1063, 1065, 1067, 1069, 1071, 1084, 0}; + +static const short _address_cond_targs[] = { + 4, 6, 7, 9, 186, 3, 3, 3, + 2, 5, 8, 3, 3, 3, 3, 3, + 0, 3, 0, 4, 6, 7, 9, 3, + 10, 3, 11, 2, 5, 8, 3, 3, + 3, 3, 3, 0, 2, 0, 2, 0, + 2, 0, 5, 0, 5, 0, 5, 0, + 4, 6, 7, 9, 3, 3, 3, 3, + 2, 5, 8, 3, 3, 3, 3, 3, + 0, 13, 15, 16, 18, 21, 12, 14, + 17, 196, 196, 196, 0, 196, 0, 12, + 0, 12, 0, 12, 0, 14, 0, 14, + 0, 14, 0, 13, 15, 16, 18, 19, + 12, 14, 17, 196, 196, 196, 0, 13, + 15, 16, 18, 12, 14, 17, 196, 196, + 196, 0, 22, 26, 44, 46, 48, 45, + 23, 23, 0, 22, 23, 23, 23, 0, + 22, 24, 23, 23, 23, 0, 25, 25, + 0, 197, 0, 22, 27, 24, 23, 23, + 23, 0, 28, 40, 42, 41, 0, 29, + 0, 30, 36, 38, 37, 0, 31, 0, + 25, 32, 34, 33, 0, 197, 33, 0, + 197, 25, 0, 35, 197, 33, 25, 0, + 197, 25, 0, 31, 37, 0, 31, 30, + 0, 31, 39, 37, 30, 0, 31, 30, + 0, 29, 41, 0, 29, 28, 0, 29, + 43, 41, 28, 0, 29, 28, 0, 22, + 27, 24, 45, 23, 23, 0, 22, 27, + 24, 26, 23, 23, 0, 22, 27, 47, + 24, 45, 26, 23, 23, 0, 22, 27, + 24, 26, 23, 23, 23, 0, 22, 24, + 49, 23, 23, 23, 0, 22, 24, 50, + 23, 23, 23, 0, 22, 51, 24, 23, + 23, 23, 0, 22, 52, 23, 23, 23, + 0, 185, 25, 53, 25, 53, 25, 25, + 53, 25, 0, 57, 197, 54, 54, 54, + 0, 57, 55, 55, 55, 0, 57, 56, + 56, 56, 0, 57, 0, 124, 58, 58, + 58, 0, 62, 59, 59, 59, 0, 62, + 60, 60, 60, 0, 62, 61, 61, 61, + 0, 62, 0, 124, 63, 63, 63, 0, + 67, 64, 64, 64, 0, 67, 65, 65, + 65, 0, 67, 66, 66, 66, 0, 67, + 0, 124, 68, 68, 68, 0, 72, 69, + 69, 69, 0, 72, 70, 70, 70, 0, + 72, 71, 71, 71, 0, 72, 0, 124, + 73, 73, 73, 0, 77, 74, 74, 74, + 0, 77, 75, 75, 75, 0, 77, 76, + 76, 76, 0, 77, 0, 98, 78, 78, + 78, 0, 82, 79, 79, 79, 0, 82, + 80, 80, 80, 0, 82, 81, 81, 81, + 0, 82, 0, 83, 91, 94, 98, 97, + 123, 123, 0, 27, 87, 84, 84, 84, + 0, 87, 85, 85, 85, 0, 87, 86, + 86, 86, 0, 87, 0, 88, 88, 88, + 0, 197, 89, 89, 89, 0, 197, 90, + 90, 90, 0, 197, 25, 25, 25, 0, + 27, 87, 92, 84, 84, 0, 27, 87, + 93, 85, 85, 0, 27, 87, 86, 86, + 86, 0, 27, 95, 87, 92, 96, 84, + 84, 0, 27, 87, 93, 85, 85, 85, + 0, 27, 87, 85, 85, 85, 0, 27, + 87, 96, 84, 84, 0, 197, 99, 99, + 99, 0, 103, 197, 100, 100, 100, 0, + 103, 197, 101, 101, 101, 0, 103, 197, + 102, 102, 102, 0, 103, 197, 0, 104, + 104, 104, 0, 108, 197, 105, 105, 105, + 0, 108, 197, 106, 106, 106, 0, 108, + 197, 107, 107, 107, 0, 108, 197, 0, + 109, 109, 109, 0, 113, 197, 110, 110, + 110, 0, 113, 197, 111, 111, 111, 0, + 113, 197, 112, 112, 112, 0, 113, 197, + 0, 114, 114, 114, 0, 118, 197, 115, + 115, 115, 0, 118, 197, 116, 116, 116, + 0, 118, 197, 117, 117, 117, 0, 118, + 197, 0, 119, 119, 119, 0, 87, 197, + 120, 120, 120, 0, 87, 197, 121, 121, + 121, 0, 87, 197, 122, 122, 122, 0, + 87, 197, 0, 87, 84, 84, 84, 0, + 125, 177, 180, 197, 183, 184, 184, 0, + 27, 129, 197, 126, 126, 126, 0, 129, + 197, 127, 127, 127, 0, 129, 197, 128, + 128, 128, 0, 129, 197, 0, 130, 169, + 172, 175, 176, 176, 0, 27, 134, 197, + 131, 131, 131, 0, 134, 197, 132, 132, + 132, 0, 134, 197, 133, 133, 133, 0, + 134, 197, 0, 135, 161, 164, 167, 168, + 168, 0, 27, 139, 197, 136, 136, 136, + 0, 139, 197, 137, 137, 137, 0, 139, + 197, 138, 138, 138, 0, 139, 197, 0, + 140, 153, 156, 159, 160, 160, 0, 27, + 144, 197, 141, 141, 141, 0, 144, 197, + 142, 142, 142, 0, 144, 197, 143, 143, + 143, 0, 144, 197, 0, 145, 146, 149, + 152, 119, 119, 0, 27, 87, 197, 120, + 120, 120, 0, 27, 87, 197, 147, 120, + 120, 0, 27, 87, 197, 148, 121, 121, + 0, 27, 87, 197, 122, 122, 122, 0, + 27, 150, 87, 197, 147, 151, 120, 120, + 0, 27, 87, 197, 148, 121, 121, 121, + 0, 27, 87, 197, 121, 121, 121, 0, + 27, 87, 197, 151, 120, 120, 0, 27, + 144, 197, 154, 141, 141, 0, 27, 144, + 197, 155, 142, 142, 0, 27, 144, 197, + 143, 143, 143, 0, 27, 157, 144, 197, + 154, 158, 141, 141, 0, 27, 144, 197, + 155, 142, 142, 142, 0, 27, 144, 197, + 142, 142, 142, 0, 27, 144, 197, 158, + 141, 141, 0, 144, 197, 141, 141, 141, + 0, 27, 139, 197, 162, 136, 136, 0, + 27, 139, 197, 163, 137, 137, 0, 27, + 139, 197, 138, 138, 138, 0, 27, 165, + 139, 197, 162, 166, 136, 136, 0, 27, + 139, 197, 163, 137, 137, 137, 0, 27, + 139, 197, 137, 137, 137, 0, 27, 139, + 197, 166, 136, 136, 0, 139, 197, 136, + 136, 136, 0, 27, 134, 197, 170, 131, + 131, 0, 27, 134, 197, 171, 132, 132, + 0, 27, 134, 197, 133, 133, 133, 0, + 27, 173, 134, 197, 170, 174, 131, 131, + 0, 27, 134, 197, 171, 132, 132, 132, + 0, 27, 134, 197, 132, 132, 132, 0, + 27, 134, 197, 174, 131, 131, 0, 134, + 197, 131, 131, 131, 0, 27, 129, 197, + 178, 126, 126, 0, 27, 129, 197, 179, + 127, 127, 0, 27, 129, 197, 128, 128, + 128, 0, 27, 181, 129, 197, 178, 182, + 126, 126, 0, 27, 129, 197, 179, 127, + 127, 127, 0, 27, 129, 197, 127, 127, + 127, 0, 27, 129, 197, 182, 126, 126, + 0, 129, 197, 126, 126, 126, 0, 124, + 197, 0, 188, 190, 191, 193, 194, 195, + 187, 189, 192, 186, 0, 186, 0, 187, + 0, 187, 0, 187, 0, 189, 0, 189, + 0, 189, 0, 11, 0, 186, 0, 13, + 15, 16, 18, 19, 20, 12, 14, 17, + 196, 196, 196, 0, 0, 0, 1, 2, + 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, + 123, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 141, 142, 143, 144, 145, 146, + 147, 148, 149, 150, 151, 152, 153, 154, + 155, 156, 157, 158, 159, 160, 161, 162, + 163, 164, 165, 166, 167, 168, 169, 170, + 171, 172, 173, 174, 175, 176, 177, 178, + 179, 180, 181, 182, 183, 184, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 0}; + +static const signed char _address_cond_actions[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 3, 0, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 0, 3, 0, 3, + 0, 3, 0, 3, 0, 3, 0, 3, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 3, 1, 3, 0, + 3, 0, 3, 0, 3, 0, 3, 0, + 3, 0, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 3, 0, + 0, 0, 0, 0, 0, 0, 1, 1, + 1, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, 0, 3, + 0, 0, 0, 0, 0, 3, 0, 0, + 3, 1, 3, 0, 0, 0, 0, 0, + 0, 3, 0, 0, 0, 0, 3, 0, + 3, 0, 0, 0, 0, 3, 0, 3, + 0, 0, 0, 0, 3, 1, 0, 3, + 1, 0, 3, 0, 1, 0, 0, 3, + 1, 0, 3, 0, 0, 3, 0, 0, + 3, 0, 0, 0, 0, 3, 0, 0, + 3, 0, 0, 3, 0, 0, 3, 0, + 0, 0, 0, 3, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 0, 3, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 3, 0, 3, 0, 0, 0, + 0, 3, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 3, 0, 0, 0, 0, + 3, 0, 3, 0, 0, 0, 0, 3, + 0, 0, 0, 0, 3, 0, 0, 0, + 0, 3, 0, 0, 0, 0, 3, 0, + 3, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 3, 0, 0, 0, 0, 3, + 0, 0, 0, 0, 3, 0, 3, 0, + 0, 0, 0, 3, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 3, 0, 3, 0, 0, 0, + 0, 3, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 3, 0, 0, 0, 0, + 3, 0, 3, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 3, 0, 3, 0, 0, 0, + 3, 1, 0, 0, 0, 3, 1, 0, + 0, 0, 3, 1, 0, 0, 0, 3, + 0, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 0, 3, 0, 0, 0, 0, + 0, 3, 0, 0, 0, 0, 0, 0, + 0, 3, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 3, 1, 0, 0, + 0, 3, 0, 1, 0, 0, 0, 3, + 0, 1, 0, 0, 0, 3, 0, 1, + 0, 0, 0, 3, 0, 1, 3, 0, + 0, 0, 3, 0, 1, 0, 0, 0, + 3, 0, 1, 0, 0, 0, 3, 0, + 1, 0, 0, 0, 3, 0, 1, 3, + 0, 0, 0, 3, 0, 1, 0, 0, + 0, 3, 0, 1, 0, 0, 0, 3, + 0, 1, 0, 0, 0, 3, 0, 1, + 3, 0, 0, 0, 3, 0, 1, 0, + 0, 0, 3, 0, 1, 0, 0, 0, + 3, 0, 1, 0, 0, 0, 3, 0, + 1, 3, 0, 0, 0, 3, 0, 1, + 0, 0, 0, 3, 0, 1, 0, 0, + 0, 3, 0, 1, 0, 0, 0, 3, + 0, 1, 3, 0, 0, 0, 0, 3, + 0, 0, 0, 1, 0, 0, 0, 3, + 0, 0, 1, 0, 0, 0, 3, 0, + 1, 0, 0, 0, 3, 0, 1, 0, + 0, 0, 3, 0, 1, 3, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 1, + 0, 0, 0, 3, 0, 1, 0, 0, + 0, 3, 0, 1, 0, 0, 0, 3, + 0, 1, 3, 0, 0, 0, 0, 0, + 0, 3, 0, 0, 1, 0, 0, 0, + 3, 0, 1, 0, 0, 0, 3, 0, + 1, 0, 0, 0, 3, 0, 1, 3, + 0, 0, 0, 0, 0, 0, 3, 0, + 0, 1, 0, 0, 0, 3, 0, 1, + 0, 0, 0, 3, 0, 1, 0, 0, + 0, 3, 0, 1, 3, 0, 0, 0, + 0, 0, 0, 3, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 1, 0, 0, + 0, 3, 0, 0, 1, 0, 0, 0, + 3, 0, 0, 1, 0, 0, 0, 3, + 0, 0, 0, 1, 0, 0, 0, 0, + 3, 0, 0, 1, 0, 0, 0, 0, + 3, 0, 0, 1, 0, 0, 0, 3, + 0, 0, 1, 0, 0, 0, 3, 0, + 0, 1, 0, 0, 0, 3, 0, 0, + 1, 0, 0, 0, 3, 0, 0, 1, + 0, 0, 0, 3, 0, 0, 0, 1, + 0, 0, 0, 0, 3, 0, 0, 1, + 0, 0, 0, 0, 3, 0, 0, 1, + 0, 0, 0, 3, 0, 0, 1, 0, + 0, 0, 3, 0, 1, 0, 0, 0, + 3, 0, 0, 1, 0, 0, 0, 3, + 0, 0, 1, 0, 0, 0, 3, 0, + 0, 1, 0, 0, 0, 3, 0, 0, + 0, 1, 0, 0, 0, 0, 3, 0, + 0, 1, 0, 0, 0, 0, 3, 0, + 0, 1, 0, 0, 0, 3, 0, 0, + 1, 0, 0, 0, 3, 0, 1, 0, + 0, 0, 3, 0, 0, 1, 0, 0, + 0, 3, 0, 0, 1, 0, 0, 0, + 3, 0, 0, 1, 0, 0, 0, 3, + 0, 0, 0, 1, 0, 0, 0, 0, + 3, 0, 0, 1, 0, 0, 0, 0, + 3, 0, 0, 1, 0, 0, 0, 3, + 0, 0, 1, 0, 0, 0, 3, 0, + 1, 0, 0, 0, 3, 0, 0, 1, + 0, 0, 0, 3, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 1, 0, 0, + 0, 3, 0, 0, 0, 1, 0, 0, + 0, 0, 3, 0, 0, 1, 0, 0, + 0, 0, 3, 0, 0, 1, 0, 0, + 0, 3, 0, 0, 1, 0, 0, 0, + 3, 0, 1, 0, 0, 0, 3, 0, + 1, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 3, 0, + 3, 0, 3, 0, 3, 0, 3, 0, + 3, 0, 3, 0, 3, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 3, 3, 0, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 0, 0, 0}; + +static const short _address_eof_trans[] = { + 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, + 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, + 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, + 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, + 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, + 1126, 1127, 1128, 1129, 1130, 1131, 1132, 1133, + 1134, 1135, 1136, 1137, 1138, 1139, 1140, 1141, + 1142, 1143, 1144, 1145, 1146, 1147, 1148, 1149, + 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, + 1158, 1159, 1160, 1161, 1162, 1163, 1164, 1165, + 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, + 1174, 1175, 1176, 1177, 1178, 1179, 1180, 1181, + 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, + 1190, 1191, 1192, 1193, 1194, 1195, 1196, 1197, + 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, + 1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213, + 1214, 1215, 1216, 1217, 1218, 1219, 1220, 1221, + 1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229, + 1230, 1231, 1232, 1233, 1234, 1235, 1236, 1237, + 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245, + 1246, 1247, 1248, 1249, 1250, 1251, 1252, 1253, + 1254, 1255, 1256, 1257, 1258, 1259, 1260, 1261, + 1262, 1263, 1264, 1265, 1266, 1267, 1268, 1269, + 1270, 1271, 1272, 1273, 1274, 1275, 1276, 1277, + 1278, 1279, 1280, 1281, 1282, 1283, 0}; + +static const int address_start = 1; + +bool is_address(const char *p, const char *pe) +{ + int cs = 0; + + const char *eof = pe; + + bool result = false; + + { + cs = (int) address_start; + } + { + int _klen; + unsigned int _trans = 0; + const signed char *_keys; + const signed char *_acts; + unsigned int _nacts; + _resume: { + } + if (p == pe && p != eof) + goto _out; + if (p == eof) { + if (_address_eof_trans[cs] > 0) { + _trans = (unsigned int) _address_eof_trans[cs] - 1; + } + } else { + _keys = (_address_trans_keys + (_address_key_offsets[cs])); + _trans = (unsigned int) _address_index_offsets[cs]; + + _klen = (int) _address_single_lengths[cs]; + if (_klen > 0) { + const signed char *_lower = _keys; + const signed char *_upper = _keys + _klen - 1; + const signed char *_mid; + while (1) { + if (_upper < _lower) { + _keys += _klen; + _trans += (unsigned int) _klen; + break; + } + + _mid = _lower + ((_upper - _lower) >> 1); + if (((*(p))) < (*(_mid))) + _upper = _mid - 1; + else if (((*(p))) > (*(_mid))) + _lower = _mid + 1; + else { + _trans += (unsigned int) (_mid - _keys); + goto _match; + } + } + } + + _klen = (int) _address_range_lengths[cs]; + if (_klen > 0) { + const signed char *_lower = _keys; + const signed char *_upper = _keys + (_klen << 1) - 2; + const signed char *_mid; + while (1) { + if (_upper < _lower) { + _trans += (unsigned int) _klen; + break; + } + + _mid = _lower + (((_upper - _lower) >> 1) & ~1); + if (((*(p))) < (*(_mid))) + _upper = _mid - 2; + else if (((*(p))) > (*(_mid + 1))) + _lower = _mid + 2; + else { + _trans += (unsigned int) ((_mid - _keys) >> 1); + break; + } + } + } + + _match: { + } + } + cs = (int) _address_cond_targs[_trans]; + + if (_address_cond_actions[_trans] != 0) { + + _acts = (_address_actions + (_address_cond_actions[_trans])); + _nacts = (unsigned int) (*(_acts)); + _acts += 1; + while (_nacts > 0) { + switch ((*(_acts))) { + case 0: { + { + result = true; + } + break; + } + case 1: { + { + result = false; + } + break; + } + } + _nacts -= 1; + _acts += 1; + } + } + + if (p == eof) { + if (cs >= 196) + goto _out; + } else { + if (cs != 0) { + p += 1; + goto _resume; + } + } + _out: { + } + } + return result; +} diff --git a/lib/All/json-schema-validator/src/smtp-address-validator.hpp b/lib/All/json-schema-validator/src/smtp-address-validator.hpp new file mode 100644 index 0000000..8d3c12b --- /dev/null +++ b/lib/All/json-schema-validator/src/smtp-address-validator.hpp @@ -0,0 +1,34 @@ +#ifndef SMTP_ADDRESS_PARSER_HPP_INCLUDED +#define SMTP_ADDRESS_PARSER_HPP_INCLUDED + +/* + +Snarfed from + +: + +Copyright (c) 2021 Gene Hightower + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +bool is_address(const char *p, const char *pe); + +#endif // SMTP_ADDRESS_PARSER_HPP_INCLUDED diff --git a/lib/All/json-schema-validator/src/string-format-check.cpp b/lib/All/json-schema-validator/src/string-format-check.cpp new file mode 100644 index 0000000..ecc428f --- /dev/null +++ b/lib/All/json-schema-validator/src/string-format-check.cpp @@ -0,0 +1,414 @@ +#include + +#include "smtp-address-validator.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef JSON_SCHEMA_BOOST_REGEX +# include +# define REGEX_NAMESPACE boost +#elif defined(JSON_SCHEMA_NO_REGEX) +# define NO_STD_REGEX +#else +# include +# define REGEX_NAMESPACE std +#endif + +/** + * Many of the RegExes are from @see http://jmrware.com/articles/2009/uri_regexp/URI_regex.html + */ + +namespace +{ +template +void range_check(const T value, const T min, const T max) +{ + if (!((value >= min) && (value <= max))) { + std::stringstream out; + out << "Value " << value << " should be in interval [" << min << "," << max << "] but is not!"; + throw std::invalid_argument(out.str()); + } +} + +/** @see date_time_check */ +void rfc3339_date_check(const std::string &value) +{ + const static REGEX_NAMESPACE::regex dateRegex{R"(^([0-9]{4})\-([0-9]{2})\-([0-9]{2})$)"}; + + REGEX_NAMESPACE::smatch matches; + if (!REGEX_NAMESPACE::regex_match(value, matches, dateRegex)) { + throw std::invalid_argument(value + " is not a date string according to RFC 3339."); + } + + const auto year = std::stoi(matches[1].str()); + const auto month = std::stoi(matches[2].str()); + const auto mday = std::stoi(matches[3].str()); + + const auto isLeapYear = (year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)); + + range_check(month, 1, 12); + if (month == 2) { + range_check(mday, 1, isLeapYear ? 29 : 28); + } else if (month <= 7) { + range_check(mday, 1, month % 2 == 0 ? 30 : 31); + } else { + range_check(mday, 1, month % 2 == 0 ? 31 : 30); + } +} + +/** @see date_time_check */ +void rfc3339_time_check(const std::string &value) +{ + const static REGEX_NAMESPACE::regex timeRegex{R"(^([0-9]{2})\:([0-9]{2})\:([0-9]{2})(\.[0-9]+)?(?:[Zz]|((?:\+|\-)[0-9]{2})\:([0-9]{2}))$)"}; + + REGEX_NAMESPACE::smatch matches; + if (!REGEX_NAMESPACE::regex_match(value, matches, timeRegex)) { + throw std::invalid_argument(value + " is not a time string according to RFC 3339."); + } + + auto hour = std::stoi(matches[1].str()); + auto minute = std::stoi(matches[2].str()); + auto second = std::stoi(matches[3].str()); + // const auto secfrac = std::stof( matches[4].str() ); + + range_check(hour, 0, 23); + range_check(minute, 0, 59); + + int offsetHour = 0, + offsetMinute = 0; + + /* don't check the numerical offset if time zone is specified as 'Z' */ + if (!matches[5].str().empty()) { + offsetHour = std::stoi(matches[5].str()); + offsetMinute = std::stoi(matches[6].str()); + + range_check(offsetHour, -23, 23); + range_check(offsetMinute, 0, 59); + if (offsetHour < 0) + offsetMinute *= -1; + } + + /** + * @todo Could be made more exact by querying a leap second database and choosing the + * correct maximum in {58,59,60}. This current solution might match some invalid dates + * but it won't lead to false negatives. This only works if we know the full date, however + */ + + auto day_minutes = hour * 60 + minute - (offsetHour * 60 + offsetMinute); + if (day_minutes < 0) + day_minutes += 60 * 24; + hour = day_minutes % 24; + minute = day_minutes / 24; + + if (hour == 23 && minute == 59) + range_check(second, 0, 60); // possible leap-second + else + range_check(second, 0, 59); +} + +/** + * @see https://tools.ietf.org/html/rfc3339#section-5.6 + * + * @verbatim + * date-fullyear = 4DIGIT + * date-month = 2DIGIT ; 01-12 + * date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on + * ; month/year + * time-hour = 2DIGIT ; 00-23 + * time-minute = 2DIGIT ; 00-59 + * time-second = 2DIGIT ; 00-58, 00-59, 00-60 based on leap second + * ; rules + * time-secfrac = "." 1*DIGIT + * time-numoffset = ("+" / "-") time-hour ":" time-minute + * time-offset = "Z" / time-numoffset + * + * partial-time = time-hour ":" time-minute ":" time-second + * [time-secfrac] + * full-date = date-fullyear "-" date-month "-" date-mday + * full-time = partial-time time-offset + * + * date-time = full-date "T" full-time + * @endverbatim + * NOTE: Per [ABNF] and ISO8601, the "T" and "Z" characters in this + * syntax may alternatively be lower case "t" or "z" respectively. + */ +void rfc3339_date_time_check(const std::string &value) +{ + const static REGEX_NAMESPACE::regex dateTimeRegex{R"(^([0-9]{4}\-[0-9]{2}\-[0-9]{2})[Tt]([0-9]{2}\:[0-9]{2}\:[0-9]{2}(?:\.[0-9]+)?(?:[Zz]|(?:\+|\-)[0-9]{2}\:[0-9]{2}))$)"}; + + REGEX_NAMESPACE::smatch matches; + if (!REGEX_NAMESPACE::regex_match(value, matches, dateTimeRegex)) { + throw std::invalid_argument(value + " is not a date-time string according to RFC 3339."); + } + + rfc3339_date_check(matches[1].str()); + rfc3339_time_check(matches[2].str()); +} + +const std::string decOctet{R"((?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]))"}; // matches numbers 0-255 +const std::string ipv4Address{"(?:" + decOctet + R"(\.){3})" + decOctet}; +const std::string h16{R"([0-9A-Fa-f]{1,4})"}; +const std::string h16Left{"(?:" + h16 + ":)"}; +const std::string ipv6Address{ + "(?:" + "(?:" + + h16Left + "{6}" + "|::" + + h16Left + "{5}" + "|(?:" + + h16 + ")?::" + h16Left + "{4}" + "|(?:" + + h16Left + "{0,1}" + h16 + ")?::" + h16Left + "{3}" + "|(?:" + + h16Left + "{0,2}" + h16 + ")?::" + h16Left + "{2}" + "|(?:" + + h16Left + "{0,3}" + h16 + ")?::" + h16Left + + "|(?:" + h16Left + "{0,4}" + h16 + ")?::" + ")(?:" + + h16Left + h16 + "|" + ipv4Address + ")" + "|(?:" + + h16Left + "{0,5}" + h16 + ")?::" + h16 + + "|(?:" + h16Left + "{0,6}" + h16 + ")?::" + ")"}; +const std::string ipvFuture{R"([Vv][0-9A-Fa-f]+\.[A-Za-z0-9\-._~!$&'()*+,;=:]+)"}; +const std::string regName{R"((?:[A-Za-z0-9\-._~!$&'()*+,;=]|%[0-9A-Fa-f]{2})*)"}; +const std::string host{ + "(?:" + R"(\[(?:)" + + ipv6Address + "|" + ipvFuture + R"()\])" + + "|" + ipv4Address + + "|" + regName + + ")"}; + +const std::string uuid{R"([0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12})"}; + +// from http://stackoverflow.com/questions/106179/regular-expression-to-match-dns-hostname-or-ip-address +const std::string hostname{R"(^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$)"}; + +bool is_ascii(std::string const &value) +{ + for (auto ch : value) { + if (ch & 0x80) { + return false; + } + } + return true; +} + +/** + * @see + * + * @verbatim + * URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] + * + * hier-part = "//" authority path-abempty + * / path-absolute + * / path-rootless + * / path-empty + * + * URI-reference = URI / relative-ref + * + * absolute-URI = scheme ":" hier-part [ "?" query ] + * + * relative-ref = relative-part [ "?" query ] [ "#" fragment ] + * + * relative-part = "//" authority path-abempty + * / path-absolute + * / path-noscheme + * / path-empty + * + * scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + * + * authority = [ userinfo "@" ] host [ ":" port ] + * userinfo = *( unreserved / pct-encoded / sub-delims / ":" ) + * host = IP-literal / IPv4address / reg-name + * port = *DIGIT + * + * IP-literal = "[" ( IPv6address / IPvFuture ) "]" + * + * IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" ) + * + * IPv6address = 6( h16 ":" ) ls32 + * / "::" 5( h16 ":" ) ls32 + * / [ h16 ] "::" 4( h16 ":" ) ls32 + * / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32 + * / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32 + * / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32 + * / [ *4( h16 ":" ) h16 ] "::" ls32 + * / [ *5( h16 ":" ) h16 ] "::" h16 + * / [ *6( h16 ":" ) h16 ] "::" + * + * h16 = 1*4HEXDIG + * ls32 = ( h16 ":" h16 ) / IPv4address + * IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet + * dec-octet = DIGIT ; 0-9 + * / %x31-39 DIGIT ; 10-99 + * / "1" 2DIGIT ; 100-199 + * / "2" %x30-34 DIGIT ; 200-249 + * / "25" %x30-35 ; 250-255 + * + * reg-name = *( unreserved / pct-encoded / sub-delims ) + * + * path = path-abempty ; begins with "/" or is empty + * / path-absolute ; begins with "/" but not "//" + * / path-noscheme ; begins with a non-colon segment + * / path-rootless ; begins with a segment + * / path-empty ; zero characters + * + * path-abempty = *( "/" segment ) + * path-absolute = "/" [ segment-nz *( "/" segment ) ] + * path-noscheme = segment-nz-nc *( "/" segment ) + * path-rootless = segment-nz *( "/" segment ) + * path-empty = 0 + * + * segment = *pchar + * segment-nz = 1*pchar + * segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) + * ; non-zero-length segment without any colon ":" + * + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + * + * query = *( pchar / "/" / "?" ) + * + * fragment = *( pchar / "/" / "?" ) + * + * pct-encoded = "%" HEXDIG HEXDIG + * + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * reserved = gen-delims / sub-delims + * gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" + * / "*" / "+" / "," / ";" / "=" + * + * @endverbatim + * @see adapted from: https://github.com/jhermsmeier/uri.regex/blob/master/uri.regex + * + */ +void rfc3986_uri_check(const std::string &value) +{ + const static std::string scheme{R"(([A-Za-z][A-Za-z0-9+\-.]*):)"}; + const static std::string hierPart{ + R"((?:(\/\/)(?:((?:[A-Za-z0-9\-._~!$&'()*+,;=:]|)" + R"(%[0-9A-Fa-f]{2})*)@)?((?:\[(?:(?:(?:(?:[0-9A-Fa-f]{1,4}:){6}|)" + R"(::(?:[0-9A-Fa-f]{1,4}:){5}|)" + R"((?:[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){4}|)" + R"((?:(?:[0-9A-Fa-f]{1,4}:){0,1}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){3}|)" + R"((?:(?:[0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){2}|)" + R"((?:(?:[0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}:|)" + R"((?:(?:[0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})?::)(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|)" + R"((?:(?:25[0-5]|2[0-4][0-9]|)" + R"([01]?[0-9][0-9]?)\.){3}(?:25[0-5]|)" + R"(2[0-4][0-9]|)" + R"([01]?[0-9][0-9]?))|)" + R"((?:(?:[0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}|)" + R"((?:(?:[0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})?::)|)" + R"([Vv][0-9A-Fa-f]+\.[A-Za-z0-9\-._~!$&'()*+,;=:]+)\]|)" + R"((?:(?:25[0-5]|)" + R"(2[0-4][0-9]|)" + R"([01]?[0-9][0-9]?)\.){3}(?:25[0-5]|)" + R"(2[0-4][0-9]|)" + R"([01]?[0-9][0-9]?)|)" + R"((?:[A-Za-z0-9\-._~!$&'()*+,;=]|)" + R"(%[0-9A-Fa-f]{2})*))(?::([0-9]*))?((?:\/(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|)" + R"(%[0-9A-Fa-f]{2})*)*)|)" + R"(\/((?:(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|)" + R"(%[0-9A-Fa-f]{2})+(?:\/(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|)" + R"(%[0-9A-Fa-f]{2})*)*)?)|)" + R"(((?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|)" + R"(%[0-9A-Fa-f]{2})+(?:\/(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|)" + R"(%[0-9A-Fa-f]{2})*)*)|))"}; + + const static std::string query{R"((?:\?((?:[A-Za-z0-9\-._~!$&'()*+,;=:@\/?]|%[0-9A-Fa-f]{2})*))?)"}; + const static std::string fragment{ + R"((?:\#((?:[A-Za-z0-9\-._~!$&'()*+,;=:@\/?]|%[0-9A-Fa-f]{2})*))?)"}; + const static std::string uriFormat{scheme + hierPart + query + fragment}; + + const static REGEX_NAMESPACE::regex uriRegex{uriFormat}; + + if (!REGEX_NAMESPACE::regex_match(value, uriRegex)) { + throw std::invalid_argument(value + " is not a URI string according to RFC 3986."); + } +} + +} // namespace + +namespace nlohmann +{ +namespace json_schema +{ +/** + * Checks validity for built-ins by converting the definitions given as ABNF in the linked RFC from + * @see https://json-schema.org/understanding-json-schema/reference/string.html#built-in-formats + * into regular expressions using @see https://www.msweet.org/abnf/ and some manual editing. + * + * @see https://json-schema.org/latest/json-schema-validation.html + */ +void default_string_format_check(const std::string &format, const std::string &value) +{ + if (format == "date-time") { + rfc3339_date_time_check(value); + } else if (format == "date") { + rfc3339_date_check(value); + } else if (format == "time") { + rfc3339_time_check(value); + } else if (format == "uri") { + rfc3986_uri_check(value); + } else if (format == "email") { + if (!is_ascii(value)) { + throw std::invalid_argument(value + " contains non-ASCII values, not RFC 5321 compliant."); + } + if (!is_address(&*value.begin(), &*value.end())) { + throw std::invalid_argument(value + " is not a valid email according to RFC 5321."); + } + } else if (format == "idn-email") { + if (!is_address(&*value.begin(), &*value.end())) { + throw std::invalid_argument(value + " is not a valid idn-email according to RFC 6531."); + } + } else if (format == "hostname") { + static const REGEX_NAMESPACE::regex hostRegex{hostname}; + if (!REGEX_NAMESPACE::regex_match(value, hostRegex)) { + throw std::invalid_argument(value + " is not a valid hostname according to RFC 3986 Appendix A."); + } + } else if (format == "ipv4") { + const static REGEX_NAMESPACE::regex ipv4Regex{"^" + ipv4Address + "$"}; + if (!REGEX_NAMESPACE::regex_match(value, ipv4Regex)) { + throw std::invalid_argument(value + " is not an IPv4 string according to RFC 2673."); + } + } else if (format == "ipv6") { + static const REGEX_NAMESPACE::regex ipv6Regex{ipv6Address}; + if (!REGEX_NAMESPACE::regex_match(value, ipv6Regex)) { + throw std::invalid_argument(value + " is not an IPv6 string according to RFC 5954."); + } + } else if (format == "uuid") { + static const REGEX_NAMESPACE::regex uuidRegex{uuid}; + if (!REGEX_NAMESPACE::regex_match(value, uuidRegex)) { + throw std::invalid_argument(value + " is not an uuid string according to RFC 4122."); + } + } else if (format == "regex") { + try { + REGEX_NAMESPACE::regex re(value, std::regex::ECMAScript); + } catch (std::exception &exception) { + throw exception; + } + } else { + /* yet unsupported JSON schema draft 7 built-ins */ + static const std::vector jsonSchemaStringFormatBuiltIns{ + "date-time", "time", "date", "email", "idn-email", "hostname", "idn-hostname", "ipv4", "ipv6", "uri", + "uri-reference", "iri", "iri-reference", "uri-template", "json-pointer", "relative-json-pointer", "regex"}; + if (std::find(jsonSchemaStringFormatBuiltIns.begin(), jsonSchemaStringFormatBuiltIns.end(), format) != jsonSchemaStringFormatBuiltIns.end()) { + throw std::logic_error("JSON schema string format built-in " + format + " not yet supported. " + + "Please open an issue or use a custom format checker."); + } + + throw std::logic_error("Don't know how to validate " + format); + } +} +} // namespace json_schema +} // namespace nlohmann diff --git a/lib/All/json-schema-validator/test/CMakeLists.txt b/lib/All/json-schema-validator/test/CMakeLists.txt new file mode 100644 index 0000000..a890491 --- /dev/null +++ b/lib/All/json-schema-validator/test/CMakeLists.txt @@ -0,0 +1,98 @@ +set(PIPE_IN_TEST_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/test-pipe-in.sh) + +# simple nlohmann_json_schema_validator-executable +add_executable(json-schema-validate json-schema-validate.cpp) +target_link_libraries(json-schema-validate nlohmann_json_schema_validator) + +function(add_test_simple_schema name schema instance) + add_test( + NAME ${name} + COMMAND ${PIPE_IN_TEST_SCRIPT} + $ + ${schema} + ${instance} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) +endfunction() + +file(GLOB TEST_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/*) + +foreach(DIR ${TEST_DIRS}) + if(IS_DIRECTORY ${DIR}) + add_subdirectory(${DIR}) + endif() +endforeach() + +add_executable(uri uri.cpp) +target_link_libraries(uri nlohmann_json_schema_validator) +add_test(NAME uri COMMAND uri) + +add_executable(errors errors.cpp) +target_link_libraries(errors nlohmann_json_schema_validator) +add_test(NAME errors COMMAND errors) + +add_executable(issue-70 issue-70.cpp) +target_link_libraries(issue-70 nlohmann_json_schema_validator) +add_test(NAME issue-70 COMMAND issue-70) + +add_executable(issue-70-root-schema-constructor issue-70-root-schema-constructor.cpp) +target_link_libraries(issue-70-root-schema-constructor nlohmann_json_schema_validator) +add_test(NAME issue-70-root-schema-constructor COMMAND issue-70-root-schema-constructor) + +add_executable(issue-25-default-values issue-25-default-values.cpp) +target_link_libraries(issue-25-default-values nlohmann_json_schema_validator) +add_test(NAME issue-25-default-values COMMAND issue-25-default-values) + +add_executable(issue-98 issue-98.cpp) +target_link_libraries(issue-98 nlohmann_json_schema_validator) +add_test(NAME issue-98-erase-exception-unknown-keywords COMMAND issue-98) + +add_executable(issue-293 issue-293.cpp) +target_link_libraries(issue-293 nlohmann_json_schema_validator) +add_test(NAME issue-293-float-point-error COMMAND issue-293) + +# Unit test for string format checks +add_executable(string-format-check-test string-format-check-test.cpp) +target_include_directories(string-format-check-test PRIVATE ${PROJECT_SOURCE_DIR}/src/) +target_link_libraries(string-format-check-test nlohmann_json_schema_validator) + +add_test(NAME string-format-check-test COMMAND string-format-check-test) + +# Unit test for json-patch +add_executable(json-patch json-patch.cpp) +target_include_directories(json-patch PRIVATE ${PROJECT_SOURCE_DIR}/src) +target_link_libraries(json-patch nlohmann_json_schema_validator) +add_test(NAME json-patch COMMAND json-patch) + +# Unit test for format checker fail at schema parsing time +add_executable(issue-117-format-error issue-117-format-error.cpp) +target_link_libraries(issue-117-format-error nlohmann_json_schema_validator) +add_test(NAME issue-117-format-error COMMAND issue-117-format-error) + +add_executable(binary-validation binary-validation.cpp) +target_include_directories(binary-validation PRIVATE ${PROJECT_SOURCE_DIR}/src) +target_link_libraries(binary-validation PRIVATE nlohmann_json_schema_validator) +add_test(NAME binary-validation COMMAND binary-validation) + +add_executable(issue-149-entry-selection issue-149-entry-selection.cpp) +target_link_libraries(issue-149-entry-selection PRIVATE nlohmann_json_schema_validator) +add_test(NAME issue-149-entry-selection COMMAND issue-149-entry-selection) + +add_executable(issue-189-default-values issue-189-default-values.cpp) +target_link_libraries(issue-189-default-values nlohmann_json_schema_validator) +add_test(NAME issue-189-default-values COMMAND issue-189-default-values) + +add_executable(issue-229-oneof-default-values issue-229-oneof-default-values.cpp) +target_link_libraries(issue-229-oneof-default-values nlohmann_json_schema_validator) +add_test(NAME issue-229-oneof-default-values COMMAND issue-229-oneof-default-values) + +add_executable(issue-243-root-default-values issue-243-root-default-values.cpp) +target_link_libraries(issue-243-root-default-values nlohmann_json_schema_validator) +add_test(NAME issue-243-root-default-values COMMAND issue-243-root-default-values) + +add_executable(issue-255-error-message-limit-precision issue-255-error-message-limit-precision.cpp) +target_link_libraries(issue-255-error-message-limit-precision nlohmann_json_schema_validator) +add_test(NAME issue-255-error-message-limit-precision COMMAND issue-255-error-message-limit-precision) + +add_executable(issue-105-verbose-combination-errors issue-105-verbose-combination-errors.cpp) +target_link_libraries(issue-105-verbose-combination-errors nlohmann_json_schema_validator) +add_test(NAME issue-105-verbose-combination-errors COMMAND issue-105-verbose-combination-errors) diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/CMakeLists.txt b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/CMakeLists.txt new file mode 100644 index 0000000..3d93b55 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/CMakeLists.txt @@ -0,0 +1,70 @@ +set(JSON_SCHEMA_TEST_PREFIX "JSON-Suite" CACHE STRING "prefix for JSON-tests added to ctest") + +set(DRAFT "draft7") + +# find schema-test-suite +find_path(JSON_SCHEMA_TEST_SUITE_PATH + NAMES + tests/${DRAFT}) + +if (NOT JSON_SCHEMA_TEST_SUITE_PATH) + message(STATUS "Set JSON_SCHEMA_TEST_SUITE_PATH to a path in which JSON-Schema-Test-Suite is located (github.com/json-schema-org/JSON-Schema-Test-Suite). Using internal test-suite which might be out of date.") + set(JSON_SCHEMA_TEST_SUITE_PATH ${CMAKE_CURRENT_SOURCE_DIR}) +endif() + +if(JSON_SCHEMA_TEST_SUITE_PATH) + # json-schema-validator-tester + add_executable(json-schema-test json-schema-test.cpp) + target_link_libraries(json-schema-test nlohmann_json_schema_validator) + target_compile_definitions(json-schema-test + PRIVATE + JSON_SCHEMA_TEST_SUITE_PATH="${JSON_SCHEMA_TEST_SUITE_PATH}") + + option(JSON_SCHEMA_ENABLE_OPTIONAL_TESTS "Enable optional tests of the JSONSchema Test Suite" ON) + + # create tests foreach test-file + file(GLOB TEST_FILES ${JSON_SCHEMA_TEST_SUITE_PATH}/tests/${DRAFT}/*.json) + + foreach(TEST_FILE ${TEST_FILES}) + get_filename_component(TEST_NAME ${TEST_FILE} NAME_WE) + add_test(NAME "${JSON_SCHEMA_TEST_PREFIX}::${TEST_NAME}" + COMMAND ${PIPE_IN_TEST_SCRIPT} $ ${TEST_FILE}) + endforeach() + + if (JSON_SCHEMA_ENABLE_OPTIONAL_TESTS) + file(GLOB OPT_TEST_FILES ${JSON_SCHEMA_TEST_SUITE_PATH}/tests/${DRAFT}/optional/*.json) + file(GLOB FORMAT_TEST_FILES ${JSON_SCHEMA_TEST_SUITE_PATH}/tests/${DRAFT}/optional/format/*.json) + + foreach(TEST_FILE ${OPT_TEST_FILES}) + get_filename_component(TEST_NAME ${TEST_FILE} NAME_WE) + add_test(NAME "${JSON_SCHEMA_TEST_PREFIX}::Optional::${TEST_NAME}" + COMMAND ${PIPE_IN_TEST_SCRIPT} $ ${TEST_FILE}) + endforeach() + + foreach(TEST_FILE ${FORMAT_TEST_FILES}) + get_filename_component(TEST_NAME ${TEST_FILE} NAME_WE) + add_test(NAME "${JSON_SCHEMA_TEST_PREFIX}::Optional::Format::${TEST_NAME}" + COMMAND ${PIPE_IN_TEST_SCRIPT} $ ${TEST_FILE}) + endforeach() + + # some optional tests will fail + set_tests_properties( + JSON-Suite::Optional::bignum + JSON-Suite::Optional::non-bmp-regex + JSON-Suite::Optional::float-overflow + + JSON-Suite::Optional::ecmascript-regex + JSON-Suite::Optional::Format::idn-hostname + JSON-Suite::Optional::Format::iri-reference + JSON-Suite::Optional::Format::iri + JSON-Suite::Optional::Format::json-pointer + JSON-Suite::Optional::Format::relative-json-pointer + JSON-Suite::Optional::Format::uri-reference + JSON-Suite::Optional::Format::uri-template + JSON-Suite::Optional::unicode + + PROPERTIES + WILL_FAIL ON) + endif() +else() +endif() diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/json-schema-test.cpp b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/json-schema-test.cpp new file mode 100644 index 0000000..deee4c8 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/json-schema-test.cpp @@ -0,0 +1,154 @@ +/* + * JSON schema validator for JSON for modern C++ + * + * Copyright (c) 2016-2019 Patrick Boettcher . + * + * SPDX-License-Identifier: MIT + * + */ +#include + +#include +#include +#include + +using nlohmann::json; +using nlohmann::json_uri; +using nlohmann::json_schema::json_validator; + +static void loader(const json_uri &uri, json &schema) +{ + if (uri.location() == "http://json-schema.org/draft-07/schema") { + schema = nlohmann::json_schema::draft7_schema_builtin; + return; + } + + std::string fn = JSON_SCHEMA_TEST_SUITE_PATH; + fn += "/remotes"; + fn += uri.path(); + std::cerr << fn << "\n"; + + std::fstream s(fn.c_str()); + if (!s.good()) + throw std::invalid_argument("could not open " + uri.url() + " for schema loading\n"); + + try { + s >> schema; + } catch (std::exception &e) { + throw e; + } +} + +// from here +// https://stackoverflow.com/a/34571089/880584 +static std::string base64_decode(const std::string &in) +{ + std::string out; + + std::vector T(256, -1); + for (int i = 0; i < 64; i++) + T["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i]] = i; + + unsigned val = 0; + int valb = -8; + for (uint8_t c : in) { + if (c == '=') + break; + + if (T[c] == -1) { + throw std::invalid_argument("base64-decode: unexpected character in encode string: '" + std::string(1, c) + "'"); + } + val = (val << 6) + T[c]; + valb += 6; + if (valb >= 0) { + out.push_back(char((val >> valb) & 0xFF)); + valb -= 8; + } + } + return out; +} + +static void content(const std::string &contentEncoding, const std::string &contentMediaType, const json &instance) +{ + std::string content = instance; + + if (contentEncoding == "base64") + content = base64_decode(instance); + else if (contentEncoding != "") + throw std::invalid_argument("unable to check for contentEncoding '" + contentEncoding + "'"); + + if (contentMediaType == "application/json") + auto dummy = json::parse(content); // throws if conversion fails + else if (contentMediaType != "") + throw std::invalid_argument("unable to check for contentMediaType '" + contentMediaType + "'"); +} + +int main(void) +{ + json validation; // a validation case following the JSON-test-suite-schema + + try { + std::cin >> validation; + } catch (std::exception &e) { + std::cout << e.what() << "\n"; + return EXIT_FAILURE; + } + + size_t total_failed = 0, + total = 0; + + for (auto &test_group : validation) { + size_t group_failed = 0, + group_total = 0; + + std::cout << "Testing Group " << test_group["description"] << "\n"; + + const auto &schema = test_group["schema"]; + + json_validator validator(loader, + nlohmann::json_schema::default_string_format_check, + content); + + validator.set_root_schema(schema); + + for (auto &test_case : test_group["tests"]) { + std::cout << " Testing Case " << test_case["description"] << "\n"; + + bool valid = true; + + try { + validator.validate(test_case["data"]); + } catch (const std::out_of_range &e) { + valid = false; + std::cout << " Test Case Exception (out of range): " << e.what() << "\n"; + + } catch (const std::invalid_argument &e) { + valid = false; + std::cout << " Test Case Exception (invalid argument): " << e.what() << "\n"; + + } catch (const std::logic_error &e) { + valid = !test_case["valid"]; /* force test-case failure */ + std::cout << " Not yet implemented: " << e.what() << "\n"; + } + + if (valid == test_case["valid"]) + std::cout << " --> Test Case exited with " << valid << " as expected.\n"; + else { + group_failed++; + std::cout << " --> Test Case exited with " << valid << " NOT expected.\n"; + } + group_total++; + std::cout << "\n"; + } + total_failed += group_failed; + total += group_total; + std::cout << "Group RESULT: " << test_group["description"] << " " + << (group_total - group_failed) << " of " << group_total + << " have succeeded - " << group_failed << " failed\n"; + std::cout << "-------------\n"; + } + + std::cout << "Total RESULT: " << (total - total_failed) << " of " << total << " have succeeded - " << total_failed << " failed\n"; + + return total_failed; +} diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/baseUriChange/folderInteger.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/baseUriChange/folderInteger.json new file mode 100644 index 0000000..8b50ea3 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/baseUriChange/folderInteger.json @@ -0,0 +1,3 @@ +{ + "type": "integer" +} diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/baseUriChangeFolder/folderInteger.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/baseUriChangeFolder/folderInteger.json new file mode 100644 index 0000000..8b50ea3 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/baseUriChangeFolder/folderInteger.json @@ -0,0 +1,3 @@ +{ + "type": "integer" +} diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/baseUriChangeFolderInSubschema/folderInteger.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/baseUriChangeFolderInSubschema/folderInteger.json new file mode 100644 index 0000000..8b50ea3 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/baseUriChangeFolderInSubschema/folderInteger.json @@ -0,0 +1,3 @@ +{ + "type": "integer" +} diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/folder/folderInteger.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/folder/folderInteger.json new file mode 100644 index 0000000..8b50ea3 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/folder/folderInteger.json @@ -0,0 +1,3 @@ +{ + "type": "integer" +} diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/integer.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/integer.json new file mode 100644 index 0000000..8b50ea3 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/integer.json @@ -0,0 +1,3 @@ +{ + "type": "integer" +} diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/name-defs.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/name-defs.json new file mode 100644 index 0000000..1dab4a4 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/name-defs.json @@ -0,0 +1,15 @@ +{ + "$defs": { + "orNull": { + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#" + } + ] + } + }, + "type": "string" +} diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/name.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/name.json new file mode 100644 index 0000000..fceacb8 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/name.json @@ -0,0 +1,15 @@ +{ + "definitions": { + "orNull": { + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#" + } + ] + } + }, + "type": "string" +} diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/ref-and-definitions.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/ref-and-definitions.json new file mode 100644 index 0000000..e0ee802 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/ref-and-definitions.json @@ -0,0 +1,11 @@ +{ + "$id": "http://localhost:1234/ref-and-definitions.json", + "definitions": { + "inner": { + "properties": { + "bar": { "type": "string" } + } + } + }, + "allOf": [ { "$ref": "#/definitions/inner" } ] +} diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/ref-and-defs.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/ref-and-defs.json new file mode 100644 index 0000000..85d06c3 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/ref-and-defs.json @@ -0,0 +1,11 @@ +{ + "$id": "http://localhost:1234/ref-and-defs.json", + "$defs": { + "inner": { + "properties": { + "bar": { "type": "string" } + } + } + }, + "$ref": "#/$defs/inner" +} diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/subSchemas-defs.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/subSchemas-defs.json new file mode 100644 index 0000000..50b7b6d --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/subSchemas-defs.json @@ -0,0 +1,10 @@ +{ + "$defs": { + "integer": { + "type": "integer" + }, + "refToInteger": { + "$ref": "#/$defs/integer" + } + } +} diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/subSchemas.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/subSchemas.json new file mode 100644 index 0000000..9f8030b --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/remotes/subSchemas.json @@ -0,0 +1,8 @@ +{ + "integer": { + "type": "integer" + }, + "refToInteger": { + "$ref": "#/integer" + } +} diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/additionalItems.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/additionalItems.json new file mode 100644 index 0000000..784bc84 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/additionalItems.json @@ -0,0 +1,149 @@ +[ + { + "description": "additionalItems as schema", + "schema": { + "items": [{}], + "additionalItems": {"type": "integer"} + }, + "tests": [ + { + "description": "additional items match schema", + "data": [ null, 2, 3, 4 ], + "valid": true + }, + { + "description": "additional items do not match schema", + "data": [ null, 2, 3, "foo" ], + "valid": false + } + ] + }, + { + "description": "when items is schema, additionalItems does nothing", + "schema": { + "items": {}, + "additionalItems": false + }, + "tests": [ + { + "description": "all items match schema", + "data": [ 1, 2, 3, 4, 5 ], + "valid": true + } + ] + }, + { + "description": "array of items with no additionalItems permitted", + "schema": { + "items": [{}, {}, {}], + "additionalItems": false + }, + "tests": [ + { + "description": "empty array", + "data": [ ], + "valid": true + }, + { + "description": "fewer number of items present (1)", + "data": [ 1 ], + "valid": true + }, + { + "description": "fewer number of items present (2)", + "data": [ 1, 2 ], + "valid": true + }, + { + "description": "equal number of items present", + "data": [ 1, 2, 3 ], + "valid": true + }, + { + "description": "additional items are not permitted", + "data": [ 1, 2, 3, 4 ], + "valid": false + } + ] + }, + { + "description": "additionalItems as false without items", + "schema": {"additionalItems": false}, + "tests": [ + { + "description": + "items defaults to empty schema so everything is valid", + "data": [ 1, 2, 3, 4, 5 ], + "valid": true + }, + { + "description": "ignores non-arrays", + "data": {"foo" : "bar"}, + "valid": true + } + ] + }, + { + "description": "additionalItems are allowed by default", + "schema": {"items": [{"type": "integer"}]}, + "tests": [ + { + "description": "only the first item is validated", + "data": [1, "foo", false], + "valid": true + } + ] + }, + { + "description": "additionalItems should not look in applicators, valid case", + "schema": { + "allOf": [ + { "items": [ { "type": "integer" } ] } + ], + "additionalItems": { "type": "boolean" } + }, + "tests": [ + { + "description": "items defined in allOf are not examined", + "data": [ 1, null ], + "valid": true + } + ] + }, + { + "description": "additionalItems should not look in applicators, invalid case", + "schema": { + "allOf": [ + { "items": [ { "type": "integer" }, { "type": "string" } ] } + ], + "items": [ {"type": "integer" } ], + "additionalItems": { "type": "boolean" } + }, + "tests": [ + { + "description": "items defined in allOf are not examined", + "data": [ 1, "hello" ], + "valid": false + } + ] + }, + { + "description": "items validation adjusts the starting index for additionalItems", + "schema": { + "items": [ { "type": "string" } ], + "additionalItems": { "type": "integer" } + }, + "tests": [ + { + "description": "valid items", + "data": [ "x", 2, 3 ], + "valid": true + }, + { + "description": "wrong type of second item", + "data": [ "x", "y" ], + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/additionalProperties.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/additionalProperties.json new file mode 100644 index 0000000..381275a --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/additionalProperties.json @@ -0,0 +1,133 @@ +[ + { + "description": + "additionalProperties being false does not allow other properties", + "schema": { + "properties": {"foo": {}, "bar": {}}, + "patternProperties": { "^v": {} }, + "additionalProperties": false + }, + "tests": [ + { + "description": "no additional properties is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "an additional property is invalid", + "data": {"foo" : 1, "bar" : 2, "quux" : "boom"}, + "valid": false + }, + { + "description": "ignores arrays", + "data": [1, 2, 3], + "valid": true + }, + { + "description": "ignores strings", + "data": "foobarbaz", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + }, + { + "description": "patternProperties are not additional properties", + "data": {"foo":1, "vroom": 2}, + "valid": true + } + ] + }, + { + "description": "non-ASCII pattern with additionalProperties", + "schema": { + "patternProperties": {"^á": {}}, + "additionalProperties": false + }, + "tests": [ + { + "description": "matching the pattern is valid", + "data": {"ármányos": 2}, + "valid": true + }, + { + "description": "not matching the pattern is invalid", + "data": {"élmény": 2}, + "valid": false + } + ] + }, + { + "description": + "additionalProperties allows a schema which should validate", + "schema": { + "properties": {"foo": {}, "bar": {}}, + "additionalProperties": {"type": "boolean"} + }, + "tests": [ + { + "description": "no additional properties is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "an additional valid property is valid", + "data": {"foo" : 1, "bar" : 2, "quux" : true}, + "valid": true + }, + { + "description": "an additional invalid property is invalid", + "data": {"foo" : 1, "bar" : 2, "quux" : 12}, + "valid": false + } + ] + }, + { + "description": + "additionalProperties can exist by itself", + "schema": { + "additionalProperties": {"type": "boolean"} + }, + "tests": [ + { + "description": "an additional valid property is valid", + "data": {"foo" : true}, + "valid": true + }, + { + "description": "an additional invalid property is invalid", + "data": {"foo" : 1}, + "valid": false + } + ] + }, + { + "description": "additionalProperties are allowed by default", + "schema": {"properties": {"foo": {}, "bar": {}}}, + "tests": [ + { + "description": "additional properties are allowed", + "data": {"foo": 1, "bar": 2, "quux": true}, + "valid": true + } + ] + }, + { + "description": "additionalProperties should not look in applicators", + "schema": { + "allOf": [ + {"properties": {"foo": {}}} + ], + "additionalProperties": {"type": "boolean"} + }, + "tests": [ + { + "description": "properties defined in allOf are not examined", + "data": {"foo": 1, "bar": true}, + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/allOf.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/allOf.json new file mode 100644 index 0000000..ec9319e --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/allOf.json @@ -0,0 +1,294 @@ +[ + { + "description": "allOf", + "schema": { + "allOf": [ + { + "properties": { + "bar": {"type": "integer"} + }, + "required": ["bar"] + }, + { + "properties": { + "foo": {"type": "string"} + }, + "required": ["foo"] + } + ] + }, + "tests": [ + { + "description": "allOf", + "data": {"foo": "baz", "bar": 2}, + "valid": true + }, + { + "description": "mismatch second", + "data": {"foo": "baz"}, + "valid": false + }, + { + "description": "mismatch first", + "data": {"bar": 2}, + "valid": false + }, + { + "description": "wrong type", + "data": {"foo": "baz", "bar": "quux"}, + "valid": false + } + ] + }, + { + "description": "allOf with base schema", + "schema": { + "properties": {"bar": {"type": "integer"}}, + "required": ["bar"], + "allOf" : [ + { + "properties": { + "foo": {"type": "string"} + }, + "required": ["foo"] + }, + { + "properties": { + "baz": {"type": "null"} + }, + "required": ["baz"] + } + ] + }, + "tests": [ + { + "description": "valid", + "data": {"foo": "quux", "bar": 2, "baz": null}, + "valid": true + }, + { + "description": "mismatch base schema", + "data": {"foo": "quux", "baz": null}, + "valid": false + }, + { + "description": "mismatch first allOf", + "data": {"bar": 2, "baz": null}, + "valid": false + }, + { + "description": "mismatch second allOf", + "data": {"foo": "quux", "bar": 2}, + "valid": false + }, + { + "description": "mismatch both", + "data": {"bar": 2}, + "valid": false + } + ] + }, + { + "description": "allOf simple types", + "schema": { + "allOf": [ + {"maximum": 30}, + {"minimum": 20} + ] + }, + "tests": [ + { + "description": "valid", + "data": 25, + "valid": true + }, + { + "description": "mismatch one", + "data": 35, + "valid": false + } + ] + }, + { + "description": "allOf with boolean schemas, all true", + "schema": {"allOf": [true, true]}, + "tests": [ + { + "description": "any value is valid", + "data": "foo", + "valid": true + } + ] + }, + { + "description": "allOf with boolean schemas, some false", + "schema": {"allOf": [true, false]}, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "allOf with boolean schemas, all false", + "schema": {"allOf": [false, false]}, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "allOf with one empty schema", + "schema": { + "allOf": [ + {} + ] + }, + "tests": [ + { + "description": "any data is valid", + "data": 1, + "valid": true + } + ] + }, + { + "description": "allOf with two empty schemas", + "schema": { + "allOf": [ + {}, + {} + ] + }, + "tests": [ + { + "description": "any data is valid", + "data": 1, + "valid": true + } + ] + }, + { + "description": "allOf with the first empty schema", + "schema": { + "allOf": [ + {}, + { "type": "number" } + ] + }, + "tests": [ + { + "description": "number is valid", + "data": 1, + "valid": true + }, + { + "description": "string is invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "allOf with the last empty schema", + "schema": { + "allOf": [ + { "type": "number" }, + {} + ] + }, + "tests": [ + { + "description": "number is valid", + "data": 1, + "valid": true + }, + { + "description": "string is invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "nested allOf, to check validation semantics", + "schema": { + "allOf": [ + { + "allOf": [ + { + "type": "null" + } + ] + } + ] + }, + "tests": [ + { + "description": "null is valid", + "data": null, + "valid": true + }, + { + "description": "anything non-null is invalid", + "data": 123, + "valid": false + } + ] + }, + { + "description": "allOf combined with anyOf, oneOf", + "schema": { + "allOf": [ { "multipleOf": 2 } ], + "anyOf": [ { "multipleOf": 3 } ], + "oneOf": [ { "multipleOf": 5 } ] + }, + "tests": [ + { + "description": "allOf: false, anyOf: false, oneOf: false", + "data": 1, + "valid": false + }, + { + "description": "allOf: false, anyOf: false, oneOf: true", + "data": 5, + "valid": false + }, + { + "description": "allOf: false, anyOf: true, oneOf: false", + "data": 3, + "valid": false + }, + { + "description": "allOf: false, anyOf: true, oneOf: true", + "data": 15, + "valid": false + }, + { + "description": "allOf: true, anyOf: false, oneOf: false", + "data": 2, + "valid": false + }, + { + "description": "allOf: true, anyOf: false, oneOf: true", + "data": 10, + "valid": false + }, + { + "description": "allOf: true, anyOf: true, oneOf: false", + "data": 6, + "valid": false + }, + { + "description": "allOf: true, anyOf: true, oneOf: true", + "data": 30, + "valid": true + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/anyOf.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/anyOf.json new file mode 100644 index 0000000..b720afa --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/anyOf.json @@ -0,0 +1,215 @@ +[ + { + "description": "anyOf", + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "minimum": 2 + } + ] + }, + "tests": [ + { + "description": "first anyOf valid", + "data": 1, + "valid": true + }, + { + "description": "second anyOf valid", + "data": 2.5, + "valid": true + }, + { + "description": "both anyOf valid", + "data": 3, + "valid": true + }, + { + "description": "neither anyOf valid", + "data": 1.5, + "valid": false + } + ] + }, + { + "description": "anyOf with base schema", + "schema": { + "type": "string", + "anyOf" : [ + { + "maxLength": 2 + }, + { + "minLength": 4 + } + ] + }, + "tests": [ + { + "description": "mismatch base schema", + "data": 3, + "valid": false + }, + { + "description": "one anyOf valid", + "data": "foobar", + "valid": true + }, + { + "description": "both anyOf invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "anyOf with boolean schemas, all true", + "schema": {"anyOf": [true, true]}, + "tests": [ + { + "description": "any value is valid", + "data": "foo", + "valid": true + } + ] + }, + { + "description": "anyOf with boolean schemas, some true", + "schema": {"anyOf": [true, false]}, + "tests": [ + { + "description": "any value is valid", + "data": "foo", + "valid": true + } + ] + }, + { + "description": "anyOf with boolean schemas, all false", + "schema": {"anyOf": [false, false]}, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "anyOf complex types", + "schema": { + "anyOf": [ + { + "properties": { + "bar": {"type": "integer"} + }, + "required": ["bar"] + }, + { + "properties": { + "foo": {"type": "string"} + }, + "required": ["foo"] + } + ] + }, + "tests": [ + { + "description": "first anyOf valid (complex)", + "data": {"bar": 2}, + "valid": true + }, + { + "description": "second anyOf valid (complex)", + "data": {"foo": "baz"}, + "valid": true + }, + { + "description": "both anyOf valid (complex)", + "data": {"foo": "baz", "bar": 2}, + "valid": true + }, + { + "description": "neither anyOf valid (complex)", + "data": {"foo": 2, "bar": "quux"}, + "valid": false + } + ] + }, + { + "description": "anyOf with one empty schema", + "schema": { + "anyOf": [ + { "type": "number" }, + {} + ] + }, + "tests": [ + { + "description": "string is valid", + "data": "foo", + "valid": true + }, + { + "description": "number is valid", + "data": 123, + "valid": true + } + ] + }, + { + "description": "nested anyOf, to check validation semantics", + "schema": { + "anyOf": [ + { + "anyOf": [ + { + "type": "null" + } + ] + } + ] + }, + "tests": [ + { + "description": "null is valid", + "data": null, + "valid": true + }, + { + "description": "anything non-null is invalid", + "data": 123, + "valid": false + } + ] + }, + { + "description": "nested anyOf, to check validation semantics", + "schema": { + "anyOf": [ + { + "anyOf": [ + { + "type": "null" + } + ] + } + ] + }, + "tests": [ + { + "description": "null is valid", + "data": null, + "valid": true + }, + { + "description": "anything non-null is invalid", + "data": 123, + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/boolean_schema.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/boolean_schema.json new file mode 100644 index 0000000..6d40f23 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/boolean_schema.json @@ -0,0 +1,104 @@ +[ + { + "description": "boolean schema 'true'", + "schema": true, + "tests": [ + { + "description": "number is valid", + "data": 1, + "valid": true + }, + { + "description": "string is valid", + "data": "foo", + "valid": true + }, + { + "description": "boolean true is valid", + "data": true, + "valid": true + }, + { + "description": "boolean false is valid", + "data": false, + "valid": true + }, + { + "description": "null is valid", + "data": null, + "valid": true + }, + { + "description": "object is valid", + "data": {"foo": "bar"}, + "valid": true + }, + { + "description": "empty object is valid", + "data": {}, + "valid": true + }, + { + "description": "array is valid", + "data": ["foo"], + "valid": true + }, + { + "description": "empty array is valid", + "data": [], + "valid": true + } + ] + }, + { + "description": "boolean schema 'false'", + "schema": false, + "tests": [ + { + "description": "number is invalid", + "data": 1, + "valid": false + }, + { + "description": "string is invalid", + "data": "foo", + "valid": false + }, + { + "description": "boolean true is invalid", + "data": true, + "valid": false + }, + { + "description": "boolean false is invalid", + "data": false, + "valid": false + }, + { + "description": "null is invalid", + "data": null, + "valid": false + }, + { + "description": "object is invalid", + "data": {"foo": "bar"}, + "valid": false + }, + { + "description": "empty object is invalid", + "data": {}, + "valid": false + }, + { + "description": "array is invalid", + "data": ["foo"], + "valid": false + }, + { + "description": "empty array is invalid", + "data": [], + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/const.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/const.json new file mode 100644 index 0000000..1c2cafc --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/const.json @@ -0,0 +1,342 @@ +[ + { + "description": "const validation", + "schema": {"const": 2}, + "tests": [ + { + "description": "same value is valid", + "data": 2, + "valid": true + }, + { + "description": "another value is invalid", + "data": 5, + "valid": false + }, + { + "description": "another type is invalid", + "data": "a", + "valid": false + } + ] + }, + { + "description": "const with object", + "schema": {"const": {"foo": "bar", "baz": "bax"}}, + "tests": [ + { + "description": "same object is valid", + "data": {"foo": "bar", "baz": "bax"}, + "valid": true + }, + { + "description": "same object with different property order is valid", + "data": {"baz": "bax", "foo": "bar"}, + "valid": true + }, + { + "description": "another object is invalid", + "data": {"foo": "bar"}, + "valid": false + }, + { + "description": "another type is invalid", + "data": [1, 2], + "valid": false + } + ] + }, + { + "description": "const with array", + "schema": {"const": [{ "foo": "bar" }]}, + "tests": [ + { + "description": "same array is valid", + "data": [{"foo": "bar"}], + "valid": true + }, + { + "description": "another array item is invalid", + "data": [2], + "valid": false + }, + { + "description": "array with additional items is invalid", + "data": [1, 2, 3], + "valid": false + } + ] + }, + { + "description": "const with null", + "schema": {"const": null}, + "tests": [ + { + "description": "null is valid", + "data": null, + "valid": true + }, + { + "description": "not null is invalid", + "data": 0, + "valid": false + } + ] + }, + { + "description": "const with false does not match 0", + "schema": {"const": false}, + "tests": [ + { + "description": "false is valid", + "data": false, + "valid": true + }, + { + "description": "integer zero is invalid", + "data": 0, + "valid": false + }, + { + "description": "float zero is invalid", + "data": 0.0, + "valid": false + } + ] + }, + { + "description": "const with true does not match 1", + "schema": {"const": true}, + "tests": [ + { + "description": "true is valid", + "data": true, + "valid": true + }, + { + "description": "integer one is invalid", + "data": 1, + "valid": false + }, + { + "description": "float one is invalid", + "data": 1.0, + "valid": false + } + ] + }, + { + "description": "const with [false] does not match [0]", + "schema": {"const": [false]}, + "tests": [ + { + "description": "[false] is valid", + "data": [false], + "valid": true + }, + { + "description": "[0] is invalid", + "data": [0], + "valid": false + }, + { + "description": "[0.0] is invalid", + "data": [0.0], + "valid": false + } + ] + }, + { + "description": "const with [true] does not match [1]", + "schema": {"const": [true]}, + "tests": [ + { + "description": "[true] is valid", + "data": [true], + "valid": true + }, + { + "description": "[1] is invalid", + "data": [1], + "valid": false + }, + { + "description": "[1.0] is invalid", + "data": [1.0], + "valid": false + } + ] + }, + { + "description": "const with {\"a\": false} does not match {\"a\": 0}", + "schema": {"const": {"a": false}}, + "tests": [ + { + "description": "{\"a\": false} is valid", + "data": {"a": false}, + "valid": true + }, + { + "description": "{\"a\": 0} is invalid", + "data": {"a": 0}, + "valid": false + }, + { + "description": "{\"a\": 0.0} is invalid", + "data": {"a": 0.0}, + "valid": false + } + ] + }, + { + "description": "const with {\"a\": true} does not match {\"a\": 1}", + "schema": {"const": {"a": true}}, + "tests": [ + { + "description": "{\"a\": true} is valid", + "data": {"a": true}, + "valid": true + }, + { + "description": "{\"a\": 1} is invalid", + "data": {"a": 1}, + "valid": false + }, + { + "description": "{\"a\": 1.0} is invalid", + "data": {"a": 1.0}, + "valid": false + } + ] + }, + { + "description": "const with 0 does not match other zero-like types", + "schema": {"const": 0}, + "tests": [ + { + "description": "false is invalid", + "data": false, + "valid": false + }, + { + "description": "integer zero is valid", + "data": 0, + "valid": true + }, + { + "description": "float zero is valid", + "data": 0.0, + "valid": true + }, + { + "description": "empty object is invalid", + "data": {}, + "valid": false + }, + { + "description": "empty array is invalid", + "data": [], + "valid": false + }, + { + "description": "empty string is invalid", + "data": "", + "valid": false + } + ] + }, + { + "description": "const with 1 does not match true", + "schema": {"const": 1}, + "tests": [ + { + "description": "true is invalid", + "data": true, + "valid": false + }, + { + "description": "integer one is valid", + "data": 1, + "valid": true + }, + { + "description": "float one is valid", + "data": 1.0, + "valid": true + } + ] + }, + { + "description": "const with -2.0 matches integer and float types", + "schema": {"const": -2.0}, + "tests": [ + { + "description": "integer -2 is valid", + "data": -2, + "valid": true + }, + { + "description": "integer 2 is invalid", + "data": 2, + "valid": false + }, + { + "description": "float -2.0 is valid", + "data": -2.0, + "valid": true + }, + { + "description": "float 2.0 is invalid", + "data": 2.0, + "valid": false + }, + { + "description": "float -2.00001 is invalid", + "data": -2.00001, + "valid": false + } + ] + }, + { + "description": "float and integers are equal up to 64-bit representation limits", + "schema": {"const": 9007199254740992}, + "tests": [ + { + "description": "integer is valid", + "data": 9007199254740992, + "valid": true + }, + { + "description": "integer minus one is invalid", + "data": 9007199254740991, + "valid": false + }, + { + "description": "float is valid", + "data": 9007199254740992.0, + "valid": true + }, + { + "description": "float minus one is invalid", + "data": 9007199254740991.0, + "valid": false + } + ] + }, + { + "description": "nul characters in strings", + "schema": { "const": "hello\u0000there" }, + "tests": [ + { + "description": "match string with nul", + "data": "hello\u0000there", + "valid": true + }, + { + "description": "do not match string lacking nul", + "data": "hellothere", + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/contains.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/contains.json new file mode 100644 index 0000000..215da98 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/contains.json @@ -0,0 +1,150 @@ +[ + { + "description": "contains keyword validation", + "schema": { + "contains": {"minimum": 5} + }, + "tests": [ + { + "description": "array with item matching schema (5) is valid", + "data": [3, 4, 5], + "valid": true + }, + { + "description": "array with item matching schema (6) is valid", + "data": [3, 4, 6], + "valid": true + }, + { + "description": "array with two items matching schema (5, 6) is valid", + "data": [3, 4, 5, 6], + "valid": true + }, + { + "description": "array without items matching schema is invalid", + "data": [2, 3, 4], + "valid": false + }, + { + "description": "empty array is invalid", + "data": [], + "valid": false + }, + { + "description": "not array is valid", + "data": {}, + "valid": true + } + ] + }, + { + "description": "contains keyword with const keyword", + "schema": { + "contains": { "const": 5 } + }, + "tests": [ + { + "description": "array with item 5 is valid", + "data": [3, 4, 5], + "valid": true + }, + { + "description": "array with two items 5 is valid", + "data": [3, 4, 5, 5], + "valid": true + }, + { + "description": "array without item 5 is invalid", + "data": [1, 2, 3, 4], + "valid": false + } + ] + }, + { + "description": "contains keyword with boolean schema true", + "schema": {"contains": true}, + "tests": [ + { + "description": "any non-empty array is valid", + "data": ["foo"], + "valid": true + }, + { + "description": "empty array is invalid", + "data": [], + "valid": false + } + ] + }, + { + "description": "contains keyword with boolean schema false", + "schema": {"contains": false}, + "tests": [ + { + "description": "any non-empty array is invalid", + "data": ["foo"], + "valid": false + }, + { + "description": "empty array is invalid", + "data": [], + "valid": false + }, + { + "description": "non-arrays are valid", + "data": "contains does not apply to strings", + "valid": true + } + ] + }, + { + "description": "items + contains", + "schema": { + "items": { "multipleOf": 2 }, + "contains": { "multipleOf": 3 } + }, + "tests": [ + { + "description": "matches items, does not match contains", + "data": [ 2, 4, 8 ], + "valid": false + }, + { + "description": "does not match items, matches contains", + "data": [ 3, 6, 9 ], + "valid": false + }, + { + "description": "matches both items and contains", + "data": [ 6, 12 ], + "valid": true + }, + { + "description": "matches neither items nor contains", + "data": [ 1, 5 ], + "valid": false + } + ] + }, + { + "description": "contains with false if subschema", + "schema": { + "contains": { + "if": false, + "else": true + } + }, + "tests": [ + { + "description": "any non-empty array is valid", + "data": ["foo"], + "valid": true + }, + { + "description": "empty array is invalid", + "data": [], + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/default.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/default.json new file mode 100644 index 0000000..289a9b6 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/default.json @@ -0,0 +1,79 @@ +[ + { + "description": "invalid type for default", + "schema": { + "properties": { + "foo": { + "type": "integer", + "default": [] + } + } + }, + "tests": [ + { + "description": "valid when property is specified", + "data": {"foo": 13}, + "valid": true + }, + { + "description": "still valid when the invalid default is used", + "data": {}, + "valid": true + } + ] + }, + { + "description": "invalid string value for default", + "schema": { + "properties": { + "bar": { + "type": "string", + "minLength": 4, + "default": "bad" + } + } + }, + "tests": [ + { + "description": "valid when property is specified", + "data": {"bar": "good"}, + "valid": true + }, + { + "description": "still valid when the invalid default is used", + "data": {}, + "valid": true + } + ] + }, + { + "description": "the default keyword does not do anything if the property is missing", + "schema": { + "type": "object", + "properties": { + "alpha": { + "type": "number", + "maximum": 3, + "default": 5 + } + } + }, + "tests": [ + { + "description": "an explicit property value is checked against maximum (passing)", + "data": { "alpha": 1 }, + "valid": true + }, + { + "description": "an explicit property value is checked against maximum (failing)", + "data": { "alpha": 5 }, + "valid": false + }, + { + "description": "missing properties are not filled in with the default", + "data": {}, + "valid": true + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/definitions.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/definitions.json new file mode 100644 index 0000000..afe396e --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/definitions.json @@ -0,0 +1,26 @@ +[ + { + "description": "validate definition against metaschema", + "schema": {"$ref": "http://json-schema.org/draft-07/schema#"}, + "tests": [ + { + "description": "valid definition schema", + "data": { + "definitions": { + "foo": {"type": "integer"} + } + }, + "valid": true + }, + { + "description": "invalid definition schema", + "data": { + "definitions": { + "foo": {"type": 1} + } + }, + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/dependencies.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/dependencies.json new file mode 100644 index 0000000..a5e5428 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/dependencies.json @@ -0,0 +1,248 @@ +[ + { + "description": "dependencies", + "schema": { + "dependencies": {"bar": ["foo"]} + }, + "tests": [ + { + "description": "neither", + "data": {}, + "valid": true + }, + { + "description": "nondependant", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "with dependency", + "data": {"foo": 1, "bar": 2}, + "valid": true + }, + { + "description": "missing dependency", + "data": {"bar": 2}, + "valid": false + }, + { + "description": "ignores arrays", + "data": ["bar"], + "valid": true + }, + { + "description": "ignores strings", + "data": "foobar", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + }, + { + "description": "dependencies with empty array", + "schema": { + "dependencies": {"bar": []} + }, + "tests": [ + { + "description": "empty object", + "data": {}, + "valid": true + }, + { + "description": "object with one property", + "data": {"bar": 2}, + "valid": true + }, + { + "description": "non-object is valid", + "data": 1, + "valid": true + } + ] + }, + { + "description": "multiple dependencies", + "schema": { + "dependencies": {"quux": ["foo", "bar"]} + }, + "tests": [ + { + "description": "neither", + "data": {}, + "valid": true + }, + { + "description": "nondependants", + "data": {"foo": 1, "bar": 2}, + "valid": true + }, + { + "description": "with dependencies", + "data": {"foo": 1, "bar": 2, "quux": 3}, + "valid": true + }, + { + "description": "missing dependency", + "data": {"foo": 1, "quux": 2}, + "valid": false + }, + { + "description": "missing other dependency", + "data": {"bar": 1, "quux": 2}, + "valid": false + }, + { + "description": "missing both dependencies", + "data": {"quux": 1}, + "valid": false + } + ] + }, + { + "description": "multiple dependencies subschema", + "schema": { + "dependencies": { + "bar": { + "properties": { + "foo": {"type": "integer"}, + "bar": {"type": "integer"} + } + } + } + }, + "tests": [ + { + "description": "valid", + "data": {"foo": 1, "bar": 2}, + "valid": true + }, + { + "description": "no dependency", + "data": {"foo": "quux"}, + "valid": true + }, + { + "description": "wrong type", + "data": {"foo": "quux", "bar": 2}, + "valid": false + }, + { + "description": "wrong type other", + "data": {"foo": 2, "bar": "quux"}, + "valid": false + }, + { + "description": "wrong type both", + "data": {"foo": "quux", "bar": "quux"}, + "valid": false + } + ] + }, + { + "description": "dependencies with boolean subschemas", + "schema": { + "dependencies": { + "foo": true, + "bar": false + } + }, + "tests": [ + { + "description": "object with property having schema true is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "object with property having schema false is invalid", + "data": {"bar": 2}, + "valid": false + }, + { + "description": "object with both properties is invalid", + "data": {"foo": 1, "bar": 2}, + "valid": false + }, + { + "description": "empty object is valid", + "data": {}, + "valid": true + } + ] + }, + { + "description": "dependencies with escaped characters", + "schema": { + "dependencies": { + "foo\nbar": ["foo\rbar"], + "foo\tbar": { + "minProperties": 4 + }, + "foo'bar": {"required": ["foo\"bar"]}, + "foo\"bar": ["foo'bar"] + } + }, + "tests": [ + { + "description": "valid object 1", + "data": { + "foo\nbar": 1, + "foo\rbar": 2 + }, + "valid": true + }, + { + "description": "valid object 2", + "data": { + "foo\tbar": 1, + "a": 2, + "b": 3, + "c": 4 + }, + "valid": true + }, + { + "description": "valid object 3", + "data": { + "foo'bar": 1, + "foo\"bar": 2 + }, + "valid": true + }, + { + "description": "invalid object 1", + "data": { + "foo\nbar": 1, + "foo": 2 + }, + "valid": false + }, + { + "description": "invalid object 2", + "data": { + "foo\tbar": 1, + "a": 2 + }, + "valid": false + }, + { + "description": "invalid object 3", + "data": { + "foo'bar": 1 + }, + "valid": false + }, + { + "description": "invalid object 4", + "data": { + "foo\"bar": 2 + }, + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/enum.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/enum.json new file mode 100644 index 0000000..f085097 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/enum.json @@ -0,0 +1,236 @@ +[ + { + "description": "simple enum validation", + "schema": {"enum": [1, 2, 3]}, + "tests": [ + { + "description": "one of the enum is valid", + "data": 1, + "valid": true + }, + { + "description": "something else is invalid", + "data": 4, + "valid": false + } + ] + }, + { + "description": "heterogeneous enum validation", + "schema": {"enum": [6, "foo", [], true, {"foo": 12}]}, + "tests": [ + { + "description": "one of the enum is valid", + "data": [], + "valid": true + }, + { + "description": "something else is invalid", + "data": null, + "valid": false + }, + { + "description": "objects are deep compared", + "data": {"foo": false}, + "valid": false + }, + { + "description": "valid object matches", + "data": {"foo": 12}, + "valid": true + }, + { + "description": "extra properties in object is invalid", + "data": {"foo": 12, "boo": 42}, + "valid": false + } + ] + }, + { + "description": "heterogeneous enum-with-null validation", + "schema": { "enum": [6, null] }, + "tests": [ + { + "description": "null is valid", + "data": null, + "valid": true + }, + { + "description": "number is valid", + "data": 6, + "valid": true + }, + { + "description": "something else is invalid", + "data": "test", + "valid": false + } + ] + }, + { + "description": "enums in properties", + "schema": { + "type":"object", + "properties": { + "foo": {"enum":["foo"]}, + "bar": {"enum":["bar"]} + }, + "required": ["bar"] + }, + "tests": [ + { + "description": "both properties are valid", + "data": {"foo":"foo", "bar":"bar"}, + "valid": true + }, + { + "description": "wrong foo value", + "data": {"foo":"foot", "bar":"bar"}, + "valid": false + }, + { + "description": "wrong bar value", + "data": {"foo":"foo", "bar":"bart"}, + "valid": false + }, + { + "description": "missing optional property is valid", + "data": {"bar":"bar"}, + "valid": true + }, + { + "description": "missing required property is invalid", + "data": {"foo":"foo"}, + "valid": false + }, + { + "description": "missing all properties is invalid", + "data": {}, + "valid": false + } + ] + }, + { + "description": "enum with escaped characters", + "schema": { + "enum": ["foo\nbar", "foo\rbar"] + }, + "tests": [ + { + "description": "member 1 is valid", + "data": "foo\nbar", + "valid": true + }, + { + "description": "member 2 is valid", + "data": "foo\rbar", + "valid": true + }, + { + "description": "another string is invalid", + "data": "abc", + "valid": false + } + ] + }, + { + "description": "enum with false does not match 0", + "schema": {"enum": [false]}, + "tests": [ + { + "description": "false is valid", + "data": false, + "valid": true + }, + { + "description": "integer zero is invalid", + "data": 0, + "valid": false + }, + { + "description": "float zero is invalid", + "data": 0.0, + "valid": false + } + ] + }, + { + "description": "enum with true does not match 1", + "schema": {"enum": [true]}, + "tests": [ + { + "description": "true is valid", + "data": true, + "valid": true + }, + { + "description": "integer one is invalid", + "data": 1, + "valid": false + }, + { + "description": "float one is invalid", + "data": 1.0, + "valid": false + } + ] + }, + { + "description": "enum with 0 does not match false", + "schema": {"enum": [0]}, + "tests": [ + { + "description": "false is invalid", + "data": false, + "valid": false + }, + { + "description": "integer zero is valid", + "data": 0, + "valid": true + }, + { + "description": "float zero is valid", + "data": 0.0, + "valid": true + } + ] + }, + { + "description": "enum with 1 does not match true", + "schema": {"enum": [1]}, + "tests": [ + { + "description": "true is invalid", + "data": true, + "valid": false + }, + { + "description": "integer one is valid", + "data": 1, + "valid": true + }, + { + "description": "float one is valid", + "data": 1.0, + "valid": true + } + ] + }, + { + "description": "nul characters in strings", + "schema": { "enum": [ "hello\u0000there" ] }, + "tests": [ + { + "description": "match string with nul", + "data": "hello\u0000there", + "valid": true + }, + { + "description": "do not match string lacking nul", + "data": "hellothere", + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/exclusiveMaximum.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/exclusiveMaximum.json new file mode 100644 index 0000000..dc3cd70 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/exclusiveMaximum.json @@ -0,0 +1,30 @@ +[ + { + "description": "exclusiveMaximum validation", + "schema": { + "exclusiveMaximum": 3.0 + }, + "tests": [ + { + "description": "below the exclusiveMaximum is valid", + "data": 2.2, + "valid": true + }, + { + "description": "boundary point is invalid", + "data": 3.0, + "valid": false + }, + { + "description": "above the exclusiveMaximum is invalid", + "data": 3.5, + "valid": false + }, + { + "description": "ignores non-numbers", + "data": "x", + "valid": true + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/exclusiveMinimum.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/exclusiveMinimum.json new file mode 100644 index 0000000..b38d7ec --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/exclusiveMinimum.json @@ -0,0 +1,30 @@ +[ + { + "description": "exclusiveMinimum validation", + "schema": { + "exclusiveMinimum": 1.1 + }, + "tests": [ + { + "description": "above the exclusiveMinimum is valid", + "data": 1.2, + "valid": true + }, + { + "description": "boundary point is invalid", + "data": 1.1, + "valid": false + }, + { + "description": "below the exclusiveMinimum is invalid", + "data": 0.6, + "valid": false + }, + { + "description": "ignores non-numbers", + "data": "x", + "valid": true + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/format.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/format.json new file mode 100644 index 0000000..e2447d6 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/format.json @@ -0,0 +1,614 @@ +[ + { + "description": "email format", + "schema": { "format": "email" }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "valid": true + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "valid": true + }, + { + "description": "all string formats ignore objects", + "data": {}, + "valid": true + }, + { + "description": "all string formats ignore arrays", + "data": [], + "valid": true + }, + { + "description": "all string formats ignore booleans", + "data": false, + "valid": true + }, + { + "description": "all string formats ignore nulls", + "data": null, + "valid": true + } + ] + }, + { + "description": "idn-email format", + "schema": { "format": "idn-email" }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "valid": true + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "valid": true + }, + { + "description": "all string formats ignore objects", + "data": {}, + "valid": true + }, + { + "description": "all string formats ignore arrays", + "data": [], + "valid": true + }, + { + "description": "all string formats ignore booleans", + "data": false, + "valid": true + }, + { + "description": "all string formats ignore nulls", + "data": null, + "valid": true + } + ] + }, + { + "description": "regex format", + "schema": { "format": "regex" }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "valid": true + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "valid": true + }, + { + "description": "all string formats ignore objects", + "data": {}, + "valid": true + }, + { + "description": "all string formats ignore arrays", + "data": [], + "valid": true + }, + { + "description": "all string formats ignore booleans", + "data": false, + "valid": true + }, + { + "description": "all string formats ignore nulls", + "data": null, + "valid": true + } + ] + }, + { + "description": "ipv4 format", + "schema": { "format": "ipv4" }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "valid": true + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "valid": true + }, + { + "description": "all string formats ignore objects", + "data": {}, + "valid": true + }, + { + "description": "all string formats ignore arrays", + "data": [], + "valid": true + }, + { + "description": "all string formats ignore booleans", + "data": false, + "valid": true + }, + { + "description": "all string formats ignore nulls", + "data": null, + "valid": true + } + ] + }, + { + "description": "ipv6 format", + "schema": { "format": "ipv6" }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "valid": true + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "valid": true + }, + { + "description": "all string formats ignore objects", + "data": {}, + "valid": true + }, + { + "description": "all string formats ignore arrays", + "data": [], + "valid": true + }, + { + "description": "all string formats ignore booleans", + "data": false, + "valid": true + }, + { + "description": "all string formats ignore nulls", + "data": null, + "valid": true + } + ] + }, + { + "description": "idn-hostname format", + "schema": { "format": "idn-hostname" }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "valid": true + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "valid": true + }, + { + "description": "all string formats ignore objects", + "data": {}, + "valid": true + }, + { + "description": "all string formats ignore arrays", + "data": [], + "valid": true + }, + { + "description": "all string formats ignore booleans", + "data": false, + "valid": true + }, + { + "description": "all string formats ignore nulls", + "data": null, + "valid": true + } + ] + }, + { + "description": "hostname format", + "schema": { "format": "hostname" }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "valid": true + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "valid": true + }, + { + "description": "all string formats ignore objects", + "data": {}, + "valid": true + }, + { + "description": "all string formats ignore arrays", + "data": [], + "valid": true + }, + { + "description": "all string formats ignore booleans", + "data": false, + "valid": true + }, + { + "description": "all string formats ignore nulls", + "data": null, + "valid": true + } + ] + }, + { + "description": "date format", + "schema": { "format": "date" }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "valid": true + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "valid": true + }, + { + "description": "all string formats ignore objects", + "data": {}, + "valid": true + }, + { + "description": "all string formats ignore arrays", + "data": [], + "valid": true + }, + { + "description": "all string formats ignore booleans", + "data": false, + "valid": true + }, + { + "description": "all string formats ignore nulls", + "data": null, + "valid": true + } + ] + }, + { + "description": "date-time format", + "schema": { "format": "date-time" }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "valid": true + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "valid": true + }, + { + "description": "all string formats ignore objects", + "data": {}, + "valid": true + }, + { + "description": "all string formats ignore arrays", + "data": [], + "valid": true + }, + { + "description": "all string formats ignore booleans", + "data": false, + "valid": true + }, + { + "description": "all string formats ignore nulls", + "data": null, + "valid": true + } + ] + }, + { + "description": "time format", + "schema": { "format": "time" }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "valid": true + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "valid": true + }, + { + "description": "all string formats ignore objects", + "data": {}, + "valid": true + }, + { + "description": "all string formats ignore arrays", + "data": [], + "valid": true + }, + { + "description": "all string formats ignore booleans", + "data": false, + "valid": true + }, + { + "description": "all string formats ignore nulls", + "data": null, + "valid": true + } + ] + }, + { + "description": "json-pointer format", + "schema": { "format": "json-pointer" }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "valid": true + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "valid": true + }, + { + "description": "all string formats ignore objects", + "data": {}, + "valid": true + }, + { + "description": "all string formats ignore arrays", + "data": [], + "valid": true + }, + { + "description": "all string formats ignore booleans", + "data": false, + "valid": true + }, + { + "description": "all string formats ignore nulls", + "data": null, + "valid": true + } + ] + }, + { + "description": "relative-json-pointer format", + "schema": { "format": "relative-json-pointer" }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "valid": true + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "valid": true + }, + { + "description": "all string formats ignore objects", + "data": {}, + "valid": true + }, + { + "description": "all string formats ignore arrays", + "data": [], + "valid": true + }, + { + "description": "all string formats ignore booleans", + "data": false, + "valid": true + }, + { + "description": "all string formats ignore nulls", + "data": null, + "valid": true + } + ] + }, + { + "description": "iri format", + "schema": { "format": "iri" }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "valid": true + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "valid": true + }, + { + "description": "all string formats ignore objects", + "data": {}, + "valid": true + }, + { + "description": "all string formats ignore arrays", + "data": [], + "valid": true + }, + { + "description": "all string formats ignore booleans", + "data": false, + "valid": true + }, + { + "description": "all string formats ignore nulls", + "data": null, + "valid": true + } + ] + }, + { + "description": "iri-reference format", + "schema": { "format": "iri-reference" }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "valid": true + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "valid": true + }, + { + "description": "all string formats ignore objects", + "data": {}, + "valid": true + }, + { + "description": "all string formats ignore arrays", + "data": [], + "valid": true + }, + { + "description": "all string formats ignore booleans", + "data": false, + "valid": true + }, + { + "description": "all string formats ignore nulls", + "data": null, + "valid": true + } + ] + }, + { + "description": "uri format", + "schema": { "format": "uri" }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "valid": true + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "valid": true + }, + { + "description": "all string formats ignore objects", + "data": {}, + "valid": true + }, + { + "description": "all string formats ignore arrays", + "data": [], + "valid": true + }, + { + "description": "all string formats ignore booleans", + "data": false, + "valid": true + }, + { + "description": "all string formats ignore nulls", + "data": null, + "valid": true + } + ] + }, + { + "description": "uri-reference format", + "schema": { "format": "uri-reference" }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "valid": true + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "valid": true + }, + { + "description": "all string formats ignore objects", + "data": {}, + "valid": true + }, + { + "description": "all string formats ignore arrays", + "data": [], + "valid": true + }, + { + "description": "all string formats ignore booleans", + "data": false, + "valid": true + }, + { + "description": "all string formats ignore nulls", + "data": null, + "valid": true + } + ] + }, + { + "description": "uri-template format", + "schema": { "format": "uri-template" }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "valid": true + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "valid": true + }, + { + "description": "all string formats ignore objects", + "data": {}, + "valid": true + }, + { + "description": "all string formats ignore arrays", + "data": [], + "valid": true + }, + { + "description": "all string formats ignore booleans", + "data": false, + "valid": true + }, + { + "description": "all string formats ignore nulls", + "data": null, + "valid": true + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/id.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/id.json new file mode 100644 index 0000000..b58e0d0 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/id.json @@ -0,0 +1,53 @@ +[ + { + "description": "id inside an enum is not a real identifier", + "comment": "the implementation must not be confused by an id buried in the enum", + "schema": { + "definitions": { + "id_in_enum": { + "enum": [ + { + "$id": "https://localhost:1234/id/my_identifier.json", + "type": "null" + } + ] + }, + "real_id_in_schema": { + "$id": "https://localhost:1234/id/my_identifier.json", + "type": "string" + }, + "zzz_id_in_const": { + "const": { + "$id": "https://localhost:1234/id/my_identifier.json", + "type": "null" + } + } + }, + "anyOf": [ + { "$ref": "#/definitions/id_in_enum" }, + { "$ref": "https://localhost:1234/id/my_identifier.json" } + ] + }, + "tests": [ + { + "description": "exact match to enum, and type matches", + "data": { + "$id": "https://localhost:1234/id/my_identifier.json", + "type": "null" + }, + "valid": true + }, + { + "description": "match $ref to id", + "data": "a string to match #/definitions/id_in_enum", + "valid": true + }, + { + "description": "no match on enum or $ref to id", + "data": 1, + "valid": false + } + ] + } + +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/if-then-else.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/if-then-else.json new file mode 100644 index 0000000..284e919 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/if-then-else.json @@ -0,0 +1,258 @@ +[ + { + "description": "ignore if without then or else", + "schema": { + "if": { + "const": 0 + } + }, + "tests": [ + { + "description": "valid when valid against lone if", + "data": 0, + "valid": true + }, + { + "description": "valid when invalid against lone if", + "data": "hello", + "valid": true + } + ] + }, + { + "description": "ignore then without if", + "schema": { + "then": { + "const": 0 + } + }, + "tests": [ + { + "description": "valid when valid against lone then", + "data": 0, + "valid": true + }, + { + "description": "valid when invalid against lone then", + "data": "hello", + "valid": true + } + ] + }, + { + "description": "ignore else without if", + "schema": { + "else": { + "const": 0 + } + }, + "tests": [ + { + "description": "valid when valid against lone else", + "data": 0, + "valid": true + }, + { + "description": "valid when invalid against lone else", + "data": "hello", + "valid": true + } + ] + }, + { + "description": "if and then without else", + "schema": { + "if": { + "exclusiveMaximum": 0 + }, + "then": { + "minimum": -10 + } + }, + "tests": [ + { + "description": "valid through then", + "data": -1, + "valid": true + }, + { + "description": "invalid through then", + "data": -100, + "valid": false + }, + { + "description": "valid when if test fails", + "data": 3, + "valid": true + } + ] + }, + { + "description": "if and else without then", + "schema": { + "if": { + "exclusiveMaximum": 0 + }, + "else": { + "multipleOf": 2 + } + }, + "tests": [ + { + "description": "valid when if test passes", + "data": -1, + "valid": true + }, + { + "description": "valid through else", + "data": 4, + "valid": true + }, + { + "description": "invalid through else", + "data": 3, + "valid": false + } + ] + }, + { + "description": "validate against correct branch, then vs else", + "schema": { + "if": { + "exclusiveMaximum": 0 + }, + "then": { + "minimum": -10 + }, + "else": { + "multipleOf": 2 + } + }, + "tests": [ + { + "description": "valid through then", + "data": -1, + "valid": true + }, + { + "description": "invalid through then", + "data": -100, + "valid": false + }, + { + "description": "valid through else", + "data": 4, + "valid": true + }, + { + "description": "invalid through else", + "data": 3, + "valid": false + } + ] + }, + { + "description": "non-interference across combined schemas", + "schema": { + "allOf": [ + { + "if": { + "exclusiveMaximum": 0 + } + }, + { + "then": { + "minimum": -10 + } + }, + { + "else": { + "multipleOf": 2 + } + } + ] + }, + "tests": [ + { + "description": "valid, but would have been invalid through then", + "data": -100, + "valid": true + }, + { + "description": "valid, but would have been invalid through else", + "data": 3, + "valid": true + } + ] + }, + { + "description": "if with boolean schema true", + "schema": { + "if": true, + "then": { "const": "then" }, + "else": { "const": "else" } + }, + "tests": [ + { + "description": "boolean schema true in if always chooses the then path (valid)", + "data": "then", + "valid": true + }, + { + "description": "boolean schema true in if always chooses the then path (invalid)", + "data": "else", + "valid": false + } + ] + }, + { + "description": "if with boolean schema false", + "schema": { + "if": false, + "then": { "const": "then" }, + "else": { "const": "else" } + }, + "tests": [ + { + "description": "boolean schema false in if always chooses the else path (invalid)", + "data": "then", + "valid": false + }, + { + "description": "boolean schema false in if always chooses the else path (valid)", + "data": "else", + "valid": true + } + ] + }, + { + "description": "if appears at the end when serialized (keyword processing sequence)", + "schema": { + "then": { "const": "yes" }, + "else": { "const": "other" }, + "if": { "maxLength": 4 } + }, + "tests": [ + { + "description": "yes redirects to then and passes", + "data": "yes", + "valid": true + }, + { + "description": "other redirects to else and passes", + "data": "other", + "valid": true + }, + { + "description": "no redirects to then and fails", + "data": "no", + "valid": false + }, + { + "description": "invalid redirects to else and fails", + "data": "invalid", + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/infinite-loop-detection.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/infinite-loop-detection.json new file mode 100644 index 0000000..f98c74f --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/infinite-loop-detection.json @@ -0,0 +1,36 @@ +[ + { + "description": "evaluating the same schema location against the same data location twice is not a sign of an infinite loop", + "schema": { + "definitions": { + "int": { "type": "integer" } + }, + "allOf": [ + { + "properties": { + "foo": { + "$ref": "#/definitions/int" + } + } + }, + { + "additionalProperties": { + "$ref": "#/definitions/int" + } + } + ] + }, + "tests": [ + { + "description": "passing case", + "data": { "foo": 1 }, + "valid": true + }, + { + "description": "failing case", + "data": { "foo": "a string" }, + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/items.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/items.json new file mode 100644 index 0000000..67f1184 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/items.json @@ -0,0 +1,250 @@ +[ + { + "description": "a schema given for items", + "schema": { + "items": {"type": "integer"} + }, + "tests": [ + { + "description": "valid items", + "data": [ 1, 2, 3 ], + "valid": true + }, + { + "description": "wrong type of items", + "data": [1, "x"], + "valid": false + }, + { + "description": "ignores non-arrays", + "data": {"foo" : "bar"}, + "valid": true + }, + { + "description": "JavaScript pseudo-array is valid", + "data": { + "0": "invalid", + "length": 1 + }, + "valid": true + } + ] + }, + { + "description": "an array of schemas for items", + "schema": { + "items": [ + {"type": "integer"}, + {"type": "string"} + ] + }, + "tests": [ + { + "description": "correct types", + "data": [ 1, "foo" ], + "valid": true + }, + { + "description": "wrong types", + "data": [ "foo", 1 ], + "valid": false + }, + { + "description": "incomplete array of items", + "data": [ 1 ], + "valid": true + }, + { + "description": "array with additional items", + "data": [ 1, "foo", true ], + "valid": true + }, + { + "description": "empty array", + "data": [ ], + "valid": true + }, + { + "description": "JavaScript pseudo-array is valid", + "data": { + "0": "invalid", + "1": "valid", + "length": 2 + }, + "valid": true + } + ] + }, + { + "description": "items with boolean schema (true)", + "schema": {"items": true}, + "tests": [ + { + "description": "any array is valid", + "data": [ 1, "foo", true ], + "valid": true + }, + { + "description": "empty array is valid", + "data": [], + "valid": true + } + ] + }, + { + "description": "items with boolean schema (false)", + "schema": {"items": false}, + "tests": [ + { + "description": "any non-empty array is invalid", + "data": [ 1, "foo", true ], + "valid": false + }, + { + "description": "empty array is valid", + "data": [], + "valid": true + } + ] + }, + { + "description": "items with boolean schemas", + "schema": { + "items": [true, false] + }, + "tests": [ + { + "description": "array with one item is valid", + "data": [ 1 ], + "valid": true + }, + { + "description": "array with two items is invalid", + "data": [ 1, "foo" ], + "valid": false + }, + { + "description": "empty array is valid", + "data": [], + "valid": true + } + ] + }, + { + "description": "items and subitems", + "schema": { + "definitions": { + "item": { + "type": "array", + "additionalItems": false, + "items": [ + { "$ref": "#/definitions/sub-item" }, + { "$ref": "#/definitions/sub-item" } + ] + }, + "sub-item": { + "type": "object", + "required": ["foo"] + } + }, + "type": "array", + "additionalItems": false, + "items": [ + { "$ref": "#/definitions/item" }, + { "$ref": "#/definitions/item" }, + { "$ref": "#/definitions/item" } + ] + }, + "tests": [ + { + "description": "valid items", + "data": [ + [ {"foo": null}, {"foo": null} ], + [ {"foo": null}, {"foo": null} ], + [ {"foo": null}, {"foo": null} ] + ], + "valid": true + }, + { + "description": "too many items", + "data": [ + [ {"foo": null}, {"foo": null} ], + [ {"foo": null}, {"foo": null} ], + [ {"foo": null}, {"foo": null} ], + [ {"foo": null}, {"foo": null} ] + ], + "valid": false + }, + { + "description": "too many sub-items", + "data": [ + [ {"foo": null}, {"foo": null}, {"foo": null} ], + [ {"foo": null}, {"foo": null} ], + [ {"foo": null}, {"foo": null} ] + ], + "valid": false + }, + { + "description": "wrong item", + "data": [ + {"foo": null}, + [ {"foo": null}, {"foo": null} ], + [ {"foo": null}, {"foo": null} ] + ], + "valid": false + }, + { + "description": "wrong sub-item", + "data": [ + [ {}, {"foo": null} ], + [ {"foo": null}, {"foo": null} ], + [ {"foo": null}, {"foo": null} ] + ], + "valid": false + }, + { + "description": "fewer items is valid", + "data": [ + [ {"foo": null} ], + [ {"foo": null} ] + ], + "valid": true + } + ] + }, + { + "description": "nested items", + "schema": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "number" + } + } + } + } + }, + "tests": [ + { + "description": "valid nested array", + "data": [[[[1]], [[2],[3]]], [[[4], [5], [6]]]], + "valid": true + }, + { + "description": "nested array with invalid type", + "data": [[[["1"]], [[2],[3]]], [[[4], [5], [6]]]], + "valid": false + }, + { + "description": "not deep enough", + "data": [[[1], [2],[3]], [[4], [5], [6]]], + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/maxItems.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/maxItems.json new file mode 100644 index 0000000..3b53a6b --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/maxItems.json @@ -0,0 +1,28 @@ +[ + { + "description": "maxItems validation", + "schema": {"maxItems": 2}, + "tests": [ + { + "description": "shorter is valid", + "data": [1], + "valid": true + }, + { + "description": "exact length is valid", + "data": [1, 2], + "valid": true + }, + { + "description": "too long is invalid", + "data": [1, 2, 3], + "valid": false + }, + { + "description": "ignores non-arrays", + "data": "foobar", + "valid": true + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/maxLength.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/maxLength.json new file mode 100644 index 0000000..811d35b --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/maxLength.json @@ -0,0 +1,33 @@ +[ + { + "description": "maxLength validation", + "schema": {"maxLength": 2}, + "tests": [ + { + "description": "shorter is valid", + "data": "f", + "valid": true + }, + { + "description": "exact length is valid", + "data": "fo", + "valid": true + }, + { + "description": "too long is invalid", + "data": "foo", + "valid": false + }, + { + "description": "ignores non-strings", + "data": 100, + "valid": true + }, + { + "description": "two supplementary Unicode code points is long enough", + "data": "\uD83D\uDCA9\uD83D\uDCA9", + "valid": true + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/maxProperties.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/maxProperties.json new file mode 100644 index 0000000..aa7209f --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/maxProperties.json @@ -0,0 +1,54 @@ +[ + { + "description": "maxProperties validation", + "schema": {"maxProperties": 2}, + "tests": [ + { + "description": "shorter is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "exact length is valid", + "data": {"foo": 1, "bar": 2}, + "valid": true + }, + { + "description": "too long is invalid", + "data": {"foo": 1, "bar": 2, "baz": 3}, + "valid": false + }, + { + "description": "ignores arrays", + "data": [1, 2, 3], + "valid": true + }, + { + "description": "ignores strings", + "data": "foobar", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + }, + { + "description": "maxProperties = 0 means the object is empty", + "schema": { "maxProperties": 0 }, + "tests": [ + { + "description": "no properties is valid", + "data": {}, + "valid": true + }, + { + "description": "one property is invalid", + "data": { "foo": 1 }, + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/maximum.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/maximum.json new file mode 100644 index 0000000..6844a39 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/maximum.json @@ -0,0 +1,54 @@ +[ + { + "description": "maximum validation", + "schema": {"maximum": 3.0}, + "tests": [ + { + "description": "below the maximum is valid", + "data": 2.6, + "valid": true + }, + { + "description": "boundary point is valid", + "data": 3.0, + "valid": true + }, + { + "description": "above the maximum is invalid", + "data": 3.5, + "valid": false + }, + { + "description": "ignores non-numbers", + "data": "x", + "valid": true + } + ] + }, + { + "description": "maximum validation with unsigned integer", + "schema": {"maximum": 300}, + "tests": [ + { + "description": "below the maximum is invalid", + "data": 299.97, + "valid": true + }, + { + "description": "boundary point integer is valid", + "data": 300, + "valid": true + }, + { + "description": "boundary point float is valid", + "data": 300.00, + "valid": true + }, + { + "description": "above the maximum is invalid", + "data": 300.5, + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/minItems.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/minItems.json new file mode 100644 index 0000000..ed51188 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/minItems.json @@ -0,0 +1,28 @@ +[ + { + "description": "minItems validation", + "schema": {"minItems": 1}, + "tests": [ + { + "description": "longer is valid", + "data": [1, 2], + "valid": true + }, + { + "description": "exact length is valid", + "data": [1], + "valid": true + }, + { + "description": "too short is invalid", + "data": [], + "valid": false + }, + { + "description": "ignores non-arrays", + "data": "", + "valid": true + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/minLength.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/minLength.json new file mode 100644 index 0000000..3f09158 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/minLength.json @@ -0,0 +1,33 @@ +[ + { + "description": "minLength validation", + "schema": {"minLength": 2}, + "tests": [ + { + "description": "longer is valid", + "data": "foo", + "valid": true + }, + { + "description": "exact length is valid", + "data": "fo", + "valid": true + }, + { + "description": "too short is invalid", + "data": "f", + "valid": false + }, + { + "description": "ignores non-strings", + "data": 1, + "valid": true + }, + { + "description": "one supplementary Unicode code point is not long enough", + "data": "\uD83D\uDCA9", + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/minProperties.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/minProperties.json new file mode 100644 index 0000000..49a0726 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/minProperties.json @@ -0,0 +1,38 @@ +[ + { + "description": "minProperties validation", + "schema": {"minProperties": 1}, + "tests": [ + { + "description": "longer is valid", + "data": {"foo": 1, "bar": 2}, + "valid": true + }, + { + "description": "exact length is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "too short is invalid", + "data": {}, + "valid": false + }, + { + "description": "ignores arrays", + "data": [], + "valid": true + }, + { + "description": "ignores strings", + "data": "", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/minimum.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/minimum.json new file mode 100644 index 0000000..21ae50e --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/minimum.json @@ -0,0 +1,69 @@ +[ + { + "description": "minimum validation", + "schema": {"minimum": 1.1}, + "tests": [ + { + "description": "above the minimum is valid", + "data": 2.6, + "valid": true + }, + { + "description": "boundary point is valid", + "data": 1.1, + "valid": true + }, + { + "description": "below the minimum is invalid", + "data": 0.6, + "valid": false + }, + { + "description": "ignores non-numbers", + "data": "x", + "valid": true + } + ] + }, + { + "description": "minimum validation with signed integer", + "schema": {"minimum": -2}, + "tests": [ + { + "description": "negative above the minimum is valid", + "data": -1, + "valid": true + }, + { + "description": "positive above the minimum is valid", + "data": 0, + "valid": true + }, + { + "description": "boundary point is valid", + "data": -2, + "valid": true + }, + { + "description": "boundary point with float is valid", + "data": -2.0, + "valid": true + }, + { + "description": "float below the minimum is invalid", + "data": -2.0001, + "valid": false + }, + { + "description": "int below the minimum is invalid", + "data": -3, + "valid": false + }, + { + "description": "ignores non-numbers", + "data": "x", + "valid": true + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/multipleOf.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/multipleOf.json new file mode 100644 index 0000000..faa87cf --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/multipleOf.json @@ -0,0 +1,71 @@ +[ + { + "description": "by int", + "schema": {"multipleOf": 2}, + "tests": [ + { + "description": "int by int", + "data": 10, + "valid": true + }, + { + "description": "int by int fail", + "data": 7, + "valid": false + }, + { + "description": "ignores non-numbers", + "data": "foo", + "valid": true + } + ] + }, + { + "description": "by number", + "schema": {"multipleOf": 1.5}, + "tests": [ + { + "description": "zero is multiple of anything", + "data": 0, + "valid": true + }, + { + "description": "4.5 is multiple of 1.5", + "data": 4.5, + "valid": true + }, + { + "description": "35 is not multiple of 1.5", + "data": 35, + "valid": false + } + ] + }, + { + "description": "by small number", + "schema": {"multipleOf": 0.0001}, + "tests": [ + { + "description": "0.0075 is multiple of 0.0001", + "data": 0.0075, + "valid": true + }, + { + "description": "0.00751 is not multiple of 0.0001", + "data": 0.00751, + "valid": false + } + ] + }, + { + "description": "invalid instance should not raise error when float division = inf", + "schema": {"type": "integer", "multipleOf": 0.123456789}, + "tests": [ + { + "description": "always invalid, but naive implementations may raise an overflow error", + "data": 1e308, + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/not.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/not.json new file mode 100644 index 0000000..a48a798 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/not.json @@ -0,0 +1,117 @@ +[ + { + "description": "not", + "schema": { + "not": {"type": "integer"} + }, + "tests": [ + { + "description": "allowed", + "data": "foo", + "valid": true + }, + { + "description": "disallowed", + "data": 1, + "valid": false + } + ] + }, + { + "description": "not multiple types", + "schema": { + "not": {"type": ["integer", "boolean"]} + }, + "tests": [ + { + "description": "valid", + "data": "foo", + "valid": true + }, + { + "description": "mismatch", + "data": 1, + "valid": false + }, + { + "description": "other mismatch", + "data": true, + "valid": false + } + ] + }, + { + "description": "not more complex schema", + "schema": { + "not": { + "type": "object", + "properties": { + "foo": { + "type": "string" + } + } + } + }, + "tests": [ + { + "description": "match", + "data": 1, + "valid": true + }, + { + "description": "other match", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "mismatch", + "data": {"foo": "bar"}, + "valid": false + } + ] + }, + { + "description": "forbidden property", + "schema": { + "properties": { + "foo": { + "not": {} + } + } + }, + "tests": [ + { + "description": "property present", + "data": {"foo": 1, "bar": 2}, + "valid": false + }, + { + "description": "property absent", + "data": {"bar": 1, "baz": 2}, + "valid": true + } + ] + }, + { + "description": "not with boolean schema true", + "schema": {"not": true}, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "not with boolean schema false", + "schema": {"not": false}, + "tests": [ + { + "description": "any value is valid", + "data": "foo", + "valid": true + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/oneOf.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/oneOf.json new file mode 100644 index 0000000..eeb7ae8 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/oneOf.json @@ -0,0 +1,274 @@ +[ + { + "description": "oneOf", + "schema": { + "oneOf": [ + { + "type": "integer" + }, + { + "minimum": 2 + } + ] + }, + "tests": [ + { + "description": "first oneOf valid", + "data": 1, + "valid": true + }, + { + "description": "second oneOf valid", + "data": 2.5, + "valid": true + }, + { + "description": "both oneOf valid", + "data": 3, + "valid": false + }, + { + "description": "neither oneOf valid", + "data": 1.5, + "valid": false + } + ] + }, + { + "description": "oneOf with base schema", + "schema": { + "type": "string", + "oneOf" : [ + { + "minLength": 2 + }, + { + "maxLength": 4 + } + ] + }, + "tests": [ + { + "description": "mismatch base schema", + "data": 3, + "valid": false + }, + { + "description": "one oneOf valid", + "data": "foobar", + "valid": true + }, + { + "description": "both oneOf valid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "oneOf with boolean schemas, all true", + "schema": {"oneOf": [true, true, true]}, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "oneOf with boolean schemas, one true", + "schema": {"oneOf": [true, false, false]}, + "tests": [ + { + "description": "any value is valid", + "data": "foo", + "valid": true + } + ] + }, + { + "description": "oneOf with boolean schemas, more than one true", + "schema": {"oneOf": [true, true, false]}, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "oneOf with boolean schemas, all false", + "schema": {"oneOf": [false, false, false]}, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "oneOf complex types", + "schema": { + "oneOf": [ + { + "properties": { + "bar": {"type": "integer"} + }, + "required": ["bar"] + }, + { + "properties": { + "foo": {"type": "string"} + }, + "required": ["foo"] + } + ] + }, + "tests": [ + { + "description": "first oneOf valid (complex)", + "data": {"bar": 2}, + "valid": true + }, + { + "description": "second oneOf valid (complex)", + "data": {"foo": "baz"}, + "valid": true + }, + { + "description": "both oneOf valid (complex)", + "data": {"foo": "baz", "bar": 2}, + "valid": false + }, + { + "description": "neither oneOf valid (complex)", + "data": {"foo": 2, "bar": "quux"}, + "valid": false + } + ] + }, + { + "description": "oneOf with empty schema", + "schema": { + "oneOf": [ + { "type": "number" }, + {} + ] + }, + "tests": [ + { + "description": "one valid - valid", + "data": "foo", + "valid": true + }, + { + "description": "both valid - invalid", + "data": 123, + "valid": false + } + ] + }, + { + "description": "oneOf with required", + "schema": { + "type": "object", + "oneOf": [ + { "required": ["foo", "bar"] }, + { "required": ["foo", "baz"] } + ] + }, + "tests": [ + { + "description": "both invalid - invalid", + "data": {"bar": 2}, + "valid": false + }, + { + "description": "first valid - valid", + "data": {"foo": 1, "bar": 2}, + "valid": true + }, + { + "description": "second valid - valid", + "data": {"foo": 1, "baz": 3}, + "valid": true + }, + { + "description": "both valid - invalid", + "data": {"foo": 1, "bar": 2, "baz" : 3}, + "valid": false + } + ] + }, + { + "description": "oneOf with missing optional property", + "schema": { + "oneOf": [ + { + "properties": { + "bar": true, + "baz": true + }, + "required": ["bar"] + }, + { + "properties": { + "foo": true + }, + "required": ["foo"] + } + ] + }, + "tests": [ + { + "description": "first oneOf valid", + "data": {"bar": 8}, + "valid": true + }, + { + "description": "second oneOf valid", + "data": {"foo": "foo"}, + "valid": true + }, + { + "description": "both oneOf valid", + "data": {"foo": "foo", "bar": 8}, + "valid": false + }, + { + "description": "neither oneOf valid", + "data": {"baz": "quux"}, + "valid": false + } + ] + }, + { + "description": "nested oneOf, to check validation semantics", + "schema": { + "oneOf": [ + { + "oneOf": [ + { + "type": "null" + } + ] + } + ] + }, + "tests": [ + { + "description": "null is valid", + "data": null, + "valid": true + }, + { + "description": "anything non-null is invalid", + "data": 123, + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/bignum.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/bignum.json new file mode 100644 index 0000000..3f49226 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/bignum.json @@ -0,0 +1,93 @@ +[ + { + "description": "integer", + "schema": { "type": "integer" }, + "tests": [ + { + "description": "a bignum is an integer", + "data": 12345678910111213141516171819202122232425262728293031, + "valid": true + }, + { + "description": "a negative bignum is an integer", + "data": -12345678910111213141516171819202122232425262728293031, + "valid": true + } + ] + }, + { + "description": "number", + "schema": { "type": "number" }, + "tests": [ + { + "description": "a bignum is a number", + "data": 98249283749234923498293171823948729348710298301928331, + "valid": true + }, + { + "description": "a negative bignum is a number", + "data": -98249283749234923498293171823948729348710298301928331, + "valid": true + } + ] + }, + { + "description": "string", + "schema": { "type": "string" }, + "tests": [ + { + "description": "a bignum is not a string", + "data": 98249283749234923498293171823948729348710298301928331, + "valid": false + } + ] + }, + { + "description": "integer comparison", + "schema": { "maximum": 18446744073709551615 }, + "tests": [ + { + "description": "comparison works for high numbers", + "data": 18446744073709551600, + "valid": true + } + ] + }, + { + "description": "float comparison with high precision", + "schema": { + "exclusiveMaximum": 972783798187987123879878123.18878137 + }, + "tests": [ + { + "description": "comparison works for high numbers", + "data": 972783798187987123879878123.188781371, + "valid": false + } + ] + }, + { + "description": "integer comparison", + "schema": { "minimum": -18446744073709551615 }, + "tests": [ + { + "description": "comparison works for very negative numbers", + "data": -18446744073709551600, + "valid": true + } + ] + }, + { + "description": "float comparison with high precision on negative numbers", + "schema": { + "exclusiveMinimum": -972783798187987123879878123.18878137 + }, + "tests": [ + { + "description": "comparison works for very negative numbers", + "data": -972783798187987123879878123.188781371, + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/content.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/content.json new file mode 100644 index 0000000..3f5a743 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/content.json @@ -0,0 +1,77 @@ +[ + { + "description": "validation of string-encoded content based on media type", + "schema": { + "contentMediaType": "application/json" + }, + "tests": [ + { + "description": "a valid JSON document", + "data": "{\"foo\": \"bar\"}", + "valid": true + }, + { + "description": "an invalid JSON document", + "data": "{:}", + "valid": false + }, + { + "description": "ignores non-strings", + "data": 100, + "valid": true + } + ] + }, + { + "description": "validation of binary string-encoding", + "schema": { + "contentEncoding": "base64" + }, + "tests": [ + { + "description": "a valid base64 string", + "data": "eyJmb28iOiAiYmFyIn0K", + "valid": true + }, + { + "description": "an invalid base64 string (% is not a valid character)", + "data": "eyJmb28iOi%iYmFyIn0K", + "valid": false + }, + { + "description": "ignores non-strings", + "data": 100, + "valid": true + } + ] + }, + { + "description": "validation of binary-encoded media type documents", + "schema": { + "contentMediaType": "application/json", + "contentEncoding": "base64" + }, + "tests": [ + { + "description": "a valid base64-encoded JSON document", + "data": "eyJmb28iOiAiYmFyIn0K", + "valid": true + }, + { + "description": "a validly-encoded invalid JSON document", + "data": "ezp9Cg==", + "valid": false + }, + { + "description": "an invalid base64 string that is valid JSON", + "data": "{}", + "valid": false + }, + { + "description": "ignores non-strings", + "data": 100, + "valid": true + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/ecmascript-regex.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/ecmascript-regex.json new file mode 100644 index 0000000..fb02e99 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/ecmascript-regex.json @@ -0,0 +1,292 @@ +[ + { + "description": "ECMA 262 regex $ does not match trailing newline", + "schema": { + "type": "string", + "pattern": "^abc$" + }, + "tests": [ + { + "description": "matches in Python, but should not in jsonschema", + "data": "abc\\n", + "valid": false + }, + { + "description": "should match", + "data": "abc", + "valid": true + } + ] + }, + { + "description": "ECMA 262 regex converts \\t to horizontal tab", + "schema": { + "type": "string", + "pattern": "^\\t$" + }, + "tests": [ + { + "description": "does not match", + "data": "\\t", + "valid": false + }, + { + "description": "matches", + "data": "\u0009", + "valid": true + } + ] + }, + { + "description": "ECMA 262 regex escapes control codes with \\c and upper letter", + "schema": { + "type": "string", + "pattern": "^\\cC$" + }, + "tests": [ + { + "description": "does not match", + "data": "\\cC", + "valid": false + }, + { + "description": "matches", + "data": "\u0003", + "valid": true + } + ] + }, + { + "description": "ECMA 262 regex escapes control codes with \\c and lower letter", + "schema": { + "type": "string", + "pattern": "^\\cc$" + }, + "tests": [ + { + "description": "does not match", + "data": "\\cc", + "valid": false + }, + { + "description": "matches", + "data": "\u0003", + "valid": true + } + ] + }, + { + "description": "ECMA 262 \\d matches ascii digits only", + "schema": { + "type": "string", + "pattern": "^\\d$" + }, + "tests": [ + { + "description": "ASCII zero matches", + "data": "0", + "valid": true + }, + { + "description": "NKO DIGIT ZERO does not match (unlike e.g. Python)", + "data": "߀", + "valid": false + }, + { + "description": "NKO DIGIT ZERO (as \\u escape) does not match", + "data": "\u07c0", + "valid": false + } + ] + }, + { + "description": "ECMA 262 \\D matches everything but ascii digits", + "schema": { + "type": "string", + "pattern": "^\\D$" + }, + "tests": [ + { + "description": "ASCII zero does not match", + "data": "0", + "valid": false + }, + { + "description": "NKO DIGIT ZERO matches (unlike e.g. Python)", + "data": "߀", + "valid": true + }, + { + "description": "NKO DIGIT ZERO (as \\u escape) matches", + "data": "\u07c0", + "valid": true + } + ] + }, + { + "description": "ECMA 262 \\w matches ascii letters only", + "schema": { + "type": "string", + "pattern": "^\\w$" + }, + "tests": [ + { + "description": "ASCII 'a' matches", + "data": "a", + "valid": true + }, + { + "description": "latin-1 e-acute does not match (unlike e.g. Python)", + "data": "é", + "valid": false + } + ] + }, + { + "description": "ECMA 262 \\W matches everything but ascii letters", + "schema": { + "type": "string", + "pattern": "^\\W$" + }, + "tests": [ + { + "description": "ASCII 'a' does not match", + "data": "a", + "valid": false + }, + { + "description": "latin-1 e-acute matches (unlike e.g. Python)", + "data": "é", + "valid": true + } + ] + }, + { + "description": "ECMA 262 \\s matches whitespace", + "schema": { + "type": "string", + "pattern": "^\\s$" + }, + "tests": [ + { + "description": "ASCII space matches", + "data": " ", + "valid": true + }, + { + "description": "Character tabulation matches", + "data": "\t", + "valid": true + }, + { + "description": "Line tabulation matches", + "data": "\u000b", + "valid": true + }, + { + "description": "Form feed matches", + "data": "\u000c", + "valid": true + }, + { + "description": "latin-1 non-breaking-space matches", + "data": "\u00a0", + "valid": true + }, + { + "description": "zero-width whitespace matches", + "data": "\ufeff", + "valid": true + }, + { + "description": "line feed matches (line terminator)", + "data": "\u000a", + "valid": true + }, + { + "description": "paragraph separator matches (line terminator)", + "data": "\u2029", + "valid": true + }, + { + "description": "EM SPACE matches (Space_Separator)", + "data": "\u2003", + "valid": true + }, + { + "description": "Non-whitespace control does not match", + "data": "\u0001", + "valid": false + }, + { + "description": "Non-whitespace does not match", + "data": "\u2013", + "valid": false + } + ] + }, + { + "description": "ECMA 262 \\S matches everything but whitespace", + "schema": { + "type": "string", + "pattern": "^\\S$" + }, + "tests": [ + { + "description": "ASCII space does not match", + "data": " ", + "valid": false + }, + { + "description": "Character tabulation does not match", + "data": "\t", + "valid": false + }, + { + "description": "Line tabulation does not match", + "data": "\u000b", + "valid": false + }, + { + "description": "Form feed does not match", + "data": "\u000c", + "valid": false + }, + { + "description": "latin-1 non-breaking-space does not match", + "data": "\u00a0", + "valid": false + }, + { + "description": "zero-width whitespace does not match", + "data": "\ufeff", + "valid": false + }, + { + "description": "line feed does not match (line terminator)", + "data": "\u000a", + "valid": false + }, + { + "description": "paragraph separator does not match (line terminator)", + "data": "\u2029", + "valid": false + }, + { + "description": "EM SPACE does not match (Space_Separator)", + "data": "\u2003", + "valid": false + }, + { + "description": "Non-whitespace control matches", + "data": "\u0001", + "valid": true + }, + { + "description": "Non-whitespace matches", + "data": "\u2013", + "valid": true + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/float-overflow.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/float-overflow.json new file mode 100644 index 0000000..52ff982 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/float-overflow.json @@ -0,0 +1,13 @@ +[ + { + "description": "all integers are multiples of 0.5, if overflow is handled", + "schema": {"type": "integer", "multipleOf": 0.5}, + "tests": [ + { + "description": "valid if optional overflow handling is implemented", + "data": 1e308, + "valid": true + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/date-time.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/date-time.json new file mode 100644 index 0000000..5f911ef --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/date-time.json @@ -0,0 +1,73 @@ +[ + { + "description": "validation of date-time strings", + "schema": {"format": "date-time"}, + "tests": [ + { + "description": "a valid date-time string", + "data": "1963-06-19T08:30:06.283185Z", + "valid": true + }, + { + "description": "a valid date-time string without second fraction", + "data": "1963-06-19T08:30:06Z", + "valid": true + }, + { + "description": "a valid date-time string with plus offset", + "data": "1937-01-01T12:00:27.87+00:20", + "valid": true + }, + { + "description": "a valid date-time string with minus offset", + "data": "1990-12-31T15:59:50.123-08:00", + "valid": true + }, + { + "description": "a invalid day in date-time string", + "data": "1990-02-31T15:59:60.123-08:00", + "valid": false + }, + { + "description": "an invalid offset in date-time string", + "data": "1990-12-31T15:59:60-24:00", + "valid": false + }, + { + "description": "an invalid date-time string", + "data": "06/19/1963 08:30:06 PST", + "valid": false + }, + { + "description": "case-insensitive T and Z", + "data": "1963-06-19t08:30:06.283185z", + "valid": true + }, + { + "description": "only RFC3339 not all of ISO 8601 are valid", + "data": "2013-350T01:01:01", + "valid": false + }, + { + "description": "invalid non-padded month dates", + "data": "1963-6-19T08:30:06.283185Z", + "valid": false + }, + { + "description": "invalid non-padded day dates", + "data": "1963-06-1T08:30:06.283185Z", + "valid": false + }, + { + "description": "non-ascii digits should be rejected in the date portion", + "data": "1963-06-1৪T00:00:00Z", + "valid": false + }, + { + "description": "non-ascii digits should be rejected in the time portion", + "data": "1963-06-11T0৪:00:00Z", + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/date.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/date.json new file mode 100644 index 0000000..6cc2feb --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/date.json @@ -0,0 +1,193 @@ +[ + { + "description": "validation of date strings", + "schema": {"format": "date"}, + "tests": [ + { + "description": "a valid date string", + "data": "1963-06-19", + "valid": true + }, + { + "description": "a valid date string with 31 days in January", + "data": "2020-01-31", + "valid": true + }, + { + "description": "a invalid date string with 32 days in January", + "data": "2020-01-32", + "valid": false + }, + { + "description": "a valid date string with 28 days in February (normal)", + "data": "2021-02-28", + "valid": true + }, + { + "description": "a invalid date string with 29 days in February (normal)", + "data": "2021-02-29", + "valid": false + }, + { + "description": "a valid date string with 29 days in February (leap)", + "data": "2020-02-29", + "valid": true + }, + { + "description": "a invalid date string with 30 days in February (leap)", + "data": "2020-02-30", + "valid": false + }, + { + "description": "a valid date string with 31 days in March", + "data": "2020-03-31", + "valid": true + }, + { + "description": "a invalid date string with 32 days in March", + "data": "2020-03-32", + "valid": false + }, + { + "description": "a valid date string with 30 days in April", + "data": "2020-04-30", + "valid": true + }, + { + "description": "a invalid date string with 31 days in April", + "data": "2020-04-31", + "valid": false + }, + { + "description": "a valid date string with 31 days in May", + "data": "2020-05-31", + "valid": true + }, + { + "description": "a invalid date string with 32 days in May", + "data": "2020-05-32", + "valid": false + }, + { + "description": "a valid date string with 30 days in June", + "data": "2020-06-30", + "valid": true + }, + { + "description": "a invalid date string with 31 days in June", + "data": "2020-06-31", + "valid": false + }, + { + "description": "a valid date string with 31 days in July", + "data": "2020-07-31", + "valid": true + }, + { + "description": "a invalid date string with 32 days in July", + "data": "2020-07-32", + "valid": false + }, + { + "description": "a valid date string with 31 days in August", + "data": "2020-08-31", + "valid": true + }, + { + "description": "a invalid date string with 32 days in August", + "data": "2020-08-32", + "valid": false + }, + { + "description": "a valid date string with 30 days in September", + "data": "2020-09-30", + "valid": true + }, + { + "description": "a invalid date string with 31 days in September", + "data": "2020-09-31", + "valid": false + }, + { + "description": "a valid date string with 31 days in October", + "data": "2020-10-31", + "valid": true + }, + { + "description": "a invalid date string with 32 days in October", + "data": "2020-10-32", + "valid": false + }, + { + "description": "a valid date string with 30 days in November", + "data": "2020-11-30", + "valid": true + }, + { + "description": "a invalid date string with 31 days in November", + "data": "2020-11-31", + "valid": false + }, + { + "description": "a valid date string with 31 days in December", + "data": "2020-12-31", + "valid": true + }, + { + "description": "a invalid date string with 32 days in December", + "data": "2020-12-32", + "valid": false + }, + { + "description": "a invalid date string with invalid month", + "data": "2020-13-01", + "valid": false + }, + { + "description": "an invalid date string", + "data": "06/19/1963", + "valid": false + }, + { + "description": "only RFC3339 not all of ISO 8601 are valid", + "data": "2013-350", + "valid": false + }, + { + "description": "non-padded month dates are not valid", + "data": "1998-1-20", + "valid": false + }, + { + "description": "non-padded day dates are not valid", + "data": "1998-01-1", + "valid": false + }, + { + "description": "invalid month", + "data": "1998-13-01", + "valid": false + }, + { + "description": "invalid month-day combination", + "data": "1998-04-31", + "valid": false + }, + { + "description": "2021 is not a leap year", + "data": "2021-02-29", + "valid": false + }, + { + "description": "2020 is a leap year", + "data": "2020-02-29", + "valid": true + }, + { + "description": "non-ascii digits should be rejected", + "data": "1963-06-1৪", + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/email.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/email.json new file mode 100644 index 0000000..02396d2 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/email.json @@ -0,0 +1,53 @@ +[ + { + "description": "validation of e-mail addresses", + "schema": {"format": "email"}, + "tests": [ + { + "description": "a valid e-mail address", + "data": "joe.bloggs@example.com", + "valid": true + }, + { + "description": "an invalid e-mail address", + "data": "2962", + "valid": false + }, + { + "description": "tilde in local part is valid", + "data": "te~st@example.com", + "valid": true + }, + { + "description": "tilde before local part is valid", + "data": "~test@example.com", + "valid": true + }, + { + "description": "tilde after local part is valid", + "data": "test~@example.com", + "valid": true + }, + { + "description": "dot before local part is not valid", + "data": ".test@example.com", + "valid": false + }, + { + "description": "dot after local part is not valid", + "data": "test.@example.com", + "valid": false + }, + { + "description": "two separated dots inside local part are valid", + "data": "te.s.t@example.com", + "valid": true + }, + { + "description": "two subsequent dots inside local part are not valid", + "data": "te..st@example.com", + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/hostname.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/hostname.json new file mode 100644 index 0000000..476541a --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/hostname.json @@ -0,0 +1,68 @@ +[ + { + "description": "validation of host names", + "schema": {"format": "hostname"}, + "tests": [ + { + "description": "a valid host name", + "data": "www.example.com", + "valid": true + }, + { + "description": "a valid punycoded IDN hostname", + "data": "xn--4gbwdl.xn--wgbh1c", + "valid": true + }, + { + "description": "a host name starting with an illegal character", + "data": "-a-host-name-that-starts-with--", + "valid": false + }, + { + "description": "a host name containing illegal characters", + "data": "not_a_valid_host_name", + "valid": false + }, + { + "description": "a host name with a component too long", + "data": "a-vvvvvvvvvvvvvvvveeeeeeeeeeeeeeeerrrrrrrrrrrrrrrryyyyyyyyyyyyyyyy-long-host-name-component", + "valid": false + }, + { + "description": "starts with hyphen", + "data": "-hostname", + "valid": false + }, + { + "description": "ends with hyphen", + "data": "hostname-", + "valid": false + }, + { + "description": "starts with underscore", + "data": "_hostname", + "valid": false + }, + { + "description": "ends with underscore", + "data": "hostname_", + "valid": false + }, + { + "description": "contains underscore", + "data": "host_name", + "valid": false + }, + { + "description": "maximum label length", + "data": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.com", + "valid": true + }, + { + "description": "exceeds maximum label length", + "data": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl.com", + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/idn-email.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/idn-email.json new file mode 100644 index 0000000..552d106 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/idn-email.json @@ -0,0 +1,28 @@ +[ + { + "description": "validation of an internationalized e-mail addresses", + "schema": {"format": "idn-email"}, + "tests": [ + { + "description": "a valid idn e-mail (example@example.test in Hangul)", + "data": "실례@실례.테스트", + "valid": true + }, + { + "description": "an invalid idn e-mail address", + "data": "2962", + "valid": false + }, + { + "description": "a valid e-mail address", + "data": "joe.bloggs@example.com", + "valid": true + }, + { + "description": "an invalid e-mail address", + "data": "2962", + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/idn-hostname.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/idn-hostname.json new file mode 100644 index 0000000..7f10bd8 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/idn-hostname.json @@ -0,0 +1,274 @@ +[ + { + "description": "validation of internationalized host names", + "schema": {"format": "idn-hostname"}, + "tests": [ + { + "description": "a valid host name (example.test in Hangul)", + "data": "실례.테스트", + "valid": true + }, + { + "description": "illegal first char U+302E Hangul single dot tone mark", + "data": "〮실례.테스트", + "valid": false + }, + { + "description": "contains illegal char U+302E Hangul single dot tone mark", + "data": "실〮례.테스트", + "valid": false + }, + { + "description": "a host name with a component too long", + "data": "실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실실례례테스트례례례례례례례례례례례례례례례례례테스트례례례례례례례례례례례례례례례례례례례테스트례례례례례례례례례례례례테스트례례실례.테스트", + "valid": 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 <--", + "valid": 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", + "valid": 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", + "valid": 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", + "valid": false + }, + { + "description": "U-label starts with a dash", + "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.1", + "data": "-hello", + "valid": false + }, + { + "description": "U-label ends with a dash", + "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.1", + "data": "hello-", + "valid": false + }, + { + "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 + }, + { + "description": "Begins with a Spacing Combining Mark", + "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.2", + "data": "\u0903hello", + "valid": false + }, + { + "description": "Begins with a Nonspacing Mark", + "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.2", + "data": "\u0300hello", + "valid": false + }, + { + "description": "Begins with an Enclosing Mark", + "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.2", + "data": "\u0488hello", + "valid": 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": "\u00df\u03c2\u0f0b\u3007", + "valid": true + }, + { + "description": "Exceptions that are PVALID, right-to-left chars", + "comment": "https://tools.ietf.org/html/rfc/rfc5891#section-4.2.2 https://tools.ietf.org/html/rfc5892#section-2.6", + "data": "\u06fd\u06fe", + "valid": 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": "\u0640\u07fa", + "valid": 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": "\u3031\u3032\u3033\u3034\u3035\u302e\u302f\u303b", + "valid": 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\u00b7l", + "valid": 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": "\u00b7l", + "valid": 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\u00b7a", + "valid": 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\u00b7", + "valid": 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\u00b7l", + "valid": 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": "\u03b1\u0375S", + "valid": 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": "\u03b1\u0375", + "valid": 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": "\u03b1\u0375\u03b2", + "valid": 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\u05f3\u05d1", + "valid": 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": "\u05f3\u05d1", + "valid": 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": "\u05d0\u05f3\u05d1", + "valid": 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\u05f4\u05d1", + "valid": 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": "\u05f4\u05d1", + "valid": 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": "\u05d0\u05f4\u05d1", + "valid": 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\u30fbabc", + "valid": 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": "\u30fb", + "valid": 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": "\u30fb\u3041", + "valid": 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": "\u30fb\u30a1", + "valid": 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": "\u30fb\u4e08", + "valid": 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": "\u0660\u06f0", + "valid": 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": "\u0628\u0660\u0628", + "valid": 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": "\u06f00", + "valid": 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": "\u0915\u200d\u0937", + "valid": 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": "\u200d\u0937", + "valid": 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": "\u0915\u094d\u200d\u0937", + "valid": 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": "\u0915\u094d\u200c\u0937", + "valid": 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": "\u0628\u064a\u200c\u0628\u064a", + "valid": true + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/ipv4.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/ipv4.json new file mode 100644 index 0000000..4d10927 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/ipv4.json @@ -0,0 +1,54 @@ +[ + { + "description": "validation of IP addresses", + "schema": {"format": "ipv4"}, + "tests": [ + { + "description": "a valid IP address", + "data": "192.168.0.1", + "valid": true + }, + { + "description": "an IP address with too many components", + "data": "127.0.0.0.1", + "valid": false + }, + { + "description": "an IP address with out-of-range values", + "data": "256.256.256.256", + "valid": false + }, + { + "description": "an IP address without 4 components", + "data": "127.0", + "valid": false + }, + { + "description": "an IP address as an integer", + "data": "0x7f000001", + "valid": false + }, + { + "description": "an IP address as an integer (decimal)", + "data": "2130706433", + "valid": false + }, + { + "description": "leading zeroes should be rejected, 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 + }, + { + "description": "value without leading zero is valid", + "data": "87.10.0.1", + "valid": true + }, + { + "description": "non-ascii digits should be rejected", + "data": "1২7.0.0.1", + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/ipv6.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/ipv6.json new file mode 100644 index 0000000..cf629c6 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/ipv6.json @@ -0,0 +1,163 @@ +[ + { + "description": "validation of IPv6 addresses", + "schema": {"format": "ipv6"}, + "tests": [ + { + "description": "a valid IPv6 address", + "data": "::1", + "valid": true + }, + { + "description": "an IPv6 address with out-of-range values", + "data": "12345::", + "valid": 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", + "valid": false + }, + { + "description": "an IPv6 address containing illegal characters", + "data": "::laptop", + "valid": false + }, + { + "description": "no digits is valid", + "data": "::", + "valid": true + }, + { + "description": "leading colons is valid", + "data": "::42:ff:1", + "valid": true + }, + { + "description": "trailing colons is valid", + "data": "d6::", + "valid": true + }, + { + "description": "missing leading octet is invalid", + "data": ":2:3:4:5:6:7:8", + "valid": false + }, + { + "description": "missing trailing octet is invalid", + "data": "1:2:3:4:5:6:7:", + "valid": false + }, + { + "description": "missing leading octet with omitted octets later", + "data": ":2:3:4::8", + "valid": false + }, + { + "description": "two sets of double colons is invalid", + "data": "1::d6::42", + "valid": false + }, + { + "description": "mixed format with the ipv4 section as decimal octets", + "data": "1::d6:192.168.0.1", + "valid": true + }, + { + "description": "mixed format with double colons between the sections", + "data": "1:2::192.168.0.1", + "valid": true + }, + { + "description": "mixed format with ipv4 section with octet out of range", + "data": "1::2:192.168.256.1", + "valid": false + }, + { + "description": "mixed format with ipv4 section with a hex octet", + "data": "1::2:192.168.ff.1", + "valid": false + }, + { + "description": "mixed format with leading double colons (ipv4-mapped ipv6 address)", + "data": "::ffff:192.168.0.1", + "valid": true + }, + { + "description": "triple colons is invalid", + "data": "1:2:3:4:5:::8", + "valid": false + }, + { + "description": "8 octets", + "data": "1:2:3:4:5:6:7:8", + "valid": true + }, + { + "description": "insufficient octets without double colons", + "data": "1:2:3:4:5:6:7", + "valid": false + }, + { + "description": "no colons is invalid", + "data": "1", + "valid": false + }, + { + "description": "ipv4 is not ipv6", + "data": "127.0.0.1", + "valid": false + }, + { + "description": "ipv4 segment must have 4 octets", + "data": "1:2:3:4:1.2.3", + "valid": false + }, + { + "description": "leading whitespace is invalid", + "data": " ::1", + "valid": false + }, + { + "description": "trailing whitespace is invalid", + "data": "::1 ", + "valid": false + }, + { + "description": "netmask is not a part of ipv6 address", + "data": "fe80::/64", + "valid": false + }, + { + "description": "zone id is not a part of ipv6 address", + "data": "fe80::a%eth1", + "valid": false + }, + { + "description": "a long valid ipv6", + "data": "1000:1000:1000:1000:1000:1000:255.255.255.255", + "valid": true + }, + { + "description": "a long invalid ipv6, below length limit, first", + "data": "100:100:100:100:100:100:255.255.255.255.255", + "valid": false + }, + { + "description": "a long invalid ipv6, below length limit, second", + "data": "100:100:100:100:100:100:100:255.255.255.255", + "valid": false + }, + { + "description": "non-ascii digits should be rejected", + "data": "1:2:3:4:5:6:7:৪", + "valid": false + }, + { + "description": "non-ascii digits should be rejected in the ipv4 portion also", + "data": "1:2::192.16৪.0.1", + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/iri-reference.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/iri-reference.json new file mode 100644 index 0000000..1fd779c --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/iri-reference.json @@ -0,0 +1,43 @@ +[ + { + "description": "validation of IRI References", + "schema": {"format": "iri-reference"}, + "tests": [ + { + "description": "a valid IRI", + "data": "http://ƒøø.ßår/?∂éœ=πîx#πîüx", + "valid": true + }, + { + "description": "a valid protocol-relative IRI Reference", + "data": "//ƒøø.ßår/?∂éœ=πîx#πîüx", + "valid": true + }, + { + "description": "a valid relative IRI Reference", + "data": "/âππ", + "valid": true + }, + { + "description": "an invalid IRI Reference", + "data": "\\\\WINDOWS\\filëßåré", + "valid": false + }, + { + "description": "a valid IRI Reference", + "data": "âππ", + "valid": true + }, + { + "description": "a valid IRI fragment", + "data": "#ƒrägmênt", + "valid": true + }, + { + "description": "an invalid IRI fragment", + "data": "#ƒräg\\mênt", + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/iri.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/iri.json new file mode 100644 index 0000000..1414f2e --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/iri.json @@ -0,0 +1,53 @@ +[ + { + "description": "validation of IRIs", + "schema": {"format": "iri"}, + "tests": [ + { + "description": "a valid IRI with anchor tag", + "data": "http://ƒøø.ßår/?∂éœ=πîx#πîüx", + "valid": true + }, + { + "description": "a valid IRI with anchor tag and parentheses", + "data": "http://ƒøø.com/blah_(wîkïpédiå)_blah#ßité-1", + "valid": true + }, + { + "description": "a valid IRI with URL-encoded stuff", + "data": "http://ƒøø.ßår/?q=Test%20URL-encoded%20stuff", + "valid": true + }, + { + "description": "a valid IRI with many special characters", + "data": "http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com", + "valid": true + }, + { + "description": "a valid IRI based on IPv6", + "data": "http://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]", + "valid": true + }, + { + "description": "an invalid IRI based on IPv6", + "data": "http://2001:0db8:85a3:0000:0000:8a2e:0370:7334", + "valid": false + }, + { + "description": "an invalid relative IRI Reference", + "data": "/abc", + "valid": false + }, + { + "description": "an invalid IRI", + "data": "\\\\WINDOWS\\filëßåré", + "valid": false + }, + { + "description": "an invalid IRI though valid IRI reference", + "data": "âππ", + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/json-pointer.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/json-pointer.json new file mode 100644 index 0000000..65c2f06 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/json-pointer.json @@ -0,0 +1,168 @@ +[ + { + "description": "validation of JSON-pointers (JSON String Representation)", + "schema": {"format": "json-pointer"}, + "tests": [ + { + "description": "a valid JSON-pointer", + "data": "/foo/bar~0/baz~1/%a", + "valid": true + }, + { + "description": "not a valid JSON-pointer (~ not escaped)", + "data": "/foo/bar~", + "valid": false + }, + { + "description": "valid JSON-pointer with empty segment", + "data": "/foo//bar", + "valid": true + }, + { + "description": "valid JSON-pointer with the last empty segment", + "data": "/foo/bar/", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #1", + "data": "", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #2", + "data": "/foo", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #3", + "data": "/foo/0", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #4", + "data": "/", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #5", + "data": "/a~1b", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #6", + "data": "/c%d", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #7", + "data": "/e^f", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #8", + "data": "/g|h", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #9", + "data": "/i\\j", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #10", + "data": "/k\"l", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #11", + "data": "/ ", + "valid": true + }, + { + "description": "valid JSON-pointer as stated in RFC 6901 #12", + "data": "/m~0n", + "valid": true + }, + { + "description": "valid JSON-pointer used adding to the last array position", + "data": "/foo/-", + "valid": true + }, + { + "description": "valid JSON-pointer (- used as object member name)", + "data": "/foo/-/bar", + "valid": true + }, + { + "description": "valid JSON-pointer (multiple escaped characters)", + "data": "/~1~0~0~1~1", + "valid": true + }, + { + "description": "valid JSON-pointer (escaped with fraction part) #1", + "data": "/~1.1", + "valid": true + }, + { + "description": "valid JSON-pointer (escaped with fraction part) #2", + "data": "/~0.1", + "valid": true + }, + { + "description": "not a valid JSON-pointer (URI Fragment Identifier) #1", + "data": "#", + "valid": false + }, + { + "description": "not a valid JSON-pointer (URI Fragment Identifier) #2", + "data": "#/", + "valid": false + }, + { + "description": "not a valid JSON-pointer (URI Fragment Identifier) #3", + "data": "#a", + "valid": false + }, + { + "description": "not a valid JSON-pointer (some escaped, but not all) #1", + "data": "/~0~", + "valid": false + }, + { + "description": "not a valid JSON-pointer (some escaped, but not all) #2", + "data": "/~0/~", + "valid": false + }, + { + "description": "not a valid JSON-pointer (wrong escape character) #1", + "data": "/~2", + "valid": false + }, + { + "description": "not a valid JSON-pointer (wrong escape character) #2", + "data": "/~-1", + "valid": false + }, + { + "description": "not a valid JSON-pointer (multiple characters not escaped)", + "data": "/~~", + "valid": false + }, + { + "description": "not a valid JSON-pointer (isn't empty nor starts with /) #1", + "data": "a", + "valid": false + }, + { + "description": "not a valid JSON-pointer (isn't empty nor starts with /) #2", + "data": "0", + "valid": false + }, + { + "description": "not a valid JSON-pointer (isn't empty nor starts with /) #3", + "data": "a/a", + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/regex.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/regex.json new file mode 100644 index 0000000..d99d021 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/regex.json @@ -0,0 +1,18 @@ +[ + { + "description": "validation of regular expressions", + "schema": {"format": "regex"}, + "tests": [ + { + "description": "a valid regular expression", + "data": "([abc])+\\s+$", + "valid": true + }, + { + "description": "a regular expression with unclosed parens is invalid", + "data": "^(abc]", + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/relative-json-pointer.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/relative-json-pointer.json new file mode 100644 index 0000000..22fb14e --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/relative-json-pointer.json @@ -0,0 +1,53 @@ +[ + { + "description": "validation of Relative JSON Pointers (RJP)", + "schema": {"format": "relative-json-pointer"}, + "tests": [ + { + "description": "a valid upwards RJP", + "data": "1", + "valid": true + }, + { + "description": "a valid downwards RJP", + "data": "0/foo/bar", + "valid": true + }, + { + "description": "a valid up and then down RJP, with array index", + "data": "2/0/baz/1/zip", + "valid": true + }, + { + "description": "a valid RJP taking the member or index name", + "data": "0#", + "valid": true + }, + { + "description": "an invalid RJP that is a valid JSON Pointer", + "data": "/foo/bar", + "valid": false + }, + { + "description": "negative prefix", + "data": "-1/foo/bar", + "valid": false + }, + { + "description": "## is not a valid json-pointer", + "data": "0##", + "valid": false + }, + { + "description": "zero cannot be followed by other digits, plus json-pointer", + "data": "01/a", + "valid": false + }, + { + "description": "zero cannot be followed by other digits, plus octothorpe", + "data": "01#", + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/time.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/time.json new file mode 100644 index 0000000..0a8da0e --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/time.json @@ -0,0 +1,168 @@ +[ + { + "description": "validation of time strings", + "schema": {"format": "time"}, + "tests": [ + { + "description": "a valid time string", + "data": "08:30:06Z", + "valid": true + }, + { + "description": "a valid time string with leap second, Zulu", + "data": "23:59:60Z", + "valid": true + }, + { + "description": "invalid leap second, Zulu (wrong hour)", + "data": "22:59:60Z", + "valid": false + }, + { + "description": "invalid leap second, Zulu (wrong minute)", + "data": "23:58:60Z", + "valid": false + }, + { + "description": "valid leap second, zero time-offset", + "data": "23:59:60+00:00", + "valid": true + }, + { + "description": "invalid leap second, zero time-offset (wrong hour)", + "data": "22:59:60+00:00", + "valid": false + }, + { + "description": "invalid leap second, zero time-offset (wrong minute)", + "data": "23:58:60+00:00", + "valid": false + }, + { + "description": "valid leap second, positive time-offset", + "data": "01:29:60+01:30", + "valid": true + }, + { + "description": "valid leap second, large positive time-offset", + "data": "23:29:60+23:30", + "valid": true + }, + { + "description": "invalid leap second, positive time-offset (wrong hour)", + "data": "23:59:60+01:00", + "valid": false + }, + { + "description": "invalid leap second, positive time-offset (wrong minute)", + "data": "23:59:60+00:30", + "valid": false + }, + { + "description": "valid leap second, negative time-offset", + "data": "15:59:60-08:00", + "valid": true + }, + { + "description": "valid leap second, large negative time-offset", + "data": "00:29:60-23:30", + "valid": true + }, + { + "description": "invalid leap second, negative time-offset (wrong hour)", + "data": "23:59:60-01:00", + "valid": false + }, + { + "description": "invalid leap second, negative time-offset (wrong minute)", + "data": "23:59:60-00:30", + "valid": false + }, + { + "description": "a valid time string with second fraction", + "data": "23:20:50.52Z", + "valid": true + }, + { + "description": "a valid time string with precise second fraction", + "data": "08:30:06.283185Z", + "valid": true + }, + { + "description": "a valid time string with plus offset", + "data": "08:30:06+00:20", + "valid": true + }, + { + "description": "a valid time string with minus offset", + "data": "08:30:06-08:00", + "valid": true + }, + { + "description": "a valid time string with case-insensitive Z", + "data": "08:30:06z", + "valid": true + }, + { + "description": "an invalid time string with invalid hour", + "data": "24:00:00Z", + "valid": false + }, + { + "description": "an invalid time string with invalid minute", + "data": "00:60:00Z", + "valid": false + }, + { + "description": "an invalid time string with invalid second", + "data": "00:00:61Z", + "valid": false + }, + { + "description": "an invalid time string with invalid leap second (wrong hour)", + "data": "22:59:60Z", + "valid": false + }, + { + "description": "an invalid time string with invalid leap second (wrong minute)", + "data": "23:58:60Z", + "valid": false + }, + { + "description": "an invalid time string with invalid time numoffset hour", + "data": "01:02:03+24:00", + "valid": false + }, + { + "description": "an invalid time string with invalid time numoffset minute", + "data": "01:02:03+00:60", + "valid": false + }, + { + "description": "an invalid time string with invalid time with both Z and numoffset", + "data": "01:02:03Z+00:30", + "valid": false + }, + { + "description": "an invalid offset indicator", + "data": "08:30:06 PST", + "valid": false + }, + { + "description": "only RFC3339 not all of ISO 8601 are valid", + "data": "01:01:01,1111", + "valid": false + }, + { + "description": "no time offset", + "data": "12:00:00", + "valid": false + }, + { + "description": "non-ascii digits should be rejected", + "data": "1২:00:00Z", + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/uri-reference.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/uri-reference.json new file mode 100644 index 0000000..e4c9eef --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/uri-reference.json @@ -0,0 +1,43 @@ +[ + { + "description": "validation of URI References", + "schema": {"format": "uri-reference"}, + "tests": [ + { + "description": "a valid URI", + "data": "http://foo.bar/?baz=qux#quux", + "valid": true + }, + { + "description": "a valid protocol-relative URI Reference", + "data": "//foo.bar/?baz=qux#quux", + "valid": true + }, + { + "description": "a valid relative URI Reference", + "data": "/abc", + "valid": true + }, + { + "description": "an invalid URI Reference", + "data": "\\\\WINDOWS\\fileshare", + "valid": false + }, + { + "description": "a valid URI Reference", + "data": "abc", + "valid": true + }, + { + "description": "a valid URI fragment", + "data": "#fragment", + "valid": true + }, + { + "description": "an invalid URI fragment", + "data": "#frag\\ment", + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/uri-template.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/uri-template.json new file mode 100644 index 0000000..33ab76e --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/uri-template.json @@ -0,0 +1,28 @@ +[ + { + "description": "format: uri-template", + "schema": {"format": "uri-template"}, + "tests": [ + { + "description": "a valid uri-template", + "data": "http://example.com/dictionary/{term:1}/{term}", + "valid": true + }, + { + "description": "an invalid uri-template", + "data": "http://example.com/dictionary/{term:1}/{term", + "valid": false + }, + { + "description": "a valid uri-template without variables", + "data": "http://example.com/dictionary", + "valid": true + }, + { + "description": "a valid relative uri-template", + "data": "dictionary/{term:1}/{term}", + "valid": true + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/uri.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/uri.json new file mode 100644 index 0000000..58d3085 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/uri.json @@ -0,0 +1,108 @@ +[ + { + "description": "validation of URIs", + "schema": {"format": "uri"}, + "tests": [ + { + "description": "a valid URL with anchor tag", + "data": "http://foo.bar/?baz=qux#quux", + "valid": true + }, + { + "description": "a valid URL with anchor tag and parentheses", + "data": "http://foo.com/blah_(wikipedia)_blah#cite-1", + "valid": true + }, + { + "description": "a valid URL with URL-encoded stuff", + "data": "http://foo.bar/?q=Test%20URL-encoded%20stuff", + "valid": true + }, + { + "description": "a valid puny-coded URL ", + "data": "http://xn--nw2a.xn--j6w193g/", + "valid": true + }, + { + "description": "a valid URL with many special characters", + "data": "http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com", + "valid": true + }, + { + "description": "a valid URL based on IPv4", + "data": "http://223.255.255.254", + "valid": true + }, + { + "description": "a valid URL with ftp scheme", + "data": "ftp://ftp.is.co.za/rfc/rfc1808.txt", + "valid": true + }, + { + "description": "a valid URL for a simple text file", + "data": "http://www.ietf.org/rfc/rfc2396.txt", + "valid": true + }, + { + "description": "a valid URL ", + "data": "ldap://[2001:db8::7]/c=GB?objectClass?one", + "valid": true + }, + { + "description": "a valid mailto URI", + "data": "mailto:John.Doe@example.com", + "valid": true + }, + { + "description": "a valid newsgroup URI", + "data": "news:comp.infosystems.www.servers.unix", + "valid": true + }, + { + "description": "a valid tel URI", + "data": "tel:+1-816-555-1212", + "valid": true + }, + { + "description": "a valid URN", + "data": "urn:oasis:names:specification:docbook:dtd:xml:4.1.2", + "valid": true + }, + { + "description": "an invalid protocol-relative URI Reference", + "data": "//foo.bar/?baz=qux#quux", + "valid": false + }, + { + "description": "an invalid relative URI Reference", + "data": "/abc", + "valid": false + }, + { + "description": "an invalid URI", + "data": "\\\\WINDOWS\\fileshare", + "valid": false + }, + { + "description": "an invalid URI though valid URI reference", + "data": "abc", + "valid": false + }, + { + "description": "an invalid URI with spaces", + "data": "http:// shouldfail.com", + "valid": false + }, + { + "description": "an invalid URI with spaces and missing scheme", + "data": ":// should fail", + "valid": false + }, + { + "description": "an invalid URI with comma in scheme", + "data": "bar,baz:foo", + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/uuid.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/uuid.json new file mode 100644 index 0000000..e54cbc0 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/format/uuid.json @@ -0,0 +1,85 @@ +[ + { + "description": "uuid format", + "schema": { + "format": "uuid" + }, + "tests": [ + { + "description": "all upper-case", + "data": "2EB8AA08-AA98-11EA-B4AA-73B441D16380", + "valid": true + }, + { + "description": "all lower-case", + "data": "2eb8aa08-aa98-11ea-b4aa-73b441d16380", + "valid": true + }, + { + "description": "mixed case", + "data": "2eb8aa08-AA98-11ea-B4Aa-73B441D16380", + "valid": true + }, + { + "description": "all zeroes is valid", + "data": "00000000-0000-0000-0000-000000000000", + "valid": true + }, + { + "description": "wrong length", + "data": "2eb8aa08-aa98-11ea-b4aa-73b441d1638", + "valid": false + }, + { + "description": "missing section", + "data": "2eb8aa08-aa98-11ea-73b441d16380", + "valid": false + }, + { + "description": "bad characters (not hex)", + "data": "2eb8aa08-aa98-11ea-b4ga-73b441d16380", + "valid": false + }, + { + "description": "no dashes", + "data": "2eb8aa08aa9811eab4aa73b441d16380", + "valid": false + }, + { + "description": "too few dashes", + "data": "2eb8aa08aa98-11ea-b4aa73b441d16380", + "valid": false + }, + { + "description": "too many dashes", + "data": "2eb8-aa08-aa98-11ea-b4aa73b44-1d16380", + "valid": false + }, + { + "description": "dashes in the wrong spot", + "data": "2eb8aa08aa9811eab4aa73b441d16380----", + "valid": false + }, + { + "description": "valid version 4", + "data": "98d80576-482e-427f-8434-7f86890ab222", + "valid": true + }, + { + "description": "valid version 5", + "data": "99c17cbb-656f-564a-940f-1a4568f03487", + "valid": true + }, + { + "description": "hypothetical version 6", + "data": "99c17cbb-656f-664a-940f-1a4568f03487", + "valid": true + }, + { + "description": "hypothetical version 15", + "data": "99c17cbb-656f-f64a-940f-1a4568f03487", + "valid": true + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/non-bmp-regex.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/non-bmp-regex.json new file mode 100644 index 0000000..dd67af2 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/non-bmp-regex.json @@ -0,0 +1,82 @@ +[ + { + "description": "Proper UTF-16 surrogate pair handling: pattern", + "comment": "Optional because .Net doesn't correctly handle 32-bit Unicode characters", + "schema": { "pattern": "^🐲*$" }, + "tests": [ + { + "description": "matches empty", + "data": "", + "valid": true + }, + { + "description": "matches single", + "data": "🐲", + "valid": true + }, + { + "description": "matches two", + "data": "🐲🐲", + "valid": true + }, + { + "description": "doesn't match one", + "data": "🐉", + "valid": false + }, + { + "description": "doesn't match two", + "data": "🐉🐉", + "valid": false + }, + { + "description": "doesn't match one ASCII", + "data": "D", + "valid": false + }, + { + "description": "doesn't match two ASCII", + "data": "DD", + "valid": false + } + ] + }, + { + "description": "Proper UTF-16 surrogate pair handling: patternProperties", + "comment": "Optional because .Net doesn't correctly handle 32-bit Unicode characters", + "schema": { + "patternProperties": { + "^🐲*$": { + "type": "integer" + } + } + }, + "tests": [ + { + "description": "matches empty", + "data": { "": 1 }, + "valid": true + }, + { + "description": "matches single", + "data": { "🐲": 1 }, + "valid": true + }, + { + "description": "matches two", + "data": { "🐲🐲": 1 }, + "valid": true + }, + { + "description": "doesn't match one", + "data": { "🐲": "hello" }, + "valid": false + }, + { + "description": "doesn't match two", + "data": { "🐲🐲": "hello" }, + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/unicode.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/unicode.json new file mode 100644 index 0000000..1dc5940 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/optional/unicode.json @@ -0,0 +1,146 @@ +[ + { + "description": "unicode semantics should be used for all pattern matching", + "schema": { "pattern": "\\wcole" }, + "tests": [ + { + "description": "literal unicode character in json string", + "data": "Les hivers de mon enfance étaient des saisons longues, longues. Nous vivions en trois lieux: l'école, l'église et la patinoire; mais la vraie vie était sur la patinoire.", + "valid": true + }, + { + "description": "unicode character in hex format in string", + "data": "Les hivers de mon enfance étaient des saisons longues, longues. Nous vivions en trois lieux: l'\u00e9cole, l'église et la patinoire; mais la vraie vie était sur la patinoire.", + "valid": true + }, + { + "description": "unicode matching is case-sensitive", + "data": "LES HIVERS DE MON ENFANCE ÉTAIENT DES SAISONS LONGUES, LONGUES. NOUS VIVIONS EN TROIS LIEUX: L'ÉCOLE, L'ÉGLISE ET LA PATINOIRE; MAIS LA VRAIE VIE ÉTAIT SUR LA PATINOIRE.", + "valid": false + } + ] + }, + { + "description": "unicode characters do not match ascii ranges", + "schema": { "pattern": "[a-z]cole" }, + "tests": [ + { + "description": "literal unicode character in json string", + "data": "Les hivers de mon enfance étaient des saisons longues, longues. Nous vivions en trois lieux: l'école, l'église et la patinoire; mais la vraie vie était sur la patinoire.", + "valid": false + }, + { + "description": "unicode character in hex format in string", + "data": "Les hivers de mon enfance étaient des saisons longues, longues. Nous vivions en trois lieux: l'\u00e9cole, l'église et la patinoire; mais la vraie vie était sur la patinoire.", + "valid": false + }, + { + "description": "ascii characters match", + "data": "Les hivers de mon enfance etaient des saisons longues, longues. Nous vivions en trois lieux: l'ecole, l'eglise et la patinoire; mais la vraie vie etait sur la patinoire.", + "valid": true + } + ] + }, + { + "description": "unicode digits are more than 0 through 9", + "schema": { "pattern": "^\\d+$" }, + "tests": [ + { + "description": "ascii digits", + "data": "42", + "valid": true + }, + { + "description": "ascii non-digits", + "data": "-%#", + "valid": false + }, + { + "description": "non-ascii digits (BENGALI DIGIT FOUR, BENGALI DIGIT TWO)", + "data": "৪২", + "valid": true + } + ] + }, + { + "description": "unicode semantics should be used for all patternProperties matching", + "schema": { + "type": "object", + "patternProperties": { + "\\wcole": true + }, + "additionalProperties": false + }, + "tests": [ + { + "description": "literal unicode character in json string", + "data": { "l'école": "pas de vraie vie" }, + "valid": true + }, + { + "description": "unicode character in hex format in string", + "data": { "l'\u00e9cole": "pas de vraie vie" }, + "valid": true + }, + { + "description": "unicode matching is case-sensitive", + "data": { "L'ÉCOLE": "PAS DE VRAIE VIE" }, + "valid": false + } + ] + }, + { + "description": "unicode characters do not match ascii ranges", + "schema": { + "type": "object", + "patternProperties": { + "[a-z]cole": true + }, + "additionalProperties": false + }, + "tests": [ + { + "description": "literal unicode character in json string", + "data": { "l'école": "pas de vraie vie" }, + "valid": false + }, + { + "description": "unicode character in hex format in string", + "data": { "l'\u00e9cole": "pas de vraie vie" }, + "valid": false + }, + { + "description": "ascii characters match", + "data": { "l'ecole": "pas de vraie vie" }, + "valid": true + } + ] + }, + { + "description": "unicode digits are more than 0 through 9", + "schema": { + "type": "object", + "patternProperties": { + "^\\d+$": true + }, + "additionalProperties": false + }, + "tests": [ + { + "description": "ascii digits", + "data": { "42": "life, the universe, and everything" }, + "valid": true + }, + { + "description": "ascii non-digits", + "data": { "-%#": "spending the year dead for tax reasons" }, + "valid": false + }, + { + "description": "non-ascii digits (BENGALI DIGIT FOUR, BENGALI DIGIT TWO)", + "data": { "৪২": "khajit has wares if you have coin" }, + "valid": true + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/pattern.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/pattern.json new file mode 100644 index 0000000..92db0f9 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/pattern.json @@ -0,0 +1,59 @@ +[ + { + "description": "pattern validation", + "schema": {"pattern": "^a*$"}, + "tests": [ + { + "description": "a matching pattern is valid", + "data": "aaa", + "valid": true + }, + { + "description": "a non-matching pattern is invalid", + "data": "abc", + "valid": false + }, + { + "description": "ignores booleans", + "data": true, + "valid": true + }, + { + "description": "ignores integers", + "data": 123, + "valid": true + }, + { + "description": "ignores floats", + "data": 1.0, + "valid": true + }, + { + "description": "ignores objects", + "data": {}, + "valid": true + }, + { + "description": "ignores arrays", + "data": [], + "valid": true + }, + { + "description": "ignores null", + "data": null, + "valid": true + } + ] + }, + { + "description": "pattern is not anchored", + "schema": {"pattern": "a+"}, + "tests": [ + { + "description": "matches a substring", + "data": "xxaayy", + "valid": true + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/patternProperties.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/patternProperties.json new file mode 100644 index 0000000..c10ffcc --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/patternProperties.json @@ -0,0 +1,156 @@ +[ + { + "description": + "patternProperties validates properties matching a regex", + "schema": { + "patternProperties": { + "f.*o": {"type": "integer"} + } + }, + "tests": [ + { + "description": "a single valid match is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "multiple valid matches is valid", + "data": {"foo": 1, "foooooo" : 2}, + "valid": true + }, + { + "description": "a single invalid match is invalid", + "data": {"foo": "bar", "fooooo": 2}, + "valid": false + }, + { + "description": "multiple invalid matches is invalid", + "data": {"foo": "bar", "foooooo" : "baz"}, + "valid": false + }, + { + "description": "ignores arrays", + "data": ["foo"], + "valid": true + }, + { + "description": "ignores strings", + "data": "foo", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + }, + { + "description": "multiple simultaneous patternProperties are validated", + "schema": { + "patternProperties": { + "a*": {"type": "integer"}, + "aaa*": {"maximum": 20} + } + }, + "tests": [ + { + "description": "a single valid match is valid", + "data": {"a": 21}, + "valid": true + }, + { + "description": "a simultaneous match is valid", + "data": {"aaaa": 18}, + "valid": true + }, + { + "description": "multiple matches is valid", + "data": {"a": 21, "aaaa": 18}, + "valid": true + }, + { + "description": "an invalid due to one is invalid", + "data": {"a": "bar"}, + "valid": false + }, + { + "description": "an invalid due to the other is invalid", + "data": {"aaaa": 31}, + "valid": false + }, + { + "description": "an invalid due to both is invalid", + "data": {"aaa": "foo", "aaaa": 31}, + "valid": false + } + ] + }, + { + "description": "regexes are not anchored by default and are case sensitive", + "schema": { + "patternProperties": { + "[0-9]{2,}": { "type": "boolean" }, + "X_": { "type": "string" } + } + }, + "tests": [ + { + "description": "non recognized members are ignored", + "data": { "answer 1": "42" }, + "valid": true + }, + { + "description": "recognized members are accounted for", + "data": { "a31b": null }, + "valid": false + }, + { + "description": "regexes are case sensitive", + "data": { "a_x_3": 3 }, + "valid": true + }, + { + "description": "regexes are case sensitive, 2", + "data": { "a_X_3": 3 }, + "valid": false + } + ] + }, + { + "description": "patternProperties with boolean schemas", + "schema": { + "patternProperties": { + "f.*": true, + "b.*": false + } + }, + "tests": [ + { + "description": "object with property matching schema true is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "object with property matching schema false is invalid", + "data": {"bar": 2}, + "valid": false + }, + { + "description": "object with both properties is invalid", + "data": {"foo": 1, "bar": 2}, + "valid": false + }, + { + "description": "object with a property matching both true and false is invalid", + "data": {"foobar":1}, + "valid": false + }, + { + "description": "empty object is valid", + "data": {}, + "valid": true + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/properties.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/properties.json new file mode 100644 index 0000000..b86c181 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/properties.json @@ -0,0 +1,167 @@ +[ + { + "description": "object properties validation", + "schema": { + "properties": { + "foo": {"type": "integer"}, + "bar": {"type": "string"} + } + }, + "tests": [ + { + "description": "both properties present and valid is valid", + "data": {"foo": 1, "bar": "baz"}, + "valid": true + }, + { + "description": "one property invalid is invalid", + "data": {"foo": 1, "bar": {}}, + "valid": false + }, + { + "description": "both properties invalid is invalid", + "data": {"foo": [], "bar": {}}, + "valid": false + }, + { + "description": "doesn't invalidate other properties", + "data": {"quux": []}, + "valid": true + }, + { + "description": "ignores arrays", + "data": [], + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + }, + { + "description": + "properties, patternProperties, additionalProperties interaction", + "schema": { + "properties": { + "foo": {"type": "array", "maxItems": 3}, + "bar": {"type": "array"} + }, + "patternProperties": {"f.o": {"minItems": 2}}, + "additionalProperties": {"type": "integer"} + }, + "tests": [ + { + "description": "property validates property", + "data": {"foo": [1, 2]}, + "valid": true + }, + { + "description": "property invalidates property", + "data": {"foo": [1, 2, 3, 4]}, + "valid": false + }, + { + "description": "patternProperty invalidates property", + "data": {"foo": []}, + "valid": false + }, + { + "description": "patternProperty validates nonproperty", + "data": {"fxo": [1, 2]}, + "valid": true + }, + { + "description": "patternProperty invalidates nonproperty", + "data": {"fxo": []}, + "valid": false + }, + { + "description": "additionalProperty ignores property", + "data": {"bar": []}, + "valid": true + }, + { + "description": "additionalProperty validates others", + "data": {"quux": 3}, + "valid": true + }, + { + "description": "additionalProperty invalidates others", + "data": {"quux": "foo"}, + "valid": false + } + ] + }, + { + "description": "properties with boolean schema", + "schema": { + "properties": { + "foo": true, + "bar": false + } + }, + "tests": [ + { + "description": "no property present is valid", + "data": {}, + "valid": true + }, + { + "description": "only 'true' property present is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "only 'false' property present is invalid", + "data": {"bar": 2}, + "valid": false + }, + { + "description": "both properties present is invalid", + "data": {"foo": 1, "bar": 2}, + "valid": false + } + ] + }, + { + "description": "properties with escaped characters", + "schema": { + "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"} + } + }, + "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 + }, + { + "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 + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/propertyNames.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/propertyNames.json new file mode 100644 index 0000000..f0788e6 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/propertyNames.json @@ -0,0 +1,107 @@ +[ + { + "description": "propertyNames validation", + "schema": { + "propertyNames": {"maxLength": 3} + }, + "tests": [ + { + "description": "all property names valid", + "data": { + "f": {}, + "foo": {} + }, + "valid": true + }, + { + "description": "some property names invalid", + "data": { + "foo": {}, + "foobar": {} + }, + "valid": false + }, + { + "description": "object without properties is valid", + "data": {}, + "valid": true + }, + { + "description": "ignores arrays", + "data": [1, 2, 3, 4], + "valid": true + }, + { + "description": "ignores strings", + "data": "foobar", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + }, + { + "description": "propertyNames validation with pattern", + "schema": { + "propertyNames": { "pattern": "^a+$" } + }, + "tests": [ + { + "description": "matching property names valid", + "data": { + "a": {}, + "aa": {}, + "aaa": {} + }, + "valid": true + }, + { + "description": "non-matching property name is invalid", + "data": { + "aaA": {} + }, + "valid": false + }, + { + "description": "object without properties is valid", + "data": {}, + "valid": true + } + ] + }, + { + "description": "propertyNames with boolean schema true", + "schema": {"propertyNames": true}, + "tests": [ + { + "description": "object with any properties is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "empty object is valid", + "data": {}, + "valid": true + } + ] + }, + { + "description": "propertyNames with boolean schema false", + "schema": {"propertyNames": false}, + "tests": [ + { + "description": "object with any properties is invalid", + "data": {"foo": 1}, + "valid": false + }, + { + "description": "empty object is valid", + "data": {}, + "valid": true + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/ref.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/ref.json new file mode 100644 index 0000000..900ebb0 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/ref.json @@ -0,0 +1,612 @@ +[ + { + "description": "root pointer ref", + "schema": { + "properties": { + "foo": {"$ref": "#"} + }, + "additionalProperties": false + }, + "tests": [ + { + "description": "match", + "data": {"foo": false}, + "valid": true + }, + { + "description": "recursive match", + "data": {"foo": {"foo": false}}, + "valid": true + }, + { + "description": "mismatch", + "data": {"bar": false}, + "valid": false + }, + { + "description": "recursive mismatch", + "data": {"foo": {"bar": false}}, + "valid": false + } + ] + }, + { + "description": "relative pointer ref to object", + "schema": { + "properties": { + "foo": {"type": "integer"}, + "bar": {"$ref": "#/properties/foo"} + } + }, + "tests": [ + { + "description": "match", + "data": {"bar": 3}, + "valid": true + }, + { + "description": "mismatch", + "data": {"bar": true}, + "valid": false + } + ] + }, + { + "description": "relative pointer ref to array", + "schema": { + "items": [ + {"type": "integer"}, + {"$ref": "#/items/0"} + ] + }, + "tests": [ + { + "description": "match array", + "data": [1, 2], + "valid": true + }, + { + "description": "mismatch array", + "data": [1, "foo"], + "valid": false + } + ] + }, + { + "description": "escaped pointer ref", + "schema": { + "definitions": { + "tilde~field": {"type": "integer"}, + "slash/field": {"type": "integer"}, + "percent%field": {"type": "integer"} + }, + "properties": { + "tilde": {"$ref": "#/definitions/tilde~0field"}, + "slash": {"$ref": "#/definitions/slash~1field"}, + "percent": {"$ref": "#/definitions/percent%25field"} + } + }, + "tests": [ + { + "description": "slash invalid", + "data": {"slash": "aoeu"}, + "valid": false + }, + { + "description": "tilde invalid", + "data": {"tilde": "aoeu"}, + "valid": false + }, + { + "description": "percent invalid", + "data": {"percent": "aoeu"}, + "valid": false + }, + { + "description": "slash valid", + "data": {"slash": 123}, + "valid": true + }, + { + "description": "tilde valid", + "data": {"tilde": 123}, + "valid": true + }, + { + "description": "percent valid", + "data": {"percent": 123}, + "valid": true + } + ] + }, + { + "description": "nested refs", + "schema": { + "definitions": { + "a": {"type": "integer"}, + "b": {"$ref": "#/definitions/a"}, + "c": {"$ref": "#/definitions/b"} + }, + "allOf": [{ "$ref": "#/definitions/c" }] + }, + "tests": [ + { + "description": "nested ref valid", + "data": 5, + "valid": true + }, + { + "description": "nested ref invalid", + "data": "a", + "valid": false + } + ] + }, + { + "description": "ref overrides any sibling keywords", + "schema": { + "definitions": { + "reffed": { + "type": "array" + } + }, + "properties": { + "foo": { + "$ref": "#/definitions/reffed", + "maxItems": 2 + } + } + }, + "tests": [ + { + "description": "ref valid", + "data": { "foo": [] }, + "valid": true + }, + { + "description": "ref valid, maxItems ignored", + "data": { "foo": [ 1, 2, 3] }, + "valid": true + }, + { + "description": "ref invalid", + "data": { "foo": "string" }, + "valid": false + } + ] + }, + { + "description": "$ref prevents a sibling $id from changing the base uri", + "schema": { + "$id": "http://localhost:1234/sibling_id/base/", + "definitions": { + "foo": { + "$id": "http://localhost:1234/sibling_id/foo.json", + "minimum": 2 + }, + "base_foo": { + "$comment": "this canonical uri is http://localhost:1234/sibling_id/base/foo.json", + "$id": "foo.json", + "minimum": 5 + } + }, + "allOf": [ + { + "$comment": "$ref resolves to http://localhost:1234/sibling_id/base/foo.json, not ttp://localhost:1234/sibling_id/foo.json", + "$id": "http://localhost:1234/sibling_id/", + "$ref": "foo.json" + } + ] + }, + "tests": [ + { + "description": "$ref resolves to /definitions/foo, data validates", + "data": 10, + "valid": true + }, + { + "description": "$ref resolves to /definitions/foo, data does not validate", + "data": 1, + "valid": false + } + ] + }, + { + "description": "remote ref, containing refs itself", + "schema": {"$ref": "http://json-schema.org/draft-07/schema#"}, + "tests": [ + { + "description": "remote ref valid", + "data": {"minLength": 1}, + "valid": true + }, + { + "description": "remote ref invalid", + "data": {"minLength": -1}, + "valid": false + } + ] + }, + { + "description": "property named $ref that is not a reference", + "schema": { + "properties": { + "$ref": {"type": "string"} + } + }, + "tests": [ + { + "description": "property named $ref valid", + "data": {"$ref": "a"}, + "valid": true + }, + { + "description": "property named $ref invalid", + "data": {"$ref": 2}, + "valid": false + } + ] + }, + { + "description": "property named $ref, containing an actual $ref", + "schema": { + "properties": { + "$ref": {"$ref": "#/definitions/is-string"} + }, + "definitions": { + "is-string": { + "type": "string" + } + } + }, + "tests": [ + { + "description": "property named $ref valid", + "data": {"$ref": "a"}, + "valid": true + }, + { + "description": "property named $ref invalid", + "data": {"$ref": 2}, + "valid": false + } + ] + }, + { + "description": "$ref to boolean schema true", + "schema": { + "allOf": [{ "$ref": "#/definitions/bool" }], + "definitions": { + "bool": true + } + }, + "tests": [ + { + "description": "any value is valid", + "data": "foo", + "valid": true + } + ] + }, + { + "description": "$ref to boolean schema false", + "schema": { + "allOf": [{ "$ref": "#/definitions/bool" }], + "definitions": { + "bool": false + } + }, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "Recursive references between schemas", + "schema": { + "$id": "http://localhost:1234/tree", + "description": "tree of nodes", + "type": "object", + "properties": { + "meta": {"type": "string"}, + "nodes": { + "type": "array", + "items": {"$ref": "node"} + } + }, + "required": ["meta", "nodes"], + "definitions": { + "node": { + "$id": "http://localhost:1234/node", + "description": "node", + "type": "object", + "properties": { + "value": {"type": "number"}, + "subtree": {"$ref": "tree"} + }, + "required": ["value"] + } + } + }, + "tests": [ + { + "description": "valid tree", + "data": { + "meta": "root", + "nodes": [ + { + "value": 1, + "subtree": { + "meta": "child", + "nodes": [ + {"value": 1.1}, + {"value": 1.2} + ] + } + }, + { + "value": 2, + "subtree": { + "meta": "child", + "nodes": [ + {"value": 2.1}, + {"value": 2.2} + ] + } + } + ] + }, + "valid": true + }, + { + "description": "invalid tree", + "data": { + "meta": "root", + "nodes": [ + { + "value": 1, + "subtree": { + "meta": "child", + "nodes": [ + {"value": "string is invalid"}, + {"value": 1.2} + ] + } + }, + { + "value": 2, + "subtree": { + "meta": "child", + "nodes": [ + {"value": 2.1}, + {"value": 2.2} + ] + } + } + ] + }, + "valid": false + } + ] + }, + { + "description": "refs with quote", + "schema": { + "properties": { + "foo\"bar": {"$ref": "#/definitions/foo%22bar"} + }, + "definitions": { + "foo\"bar": {"type": "number"} + } + }, + "tests": [ + { + "description": "object with numbers is valid", + "data": { + "foo\"bar": 1 + }, + "valid": true + }, + { + "description": "object with strings is invalid", + "data": { + "foo\"bar": "1" + }, + "valid": false + } + ] + }, + { + "description": "Location-independent identifier", + "schema": { + "allOf": [{ + "$ref": "#foo" + }], + "definitions": { + "A": { + "$id": "#foo", + "type": "integer" + } + } + }, + "tests": [ + { + "data": 1, + "description": "match", + "valid": true + }, + { + "data": "a", + "description": "mismatch", + "valid": false + } + ] + }, + { + "description": "Location-independent identifier with base URI change in subschema", + "schema": { + "$id": "http://localhost:1234/root", + "allOf": [{ + "$ref": "http://localhost:1234/nested.json#foo" + }], + "definitions": { + "A": { + "$id": "nested.json", + "definitions": { + "B": { + "$id": "#foo", + "type": "integer" + } + } + } + } + }, + "tests": [ + { + "data": 1, + "description": "match", + "valid": true + }, + { + "data": "a", + "description": "mismatch", + "valid": false + } + ] + }, + { + "description": "naive replacement of $ref with its destination is not correct", + "schema": { + "definitions": { + "a_string": { "type": "string" } + }, + "enum": [ + { "$ref": "#/definitions/a_string" } + ] + }, + "tests": [ + { + "description": "do not evaluate the $ref inside the enum, matching any string", + "data": "this is a string", + "valid": false + }, + { + "description": "do not evaluate the $ref inside the enum, definition exact match", + "data": { "type": "string" }, + "valid": false + }, + { + "description": "match the enum exactly", + "data": { "$ref": "#/definitions/a_string" }, + "valid": true + } + ] + }, + { + "description": "refs with relative uris and defs", + "schema": { + "$id": "http://example.com/schema-relative-uri-defs1.json", + "properties": { + "foo": { + "$id": "schema-relative-uri-defs2.json", + "definitions": { + "inner": { + "properties": { + "bar": { "type": "string" } + } + } + }, + "allOf": [ { "$ref": "#/definitions/inner" } ] + } + }, + "allOf": [ { "$ref": "schema-relative-uri-defs2.json" } ] + }, + "tests": [ + { + "description": "invalid on inner field", + "data": { + "foo": { + "bar": 1 + }, + "bar": "a" + }, + "valid": false + }, + { + "description": "invalid on outer field", + "data": { + "foo": { + "bar": "a" + }, + "bar": 1 + }, + "valid": false + }, + { + "description": "valid on both fields", + "data": { + "foo": { + "bar": "a" + }, + "bar": "a" + }, + "valid": true + } + ] + }, + { + "description": "relative refs with absolute uris and defs", + "schema": { + "$id": "http://example.com/schema-refs-absolute-uris-defs1.json", + "properties": { + "foo": { + "$id": "http://example.com/schema-refs-absolute-uris-defs2.json", + "definitions": { + "inner": { + "properties": { + "bar": { "type": "string" } + } + } + }, + "allOf": [ { "$ref": "#/definitions/inner" } ] + } + }, + "allOf": [ { "$ref": "schema-refs-absolute-uris-defs2.json" } ] + }, + "tests": [ + { + "description": "invalid on inner field", + "data": { + "foo": { + "bar": 1 + }, + "bar": "a" + }, + "valid": false + }, + { + "description": "invalid on outer field", + "data": { + "foo": { + "bar": "a" + }, + "bar": 1 + }, + "valid": false + }, + { + "description": "valid on both fields", + "data": { + "foo": { + "bar": "a" + }, + "bar": "a" + }, + "valid": true + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/refRemote.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/refRemote.json new file mode 100644 index 0000000..a2221b2 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/refRemote.json @@ -0,0 +1,196 @@ +[ + { + "description": "remote ref", + "schema": {"$ref": "http://localhost:1234/integer.json"}, + "tests": [ + { + "description": "remote ref valid", + "data": 1, + "valid": true + }, + { + "description": "remote ref invalid", + "data": "a", + "valid": false + } + ] + }, + { + "description": "fragment within remote ref", + "schema": {"$ref": "http://localhost:1234/subSchemas.json#/integer"}, + "tests": [ + { + "description": "remote fragment valid", + "data": 1, + "valid": true + }, + { + "description": "remote fragment invalid", + "data": "a", + "valid": false + } + ] + }, + { + "description": "ref within remote ref", + "schema": { + "$ref": "http://localhost:1234/subSchemas.json#/refToInteger" + }, + "tests": [ + { + "description": "ref within ref valid", + "data": 1, + "valid": true + }, + { + "description": "ref within ref invalid", + "data": "a", + "valid": false + } + ] + }, + { + "description": "base URI change", + "schema": { + "$id": "http://localhost:1234/", + "items": { + "$id": "baseUriChange/", + "items": {"$ref": "folderInteger.json"} + } + }, + "tests": [ + { + "description": "base URI change ref valid", + "data": [[1]], + "valid": true + }, + { + "description": "base URI change ref invalid", + "data": [["a"]], + "valid": false + } + ] + }, + { + "description": "base URI change - change folder", + "schema": { + "$id": "http://localhost:1234/scope_change_defs1.json", + "type" : "object", + "properties": { + "list": {"$ref": "#/definitions/baz"} + }, + "definitions": { + "baz": { + "$id": "baseUriChangeFolder/", + "type": "array", + "items": {"$ref": "folderInteger.json"} + } + } + }, + "tests": [ + { + "description": "number is valid", + "data": {"list": [1]}, + "valid": true + }, + { + "description": "string is invalid", + "data": {"list": ["a"]}, + "valid": false + } + ] + }, + { + "description": "base URI change - change folder in subschema", + "schema": { + "$id": "http://localhost:1234/scope_change_defs2.json", + "type" : "object", + "properties": { + "list": {"$ref": "#/definitions/baz/definitions/bar"} + }, + "definitions": { + "baz": { + "$id": "baseUriChangeFolderInSubschema/", + "definitions": { + "bar": { + "type": "array", + "items": {"$ref": "folderInteger.json"} + } + } + } + } + }, + "tests": [ + { + "description": "number is valid", + "data": {"list": [1]}, + "valid": true + }, + { + "description": "string is invalid", + "data": {"list": ["a"]}, + "valid": false + } + ] + }, + { + "description": "root ref in remote ref", + "schema": { + "$id": "http://localhost:1234/object", + "type": "object", + "properties": { + "name": {"$ref": "name.json#/definitions/orNull"} + } + }, + "tests": [ + { + "description": "string is valid", + "data": { + "name": "foo" + }, + "valid": true + }, + { + "description": "null is valid", + "data": { + "name": null + }, + "valid": true + }, + { + "description": "object is invalid", + "data": { + "name": { + "name": null + } + }, + "valid": false + } + ] + }, + { + "description": "remote ref with ref to definitions", + "schema": { + "$id": "http://localhost:1234/schema-remote-ref-ref-defs1.json", + "allOf": [ + { "$ref": "ref-and-definitions.json" } + ] + }, + "tests": [ + { + "description": "invalid", + "data": { + "bar": 1 + }, + "valid": false + }, + { + "description": "valid", + "data": { + "bar": "a" + }, + "valid": true + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/required.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/required.json new file mode 100644 index 0000000..abf18f3 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/required.json @@ -0,0 +1,105 @@ +[ + { + "description": "required validation", + "schema": { + "properties": { + "foo": {}, + "bar": {} + }, + "required": ["foo"] + }, + "tests": [ + { + "description": "present required property is valid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "non-present required property is invalid", + "data": {"bar": 1}, + "valid": false + }, + { + "description": "ignores arrays", + "data": [], + "valid": true + }, + { + "description": "ignores strings", + "data": "", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + }, + { + "description": "required default validation", + "schema": { + "properties": { + "foo": {} + } + }, + "tests": [ + { + "description": "not required by default", + "data": {}, + "valid": true + } + ] + }, + { + "description": "required with empty array", + "schema": { + "properties": { + "foo": {} + }, + "required": [] + }, + "tests": [ + { + "description": "property not required", + "data": {}, + "valid": true + } + ] + }, + { + "description": "required with escaped characters", + "schema": { + "required": [ + "foo\nbar", + "foo\"bar", + "foo\\bar", + "foo\rbar", + "foo\tbar", + "foo\fbar" + ] + }, + "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 + }, + { + "description": "object with some properties missing is invalid", + "data": { + "foo\nbar": "1", + "foo\"bar": "1" + }, + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/type.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/type.json new file mode 100644 index 0000000..efb4f57 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/type.json @@ -0,0 +1,469 @@ +[ + { + "description": "integer type matches integers", + "schema": {"type": "integer"}, + "tests": [ + { + "description": "an integer is an integer", + "data": 1, + "valid": true + }, + { + "description": "a float is not an integer", + "data": 1.1, + "valid": false + }, + { + "description": "a string is not an integer", + "data": "foo", + "valid": false + }, + { + "description": "a string is still not an integer, even if it looks like one", + "data": "1", + "valid": false + }, + { + "description": "an object is not an integer", + "data": {}, + "valid": false + }, + { + "description": "an array is not an integer", + "data": [], + "valid": false + }, + { + "description": "a boolean is not an integer", + "data": true, + "valid": false + }, + { + "description": "null is not an integer", + "data": null, + "valid": false + } + ] + }, + { + "description": "number type matches numbers", + "schema": {"type": "number"}, + "tests": [ + { + "description": "an integer is a number", + "data": 1, + "valid": true + }, + { + "description": "a float with zero fractional part is a number (and an integer)", + "data": 1.0, + "valid": true + }, + { + "description": "a float is a number", + "data": 1.1, + "valid": true + }, + { + "description": "a string is not a number", + "data": "foo", + "valid": false + }, + { + "description": "a string is still not a number, even if it looks like one", + "data": "1", + "valid": false + }, + { + "description": "an object is not a number", + "data": {}, + "valid": false + }, + { + "description": "an array is not a number", + "data": [], + "valid": false + }, + { + "description": "a boolean is not a number", + "data": true, + "valid": false + }, + { + "description": "null is not a number", + "data": null, + "valid": false + } + ] + }, + { + "description": "string type matches strings", + "schema": {"type": "string"}, + "tests": [ + { + "description": "1 is not a string", + "data": 1, + "valid": false + }, + { + "description": "a float is not a string", + "data": 1.1, + "valid": false + }, + { + "description": "a string is a string", + "data": "foo", + "valid": true + }, + { + "description": "a string is still a string, even if it looks like a number", + "data": "1", + "valid": true + }, + { + "description": "an empty string is still a string", + "data": "", + "valid": true + }, + { + "description": "an object is not a string", + "data": {}, + "valid": false + }, + { + "description": "an array is not a string", + "data": [], + "valid": false + }, + { + "description": "a boolean is not a string", + "data": true, + "valid": false + }, + { + "description": "null is not a string", + "data": null, + "valid": false + } + ] + }, + { + "description": "object type matches objects", + "schema": {"type": "object"}, + "tests": [ + { + "description": "an integer is not an object", + "data": 1, + "valid": false + }, + { + "description": "a float is not an object", + "data": 1.1, + "valid": false + }, + { + "description": "a string is not an object", + "data": "foo", + "valid": false + }, + { + "description": "an object is an object", + "data": {}, + "valid": true + }, + { + "description": "an array is not an object", + "data": [], + "valid": false + }, + { + "description": "a boolean is not an object", + "data": true, + "valid": false + }, + { + "description": "null is not an object", + "data": null, + "valid": false + } + ] + }, + { + "description": "array type matches arrays", + "schema": {"type": "array"}, + "tests": [ + { + "description": "an integer is not an array", + "data": 1, + "valid": false + }, + { + "description": "a float is not an array", + "data": 1.1, + "valid": false + }, + { + "description": "a string is not an array", + "data": "foo", + "valid": false + }, + { + "description": "an object is not an array", + "data": {}, + "valid": false + }, + { + "description": "an array is an array", + "data": [], + "valid": true + }, + { + "description": "a boolean is not an array", + "data": true, + "valid": false + }, + { + "description": "null is not an array", + "data": null, + "valid": false + } + ] + }, + { + "description": "boolean type matches booleans", + "schema": {"type": "boolean"}, + "tests": [ + { + "description": "an integer is not a boolean", + "data": 1, + "valid": false + }, + { + "description": "zero is not a boolean", + "data": 0, + "valid": false + }, + { + "description": "a float is not a boolean", + "data": 1.1, + "valid": false + }, + { + "description": "a string is not a boolean", + "data": "foo", + "valid": false + }, + { + "description": "an empty string is not a boolean", + "data": "", + "valid": false + }, + { + "description": "an object is not a boolean", + "data": {}, + "valid": false + }, + { + "description": "an array is not a boolean", + "data": [], + "valid": false + }, + { + "description": "true is a boolean", + "data": true, + "valid": true + }, + { + "description": "false is a boolean", + "data": false, + "valid": true + }, + { + "description": "null is not a boolean", + "data": null, + "valid": false + } + ] + }, + { + "description": "null type matches only the null object", + "schema": {"type": "null"}, + "tests": [ + { + "description": "an integer is not null", + "data": 1, + "valid": false + }, + { + "description": "a float is not null", + "data": 1.1, + "valid": false + }, + { + "description": "zero is not null", + "data": 0, + "valid": false + }, + { + "description": "a string is not null", + "data": "foo", + "valid": false + }, + { + "description": "an empty string is not null", + "data": "", + "valid": false + }, + { + "description": "an object is not null", + "data": {}, + "valid": false + }, + { + "description": "an array is not null", + "data": [], + "valid": false + }, + { + "description": "true is not null", + "data": true, + "valid": false + }, + { + "description": "false is not null", + "data": false, + "valid": false + }, + { + "description": "null is null", + "data": null, + "valid": true + } + ] + }, + { + "description": "multiple types can be specified in an array", + "schema": {"type": ["integer", "string"]}, + "tests": [ + { + "description": "an integer is valid", + "data": 1, + "valid": true + }, + { + "description": "a string is valid", + "data": "foo", + "valid": true + }, + { + "description": "a float is invalid", + "data": 1.1, + "valid": false + }, + { + "description": "an object is invalid", + "data": {}, + "valid": false + }, + { + "description": "an array is invalid", + "data": [], + "valid": false + }, + { + "description": "a boolean is invalid", + "data": true, + "valid": false + }, + { + "description": "null is invalid", + "data": null, + "valid": false + } + ] + }, + { + "description": "type as array with one item", + "schema": { + "type": ["string"] + }, + "tests": [ + { + "description": "string is valid", + "data": "foo", + "valid": true + }, + { + "description": "number is invalid", + "data": 123, + "valid": false + } + ] + }, + { + "description": "type: array or object", + "schema": { + "type": ["array", "object"] + }, + "tests": [ + { + "description": "array is valid", + "data": [1,2,3], + "valid": true + }, + { + "description": "object is valid", + "data": {"foo": 123}, + "valid": true + }, + { + "description": "number is invalid", + "data": 123, + "valid": false + }, + { + "description": "string is invalid", + "data": "foo", + "valid": false + }, + { + "description": "null is invalid", + "data": null, + "valid": false + } + ] + }, + { + "description": "type: array, object or null", + "schema": { + "type": ["array", "object", "null"] + }, + "tests": [ + { + "description": "array is valid", + "data": [1,2,3], + "valid": true + }, + { + "description": "object is valid", + "data": {"foo": 123}, + "valid": true + }, + { + "description": "null is valid", + "data": null, + "valid": true + }, + { + "description": "number is invalid", + "data": 123, + "valid": false + }, + { + "description": "string is invalid", + "data": "foo", + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/uniqueItems.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/uniqueItems.json new file mode 100644 index 0000000..4846c77 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/uniqueItems.json @@ -0,0 +1,384 @@ +[ + { + "description": "uniqueItems validation", + "schema": {"uniqueItems": true}, + "tests": [ + { + "description": "unique array of integers is valid", + "data": [1, 2], + "valid": true + }, + { + "description": "non-unique array of integers is invalid", + "data": [1, 1], + "valid": false + }, + { + "description": "numbers are unique if mathematically unequal", + "data": [1.0, 1.00, 1], + "valid": false + }, + { + "description": "false is not equal to zero", + "data": [0, false], + "valid": true + }, + { + "description": "true is not equal to one", + "data": [1, true], + "valid": true + }, + { + "description": "unique array of objects is valid", + "data": [{"foo": "bar"}, {"foo": "baz"}], + "valid": true + }, + { + "description": "non-unique array of objects is invalid", + "data": [{"foo": "bar"}, {"foo": "bar"}], + "valid": false + }, + { + "description": "unique array of nested objects is valid", + "data": [ + {"foo": {"bar" : {"baz" : true}}}, + {"foo": {"bar" : {"baz" : false}}} + ], + "valid": true + }, + { + "description": "non-unique array of nested objects is invalid", + "data": [ + {"foo": {"bar" : {"baz" : true}}}, + {"foo": {"bar" : {"baz" : true}}} + ], + "valid": false + }, + { + "description": "unique array of arrays is valid", + "data": [["foo"], ["bar"]], + "valid": true + }, + { + "description": "non-unique array of arrays is invalid", + "data": [["foo"], ["foo"]], + "valid": false + }, + { + "description": "1 and true are unique", + "data": [1, true], + "valid": true + }, + { + "description": "0 and false are unique", + "data": [0, false], + "valid": true + }, + { + "description": "[1] and [true] are unique", + "data": [[1], [true]], + "valid": true + }, + { + "description": "[0] and [false] are unique", + "data": [[0], [false]], + "valid": true + }, + { + "description": "nested [1] and [true] are unique", + "data": [[[1], "foo"], [[true], "foo"]], + "valid": true + }, + { + "description": "nested [0] and [false] are unique", + "data": [[[0], "foo"], [[false], "foo"]], + "valid": true + }, + { + "description": "unique heterogeneous types are valid", + "data": [{}, [1], true, null, 1, "{}"], + "valid": true + }, + { + "description": "non-unique heterogeneous types are invalid", + "data": [{}, [1], true, null, {}, 1], + "valid": false + }, + { + "description": "different objects are unique", + "data": [{"a": 1, "b": 2}, {"a": 2, "b": 1}], + "valid": true + }, + { + "description": "objects are non-unique despite key order", + "data": [{"a": 1, "b": 2}, {"b": 2, "a": 1}], + "valid": false + }, + { + "description": "{\"a\": false} and {\"a\": 0} are unique", + "data": [{"a": false}, {"a": 0}], + "valid": true + }, + { + "description": "{\"a\": true} and {\"a\": 1} are unique", + "data": [{"a": true}, {"a": 1}], + "valid": true + } + ] + }, + { + "description": "uniqueItems with an array of items", + "schema": { + "items": [{"type": "boolean"}, {"type": "boolean"}], + "uniqueItems": true + }, + "tests": [ + { + "description": "[false, true] from items array is valid", + "data": [false, true], + "valid": true + }, + { + "description": "[true, false] from items array is valid", + "data": [true, false], + "valid": true + }, + { + "description": "[false, false] from items array is not valid", + "data": [false, false], + "valid": false + }, + { + "description": "[true, true] from items array is not valid", + "data": [true, true], + "valid": false + }, + { + "description": "unique array extended from [false, true] is valid", + "data": [false, true, "foo", "bar"], + "valid": true + }, + { + "description": "unique array extended from [true, false] is valid", + "data": [true, false, "foo", "bar"], + "valid": true + }, + { + "description": "non-unique array extended from [false, true] is not valid", + "data": [false, true, "foo", "foo"], + "valid": false + }, + { + "description": "non-unique array extended from [true, false] is not valid", + "data": [true, false, "foo", "foo"], + "valid": false + } + ] + }, + { + "description": "uniqueItems with an array of items and additionalItems=false", + "schema": { + "items": [{"type": "boolean"}, {"type": "boolean"}], + "uniqueItems": true, + "additionalItems": false + }, + "tests": [ + { + "description": "[false, true] from items array is valid", + "data": [false, true], + "valid": true + }, + { + "description": "[true, false] from items array is valid", + "data": [true, false], + "valid": true + }, + { + "description": "[false, false] from items array is not valid", + "data": [false, false], + "valid": false + }, + { + "description": "[true, true] from items array is not valid", + "data": [true, true], + "valid": false + }, + { + "description": "extra items are invalid even if unique", + "data": [false, true, null], + "valid": false + } + ] + }, + { + "description": "uniqueItems=false validation", + "schema": { "uniqueItems": false }, + "tests": [ + { + "description": "unique array of integers is valid", + "data": [1, 2], + "valid": true + }, + { + "description": "non-unique array of integers is valid", + "data": [1, 1], + "valid": true + }, + { + "description": "numbers are unique if mathematically unequal", + "data": [1.0, 1.00, 1], + "valid": true + }, + { + "description": "false is not equal to zero", + "data": [0, false], + "valid": true + }, + { + "description": "true is not equal to one", + "data": [1, true], + "valid": true + }, + { + "description": "unique array of objects is valid", + "data": [{"foo": "bar"}, {"foo": "baz"}], + "valid": true + }, + { + "description": "non-unique array of objects is valid", + "data": [{"foo": "bar"}, {"foo": "bar"}], + "valid": true + }, + { + "description": "unique array of nested objects is valid", + "data": [ + {"foo": {"bar" : {"baz" : true}}}, + {"foo": {"bar" : {"baz" : false}}} + ], + "valid": true + }, + { + "description": "non-unique array of nested objects is valid", + "data": [ + {"foo": {"bar" : {"baz" : true}}}, + {"foo": {"bar" : {"baz" : true}}} + ], + "valid": true + }, + { + "description": "unique array of arrays is valid", + "data": [["foo"], ["bar"]], + "valid": true + }, + { + "description": "non-unique array of arrays is valid", + "data": [["foo"], ["foo"]], + "valid": true + }, + { + "description": "1 and true are unique", + "data": [1, true], + "valid": true + }, + { + "description": "0 and false are unique", + "data": [0, false], + "valid": true + }, + { + "description": "unique heterogeneous types are valid", + "data": [{}, [1], true, null, 1], + "valid": true + }, + { + "description": "non-unique heterogeneous types are valid", + "data": [{}, [1], true, null, {}, 1], + "valid": true + } + ] + }, + { + "description": "uniqueItems=false with an array of items", + "schema": { + "items": [{"type": "boolean"}, {"type": "boolean"}], + "uniqueItems": false + }, + "tests": [ + { + "description": "[false, true] from items array is valid", + "data": [false, true], + "valid": true + }, + { + "description": "[true, false] from items array is valid", + "data": [true, false], + "valid": true + }, + { + "description": "[false, false] from items array is valid", + "data": [false, false], + "valid": true + }, + { + "description": "[true, true] from items array is valid", + "data": [true, true], + "valid": true + }, + { + "description": "unique array extended from [false, true] is valid", + "data": [false, true, "foo", "bar"], + "valid": true + }, + { + "description": "unique array extended from [true, false] is valid", + "data": [true, false, "foo", "bar"], + "valid": true + }, + { + "description": "non-unique array extended from [false, true] is valid", + "data": [false, true, "foo", "foo"], + "valid": true + }, + { + "description": "non-unique array extended from [true, false] is valid", + "data": [true, false, "foo", "foo"], + "valid": true + } + ] + }, + { + "description": "uniqueItems=false with an array of items and additionalItems=false", + "schema": { + "items": [{"type": "boolean"}, {"type": "boolean"}], + "uniqueItems": false, + "additionalItems": false + }, + "tests": [ + { + "description": "[false, true] from items array is valid", + "data": [false, true], + "valid": true + }, + { + "description": "[true, false] from items array is valid", + "data": [true, false], + "valid": true + }, + { + "description": "[false, false] from items array is valid", + "data": [false, false], + "valid": true + }, + { + "description": "[true, true] from items array is valid", + "data": [true, true], + "valid": true + }, + { + "description": "extra items are invalid even if unique", + "data": [false, true, null], + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/unknownKeyword.json b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/unknownKeyword.json new file mode 100644 index 0000000..1f58d97 --- /dev/null +++ b/lib/All/json-schema-validator/test/JSON-Schema-Test-Suite/tests/draft7/unknownKeyword.json @@ -0,0 +1,56 @@ +[ + { + "description": "$id inside an unknown keyword is not a real identifier", + "comment": "the implementation must not be confused by an $id in locations we do not know how to parse", + "schema": { + "definitions": { + "id_in_unknown0": { + "not": { + "array_of_schemas": [ + { + "$id": "https://localhost:1234/unknownKeyword/my_identifier.json", + "type": "null" + } + ] + } + }, + "real_id_in_schema": { + "$id": "https://localhost:1234/unknownKeyword/my_identifier.json", + "type": "string" + }, + "id_in_unknown1": { + "not": { + "object_of_schemas": { + "foo": { + "$id": "https://localhost:1234/unknownKeyword/my_identifier.json", + "type": "integer" + } + } + } + } + }, + "anyOf": [ + { "$ref": "#/definitions/id_in_unknown0" }, + { "$ref": "#/definitions/id_in_unknown1" }, + { "$ref": "https://localhost:1234/unknownKeyword/my_identifier.json" } + ] + }, + "tests": [ + { + "description": "type matches second anyOf, which has a real schema in it", + "data": "a string", + "valid": true + }, + { + "description": "type matches non-schema in first anyOf", + "data": null, + "valid": false + }, + { + "description": "type matches non-schema in third anyOf", + "data": 1, + "valid": false + } + ] + } +] diff --git a/lib/All/json-schema-validator/test/binary-validation.cpp b/lib/All/json-schema-validator/test/binary-validation.cpp new file mode 100644 index 0000000..23831fc --- /dev/null +++ b/lib/All/json-schema-validator/test/binary-validation.cpp @@ -0,0 +1,175 @@ +// bson-validate.cpp + +#include +#include +#include + +static int error_count = 0; + +#define EXPECT_EQ(a, b) \ + do { \ + if (a != b) { \ + std::cerr << "Failed: '" << a << "' != '" << b << "'\n"; \ + error_count++; \ + } \ + } while (0) + +#define EXPECT_THROW(foo) \ + { \ + bool ok = false; \ + try { \ + foo; \ + } catch (std::exception &) { \ + ok = true; \ + } \ + if (ok == false) { \ + error_count++; \ + } \ + } + +using json = nlohmann::json; +using validator = nlohmann::json_schema::json_validator; + +// check binary data validation +const json bson_schema = json::parse(R"( +{ + "type": "object", + "properties": { + "standard_string": { + "type": "string" + }, + "binary_data": { + "type": "string", + "contentEncoding": "binary" + } + }, + "additionalProperties": false +} +)"); + +const json array_of_types = json::parse(R"( +{ + "type": "object", + "properties": { + "something": { + "type": ["string", "number", "boolean"], + "contentEncoding": "binary" + } + } +} +)"); + +const json array_of_types_without_binary = json::parse(R"( +{ + "type": "object", + "properties": { + "something": { + "type": ["string", "number", "boolean"] + } + } +} +)"); + +class store_ptr_err_handler : public nlohmann::json_schema::basic_error_handler +{ + void error(const nlohmann::json::json_pointer &ptr, const json &, const std::string &message) override + { + nlohmann::json_schema::basic_error_handler::error(ptr, "", message); + std::cerr << "ERROR: '" << ptr << "' - '" + << "" + << "': " << message << "\n"; + failed_pointers.push_back(ptr); + } + +public: + std::vector failed_pointers; + + void reset() override + { + nlohmann::json_schema::basic_error_handler::reset(); + failed_pointers.clear(); + } +}; + +static void content(const std::string &contentEncoding, const std::string &contentMediaType, const json &instance) +{ + std::cerr << "mediaType: '" << contentMediaType << "', encoding: '" << contentEncoding << "'\n"; + + if (contentEncoding == "binary") { + if (instance.type() != json::value_t::binary) { + throw std::invalid_argument{"expected binary data"}; + } + } else { + if (instance.type() == json::value_t::binary) { + throw std::invalid_argument{"expected string, but get binary"}; + } + } +} + +int main() +{ + validator val(nullptr, nullptr, content); + + // create some bson doc + json::binary_t arr; + std::string as_binary = "hello world"; + std::copy(as_binary.begin(), as_binary.end(), std::back_inserter(arr)); + + json binary = json::binary(arr); + + store_ptr_err_handler err; + + ///////////////////////////////////// + val.set_root_schema(bson_schema); + + // all right + val.validate({{"standard_string", "some string"}, {"binary_data", binary}}, err); + EXPECT_EQ(err.failed_pointers.size(), 0); + err.reset(); + + // invalid binary data + val.validate({{"binary_data", "string, but expect binary data"}}, err); + EXPECT_EQ(err.failed_pointers.size(), 1); + EXPECT_EQ(err.failed_pointers[0].to_string(), "/binary_data"); + err.reset(); + + // also check that simple string not accept binary data + val.validate({{"standard_string", binary}, {"binary_data", binary}}, err); + EXPECT_EQ(err.failed_pointers.size(), 1); + EXPECT_EQ(err.failed_pointers[0].to_string(), "/standard_string"); + err.reset(); + + ///////////////////////////////////// + // check with array of types + + // check simple types + val.set_root_schema(array_of_types); + val.validate({{"something", 1}}, err); + val.validate({{"something", false}}, err); + // TODO when we set `string` in array and set `contentEncoding` = "binary" - what it means? We expected string or binary? + // Or we expect only binary? Now if you set `contentEncoding` = "binary", then it means that you expect only binary data, + // not string + // val.validate({{"something", "string"}}, err); -> produce error about type + EXPECT_EQ(err.failed_pointers.size(), 0); + err.reset(); + + // check binary data + val.validate({{"something", binary}}, err); + EXPECT_EQ(err.failed_pointers.size(), 0); + err.reset(); + + ///////////////////////////////////// + // and check that you can't set binary data if contentEncoding don't set + val.set_root_schema(array_of_types_without_binary); + val.validate({{"something", binary}}, err); + EXPECT_EQ(err.failed_pointers.size(), 1); + EXPECT_EQ(err.failed_pointers[0].to_string(), "/something"); + err.reset(); + + // check that without content callback you get exception with schema with contentEncoding or contentMeditType + validator val_no_content; + + EXPECT_THROW(val_no_content.set_root_schema(bson_schema)); + + return error_count; +} diff --git a/lib/All/json-schema-validator/test/errors.cpp b/lib/All/json-schema-validator/test/errors.cpp new file mode 100644 index 0000000..3f95d15 --- /dev/null +++ b/lib/All/json-schema-validator/test/errors.cpp @@ -0,0 +1,130 @@ +#include + +#include + +static int error_count; + +#define EXPECT_EQ(a, b) \ + do { \ + if (a != b) { \ + std::cerr << "Failed: '" << a << "' != '" << b << "'\n"; \ + error_count++; \ + } \ + } while (0) + +using nlohmann::json; +using nlohmann::json_schema::json_validator; + +namespace +{ + +// The schema is defined based upon a string literal +static json person_schema = R"( +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "A person", + "properties": { + "name": { + "description": "Name", + "type": "string" + }, + "age": { + "description": "Age of the person", + "type": "number", + "minimum": 2, + "maximum": 200 + }, + "phones": { + "type": "array", + "items": { + "type": "number" + } + } + }, + "required": [ + "name", + "age" + ], + "additionalProperties": false, + "type": "object" +})"_json; + +class store_ptr_err_handler : public nlohmann::json_schema::basic_error_handler +{ + void error(const nlohmann::json::json_pointer &ptr, const json &instance, const std::string &message) override + { + nlohmann::json_schema::basic_error_handler::error(ptr, instance, message); + std::cerr << "ERROR: '" << ptr << "' - '" << instance << "': " << message << "\n"; + failed_pointers.push_back(ptr); + } + +public: + std::vector failed_pointers; + + void reset() override + { + nlohmann::json_schema::basic_error_handler::reset(); + failed_pointers.clear(); + } +}; + +} // namespace + +int main(void) +{ + json_validator validator; + + try { + validator.set_root_schema(person_schema); // insert root-schema + } catch (const std::exception &e) { + std::cerr << "Validation of schema failed, here is why: " << e.what() << "\n"; + return EXIT_FAILURE; + } + + store_ptr_err_handler err; + + validator.validate({{"age", 42}, {"name", "John"}}, err); // OK + EXPECT_EQ(err.failed_pointers.size(), 0); + err.reset(); + + validator.validate({{"age", 42}}, err); // no name + + EXPECT_EQ(err.failed_pointers.size(), 1); + EXPECT_EQ(err.failed_pointers[0].to_string(), ""); + err.reset(); + + validator.validate({{"street", "Boulevard"}}, err); // no name and no age + EXPECT_EQ(err.failed_pointers.size(), 3); + EXPECT_EQ(err.failed_pointers[0].to_string(), ""); + EXPECT_EQ(err.failed_pointers[1].to_string(), ""); + EXPECT_EQ(err.failed_pointers[2].to_string(), ""); + err.reset(); + + validator.validate({{"age", 42}, {"name", 12}}, err); // name must be a string + EXPECT_EQ(err.failed_pointers.size(), 1); + EXPECT_EQ(err.failed_pointers[0].to_string(), "/name"); + err.reset(); + + validator.validate({ + {"age", 42}, + {"name", "John"}, + {"phones", {1234, "223"}}, + }, + err); // name must be a string + EXPECT_EQ(err.failed_pointers.size(), 1); + EXPECT_EQ(err.failed_pointers[0].to_string(), "/phones/1"); + err.reset(); + + validator.validate({ + {"age", 42}, + {"name", "John"}, + {"phones", {0}}, + {"post-code", 12345}, + }, + err); // name must be a string + EXPECT_EQ(err.failed_pointers.size(), 1); + EXPECT_EQ(err.failed_pointers[0].to_string(), ""); + err.reset(); + + return error_count; +} diff --git a/lib/All/json-schema-validator/test/id-ref.cpp b/lib/All/json-schema-validator/test/id-ref.cpp new file mode 100644 index 0000000..5009b3d --- /dev/null +++ b/lib/All/json-schema-validator/test/id-ref.cpp @@ -0,0 +1,146 @@ +#include + +#include + +#include + +using nlohmann::json; + +auto schema_draft = R"( + { + "$id": "http://example.com/root.json", + "definitions": { + "A": { "$id": "#foo" }, + "B": { + "$id": "other.json", + "definitions": { + "X": { "$id": "#bar" }, + "Y": { "$id": "t/inner.json" } + } + }, + "C": { + + "$id": "urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f", + "definitions": { + "Z": { "$id": "#bar" }, + "9": { "$id": "http://example.com/drole.json" } + } + } + } + } +)"_json; + +/* # (document root) + + http://example.com/root.json + http://example.com/root.json# + + #/definitions/A + + http://example.com/root.json#foo + http://example.com/root.json#/definitions/A + + #/definitions/B + + http://example.com/other.json + http://example.com/other.json# + http://example.com/root.json#/definitions/B + + #/definitions/B/definitions/X + + http://example.com/other.json#bar + http://example.com/other.json#/definitions/X + http://example.com/root.json#/definitions/B/definitions/X + + #/definitions/B/definitions/Y + + http://example.com/t/inner.json + http://example.com/t/inner.json# + http://example.com/other.json#/definitions/Y + http://example.com/root.json#/definitions/B/definitions/Y + + #/definitions/C + + urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f + urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f# + http://example.com/root.json#/definitions/C + */ + +auto schema = R"( +{ + "id": "http://localhost:1234/scope_change_defs2.json", + "type" : "object", + "properties": { + "list": {"$ref": "#/definitions/baz/definitions/bar"} + }, + "definitions": { + "baz": { + "id": "folder/", + "definitions": { + "bar": { + "type": "array", + "items": {"$ref": "folderInteger.json"} + } + } + } + } +})"_json; + +class json_schema_validator +{ +public: + std::vector schemas_; + std::map schema_store_; + +public: + void insert_schema(json &s, std::vector base_uris) + { + auto id = s.find("$id"); + if (id != s.end()) + base_uris.push_back(base_uris.back().derive(id.value())); + + for (auto &u : base_uris) + schema_store_[u] = &s; + + for (auto i = s.begin(); + i != s.end(); + ++i) { + + switch (i.value().type()) { + case json::value_t::object: { // child is object, thus a schema + std::vector subschema_uri = base_uris; + + for (auto &ss : subschema_uri) + ss = ss.append(nlohmann::json_uri::escape(i.key())); + + insert_schema(i.value(), subschema_uri); + } break; + + case json::value_t::string: + // this schema is a reference + if (i.key() == "$ref") { + auto id = base_uris.back().derive(i.value()); + i.value() = id.to_string(); + } + + break; + + default: + break; + } + } + } +}; + +int main(void) +{ + json_schema_validator store; + + store.insert_schema(schema_draft, {{"#"}}); + + for (auto &i : store.schema_store_) { + std::cerr << i.first << " " << *i.second << "\n"; + } + + return 0; +} diff --git a/lib/All/json-schema-validator/test/issue-100/CMakeLists.txt b/lib/All/json-schema-validator/test/issue-100/CMakeLists.txt new file mode 100644 index 0000000..06a754f --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-100/CMakeLists.txt @@ -0,0 +1,6 @@ +add_test_simple_schema(Issue::100 + ${CMAKE_CURRENT_SOURCE_DIR}/schema.json + ${CMAKE_CURRENT_SOURCE_DIR}/instance.json) +set_tests_properties(Issue::100 + PROPERTIES + WILL_FAIL 1) diff --git a/lib/All/json-schema-validator/test/issue-100/instance.json b/lib/All/json-schema-validator/test/issue-100/instance.json new file mode 100644 index 0000000..0f8d8df --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-100/instance.json @@ -0,0 +1,4 @@ +{ + "Prop1": 1, + "Prop2": [] +} diff --git a/lib/All/json-schema-validator/test/issue-100/schema.json b/lib/All/json-schema-validator/test/issue-100/schema.json new file mode 100644 index 0000000..3230714 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-100/schema.json @@ -0,0 +1,15 @@ +{ + "$id": "http://xxx.local/schemas/mySchema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + + "type": "object", + "properties": { + "Prop1": { + "type": "integer", + "$comment": "Just a comment" + }, + "Prop2": { + "$ref": "#random_ref" + } + } +} diff --git a/lib/All/json-schema-validator/test/issue-101/CMakeLists.txt b/lib/All/json-schema-validator/test/issue-101/CMakeLists.txt new file mode 100644 index 0000000..41ad0c9 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-101/CMakeLists.txt @@ -0,0 +1,6 @@ +add_test_simple_schema(Issue::101 + ${CMAKE_CURRENT_SOURCE_DIR}/schema.json + ${CMAKE_CURRENT_SOURCE_DIR}/instance.json) +set_tests_properties(Issue::101 + PROPERTIES + WILL_FAIL 1) diff --git a/lib/All/json-schema-validator/test/issue-101/instance.json b/lib/All/json-schema-validator/test/issue-101/instance.json new file mode 100644 index 0000000..fb5716b --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-101/instance.json @@ -0,0 +1 @@ +{"top": 1} diff --git a/lib/All/json-schema-validator/test/issue-101/schema.json b/lib/All/json-schema-validator/test/issue-101/schema.json new file mode 100644 index 0000000..19fad64 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-101/schema.json @@ -0,0 +1,12 @@ +{ + "$id": "http://xxx.local/schemas/mySchema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + + "type": "object", + "properties": { + "top": { + "type": "integer" + }, + "required": ["top"] + } +} diff --git a/lib/All/json-schema-validator/test/issue-105-verbose-combination-errors.cpp b/lib/All/json-schema-validator/test/issue-105-verbose-combination-errors.cpp new file mode 100644 index 0000000..f93e1da --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-105-verbose-combination-errors.cpp @@ -0,0 +1,321 @@ +#include "nlohmann/json-schema.hpp" +#include "nlohmann/json.hpp" + +#include +#include +#include +#include + +//============================================================================== +// Test macros +//============================================================================== +#define LOG_ERROR(LOG_ERROR__ARGS) \ + std::cerr << __FILE__ << ":" << __LINE__ << ": " << LOG_ERROR__ARGS << std::endl + +#define EXPECT_THROW_WITH_MESSAGE(EXPRESSION, MESSAGE) \ + do { \ + try { \ + EXPRESSION; \ + LOG_ERROR("Expected exception not thrown with matching regex: \"" << MESSAGE << "\""); \ + ++g_error_count; \ + } catch (const std::exception &error) { \ + const std::regex error_re{MESSAGE}; \ + if (!std::regex_search(error.what(), error_re)) { \ + LOG_ERROR("Expected exception with matching regex: \"" << MESSAGE << "\", but got this instead: " << error.what()); \ + ++g_error_count; \ + } \ + } \ + } while (false) + +#define ASSERT_OR_EXPECT_EQ(FIRST_THING, SECOND_THING, RETURN_IN_CASE_OF_ERROR) \ + do { \ + if ((FIRST_THING) != (SECOND_THING)) { \ + LOG_ERROR("The two values of " << (FIRST_THING) << " (" #FIRST_THING << ") and " << (SECOND_THING) << " (" #SECOND_THING << ") should be equal"); \ + if (RETURN_IN_CASE_OF_ERROR) { \ + return; \ + } \ + } \ + } while (false) + +#define ASSERT_EQ(FIRST_THING, SECOND_THING) ASSERT_OR_EXPECT_EQ(FIRST_THING, SECOND_THING, true) +#define EXPECT_EQ(FIRST_THING, SECOND_THING) ASSERT_OR_EXPECT_EQ(FIRST_THING, SECOND_THING, true) + +#define EXPECT_MATCH(STRING, REGEX) \ + do { \ + if (!std::regex_search((STRING), std::regex{(REGEX)})) { \ + LOG_ERROR("String \"" << (STRING) << "\" doesn't match with regex: \"" << (REGEX) << "\""); \ + ++g_error_count; \ + } \ + } while (false) + +namespace +{ + +//============================================================================== +// Test environment +//============================================================================== +int g_error_count = 0; + +//============================================================================== +// The schema used for testing +//============================================================================== +const std::string g_schema_template = R"( +{ + "properties": { + "first": { + "%COMBINATION_FIRST_LEVEL%": [ + { + "properties": { + "second": { + "%COMBINATION_SECOND_LEVEL%": [ + { + "minimum": 5, + "type": "integer" + }, + { + "multipleOf": 2, + "type": "integer" + } + ] + } + }, + "type": "object" + }, + { + "minimum": 20, + "type": "integer" + }, + { + "minLength": 10, + "type": "string" + } + ] + } + }, + "type": "object" +} +)"; + +auto generateSchema(const std::string &first_combination, const std::string &second_combination) -> nlohmann::json +{ + static const std::regex first_replace_re{"%COMBINATION_FIRST_LEVEL%"}; + static const std::regex second_replace_re{"%COMBINATION_SECOND_LEVEL%"}; + + std::string intermediate = std::regex_replace(g_schema_template, first_replace_re, first_combination); + + return nlohmann::json::parse(std::regex_replace(intermediate, second_replace_re, second_combination)); +} + +//============================================================================== +// Error handler to catch all the errors generated by the validator - also inside the combinations +//============================================================================== +class MyErrorHandler : public nlohmann::json_schema::error_handler +{ +public: + struct ErrorEntry { + nlohmann::json::json_pointer ptr; + nlohmann::json intance; + std::string message; + }; + + using ErrorEntryList = std::vector; + + auto getErrors() const -> const ErrorEntryList & + { + return m_error_list; + } + +private: + auto error(const nlohmann::json::json_pointer &ptr, const nlohmann::json &instance, const std::string &message) -> void override + { + m_error_list.push_back(ErrorEntry{ptr, instance, message}); + } + + ErrorEntryList m_error_list; +}; + +//============================================================================== +// Error string helpers +//============================================================================== +auto operator<<(std::string first, const std::string &second) -> std::string +{ + first += ".*"; + first += second; + return first; +} + +auto rootError(const std::string &combination_type, std::size_t number_of_subschemas) -> std::string +{ + return "no subschema has succeeded, but one of them is required to validate. Type: " + combination_type + ", number of failed subschemas: " + std::to_string(number_of_subschemas); +} + +auto combinationError(const std::string &combination_type, std::size_t test_case_number) -> std::string +{ + return "[combination: " + combination_type + " / case#" + std::to_string(test_case_number) + "]"; +} + +//============================================================================== +// Validator function - for simplicity +//============================================================================== +auto validate(const nlohmann::json &schema, const nlohmann::json &instance, nlohmann::json_schema::error_handler *error_handler = nullptr) -> void +{ + nlohmann::json_schema::json_validator validator; + validator.set_root_schema(schema); + + if (error_handler) { + validator.validate(instance, *error_handler); + } else { + validator.validate(instance); + } +} + +//============================================================================== +// The test cases +//============================================================================== +auto simpleTest(const std::string &first_combination, const std::string &second_combination) -> void +{ + const nlohmann::json schema = generateSchema(first_combination, second_combination); + EXPECT_THROW_WITH_MESSAGE(validate(schema, nlohmann::json{{"first", {{"second", 1}}}}), rootError(first_combination, 3)); + if (second_combination == "oneOf") { + EXPECT_THROW_WITH_MESSAGE(validate(schema, nlohmann::json{{"first", {{"second", 8}}}}), rootError(first_combination, 3)); + } + EXPECT_THROW_WITH_MESSAGE(validate(schema, nlohmann::json{{"first", 10}}), rootError(first_combination, 3)); + EXPECT_THROW_WITH_MESSAGE(validate(schema, nlohmann::json{{"first", "short"}}), rootError(first_combination, 3)); +} + +auto verboseTest(const std::string &first_combination, const std::string &second_combination) -> void +{ + const nlohmann::json schema = generateSchema(first_combination, second_combination); + + { + MyErrorHandler error_handler; + validate(schema, nlohmann::json{{"first", {{"second", 1}}}}, &error_handler); + + const MyErrorHandler::ErrorEntryList &error_list = error_handler.getErrors(); + EXPECT_EQ(error_list.size(), 6); + + EXPECT_EQ(error_list[0].ptr, nlohmann::json::json_pointer{"/first"}); + EXPECT_MATCH(error_list[0].message, rootError(first_combination, 3)); + + EXPECT_EQ(error_list[1].ptr, nlohmann::json::json_pointer{"/first/second"}); + EXPECT_MATCH(error_list[1].message, combinationError(first_combination, 0) << rootError(second_combination, 2)); + + EXPECT_EQ(error_list[2].ptr, nlohmann::json::json_pointer{"/first/second"}); + EXPECT_MATCH(error_list[2].message, combinationError(first_combination, 0) << combinationError(second_combination, 0) << "instance is below minimum of 5"); + + EXPECT_EQ(error_list[3].ptr, nlohmann::json::json_pointer{"/first/second"}); + EXPECT_MATCH(error_list[3].message, combinationError(first_combination, 0) << combinationError(second_combination, 1) << "instance is not a multiple of 2.0"); + + EXPECT_EQ(error_list[4].ptr, nlohmann::json::json_pointer{"/first"}); + EXPECT_MATCH(error_list[4].message, combinationError(first_combination, 1) << "unexpected instance type"); + + EXPECT_EQ(error_list[5].ptr, nlohmann::json::json_pointer{"/first"}); + EXPECT_MATCH(error_list[5].message, combinationError(first_combination, 2) << "unexpected instance type"); + } + + { + MyErrorHandler error_handler; + validate(schema, nlohmann::json{{"first", {{"second", "not-an-integer"}}}}, &error_handler); + + const MyErrorHandler::ErrorEntryList &error_list = error_handler.getErrors(); + EXPECT_EQ(error_list.size(), 6); + + EXPECT_EQ(error_list[0].ptr, nlohmann::json::json_pointer{"/first"}); + EXPECT_MATCH(error_list[0].message, rootError(first_combination, 3)); + + EXPECT_EQ(error_list[1].ptr, nlohmann::json::json_pointer{"/first/second"}); + EXPECT_MATCH(error_list[1].message, combinationError(first_combination, 0) << rootError(second_combination, 2)); + + EXPECT_EQ(error_list[2].ptr, nlohmann::json::json_pointer{"/first/second"}); + EXPECT_MATCH(error_list[2].message, combinationError(first_combination, 0) << combinationError(second_combination, 0) << "unexpected instance type"); + + EXPECT_EQ(error_list[3].ptr, nlohmann::json::json_pointer{"/first/second"}); + EXPECT_MATCH(error_list[3].message, combinationError(first_combination, 0) << combinationError(second_combination, 1) << "unexpected instance type"); + + EXPECT_EQ(error_list[4].ptr, nlohmann::json::json_pointer{"/first"}); + EXPECT_MATCH(error_list[4].message, combinationError(first_combination, 1) << "unexpected instance type"); + + EXPECT_EQ(error_list[5].ptr, nlohmann::json::json_pointer{"/first"}); + EXPECT_MATCH(error_list[5].message, combinationError(first_combination, 2) << "unexpected instance type"); + } + + if (second_combination == "oneOf") { + MyErrorHandler error_handler; + validate(schema, nlohmann::json{{"first", {{"second", 8}}}}, &error_handler); + + const MyErrorHandler::ErrorEntryList &error_list = error_handler.getErrors(); + EXPECT_EQ(error_list.size(), 4); + + EXPECT_EQ(error_list[0].ptr, nlohmann::json::json_pointer{"/first"}); + EXPECT_MATCH(error_list[0].message, rootError(first_combination, 3)); + + EXPECT_EQ(error_list[1].ptr, nlohmann::json::json_pointer{"/first/second"}); + EXPECT_MATCH(error_list[1].message, combinationError(first_combination, 0) << "more than one subschema has succeeded, but exactly one of them is required to validate"); + + EXPECT_EQ(error_list[2].ptr, nlohmann::json::json_pointer{"/first"}); + EXPECT_MATCH(error_list[2].message, combinationError(first_combination, 1) << "unexpected instance type"); + + EXPECT_EQ(error_list[3].ptr, nlohmann::json::json_pointer{"/first"}); + EXPECT_MATCH(error_list[3].message, combinationError(first_combination, 2) << "unexpected instance type"); + } + + { + MyErrorHandler error_handler; + validate(schema, nlohmann::json{{"first", 10}}, &error_handler); + + const MyErrorHandler::ErrorEntryList &error_list = error_handler.getErrors(); + EXPECT_EQ(error_list.size(), 4); + + EXPECT_EQ(error_list[0].ptr, nlohmann::json::json_pointer{"/first"}); + EXPECT_MATCH(error_list[0].message, rootError(first_combination, 3)); + + EXPECT_EQ(error_list[1].ptr, nlohmann::json::json_pointer{"/first"}); + EXPECT_MATCH(error_list[1].message, combinationError(first_combination, 0) << "unexpected instance type"); + + EXPECT_EQ(error_list[2].ptr, nlohmann::json::json_pointer{"/first"}); + EXPECT_MATCH(error_list[2].message, combinationError(first_combination, 1) << "instance is below minimum of 20"); + + EXPECT_EQ(error_list[3].ptr, nlohmann::json::json_pointer{"/first"}); + EXPECT_MATCH(error_list[3].message, combinationError(first_combination, 2) << "unexpected instance type"); + } + + { + MyErrorHandler error_handler; + validate(schema, nlohmann::json{{"first", "short"}}, &error_handler); + + const MyErrorHandler::ErrorEntryList &error_list = error_handler.getErrors(); + EXPECT_EQ(error_list.size(), 4); + + EXPECT_EQ(error_list[0].ptr, nlohmann::json::json_pointer{"/first"}); + EXPECT_MATCH(error_list[0].message, rootError(first_combination, 3)); + + EXPECT_EQ(error_list[1].ptr, nlohmann::json::json_pointer{"/first"}); + EXPECT_MATCH(error_list[1].message, combinationError(first_combination, 0) << "unexpected instance type"); + + EXPECT_EQ(error_list[2].ptr, nlohmann::json::json_pointer{"/first"}); + EXPECT_MATCH(error_list[2].message, combinationError(first_combination, 1) << "unexpected instance type"); + + EXPECT_EQ(error_list[3].ptr, nlohmann::json::json_pointer{"/first"}); + EXPECT_MATCH(error_list[3].message, combinationError(first_combination, 2) << "instance is too short as per minLength:10"); + } +} + +} // namespace + +//============================================================================== +// MAIN - calling the test cases +//============================================================================== +auto main() -> int +{ + simpleTest("anyOf", "anyOf"); + simpleTest("anyOf", "oneOf"); + simpleTest("oneOf", "anyOf"); + simpleTest("oneOf", "oneOf"); + + verboseTest("anyOf", "anyOf"); + verboseTest("anyOf", "oneOf"); + verboseTest("oneOf", "anyOf"); + verboseTest("oneOf", "oneOf"); + + return g_error_count; +} diff --git a/lib/All/json-schema-validator/test/issue-117-format-error.cpp b/lib/All/json-schema-validator/test/issue-117-format-error.cpp new file mode 100644 index 0000000..5422e5a --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-117-format-error.cpp @@ -0,0 +1,69 @@ +// issue-00-format-error.cpp + +#include "nlohmann/json-schema.hpp" +#include "nlohmann/json.hpp" +#include + +static int error_count = 0; + +#define CHECK_THROW(x, msg) \ + { \ + bool fail = false; \ + try { \ + x; \ + } catch (std::exception &) { \ + fail = true; \ + } \ + if (fail == false) { \ + ++error_count; \ + std::cout << msg << std::endl; \ + } \ + } + +#define CHECK_NO_THROW(x, msg) \ + { \ + bool fail = false; \ + std::string exception_error; \ + try { \ + x; \ + } catch (std::exception & e) { \ + fail = true; \ + exception_error = e.what(); \ + } \ + if (fail == true) { \ + ++error_count; \ + std::cout << msg << ": " << exception_error << std::endl; \ + } \ + } + +using json = nlohmann::json; +using validator = nlohmann::json_schema::json_validator; + +json schema_with_format = json::parse(R"( +{ + "type": "object", + "properties": { + "str": { + "type": "string", + "format": "placeholder" + } + } +} +)"); + +int main() +{ + // check that if we get validator without format checker we get error at schema loading + validator without_format_checker; + + CHECK_THROW(without_format_checker.set_root_schema(schema_with_format), "validator without format checker must fail at schema loading"); + + // check that with format checker all works fine + validator with_format_checker{nullptr, [](const std::string &, const std::string &) {}}; + + CHECK_NO_THROW(with_format_checker.set_root_schema(schema_with_format), "schema must be succesed by validator with format checker"); + + CHECK_NO_THROW(with_format_checker.validate(json{{"str", "placeholder"}}), "validator must not throw while validation schema with format"); + + return error_count; +} diff --git a/lib/All/json-schema-validator/test/issue-12/CMakeLists.txt b/lib/All/json-schema-validator/test/issue-12/CMakeLists.txt new file mode 100644 index 0000000..5dc7595 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-12/CMakeLists.txt @@ -0,0 +1,3 @@ +add_test_simple_schema(Issue::12 + ${CMAKE_CURRENT_SOURCE_DIR}/schema.json + ${CMAKE_CURRENT_SOURCE_DIR}/instance.json) diff --git a/lib/All/json-schema-validator/test/issue-12/instance.json b/lib/All/json-schema-validator/test/issue-12/instance.json new file mode 100644 index 0000000..13b78c1 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-12/instance.json @@ -0,0 +1,3 @@ +{ + "x": 1503681668603 +} diff --git a/lib/All/json-schema-validator/test/issue-12/schema.json b/lib/All/json-schema-validator/test/issue-12/schema.json new file mode 100644 index 0000000..ab104fa --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-12/schema.json @@ -0,0 +1,10 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "x": { + "type": "integer", + "minimum": 1000000000000, + "maximum": 2000000000000 + } + } +} diff --git a/lib/All/json-schema-validator/test/issue-143/CMakeLists.txt b/lib/All/json-schema-validator/test/issue-143/CMakeLists.txt new file mode 100644 index 0000000..1cc2365 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-143/CMakeLists.txt @@ -0,0 +1,13 @@ +add_test_simple_schema(Issue::143-1 + ${CMAKE_CURRENT_SOURCE_DIR}/schema.json + ${CMAKE_CURRENT_SOURCE_DIR}/instance-fail-1.json) +add_test_simple_schema(Issue::143-a + ${CMAKE_CURRENT_SOURCE_DIR}/schema.json + ${CMAKE_CURRENT_SOURCE_DIR}/instance-fail-a.json) +add_test_simple_schema(Issue::143-ok + ${CMAKE_CURRENT_SOURCE_DIR}/schema.json + ${CMAKE_CURRENT_SOURCE_DIR}/instance.json) + +set_tests_properties(Issue::143-1 Issue::143-a + PROPERTIES + WILL_FAIL 1) diff --git a/lib/All/json-schema-validator/test/issue-143/instance-fail-1.json b/lib/All/json-schema-validator/test/issue-143/instance-fail-1.json new file mode 100644 index 0000000..7eefb69 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-143/instance-fail-1.json @@ -0,0 +1,4 @@ +{ + "ref1": "a", + "refa": "a" +} diff --git a/lib/All/json-schema-validator/test/issue-143/instance-fail-a.json b/lib/All/json-schema-validator/test/issue-143/instance-fail-a.json new file mode 100644 index 0000000..67f7c5e --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-143/instance-fail-a.json @@ -0,0 +1,4 @@ +{ + "ref1": 12, + "refa": 12 +} diff --git a/lib/All/json-schema-validator/test/issue-143/instance.json b/lib/All/json-schema-validator/test/issue-143/instance.json new file mode 100644 index 0000000..d2d55e6 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-143/instance.json @@ -0,0 +1,4 @@ +{ + "ref1": 12, + "refa": "a" +} diff --git a/lib/All/json-schema-validator/test/issue-143/schema.json b/lib/All/json-schema-validator/test/issue-143/schema.json new file mode 100644 index 0000000..4a4503f --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-143/schema.json @@ -0,0 +1,21 @@ +{ + "type": "object", + + "properties": { + "unknown_keyword_storage": { + "1": { + "type": "number" + }, + "a": { + "type": "string" + } + }, + "ref1": { + "$ref": "#/properties/unknown_keyword_storage/1" + }, + "refa": { + "$ref": "#/properties/unknown_keyword_storage/a" + } + }, + "additionalProperties": false +} diff --git a/lib/All/json-schema-validator/test/issue-149-entry-selection.cpp b/lib/All/json-schema-validator/test/issue-149-entry-selection.cpp new file mode 100644 index 0000000..c54c2c4 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-149-entry-selection.cpp @@ -0,0 +1,93 @@ +#include + +#include + +using nlohmann::json; +using nlohmann::json_uri; +using nlohmann::json_schema::json_validator; + +namespace +{ + +static int error_count; +#define EXPECT_EQ(a, b) \ + do { \ + if (a != b) { \ + std::cerr << "Failed: '" << a << "' != '" << b << "'\n"; \ + error_count++; \ + } \ + } while (0) + +// The schema is defined based upon a string literal +static json person_schema = R"( +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "integer", + "definitions": { + "A": { + "type": "object", + "properties": { + "b": { + "$ref": "#/definitions/B" + } + } + }, + "B": { + "type": "integer" + } + } +})"_json; + +class store_err_handler : public nlohmann::json_schema::basic_error_handler +{ + void error(const nlohmann::json::json_pointer &ptr, const json &instance, const std::string &message) override + { + nlohmann::json_schema::basic_error_handler::error(ptr, instance, message); + std::cerr << "ERROR: '" << ptr << "' - '" << instance << "': " << message << "\n"; + failed.push_back(ptr); + } + +public: + std::vector failed; + + void reset() override + { + nlohmann::json_schema::basic_error_handler::reset(); + failed.clear(); + } +}; + +} // namespace + +static json_validator validator(person_schema); + +int main(void) +{ + store_err_handler err; + + validator.validate(1, err); // OK + EXPECT_EQ(err.failed.size(), 0); + err.reset(); + + validator.validate("1", err); // no name + EXPECT_EQ(err.failed.size(), 1); + err.reset(); + + validator.validate(1, err, json_uri("#/definitions/B")); + EXPECT_EQ(err.failed.size(), 0); + err.reset(); + + validator.validate("1", err, json_uri("#/definitions/B")); + EXPECT_EQ(err.failed.size(), 1); + err.reset(); + + validator.validate({{"b", 1}}, err, json_uri("#/definitions/A")); + EXPECT_EQ(err.failed.size(), 0); + err.reset(); + + validator.validate({{"b", "1"}}, err, json_uri("#/definitions/A")); + EXPECT_EQ(err.failed.size(), 1); + err.reset(); + + return error_count; +} diff --git a/lib/All/json-schema-validator/test/issue-189-default-values.cpp b/lib/All/json-schema-validator/test/issue-189-default-values.cpp new file mode 100644 index 0000000..e7232d3 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-189-default-values.cpp @@ -0,0 +1,109 @@ +#include +#include + +using nlohmann::json; +using nlohmann::json_uri; +using nlohmann::json_schema::json_validator; + +static const json rectangle_schema = R"( +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "width": { + "$ref": "#/definitions/length", + "default": 20 + }, + "height": { + "$ref": "#/definitions/length" + } + }, + "definitions": { + "length": { + "type": "integer", + "default": 10 + } + } +})"_json; + +static const json quad_schema = R"( +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "width": { + "$ref": "#/properties/height", + "default": 20 + }, + "height": { + "$ref": "#/definitions/length" + }, + "depth": { + "$ref": "default_schema#/definitions/defaultLength" + }, + "time": { + "$ref": "#/definitions/time" + } + }, + "definitions": { + "length": { + "$ref": "default_schema#/definitions/defaultLength", + "default": 10 + }, + "time": { + "type": "integer", + "default": 15 + } + } +})"_json; + +static const json default_schema = R"( +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "defaultLength": { + "default": 5 + } + } +})"_json; + +static void loader(const json_uri &uri, json &schema) +{ + schema = default_schema; +} + +int main(void) +{ + json_validator validator(loader); + + validator.set_root_schema(quad_schema); + + { + json empty_quad = R"({})"_json; + + const auto default_patch = validator.validate(empty_quad); + const auto actual = empty_quad.patch(default_patch); + + const auto expected = R"({"height":10,"width":20,"depth":5,"time":15})"_json; + if (actual != expected) { + std::cerr << "Patch with defaults contains wrong value: '" << actual << "' instead of expected '" << expected.dump() << "'" << std::endl; + return 1; + } + } + + validator.set_root_schema(rectangle_schema); + + { + json empty_rectangle = R"({})"_json; + + const auto default_patch = validator.validate(empty_rectangle); + const auto actual = empty_rectangle.patch(default_patch); + + // height must be 10 according to the default specified in the length definition while width must be 10 overridden by the width element + const auto expected = R"({"height":10,"width":20})"_json; + if (actual != expected) { + std::cerr << "Patch with defaults contains wrong value: '" << actual << "' instead of expected '" << expected.dump() << "'" << std::endl; + return 1; + } + } + + return 0; +} diff --git a/lib/All/json-schema-validator/test/issue-209/CMakeLists.txt b/lib/All/json-schema-validator/test/issue-209/CMakeLists.txt new file mode 100644 index 0000000..fa4c564 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-209/CMakeLists.txt @@ -0,0 +1,3 @@ +add_test_simple_schema(Issue::209 + ${CMAKE_CURRENT_SOURCE_DIR}/entities.schema.json + ${CMAKE_CURRENT_SOURCE_DIR}/instance.json) diff --git a/lib/All/json-schema-validator/test/issue-209/color.schema.json b/lib/All/json-schema-validator/test/issue-209/color.schema.json new file mode 100644 index 0000000..2d4227b --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-209/color.schema.json @@ -0,0 +1,8 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://example.invalid/color.schema.json", + "title": "color", + "description": "X11/HTML/CSS color name as a JSON string", + "type": "string", + "enum": [ "White", "Black", "Red" ] +} diff --git a/lib/All/json-schema-validator/test/issue-209/entities.schema.json b/lib/All/json-schema-validator/test/issue-209/entities.schema.json new file mode 100644 index 0000000..95828b8 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-209/entities.schema.json @@ -0,0 +1,16 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://example.invalid/entities.schema.json", + "title": "Entities", + "type": "array", + "items": { + "type": "object", + "required": [ "name" ], + "properties": { + "name": { + "type": "string" + }, + "fg": { "$ref": "color.schema.json", "default": "Black" } + } + } +} diff --git a/lib/All/json-schema-validator/test/issue-209/instance.json b/lib/All/json-schema-validator/test/issue-209/instance.json new file mode 100644 index 0000000..8de2c32 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-209/instance.json @@ -0,0 +1,10 @@ +[ + { + "name": "player", + "fg": "White" + }, + { + "name": "enemy", + "fg": "Red" + } +] diff --git a/lib/All/json-schema-validator/test/issue-229-oneof-default-values.cpp b/lib/All/json-schema-validator/test/issue-229-oneof-default-values.cpp new file mode 100644 index 0000000..6bd6e8e --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-229-oneof-default-values.cpp @@ -0,0 +1,69 @@ +#include +#include + +using nlohmann::json; +using nlohmann::json_uri; +using nlohmann::json_schema::json_validator; + +static const json default_schema = R"( +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "oneOf": [ + { + "type": "object", + "properties": { + "name": { + "enum": "foo" + }, + "code": { + "const": 1, + "default": 1 + } + } + }, + { + "type": "object", + "properties": { + "name": { + "enum": "bar" + }, + "code": { + "const": 2, + "default": 2 + } + } + } + ] +})"_json; + +static void loader(const json_uri &uri, json &schema) +{ + schema = default_schema; +} + +int main(void) +{ + json_validator validator(loader); + + validator.set_root_schema(default_schema); + + json data = R"({"name": "bar"})"_json; + json expected = R"( + [ + { + "op": "add", + "path": "/code", + "value": 2 + } + ] + )"_json; + + json patch = validator.validate(data); + if (patch != expected) { + std::cerr << "Patch contains wrong operation: '" << patch.dump() << "' instead of expected '" << expected.dump() << "'" << std::endl; + return 1; + } + + return 0; +} diff --git a/lib/All/json-schema-validator/test/issue-243-root-default-values.cpp b/lib/All/json-schema-validator/test/issue-243-root-default-values.cpp new file mode 100644 index 0000000..34f0582 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-243-root-default-values.cpp @@ -0,0 +1,48 @@ +#include +#include + +using nlohmann::json; +using nlohmann::json_uri; +using nlohmann::json_schema::json_validator; + +static const json root_default = R"( +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "width": { + "type": "integer" + } + }, + "default": { + "width": 42 + } +})"_json; + +int main(void) +{ + json_validator validator{}; + + validator.set_root_schema(root_default); + + { + json nul_json; + if (!nul_json.is_null()) { + return 1; + } + + const auto default_patch = validator.validate(nul_json); + + if (default_patch.is_null()) { + std::cerr << "Patch is null but should contain operation to add defaults to root" << std::endl; + return 1; + } + + const auto actual = nul_json.patch(default_patch); + const auto expected = R"({"width": 42})"_json; + if (actual != expected) { + std::cerr << "Patch of defaults is wrong for root schema: '" << actual.dump() << "' instead of expected '" << expected.dump() << "'" << std::endl; + } + } + + return 0; +} diff --git a/lib/All/json-schema-validator/test/issue-25-default-values.cpp b/lib/All/json-schema-validator/test/issue-25-default-values.cpp new file mode 100644 index 0000000..39a53df --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-25-default-values.cpp @@ -0,0 +1,174 @@ +#include +#include + +using nlohmann::json; +using nlohmann::json_schema::json_validator; + +static const json person_schema = R"( +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "A person", + "properties": { + "name": { + "description": "Name", + "type": "string" + }, + "age": { + "description": "Age of the person", + "type": "number", + "minimum": 2, + "maximum": 200 + }, + "address": { + "type": "object", + "default": {}, + "properties": { + "street": { + "type": "string", + "default": "Abbey Road" + } + } + }, + "work address": { + "type": "object", + "default": null, + "properties": { + "street": { + "type": "string", + "default": "Abbey Road" + } + } + }, + "other address": { + "type": "object", + "properties": { + "street": { + "type": "string", + "default": "Abbey Road" + } + } + } + }, + "required": [ + "name", + "age" + ], + "additionalProperties": false, + "type": "object" +})"_json; + +int main(void) +{ + json_validator validator{}; + validator.set_root_schema(person_schema); + + { + // add address which is optional that should generate a diff containing a default street + json person_emtpy_address = R"({ + "name": "Hans", + "age": 69, + "address": {} + })"_json; + + const auto default_patch = validator.validate(person_emtpy_address); + + if (!default_patch.is_array()) { + std::cerr << "Patch with defaults is expected to be an array" << std::endl; + return 1; + } + + if (default_patch.size() != 1) { + std::cerr << "Patch with defaults is expected to contain one opperation" << std::endl; + return 1; + } + + const auto &single_op = default_patch[0]; + + if (!single_op.contains("op")) { + std::cerr << "Patch with defaults is expected to contain opperation entry" << std::endl; + return 1; + } + + if (single_op["op"].get() != "add") { + std::cerr << "Patch with defaults is expected to contain add opperation" << std::endl; + return 1; + } + + if (!single_op.contains("path")) { + std::cerr << "Patch with defaults is expected to contain a path" << std::endl; + return 1; + } + + const auto &readPath = single_op["path"].get(); + if (readPath != "/address/street") { + std::cerr << "Patch with defaults contains wrong path. It is " << readPath << " and should be " + << "/address/street" << std::endl; + return 1; + } + + if (!single_op.contains("value")) { + std::cerr << "Patch with defaults is expected to contain a value" << std::endl; + return 1; + } + + if (single_op["value"].get() != "Abbey Road") { + std::cerr << "Patch with defaults contains wrong value" << std::endl; + return 1; + } + } + { + // add address which is optional that should generate a diff containing a empty object + // but not work address which is null or other address which has no default + json person_missing_address = R"({ + "name": "Hans", + "age": 69 + })"_json; + + const auto default_patch = validator.validate(person_missing_address); + + if (!default_patch.is_array()) { + std::cerr << "Patch with defaults is expected to be an array" << std::endl; + return 1; + } + + if (default_patch.size() != 1) { + std::cerr << "Patch with defaults is expected to contain one opperation" << std::endl; + return 1; + } + + const auto &single_op = default_patch[0]; + + if (!single_op.contains("op")) { + std::cerr << "Patch with defaults is expected to contain opperation entry" << std::endl; + return 1; + } + + if (single_op["op"].get() != "add") { + std::cerr << "Patch with defaults is expected to contain add opperation" << std::endl; + return 1; + } + + if (!single_op.contains("path")) { + std::cerr << "Patch with defaults is expected to contain a path" << std::endl; + return 1; + } + + const auto &readPath = single_op["path"].get(); + if (readPath != "/address") { + std::cerr << "Patch with defaults contains wrong path. It is " << readPath << " and should be " + << "/address" << std::endl; + return 1; + } + + if (!single_op.contains("value")) { + std::cerr << "Patch with defaults is expected to contain a value" << std::endl; + return 1; + } + + if (!single_op["value"].is_object() || !single_op["value"].empty()) { + std::cerr << "Patch with defaults contains wrong value" << std::endl; + return 1; + } + } + return 0; +} diff --git a/lib/All/json-schema-validator/test/issue-255-error-message-limit-precision.cpp b/lib/All/json-schema-validator/test/issue-255-error-message-limit-precision.cpp new file mode 100644 index 0000000..5e8a6cf --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-255-error-message-limit-precision.cpp @@ -0,0 +1,41 @@ +#include +#include + +using nlohmann::json; +using nlohmann::json_schema::json_validator; + +static const json schema = R"( +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "arc.schema.json", + "properties": { + "angle": { + "type": "number", + "description": "Radians, from -π to π.", + "minimum": -3.14159265358979323846, + "maximum": 3.14159265358979323846 + } + } +})"_json; + +class custom_error_handler : public nlohmann::json_schema::basic_error_handler +{ + void error(const nlohmann::json::json_pointer &ptr, const json &instance, const std::string &message) override + { + if (message != "instance exceeds maximum of 3.141592653589793") + throw std::invalid_argument("Precision print does not work."); + } +}; + +int main(void) +{ + json_validator validator; + + auto instance = R"({ "angle": 3.1415927410125732 })"_json; + + validator.set_root_schema(schema); + custom_error_handler err; + validator.validate(instance, err); + + return 0; +} diff --git a/lib/All/json-schema-validator/test/issue-27/CMakeLists.txt b/lib/All/json-schema-validator/test/issue-27/CMakeLists.txt new file mode 100644 index 0000000..79e3001 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-27/CMakeLists.txt @@ -0,0 +1,6 @@ +add_test_simple_schema(Issue::27 + ${CMAKE_CURRENT_SOURCE_DIR}/schema.json + ${CMAKE_CURRENT_SOURCE_DIR}/instance.json) +set_tests_properties(Issue::27 + PROPERTIES + WILL_FAIL 1) diff --git a/lib/All/json-schema-validator/test/issue-27/README b/lib/All/json-schema-validator/test/issue-27/README new file mode 100644 index 0000000..ac34a62 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-27/README @@ -0,0 +1 @@ +Numbers higher that UINT32_MAX diff --git a/lib/All/json-schema-validator/test/issue-27/instance.json b/lib/All/json-schema-validator/test/issue-27/instance.json new file mode 100644 index 0000000..b89e11e --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-27/instance.json @@ -0,0 +1 @@ +{"gps_time": 4294967296} diff --git a/lib/All/json-schema-validator/test/issue-27/schema.json b/lib/All/json-schema-validator/test/issue-27/schema.json new file mode 100644 index 0000000..670fb6c --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-27/schema.json @@ -0,0 +1,13 @@ +{ + "properties": { + "gps_time": { + "type": "number", + "minimum": 0, + "maximum": 4294967295 + } + }, + "required": [ + "gps_time" + ], + "type": "object" +} diff --git a/lib/All/json-schema-validator/test/issue-293.cpp b/lib/All/json-schema-validator/test/issue-293.cpp new file mode 100644 index 0000000..dbfdac9 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-293.cpp @@ -0,0 +1,32 @@ +#include "nlohmann/json-schema.hpp" + +using nlohmann::json_schema::json_validator; + +template +int should_throw(const nlohmann::json &schema, T value) +{ + try { + json_validator(schema).validate(value); + } catch (const std::exception &ex) { + return 0; + } + return 1; +} + +int main(void) +{ + + json_validator({{"type", "number"}, {"multipleOf", 0.001}}).validate(0.3 - 0.2); + json_validator({{"type", "number"}, {"multipleOf", 3.3}}).validate(8.0 - 1.4); + json_validator({{"type", "number"}, {"multipleOf", 1000.01}}).validate((1000.03 - 0.02) * 15.0); + json_validator({{"type", "number"}, {"multipleOf", 0.001}}).validate(0.030999999999999993); + json_validator({{"type", "number"}, {"multipleOf", 0.100000}}).validate(1.9); + json_validator({{"type", "number"}, {"multipleOf", 100000.1}}).validate(9000009); + + int exc_count = 0; + exc_count += should_throw({{"type", "number"}, {"multipleOf", 0.001}}, 0.3 - 0.2005); + exc_count += should_throw({{"type", "number"}, {"multipleOf", 1000.02}}, (1000.03 - 0.02) * 15.0); + exc_count += should_throw({{"type", "number"}, {"multipleOf", 100000.11}}, 9000009); + + return exc_count; +} diff --git a/lib/All/json-schema-validator/test/issue-311/CMakeLists.txt b/lib/All/json-schema-validator/test/issue-311/CMakeLists.txt new file mode 100644 index 0000000..19b5b8c --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-311/CMakeLists.txt @@ -0,0 +1,3 @@ +add_test_simple_schema(Issue::311 + ${CMAKE_CURRENT_SOURCE_DIR}/schema.json + ${CMAKE_CURRENT_SOURCE_DIR}/instance.json) diff --git a/lib/All/json-schema-validator/test/issue-311/instance.json b/lib/All/json-schema-validator/test/issue-311/instance.json new file mode 100644 index 0000000..508124e --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-311/instance.json @@ -0,0 +1,4 @@ +{ + "element": [1], + "element2": "test" +} diff --git a/lib/All/json-schema-validator/test/issue-311/schema.json b/lib/All/json-schema-validator/test/issue-311/schema.json new file mode 100644 index 0000000..9bb41a4 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-311/schema.json @@ -0,0 +1,26 @@ +{ + "type": "object", + "properties": { + "element": { + "$ref": "#/$defs/element" + }, + "element2": { + "$ref": "#/$defs/element/items/0/$defs/element2" + } + }, + "$defs": { + "element": { + "type": "array", + "items": [ + { + "$defs": { + "element2": { + "type": "string" + } + }, + "type": "number" + } + ] + } + } +} diff --git a/lib/All/json-schema-validator/test/issue-48/CMakeLists.txt b/lib/All/json-schema-validator/test/issue-48/CMakeLists.txt new file mode 100644 index 0000000..832d374 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-48/CMakeLists.txt @@ -0,0 +1,3 @@ +add_test_simple_schema(Issue::48 + ${CMAKE_CURRENT_SOURCE_DIR}/schema.json + ${CMAKE_CURRENT_SOURCE_DIR}/instance.json) diff --git a/lib/All/json-schema-validator/test/issue-48/instance.json b/lib/All/json-schema-validator/test/issue-48/instance.json new file mode 100644 index 0000000..5625e59 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-48/instance.json @@ -0,0 +1 @@ +1.2 diff --git a/lib/All/json-schema-validator/test/issue-48/schema.json b/lib/All/json-schema-validator/test/issue-48/schema.json new file mode 100644 index 0000000..71782fc --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-48/schema.json @@ -0,0 +1,3 @@ +{ + "multipleOf": 0.1 +} diff --git a/lib/All/json-schema-validator/test/issue-54/CMakeLists.txt b/lib/All/json-schema-validator/test/issue-54/CMakeLists.txt new file mode 100644 index 0000000..016e594 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-54/CMakeLists.txt @@ -0,0 +1,3 @@ +add_test_simple_schema(Issue::54 + ${CMAKE_CURRENT_SOURCE_DIR}/schema.json + ${CMAKE_CURRENT_SOURCE_DIR}/instance.json) diff --git a/lib/All/json-schema-validator/test/issue-54/instance.json b/lib/All/json-schema-validator/test/issue-54/instance.json new file mode 100644 index 0000000..573541a --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-54/instance.json @@ -0,0 +1 @@ +0 diff --git a/lib/All/json-schema-validator/test/issue-54/schema.json b/lib/All/json-schema-validator/test/issue-54/schema.json new file mode 100644 index 0000000..c097e9d --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-54/schema.json @@ -0,0 +1,4 @@ +{ + "type": "integer", + "minimum": -2 +} diff --git a/lib/All/json-schema-validator/test/issue-70-root-schema-constructor.cpp b/lib/All/json-schema-validator/test/issue-70-root-schema-constructor.cpp new file mode 100644 index 0000000..f19db3c --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-70-root-schema-constructor.cpp @@ -0,0 +1,123 @@ +#include + +#include + +static int error_count; + +#define EXPECT_EQ(a, b) \ + do { \ + if (a != b) { \ + std::cerr << "Failed: '" << a << "' != '" << b << "'\n"; \ + error_count++; \ + } \ + } while (0) + +using nlohmann::json; +using nlohmann::json_schema::json_validator; + +namespace +{ + +// The schema is defined based upon a string literal +static json person_schema = R"( +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "A person", + "properties": { + "name": { + "description": "Name", + "type": "string" + }, + "age": { + "description": "Age of the person", + "type": "number", + "minimum": 2, + "maximum": 200 + }, + "phones": { + "type": "array", + "items": { + "type": "number" + } + } + }, + "required": [ + "name", + "age" + ], + "additionalProperties": false, + "type": "object" +})"_json; + +class store_ptr_err_handler : public nlohmann::json_schema::basic_error_handler +{ + void error(const nlohmann::json::json_pointer &ptr, const json &instance, const std::string &message) override + { + nlohmann::json_schema::basic_error_handler::error(ptr, instance, message); + std::cerr << "ERROR: '" << ptr << "' - '" << instance << "': " << message << "\n"; + failed_pointers.push_back(ptr); + } + +public: + std::vector failed_pointers; + + void reset() override + { + nlohmann::json_schema::basic_error_handler::reset(); + failed_pointers.clear(); + } +}; + +} // namespace + +static json_validator validator(person_schema); + +int main(void) +{ + store_ptr_err_handler err; + + validator.validate({{"age", 42}, {"name", "John"}}, err); // OK + EXPECT_EQ(err.failed_pointers.size(), 0); + err.reset(); + + validator.validate({{"age", 42}}, err); // no name + + EXPECT_EQ(err.failed_pointers.size(), 1); + EXPECT_EQ(err.failed_pointers[0].to_string(), ""); + err.reset(); + + validator.validate({{"street", "Boulevard"}}, err); // no name and no age + EXPECT_EQ(err.failed_pointers.size(), 3); + EXPECT_EQ(err.failed_pointers[0].to_string(), ""); + EXPECT_EQ(err.failed_pointers[1].to_string(), ""); + EXPECT_EQ(err.failed_pointers[2].to_string(), ""); + err.reset(); + + validator.validate({{"age", 42}, {"name", 12}}, err); // name must be a string + EXPECT_EQ(err.failed_pointers.size(), 1); + EXPECT_EQ(err.failed_pointers[0].to_string(), "/name"); + err.reset(); + + validator.validate({ + {"age", 42}, + {"name", "John"}, + {"phones", {1234, "223"}}, + }, + err); // name must be a string + EXPECT_EQ(err.failed_pointers.size(), 1); + EXPECT_EQ(err.failed_pointers[0].to_string(), "/phones/1"); + err.reset(); + + validator.validate({ + {"age", 42}, + {"name", "John"}, + {"phones", {0}}, + {"post-code", 12345}, + }, + err); // name must be a string + EXPECT_EQ(err.failed_pointers.size(), 1); + EXPECT_EQ(err.failed_pointers[0].to_string(), ""); + err.reset(); + + return error_count; +} diff --git a/lib/All/json-schema-validator/test/issue-70.cpp b/lib/All/json-schema-validator/test/issue-70.cpp new file mode 100644 index 0000000..bfac0a5 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-70.cpp @@ -0,0 +1,44 @@ +#include + +using nlohmann::json; +using nlohmann::json_schema::json_validator; + +static const json person_schema = R"( +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "A person", + "properties": { + "name": { + "description": "Name", + "type": "string" + }, + "age": { + "description": "Age of the person", + "type": "number", + "minimum": 2, + "maximum": 200 + }, + "phones": { + "type": "array", + "items": { + "type": "number" + } + } + }, + "required": [ + "name", + "age" + ], + "additionalProperties": false, + "type": "object" +})"_json; + +int main(void) +{ + json_validator validator; + + validator.set_root_schema(person_schema); + validator.set_root_schema(person_schema); + + return 0; +} diff --git a/lib/All/json-schema-validator/test/issue-75/CMakeLists.txt b/lib/All/json-schema-validator/test/issue-75/CMakeLists.txt new file mode 100644 index 0000000..02639dd --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-75/CMakeLists.txt @@ -0,0 +1,3 @@ +add_test_simple_schema(Issue::75 + ${CMAKE_CURRENT_SOURCE_DIR}/schema.json + ${CMAKE_CURRENT_SOURCE_DIR}/instance.json) diff --git a/lib/All/json-schema-validator/test/issue-75/TypeId.json b/lib/All/json-schema-validator/test/issue-75/TypeId.json new file mode 100644 index 0000000..5e50a0d --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-75/TypeId.json @@ -0,0 +1,10 @@ +{ + "data" : { + "TypeId" : { + "type" : "string", + "description" : "POD type of data matching bmf::data::TypeId enum", + "enum" : [ "CHAR", "UCHAR", "SHORT", "USHORT", "INT", "UINT", + "LONG", "ULONG", "FLOAT", "DOUBLE" ] + } + } +} diff --git a/lib/All/json-schema-validator/test/issue-75/instance.json b/lib/All/json-schema-validator/test/issue-75/instance.json new file mode 100644 index 0000000..585c79a --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-75/instance.json @@ -0,0 +1 @@ +["INT", "LONG"] diff --git a/lib/All/json-schema-validator/test/issue-75/schema.json b/lib/All/json-schema-validator/test/issue-75/schema.json new file mode 100644 index 0000000..d98b507 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-75/schema.json @@ -0,0 +1,6 @@ +{ + "type" : "array", + "items": { + "$ref": "TypeId.json#/data/TypeId" + } +} diff --git a/lib/All/json-schema-validator/test/issue-9/CMakeLists.txt b/lib/All/json-schema-validator/test/issue-9/CMakeLists.txt new file mode 100644 index 0000000..41b56a2 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-9/CMakeLists.txt @@ -0,0 +1,3 @@ +add_test_simple_schema(Issue::9 + ${CMAKE_CURRENT_SOURCE_DIR}/base.json + ${CMAKE_CURRENT_SOURCE_DIR}/instance.json) diff --git a/lib/All/json-schema-validator/test/issue-9/bar.json b/lib/All/json-schema-validator/test/issue-9/bar.json new file mode 100644 index 0000000..6f09818 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-9/bar.json @@ -0,0 +1,13 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Describes bar", + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + } + } +} diff --git a/lib/All/json-schema-validator/test/issue-9/base.json b/lib/All/json-schema-validator/test/issue-9/base.json new file mode 100644 index 0000000..8faa877 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-9/base.json @@ -0,0 +1,9 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Describes foo", + "type": "object", + "allOf": [ + { "$ref": "bar.json" }, + { "$ref": "foo/foo.json" } + ] +} diff --git a/lib/All/json-schema-validator/test/issue-9/foo/baz/baz.json b/lib/All/json-schema-validator/test/issue-9/foo/baz/baz.json new file mode 100644 index 0000000..1ed89d2 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-9/foo/baz/baz.json @@ -0,0 +1,5 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Describes baz", + "$ref": "qux/qux.json" +} diff --git a/lib/All/json-schema-validator/test/issue-9/foo/baz/qux/qux.json b/lib/All/json-schema-validator/test/issue-9/foo/baz/qux/qux.json new file mode 100644 index 0000000..ebdc4c7 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-9/foo/baz/qux/qux.json @@ -0,0 +1,13 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Describes qux", + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + } + } +} diff --git a/lib/All/json-schema-validator/test/issue-9/foo/foo.json b/lib/All/json-schema-validator/test/issue-9/foo/foo.json new file mode 100644 index 0000000..298f9c8 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-9/foo/foo.json @@ -0,0 +1,5 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Describes foo", + "$ref": "baz/baz.json" +} diff --git a/lib/All/json-schema-validator/test/issue-9/instance.json b/lib/All/json-schema-validator/test/issue-9/instance.json new file mode 100644 index 0000000..1193e8e --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-9/instance.json @@ -0,0 +1,3 @@ +{ + "name": "name" +} diff --git a/lib/All/json-schema-validator/test/issue-93/CMakeLists.txt b/lib/All/json-schema-validator/test/issue-93/CMakeLists.txt new file mode 100644 index 0000000..eaccc41 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-93/CMakeLists.txt @@ -0,0 +1,7 @@ + +add_executable(issue-93 issue-93.cpp) +target_link_libraries(issue-93 nlohmann_json_schema_validator) + +add_test(NAME issue-93 + COMMAND issue-93 + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/lib/All/json-schema-validator/test/issue-93/blueprints.schema.json b/lib/All/json-schema-validator/test/issue-93/blueprints.schema.json new file mode 100644 index 0000000..c35c0f4 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-93/blueprints.schema.json @@ -0,0 +1,11 @@ +{ + "type":"array", + "items": { + "type":"object", + "properties": { + "renderable": { + "$ref":"/components.schema.json#/Renderable" + } + } + } +} diff --git a/lib/All/json-schema-validator/test/issue-93/components.schema.json b/lib/All/json-schema-validator/test/issue-93/components.schema.json new file mode 100644 index 0000000..3aaeea9 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-93/components.schema.json @@ -0,0 +1,13 @@ +{ + "Renderable": { + "type":"object", + "properties": { + "fg":{ + "$ref":"/types/color.schema.json" + }, + "bg":{ + "$ref":"/types/color.schema.json" + } + } + } +} diff --git a/lib/All/json-schema-validator/test/issue-93/issue-93.cpp b/lib/All/json-schema-validator/test/issue-93/issue-93.cpp new file mode 100644 index 0000000..87ba599 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-93/issue-93.cpp @@ -0,0 +1,55 @@ +#include + +#include +#include + +using nlohmann::json; +using nlohmann::json_uri; +using nlohmann::json_schema::json_validator; + +static const auto expected_patch = R"( +[{"op":"add","path":"/0/renderable/bg","value":"Black"}] +)"_json; + +static const auto instance = R"( +[ + { + "name":"player", + "renderable": { + "fg":"White" + } + } +] +)"_json; + +static void loader(const json_uri &uri, json &schema) +{ + std::string filename = "./" + uri.path(); + std::ifstream lf(filename); + if (!lf.good()) + throw std::invalid_argument("could not open " + uri.url() + " tried with " + filename); + try { + lf >> schema; + } catch (const std::exception &e) { + throw e; + } +} + +int main(void) +{ + json_validator validator(loader); + + std::fstream f("blueprints.schema.json"); + + json schema; + f >> schema; + + validator.set_root_schema(schema); + + auto missing_default_patch = validator.validate(instance); + + std::cerr << missing_default_patch << "\n"; + std::cerr << expected_patch << "\n"; + + return missing_default_patch != expected_patch; +} diff --git a/lib/All/json-schema-validator/test/issue-93/types/color.schema.json b/lib/All/json-schema-validator/test/issue-93/types/color.schema.json new file mode 100644 index 0000000..11d3092 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-93/types/color.schema.json @@ -0,0 +1,4 @@ +{ + "type":"string", + "default":"Black" +} diff --git a/lib/All/json-schema-validator/test/issue-96/CMakeLists.txt b/lib/All/json-schema-validator/test/issue-96/CMakeLists.txt new file mode 100644 index 0000000..03582e6 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-96/CMakeLists.txt @@ -0,0 +1,6 @@ +add_test_simple_schema(Issue::96 + ${CMAKE_CURRENT_SOURCE_DIR}/schema.json + ${CMAKE_CURRENT_SOURCE_DIR}/instance.json) +set_tests_properties(Issue::96 + PROPERTIES + WILL_FAIL 1) diff --git a/lib/All/json-schema-validator/test/issue-96/instance.json b/lib/All/json-schema-validator/test/issue-96/instance.json new file mode 100644 index 0000000..0756430 --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-96/instance.json @@ -0,0 +1 @@ +{"top": {"value": 101}} diff --git a/lib/All/json-schema-validator/test/issue-96/schema.json b/lib/All/json-schema-validator/test/issue-96/schema.json new file mode 100644 index 0000000..c608adf --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-96/schema.json @@ -0,0 +1,23 @@ +{ + "$id": "http://xxx.local/schemas/mySchema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "topDef": { + "$id": "#topDef_ref", + "type": "object", + "properties": { + "value": { + "type": "integer", + "maximum": 100 + } + } + } + }, + + "type": "object", + "properties": { + "top": { + "$ref": "#/definitions/topDef" + } + } +} diff --git a/lib/All/json-schema-validator/test/issue-98.cpp b/lib/All/json-schema-validator/test/issue-98.cpp new file mode 100644 index 0000000..63a824c --- /dev/null +++ b/lib/All/json-schema-validator/test/issue-98.cpp @@ -0,0 +1,16 @@ +#include + +int main(void) +{ + nlohmann::json nlBase{{"$ref", "#/unknown/keywords"}}; + nlohmann::json_schema::json_validator validator; + + try { + validator.set_root_schema(nlBase); // this line will log the caught exception + } catch (const std::exception &e) { + + if (std::string("after all files have been parsed, '' has still the following undefined references: [/unknown/keywords]") == e.what()) + return EXIT_SUCCESS; + } + return EXIT_FAILURE; +} diff --git a/lib/All/json-schema-validator/test/json-patch.cpp b/lib/All/json-schema-validator/test/json-patch.cpp new file mode 100644 index 0000000..cf5a5a4 --- /dev/null +++ b/lib/All/json-schema-validator/test/json-patch.cpp @@ -0,0 +1,48 @@ +#include "../src/json-patch.hpp" + +#include + +using nlohmann::json_patch; + +#define OK(code) \ + do { \ + try { \ + code; \ + } catch (const std::exception &e) { \ + std::cerr << "UNEXPECTED FAILED: " << e.what() << "\n"; \ + return 1; \ + } \ + } while (0) + +#define KO(code) \ + do { \ + try { \ + code; \ + std::cerr << "UNEXPECTED SUCCESS.\n"; \ + return 1; \ + } catch (const std::exception &e) { \ + std::cerr << "EXPECTED FAIL: " << e.what() << "\n"; \ + } \ + } while (0) + +int main(void) +{ + OK(json_patch p1(R"([{"op":"add","path":"/0/renderable/bg","value":"Black"}])"_json)); + OK(json_patch p1(R"([{"op":"replace","path":"/0/renderable/bg","value":"Black"}])"_json)); + OK(json_patch p1(R"([{"op":"remove","path":"/0/renderable/bg"}])"_json)); + + // value not needed + KO(json_patch p1(R"([{"op":"remove","path":"/0/renderable/bg", "value":"Black"}])"_json)); + // value missing + KO(json_patch p1(R"([{"op":"add","path":"/0/renderable/bg"}])"_json)); + // value missing + KO(json_patch p1(R"([{"op":"replace","path":"/0/renderable/bg"}])"_json)); + + // wrong op + KO(json_patch p1(R"([{"op":"ad","path":"/0/renderable/bg","value":"Black"}])"_json)); + + // invalid json-pointer + KO(json_patch p1(R"([{"op":"add","path":"0/renderable/bg","value":"Black"}])"_json)); + + return 0; +} diff --git a/lib/All/json-schema-validator/test/json-schema-validate.cpp b/lib/All/json-schema-validator/test/json-schema-validate.cpp new file mode 100644 index 0000000..de683ff --- /dev/null +++ b/lib/All/json-schema-validator/test/json-schema-validate.cpp @@ -0,0 +1,100 @@ +/* + * JSON schema validator for JSON for modern C++ + * + * Copyright (c) 2016-2019 Patrick Boettcher . + * + * SPDX-License-Identifier: MIT + * + */ +#include + +#include +#include + +using nlohmann::json; +using nlohmann::json_uri; +using nlohmann::json_schema::json_validator; + +static void usage(const char *name) +{ + std::cerr << "Usage: " << name << " < \n"; + exit(EXIT_FAILURE); +} + +static void loader(const json_uri &uri, json &schema) +{ + std::string filename = "./" + uri.path(); + std::ifstream lf(filename); + if (!lf.good()) + throw std::invalid_argument("could not open " + uri.url() + " tried with " + filename); + try { + lf >> schema; + } catch (const std::exception &e) { + throw e; + } +} + +class custom_error_handler : public nlohmann::json_schema::basic_error_handler +{ + void error(const nlohmann::json::json_pointer &ptr, const json &instance, const std::string &message) override + { + nlohmann::json_schema::basic_error_handler::error(ptr, instance, message); + std::cerr << "ERROR: '" << ptr << "' - '" << instance << "': " << message << "\n"; + } +}; + +int main(int argc, char *argv[]) +{ + if (argc != 2) + usage(argv[0]); + + std::ifstream f(argv[1]); + if (!f.good()) { + std::cerr << "could not open " << argv[1] << " for reading\n"; + usage(argv[0]); + } + + // 1) Read the schema for the document you want to validate + json schema; + try { + f >> schema; + } catch (const std::exception &e) { + std::cerr << e.what() << " at " << f.tellg() << " - while parsing the schema\n"; + return EXIT_FAILURE; + } + + // 2) create the validator and + json_validator validator(loader, + nlohmann::json_schema::default_string_format_check); + + try { + // insert this schema as the root to the validator + // this resolves remote-schemas, sub-schemas and references via the given loader-function + validator.set_root_schema(schema); + } catch (const std::exception &e) { + std::cerr << "setting root schema failed\n"; + std::cerr << e.what() << "\n"; + } + + // 3) do the actual validation of the document + json document; + + try { + std::cin >> document; + } catch (const std::exception &e) { + std::cerr << "json parsing failed: " << e.what() << " at offset: " << std::cin.tellg() << "\n"; + return EXIT_FAILURE; + } + + custom_error_handler err; + validator.validate(document, err); + + if (err) { + std::cerr << "schema validation failed\n"; + return EXIT_FAILURE; + } + + std::cerr << "document is valid\n"; + + return EXIT_SUCCESS; +} diff --git a/lib/All/json-schema-validator/test/string-format-check-test.cpp b/lib/All/json-schema-validator/test/string-format-check-test.cpp new file mode 100644 index 0000000..4a207b1 --- /dev/null +++ b/lib/All/json-schema-validator/test/string-format-check-test.cpp @@ -0,0 +1,102 @@ +#include + +#include + +/** @return number of failed tests */ +size_t +testStringFormat(const std::string &format, + const std::vector> &stringValidTests) +{ + size_t numberOfErrors = 0; + + for (auto stringValid = stringValidTests.begin(); stringValid != stringValidTests.end(); ++stringValid) { + std::cout << "[INFO] Testing " << format << ": " << stringValid->first << "\n"; + + try { + nlohmann::json_schema::default_string_format_check(format, stringValid->first); + + if (!stringValid->second) { + ++numberOfErrors; + std::cerr << "[ERROR] String with " << format << " format '" << stringValid->first + << "' validated even though it should NOT!\n"; + } + } catch (std::exception &exception) { + std::cout << "[INFO] Validation failed with: " << exception.what() << "\n"; + if (stringValid->second) { + ++numberOfErrors; + std::cerr << "[ERROR] String with " << format << " format '" << stringValid->first + << "' did NOT validate even though it should!\n"; + } + } + } + + return numberOfErrors; +} + +int main() +{ + size_t numberOfErrors = 0; + + const std::vector> dateTimeChecks{ + {"1985-04-12T23:20:50.52Z", true}, + {"1996-12-19T16:39:57-08:00", true}, + {"1990-12-31T23:59:60Z", true}, + {"1990-12-31T15:59:60-08:00", true}, + {"1937-01-01T12:00:27.87+00:20", true}, + {"1985-4-12T23:20:50.52Z", false}, + {"1985-04-12T23:20:50.52", false}, + {"1985-04-12T24:00:00", false}, + {"", false}, + {"2019-04-30T11:11:11+01:00", true}, + {"2019-04-31T11:11:11+01:00", false}, + {"2019-02-28T11:11:11+01:00", true}, + {"2019-02-29T11:11:11+01:00", false}, + {"2020-02-29T11:11:11+01:00", true}, + {"2020-02-30T11:11:11+01:00", false}, + {"2020-02-29T23:59:59+01:00", true}, + {"2020-02-29T23:59:60+01:00", false}, + {"2020-02-29T23:59:60+00:00", true}, + {"2020-02-29T23:60:59+01:00", false}, + {"2019-09-30T11:11:11+01:00", true}, + {"2019-09-31T11:11:11+01:00", false}, + {"2019-09-30T11:11:11+23:59", true}, + {"2019-09-30T11:11:11+24:00", false}}; + + numberOfErrors += testStringFormat("date-time", dateTimeChecks); + + const std::vector> ipv4Checks{ + {"", false}, + {"x99.99.99.99", false}, + {"99.99.99.99x", false}, + {"192.168.0.1", true}, + {"127.0.0", false}, + {"127.0.0.1", true}, + {"127.0.0.0.1", false}, + {"255.255.255.255", true}, + {"255.255.255.256", false}, + {"255.255.256.255", false}, + {"255.256.255.255", false}, + {"256.255.255.255", false}, + {"256.256.256.256", false}, + {"0x7f000001", false}}; + + numberOfErrors += testStringFormat("ipv4", ipv4Checks); + + const std::vector> uriChecks{ + {"http://www.google.com/search?q=regular%20expression", true}, + {"http://www.google.com/", true}, + {"http://www.google.com/search?q=regular%20expression", true}, + {"www.google.com", false}, + {"http://www.google.comj", true}, + {"ldap://[2001:db8::7]/c=GB?objectClass?one", true}, + {"mailto:John.Doe@example.com", true}, + {"news:comp.infosystems.www.servers.unix", true}, + {"https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top", true}, + {"tel:+1-816-555-1212", true}, + {"telnet://192.0.2.16:80/", true}, + {"urn:oasis:names:specification:docbook:dtd:xml:4.1.2", true}}; + + numberOfErrors += testStringFormat("uri", uriChecks); + + return numberOfErrors; +} diff --git a/lib/All/json-schema-validator/test/test-pipe-in.sh b/lib/All/json-schema-validator/test/test-pipe-in.sh new file mode 100755 index 0000000..be7315f --- /dev/null +++ b/lib/All/json-schema-validator/test/test-pipe-in.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# all argument are considered as a program to call (with its arguments), +# the last argument is read from stdin via '<' + +set -e + +arr=( "$@" ) + +input=${arr[${#arr[@]}-1]} +unset 'arr[${#arr[@]}-1]' + +${arr[@]} < $input diff --git a/lib/All/json-schema-validator/test/uri.cpp b/lib/All/json-schema-validator/test/uri.cpp new file mode 100644 index 0000000..38c81ee --- /dev/null +++ b/lib/All/json-schema-validator/test/uri.cpp @@ -0,0 +1,106 @@ +/* + * JSON schema validator for JSON for modern C++ + * + * Copyright (c) 2016-2019 Patrick Boettcher . + * + * SPDX-License-Identifier: MIT + * + */ +#include +#include + +#include + +using nlohmann::json; +using nlohmann::json_uri; + +static int errors; + +static void EXPECT_EQ(const std::string &a, const std::string &b) +{ + if (a != b) { + std::cerr << "Failed: '" << a << "' != '" << b << "'\n"; + errors++; + } +} + +static void EXPECT_EQ(const nlohmann::json_uri &a, const std::string &b) +{ + EXPECT_EQ(a.to_string(), b); +} + +static void paths(json_uri start, + const std::string &full, + const std::string &full_path, + const std::string &no_path) +{ + EXPECT_EQ(start, full + " # "); + + auto a = start.derive("other.json"); + EXPECT_EQ(a, full_path + "/other.json # "); + + auto b = a.derive("base.json"); + EXPECT_EQ(b, full_path + "/base.json # "); + + auto c = b.derive("subdir/base.json"); + EXPECT_EQ(c, full_path + "/subdir/base.json # "); + + auto d = c.derive("subdir2/base.json"); + EXPECT_EQ(d, full_path + "/subdir/subdir2/base.json # "); + + auto e = c.derive("/subdir2/base.json"); + EXPECT_EQ(e, no_path + "/subdir2/base.json # "); + + auto f = c.derive("new.json"); + EXPECT_EQ(f, full_path + "/subdir/new.json # "); + + auto g = c.derive("/new.json"); + EXPECT_EQ(g, no_path + "/new.json # "); +} + +static void pointer_plain_name(json_uri start, + const std::string &full, + const std::string &full_path, + const std::string &no_path) +{ + auto a = start.derive("#/json/path"); + EXPECT_EQ(a, full + " # /json/path"); + + a = start.derive("#/json/special_%22"); + EXPECT_EQ(a, full + " # /json/special_\""); + + a = a.derive("#foo"); + EXPECT_EQ(a, full + " # foo"); + + a = a.derive("#foo/looks_like_json/poiner/but/isnt"); + EXPECT_EQ(a, full + " # foo/looks_like_json/poiner/but/isnt"); + EXPECT_EQ(a.identifier(), "foo/looks_like_json/poiner/but/isnt"); + EXPECT_EQ(a.pointer().to_string(), ""); + + a = a.derive("#/looks_like_json/poiner/and/it/is"); + EXPECT_EQ(a, full + " # /looks_like_json/poiner/and/it/is"); + EXPECT_EQ(a.pointer().to_string(), "/looks_like_json/poiner/and/it/is"); + EXPECT_EQ(a.identifier(), ""); +} + +int main(void) +{ + json_uri empty(""); + paths(empty, + "", + "", + ""); + + json_uri http("http://json-schema.org/draft-07/schema#"); + paths(http, + "http://json-schema.org/draft-07/schema", + "http://json-schema.org/draft-07", + "http://json-schema.org"); + + pointer_plain_name(http, + "http://json-schema.org/draft-07/schema", + "http://json-schema.org/draft-07", + "http://json-schema.org"); + + return errors; +} diff --git a/lib/CMake/Linux/JsonValidatorConfig.cmake b/lib/CMake/Linux/JsonValidatorConfig.cmake new file mode 100644 index 0000000..a2f5cb4 --- /dev/null +++ b/lib/CMake/Linux/JsonValidatorConfig.cmake @@ -0,0 +1,3 @@ +set(JSONVALIDATOR_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/lib/All/json-schema-validator/lib/include/") + +set(JSONVALIDATOR_LIBRARIES "${CMAKE_CURRENT_SOURCE_DIR}/lib/All/json-schema-validator/lib/libnlohmann_json_schema_validator.a") diff --git a/src/Engine/Core/Kernel/CKernel.cpp b/src/Engine/Core/Kernel/CKernel.cpp index 49bd9a5..2a4b23b 100644 --- a/src/Engine/Core/Kernel/CKernel.cpp +++ b/src/Engine/Core/Kernel/CKernel.cpp @@ -46,27 +46,11 @@ namespace CosmicCore { { } - /*void CKernel::setContext(SDL_GLContext context) - { - m_GLcontext = context; - }*/ - CScene* CKernel::getActiveScene() { return m_activeScene; } - /*void CKernel::initGL() - { - m_window.setCursorGrabbed(false); - m_window.setAntiAliasing(m_config.getMsaa()); - m_window.initialization(); - m_GLcontext = m_window.getOpenGLContext(); - SDL_GL_MakeCurrent(m_window.getWindow(), m_GLcontext); - m_window.setVisible(true); - SDL_GL_SetSwapInterval(1); - }*/ - void CKernel::start(bool isPreview) { if(!isPreview) { @@ -81,11 +65,12 @@ namespace CosmicCore { configCamera = {"camera", "une caméra", {0.0f,0.0f,6.0f}, {1.0f,1.0f,1.0f}, glm::vec3(), "", "triangle", EColliderType::Box, EBodyType::Static, false}; configSol = {"sol", "le sol, ne bouge pas", {0.0f,-2.0f,0.0f}, {100.0f,1.0f,100.0f}, glm::vec3(), "assets/models/cube.glb", "triangle", EColliderType::Box, EBodyType::Static, true}; - configCube = {"cube", "le cube, shrek", {0.0f,2.0f,0.0f}, {1.0f,1.0f,1.0f}, glm::vec3(), "assets/models/cube.glb", "triangle", EColliderType::Box, EBodyType::Dynamic, true}; + configCube = {"cube", "le cube, shrek", {0.0f,60.0f,0.0f}, {1.0f,1.0f,1.0f}, glm::vec3(), "assets/models/cube.glb", "triangle", EColliderType::Box, EBodyType::Dynamic, true}; auto cam = CEntityFactory::create(m_activeScene, configCamera); ComponentFactory::addCamera(cam); + CEntityFactory::create(m_activeScene, configSol); auto e = CEntityFactory::create(m_activeScene, configCube); auto& renderer = m_activeScene->getECManager().registry.get(*e); @@ -138,22 +123,22 @@ namespace CosmicCore { auto& ent = m_activeScene->getECManager().registry.get(entities.front()); switch (keyPressed) { case SDLK_Z: - ent.forward({0.0f, 0.0f, -0.05f}); + ent.forward({0.0f, 0.0f, -0.08f}); break; case SDLK_Q: - ent.forward({-0.05f, 0.0f, 0.0f}); + ent.forward({-0.08f, 0.0f, 0.0f}); break; case SDLK_S: - ent.forward({0.0f, 0.0f, 0.05f}); + ent.forward({0.0f, 0.0f, 0.08f}); break; case SDLK_D: - ent.forward({0.05f, 0.0f, 0.0f}); + ent.forward({0.08f, 0.0f, 0.0f}); break; case SDLK_E: - ent.forward({0.0f, -0.05f, 0.0f}); + ent.forward({0.0f, -0.08f, 0.0f}); break; case SDLK_A: - ent.forward({0.0f, 0.05f, 0.0f}); + ent.forward({0.0f, 0.08f, 0.0f}); break; default: break; diff --git a/src/Engine/Core/Kernel/CKernel.hpp b/src/Engine/Core/Kernel/CKernel.hpp index f52b75e..ee02d33 100644 --- a/src/Engine/Core/Kernel/CKernel.hpp +++ b/src/Engine/Core/Kernel/CKernel.hpp @@ -7,24 +7,9 @@ #include #include -//#include "../Context/CContext.hpp" #include "../Graphics/Window/CGameWindow.hpp" -//#include "../Context/Window/CLoadingWindow.hpp" -//#include "../Controller/Configuration/CGameConfiguration.hpp" -//#include "../Controller/Configuration/CEngineConfiguration.hpp" - -//#include "../Controller/Exception/CExceptionManager.hpp" - -//#include "Input/CInput.hpp" #include "../Scene/CScene.hpp" -//#include "../Model/Node/Components/Graphic/CAbstractRenderer.hpp" -//#include "../Model/Node/Components/CAbstractScript.hpp" -//#include "../Model/Node/Components/Graphic/CCamera.hpp" -//#include "../Model/Graphic/Shader/CShader.hpp" -//#include "Shader/CShadersManager.hpp" -//#include "../Utils/CSerializable.hpp" -//#include namespace CosmicCore { @@ -56,38 +41,28 @@ namespace CosmicCore { CScene* m_activeScene; std::map> m_sceneMap; - //CInput m_inputHandler; - //SDL_GLContext m_GLcontext; - //bool m_isOriginOfContext; - - //CShadersManager m_shaderManager; - public: /** * @brief A pointer to the simulation which is accessible from anywhere. */ static CKernel* m_kernel; - /** - * @brief A pointer to the shader used, accessible from anywhere. - */ - //static CShader* m_mainShader; - CKernel() = delete; CKernel(std::string name, std::string gameName); - //CKernel(std::string name, std::string gameName, SDL_Window* window); ~CKernel(); std::string getName() { return m_gameName; }; + //CGameConfiguration* getConfig() { return &m_config; }; //CEngineConfiguration* getEngineConfig() { return &m_engineConfig; }; //void addScene(std::shared_ptr& scene); //void setActiveScene(std::string scene); - //void setContext(SDL_GLContext context); + CScene* getActiveScene(); void cleanup(){m_sceneMap.clear();}; + //unsigned int getNbScene() { return m_sceneList.size(); }; //std::map& getScenes() { return m_sceneList; }; @@ -107,49 +82,14 @@ namespace CosmicCore { m_deltaTime = delta; } - /*void updateInput(){ - m_inputHandler.updateEvent(); - }*/ - /*CShader* getShader(std::string shader) - { - return m_shaderManager.get(shader); - }*/ //CGameWindow& getGameWindow(){return m_window;}; - //SDL_GLContext getContext(){return m_GLcontext;}; - //void initGL(); + void start(bool isPreview = false); void loop(); void quit(); void fullscreen(); void desktop(); void focus(); - - //nlohmann::json to_json(); - - /*static CKernel* from_json(SDL_Window* window, SDL_GLContext context, nlohmann::json& j) - { - CKernel* g = new CKernel(j["ProjectName"], j["ProjectName"], window); - g->setContext(context); - g->start(true); - for (nlohmann::json& scene : j["Scenes"]) - { - g->addScene(CScene::from_json(scene)); - } - g->setActiveScene(j["ActiveScene"]); - return g; - };*/ - - /*static CKernel* from_json(nlohmann::json& j) - { - CKernel* g = new CKernel(j["ProjectName"], j["ProjectName"]); - g->initGL(); - for (nlohmann::json& scene : j["Scenes"]) - { - g->addScene(CScene::from_json(scene)); - } - g->setActiveScene(j["ActiveScene"]); - return g; - };*/ }; } diff --git a/src/Engine/Core/Physics/CTangibleWorld.cpp b/src/Engine/Core/Physics/CTangibleWorld.cpp index 26d18c5..c6f6b89 100644 --- a/src/Engine/Core/Physics/CTangibleWorld.cpp +++ b/src/Engine/Core/Physics/CTangibleWorld.cpp @@ -19,6 +19,7 @@ namespace CosmicCore { m_tempAllocator = std::make_unique(10 * 1024 * 1024); m_jobSystem = std::make_unique(JPH::cMaxPhysicsJobs, JPH::cMaxPhysicsBarriers, JPH::thread::hardware_concurrency() - 1); m_physicsSystem.Init(cMaxBodies, cNumBodyMutexes, cMaxBodyPairs, cMaxContactConstraints, m_broadPhaseLayer, m_objectVsBroadPhase, m_objectLayerPairFilter); + m_physicsSystem.SetGravity( {0.0, -1.25, 0.0}); } void CTangibleWorld::updateWorld(float deltaTime){ diff --git a/src/Engine/Core/Resource/CAbstractResource.cpp b/src/Engine/Core/Resource/CAbstractResource.cpp deleted file mode 100644 index 9022d6b..0000000 --- a/src/Engine/Core/Resource/CAbstractResource.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "CAbstractResource.hpp" - -namespace CosmicCore { - - - const char* typeToString(EResourceType type) - { - switch (type) { - case EResourceType::RESOURCE_MESH: - return "Mesh"; - case EResourceType::RESOURCE_MATERIAL: - return "Material"; - default: - return "UNKNOWN_RESOURCE"; - } - } -} \ No newline at end of file diff --git a/src/Engine/Core/Resource/CAbstractResource.hpp b/src/Engine/Core/Resource/CAbstractResource.hpp deleted file mode 100644 index 9983297..0000000 --- a/src/Engine/Core/Resource/CAbstractResource.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef CABSTRACT_RESOURCE_HPP -#define CABSTRACT_RESOURCE_HPP -#include "../Utils/CSerializable.hpp" - -namespace CosmicCore { - /** - * @brief Enum representing every type of resources that can be created. - */ - enum class EResourceType : unsigned char { - RESOURCE_MESH, - RESOURCE_MATERIAL, - RESOURCE_COUNT - }; - - const char* typeToString(EResourceType type); - - class CAbstractResource : public CSerializable{ - public: - virtual ~CAbstractResource() = default; - virtual nlohmann::json to_json() = 0; - }; - -} - -#endif \ No newline at end of file diff --git a/src/Engine/Core/Resource/Model/Material/CAbstractMaterial.cpp b/src/Engine/Core/Resource/Model/Material/CAbstractMaterial.cpp deleted file mode 100644 index a5180cb..0000000 --- a/src/Engine/Core/Resource/Model/Material/CAbstractMaterial.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "CAbstractMaterial.hpp" -namespace CosmicCore { - CAbstractMaterial::CAbstractMaterial(): CAbstractResource() - { - } -} \ No newline at end of file diff --git a/src/Engine/Core/Resource/Model/Material/CAbstractMaterial.hpp b/src/Engine/Core/Resource/Model/Material/CAbstractMaterial.hpp deleted file mode 100644 index 197704a..0000000 --- a/src/Engine/Core/Resource/Model/Material/CAbstractMaterial.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef CABSTRACTMATERIAL_HPP -#define CABSTRACTMATERIAL_HPP -#include "../../CAbstractResource.hpp" -#include "nlohmann/json_fwd.hpp" -namespace CosmicCore { - class CAbstractMaterial: public CAbstractResource - { - public: - CAbstractMaterial(); - nlohmann::json to_json(){return nlohmann::json();}; - }; -} -#endif \ No newline at end of file diff --git a/src/Engine/Core/Resource/Model/Mesh/CAbstractMesh.cpp b/src/Engine/Core/Resource/Model/Mesh/CAbstractMesh.cpp deleted file mode 100644 index c0d6a13..0000000 --- a/src/Engine/Core/Resource/Model/Mesh/CAbstractMesh.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "CAbstractMesh.hpp" - -namespace CosmicCore { - CAbstractMesh::CAbstractMesh(): CAbstractResource() - { - - } - -} \ No newline at end of file diff --git a/src/Engine/Core/Resource/Model/Mesh/CAbstractMesh.hpp b/src/Engine/Core/Resource/Model/Mesh/CAbstractMesh.hpp deleted file mode 100644 index ba5f91c..0000000 --- a/src/Engine/Core/Resource/Model/Mesh/CAbstractMesh.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef CABSTRACTMESH_HPP -#define CABSTRACTMESH_HPP -#include "../../CAbstractResource.hpp" -#include "nlohmann/json_fwd.hpp" -namespace CosmicCore { - class CAbstractMesh: public CAbstractResource - { - public: - CAbstractMesh(); - nlohmann::json to_json(){return nlohmann::json();}; - }; -} -#endif \ No newline at end of file diff --git a/src/Engine/Core/Scene/CScene.cpp b/src/Engine/Core/Scene/CScene.cpp index d63efdc..cc41b75 100644 --- a/src/Engine/Core/Scene/CScene.cpp +++ b/src/Engine/Core/Scene/CScene.cpp @@ -4,12 +4,9 @@ #include "../Component/Meta/CMetaData.hpp" #include "../Component/Geometry/CTransform.hpp" #include "../Component/Camera/CCamera.hpp" -#include "../Component/Relationships/CRelationship.hpp" #include "../Graphics/API/GraphicsAPI.hpp" -#include "../Graphics/Data/CModelLoader.hpp" #include -#include namespace CosmicCore { CScene::CScene(std::string name) : CSerializable(), @@ -96,16 +93,6 @@ namespace CosmicCore { } } - // void CScene::setMask(unsigned int mask) - // { - // m_maskLayer = mask; - // } - - // unsigned int CScene::getMask(void) - // { - // return m_maskLayer; - // } - nlohmann::json CScene::to_json() { return nlohmann::json(); diff --git a/src/Engine/Core/Utils/File/CFileManager.cpp b/src/Engine/Core/Utils/File/CFileManager.cpp deleted file mode 100644 index a88c2f5..0000000 --- a/src/Engine/Core/Utils/File/CFileManager.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include "CFileManager.hpp" - -/*void CFileManager::open(const char mode) { - DEBUG_LOG(trace, "Kernel", "FileManager", "file " + m_filePath + " opened.") - - switch (mode) { - case 'r': - m_filePtr = fopen(m_filePath.c_str(), "r"); - break; - case 'w': - m_filePtr = fopen(m_filePath.c_str(), "w"); - break; - default: - throw std::invalid_argument("\'mode\' parameter must be \'r\' (read) or \'w\' (write)"); - } - if (m_filePtr == NULL) { - throw CFileException("File \"" + m_filePath + "\" can't be opened"); - } -} - -void CFileManager::close(void) { - DEBUG_LOG(trace, "Kernel", "FileManager", "file " + m_filePath + " closed.") - - if (m_filePtr != NULL) { - fclose(m_filePtr); - } -} - -CFileManager::CFileManager(std::string path) : - m_filePath(path), - m_filePtr(NULL) { -} - -CFileManager::~CFileManager(void) { -} - -std::string CFileManager::getPath(void) const { - return m_filePath; -} - -void CFileManager::write(std::string content) { - open('w'); - - fputs(content.c_str(), m_filePtr); - - close(); -} - -std::string CFileManager::read(void) { - open('r'); - - std::string out(""); - char ch; - - while ((ch = fgetc(m_filePtr)) != EOF) { - out += ch; - } - - close(); - - return out; -}*/ \ No newline at end of file diff --git a/src/Engine/Core/Utils/File/CFileManager.hpp b/src/Engine/Core/Utils/File/CFileManager.hpp deleted file mode 100644 index f451c6a..0000000 --- a/src/Engine/Core/Utils/File/CFileManager.hpp +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef CFILEMANAGER_HPP -#define CFILEMANAGER_HPP - -#include -#include - -/** - * @file CFileManager.hpp - * @brief File of CException, a class to manage program file. - */ - -/** - * @brief Class to manage file. - */ -class CFileManager { -private: - // The pointer to file. - FILE* m_filePtr; - - // The file path. - std::string m_filePath; - - /** - * @brief Open the file with the given mode - * @param[in] mode The mode of opening file, must be 'r' or 'w'; - * @post throw a std::invalid_argument if mode is invalid, or a CFileException if the file can't be opened. - */ - void open(const char mode); - - /** - * @brief Close the file - * @post Do nothing if the file isn't opened. - */ - void close(void); - -public: - CFileManager(void) = delete; - CFileManager(const CFileManager& param) = delete; - CFileManager& operator=(const CFileManager& param) = delete; - - /** - * @brief Build a file manager to the file's given path. - * @param[in] path The path of the file; - */ - CFileManager(std::string path); - - /** - * @brief the destructor. - * @pre The file must be close before destroying this. - */ - ~CFileManager(void); - - /** - * @brief The file path getter. - * @return std::string The path of the file; - */ - std::string getPath(void) const; - - /** - * @brief Write the file function. - * @param[in] content The new content of the file. - * - * This function erase the old content of the file and replace it by "content" - */ - void write(std::string content); - - /** - * @brief Read the file function. - * @return std::string, The content of the file. - */ - std::string read(void); -}; - -#endif \ No newline at end of file diff --git a/src/Engine/Utils/Factory/CEntityFactory.cpp b/src/Engine/Utils/Factory/CEntityFactory.cpp index 338f43a..4348892 100644 --- a/src/Engine/Utils/Factory/CEntityFactory.cpp +++ b/src/Engine/Utils/Factory/CEntityFactory.cpp @@ -5,6 +5,7 @@ namespace CEntityFactory{ CEntity CEntityFactory::create(CScene* scene, const EntityConfig& config) { auto entity = scene->createEntity(); + ComponentFactory::addMetaData(entity, config.name, config.description); ComponentFactory::addTransform(entity, config.position, config.scale, config.rotation); if(!config.modelPath.empty()) ComponentFactory::addRenderer(entity, config.modelPath); diff --git a/src/Engine/Utils/Factory/ComponentFactory.cpp b/src/Engine/Utils/Factory/ComponentFactory.cpp index 5c74dd7..8ed70d7 100644 --- a/src/Engine/Utils/Factory/ComponentFactory.cpp +++ b/src/Engine/Utils/Factory/ComponentFactory.cpp @@ -93,4 +93,13 @@ namespace ComponentFactory { rb.init(); return rb; } + + CMetaData& addMetaData(CEntity& entity, std::string n, std::string des) + { + auto& reg = entity.getRegistry(); + + auto& rb = reg.registry.emplace(*entity, entity, n, des); + return rb; + } + }; \ No newline at end of file diff --git a/src/Engine/Utils/Factory/ComponentFactory.hpp b/src/Engine/Utils/Factory/ComponentFactory.hpp index df42b11..448c7e3 100644 --- a/src/Engine/Utils/Factory/ComponentFactory.hpp +++ b/src/Engine/Utils/Factory/ComponentFactory.hpp @@ -7,7 +7,7 @@ #include "../../Core/Component/Rigidbody/CRigidBody.hpp" #include "../../Core/Component/Graphics/CRenderer.hpp" #include "../../Core/Component/Camera/CCamera.hpp" - +#include "../../Core/Component/Meta/CMetaData.hpp" namespace ComponentFactory { using namespace CosmicCore; @@ -31,6 +31,8 @@ namespace ComponentFactory { // crée et initialise un CRigidBody CRigidBody& addRigidBody(CEntity& entity, EBodyType type = EBodyType::Dynamic); + + CMetaData& addMetaData(CEntity& entity, std::string n, std::string des); }; #endif

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 rqpl%#Tj> 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 H`TFy&n+^ZF@ITW2^5-u2?ApIy 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�kb^;}SJI52&&&szCu!B?-SETON`H3Jis!Vx$Df zI>~OG1GiIqjsE!*8czId*RG$A!5TGJ4d4U6BG`YwiE6}jIZ&qVa(c@?KVS+KnKs)W znKM0aUHug#bKUr~fx^yt$6I#`G;81f`Xl+-7$fG|hZJPnOQQ~5^+OVz+Kd@WsFy#o zU|!ZXsU)x~sG;$PKl888uOQ}V<@2Ec^#eJZy>&Cu<(cy@U_V7}!hJuv&yR|k%5*Rt zyoEnfokCoMKb)Up*SCd|?Tj5#+=R%HX%IOt;MqRjyCgNg?yc$**9i~ld}3q&i~OrT zND3qtWKRgcmRCEb_qikTB73x@(NioDjc?%k{5kol-nwfrF377{ESg7{;=w@s;wPz$^#CrfaE)nCs#0q# zMF`qql)At6e4pTvZ{ztXGA8ocPEN1GykKvj`Q>~LlPS8Bjrl#5S9Z(R?@+aWlr08S zADhBqxdm%Kxo`nGoFkk4k;$o4e%)n%;>S#yXe;2UV=;yOJqqyT^asV~#=jR6-Gdv&w z?(iCBn;!CmQMQxM_=c&}rRjBdzF?qISeiiR7hz*L-(MGGe)YI1uf|bI`fYPn!;H z#z+UsS(D7s`UYy?beb%oLqXksiW@{CpoU0GMh=Tu?~TO-X;2PYjJlQ8>2|~e!d&|( zGR9k9jzY+*X+v>5hBcdG8XlL3bsA_)yUuUxgkkju!S%8;;&|JZo0YypawU*b=MMVKK?1WN*^rjR}!^upX+DRmFmCH-Y>|-)V5{%=b${Eq{9wp zQ=OBa9-5?@>HO5z%On>3$Mzs}(q7LrQgFJk5Ek6ftQ?+BFhN9LmaUT3u5U&n2~ z=S-gv3C<4WeC(~WA(*N4>~_``E%w+;e&H2w(%{ZBO} zFSxbidtL6NMj+>FZ~f^M$n)@z*1mkyfGzVuRg5BJm2GRLB`-8msI+Zz-_CO zz4g^Fmt9`}IwZEvB>O=r+O02RjpAb(VdPDcD-{=i)=Wc$CFt^~-h1mNp^cSO3tG;P z909A6y&3hHsKR#R^_1jiJ(Zue60lr?d3HQXlxL|S{As5W3j)}Y`fR!%d03LtSnLw& zR`mq$9vkB@G}5cSr}^E}cH=2X*U1OM}|gEc2=V@cz-88vRR`<@1*4pg5`r4-%>Gz!46>ypwD?~+~X4FITi z!Ib+9x|l%Z;6P+Xe7O@cJ`05JRC0fU++I@dPmmi%$k9q?{Yt70B==61>x;_00unmP zU4_OW5ZPZY^KfX!4ArJ9M+7o9+2MLA9u)}7zTV4Tq)^9P$y-Mo0PK1+`zL4(9%c