Files
EVEngine/test/asset_dependency.cpp

89 lines
4.2 KiB
C++

#include "asset/AssetDependency.h"
#include "zeroerr/assert.h"
#include "zeroerr/unittest.h"
using namespace eve;
using namespace eve::asset;
namespace {
AssetRef ref(std::string_view value) {
auto parsed = AssetRef::parse(value);
REQUIRE(parsed.ok());
return std::move(parsed).takeValue();
}
EvaAssetEntry entry(AssetRef asset, std::string type) {
return {std::move(asset), std::move(type), SchemaVersion(1), "definition.json",
"sha256:0000000000000000000000000000000000000000000000000000000000000000", {}};
}
} // namespace
TEST_CASE("asset.dependency.requiredOptionalAndProviderPresenceAreExplicit") {
const auto root = ref("asset://550e8400-e29b-41d4-a716-446655440000");
const auto required = ref("asset://550e8400-e29b-41d4-a716-446655440001");
const auto optional = ref("asset://550e8400-e29b-41d4-a716-446655440002");
EvaManifest manifest;
manifest.assets.push_back(entry(root, "eve.material"));
manifest.entrypoints.emplace("default", root);
manifest.dependencies.push_back({root, required, EvaDependencyKind::RuntimeRequired,
"baseColor", {}, "eve.image/1"});
manifest.dependencies.push_back({root, optional, EvaDependencyKind::RuntimeOptional,
"detail", {}, "eve.image/1",
{{"behavior", Value("use-default")},
{"observableCode", Value("material.detail-defaulted")}}});
auto absent = validateEvaDependencies(manifest);
REQUIRE(!absent.ok());
CHECK_EQ(absent.error()->code(), DiagnosticCode::NotFound);
const std::vector<AvailableAssetDependency> available = {
{required, "eve.image", SchemaVersion(1)}};
auto present = validateEvaDependencies(manifest, available);
REQUIRE(present.ok());
REQUIRE_EQ(present.value().omittedOptionalAssets.size(), std::size_t(1));
CHECK_EQ(present.value().omittedOptionalAssets.front(), optional.id());
const std::vector<AvailableAssetDependency> wrong = {
{required, "eve.mesh", SchemaVersion(1)}};
auto wrongType = validateEvaDependencies(manifest, wrong);
REQUIRE(!wrongType.ok());
CHECK_EQ(wrongType.error()->code(), DiagnosticCode::TypeMismatch);
}
TEST_CASE("asset.dependency.requiredCycleAndForeignSourceAreRejected") {
const auto first = ref("asset://550e8400-e29b-41d4-a716-446655440000");
const auto second = ref("asset://550e8400-e29b-41d4-a716-446655440001");
EvaManifest manifest;
manifest.assets = {entry(first, "eve.material"), entry(second, "eve.image")};
manifest.entrypoints.emplace("default", first);
manifest.dependencies.push_back({first, second, EvaDependencyKind::RuntimeRequired,
"image", {}, "eve.image/1"});
manifest.dependencies.push_back({second, first, EvaDependencyKind::RuntimeRequired,
"owner", {}, "eve.material/1"});
auto cycle = validateEvaDependencies(manifest);
REQUIRE(!cycle.ok());
CHECK_EQ(cycle.error()->code(), DiagnosticCode::Conflict);
manifest.dependencies.clear();
const auto foreign = ref("asset://550e8400-e29b-41d4-a716-446655440009");
manifest.dependencies.push_back(
{foreign, first, EvaDependencyKind::RuntimeOptional, "bad", {}, {},
{{"behavior", Value("omit-feature")},
{"observableCode", Value("test.foreign-missing")}}});
auto badSource = validateEvaDependencies(manifest);
REQUIRE(!badSource.ok());
CHECK_EQ(badSource.error()->code(), DiagnosticCode::NotFound);
}
TEST_CASE("asset.dependency.optionalRequiresExplicitObservableFallback") {
const auto root = ref("asset://550e8400-e29b-41d4-a716-446655440000");
const auto optional = ref("asset://550e8400-e29b-41d4-a716-446655440002");
EvaManifest manifest;
manifest.assets.push_back(entry(root, "eve.material"));
manifest.dependencies.push_back({root, optional, EvaDependencyKind::RuntimeOptional,
"detail", {}, "eve.image/1"});
auto missingPolicy = validateEvaDependencies(manifest);
REQUIRE(!missingPolicy.ok());
CHECK_EQ(missingPolicy.error()->code(), DiagnosticCode::InvalidArgument);
}