From ab53944ed4e0b9b7298e90592111fe0844a6c59f Mon Sep 17 00:00:00 2001 From: Sakars Date: Mon, 30 Dec 2024 19:25:11 +0000 Subject: [PATCH 1/9] Test tweaks --- include/LinkedSchema.h | 2 +- include/SchemaResource.h | 16 +-- src/LinkedSchema.cpp | 22 ++-- src/main.cpp | 6 +- tests/output_tests/test_hotel.cpp | 2 +- .../output_tests/test_lengthLimitedString.cpp | 13 +- tests/output_tests/test_myself.cpp | 2 +- .../output_tests/test_regexMatcherString.cpp | 13 +- tests/output_tests/test_simpleString.cpp | 10 +- .../output_tests/test_stringNumberVariant.cpp | 3 +- tests/output_tests/test_true.cpp | 2 +- tests/test_CodeBlock.cpp | 59 ++++++--- tests/test_DraftRecognisedDocument.cpp | 62 +++++----- tests/test_IdentifiableSchema.cpp | 113 +++++++++--------- tests/test_LinkedSchema.cpp | 12 +- tests/test_SchemaResource.cpp | 21 ++-- tests/test_SelfRef.cpp | 6 +- 17 files changed, 203 insertions(+), 161 deletions(-) diff --git a/include/LinkedSchema.h b/include/LinkedSchema.h index 2ded2ea..dc84dca 100644 --- a/include/LinkedSchema.h +++ b/include/LinkedSchema.h @@ -98,7 +98,7 @@ extern std::map (*)(const nlohmann::json&, /// schemas and a map of idendifiers to indices to the schemas via vector std::tuple>, std::map> -deconstructUnresolvedSchemaMap(SetMap&& setMap); +deconstructSchemaResourceMap(SetMap&& setMap); /// @brief Resolves the dependencies of a set map of schemas /// @param setMap The set map of schemas diff --git a/include/SchemaResource.h b/include/SchemaResource.h index 3536380..766486c 100644 --- a/include/SchemaResource.h +++ b/include/SchemaResource.h @@ -113,17 +113,17 @@ class SchemaResource { } return setMap; } catch (const std::exception& e) { - std::cerr << "Error caught in UnresolvedSchema::generateSetMap:\n"; + std::cerr << "Error caught in SchemaResource::generateSetMap:\n"; throw e; } } - static void dumpSchemas(SetMap& unresolvedSchemas, + static void dumpSchemas(SetMap& schemaResources, std::filesystem::path outputDirectory = ".") { - nlohmann::json unresolvedSchemaDump = nlohmann::json::object(); - for (const auto& [uris, schema] : unresolvedSchemas) { + nlohmann::json schemaResourceDump = nlohmann::json::object(); + for (const auto& [uris, schema] : schemaResources) { auto& baseUriList = - unresolvedSchemaDump[schema.get().baseUri_.toString().value()]; + schemaResourceDump[schema.get().baseUri_.toString().value()]; baseUriList[schema.get().pointer_.toFragment()] = nlohmann::json::array(); for (const auto& uri : uris.get()) { baseUriList[schema.get().pointer_.toFragment()].push_back( @@ -131,9 +131,9 @@ class SchemaResource { uri.getFragment().value_or("")})); } } - std::ofstream unresolvedDump(outputDirectory / "unresolved.dump.json"); - unresolvedDump << unresolvedSchemaDump.dump(2); - unresolvedDump.close(); + std::ofstream resourceDump(outputDirectory / "resource.dump.json"); + resourceDump << schemaResourceDump.dump(2); + resourceDump.close(); } }; diff --git a/src/LinkedSchema.cpp b/src/LinkedSchema.cpp index c5aa30e..ba6adfa 100644 --- a/src/LinkedSchema.cpp +++ b/src/LinkedSchema.cpp @@ -15,17 +15,17 @@ std::map>, std::map> -deconstructUnresolvedSchemaMap(SetMap&& setMap) { +deconstructSchemaResourceMap(SetMap&& setMap) { auto map = setMap.extract(); - std::vector> unresolvedSchemas; + std::vector> schemaResources; std::map schemaIndices; for (auto& [keys, value] : map) { for (const auto& key : keys) { - schemaIndices[key] = unresolvedSchemas.size(); + schemaIndices[key] = schemaResources.size(); } - unresolvedSchemas.push_back(std::move(value)); + schemaResources.push_back(std::move(value)); } - return {std::move(unresolvedSchemas), std::move(schemaIndices)}; + return {std::move(schemaResources), std::move(schemaIndices)}; } std::vector> @@ -41,8 +41,8 @@ resolveDependencies(SetMap&& setMap, return normalized; }(); try { - auto [unresolvedSchemas, schemaIndices] = - deconstructUnresolvedSchemaMap(std::move(setMap)); + auto [schemaResources, schemaIndices] = + deconstructSchemaResourceMap(std::move(setMap)); std::set buildableRequiredSchemas; @@ -57,14 +57,14 @@ resolveDependencies(SetMap&& setMap, std::set builtRequiredSchemas; std::vector> dependencyList( - unresolvedSchemas.size()); + schemaResources.size()); while (!buildableRequiredSchemas.empty()) { auto schemaIdx = *buildableRequiredSchemas.begin(); - auto& schema = *unresolvedSchemas[schemaIdx]; + auto& schema = *schemaResources[schemaIdx]; buildableRequiredSchemas.erase(schemaIdx); builtRequiredSchemas.insert(schemaIdx); - auto dependencies = linkers[unresolvedSchemas[schemaIdx]->draft_]( + auto dependencies = linkers[schemaResources[schemaIdx]->draft_]( schema.json_.get(), schema.baseUri_, schema.pointer_); std::map depIndices_; for (const auto& dep : dependencies) { @@ -109,7 +109,7 @@ resolveDependencies(SetMap&& setMap, std::vector> shrunkSchemas; for (const auto builtIdx : builtRequiredSchemas) { - shrunkSchemas.push_back(std::move(unresolvedSchemas[builtIdx])); + shrunkSchemas.push_back(std::move(schemaResources[builtIdx])); } std::vector> linkedSchemas; diff --git a/src/main.cpp b/src/main.cpp index ddfdc50..9f5cf67 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -143,13 +143,13 @@ int main(int argc, char* argv[]) { std::vector documents = loadDocuments(inputFiles); std::vector draftDocs = DraftRecognisedDocument::performDraftRecognition(std::move(documents)); - auto unresolvedSchemas = SchemaResource::generateSetMap(draftDocs); + auto schemaResources = SchemaResource::generateSetMap(draftDocs); if (dumpSchemas) - SchemaResource::dumpSchemas(unresolvedSchemas, outputDirectory); + SchemaResource::dumpSchemas(schemaResources, outputDirectory); auto linkedSchemas = - resolveDependencies(std::move(unresolvedSchemas), requiredReferences); + resolveDependencies(std::move(schemaResources), requiredReferences); if (dumpSchemas) LinkedSchema::dumpSchemas(linkedSchemas, outputDirectory); diff --git a/tests/output_tests/test_hotel.cpp b/tests/output_tests/test_hotel.cpp index a0c0337..aa69f6b 100644 --- a/tests/output_tests/test_hotel.cpp +++ b/tests/output_tests/test_hotel.cpp @@ -1,7 +1,7 @@ #include "Hotel.h" #include -TEST_CASE("Test hotel") { +TEST_CASE("Test hotel", "[Output][Hotel]") { nlohmann::json json = R"({ "id": "00000000-0000-0000-0000-000000000000", "name": "Hotel California", diff --git a/tests/output_tests/test_lengthLimitedString.cpp b/tests/output_tests/test_lengthLimitedString.cpp index c62a8da..36af59c 100644 --- a/tests/output_tests/test_lengthLimitedString.cpp +++ b/tests/output_tests/test_lengthLimitedString.cpp @@ -5,7 +5,7 @@ #include "LengthLimitedString.h" -TEST_CASE("Static lengthLimitedString tests") { +TEST_CASE("Static lengthLimitedString tests", "[Output][LengthLimitedString]") { STATIC_REQUIRE(std::is_same_v); using ConstructType = decltype(JSOG::LengthLimitedString::construct); @@ -20,7 +20,8 @@ TEST_CASE("Static lengthLimitedString tests") { STATIC_REQUIRE(std::is_same_v); } -TEST_CASE("Check LengthLimitedString::construct") { +TEST_CASE("Check LengthLimitedString::construct", + "[Output][LengthLimitedString]") { SECTION("Valid size strings") { std::string str = GENERATE(take(100, randomString(10, 5))); INFO(str); @@ -51,7 +52,8 @@ TEST_CASE("Check LengthLimitedString::construct") { } } -TEST_CASE("Check LengthLimitedString::rawExport") { +TEST_CASE("Check LengthLimitedString::rawExport", + "[Output][LengthLimitedString]") { std::string str = GENERATE(take(100, randomString(10, 5))); auto result = JSOG::LengthLimitedString::rawExport(str); CAPTURE(str); @@ -60,13 +62,14 @@ TEST_CASE("Check LengthLimitedString::rawExport") { REQUIRE(result == str); } -TEST_CASE("Check LengthLimitedString::validate") { +TEST_CASE("Check LengthLimitedString::validate", + "[Output][LengthLimitedString]") { std::string str = GENERATE(take(100, randomString(10, 5))); CAPTURE(str); REQUIRE(JSOG::LengthLimitedString::validate(str)); } -TEST_CASE("LengthLimitedString::json") { +TEST_CASE("LengthLimitedString::json", "[Output][LengthLimitedString]") { SECTION("Valid strings") { std::string str = GENERATE(take(100, randomString(10, 5))); auto jsonopt = JSOG::LengthLimitedString::json(str); diff --git a/tests/output_tests/test_myself.cpp b/tests/output_tests/test_myself.cpp index 691b2d0..6e5d903 100644 --- a/tests/output_tests/test_myself.cpp +++ b/tests/output_tests/test_myself.cpp @@ -2,7 +2,7 @@ #include TEST_CASE("Myself: Static checks for whether self-referential types can exist", - "[myself]") { + "[Output][myself]") { JSOG::Myself::Myself myself; myself.object_ = std::make_unique(); myself.additionalProperties["key"] = "value"; diff --git a/tests/output_tests/test_regexMatcherString.cpp b/tests/output_tests/test_regexMatcherString.cpp index 62a434a..203f39f 100644 --- a/tests/output_tests/test_regexMatcherString.cpp +++ b/tests/output_tests/test_regexMatcherString.cpp @@ -2,7 +2,7 @@ #include "randomString.h" #include -TEST_CASE("Static RegexMatcherString tests") { +TEST_CASE("Static RegexMatcherString tests", "[Output][RegexMatcherString]") { STATIC_REQUIRE(std::is_same_v); using ConstructType = decltype(JSOG::RegexMatcherString::construct); @@ -17,7 +17,8 @@ TEST_CASE("Static RegexMatcherString tests") { STATIC_REQUIRE(std::is_same_v); } -TEST_CASE("Check RegexMatcherString::construct") { +TEST_CASE("Check RegexMatcherString::construct", + "[Output][RegexMatcherString]") { SECTION("Valid strings") { std::string str = GENERATE(take(100, randomString())); for (auto& c : str) { @@ -47,7 +48,8 @@ TEST_CASE("Check RegexMatcherString::construct") { } } -TEST_CASE("Check RegexMatcherString::rawExport") { +TEST_CASE("Check RegexMatcherString::rawExport", + "[Output][RegexMatcherString]") { std::string str = GENERATE(take(100, randomString())); auto result = JSOG::RegexMatcherString::rawExport(str); CAPTURE(str); @@ -56,7 +58,8 @@ TEST_CASE("Check RegexMatcherString::rawExport") { REQUIRE(result == str); } -TEST_CASE("Check RegexMatcherString::validate") { +TEST_CASE("Check RegexMatcherString::validate", + "[Output][RegexMatcherString]") { SECTION("Valid strings") { std::string str = GENERATE(take(100, randomString())); for (auto& c : str) { @@ -80,7 +83,7 @@ TEST_CASE("Check RegexMatcherString::validate") { } } -TEST_CASE("RegexMatcherString::json") { +TEST_CASE("RegexMatcherString::json", "[Output][RegexMatcherString]") { SECTION("Valid strings") { std::string str = GENERATE(take(100, randomString())); for (auto& c : str) { diff --git a/tests/output_tests/test_simpleString.cpp b/tests/output_tests/test_simpleString.cpp index 4e47937..90edc04 100644 --- a/tests/output_tests/test_simpleString.cpp +++ b/tests/output_tests/test_simpleString.cpp @@ -9,7 +9,7 @@ #include #include -TEST_CASE("Simple String static tests", "[SimpleString]") { +TEST_CASE("Simple String static tests", "[Output][SimpleString]") { STATIC_REQUIRE(std::is_same_v); using ConstructType = decltype(JSOG::SimpleString::construct); @@ -24,7 +24,7 @@ TEST_CASE("Simple String static tests", "[SimpleString]") { STATIC_REQUIRE(std::is_same_v); } -TEST_CASE("Check SimpleString::construct", "[SimpleString]") { +TEST_CASE("Check SimpleString::construct", "[Output][SimpleString]") { std::string str = GENERATE(take(100, randomString())); nlohmann::json json = str; auto result = JSOG::SimpleString::construct(json); @@ -33,7 +33,7 @@ TEST_CASE("Check SimpleString::construct", "[SimpleString]") { REQUIRE(result.value() == str); } -TEST_CASE("Check SimpleString::rawExport", "[SimpleString]") { +TEST_CASE("Check SimpleString::rawExport", "[Output][SimpleString]") { std::string str = GENERATE(take(100, randomString())); auto result = JSOG::SimpleString::rawExport(str); CAPTURE(str); @@ -42,13 +42,13 @@ TEST_CASE("Check SimpleString::rawExport", "[SimpleString]") { REQUIRE(result == str); } -TEST_CASE("Check SimpleString::validate", "[SimpleString]") { +TEST_CASE("Check SimpleString::validate", "[Output][SimpleString]") { std::string str = GENERATE(take(100, randomString())); CAPTURE(str); REQUIRE(JSOG::SimpleString::validate(str)); } -TEST_CASE("SimpleString::json", "[SimpleString]") { +TEST_CASE("SimpleString::json", "[Output][SimpleString]") { std::string str = GENERATE(take(100, randomString())); nlohmann::json json = JSOG::SimpleString::json(str).value(); CAPTURE(str); diff --git a/tests/output_tests/test_stringNumberVariant.cpp b/tests/output_tests/test_stringNumberVariant.cpp index b288d78..a4b3bff 100644 --- a/tests/output_tests/test_stringNumberVariant.cpp +++ b/tests/output_tests/test_stringNumberVariant.cpp @@ -4,7 +4,8 @@ #include "StringNumberVariant.h" -TEST_CASE("Static StringNumberVariant checks") { +TEST_CASE("Static StringNumberVariant checks", + "[Output][StringNumberVariant]") { STATIC_CHECK((std::is_same_v> || std::is_same_v -TEST_CASE("True static tests", "[True]") { +TEST_CASE("True static tests", "[Output][True]") { STATIC_REQUIRE(std::is_same_v); using ConstructType = decltype(JSOG::True::construct); diff --git a/tests/test_CodeBlock.cpp b/tests/test_CodeBlock.cpp index 648adaa..e98f678 100644 --- a/tests/test_CodeBlock.cpp +++ b/tests/test_CodeBlock.cpp @@ -2,26 +2,53 @@ #include "CodeBlock.h" -TEST_CASE("CodeBlock") -{ +TEST_CASE("CodeBlock base test", "[CodeBlock]") { CodeBlock block; - block << "Hello, World!" - << CodeBlock::inc - << "Goodbye, World!" - << CodeBlock::dec - << "Hello, World!"; + block << "Hello, World!" << CodeBlock::inc << "Goodbye, World!" + << CodeBlock::dec << "Hello, World!"; REQUIRE(block.str() == "Hello, World!\n Goodbye, World!\nHello, World!\n"); } -TEST_CASE("CodeBlock with custom indent") -{ +TEST_CASE("CodeBlock with custom indent", "[CodeBlock]") { CodeBlock block(" "); - block << "Hello, World!" - << CodeBlock::inc - << "Goodbye, World!" - << CodeBlock::inc - << "Goodbye, World!" - << CodeBlock::dec + block << "Hello, World!" << CodeBlock::inc << "Goodbye, World!" + << CodeBlock::inc << "Goodbye, World!" << CodeBlock::dec << "Hello, World!"; - REQUIRE(block.str() == "Hello, World!\n Goodbye, World!\n Goodbye, World!\n Hello, World!\n"); + REQUIRE(block.str() == "Hello, World!\n Goodbye, World!\n Goodbye, " + "World!\n Hello, World!\n"); +} + +TEST_CASE("CodeBlock with discard", "[CodeBlock]") { + CodeBlock block; + block.indent = "x"; + block << "Hello, World!" << CodeBlock::inc << "Goodbye, World!" + << CodeBlock::dis << "Hello, World!"; + REQUIRE(block.str() == "Hello, World!\nxGoodbye, World!Hello, World!\n"); +} + +TEST_CASE("CodeBlock with multiple discards", "[CodeBlock]") { + CodeBlock block; + block.indent = "x"; + block << "Hello, World!" << CodeBlock::inc << "Goodbye, World!" + << CodeBlock::dis << "Hello, World!" << CodeBlock::dis + << "Goodbye World!"; + REQUIRE(block.str() == "Hello, World!\nxGoodbye, World!Hello, World!Goodbye " + "World!\n"); +} + +TEST_CASE("Indent blocks function as expected", "[CodeBlock]") { + CodeBlock block; + block.indent = " "; + block << "Hello, World!"; + { + Indent indent(block); + block << "Goodbye, World!"; + { + Indent indent(block); + block << "Goodbye, World!"; + } + block << "Hello, World!"; + } + REQUIRE(block.str() == "Hello, World!\n Goodbye, World!\n Goodbye, " + "World!\n Hello, World!\n"); } diff --git a/tests/test_DraftRecognisedDocument.cpp b/tests/test_DraftRecognisedDocument.cpp index 2ab28b2..aed19da 100644 --- a/tests/test_DraftRecognisedDocument.cpp +++ b/tests/test_DraftRecognisedDocument.cpp @@ -9,32 +9,40 @@ TEST_CASE("DraftRecognisedDocument construction", "[DraftRecognisedDocument]") { } )"_json; UriWrapper fileUri("file://test.json"); - SECTION("Pure construction") { - DraftRecognisedDocument doc{nlohmann::json(json), UriWrapper(fileUri)}; - REQUIRE(doc.draft_ == Draft::DRAFT_07); - REQUIRE(doc.fileUri_ == fileUri); - REQUIRE(doc.json_ == json); - } - SECTION("Construction through Document") { - Document doc(std::move(json), std::move(fileUri)); - DraftRecognisedDocument doc_(std::move(doc)); - REQUIRE(doc_.draft_ == Draft::DRAFT_07); - REQUIRE(doc_.fileUri_ == "file://test.json"); - REQUIRE(doc_.json_.is_object()); - REQUIRE(doc_.json_["title"] == "Test Schema"); - REQUIRE(doc_.json_["$schema"] == "http://json-schema.org/draft-07/schema#"); - } + DraftRecognisedDocument doc{nlohmann::json(json), UriWrapper(fileUri)}; + REQUIRE(doc.draft_ == Draft::DRAFT_07); + REQUIRE(doc.fileUri_ == fileUri); + REQUIRE(doc.json_ == json); +} - SECTION("Construction through Document with file") { - std::filesystem::path path = "samples/document_1.json"; - Document doc(path); - DraftRecognisedDocument doc_(std::move(doc)); - REQUIRE(doc_.draft_ == Draft::DRAFT_07); - REQUIRE(doc_.fileUri_ == - "file://" + std::filesystem::absolute(path).string()); - REQUIRE(doc_.json_.is_object()); - REQUIRE(doc_.json_["title"] == "Test Schema"); - REQUIRE(doc_.json_["$schema"] == "http://json-schema.org/draft-07/schema#"); - } -} \ No newline at end of file +TEST_CASE("DraftRecognisedDocument construction through Document", + "[DraftRecognisedDocument][Document]") { + nlohmann::json json = R"( +{ +"$schema": "http://json-schema.org/draft-07/schema#", +"title": "Test Schema" +} +)"_json; + UriWrapper fileUri("file://test.json"); + Document doc(std::move(json), std::move(fileUri)); + DraftRecognisedDocument doc_(std::move(doc)); + REQUIRE(doc_.draft_ == Draft::DRAFT_07); + REQUIRE(doc_.fileUri_ == "file://test.json"); + REQUIRE(doc_.json_.is_object()); + REQUIRE(doc_.json_["title"] == "Test Schema"); + REQUIRE(doc_.json_["$schema"] == "http://json-schema.org/draft-07/schema#"); +} + +TEST_CASE("DraftRecognisedDocument construction from file", + "[DraftRecognisedDocument][Document]") { + std::filesystem::path path = "samples/document_1.json"; + Document doc(path); + DraftRecognisedDocument doc_(std::move(doc)); + REQUIRE(doc_.draft_ == Draft::DRAFT_07); + REQUIRE(doc_.fileUri_ == + "file://" + std::filesystem::absolute(path).string()); + REQUIRE(doc_.json_.is_object()); + REQUIRE(doc_.json_["title"] == "Test Schema"); + REQUIRE(doc_.json_["$schema"] == "http://json-schema.org/draft-07/schema#"); +} diff --git a/tests/test_IdentifiableSchema.cpp b/tests/test_IdentifiableSchema.cpp index 3347369..48c8667 100644 --- a/tests/test_IdentifiableSchema.cpp +++ b/tests/test_IdentifiableSchema.cpp @@ -4,9 +4,8 @@ #include "LinkedSchema.h" #include "UriWrapper.h" -TEST_CASE("IdentifiableSchema") { - SECTION("transition") { - const auto json = R"( +TEST_CASE("IdentifiableSchema transition", "[IdentifiableSchema]") { + const auto json = R"( { "$id": "https://example.com/schema", "title": "Schema", @@ -16,35 +15,36 @@ TEST_CASE("IdentifiableSchema") { } } })"_json; - const UriWrapper baseUri("https://example.com/schema"); - const JSONPointer pointer = JSONPointer(); - const Draft draft = Draft::DRAFT_07; - std::vector> linkedSchemas; - linkedSchemas.emplace_back(std::make_unique( - json["properties"]["a"], baseUri, pointer / "properties" / "a", draft, - std::map{})); - linkedSchemas.emplace_back(std::make_unique( - json, baseUri, pointer, draft, - std::map{ - {baseUri.withPointer(pointer / "properties" / "a"), 0}})); - auto identifiableSchemas = - IdentifiableSchema::transition(std::move(linkedSchemas)); - REQUIRE(identifiableSchemas.size() == 2); - REQUIRE(identifiableSchemas[1].dependencies_.contains( - baseUri.withPointer(pointer / "properties" / "a"))); - REQUIRE(identifiableSchemas[1].dependencies_.at( - baseUri.withPointer(pointer / "properties" / "a")) == 0); - // Identifiers are unique + const UriWrapper baseUri("https://example.com/schema"); + const JSONPointer pointer = JSONPointer(); + const Draft draft = Draft::DRAFT_07; + std::vector> linkedSchemas; + linkedSchemas.emplace_back(std::make_unique( + json["properties"]["a"], baseUri, pointer / "properties" / "a", draft, + std::map{})); + linkedSchemas.emplace_back(std::make_unique( + json, baseUri, pointer, draft, + std::map{ + {baseUri.withPointer(pointer / "properties" / "a"), 0}})); + auto identifiableSchemas = + IdentifiableSchema::transition(std::move(linkedSchemas)); + REQUIRE(identifiableSchemas.size() == 2); + REQUIRE(identifiableSchemas[1].dependencies_.contains( + baseUri.withPointer(pointer / "properties" / "a"))); + REQUIRE(identifiableSchemas[1].dependencies_.at( + baseUri.withPointer(pointer / "properties" / "a")) == 0); + // Identifiers are unique - REQUIRE(identifiableSchemas[1].identifier_ != - identifiableSchemas[0].identifier_); + REQUIRE(identifiableSchemas[1].identifier_ != + identifiableSchemas[0].identifier_); - REQUIRE(identifiableSchemas[0].identifier_ == "Schema"); - REQUIRE(identifiableSchemas[1].identifier_ == "Schema0"); - } + REQUIRE(identifiableSchemas[0].identifier_ == "Schema"); + REQUIRE(identifiableSchemas[1].identifier_ == "Schema0"); +} - SECTION("transition with preferred identifiers") { - const auto json = R"( +TEST_CASE("IdentifiableSchema transition with preferred identifiers", + "[IdentifiableSchema]") { + const auto json = R"( { "$id": "https://example.com/schema", "title": "Schema", @@ -54,35 +54,34 @@ TEST_CASE("IdentifiableSchema") { } } })"_json; - const UriWrapper baseUri("https://example.com/schema"); - const JSONPointer pointer = JSONPointer(); - const Draft draft = Draft::DRAFT_07; - std::vector> linkedSchemas; - linkedSchemas.emplace_back(std::make_unique( - json["properties"]["a"], baseUri, pointer / "properties" / "a", draft, - std::map{})); - linkedSchemas.emplace_back(std::make_unique( - json, baseUri, pointer, draft, - std::map{ - {baseUri.withPointer(pointer / "properties" / "a"), 0}})); - std::map preferredIdentifiers = { - {baseUri.withPointer(pointer), "MySchema"}, - {baseUri.withPointer(pointer / "properties" / "a"), "MySchemaA"}}; + const UriWrapper baseUri("https://example.com/schema"); + const JSONPointer pointer = JSONPointer(); + const Draft draft = Draft::DRAFT_07; + std::vector> linkedSchemas; + linkedSchemas.emplace_back(std::make_unique( + json["properties"]["a"], baseUri, pointer / "properties" / "a", draft, + std::map{})); + linkedSchemas.emplace_back(std::make_unique( + json, baseUri, pointer, draft, + std::map{ + {baseUri.withPointer(pointer / "properties" / "a"), 0}})); + std::map preferredIdentifiers = { + {baseUri.withPointer(pointer), "MySchema"}, + {baseUri.withPointer(pointer / "properties" / "a"), "MySchemaA"}}; - auto identifiableSchemas = IdentifiableSchema::transition( - std::move(linkedSchemas), preferredIdentifiers); + auto identifiableSchemas = IdentifiableSchema::transition( + std::move(linkedSchemas), preferredIdentifiers); - REQUIRE(identifiableSchemas.size() == 2); - REQUIRE(identifiableSchemas[0].dependencies_.contains( - baseUri.withPointer(pointer / "properties" / "a"))); - REQUIRE(identifiableSchemas[0].dependencies_.at( - baseUri.withPointer(pointer / "properties" / "a")) == 0); - // Identifiers are unique + REQUIRE(identifiableSchemas.size() == 2); + REQUIRE(identifiableSchemas[0].dependencies_.contains( + baseUri.withPointer(pointer / "properties" / "a"))); + REQUIRE(identifiableSchemas[0].dependencies_.at( + baseUri.withPointer(pointer / "properties" / "a")) == 0); + // Identifiers are unique - REQUIRE(identifiableSchemas[1].identifier_ != - identifiableSchemas[0].identifier_); + REQUIRE(identifiableSchemas[1].identifier_ != + identifiableSchemas[0].identifier_); - REQUIRE(identifiableSchemas[0].identifier_ == "MySchema"); - REQUIRE(identifiableSchemas[1].identifier_ == "MySchemaA"); - } -} \ No newline at end of file + REQUIRE(identifiableSchemas[0].identifier_ == "MySchema"); + REQUIRE(identifiableSchemas[1].identifier_ == "MySchemaA"); +} diff --git a/tests/test_LinkedSchema.cpp b/tests/test_LinkedSchema.cpp index 80b0fb4..8b2c0fc 100644 --- a/tests/test_LinkedSchema.cpp +++ b/tests/test_LinkedSchema.cpp @@ -3,7 +3,7 @@ #include "LinkedSchema.h" #include -SCENARIO("Buildable Schema Draft07 constructs correct deps", +SCENARIO("Buildable Schema Draft07 constructs correct dependencies", "[Draft07][LinkedSchema]") { // FAIL("Refactors needed"); WHEN("Schema has a ref in properties") { @@ -175,7 +175,7 @@ SCENARIO("Multi-file Draft07 reference resolution", "[Draft07][LinkedSchema]") { } SCENARIO("Full pipeline run up to LinkedSchema", - "[Draft07][filesystem][LinkedSchema][DraftRecognisedDocument][" + "[Draft07][LinkedSchema][DraftRecognisedDocument][" "Document]") { GIVEN("A sample case with 2 documents") { std::vector files{"samples/document_1.json", @@ -185,12 +185,12 @@ SCENARIO("Full pipeline run up to LinkedSchema", auto recognised = DraftRecognisedDocument::performDraftRecognition(std::move(documents)); REQUIRE(recognised.size() == 2); - auto unresolvedSchecmas = + auto schemaResources = SchemaResource::generateSetMap(std::move(recognised)); - REQUIRE(unresolvedSchecmas.getSet().size() == 5); + REQUIRE(schemaResources.getSet().size() == 5); const auto doesSetContainUri = [&](const UriWrapper& uri) { - for (const auto& value : unresolvedSchecmas.getSet()) { + for (const auto& value : schemaResources.getSet()) { if (value->baseUri_.withPointer(value->pointer_) == uri) { return true; } @@ -210,7 +210,7 @@ SCENARIO("Full pipeline run up to LinkedSchema", std::set refs; refs.insert(UriWrapper("file://samples/document_2.json")); - auto resolved = resolveDependencies(std::move(unresolvedSchecmas), refs); + auto resolved = resolveDependencies(std::move(schemaResources), refs); THEN("The references are resolved") { REQUIRE(resolved.size() == 4); const auto uri = diff --git a/tests/test_SchemaResource.cpp b/tests/test_SchemaResource.cpp index 09078bd..09d33b5 100644 --- a/tests/test_SchemaResource.cpp +++ b/tests/test_SchemaResource.cpp @@ -1,7 +1,8 @@ #include "SchemaResource.h" #include -TEST_CASE("UnresolvedSchema construction", "[UnresolvedSchema]") { +TEST_CASE("Schema Resource construction", + "[SchemaResource][DraftRecognisedDocument][Document]") { SECTION("Construction from atoms") { nlohmann::json json = R"( { @@ -43,7 +44,8 @@ TEST_CASE("UnresolvedSchema construction", "[UnresolvedSchema]") { } } -TEST_CASE("Unresolved Schema setmap construction", "[UnresolvedSchema]") { +TEST_CASE("Schema Resource setmap construction", + "[SchemaResource][DraftRecognisedDocument]") { nlohmann::json json = R"( { "$schema": "http://json-schema.org/draft-07/schema#", @@ -54,8 +56,8 @@ TEST_CASE("Unresolved Schema setmap construction", "[UnresolvedSchema]") { JSONPointer pointer; std::vector drafts{ DraftRecognisedDocument{nlohmann::json(json), UriWrapper(fileUri)}}; - auto unresolvedMap = SchemaResource::generateSetMap(drafts); - auto extracted = unresolvedMap.extract(); + auto resourceMap = SchemaResource::generateSetMap(drafts); + auto extracted = resourceMap.extract(); REQUIRE(extracted.size() == 1); auto& [keys, value] = extracted[0]; REQUIRE(keys.size() == 1); @@ -66,18 +68,17 @@ TEST_CASE("Unresolved Schema setmap construction", "[UnresolvedSchema]") { } TEST_CASE("Full pipeline run up to LinkedSchema", - "[Draft07][filesystem][LinkedSchema][DraftRecognisedDocument][" - "Document]") { + "[Draft07][LinkedSchema][DraftRecognisedDocument][" + "Document][SchemaResource]") { std::vector files{"./samples/document_1.json", "./samples/document_2.json"}; auto documents = loadDocuments(files); auto recognised = DraftRecognisedDocument::performDraftRecognition(std::move(documents)); - auto unresolvedSchecmas = - SchemaResource::generateSetMap(std::move(recognised)); - REQUIRE(unresolvedSchecmas.getSet().size() == 5); + auto schemaResources = SchemaResource::generateSetMap(std::move(recognised)); + REQUIRE(schemaResources.getSet().size() == 5); const auto doesSetContainUri = [&](const UriWrapper& uri) { - for (const auto& value : unresolvedSchecmas.getSet()) { + for (const auto& value : schemaResources.getSet()) { if (value->baseUri_.withPointer(value->pointer_) == uri) { return true; } diff --git a/tests/test_SelfRef.cpp b/tests/test_SelfRef.cpp index 5dacdf2..b10c71b 100644 --- a/tests/test_SelfRef.cpp +++ b/tests/test_SelfRef.cpp @@ -25,11 +25,11 @@ TEST_CASE("Self referencial code generation doesn't crash", "[selfref]") { })"_json; std::vector documents = { DraftRecognisedDocument(Document(std::move(selfRef), "jsog://SelfRef"))}; - auto unresolvedSchemas = SchemaResource::generateSetMap(documents); - REQUIRE(unresolvedSchemas.getSet().size() == + auto schemaResources = SchemaResource::generateSetMap(documents); + REQUIRE(schemaResources.getSet().size() == 3); // the schema, properties, object auto linkedSchemas = resolveDependencies( - std::move(unresolvedSchemas), std::set{"jsog://SelfRef"}); + std::move(schemaResources), std::set{"jsog://SelfRef"}); REQUIRE(linkedSchemas.size() == 2); auto identifiableSchemas = IdentifiableSchema::transition(std::move(linkedSchemas)); From 7f35c49298a9443e730b8d9b5343e9090508a0b9 Mon Sep 17 00:00:00 2001 From: Sakars Date: Mon, 30 Dec 2024 23:50:05 +0000 Subject: [PATCH 2/9] More tests and fixes --- src/SyncedSchema/ArrayProperties.cpp | 50 +++++++++++++++++++----- tests/output_tests/test_arrayTuple.cpp | 20 ++++++++++ tests/schemas_to_compile/arrayTuple.json | 16 ++++++++ tests/test_CodeBlock.cpp | 9 +++-- 4 files changed, 82 insertions(+), 13 deletions(-) create mode 100644 tests/output_tests/test_arrayTuple.cpp create mode 100644 tests/schemas_to_compile/arrayTuple.json diff --git a/src/SyncedSchema/ArrayProperties.cpp b/src/SyncedSchema/ArrayProperties.cpp index 0ad234f..a7aa9fc 100644 --- a/src/SyncedSchema/ArrayProperties.cpp +++ b/src/SyncedSchema/ArrayProperties.cpp @@ -110,7 +110,12 @@ ArrayProperties::arrayClassDefinition(const CodeProperties& codeProperties, } } } - BLOCK << std::format("std::vector<{}> items;", items_.get().getType()); + std::string itemsType = items_.get().getType(); + // Avoid bool type, as bool vectors have a different interface + if (itemsType == "bool") { + itemsType = "unsigned char"; + } + BLOCK << std::format("std::vector<{}> items;", itemsType); BLOCK << CodeBlock::dec << "public:" << CodeBlock::inc; BLOCK << "template "; @@ -125,11 +130,12 @@ ArrayProperties::arrayClassDefinition(const CodeProperties& codeProperties, minItems_.has_value() && i < minItems_.value()) { BLOCK << std::format("return item{};", i); } else { - BLOCK << std::format("if (item{}.has_value()) {{", i) - << CodeBlock::inc; + // BLOCK << std::format("if (item{}.has_value()) {{", i) + // << CodeBlock::inc; + // BLOCK << std::format("return item{}.value();", i); + // BLOCK << CodeBlock::dec << "}"; + BLOCK << std::format("return item{};", i); } - BLOCK << std::format("return item{}.value();", i); - BLOCK << CodeBlock::dec << "}"; } BLOCK << CodeBlock::dec << CodeBlock::dis << "} else "; } @@ -150,7 +156,33 @@ ArrayProperties::arrayClassDefinition(const CodeProperties& codeProperties, "std::to_string(N) + \" out of range\");"; } BLOCK << CodeBlock::dec << "}"; - BLOCK << std::format("inline {}& get(size_t n) {{", items_.get().getType()); + + std::set arrayItemTypes; + if (tupleableItems_.has_value()) { + for (const auto& item : *tupleableItems_) { + arrayItemTypes.insert(item.get().getType()); + } + } + arrayItemTypes.insert(itemsType); + std::string arrayType; + if (arrayItemTypes.size() == 1) { + arrayType = *arrayItemTypes.begin() + "&"; + } else if (arrayItemTypes.size() > 1) { + std::vector wrappedArrayItemTypes(arrayItemTypes.size()); + for (auto& item : arrayItemTypes) { + wrappedArrayItemTypes.emplace_back("std::reference_wrapper<" + item + + ">"); + } + arrayType = + "std::variant<" + + std::accumulate(wrappedArrayItemTypes.begin(), + wrappedArrayItemTypes.end(), std::string(), + [](const std::string acc, const std::string& item) { + return acc.empty() ? item : acc + ", " + item; + }) + + ">"; + } + BLOCK << std::format("inline {} get(size_t n) {{", arrayType); if (tupleableItems_.has_value()) { for (size_t i = 0; i < tupleableItems_->size(); i++) { @@ -158,11 +190,11 @@ ArrayProperties::arrayClassDefinition(const CodeProperties& codeProperties, { if (codeProperties.minItemsMakeTupleableRequired_ && minItems_.has_value() && i < minItems_.value()) { - BLOCK << "return item" + std::to_string(i) + ";"; + BLOCK << "return std::ref(item" + std::to_string(i) + ");"; } else { BLOCK << "if(item" + std::to_string(i) + ".has_value()) {" << CodeBlock::inc; - BLOCK << "return item" + std::to_string(i) + ".value();"; + BLOCK << "return std::ref(item" + std::to_string(i) + ".value());"; BLOCK << CodeBlock::dec << "}"; } } @@ -176,7 +208,7 @@ ArrayProperties::arrayClassDefinition(const CodeProperties& codeProperties, << "throw std::range_error(\"Item \" + std::to_string(n) + \" out " "of range\");" << "}" - << "return items[n];" << CodeBlock::dec << "}"; + << "return std::ref(items[n]);" << CodeBlock::dec << "}"; } BLOCK << CodeBlock::dec; BLOCK << "};"; diff --git a/tests/output_tests/test_arrayTuple.cpp b/tests/output_tests/test_arrayTuple.cpp new file mode 100644 index 0000000..7887bc7 --- /dev/null +++ b/tests/output_tests/test_arrayTuple.cpp @@ -0,0 +1,20 @@ +#include "arrayTuple.h" + +// #define CATCH_CONFIG_RUNTIME_STATIC_REQUIRE +#include + +TEST_CASE("arrayTuple: Static checks", "[Output][arrayTuple]") { + JSOG::arrayTuple::Array array; + STATIC_REQUIRE((std::is_same_v>)); + STATIC_REQUIRE((std::is_same_v>)); + STATIC_REQUIRE((std::is_same_v>)); + STATIC_REQUIRE( + std::is_same_v()), std::optional>); + STATIC_REQUIRE( + (std::is_same_v()), std::optional>)); + STATIC_REQUIRE((std::is_same_v()), unsigned char>)); + STATIC_REQUIRE((std::is_same_v()), unsigned char>)); +} \ No newline at end of file diff --git a/tests/schemas_to_compile/arrayTuple.json b/tests/schemas_to_compile/arrayTuple.json new file mode 100644 index 0000000..240ed74 --- /dev/null +++ b/tests/schemas_to_compile/arrayTuple.json @@ -0,0 +1,16 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "array", + "title": "arrayTuple", + "items": [ + { + "type": "string" + }, + { + "type": "number" + } + ], + "additionalItems": { + "type": "boolean" + } +} \ No newline at end of file diff --git a/tests/test_CodeBlock.cpp b/tests/test_CodeBlock.cpp index e98f678..86ce81c 100644 --- a/tests/test_CodeBlock.cpp +++ b/tests/test_CodeBlock.cpp @@ -21,16 +21,17 @@ TEST_CASE("CodeBlock with custom indent", "[CodeBlock]") { TEST_CASE("CodeBlock with discard", "[CodeBlock]") { CodeBlock block; block.indent = "x"; - block << "Hello, World!" << CodeBlock::inc << "Goodbye, World!" - << CodeBlock::dis << "Hello, World!"; + block << "Hello, World!" << CodeBlock::inc << CodeBlock::dis + << "Goodbye, World!" + << "Hello, World!"; REQUIRE(block.str() == "Hello, World!\nxGoodbye, World!Hello, World!\n"); } TEST_CASE("CodeBlock with multiple discards", "[CodeBlock]") { CodeBlock block; block.indent = "x"; - block << "Hello, World!" << CodeBlock::inc << "Goodbye, World!" - << CodeBlock::dis << "Hello, World!" << CodeBlock::dis + block << "Hello, World!" << CodeBlock::inc << CodeBlock::dis + << "Goodbye, World!" << CodeBlock::dis << "Hello, World!" << "Goodbye World!"; REQUIRE(block.str() == "Hello, World!\nxGoodbye, World!Hello, World!Goodbye " "World!\n"); From a024d8e37015c4f391d87c6ac39171ff3a51e9a8 Mon Sep 17 00:00:00 2001 From: Sakars Date: Mon, 30 Dec 2024 23:51:49 +0000 Subject: [PATCH 3/9] output on failure --- .github/workflows/cmake-single-platform.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake-single-platform.yml b/.github/workflows/cmake-single-platform.yml index b5c1126..ddbb217 100644 --- a/.github/workflows/cmake-single-platform.yml +++ b/.github/workflows/cmake-single-platform.yml @@ -74,7 +74,7 @@ jobs: - name: Run tests run: | chmod +x ./build/tests - ctest --test-dir build --output-junit test-results.xml + ctest --test-dir build --output-on-failure --output-junit test-results.xml # Upload test results - name: Upload test results From bbe9fbb66b8be9a6e145d73be5e54025098b54c8 Mon Sep 17 00:00:00 2001 From: Sakars Date: Mon, 30 Dec 2024 23:55:29 +0000 Subject: [PATCH 4/9] testing fail --- tests/test_Document.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_Document.cpp b/tests/test_Document.cpp index a26963e..1f2ae57 100644 --- a/tests/test_Document.cpp +++ b/tests/test_Document.cpp @@ -39,4 +39,6 @@ TEST_CASE("Load Documents loads documents with unique fileUris", "[Document]") { auto documents = loadDocuments(paths); REQUIRE(documents.size() == 2); REQUIRE(documents[0].fileUri_ != documents[1].fileUri_); -} \ No newline at end of file +} + +TEST_CASE("Fail") { REQUIRE(1 == 2); } \ No newline at end of file From 0cdfd5352700f91c64665bd358a0446ade77accd Mon Sep 17 00:00:00 2001 From: Sakars Date: Tue, 31 Dec 2024 00:07:13 +0000 Subject: [PATCH 5/9] has test-results --- .github/workflows/cmake-single-platform.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/cmake-single-platform.yml b/.github/workflows/cmake-single-platform.yml index ddbb217..f2f4d84 100644 --- a/.github/workflows/cmake-single-platform.yml +++ b/.github/workflows/cmake-single-platform.yml @@ -78,6 +78,7 @@ jobs: # Upload test results - name: Upload test results + if: ${{ hashFiles('build/test-results.xml') != '' }} uses: actions/upload-artifact@v4 with: path: build/test-results.xml From 31d21406f424c79b7de0ae53138877fbffe9bfcb Mon Sep 17 00:00:00 2001 From: Sakars Date: Tue, 31 Dec 2024 00:14:21 +0000 Subject: [PATCH 6/9] continue-on-error --- .github/workflows/cmake-single-platform.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/cmake-single-platform.yml b/.github/workflows/cmake-single-platform.yml index f2f4d84..7cb208e 100644 --- a/.github/workflows/cmake-single-platform.yml +++ b/.github/workflows/cmake-single-platform.yml @@ -72,6 +72,7 @@ jobs: # Run tests - name: Run tests + continue-on-error: true run: | chmod +x ./build/tests ctest --test-dir build --output-on-failure --output-junit test-results.xml From 7d1d1c01425b49a89ee35da5b63713ec8bc3af61 Mon Sep 17 00:00:00 2001 From: Sakars Date: Tue, 31 Dec 2024 00:23:36 +0000 Subject: [PATCH 7/9] Removed bad test --- tests/test_Document.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/test_Document.cpp b/tests/test_Document.cpp index 1f2ae57..e4c28f2 100644 --- a/tests/test_Document.cpp +++ b/tests/test_Document.cpp @@ -40,5 +40,3 @@ TEST_CASE("Load Documents loads documents with unique fileUris", "[Document]") { REQUIRE(documents.size() == 2); REQUIRE(documents[0].fileUri_ != documents[1].fileUri_); } - -TEST_CASE("Fail") { REQUIRE(1 == 2); } \ No newline at end of file From 2dca328174586ad7272eb7e841b3c7f9a9fcedb2 Mon Sep 17 00:00:00 2001 From: Sakars Date: Tue, 31 Dec 2024 00:30:44 +0000 Subject: [PATCH 8/9] testing fail --- tests/output_tests/test_myself.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/output_tests/test_myself.cpp b/tests/output_tests/test_myself.cpp index 6e5d903..6799c23 100644 --- a/tests/output_tests/test_myself.cpp +++ b/tests/output_tests/test_myself.cpp @@ -7,4 +7,6 @@ TEST_CASE("Myself: Static checks for whether self-referential types can exist", myself.object_ = std::make_unique(); myself.additionalProperties["key"] = "value"; REQUIRE(myself.object_ != nullptr); -} \ No newline at end of file +} + +TEST_CASE("FAIL") { FAIL(); } \ No newline at end of file From 1d0d9b3a0f2ce115c4545f567db0d858a68b3ab3 Mon Sep 17 00:00:00 2001 From: Sakars Date: Tue, 31 Dec 2024 00:42:49 +0000 Subject: [PATCH 9/9] fix --- tests/output_tests/test_myself.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/output_tests/test_myself.cpp b/tests/output_tests/test_myself.cpp index 6799c23..a53286f 100644 --- a/tests/output_tests/test_myself.cpp +++ b/tests/output_tests/test_myself.cpp @@ -8,5 +8,3 @@ TEST_CASE("Myself: Static checks for whether self-referential types can exist", myself.additionalProperties["key"] = "value"; REQUIRE(myself.object_ != nullptr); } - -TEST_CASE("FAIL") { FAIL(); } \ No newline at end of file