Files
2026-09-21 12:15:57 +03:00

255 lines
12 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading;
using NUnit.Framework;
using Unity.Collections;
using UnityEditor.AddressableAssets.Build.Layout;
using UnityEditor.AddressableAssets.Diagnostics;
using UnityEditor.AddressableAssets.Settings;
using UnityEditor.Build.Pipeline;
using UnityEditor.VersionControl;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Playables;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.ResourceManagement.Profiling;
using UnityEngine.ResourceManagement.ResourceProviders;
using UnityEngine.ResourceManagement.Util;
using UnityEngine.TestTools;
using UnityEngine.UIElements;
using TreeView = UnityEditor.IMGUI.Controls.TreeView;
namespace UnityEditor.AddressableAssets.Tests.Diagnostics.Profiler
{
public class AddressablesProfilerDetailsViewTests
{
private static BuildLayout.ExplicitAsset m_TestAsset;
AddressablesProfilerDetailsView m_AddressablesProfilerDetailsView;
private TestProfiler testProfiler;
[SetUp]
public void SetUp()
{
// this is an implementation of the profiler interfaces to allow us to create profile events
// and then retrieve them for testing
testProfiler = new TestProfiler();
ProfilerRuntime.m_profilerEmitter = testProfiler;
ProfilerRuntime.Initialise();
AddressablesProfilerDetailsView.m_frameDataStore = testProfiler;
AddressablesProfilerViewController.LayoutsManager.ClearReports();
m_AddressablesProfilerDetailsView = new AddressablesProfilerDetailsView(null);
m_TestAsset = new BuildLayout.ExplicitAsset
{
AddressableName = "MainScene",
AssetPath = "Assets/Scenes/MainScene.unity",
Guid = new Hash128().ToString()
};
}
[TearDown]
public void TearDown()
{
m_AddressablesProfilerDetailsView.Dispose();
}
[Test]
public void Test_GenerateContentData_EmptyFrameData()
{
AddressablesProfilerDetailsView.FrameData frameData = new AddressablesProfilerDetailsView.FrameData(1);
List<GroupData> groupData = m_AddressablesProfilerDetailsView.GenerateContentDataForFrame(frameData);
Assert.AreEqual(0, groupData.Count);
}
[Test]
public void Test_GenerateContentData_ValidData()
{
Test_GenerateContentData_FrameData(true, true, true, true);
}
[Test]
public void Test_GenerateContentData_MissingReferencedBundle()
{
LogAssert.Expect(LogType.Warning, "Asset Assets/AddressMe/brown.bmp referenced bundle folder_assets_assets/addressme_3876ae7ae6d93912555c4c93ef6e3fd7.bundle not loaded from build layout, attaching to parent scene_scenes_all_ea5d4d944831b5303deb66b664bd2e25.bundle");
Test_GenerateContentData_FrameData(true, true, true, false);
}
private void Test_GenerateContentData_FrameData(bool loadTextureBundle, bool loadSceneBundle, bool loadLocalAssets, bool loadFolderBundle)
{
AddressablesProfilerViewController.LayoutsManager.LoadManualReport(AddressablesTestUtility.GetPackagePath() + "/Tests/Editor/Fixtures/buildlayout1.json");
AddressablesProfilerViewController.LayoutsManager.AddActiveLayout("3e22efc5f159401a15e7d27179b7cc4c"); // this is the value of BuildResultHash in buildlayout1.json
// this creates the build report
// var builder = new BuildLayoutBuilder().AddGroup("Remote Content").AddBundle("a.bundle").AddAsset("test.asset", "https://example.com/a.bundle").AddToLayoutManager();
// texture bundle
if (loadTextureBundle)
{
var bundleEvents = new ProfilerEventBuilder(testProfiler).SetBundleName("c75e210455b9b7f32a8e902db35e6ee3")
.SendBundleEvent(1, ContentStatus.Loading)
.SendBundleEvent(2, ContentStatus.Active)
.SendBundleEvent(3, ContentStatus.Released);
}
// scene bundle
if (loadSceneBundle)
{
var bundleEvents2 = new ProfilerEventBuilder(testProfiler).SetBundleName("79f2518976c47599628aad579c012657")
.SendBundleEvent(1, ContentStatus.Loading)
.SendBundleEvent(2, ContentStatus.Active)
.SendBundleEvent(3, ContentStatus.Released);
}
// default local assets
if (loadLocalAssets)
{
var bundleEvents3 = new ProfilerEventBuilder(testProfiler).SetBundleName("0113602827489280bf434abd9b49426c")
.SendBundleEvent(1, ContentStatus.Loading)
.SendBundleEvent(2, ContentStatus.Active)
.SendBundleEvent(3, ContentStatus.Released);
}
// folder bundle
if (loadFolderBundle)
{
var bundleEvents4 = new ProfilerEventBuilder(testProfiler).SetBundleName("6801756afe332320683f01526bb77e3d")
.SendBundleEvent(1, ContentStatus.Loading)
.SendBundleEvent(2, ContentStatus.Active)
.SendBundleEvent(3, ContentStatus.Released);
}
var sceneEvents = new ProfilerEventBuilder(testProfiler)
.SetAssetLocation("Assets/Scenes/SampleScene.unity", "79f2518976c47599628aad579c012657") // FIXME, should this take a builder so it can look this up for us?
.SendSceneEvent(1, ContentStatus.Loading)
.SendSceneEvent(2, ContentStatus.Active)
.SendSceneEvent(3, ContentStatus.Released);
var assetEvents = new ProfilerEventBuilder(testProfiler)
.SetAssetLocation("Assets/khaki.png", "a1dd26be86668e2320052da88bcb6d39") // FIXME, should this take a builder so it can look this up for us?
.SendAssetEvent(1, ContentStatus.Loading)
.SendAssetEvent(2, ContentStatus.Active); // assets do not have an explicit released event
// so this is an internal prefab, I need one with external references
var embeddedPrefabEvents = new ProfilerEventBuilder(testProfiler)
.SetAssetLocation("Assets/Prefabs/YellowCube.prefab", "c75e210455b9b7f32a8e902db35e6ee3") // FIXME, should this take a builder so it can look this up for us?
.SendAssetEvent(1, ContentStatus.Loading)
.SendAssetEvent(2, ContentStatus.Active); // assets do not have an explicit released event
var referencePrefabEvents = new ProfilerEventBuilder(testProfiler)
.SetAssetLocation("Assets/Prefabs/Canvas.prefab", "c75e210455b9b7f32a8e902db35e6ee3") // FIXME, should this take a builder so it can look this up for us?
.SendAssetEvent(1, ContentStatus.Loading)
.SendAssetEvent(2, ContentStatus.Active); // assets do not have an explicit released event
// this simulates clicking each frame in the UI, retrieving data and verifying what is returned
for (int i = 1; i <= 2; i++)
{
AddressablesProfilerDetailsView.FrameData frameData = new AddressablesProfilerDetailsView.FrameData(i);
List<GroupData> groupData = m_AddressablesProfilerDetailsView.GenerateContentDataForFrame(frameData);
Assert.AreEqual("Prefabs", groupData[0].Name);
Assert.GreaterOrEqual(groupData[0].Children.Count, 1);
Assert.AreEqual("prefabs_assets_texture_8d87ce5cdbde7dec1bdded52918590d0.bundle", groupData[0].Children[0].Name);
foreach (var child in groupData[0].Children)
{
if (child is AssetData)
{
assetEvents.VerifyFrameStatus(i, child.Status);
}
}
}
}
[Test]
public void Test_GetAssetDataForFrameData_HasData()
{
AssetFrameData frameData = new AssetFrameData
{
AssetCode = 1,
BundleCode = 10,
Status = ContentStatus.Downloading
};
var bundleCodeToData = GetBundleCodeToData();
var retVal = m_AddressablesProfilerDetailsView.GetAssetDataForFrameData(m_TestAsset, frameData, bundleCodeToData);
Assert.AreEqual(ContentStatus.Downloading, retVal.Status);
Assert.AreEqual(bundleCodeToData[10], retVal.Parent);
Assert.AreEqual(m_TestAsset.AssetPath, retVal.AssetPath);
Assert.AreEqual(m_TestAsset.AddressableName, retVal.Name);
Assert.AreEqual(m_TestAsset.Guid, retVal.AssetGuid);
}
[Test]
public void Test_GetAssetDataForFrameData_NoData()
{
// the BundleCode is used to lookup the asset frame data, so since these
// don't match we expect to get null
AssetFrameData frameData = new AssetFrameData
{
AssetCode = 1,
BundleCode = 20,
Status = ContentStatus.Downloading
};
var retVal = m_AddressablesProfilerDetailsView.GetAssetDataForFrameData(m_TestAsset, frameData, GetBundleCodeToData());
Assert.IsNull(retVal);
}
private Dictionary<int, BundleData> GetBundleCodeToData() => new()
{
{ 10, new BundleData(new BuildLayout.Bundle(), new BundleFrameData()) }
};
[Test]
[TestCase(null)]
[TestCase("Assets/Cube.prefab")]
public void Test_ExplicitAssetsHaveUniqueTreeViewIDs(string assetPath1)
{
// These two GUID strings evaluate to the same hashcode.
var cube = new BuildLayout.ExplicitAsset
{
AssetPath = assetPath1,
Guid = "bf1daffab47bbb34587f194ac0dcc1bf"
};
var sphere = new BuildLayout.ExplicitAsset
{
AssetPath = "Assets/Sphere.prefab",
Guid = "61a57bae3cb0cec499b6e6b8db8f4008"
};
var cubeData = new AssetData(cube);
var sphereData = new AssetData(sphere);
Assert.AreNotEqual(cubeData.TreeViewID, sphereData.TreeViewID, "Explicit assets should have unique TreeViewIds.");
}
[Test]
public void TestHasValues()
{
testProfiler.CurrentFrame = 1;
testProfiler.EmitFrameMetaData(ProfilerRuntime.kResourceManagerProfilerGuid, ProfilerRuntime.kCatalogTag, new CatalogFrameData[] {});
testProfiler.CurrentFrame = 2;
testProfiler.EmitFrameMetaData(ProfilerRuntime.kResourceManagerProfilerGuid, ProfilerRuntime.kCatalogTag, new CatalogFrameData[] {new CatalogFrameData()});
testProfiler.CurrentFrame = 3;
testProfiler.EmitFrameMetaData(ProfilerRuntime.kResourceManagerProfilerGuid, ProfilerRuntime.kCatalogTag, new CatalogFrameData[] {new CatalogFrameData(), new CatalogFrameData()});
AddressablesProfilerDetailsView.FrameData frameData = new AddressablesProfilerDetailsView.FrameData(1);
Assert.False(frameData.HasValues);
AssertEnumerableSize(frameData.CatalogValues, 0);
frameData = new AddressablesProfilerDetailsView.FrameData(2);
Assert.True(frameData.HasValues);
AssertEnumerableSize(frameData.CatalogValues, 1);
frameData = new AddressablesProfilerDetailsView.FrameData(3);
Assert.True(frameData.HasValues);
AssertEnumerableSize(frameData.CatalogValues, 2);
}
private void AssertEnumerableSize(IEnumerable<CatalogFrameData> values, int expected)
{
int valueCount = 0;
foreach (var data in values)
{
valueCount++;
}
Assert.AreEqual(expected, valueCount);
}
}
}