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
32 changes: 28 additions & 4 deletions src/test/include/sourcemeta/blaze/test.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,6 @@ struct SOURCEMETA_BLAZE_TEST_EXPORT TestSuite {
std::vector<sourcemeta::core::JSON::String> targets;
/// The list of test cases in the suite
std::vector<TestCase> tests;
/// The compiled schema templates for fast validation
std::vector<Template> schemas_fast;
/// The compiled schema templates for exhaustive validation
std::vector<Template> schemas_exhaustive;
#if defined(_MSC_VER)
#pragma warning(default : 4251)
#endif
Expand All @@ -135,6 +131,14 @@ struct SOURCEMETA_BLAZE_TEST_EXPORT TestSuite {
std::size_t total, const TestCase &test_case, const TestOutcome &outcome,
TestTimestamp start, TestTimestamp end)>;

/// The compiled schema template for fast validation of the given target
[[nodiscard]] auto fast(std::size_t target_index) const -> const Template &;

/// The compiled schema template for exhaustive validation of the given
/// target, compiled on the first request and cached from then on. A test
/// suite must not be shared across threads
auto exhaustive(std::size_t target_index) -> const Template &;

/// Run all test cases in the suite, invoking the callback for each.
/// For example:
///
Expand Down Expand Up @@ -231,6 +235,26 @@ struct SOURCEMETA_BLAZE_TEST_EXPORT TestSuite {
const sourcemeta::blaze::SchemaWalker &walker, const Compiler &compiler,
std::string_view default_dialect = "", std::string_view default_id = "",
const std::optional<Tweaks> &tweaks = std::nullopt) -> TestSuite;

private:
[[nodiscard]] auto compile_target(std::size_t target_index, Mode mode) const
-> Template;

#if defined(_MSC_VER)
#pragma warning(disable : 4251)
#endif
std::vector<Template> schemas_fast;
std::vector<std::optional<Template>> schemas_exhaustive;
SchemaResolver schema_resolver;
SchemaWalker walker;
Compiler compiler;
sourcemeta::core::JSON::String default_dialect;
sourcemeta::core::JSON::String default_id;
std::optional<Tweaks> tweaks_fast;
std::optional<Tweaks> tweaks_exhaustive;
#if defined(_MSC_VER)
#pragma warning(default : 4251)
#endif
};

} // namespace sourcemeta::blaze
Expand Down
84 changes: 56 additions & 28 deletions src/test/test_parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -208,45 +208,73 @@ auto TestSuite::parse(const sourcemeta::core::JSON &document,
return test_case.rdf.has_value();
})};

auto tweaks_fast{tweaks};
test_suite.tweaks_fast = tweaks;
test_suite.tweaks_exhaustive = tweaks;
if (with_rdf) {
if (!tweaks_fast.has_value()) {
tweaks_fast.emplace();
if (!test_suite.tweaks_fast.has_value()) {
test_suite.tweaks_fast.emplace();
}

if (!tweaks_fast.value().annotations.has_value()) {
tweaks_fast.value().annotations.emplace();
if (!test_suite.tweaks_fast.value().annotations.has_value()) {
test_suite.tweaks_fast.value().annotations.emplace();
}

tweaks_fast.value().annotations.value().insert(JSONLD_KEYWORDS.cbegin(),
JSONLD_KEYWORDS.cend());
test_suite.tweaks_fast.value().annotations.value().insert(
JSONLD_KEYWORDS.cbegin(), JSONLD_KEYWORDS.cend());
}

test_suite.schema_resolver = schema_resolver;
Comment thread
jviotti marked this conversation as resolved.
test_suite.walker = walker;
test_suite.compiler = compiler;
test_suite.default_dialect = default_dialect;
test_suite.default_id = default_id;

test_suite.schemas_fast.reserve(test_suite.targets.size());
test_suite.schemas_exhaustive.reserve(test_suite.targets.size());

for (const auto &target : test_suite.targets) {
const auto target_schema{wrap_identifier(target)};

try {
test_suite.schemas_fast.push_back(compile(
target_schema, walker, schema_resolver, compiler,
Mode::FastValidation, default_dialect, default_id, "", tweaks_fast));
test_suite.schemas_exhaustive.push_back(
compile(target_schema, walker, schema_resolver, compiler,
Mode::Exhaustive, default_dialect, default_id, "", tweaks));
} catch (const sourcemeta::blaze::SchemaReferenceError &error) {
if (error.location() == sourcemeta::core::Pointer{"$ref"} &&
error.identifier() == target) {
throw sourcemeta::blaze::SchemaResolutionError{
target, "Could not resolve schema under test"};
}

throw;
}
test_suite.schemas_exhaustive.resize(test_suite.targets.size());

for (std::size_t target_index = 0; target_index < test_suite.targets.size();
++target_index) {
test_suite.schemas_fast.push_back(
test_suite.compile_target(target_index, Mode::FastValidation));
}

return test_suite;
}

auto TestSuite::compile_target(const std::size_t target_index,
const Mode mode) const -> Template {
const auto &target{this->targets[target_index]};

try {
return compile(wrap_identifier(target), this->walker, this->schema_resolver,
this->compiler, mode, this->default_dialect,
this->default_id, "",
mode == Mode::FastValidation ? this->tweaks_fast
: this->tweaks_exhaustive);
} catch (const sourcemeta::blaze::SchemaReferenceError &error) {
if (error.location() == sourcemeta::core::Pointer{"$ref"} &&
error.identifier() == target) {
throw sourcemeta::blaze::SchemaResolutionError{
target, "Could not resolve schema under test"};
}

throw;
}
}

auto TestSuite::fast(const std::size_t target_index) const -> const Template & {
assert(target_index < this->schemas_fast.size());
return this->schemas_fast[target_index];
}

auto TestSuite::exhaustive(const std::size_t target_index) -> const Template & {
Comment thread
jviotti marked this conversation as resolved.
assert(target_index < this->schemas_exhaustive.size());
auto &schema_exhaustive{this->schemas_exhaustive[target_index]};
if (!schema_exhaustive.has_value()) {
schema_exhaustive = this->compile_target(target_index, Mode::Exhaustive);
}

return schema_exhaustive.value();
}

} // namespace sourcemeta::blaze
2 changes: 1 addition & 1 deletion src/test/test_runner.cc
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ auto TestSuite::run(const Callback &callback) -> Result {
for (std::size_t target_index = 0; target_index < this->targets.size();
++target_index) {
const auto &target = this->targets[target_index];
const auto &schema_fast = this->schemas_fast[target_index];
const auto &schema_fast = this->fast(target_index);
for (const auto &test_case : this->tests) {
const auto start{std::chrono::steady_clock::now()};
const auto outcome{
Expand Down
Loading
Loading