#include #include #include #include #include #include #include #include #include #include #include using namespace XCEngine::Resources; namespace { std::vector 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& bytes) { std::ofstream output(path, std::ios::binary | std::ios::trunc); output.write(reinterpret_cast(bytes.data()), static_cast(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 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(result.resource); EXPECT_EQ(volumeField->GetStorageKind(), VolumeStorageKind::NanoVDB); EXPECT_EQ(volumeField->GetPayloadSize(), bytes.size()); EXPECT_EQ(static_cast(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(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 bytes = MakeTestNanoVDBPayload(); fs::remove_all(projectRoot); fs::create_directories(assetsDir); WriteBinaryFile(volumePath, bytes); manager.SetResourceRoot(projectRoot.string().c_str()); { const auto firstHandle = manager.Load("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(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