370 lines
16 KiB
C++
370 lines
16 KiB
C++
/*********************************************************************
|
|
* \file BigFile.cpp
|
|
*
|
|
* \author Romain BOULLARD
|
|
* \date August 2026
|
|
*********************************************************************/
|
|
#include <Engine/BigFile/BigFile.hpp>
|
|
|
|
#include <System/File/File.hpp>
|
|
|
|
#include <EngineTests/BigFileInfo_generated.hpp>
|
|
|
|
#include <AssetsForTesting/Asset/AssetA.hpp>
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#include <chrono>
|
|
#include <thread>
|
|
|
|
namespace Bigfoot
|
|
{
|
|
#ifdef BIGFOOT_TOOLMODE
|
|
class BigFileFixture: public ::testing::Test
|
|
{
|
|
protected:
|
|
void SetUp() override
|
|
{
|
|
BigFile::Request {m_bigFile, "DELETE FROM Asset;"}.Execute();
|
|
BigFile::Request {m_bigFile, "DELETE FROM AssetMetadata;"}.Execute();
|
|
}
|
|
|
|
BigFile m_bigFile {File {BIGFILE_ENGINETESTS_LOCATION}};
|
|
};
|
|
|
|
/****************************************************************************************/
|
|
|
|
TEST_F(BigFileFixture, GetAssetFlatbuffer_ShouldReturnNulloptForNonExistentUUID)
|
|
{
|
|
const UUID uuid;
|
|
|
|
EXPECT_FALSE(m_bigFile.GetAssetFlatbuffer(uuid).has_value());
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TEST_F(BigFileFixture, GetAssetFlatbuffer_ShouldGetTheAssetFlatbuffer)
|
|
{
|
|
AssetA asset;
|
|
asset.SetName("hello");
|
|
asset.GetAsset().health = 42;
|
|
asset.GetAsset().mana = 7;
|
|
const eastl::vector<std::byte> flatbuffer = asset.Pack();
|
|
|
|
const AssetMetadata metadata {.m_uuid = asset.GetHeader().uuid,
|
|
.m_name = asset.GetHeader().name,
|
|
.m_typeID = asset.GetHeader().type_id,
|
|
.m_typeName = asset.GetHeader().type_name};
|
|
|
|
m_bigFile.SaveAssetFlatbuffer(metadata, flatbuffer);
|
|
|
|
const eastl::optional<eastl::vector<std::byte>> savedFlatbuffer = m_bigFile.GetAssetFlatbuffer(
|
|
asset.GetHeader().uuid);
|
|
ASSERT_TRUE(savedFlatbuffer.has_value());
|
|
EXPECT_EQ(*savedFlatbuffer, flatbuffer);
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TEST_F(BigFileFixture, GetAssetFlatbuffers_ShouldOmitUUIDsThatDoNotExist)
|
|
{
|
|
AssetA assetA;
|
|
assetA.SetName("hello");
|
|
const eastl::vector<std::byte> flatbufferA = assetA.Pack();
|
|
m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = assetA.GetHeader().uuid,
|
|
.m_name = assetA.GetHeader().name,
|
|
.m_typeID = assetA.GetHeader().type_id,
|
|
.m_typeName = assetA.GetHeader().type_name},
|
|
flatbufferA);
|
|
|
|
AssetA assetB;
|
|
assetB.SetName("world");
|
|
const eastl::vector<std::byte> flatbufferB = assetB.Pack();
|
|
m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = assetB.GetHeader().uuid,
|
|
.m_name = assetB.GetHeader().name,
|
|
.m_typeID = assetB.GetHeader().type_id,
|
|
.m_typeName = assetB.GetHeader().type_name},
|
|
flatbufferB);
|
|
|
|
const eastl::vector<UUID> uuids {assetA.GetHeader().uuid, UUID {}, assetB.GetHeader().uuid};
|
|
|
|
const eastl::vector<eastl::vector<std::byte>> flatbuffers = m_bigFile.GetAssetFlatbuffers(uuids);
|
|
|
|
ASSERT_EQ(flatbuffers.size(), 2);
|
|
EXPECT_TRUE((flatbuffers[0] == flatbufferA && flatbuffers[1] == flatbufferB) ||
|
|
(flatbuffers[0] == flatbufferB && flatbuffers[1] == flatbufferA));
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TEST_F(BigFileFixture, GetAssetFlatbuffers_ShouldNotDuplicateResultsForADuplicateUUID)
|
|
{
|
|
AssetA assetA;
|
|
assetA.SetName("hello");
|
|
const eastl::vector<std::byte> flatbufferA = assetA.Pack();
|
|
m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = assetA.GetHeader().uuid,
|
|
.m_name = assetA.GetHeader().name,
|
|
.m_typeID = assetA.GetHeader().type_id,
|
|
.m_typeName = assetA.GetHeader().type_name},
|
|
flatbufferA);
|
|
|
|
const eastl::vector<UUID> uuids {assetA.GetHeader().uuid, assetA.GetHeader().uuid};
|
|
|
|
const eastl::vector<eastl::vector<std::byte>> flatbuffers = m_bigFile.GetAssetFlatbuffers(uuids);
|
|
|
|
ASSERT_EQ(flatbuffers.size(), 1);
|
|
EXPECT_EQ(flatbuffers[0], flatbufferA);
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TEST_F(BigFileFixture, GetAssetMetadata_ShouldReturnNulloptForNonExistentUUID)
|
|
{
|
|
const UUID uuid;
|
|
|
|
EXPECT_FALSE(m_bigFile.GetAssetMetadata(uuid).has_value());
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TEST_F(BigFileFixture, GetAssetMetadata_ShouldGetTheAssetMetadata)
|
|
{
|
|
AssetA asset;
|
|
asset.SetName("hello");
|
|
asset.GetAsset().health = 42;
|
|
asset.GetAsset().mana = 7;
|
|
const eastl::vector<std::byte> flatbuffer = asset.Pack();
|
|
|
|
const AssetMetadata metadata {.m_uuid = asset.GetHeader().uuid,
|
|
.m_name = asset.GetHeader().name,
|
|
.m_typeID = asset.GetHeader().type_id,
|
|
.m_typeName = asset.GetHeader().type_name};
|
|
|
|
m_bigFile.SaveAssetFlatbuffer(metadata, flatbuffer);
|
|
|
|
const eastl::optional<AssetMetadata> savedMetadata = m_bigFile.GetAssetMetadata(asset.GetHeader().uuid);
|
|
ASSERT_TRUE(savedMetadata.has_value());
|
|
|
|
EXPECT_EQ(savedMetadata->m_uuid, metadata.m_uuid);
|
|
EXPECT_EQ(savedMetadata->m_name, metadata.m_name);
|
|
EXPECT_EQ(savedMetadata->m_typeID, metadata.m_typeID);
|
|
EXPECT_EQ(savedMetadata->m_typeName, metadata.m_typeName);
|
|
EXPECT_GT(savedMetadata->m_creationTime, Time {0});
|
|
EXPECT_GT(savedMetadata->m_modificationTime, Time {0});
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TEST_F(BigFileFixture, GetAssetMetadatas_ShouldOmitUUIDsThatDoNotExist)
|
|
{
|
|
AssetA assetA;
|
|
assetA.SetName("hello");
|
|
m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = assetA.GetHeader().uuid,
|
|
.m_name = assetA.GetHeader().name,
|
|
.m_typeID = assetA.GetHeader().type_id,
|
|
.m_typeName = assetA.GetHeader().type_name},
|
|
assetA.Pack());
|
|
|
|
AssetA assetB;
|
|
assetB.SetName("world");
|
|
m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = assetB.GetHeader().uuid,
|
|
.m_name = assetB.GetHeader().name,
|
|
.m_typeID = assetB.GetHeader().type_id,
|
|
.m_typeName = assetB.GetHeader().type_name},
|
|
assetB.Pack());
|
|
|
|
const UUID missingUUID;
|
|
const eastl::vector<UUID> uuids {assetA.GetHeader().uuid, missingUUID, assetB.GetHeader().uuid};
|
|
|
|
const eastl::vector<AssetMetadata> metadatas = m_bigFile.GetAssetMetadatas(uuids);
|
|
|
|
ASSERT_EQ(metadatas.size(), 2);
|
|
EXPECT_TRUE((metadatas[0].m_uuid == assetA.GetHeader().uuid && metadatas[0].m_name == "hello" &&
|
|
metadatas[1].m_uuid == assetB.GetHeader().uuid && metadatas[1].m_name == "world") ||
|
|
(metadatas[0].m_uuid == assetB.GetHeader().uuid && metadatas[0].m_name == "world" &&
|
|
metadatas[1].m_uuid == assetA.GetHeader().uuid && metadatas[1].m_name == "hello"));
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TEST_F(BigFileFixture, SaveAssetFlatbuffer_ShouldSaveTheAsset)
|
|
{
|
|
AssetA asset;
|
|
asset.SetName("hello");
|
|
asset.GetAsset().health = 42;
|
|
asset.GetAsset().mana = 7;
|
|
const eastl::vector<std::byte> flatbuffer = asset.Pack();
|
|
|
|
const AssetMetadata metadata {.m_uuid = asset.GetHeader().uuid,
|
|
.m_name = asset.GetHeader().name,
|
|
.m_typeID = asset.GetHeader().type_id,
|
|
.m_typeName = asset.GetHeader().type_name};
|
|
|
|
m_bigFile.SaveAssetFlatbuffer(metadata, flatbuffer);
|
|
|
|
EXPECT_TRUE(m_bigFile.Has(asset.GetHeader().uuid));
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TEST_F(BigFileFixture, SaveAssetFlatbuffer_ShouldUpdateTheDataWhenCalledTwice)
|
|
{
|
|
const UUID uuid;
|
|
|
|
AssetA asset;
|
|
asset.GetAsset().health = 1;
|
|
m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = uuid,
|
|
.m_name = "hello",
|
|
.m_typeID = AssetA::GetTypeID(),
|
|
.m_typeName = eastl::string {AssetA::GetTypeName()}},
|
|
asset.Pack());
|
|
|
|
const eastl::optional<AssetMetadata> savedMetadata1 = m_bigFile.GetAssetMetadata(uuid);
|
|
ASSERT_TRUE(savedMetadata1.has_value());
|
|
EXPECT_EQ(savedMetadata1->m_name, "hello");
|
|
EXPECT_EQ(savedMetadata1->m_typeID, AssetA::GetTypeID());
|
|
EXPECT_EQ(savedMetadata1->m_typeName, eastl::string {AssetA::GetTypeName()});
|
|
EXPECT_EQ(savedMetadata1->m_modificationTime, savedMetadata1->m_creationTime);
|
|
|
|
const eastl::optional<eastl::vector<std::byte>> savedFlatbuffer1 = m_bigFile.GetAssetFlatbuffer(uuid);
|
|
ASSERT_TRUE(savedFlatbuffer1.has_value());
|
|
|
|
AssetA savedAsset1;
|
|
savedAsset1.Unpack(*savedFlatbuffer1);
|
|
EXPECT_EQ(savedAsset1.GetAsset().health, 1);
|
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
|
|
|
asset.GetAsset().health = 2;
|
|
m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = uuid,
|
|
.m_name = "world",
|
|
.m_typeID = AssetA::GetTypeID(),
|
|
.m_typeName = eastl::string {AssetA::GetTypeName()}},
|
|
asset.Pack());
|
|
|
|
const eastl::optional<AssetMetadata> savedMetadata2 = m_bigFile.GetAssetMetadata(uuid);
|
|
ASSERT_TRUE(savedMetadata2.has_value());
|
|
EXPECT_EQ(savedMetadata2->m_name, "world");
|
|
EXPECT_EQ(savedMetadata2->m_typeID, AssetA::GetTypeID());
|
|
EXPECT_EQ(savedMetadata2->m_typeName, eastl::string {AssetA::GetTypeName()});
|
|
EXPECT_GT(savedMetadata2->m_modificationTime, savedMetadata2->m_creationTime);
|
|
|
|
EXPECT_LT(savedMetadata1->m_modificationTime, savedMetadata2->m_modificationTime);
|
|
|
|
const eastl::optional<eastl::vector<std::byte>> savedFlatbuffer2 = m_bigFile.GetAssetFlatbuffer(uuid);
|
|
ASSERT_TRUE(savedFlatbuffer2.has_value());
|
|
|
|
AssetA savedAsset2;
|
|
savedAsset2.Unpack(*savedFlatbuffer2);
|
|
EXPECT_EQ(savedAsset2.GetAsset().health, 2);
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TEST_F(BigFileFixture, SaveAssetFlatbuffers_ShouldSaveTheAssets)
|
|
{
|
|
AssetA assetA;
|
|
assetA.SetName("hello");
|
|
assetA.GetAsset().health = 42;
|
|
|
|
AssetA assetB;
|
|
assetB.SetName("world");
|
|
assetB.GetAsset().health = 7;
|
|
|
|
const eastl::vector<AssetMetadata> metadatas {AssetMetadata {.m_uuid = assetA.GetHeader().uuid,
|
|
.m_name = assetA.GetHeader().name,
|
|
.m_typeID = assetA.GetHeader().type_id,
|
|
.m_typeName = assetA.GetHeader().type_name},
|
|
AssetMetadata {.m_uuid = assetB.GetHeader().uuid,
|
|
.m_name = assetB.GetHeader().name,
|
|
.m_typeID = assetB.GetHeader().type_id,
|
|
.m_typeName = assetB.GetHeader().type_name}};
|
|
const eastl::vector<eastl::vector<std::byte>> flatbuffers {assetA.Pack(), assetB.Pack()};
|
|
|
|
m_bigFile.SaveAssetFlatbuffers(metadatas, flatbuffers);
|
|
|
|
EXPECT_TRUE(m_bigFile.Has(assetA.GetHeader().uuid));
|
|
EXPECT_TRUE(m_bigFile.Has(assetB.GetHeader().uuid));
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TEST_F(BigFileFixture, SaveAssetFlatbuffers_ShouldUpdateTheDataWhenCalledTwice)
|
|
{
|
|
const UUID uuid;
|
|
|
|
AssetA asset;
|
|
asset.GetAsset().health = 1;
|
|
const eastl::vector<AssetMetadata> metadatas1 {AssetMetadata {.m_uuid = uuid,
|
|
.m_name = "hello",
|
|
.m_typeID = AssetA::GetTypeID(),
|
|
.m_typeName = eastl::string {AssetA::GetTypeName()}}};
|
|
const eastl::vector<eastl::vector<std::byte>> flatbuffers1 {asset.Pack()};
|
|
m_bigFile.SaveAssetFlatbuffers(metadatas1, flatbuffers1);
|
|
|
|
const eastl::optional<AssetMetadata> savedMetadata1 = m_bigFile.GetAssetMetadata(uuid);
|
|
ASSERT_TRUE(savedMetadata1.has_value());
|
|
EXPECT_EQ(savedMetadata1->m_name, "hello");
|
|
EXPECT_EQ(savedMetadata1->m_modificationTime, savedMetadata1->m_creationTime);
|
|
|
|
const eastl::optional<eastl::vector<std::byte>> savedFlatbuffer1 = m_bigFile.GetAssetFlatbuffer(uuid);
|
|
ASSERT_TRUE(savedFlatbuffer1.has_value());
|
|
|
|
AssetA savedAsset1;
|
|
savedAsset1.Unpack(*savedFlatbuffer1);
|
|
EXPECT_EQ(savedAsset1.GetAsset().health, 1);
|
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
|
|
|
asset.GetAsset().health = 2;
|
|
const eastl::vector<AssetMetadata> metadatas2 {AssetMetadata {.m_uuid = uuid,
|
|
.m_name = "world",
|
|
.m_typeID = AssetA::GetTypeID(),
|
|
.m_typeName = eastl::string {AssetA::GetTypeName()}}};
|
|
const eastl::vector<eastl::vector<std::byte>> flatbuffers2 {asset.Pack()};
|
|
m_bigFile.SaveAssetFlatbuffers(metadatas2, flatbuffers2);
|
|
|
|
const eastl::optional<AssetMetadata> savedMetadata2 = m_bigFile.GetAssetMetadata(uuid);
|
|
ASSERT_TRUE(savedMetadata2.has_value());
|
|
EXPECT_EQ(savedMetadata2->m_name, "world");
|
|
EXPECT_GT(savedMetadata2->m_modificationTime, savedMetadata2->m_creationTime);
|
|
|
|
EXPECT_LT(savedMetadata1->m_modificationTime, savedMetadata2->m_modificationTime);
|
|
|
|
const eastl::optional<eastl::vector<std::byte>> savedFlatbuffer2 = m_bigFile.GetAssetFlatbuffer(uuid);
|
|
ASSERT_TRUE(savedFlatbuffer2.has_value());
|
|
|
|
AssetA savedAsset2;
|
|
savedAsset2.Unpack(*savedFlatbuffer2);
|
|
EXPECT_EQ(savedAsset2.GetAsset().health, 2);
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TEST_F(BigFileFixture, Has_ShouldReturnTrueIfTheAssetExists)
|
|
{
|
|
AssetA asset;
|
|
asset.SetName("hello");
|
|
asset.GetAsset().health = 42;
|
|
asset.GetAsset().mana = 7;
|
|
const eastl::vector<std::byte> flatbuffer = asset.Pack();
|
|
|
|
const AssetMetadata metadata {.m_uuid = asset.GetHeader().uuid,
|
|
.m_name = asset.GetHeader().name,
|
|
.m_typeID = asset.GetHeader().type_id,
|
|
.m_typeName = asset.GetHeader().type_name};
|
|
|
|
m_bigFile.SaveAssetFlatbuffer(metadata, flatbuffer);
|
|
|
|
EXPECT_TRUE(m_bigFile.Has(asset.GetHeader().uuid));
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TEST_F(BigFileFixture, Has_ShouldReturnFalseIfTheAssetDoesNotExist)
|
|
{
|
|
EXPECT_FALSE(m_bigFile.Has(UUID {}));
|
|
}
|
|
#endif
|
|
} // namespace Bigfoot
|