Files
XCEngine/tests/Resources/Volume/test_volume_field_loader.cpp

156 lines
5.6 KiB
C++
Raw Normal View History

2026-04-08 19:45:53 +08:00
#include <gtest/gtest.h>
#include <XCEngine/Core/Asset/AssetDatabase.h>
#include <XCEngine/Core/Asset/AssetRef.h>
#include <XCEngine/Core/Asset/ResourceManager.h>
#include <XCEngine/Resources/Volume/VolumeField.h>
#include <XCEngine/Resources/Volume/VolumeFieldLoader.h>
#include <chrono>
#include <filesystem>
#include <fstream>
#include <thread>
#include <vector>
using namespace XCEngine::Resources;
namespace {
std::vector<unsigned char> MakeTestNanoVDBPayload() {
return {
0x4E, 0x56, 0x44, 0x42,
0x10, 0x20, 0x30, 0x40,
0x01, 0x03, 0x05, 0x07,
0xAA, 0xBB, 0xCC, 0xDD
};
}
void WriteBinaryFile(const std::filesystem::path& path, const std::vector<unsigned char>& bytes) {
std::ofstream output(path, std::ios::binary | std::ios::trunc);
output.write(reinterpret_cast<const char*>(bytes.data()), static_cast<std::streamsize>(bytes.size()));
}
TEST(VolumeFieldLoader, GetResourceType) {
VolumeFieldLoader loader;
EXPECT_EQ(loader.GetResourceType(), ResourceType::VolumeField);
}
TEST(VolumeFieldLoader, CanLoad) {
VolumeFieldLoader loader;
EXPECT_TRUE(loader.CanLoad("cloud.nvdb"));
EXPECT_TRUE(loader.CanLoad("cloud.xcvol"));
EXPECT_FALSE(loader.CanLoad("cloud.txt"));
}
TEST(VolumeFieldLoader, LoadInvalidPath) {
VolumeFieldLoader loader;
LoadResult result = loader.Load("invalid/path/cloud.nvdb");
EXPECT_FALSE(result);
}
TEST(VolumeFieldLoader, LoadSourceNanoVDBBlob) {
namespace fs = std::filesystem;
const fs::path volumePath = fs::temp_directory_path() / "xc_volume_loader_source_test.nvdb";
const std::vector<unsigned char> bytes = MakeTestNanoVDBPayload();
WriteBinaryFile(volumePath, bytes);
VolumeFieldLoader loader;
LoadResult result = loader.Load(volumePath.string().c_str());
ASSERT_TRUE(result);
ASSERT_NE(result.resource, nullptr);
auto* volumeField = static_cast<VolumeField*>(result.resource);
EXPECT_EQ(volumeField->GetStorageKind(), VolumeStorageKind::NanoVDB);
EXPECT_EQ(volumeField->GetPayloadSize(), bytes.size());
EXPECT_EQ(static_cast<const unsigned char*>(volumeField->GetPayloadData())[0], bytes[0]);
delete volumeField;
fs::remove(volumePath);
}
TEST(VolumeFieldLoader, AssetDatabaseCreatesVolumeArtifactAndReusesItWithoutReimport) {
namespace fs = std::filesystem;
using namespace std::chrono_literals;
const fs::path projectRoot = fs::temp_directory_path() / "xc_volume_library_cache_test";
const fs::path assetsDir = projectRoot / "Assets";
const fs::path volumePath = assetsDir / "cloud.nvdb";
fs::remove_all(projectRoot);
fs::create_directories(assetsDir);
WriteBinaryFile(volumePath, MakeTestNanoVDBPayload());
AssetDatabase database;
database.Initialize(projectRoot.string().c_str());
AssetDatabase::ResolvedAsset firstResolve;
ASSERT_TRUE(database.EnsureArtifact("Assets/cloud.nvdb", ResourceType::VolumeField, firstResolve));
ASSERT_TRUE(firstResolve.exists);
ASSERT_TRUE(firstResolve.artifactReady);
EXPECT_TRUE(fs::exists(firstResolve.artifactMainPath.CStr()));
EXPECT_EQ(fs::path(firstResolve.artifactMainPath.CStr()).extension().generic_string(), ".xcvol");
VolumeFieldLoader loader;
LoadResult artifactLoad = loader.Load(firstResolve.artifactMainPath);
ASSERT_TRUE(artifactLoad);
ASSERT_NE(artifactLoad.resource, nullptr);
auto* artifactVolume = static_cast<VolumeField*>(artifactLoad.resource);
EXPECT_EQ(artifactVolume->GetStorageKind(), VolumeStorageKind::NanoVDB);
EXPECT_EQ(artifactVolume->GetPayloadSize(), MakeTestNanoVDBPayload().size());
delete artifactVolume;
const auto originalArtifactWriteTime = fs::last_write_time(firstResolve.artifactMainPath.CStr());
std::this_thread::sleep_for(50ms);
AssetDatabase::ResolvedAsset secondResolve;
ASSERT_TRUE(database.EnsureArtifact("Assets/cloud.nvdb", ResourceType::VolumeField, secondResolve));
EXPECT_EQ(firstResolve.artifactMainPath, secondResolve.artifactMainPath);
EXPECT_EQ(originalArtifactWriteTime, fs::last_write_time(secondResolve.artifactMainPath.CStr()));
database.Shutdown();
fs::remove_all(projectRoot);
}
TEST(VolumeFieldLoader, ResourceManagerLoadsVolumeByAssetRefFromProjectAssets) {
namespace fs = std::filesystem;
ResourceManager& manager = ResourceManager::Get();
manager.Initialize();
const fs::path projectRoot = fs::temp_directory_path() / "xc_volume_asset_ref_test";
const fs::path assetsDir = projectRoot / "Assets";
const fs::path volumePath = assetsDir / "cloud.nvdb";
const std::vector<unsigned char> bytes = MakeTestNanoVDBPayload();
fs::remove_all(projectRoot);
fs::create_directories(assetsDir);
WriteBinaryFile(volumePath, bytes);
manager.SetResourceRoot(projectRoot.string().c_str());
{
const auto firstHandle = manager.Load<VolumeField>("Assets/cloud.nvdb");
ASSERT_TRUE(firstHandle.IsValid());
EXPECT_EQ(firstHandle->GetStorageKind(), VolumeStorageKind::NanoVDB);
EXPECT_EQ(firstHandle->GetPayloadSize(), bytes.size());
AssetRef assetRef;
ASSERT_TRUE(manager.TryGetAssetRef("Assets/cloud.nvdb", ResourceType::VolumeField, assetRef));
EXPECT_TRUE(assetRef.IsValid());
manager.UnloadAll();
const auto secondHandle = manager.Load<VolumeField>(assetRef);
ASSERT_TRUE(secondHandle.IsValid());
EXPECT_EQ(secondHandle->GetStorageKind(), VolumeStorageKind::NanoVDB);
EXPECT_EQ(secondHandle->GetPayloadSize(), bytes.size());
}
manager.SetResourceRoot("");
manager.Shutdown();
fs::remove_all(projectRoot);
}
} // namespace