Migrate tests to Catch2

Signed-off-by: Cristian Le <cristian.le@mpsd.mpg.de>
This commit is contained in:
Cristian Le 2023-11-28 10:23:21 +01:00
parent 23934ca763
commit cadf5cc226
29 changed files with 370 additions and 192 deletions

View File

@ -9,6 +9,10 @@ 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 #
]==============================================================================================]
@ -66,12 +70,12 @@ 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 CONFIG
FIND_PACKAGE_ARGS 3.4.0 CONFIG
)
list(APPEND fetch_packages Catch2)
else ()
# Try to get system installed version
find_package(Catch2 QUIET)
find_package(Catch2 3.4.0 QUIET)
if (NOT Catch2_FOUND)
# If failed fetch the desired version
FetchContent_Declare(Catch2
@ -99,30 +103,27 @@ set_target_properties(json-schema-test-suite PROPERTIES
target_link_libraries(json-schema-test-suite PRIVATE Catch2::Catch2WithMain nlohmann_json_schema_validator::validator)
catch_discover_tests(json-schema-test-suite)
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}
$<TARGET_FILE:json-schema-validate>
${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)
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)

View File

@ -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)

View File

@ -0,0 +1,19 @@
#include <filesystem>
#include <string_view>
#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers_all.hpp>
#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]")));
}

View File

@ -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)

View File

@ -0,0 +1,20 @@
#include <filesystem>
#include <string_view>
#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers_all.hpp>
#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.*")));
}

View File

@ -1,3 +0,0 @@
add_test_simple_schema(Issue::12
${CMAKE_CURRENT_SOURCE_DIR}/schema.json
${CMAKE_CURRENT_SOURCE_DIR}/instance.json)

View File

@ -0,0 +1,16 @@
#include <filesystem>
#include <string_view>
#include <catch2/catch_test_macros.hpp>
#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));
}

View File

@ -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)

View File

@ -0,0 +1,23 @@
#include <filesystem>
#include <string_view>
#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers_all.hpp>
#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));
}

View File

@ -0,0 +1,16 @@
#include <filesystem>
#include <string_view>
#include <catch2/catch_test_macros.hpp>
#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));
}

View File

@ -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)

View File

@ -0,0 +1,19 @@
#include <filesystem>
#include <string_view>
#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers_all.hpp>
#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")));
}

View File

@ -1,3 +0,0 @@
add_test_simple_schema(Issue::48
${CMAKE_CURRENT_SOURCE_DIR}/schema.json
${CMAKE_CURRENT_SOURCE_DIR}/instance.json)

View File

@ -0,0 +1,16 @@
#include <filesystem>
#include <string_view>
#include <catch2/catch_test_macros.hpp>
#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));
}

View File

@ -1,3 +0,0 @@
add_test_simple_schema(Issue::54
${CMAKE_CURRENT_SOURCE_DIR}/schema.json
${CMAKE_CURRENT_SOURCE_DIR}/instance.json)

View File

@ -0,0 +1,16 @@
#include <filesystem>
#include <string_view>
#include <catch2/catch_test_macros.hpp>
#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));
}

View File

@ -1,3 +0,0 @@
add_test_simple_schema(Issue::75
${CMAKE_CURRENT_SOURCE_DIR}/schema.json
${CMAKE_CURRENT_SOURCE_DIR}/instance.json)

View File

@ -0,0 +1,16 @@
#include <filesystem>
#include <string_view>
#include <catch2/catch_test_macros.hpp>
#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));
}

View File

@ -1,3 +0,0 @@
add_test_simple_schema(Issue::9
${CMAKE_CURRENT_SOURCE_DIR}/base.json
${CMAKE_CURRENT_SOURCE_DIR}/instance.json)

View File

@ -0,0 +1,16 @@
#include <filesystem>
#include <string_view>
#include <catch2/catch_test_macros.hpp>
#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));
}

View File

@ -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})

View File

@ -1,55 +0,0 @@
#include <nlohmann/json-schema.hpp>
#include <fstream>
#include <iostream>
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;
}

View File

@ -0,0 +1,37 @@
#include <filesystem>
#include <string_view>
#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers_all.hpp>
#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);
}

View File

@ -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)

View File

@ -0,0 +1,19 @@
#include <filesystem>
#include <string_view>
#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers_all.hpp>
#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")));
}

View File

@ -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

View File

@ -6,56 +6,49 @@
* SPDX-License-Identifier: MIT
*
*/
#include <cstdlib>
#include <nlohmann/json-schema.hpp>
#include <iostream>
#include <catch2/catch_test_macros.hpp>
#include <nlohmann/json-schema.hpp>
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++;
}
bool operator==(const json_uri &a, const std::string &b)
{
return a.to_string() == b;
}
} // namespace nlohmann
static void EXPECT_EQ(const nlohmann::json_uri &a, const std::string &b)
void paths(json_uri start,
const std::string &full,
const std::string &full_path,
const std::string &no_path)
{
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 + " # ");
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;
}

60
test/utils.cpp Normal file
View File

@ -0,0 +1,60 @@
#include <fstream>
#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);
}

20
test/utils.h Normal file
View File

@ -0,0 +1,20 @@
#pragma once
#include <filesystem>
#include <string>
#include <nlohmann/json-schema.hpp>
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);
};