Files
GDevelop/Core/tests/PlatformMetadataIndex.cpp
T
Clément Pasteau bc662995f4 Add tests for the MetadataProvider constant-time index
- Core/tests/PlatformMetadataIndex.cpp (native/catch): every lookup kind against
  DummyPlatform, object-expression fallback to the base ("") type, behavior
  actions indexed alongside free/object ones, bad-metadata for unknown types,
  the declaring extension is returned, and the index rebuilds after an extension
  is removed.
- Expand the jest MetadataProviderIndex test to assert *all* metadata kinds
  resolve after an extension is added and *all* become bad after it is removed
  (invalidation covers the whole index, not just objects/actions).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 17:32:24 +02:00

115 lines
5.5 KiB
C++

/*
* GDevelop Core
* Copyright 2008-2026 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
/**
* @file Tests for gd::MetadataProvider lookups, which are backed by
* gd::PlatformMetadataIndex (constant-time index of a platform's metadata).
*/
#include "DummyPlatform.h"
#include "GDCore/Extensions/Metadata/BehaviorMetadata.h"
#include "GDCore/Extensions/Metadata/EffectMetadata.h"
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
#include "GDCore/Extensions/Metadata/ObjectMetadata.h"
#include "GDCore/Extensions/Platform.h"
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/Project/Project.h"
#include "catch.hpp"
using namespace gd;
TEST_CASE("PlatformMetadataIndex (via MetadataProvider)", "[common]") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
SECTION("It resolves every kind of metadata declared by an extension") {
REQUIRE_FALSE(MetadataProvider::IsBadObjectMetadata(
MetadataProvider::GetObjectMetadata(platform, "MyExtension::Sprite")));
REQUIRE_FALSE(MetadataProvider::IsBadBehaviorMetadata(
MetadataProvider::GetBehaviorMetadata(platform,
"MyExtension::MyBehavior")));
REQUIRE_FALSE(MetadataProvider::IsBadInstructionMetadata(
MetadataProvider::GetActionMetadata(platform, "MyExtension::DoSomething")));
REQUIRE_FALSE(MetadataProvider::IsBadExpressionMetadata(
MetadataProvider::GetExpressionMetadata(platform, "MyExtension::GetNumber")));
REQUIRE_FALSE(MetadataProvider::IsBadExpressionMetadata(
MetadataProvider::GetStrExpressionMetadata(platform, "MyExtension::ToString")));
}
SECTION("Behavior actions are indexed alongside free/object actions") {
REQUIRE_FALSE(MetadataProvider::IsBadInstructionMetadata(
MetadataProvider::GetActionMetadata(
platform, "MyExtension::BehaviorDoSomething")));
}
SECTION("It resolves object/behavior expressions on their own type") {
REQUIRE_FALSE(MetadataProvider::IsBadExpressionMetadata(
MetadataProvider::GetObjectExpressionMetadata(
platform, "MyExtension::Sprite", "GetObjectNumber")));
REQUIRE_FALSE(MetadataProvider::IsBadExpressionMetadata(
MetadataProvider::GetObjectStrExpressionMetadata(
platform, "MyExtension::Sprite", "GetObjectStringWith1Param")));
REQUIRE_FALSE(MetadataProvider::IsBadExpressionMetadata(
MetadataProvider::GetBehaviorExpressionMetadata(
platform, "MyExtension::MyBehavior", "GetBehaviorNumberWith1Param")));
REQUIRE_FALSE(MetadataProvider::IsBadExpressionMetadata(
MetadataProvider::GetBehaviorStrExpressionMetadata(
platform, "MyExtension::MyBehavior", "GetBehaviorStringWith1Param")));
}
SECTION("Object expressions fall back to the base object type") {
// "GetFromBaseExpression" is declared on the base object (""), not on
// Sprite, so it must be resolved through the base-type fallback.
const auto& fromBase = MetadataProvider::GetObjectExpressionMetadata(
platform, "MyExtension::Sprite", "GetFromBaseExpression");
REQUIRE_FALSE(MetadataProvider::IsBadExpressionMetadata(fromBase));
// It must also be found for an object type that is not declared by any
// extension (still resolved via the base object).
REQUIRE_FALSE(MetadataProvider::IsBadExpressionMetadata(
MetadataProvider::GetObjectExpressionMetadata(
platform, "UnknownObjectType", "GetFromBaseExpression")));
}
SECTION("Unknown types resolve to the bad metadata") {
REQUIRE(MetadataProvider::IsBadObjectMetadata(
MetadataProvider::GetObjectMetadata(platform, "MyExtension::DoesNotExist")));
REQUIRE(MetadataProvider::IsBadBehaviorMetadata(
MetadataProvider::GetBehaviorMetadata(platform, "Does::NotExist")));
REQUIRE(MetadataProvider::IsBadInstructionMetadata(
MetadataProvider::GetActionMetadata(platform, "Does::NotExist")));
REQUIRE(MetadataProvider::IsBadInstructionMetadata(
MetadataProvider::GetConditionMetadata(platform, "Does::NotExist")));
REQUIRE(MetadataProvider::IsBadExpressionMetadata(
MetadataProvider::GetExpressionMetadata(platform, "Does::NotExist")));
REQUIRE(MetadataProvider::IsBadExpressionMetadata(
MetadataProvider::GetObjectExpressionMetadata(
platform, "MyExtension::Sprite", "DoesNotExist")));
}
SECTION("It returns the extension that declares the metadata") {
auto extensionAndMetadata =
MetadataProvider::GetExtensionAndObjectMetadata(platform,
"MyExtension::Sprite");
REQUIRE(extensionAndMetadata.GetExtension().GetName() == "MyExtension");
auto badExtensionAndMetadata =
MetadataProvider::GetExtensionAndObjectMetadata(platform,
"MyExtension::DoesNotExist");
REQUIRE(badExtensionAndMetadata.GetExtension().GetName().empty());
}
SECTION("The index is rebuilt after the platform's extensions change") {
REQUIRE_FALSE(MetadataProvider::IsBadObjectMetadata(
MetadataProvider::GetObjectMetadata(platform, "MyExtension::Sprite")));
platform.RemoveExtension("MyExtension");
REQUIRE(MetadataProvider::IsBadObjectMetadata(
MetadataProvider::GetObjectMetadata(platform, "MyExtension::Sprite")));
}
}