Files
Bigfoot/Bigfoot/Tests/Engine/Asset/AssetLibrary.cpp
T
rboullard aa149ae556
Bigfoot / Sonarqube (push) Skipped
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/host/clang (Unity Build: OFF, Variant: game) (push) Successful in 42s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/host/clang (Unity Build: ON, Variant: game) (push) Successful in 29s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/host/clang (Unity Build: OFF, Variant: toolmode) (push) Successful in 47s
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang (Unity Build: OFF, Variant: game) (push) Successful in 37s
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang (Unity Build: ON, Variant: game) (push) Successful in 24s
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang (Unity Build: OFF, Variant: toolmode) (push) Successful in 42s
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang (Unity Build: ON, Variant: toolmode) (push) Successful in 26s
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang_asan (Unity Build: OFF, Variant: game) (push) Successful in 1m5s
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang_asan (Unity Build: ON, Variant: game) (push) Successful in 51s
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang_asan (Unity Build: OFF, Variant: toolmode) (push) Successful in 1m12s
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang_asan (Unity Build: ON, Variant: toolmode) (push) Successful in 57s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/host/clang_asan (Unity Build: OFF, Variant: toolmode) (push) Successful in 1m15s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/host/clang_asan (Unity Build: ON, Variant: toolmode) (push) Successful in 59s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/host/clang (Unity Build: ON, Variant: toolmode) (push) Successful in 31s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/host/clang_asan (Unity Build: OFF, Variant: game) (push) Successful in 1m8s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/host/clang_asan (Unity Build: ON, Variant: game) (push) Successful in 52s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang (Unity Build: OFF, Variant: game) (push) Successful in 32s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang (Unity Build: ON, Variant: game) (push) Successful in 24s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang (Unity Build: OFF, Variant: toolmode) (push) Successful in 51s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang (Unity Build: ON, Variant: toolmode) (push) Successful in 38s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang_asan (Unity Build: OFF, Variant: game) (push) Successful in 48s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang_asan (Unity Build: ON, Variant: game) (push) Successful in 42s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang_asan (Unity Build: OFF, Variant: toolmode) (push) Successful in 52s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang_asan (Unity Build: ON, Variant: toolmode) (push) Successful in 46s
Bigfoot / Clang Format Checks (push) Successful in 11s
Fix tests
2026-08-31 00:00:02 +02:00

262 lines
9.4 KiB
C++

/*********************************************************************
* \file AssetLibrary.cpp
*
* \author Romain BOULLARD
* \date July 2026
*********************************************************************/
#include <Engine/Asset/AssetLibrary.hpp>
#include <AssetsForTesting/Asset/AssetA.hpp>
#include <AssetsForTesting/Asset/AssetB.hpp>
#include <AssetsForTesting/Asset/AssetC.hpp>
#include <gtest/gtest.h>
namespace Bigfoot
{
class AssetLibraryFixture: public ::testing::Test
{
protected:
AssetContainer<AssetA> m_containerA;
AssetContainer<AssetB> m_containerB;
AssetContainer<AssetC> m_containerC;
AssetLibrary m_library;
};
/****************************************************************************************/
TEST_F(AssetLibraryFixture, Insert_ShouldReturnTrueOnSuccess)
{
EXPECT_TRUE(m_library.Insert(&m_containerA));
EXPECT_TRUE(m_library.Insert(&m_containerB));
EXPECT_TRUE(m_library.Insert(&m_containerC));
}
/****************************************************************************************/
TEST_F(AssetLibraryFixture, Insert_ShouldReturnFalseOnDuplicate)
{
std::ignore = m_library.Insert(&m_containerA);
EXPECT_FALSE(m_library.Insert(&m_containerA));
AssetContainer<AssetA> m_containerAA;
EXPECT_FALSE(m_library.Insert(&m_containerAA));
}
/****************************************************************************************/
TEST_F(AssetLibraryFixture, GetAssetContainer_ShouldReturnTheAssetContainerIfAvailable)
{
std::ignore = m_library.Insert(&m_containerA);
std::ignore = m_library.Insert(&m_containerB);
std::ignore = m_library.Insert(&m_containerC);
EXPECT_EQ(m_library.GetAssetContainer(GetAssetTypeID<AssetA>()), &m_containerA);
EXPECT_EQ(m_library.GetAssetContainer(GetAssetTypeID<AssetB>()), &m_containerB);
EXPECT_EQ(m_library.GetAssetContainer(GetAssetTypeID<AssetC>()), &m_containerC);
EXPECT_EQ(std::as_const(m_library).GetAssetContainer(GetAssetTypeID<AssetA>()), &m_containerA);
EXPECT_EQ(std::as_const(m_library).GetAssetContainer(GetAssetTypeID<AssetB>()), &m_containerB);
EXPECT_EQ(std::as_const(m_library).GetAssetContainer(GetAssetTypeID<AssetC>()), &m_containerC);
}
/****************************************************************************************/
TEST_F(AssetLibraryFixture, GetAssetContainer_ShouldReturnNullptrIfTheContainerDoesNotExist)
{
std::ignore = m_library.Insert(&m_containerB);
EXPECT_EQ(m_library.GetAssetContainer(GetAssetTypeID<AssetA>()), nullptr);
EXPECT_EQ(std::as_const(m_library).GetAssetContainer(GetAssetTypeID<AssetA>()), nullptr);
}
/****************************************************************************************/
TEST_F(AssetLibraryFixture, GetAssetContainer_ShouldReturnTheContainerThatHasTheAsset)
{
std::ignore = m_library.Insert(&m_containerA);
std::ignore = m_library.Insert(&m_containerB);
const UUID uuid = m_containerB.Insert()->GetAsset()->GetHeader().uuid;
EXPECT_EQ(m_library.GetAssetContainer(uuid), &m_containerB);
EXPECT_EQ(std::as_const(m_library).GetAssetContainer(uuid), &m_containerB);
}
/****************************************************************************************/
TEST_F(AssetLibraryFixture, GetAssetContainer_ShouldReturnNullptrIfNoContainerHasTheAsset)
{
std::ignore = m_library.Insert(&m_containerA);
std::ignore = m_library.Insert(&m_containerB);
const UUID uuid;
EXPECT_EQ(m_library.GetAssetContainer(uuid), nullptr);
EXPECT_EQ(std::as_const(m_library).GetAssetContainer(uuid), nullptr);
}
/****************************************************************************************/
TEST_F(AssetLibraryFixture, IsLoaded_ShouldReturnTrueIfTheAssetIsLoaded)
{
std::ignore = m_library.Insert(&m_containerA);
std::ignore = m_library.Insert(&m_containerB);
const UUID uuid = m_containerB.Insert()->GetAsset()->GetHeader().uuid;
EXPECT_TRUE(m_library.IsLoaded(uuid));
}
/****************************************************************************************/
TEST_F(AssetLibraryFixture, IsLoaded_ShouldReturnFalseIfTheAssetIsNotLoaded)
{
std::ignore = m_library.Insert(&m_containerA);
std::ignore = m_library.Insert(&m_containerB);
const UUID uuid;
EXPECT_FALSE(m_library.IsLoaded(uuid));
}
/****************************************************************************************/
TEST_F(AssetLibraryFixture, IsLoaded_ShouldReturnFalseIfTheAssetWasRemovedFromItsContainer)
{
std::ignore = m_library.Insert(&m_containerA);
std::ignore = m_library.Insert(&m_containerB);
const UUID uuid = m_containerB.Insert()->GetAsset()->GetHeader().uuid;
ASSERT_TRUE(m_library.IsLoaded(uuid));
m_containerB.Remove(uuid);
EXPECT_FALSE(m_library.IsLoaded(uuid));
}
/****************************************************************************************/
TEST_F(AssetLibraryFixture, ProcessPendingRemovals_ShouldProcessRemovalsOnEveryContainer)
{
std::ignore = m_library.Insert(&m_containerA);
std::ignore = m_library.Insert(&m_containerB);
const UUID uuidA = m_containerA.Insert()->GetAsset()->GetHeader().uuid;
const UUID uuidB = m_containerB.Insert()->GetAsset()->GetHeader().uuid;
m_containerA.QueueForRemoval(uuidA);
m_containerB.QueueForRemoval(uuidB);
m_library.ProcessPendingRemovals();
EXPECT_FALSE(m_containerA.Has(uuidA));
EXPECT_FALSE(m_containerB.Has(uuidB));
}
/****************************************************************************************/
TEST_F(AssetLibraryFixture, ProcessPendingRemovals_ShouldNotRemoveAssetsThatAreNotQueued)
{
std::ignore = m_library.Insert(&m_containerA);
const UUID uuid = m_containerA.Insert()->GetAsset()->GetHeader().uuid;
m_library.ProcessPendingRemovals();
EXPECT_TRUE(m_containerA.Has(uuid));
}
/****************************************************************************************/
TEST_F(AssetLibraryFixture, ProcessPendingRemovals_ShouldCascadeThroughHardReferencedAssetsOneLevelPerCall)
{
const ScopedActiveAssetLibrary activeAssetLibraryScoped {&m_library};
std::ignore = m_library.Insert(&m_containerA);
std::ignore = m_library.Insert(&m_containerB);
std::ignore = m_library.Insert(&m_containerC);
UUID leafUUID;
UUID middleUUID;
UUID rootUUID;
{
// leaf
AssetA* leaf = static_cast<AssetA*>(m_containerA.Insert()->GetAsset());
leafUUID = leaf->GetHeader().uuid;
// middle --> leaf
AssetB* middle = static_cast<AssetB*>(m_containerB.Insert()->GetAsset());
middle->GetAsset().ref_a = HardReference<AssetA> {leafUUID};
middleUUID = middle->GetHeader().uuid;
// root
// / \
// v v
// middle --> leaf
AssetC* root = static_cast<AssetC*>(m_containerC.Insert()->GetAsset());
root->GetAsset().asset_b_ref = HardReference<AssetB> {middleUUID};
root->GetAsset().inner_table->asset_a_ref = HardReference<AssetA> {leafUUID};
rootUUID = root->GetHeader().uuid;
const HardReference<AssetC> rootRef {rootUUID};
const HardReference<AssetB> middleRef {middleUUID};
const HardReference<AssetA> leafRef {leafUUID};
ASSERT_NE(rootRef.Get(), nullptr);
ASSERT_NE(middleRef.Get(), nullptr);
ASSERT_NE(leafRef.Get(), nullptr);
}
// Releasing the outer HardReferences only drops root's count to zero: middle and leaf are
// still kept alive by root's own internal HardReferences to them.
EXPECT_TRUE(m_containerC.IsMarkedForRemove(rootUUID));
EXPECT_FALSE(m_containerB.IsMarkedForRemove(middleUUID));
EXPECT_FALSE(m_containerA.IsMarkedForRemove(leafUUID));
EXPECT_TRUE(m_library.IsLoaded(rootUUID));
EXPECT_TRUE(m_library.IsLoaded(middleUUID));
EXPECT_TRUE(m_library.IsLoaded(leafUUID));
// 1st pass: removing root destroys its HardReference to middle, dropping middle's count to
// zero; leaf is still held alive by middle's own HardReference to it.
m_library.ProcessPendingRemovals();
EXPECT_FALSE(m_library.IsLoaded(rootUUID));
EXPECT_TRUE(m_containerB.IsMarkedForRemove(middleUUID));
EXPECT_TRUE(m_library.IsLoaded(middleUUID));
EXPECT_TRUE(m_library.IsLoaded(leafUUID));
// 2nd pass: removing middle destroys its HardReference to leaf, dropping leaf's count to zero.
m_library.ProcessPendingRemovals();
EXPECT_FALSE(m_library.IsLoaded(middleUUID));
EXPECT_TRUE(m_containerA.IsMarkedForRemove(leafUUID));
EXPECT_TRUE(m_library.IsLoaded(leafUUID));
// 3rd pass: nothing references leaf anymore, it finally gets removed.
m_library.ProcessPendingRemovals();
EXPECT_FALSE(m_library.IsLoaded(leafUUID));
}
/****************************************************************************************/
TEST_F(AssetLibraryFixture, SetActiveAssetLibrary_ShouldSetTheActiveAssetLibraryToTheGivenLibrary)
{
SetActiveAssetLibrary(&m_library);
EXPECT_EQ(g_activeAssetLibrary, &m_library);
SetActiveAssetLibrary(&g_assetLibrary);
}
/****************************************************************************************/
TEST_F(AssetLibraryFixture, ScopedActiveAssetLibrary_ShouldChangeTheActiveAssetLibraryInAScopedWay)
{
EXPECT_EQ(g_activeAssetLibrary, &g_assetLibrary);
{
ScopedActiveAssetLibrary activeAssetLibraryScoped {&m_library};
EXPECT_EQ(g_activeAssetLibrary, &m_library);
}
EXPECT_EQ(g_activeAssetLibrary, &g_assetLibrary);
}
} // namespace Bigfoot