Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/cmake-single-platform.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,14 @@ jobs:

# Run tests
- name: Run tests
continue-on-error: true
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
if: ${{ hashFiles('build/test-results.xml') != '' }}
uses: actions/upload-artifact@v4
with:
path: build/test-results.xml
Expand Down
2 changes: 1 addition & 1 deletion include/LinkedSchema.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ extern std::map<Draft, std::vector<std::string> (*)(const nlohmann::json&,
/// schemas and a map of idendifiers to indices to the schemas via vector
std::tuple<std::vector<std::unique_ptr<SchemaResource>>,
std::map<UriWrapper, size_t>>
deconstructUnresolvedSchemaMap(SetMap<UriWrapper, SchemaResource>&& setMap);
deconstructSchemaResourceMap(SetMap<UriWrapper, SchemaResource>&& setMap);

/// @brief Resolves the dependencies of a set map of schemas
/// @param setMap The set map of schemas
Expand Down
16 changes: 8 additions & 8 deletions include/SchemaResource.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,27 +113,27 @@ 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<UriWrapper, SchemaResource>& unresolvedSchemas,
static void dumpSchemas(SetMap<UriWrapper, SchemaResource>& 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(
nlohmann::json::array({uri.toFragmentlessString().value_or(""),
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();
}
};

Expand Down
22 changes: 11 additions & 11 deletions src/LinkedSchema.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@ std::map<Draft,

std::tuple<std::vector<std::unique_ptr<SchemaResource>>,
std::map<UriWrapper, size_t>>
deconstructUnresolvedSchemaMap(SetMap<UriWrapper, SchemaResource>&& setMap) {
deconstructSchemaResourceMap(SetMap<UriWrapper, SchemaResource>&& setMap) {
auto map = setMap.extract();
std::vector<std::unique_ptr<SchemaResource>> unresolvedSchemas;
std::vector<std::unique_ptr<SchemaResource>> schemaResources;
std::map<UriWrapper, size_t> 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<std::unique_ptr<LinkedSchema>>
Expand All @@ -41,8 +41,8 @@ resolveDependencies(SetMap<UriWrapper, SchemaResource>&& setMap,
return normalized;
}();
try {
auto [unresolvedSchemas, schemaIndices] =
deconstructUnresolvedSchemaMap(std::move(setMap));
auto [schemaResources, schemaIndices] =
deconstructSchemaResourceMap(std::move(setMap));

std::set<size_t> buildableRequiredSchemas;

Expand All @@ -57,14 +57,14 @@ resolveDependencies(SetMap<UriWrapper, SchemaResource>&& setMap,

std::set<size_t> builtRequiredSchemas;
std::vector<std::map<UriWrapper, size_t>> 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<UriWrapper, size_t> depIndices_;
for (const auto& dep : dependencies) {
Expand Down Expand Up @@ -109,7 +109,7 @@ resolveDependencies(SetMap<UriWrapper, SchemaResource>&& setMap,

std::vector<std::unique_ptr<SchemaResource>> shrunkSchemas;
for (const auto builtIdx : builtRequiredSchemas) {
shrunkSchemas.push_back(std::move(unresolvedSchemas[builtIdx]));
shrunkSchemas.push_back(std::move(schemaResources[builtIdx]));
}

std::vector<std::unique_ptr<LinkedSchema>> linkedSchemas;
Expand Down
50 changes: 41 additions & 9 deletions src/SyncedSchema/ArrayProperties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <size_t N>";
Expand All @@ -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 ";
}
Expand All @@ -150,19 +156,45 @@ 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<std::string> 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<std::string> 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++) {
BLOCK << std::format("if(n == {}) {{", i) << CodeBlock::inc;
{
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 << "}";
}
}
Expand All @@ -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 << "};";
Expand Down
6 changes: 3 additions & 3 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,13 @@ int main(int argc, char* argv[]) {
std::vector<Document> documents = loadDocuments(inputFiles);
std::vector<DraftRecognisedDocument> 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);
Expand Down
20 changes: 20 additions & 0 deletions tests/output_tests/test_arrayTuple.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include "arrayTuple.h"

// #define CATCH_CONFIG_RUNTIME_STATIC_REQUIRE
#include <catch2/catch_all.hpp>

TEST_CASE("arrayTuple: Static checks", "[Output][arrayTuple]") {
JSOG::arrayTuple::Array array;
STATIC_REQUIRE((std::is_same_v<decltype(JSOG::arrayTuple::Array::item0),
std::optional<std::string>>));
STATIC_REQUIRE((std::is_same_v<decltype(JSOG::arrayTuple::Array::item1),
std::optional<double>>));
STATIC_REQUIRE((std::is_same_v<decltype(JSOG::arrayTuple::Array::items),
std::vector<unsigned char>>));
STATIC_REQUIRE(
std::is_same_v<decltype(array.get<0>()), std::optional<std::string>>);
STATIC_REQUIRE(
(std::is_same_v<decltype(array.get<1>()), std::optional<double>>));
STATIC_REQUIRE((std::is_same_v<decltype(array.get<2>()), unsigned char>));
STATIC_REQUIRE((std::is_same_v<decltype(array.get<3>()), unsigned char>));
}
2 changes: 1 addition & 1 deletion tests/output_tests/test_hotel.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

#include "Hotel.h"
#include <catch2/catch_all.hpp>
TEST_CASE("Test hotel") {
TEST_CASE("Test hotel", "[Output][Hotel]") {
nlohmann::json json = R"({
"id": "00000000-0000-0000-0000-000000000000",
"name": "Hotel California",
Expand Down
13 changes: 8 additions & 5 deletions tests/output_tests/test_lengthLimitedString.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<JSOG::LengthLimitedString::LengthLimitedString,
std::string>);
using ConstructType = decltype(JSOG::LengthLimitedString::construct);
Expand All @@ -20,7 +20,8 @@ TEST_CASE("Static lengthLimitedString tests") {
STATIC_REQUIRE(std::is_same_v<ValidateType, bool(const std::string&)>);
}

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);
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions tests/output_tests/test_myself.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
#include <catch2/catch_all.hpp>

TEST_CASE("Myself: Static checks for whether self-referential types can exist",
"[myself]") {
"[Output][myself]") {
JSOG::Myself::Myself myself;
myself.object_ = std::make_unique<JSOG::Myself::Myself>();
myself.additionalProperties["key"] = "value";
REQUIRE(myself.object_ != nullptr);
}
}
13 changes: 8 additions & 5 deletions tests/output_tests/test_regexMatcherString.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#include "randomString.h"
#include <catch2/catch_all.hpp>

TEST_CASE("Static RegexMatcherString tests") {
TEST_CASE("Static RegexMatcherString tests", "[Output][RegexMatcherString]") {
STATIC_REQUIRE(std::is_same_v<JSOG::RegexMatcherString::RegexMatcherString,
std::string>);
using ConstructType = decltype(JSOG::RegexMatcherString::construct);
Expand All @@ -17,7 +17,8 @@ TEST_CASE("Static RegexMatcherString tests") {
STATIC_REQUIRE(std::is_same_v<ValidateType, bool(const std::string&)>);
}

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) {
Expand Down Expand Up @@ -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);
Expand All @@ -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) {
Expand All @@ -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) {
Expand Down
Loading