diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2eaa1a1..7dc2ffd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/Takishima/cmake-pre-commit-hooks - rev: v1.8.1 + rev: v1.9.4 hooks: - id: clang-format args: @@ -13,20 +13,21 @@ repos: - '-Bcmake-build-pre-commit' - '--preset' - 'pre-commit' + stages: [ manual ] - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.5.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer - id: check-yaml - repo: https://github.com/executablebooks/mdformat - rev: 0.7.16 + rev: 0.7.17 hooks: - id: mdformat additional_dependencies: - mdformat-gfm - mdformat-tables - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.23.0 + rev: 0.27.2 hooks: - id: check-github-workflows diff --git a/CMakeLists.txt b/CMakeLists.txt index 8847ba3..a647a60 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,11 +5,18 @@ if (POLICY CMP0140) # Enables: return(PROPAGATE) cmake_policy(SET CMP0140 NEW) endif () +# TODO: Remove when bumping cmake >= 3.22 +if (POLICY CMP0127) + # Enables: cmake_dependent_option: Full Condition Syntax + cmake_policy(SET CMP0127 NEW) +endif () #[==============================================================================================[ # Basic project definition # ]==============================================================================================] +list(APPEND CMAKE_MESSAGE_CONTEXT schema_validator) + # TODO: CMake >= 3.19 can use string(JSON VERSION GET "${METADATA}" "version") to load from JSON set(PROJECT_VERSION 2.4.0) @@ -23,8 +30,10 @@ project(nlohmann_json_schema_validator if (NOT DEFINED nlohmann_json_schema_validator_IS_TOP_LEVEL) if (CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) set(PROJECT_IS_TOP_LEVEL ON) + set(nlohmann_json_schema_validator_IS_TOP_LEVEL ON) else () set(PROJECT_IS_TOP_LEVEL OFF) + set(nlohmann_json_schema_validator_IS_TOP_LEVEL OFF) endif () endif () @@ -32,12 +41,17 @@ endif () # Options # ]==============================================================================================] +include(CMakeDependentOption) + 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}) +if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.22) + # Only enable BUILD_EXAMPLES if we are building tests or installing the targets + cmake_dependent_option(JSON_VALIDATOR_BUILD_EXAMPLES "JsonValidator: Build examples" ${PROJECT_IS_TOP_LEVEL} "JSON_VALIDATOR_BUILD_TESTS OR JSON_VALIDATOR_INSTALL" OFF) +else () + option(JSON_VALIDATOR_BUILD_EXAMPLES "JsonValidator: Build examples" ${PROJECT_IS_TOP_LEVEL}) +endif () 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}) @@ -65,19 +79,6 @@ 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 # ]==============================================================================================] @@ -119,7 +120,7 @@ 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" + "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 () @@ -128,11 +129,11 @@ endif () # Main definition # ]==============================================================================================] -message(STATUS "JsonValidator: Configured for ${CMAKE_BUILD_TYPE}") +message(STATUS "Configured for ${CMAKE_BUILD_TYPE}") if (DEFINED nlohmann_json_VERSION) - message(STATUS "JsonValidator: Using nlohmann/json version: ${nlohmann_json_VERSION}") + message(STATUS "Using nlohmann/json version: ${nlohmann_json_VERSION}") else () - message(STATUS "JsonValidator: nlohmann_json_VERSION is not set. Possible value: ${JSON_FETCH_VERSION}") + message(STATUS "nlohmann_json_VERSION is not set. Possible value: ${JSON_FETCH_VERSION}") endif () ## Main targets diff --git a/cmake/CMakePresets-defaults.json b/cmake/CMakePresets-defaults.json index bfc642c..e4415bc 100644 --- a/cmake/CMakePresets-defaults.json +++ b/cmake/CMakePresets-defaults.json @@ -9,6 +9,10 @@ "CMAKE_BUILD_TYPE": { "type": "STRING", "value": "Release" + }, + "CMAKE_MESSAGE_CONTEXT_SHOW": { + "type": "BOOL", + "value": true } } } diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 039c40e..16cfd56 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -1,14 +1,87 @@ -# 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) +# TODO: This definition should be moved to /test, together with the for loop +function(schema_validator_add_test name) + #[===[.md + # schema_validator_add_test -add_executable(readme-json-schema readme.cpp) -target_link_libraries(readme-json-schema nlohmann_json_schema_validator) + Internal helper for adding example/functional tests specific for the current template project -add_executable(format-json-schema format.cpp) -target_link_libraries(format-json-schema nlohmann_json_schema_validator) + ## Synopsis + ```cmake + schema_validator_add_test( + [TEST_NAME ] + [TARGET ] + [LABELS ]) + ``` -if (JSON_VALIDATOR_INSTALL) - install(TARGETS json-schema-validate readme-json-schema format-json-schema - DESTINATION ${CMAKE_INSTALL_BINDIR}) -endif () + ## Options + + `` + Path to the CMake project to be executed relative to `${CMAKE_CURRENT_SOURCE_DIR}` + + `TEST_NAME` [Default: ``] + Name for the test to be used as the ctest name + + `LABELS` + Additional labels to be added + + ]===] + + list(APPEND CMAKE_MESSAGE_CONTEXT "schema_validator_add_test") + + set(ARGS_Options) + set(ARGS_OneValue + TEST_NAME + ) + set(ARGS_MultiValue + LABELS + ) + cmake_parse_arguments(PARSE_ARGV 1 ARGS "${ARGS_Options}" "${ARGS_OneValue}" "${ARGS_MultiValue}") + # Check required/optional arguments + if (ARGC LESS 1) + message(FATAL_ERROR "Missing test name") + endif () + if (NOT DEFINED ARGS_TEST_NAME) + set(ARGS_TEST_NAME test-${name}) + endif () + set(extra_args) + if (nlohmann_json_schema_validator_IS_TOP_LEVEL) + list(APPEND extra_args + -DFETCHCONTENT_TRY_FIND_PACKAGE_MODE=ALWAYS + # Generated Config file point to binary targets until it is installed + -Dnlohmann_json_schema_validator_ROOT=${Template_BINARY_DIR} + -DFETCHCONTENT_SOURCE_DIR_TEMPLATE=${Template_SOURCE_DIR} + ) + endif () + + add_test(NAME ${ARGS_TEST_NAME} + COMMAND ${CMAKE_CTEST_COMMAND} --build-and-test ${CMAKE_CURRENT_SOURCE_DIR}/${test} + ${CMAKE_CURRENT_BINARY_DIR}/${test} + # Use the same build environment as the current runner + --build-generator "${CMAKE_GENERATOR}" + --build-options -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} + ${extra_args} + --test-command ${CMAKE_CTEST_COMMAND} --test-dir ${CMAKE_CURRENT_BINARY_DIR}/${test} + --output-on-failure --no-tests=ignore + ) + set_tests_properties(${ARGS_TEST_NAME} PROPERTIES + LABELS "${ARGS_LABELS}" + ) +endfunction() + +foreach (example IN ITEMS + format + readme + validate +) + if (JSON_VALIDATOR_INSTALL) + # The projects need to be added only if they are to be installed + add_subdirectory(${example}) + elseif (JSON_VALIDATOR_BUILD_TESTS) + schema_validator_add_test(${example}) + else () + # Can be simplified after CMake >= 3.22 + message(WARNING + "Nothing specified to do with the examples. Enable this together with INSTALL or BUILD_TESTS" + ) + endif () +endforeach () diff --git a/example/format/CMakeLists.txt b/example/format/CMakeLists.txt new file mode 100644 index 0000000..83623ae --- /dev/null +++ b/example/format/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 3.24) + +project(example_format LANGUAGES CXX) + +include(FetchContent) + +# The target check is not generally needed. It is used here because these projects are reused by the top-level project +if (NOT TARGET nlohmann_json_schema_validator::validator) + # Note: The 3.24 cmake requirement only appears due to `FetchContent_Declare(FIND_PACKAGE_ARGS)` + # To support earlier versions, you can replace this with `find_package` or remove `FIND_PACKAGE_ARGS` + FetchContent_Declare(nlohmann_json_schema_validator + GIT_REPOSITORY https://github.com/pboettch/json-schema-validator + GIT_TAG main + FIND_PACKAGE_ARGS CONFIG + ) + FetchContent_MakeAvailable(nlohmann_json_schema_validator) +endif () + +add_executable(format-json-schema format.cpp) +target_link_libraries(format-json-schema PRIVATE nlohmann_json_schema_validator::validator) + +# Reusing the top-level install in order to bundle these executables +if (JSON_VALIDATOR_INSTALL) + install(TARGETS format-json-schema + DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif () diff --git a/example/format.cpp b/example/format/format.cpp similarity index 100% rename from example/format.cpp rename to example/format/format.cpp diff --git a/example/readme/CMakeLists.txt b/example/readme/CMakeLists.txt new file mode 100644 index 0000000..106b520 --- /dev/null +++ b/example/readme/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 3.24) + +project(example_readme LANGUAGES CXX) + +include(FetchContent) + +# The target check is not generally needed. It is used here because these projects are reused by the top-level project +if (NOT TARGET nlohmann_json_schema_validator::validator) + # Note: The 3.24 cmake requirement only appears due to `FetchContent_Declare(FIND_PACKAGE_ARGS)` + # To support earlier versions, you can replace this with `find_package` or remove `FIND_PACKAGE_ARGS` + FetchContent_Declare(nlohmann_json_schema_validator + GIT_REPOSITORY https://github.com/pboettch/json-schema-validator + GIT_TAG main + FIND_PACKAGE_ARGS CONFIG + ) + FetchContent_MakeAvailable(nlohmann_json_schema_validator) +endif () + +add_executable(readme-json-schema readme.cpp) +target_link_libraries(readme-json-schema PRIVATE nlohmann_json_schema_validator::validator) + +# Reusing the top-level install in order to bundle these executables +if (JSON_VALIDATOR_INSTALL) + install(TARGETS readme-json-schema + DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif () diff --git a/example/readme.cpp b/example/readme/readme.cpp similarity index 100% rename from example/readme.cpp rename to example/readme/readme.cpp diff --git a/example/validate/CMakeLists.txt b/example/validate/CMakeLists.txt new file mode 100644 index 0000000..404431b --- /dev/null +++ b/example/validate/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 3.24) + +project(example_validate LANGUAGES CXX) + +include(FetchContent) + +# The target check is not generally needed. It is used here because these projects are reused by the top-level project +if (NOT TARGET nlohmann_json_schema_validator::validator) + # Note: The 3.24 cmake requirement only appears due to `FetchContent_Declare(FIND_PACKAGE_ARGS)` + # To support earlier versions, you can replace this with `find_package` or remove `FIND_PACKAGE_ARGS` + FetchContent_Declare(nlohmann_json_schema_validator + GIT_REPOSITORY https://github.com/pboettch/json-schema-validator + GIT_TAG main + FIND_PACKAGE_ARGS CONFIG + ) + FetchContent_MakeAvailable(nlohmann_json_schema_validator) +endif () + +add_executable(json-schema-validate json-schema-validate.cpp) +target_link_libraries(json-schema-validate PRIVATE nlohmann_json_schema_validator::validator) + +# Reusing the top-level install in order to bundle these executables +if (JSON_VALIDATOR_INSTALL) + install(TARGETS json-schema-validate + DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif () diff --git a/example/json-schema-validate.cpp b/example/validate/json-schema-validate.cpp similarity index 100% rename from example/json-schema-validate.cpp rename to example/validate/json-schema-validate.cpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 50ba0e6..76854a8 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,27 +1,129 @@ -set(PIPE_IN_TEST_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/test-pipe-in.sh) - -# built-in tests -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) +cmake_minimum_required(VERSION 3.14) + +#[==============================================================================================[ +# Basic project definition # +]==============================================================================================] + +list(APPEND CMAKE_MESSAGE_CONTEXT Test) +project(nlohmann_json_schema_validator_test + LANGUAGES CXX +) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +#[==============================================================================================[ +# Options # +]==============================================================================================] + +include(CMakeDependentOption) +cmake_dependent_option(JSON_VALIDATOR_TEST_COVERAGE "JsonValidator: Build with test coverage" OFF "nlohmann_json_schema_validator_IS_TOP_LEVEL" OFF) +mark_as_advanced(JSON_VALIDATOR_TEST_COVERAGE) + +#[==============================================================================================[ +# Project configuration # +]==============================================================================================] + +include(FetchContent) + +if (JSON_VALIDATOR_TEST_COVERAGE) + if (NOT CMAKE_CXX_COMPILER_ID MATCHES "(Clang|GNU)") + message(WARNING + "Coverage flags not known for: ${CMAKE_CXX_COMPILER_ID}.\n" + "Using --coverage as default") + endif () + target_compile_options(nlohmann_json_schema_validator PRIVATE --coverage) + target_link_options(nlohmann_json_schema_validator PUBLIC --coverage) +endif () + +#[==============================================================================================[ +# External packages # +]==============================================================================================] + +set(fetch_packages) +if (NOT TARGET nlohmann_json_schema_validator::validator) + # Fetch/Find nlohmann_json_schema_validator + # TODO: Remove when bumping cmake >= 3.24 + if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.24) + FetchContent_Declare(nlohmann_json_schema_validator + GIT_REPOSITORY https://github.com/pboettch/json-schema-validator + GIT_TAG main + FIND_PACKAGE_ARGS CONFIG + ) + list(APPEND fetch_packages nlohmann_json_schema_validator) + else () + # Try to get system installed version + find_package(nlohmann_json_schema_validator QUIET) + if (NOT nlohmann_json_schema_validator_FOUND) + # If failed fetch the desired version + FetchContent_Declare(nlohmann_json_schema_validator + GIT_REPOSITORY https://github.com/pboettch/json-schema-validator + GIT_TAG main + ) + list(APPEND fetch_packages nlohmann_json_schema_validator) + endif () + endif () +endif () +# Fetch/Find Catch2 +if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.24) + FetchContent_Declare(Catch2 + GIT_REPOSITORY https://github.com/catchorg/Catch2 + GIT_TAG v3.4.0 + FIND_PACKAGE_ARGS 3.4.0 CONFIG + ) + list(APPEND fetch_packages Catch2) +else () + # Try to get system installed version + find_package(Catch2 3.4.0 QUIET) + if (NOT Catch2_FOUND) + # If failed fetch the desired version + FetchContent_Declare(Catch2 + GIT_REPOSITORY https://github.com/catchorg/Catch2 + GIT_TAG v3.4.0 + ) + list(APPEND fetch_packages Catch2) + endif () +endif () + +# Get all dependencies +FetchContent_MakeAvailable(${fetch_packages}) + +#[==============================================================================================[ +# Main definition # +]==============================================================================================] + +enable_testing() +include(Catch) + +add_executable(json-schema-test-suite) +set_target_properties(json-schema-test-suite PROPERTIES + OUTPUT_NAME test-suite +) +target_link_libraries(json-schema-test-suite PRIVATE Catch2::Catch2WithMain nlohmann_json_schema_validator::validator) +catch_discover_tests(json-schema-test-suite) + +target_sources(json-schema-test-suite PRIVATE + test_uri.cpp + utils.cpp +) +target_include_directories(json-schema-test-suite PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +foreach (issue IN ITEMS + issue-9 + issue-12 + issue-27 + issue-48 + issue-54 + issue-75 + issue-93 + issue-96 + issue-100 + issue-101 + issue-143 + issue-209 +) + target_sources(json-schema-test-suite PRIVATE ${issue}/test_issue.cpp) +endforeach () add_executable(errors errors.cpp) target_link_libraries(errors nlohmann_json_schema_validator) @@ -89,3 +191,5 @@ add_test(NAME issue-243-root-default-values COMMAND issue-243-root-default-value 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_subdirectory(JSON-Schema-Test-Suite) diff --git a/test/issue-100/CMakeLists.txt b/test/issue-100/CMakeLists.txt deleted file mode 100644 index 06a754f..0000000 --- a/test/issue-100/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -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/test/issue-100/test_issue.cpp b/test/issue-100/test_issue.cpp new file mode 100644 index 0000000..0892a1c --- /dev/null +++ b/test/issue-100/test_issue.cpp @@ -0,0 +1,19 @@ +#include +#include + +#include +#include + +#include "utils.h" + +using namespace std::literals; +using Catch::Matchers::ContainsSubstring; +using Catch::Matchers::MessageMatches; + +TEST_CASE_METHOD(JsonValidateFixture, "issue-100") +{ + // Change the working directory to the issue path + auto path = std::filesystem::path(__FILE__).parent_path(); + REQUIRE_NOTHROW(std::filesystem::current_path(path)); + REQUIRE_THROWS_MATCHES(validate("schema.json"sv, "instance.json"sv), std::invalid_argument, MessageMatches(ContainsSubstring("undefined references: [random_ref]"))); +} diff --git a/test/issue-101/CMakeLists.txt b/test/issue-101/CMakeLists.txt deleted file mode 100644 index 41ad0c9..0000000 --- a/test/issue-101/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -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/test/issue-101/test_issue.cpp b/test/issue-101/test_issue.cpp new file mode 100644 index 0000000..4f9df7e --- /dev/null +++ b/test/issue-101/test_issue.cpp @@ -0,0 +1,20 @@ +#include +#include + +#include +#include + +#include "utils.h" + +using namespace std::literals; +using Catch::Matchers::Matches; +using Catch::Matchers::MessageMatches; + +TEST_CASE_METHOD(JsonValidateFixture, "issue-101") +{ + // Change the working directory to the issue path + auto path = std::filesystem::path(__FILE__).parent_path(); + REQUIRE_NOTHROW(std::filesystem::current_path(path)); + REQUIRE_THROWS_MATCHES(validate("schema.json"sv, "instance.json"sv), std::invalid_argument, + MessageMatches(Matches("invalid JSON-type.*/properties/required.*expected: boolean or object.*"))); +} diff --git a/test/issue-12/CMakeLists.txt b/test/issue-12/CMakeLists.txt deleted file mode 100644 index 5dc7595..0000000 --- a/test/issue-12/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -add_test_simple_schema(Issue::12 - ${CMAKE_CURRENT_SOURCE_DIR}/schema.json - ${CMAKE_CURRENT_SOURCE_DIR}/instance.json) diff --git a/test/issue-12/test_issue.cpp b/test/issue-12/test_issue.cpp new file mode 100644 index 0000000..e535694 --- /dev/null +++ b/test/issue-12/test_issue.cpp @@ -0,0 +1,16 @@ +#include +#include + +#include + +#include "utils.h" + +using namespace std::literals; + +TEST_CASE_METHOD(JsonValidateFixture, "issue-12") +{ + // Change the working directory to the issue path + auto path = std::filesystem::path(__FILE__).parent_path(); + REQUIRE_NOTHROW(std::filesystem::current_path(path)); + REQUIRE_NOTHROW(validate("schema.json"sv, "instance.json"sv)); +} diff --git a/test/issue-143/CMakeLists.txt b/test/issue-143/CMakeLists.txt deleted file mode 100644 index 1cc2365..0000000 --- a/test/issue-143/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -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/test/issue-143/test_issue.cpp b/test/issue-143/test_issue.cpp new file mode 100644 index 0000000..fcd9c3e --- /dev/null +++ b/test/issue-143/test_issue.cpp @@ -0,0 +1,23 @@ +#include +#include + +#include +#include + +#include "utils.h" + +using namespace std::literals; +using Catch::Matchers::ContainsSubstring; +using Catch::Matchers::MessageMatches; + +TEST_CASE_METHOD(JsonValidateFixture, "issue-143") +{ + // Change the working directory to the issue path + auto path = std::filesystem::path(__FILE__).parent_path(); + REQUIRE_NOTHROW(std::filesystem::current_path(path)); + CHECK_THROWS_MATCHES(validate("schema.json"sv, "instance-fail-1.json"sv), std::invalid_argument, + MessageMatches(ContainsSubstring("At /ref1 of \"a\" - unexpected instance type"))); + CHECK_THROWS_MATCHES(validate("schema.json"sv, "instance-fail-a.json"sv), std::invalid_argument, + MessageMatches(ContainsSubstring("At /refa of 12 - unexpected instance type"))); + CHECK_NOTHROW(validate("schema.json"sv, "instance.json"sv)); +} diff --git a/test/issue-209/test_issue.cpp b/test/issue-209/test_issue.cpp new file mode 100644 index 0000000..0e9b8bd --- /dev/null +++ b/test/issue-209/test_issue.cpp @@ -0,0 +1,16 @@ +#include +#include + +#include + +#include "utils.h" + +using namespace std::literals; + +TEST_CASE_METHOD(JsonValidateFixture, "issue-209") +{ + // Change the working directory to the issue path + auto path = std::filesystem::path(__FILE__).parent_path(); + REQUIRE_NOTHROW(std::filesystem::current_path(path)); + REQUIRE_NOTHROW(validate("entities.schema.json"sv, "instance.json"sv)); +} diff --git a/test/issue-27/CMakeLists.txt b/test/issue-27/CMakeLists.txt deleted file mode 100644 index 79e3001..0000000 --- a/test/issue-27/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -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/test/issue-27/test_issue.cpp b/test/issue-27/test_issue.cpp new file mode 100644 index 0000000..2fbe020 --- /dev/null +++ b/test/issue-27/test_issue.cpp @@ -0,0 +1,19 @@ +#include +#include + +#include +#include + +#include "utils.h" + +using namespace std::literals; +using Catch::Matchers::ContainsSubstring; +using Catch::Matchers::MessageMatches; + +TEST_CASE_METHOD(JsonValidateFixture, "issue-27") +{ + // Change the working directory to the issue path + auto path = std::filesystem::path(__FILE__).parent_path(); + REQUIRE_NOTHROW(std::filesystem::current_path(path)); + REQUIRE_THROWS_MATCHES(validate("schema.json"sv, "instance.json"sv), std::invalid_argument, MessageMatches(ContainsSubstring("instance exceeds maximum"))); +} diff --git a/test/issue-48/CMakeLists.txt b/test/issue-48/CMakeLists.txt deleted file mode 100644 index 832d374..0000000 --- a/test/issue-48/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -add_test_simple_schema(Issue::48 - ${CMAKE_CURRENT_SOURCE_DIR}/schema.json - ${CMAKE_CURRENT_SOURCE_DIR}/instance.json) diff --git a/test/issue-48/test_issue.cpp b/test/issue-48/test_issue.cpp new file mode 100644 index 0000000..07e52a6 --- /dev/null +++ b/test/issue-48/test_issue.cpp @@ -0,0 +1,16 @@ +#include +#include + +#include + +#include "utils.h" + +using namespace std::literals; + +TEST_CASE_METHOD(JsonValidateFixture, "issue-48") +{ + // Change the working directory to the issue path + auto path = std::filesystem::path(__FILE__).parent_path(); + REQUIRE_NOTHROW(std::filesystem::current_path(path)); + REQUIRE_NOTHROW(validate("schema.json"sv, "instance.json"sv)); +} diff --git a/test/issue-54/CMakeLists.txt b/test/issue-54/CMakeLists.txt deleted file mode 100644 index 016e594..0000000 --- a/test/issue-54/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -add_test_simple_schema(Issue::54 - ${CMAKE_CURRENT_SOURCE_DIR}/schema.json - ${CMAKE_CURRENT_SOURCE_DIR}/instance.json) diff --git a/test/issue-54/test_issue.cpp b/test/issue-54/test_issue.cpp new file mode 100644 index 0000000..626732c --- /dev/null +++ b/test/issue-54/test_issue.cpp @@ -0,0 +1,16 @@ +#include +#include + +#include + +#include "utils.h" + +using namespace std::literals; + +TEST_CASE_METHOD(JsonValidateFixture, "issue-54") +{ + // Change the working directory to the issue path + auto path = std::filesystem::path(__FILE__).parent_path(); + REQUIRE_NOTHROW(std::filesystem::current_path(path)); + REQUIRE_NOTHROW(validate("schema.json"sv, "instance.json"sv)); +} diff --git a/test/issue-75/CMakeLists.txt b/test/issue-75/CMakeLists.txt deleted file mode 100644 index 02639dd..0000000 --- a/test/issue-75/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -add_test_simple_schema(Issue::75 - ${CMAKE_CURRENT_SOURCE_DIR}/schema.json - ${CMAKE_CURRENT_SOURCE_DIR}/instance.json) diff --git a/test/issue-75/test_issue.cpp b/test/issue-75/test_issue.cpp new file mode 100644 index 0000000..b8ec50f --- /dev/null +++ b/test/issue-75/test_issue.cpp @@ -0,0 +1,16 @@ +#include +#include + +#include + +#include "utils.h" + +using namespace std::literals; + +TEST_CASE_METHOD(JsonValidateFixture, "issue-75") +{ + // Change the working directory to the issue path + auto path = std::filesystem::path(__FILE__).parent_path(); + REQUIRE_NOTHROW(std::filesystem::current_path(path)); + REQUIRE_NOTHROW(validate("schema.json"sv, "instance.json"sv)); +} diff --git a/test/issue-9/CMakeLists.txt b/test/issue-9/CMakeLists.txt deleted file mode 100644 index 41b56a2..0000000 --- a/test/issue-9/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -add_test_simple_schema(Issue::9 - ${CMAKE_CURRENT_SOURCE_DIR}/base.json - ${CMAKE_CURRENT_SOURCE_DIR}/instance.json) diff --git a/test/issue-9/test_issue.cpp b/test/issue-9/test_issue.cpp new file mode 100644 index 0000000..02e2891 --- /dev/null +++ b/test/issue-9/test_issue.cpp @@ -0,0 +1,16 @@ +#include +#include + +#include + +#include "utils.h" + +using namespace std::literals; + +TEST_CASE_METHOD(JsonValidateFixture, "issue-9") +{ + // Change the working directory to the issue path + auto path = std::filesystem::path(__FILE__).parent_path(); + REQUIRE_NOTHROW(std::filesystem::current_path(path)); + REQUIRE_NOTHROW(validate("base.json"sv, "instance.json"sv)); +} diff --git a/test/issue-93/CMakeLists.txt b/test/issue-93/CMakeLists.txt deleted file mode 100644 index eaccc41..0000000 --- a/test/issue-93/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ - -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/test/issue-93/issue-93.cpp b/test/issue-93/issue-93.cpp deleted file mode 100644 index 87ba599..0000000 --- a/test/issue-93/issue-93.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#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/test/issue-93/test_issue.cpp b/test/issue-93/test_issue.cpp new file mode 100644 index 0000000..d74eff8 --- /dev/null +++ b/test/issue-93/test_issue.cpp @@ -0,0 +1,37 @@ +#include +#include + +#include +#include + +#include "utils.h" + +using namespace std::literals; +using Catch::Matchers::ContainsSubstring; +using Catch::Matchers::MessageMatches; + +static const auto instance = R"( +[ + { + "name":"player", + "renderable": { + "fg":"White" + } + } +] +)"_json; + +static const auto expected_patch = R"( +[{"op":"add","path":"/0/renderable/bg","value":"Black"}] +)"_json; + +TEST_CASE_METHOD(JsonValidateFixture, "issue-93") +{ + // Change the working directory to the issue path + auto path = std::filesystem::path(__FILE__).parent_path(); + nlohmann::json patch; + REQUIRE_NOTHROW(std::filesystem::current_path(path)); + auto schema_path = path / "blueprints.schema.json"; + REQUIRE_NOTHROW(patch = validate(schema_path, instance)); + REQUIRE(patch == expected_patch); +} diff --git a/test/issue-96/CMakeLists.txt b/test/issue-96/CMakeLists.txt deleted file mode 100644 index 03582e6..0000000 --- a/test/issue-96/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -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/test/issue-96/test_issue.cpp b/test/issue-96/test_issue.cpp new file mode 100644 index 0000000..1483445 --- /dev/null +++ b/test/issue-96/test_issue.cpp @@ -0,0 +1,19 @@ +#include +#include + +#include +#include + +#include "utils.h" + +using namespace std::literals; +using Catch::Matchers::ContainsSubstring; +using Catch::Matchers::MessageMatches; + +TEST_CASE_METHOD(JsonValidateFixture, "issue-96") +{ + // Change the working directory to the issue path + auto path = std::filesystem::path(__FILE__).parent_path(); + REQUIRE_NOTHROW(std::filesystem::current_path(path)); + REQUIRE_THROWS_MATCHES(validate("schema.json"sv, "instance.json"sv), std::invalid_argument, MessageMatches(ContainsSubstring("instance exceeds maximum"))); +} diff --git a/test/test-pipe-in.sh b/test/test-pipe-in.sh deleted file mode 100755 index be7315f..0000000 --- a/test/test-pipe-in.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/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/test/uri.cpp b/test/test_uri.cpp similarity index 51% rename from test/uri.cpp rename to test/test_uri.cpp index 38c81ee..671565c 100644 --- a/test/uri.cpp +++ b/test/test_uri.cpp @@ -6,56 +6,49 @@ * SPDX-License-Identifier: MIT * */ -#include -#include -#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) +namespace nlohmann { - if (a != b) { - std::cerr << "Failed: '" << a << "' != '" << b << "'\n"; - errors++; - } -} - -static void EXPECT_EQ(const nlohmann::json_uri &a, const std::string &b) +bool operator==(const json_uri &a, const std::string &b) { - EXPECT_EQ(a.to_string(), b); + return a.to_string() == b; } +} // namespace nlohmann -static void paths(json_uri start, - const std::string &full, - const std::string &full_path, - const std::string &no_path) +void paths(json_uri start, + const std::string &full, + const std::string &full_path, + const std::string &no_path) { - EXPECT_EQ(start, full + " # "); + CHECK(start == full + " # "); auto a = start.derive("other.json"); - EXPECT_EQ(a, full_path + "/other.json # "); + CHECK(a == full_path + "/other.json # "); auto b = a.derive("base.json"); - EXPECT_EQ(b, full_path + "/base.json # "); + CHECK(b == full_path + "/base.json # "); auto c = b.derive("subdir/base.json"); - EXPECT_EQ(c, full_path + "/subdir/base.json # "); + CHECK(c == full_path + "/subdir/base.json # "); auto d = c.derive("subdir2/base.json"); - EXPECT_EQ(d, full_path + "/subdir/subdir2/base.json # "); + CHECK(d == full_path + "/subdir/subdir2/base.json # "); auto e = c.derive("/subdir2/base.json"); - EXPECT_EQ(e, no_path + "/subdir2/base.json # "); + CHECK(e == no_path + "/subdir2/base.json # "); auto f = c.derive("new.json"); - EXPECT_EQ(f, full_path + "/subdir/new.json # "); + CHECK(f == full_path + "/subdir/new.json # "); auto g = c.derive("/new.json"); - EXPECT_EQ(g, no_path + "/new.json # "); + CHECK(g == no_path + "/new.json # "); } static void pointer_plain_name(json_uri start, @@ -64,26 +57,26 @@ static void pointer_plain_name(json_uri start, const std::string &no_path) { auto a = start.derive("#/json/path"); - EXPECT_EQ(a, full + " # /json/path"); + CHECK(a == full + " # /json/path"); a = start.derive("#/json/special_%22"); - EXPECT_EQ(a, full + " # /json/special_\""); + CHECK(a == full + " # /json/special_\""); a = a.derive("#foo"); - EXPECT_EQ(a, full + " # foo"); + CHECK(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(), ""); + CHECK(a == full + " # foo/looks_like_json/poiner/but/isnt"); + CHECK(a.identifier() == "foo/looks_like_json/poiner/but/isnt"); + CHECK(a.pointer().to_string().empty()); 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(), ""); + CHECK(a == full + " # /looks_like_json/poiner/and/it/is"); + CHECK(a.pointer().to_string() == "/looks_like_json/poiner/and/it/is"); + CHECK(a.identifier().empty()); } -int main(void) +TEST_CASE("uri") { json_uri empty(""); paths(empty, @@ -101,6 +94,4 @@ int main(void) "http://json-schema.org/draft-07/schema", "http://json-schema.org/draft-07", "http://json-schema.org"); - - return errors; } diff --git a/test/utils.cpp b/test/utils.cpp new file mode 100644 index 0000000..4750616 --- /dev/null +++ b/test/utils.cpp @@ -0,0 +1,60 @@ +#include + +#include "utils.h" + +using nlohmann::json; +using nlohmann::json_uri; +using nlohmann::json_schema::default_string_format_check; +using nlohmann::json_schema::json_validator; + +static void loader(const json_uri &uri, json &schema) +{ + std::string filename = "./" + uri.path(); + std::ifstream fstream(filename); + if (!fstream.good()) + throw std::invalid_argument("could not open " + uri.url() + " tried with " + filename); + try { + fstream >> schema; + } catch (const std::exception &e) { + throw e; + } +} + +JsonValidateFixture::JsonValidateFixture() + : validator(loader, default_string_format_check) {} +json JsonValidateFixture::validate(const std::filesystem::path &schema_path, const std::filesystem::path &instance_path) +{ + json schema; + std::ifstream fstream{absolute(schema_path).string()}; + fstream >> schema; + return validate(schema, instance_path); +} +json JsonValidateFixture::validate(const json &schema, const json &instance) +{ + validator.set_root_schema(schema); + return validator.validate(instance); +} +json JsonValidateFixture::validate(const json &schema, const std::filesystem::path &instance_path) +{ + json instance; + std::ifstream fstream{absolute(instance_path).string()}; + fstream >> instance; + return validate(schema, instance); +} +json JsonValidateFixture::validate(std::string_view schema_path, std::string_view instance_path) +{ + auto path = std::filesystem::current_path() / schema_path; + return validate(path, instance_path); +} +json JsonValidateFixture::validate(const std::filesystem::path &schema_path, std::string_view instance_path) +{ + auto path = std::filesystem::current_path() / instance_path; + return validate(schema_path, path); +} +json JsonValidateFixture::validate(const std::filesystem::path &schema_path, const json &instance) +{ + json schema; + std::ifstream fstream{absolute(schema_path).string()}; + fstream >> schema; + return validate(schema, instance); +} diff --git a/test/utils.h b/test/utils.h new file mode 100644 index 0000000..45aa315 --- /dev/null +++ b/test/utils.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include + +#include + +class JsonValidateFixture +{ + nlohmann::json_schema::json_validator validator; + +public: + JsonValidateFixture(); + nlohmann::json validate(std::string_view schema_path, std::string_view instance_path); + nlohmann::json validate(const std::filesystem::path &schema_path, std::string_view instance_path); + nlohmann::json validate(const std::filesystem::path &schema_path, const std::filesystem::path &instance_path); + nlohmann::json validate(const std::filesystem::path &schema_path, const nlohmann::json &instance); + nlohmann::json validate(const nlohmann::json &schema, const std::filesystem::path &instance_path); + nlohmann::json validate(const nlohmann::json &schema, const nlohmann::json &instance); +};