initial commit

This commit is contained in:
Jo 2025-01-07 02:06:59 +01:00
parent 6715289efe
commit 788c3389af
37645 changed files with 2526849 additions and 80 deletions

View file

@ -0,0 +1,648 @@
using System;
using System.Collections.Generic;
using System.IO;
using AddressableAssetsIntegrationTests;
using NUnit.Framework;
using UnityEditor.AddressableAssets.Build.BuildPipelineTasks;
using UnityEditor.AddressableAssets.Build.Layout;
using UnityEditor.Animations;
using UnityEngine;
namespace UnityEditor.AddressableAssets.Tests.Diagnostics
{
public class BuildLayoutTests
{
private BuildLayout.ExplicitAsset CreateExplicitAssetWithParentBundle(BuildLayout.Bundle parent, ulong filesize = 1)
{
BuildLayout.ExplicitAsset asset = new BuildLayout.ExplicitAsset();
asset.Bundle = parent;
asset.SerializedSize = filesize;
return asset;
}
private BuildLayout.Bundle CreateBundleWithFileSize(ulong filesize, string name = "default")
{
var bundle = new BuildLayout.Bundle();
bundle.Name = name;
bundle.FileSize = (ulong) filesize;
return bundle;
}
private BuildLayout.Bundle CreateBundleWithFileSize(int assetCount, string name = "default")
{
var bundle = new BuildLayout.Bundle();
bundle.AssetCount = assetCount;
bundle.Name = name;
bundle.FileSize = (ulong) assetCount;
return bundle;
}
[Test]
public void BuildLayoutBundle_CalculateEfficiency_CorrectlyWorksInSimpleCase()
{
BuildLayout.Bundle parent = CreateBundleWithFileSize(5);
BuildLayout.Bundle child = CreateBundleWithFileSize(10);
BuildLayout.ExplicitAsset parentAsset = CreateExplicitAssetWithParentBundle(parent);
BuildLayout.ExplicitAsset childAsset = CreateExplicitAssetWithParentBundle(child);
child.DependentBundles.Add(parent);
parent.UpdateBundleDependency(parentAsset, childAsset);
parent.SerializeBundleToBundleDependency();
BuildLayoutGenerationTask.CalculateEfficiency(parent);
float expectedEfficiency = .10f;
Assert.AreEqual(expectedEfficiency, parent.BundleDependencies[0].ExpandedEfficiency);
}
[Test]
public void BuildLayoutBundle_CalculateEfficiency_MultipleAssetDependencyCaseStillCreatesCorrectEfficiency()
{
BuildLayout.Bundle parent = CreateBundleWithFileSize(5);
BuildLayout.Bundle child = CreateBundleWithFileSize(10);
BuildLayout.ExplicitAsset parentAsset = CreateExplicitAssetWithParentBundle(parent);
for (int i = 0; i < 10; i++)
{
var asset = CreateExplicitAssetWithParentBundle(child);
parent.UpdateBundleDependency(parentAsset, asset);
}
parent.SerializeBundleToBundleDependency();
BuildLayoutGenerationTask.CalculateEfficiency(parent);
float expectedEfficiency = 1f;
Assert.AreEqual(expectedEfficiency, parent.BundleDependencies[0].ExpandedEfficiency);
}
[Test]
[TestCase(5, 10, 1, 5)]
[TestCase(6, 12, 2, 7)]
[TestCase(20, 43, 7, 15)]
[TestCase(27, 68, 25, 60)]
public void BuildLayoutBundle_CalculateEfficiency_ThreeLayeredTreeGeneratesCorrectEfficiencyAtAllLevels(
int parentAssetCount,
int childAssetCount,
int parentDependencyCount,
int childDependencyCount)
{
BuildLayout.Bundle grandparent = CreateBundleWithFileSize(1);
BuildLayout.Bundle parent = CreateBundleWithFileSize(parentAssetCount);
BuildLayout.Bundle child = CreateBundleWithFileSize(childAssetCount);
BuildLayout.ExplicitAsset grandparentAsset = CreateExplicitAssetWithParentBundle(grandparent);
List<BuildLayout.ExplicitAsset> parentAssets = new List<BuildLayout.ExplicitAsset>();
for (int i = 0; i < parentDependencyCount; i++)
{
var parentAsset = CreateExplicitAssetWithParentBundle(parent);
grandparent.UpdateBundleDependency(grandparentAsset, parentAsset);
parentAssets.Add(parentAsset);
}
for (int i = 0; i < childDependencyCount; i++)
{
var childAsset = CreateExplicitAssetWithParentBundle(child);
parent.UpdateBundleDependency(parentAssets[0], childAsset);
}
grandparent.SerializeBundleToBundleDependency();
parent.SerializeBundleToBundleDependency();
BuildLayoutGenerationTask.CalculateEfficiency(grandparent);
float expectedGrandparentEfficiency = (float) parentDependencyCount / parentAssetCount;
float expectedGrandparentExpandedEfficiency = (float) (childDependencyCount + parentDependencyCount) / (childAssetCount + parentAssetCount);
float expectedParentEfficiency = (float) childDependencyCount / childAssetCount;
Assert.AreEqual(expectedGrandparentEfficiency, grandparent.BundleDependencies[0].Efficiency, "Grandparent Efficiency not calculated correctly - this should not be affected by the children of parent.");
Assert.AreEqual(expectedGrandparentExpandedEfficiency, grandparent.BundleDependencies[0].ExpandedEfficiency, "Grandparent ExpandedEfficiency not calculated correctly - this should take into account the total Efficiency of both the direct children Dependency Links as well as all BundleDependencies below the child.");
Assert.AreEqual(expectedParentEfficiency, parent.BundleDependencies[0].ExpandedEfficiency, "Parent ExpandedEfficiency not calculated correctly - this should take into account the Efficiency of the direct child only.");
}
[Test]
public void BuildLayoutBundle_CalculateEfficiency_AssetDependenciesAreNotDoubleCounted()
{
var parentBundle = CreateBundleWithFileSize(1);
var childBundle = CreateBundleWithFileSize(1);
var parentAsset = CreateExplicitAssetWithParentBundle(parentBundle);
var childAsset = CreateExplicitAssetWithParentBundle(childBundle);
parentBundle.UpdateBundleDependency(parentAsset, childAsset);
parentBundle.SerializeBundleToBundleDependency();
BuildLayoutGenerationTask.CalculateEfficiency(parentBundle);
Assert.AreEqual(1f, parentBundle.BundleDependencies[0].ExpandedEfficiency, "ExpandedEfficiency not correctly calculated");
Assert.AreEqual(1f, parentBundle.BundleDependencies[0].Efficiency, "Efficiency not correctly calculated");
}
[Test]
[TestCase(3, 3, 1, 1 )]
[TestCase(50, 5, 5, 2)]
[TestCase(100, 100, 1, 50)]
public void BuildLayoutBundle_CalculateEfficiency_MultiProngedShortTreeGeneratesCorrectEfficiency(
int child1AssetCount,
int child2AssetCount,
int child1DependencyCount,
int child2DependencyCount)
{
BuildLayout.Bundle parentBundle = CreateBundleWithFileSize(2);
BuildLayout.Bundle childBundle1 = CreateBundleWithFileSize(child1AssetCount);
BuildLayout.Bundle childBundle2 = CreateBundleWithFileSize(child2AssetCount);
var parentAsset1 = CreateExplicitAssetWithParentBundle(parentBundle);
var parentAsset2 = CreateExplicitAssetWithParentBundle(parentBundle);
for (int i = 0; i < child1DependencyCount; i++)
{
var childAsset = CreateExplicitAssetWithParentBundle(childBundle1);
parentBundle.UpdateBundleDependency(parentAsset1, childAsset);
}
for (int i = 0; i < child2DependencyCount; i++)
{
var childAsset = CreateExplicitAssetWithParentBundle(childBundle2);
parentBundle.UpdateBundleDependency(parentAsset2, childAsset);
}
parentBundle.SerializeBundleToBundleDependency();
BuildLayoutGenerationTask.CalculateEfficiency(parentBundle);
float expectedChild1Efficiency = (float) child1DependencyCount / child1AssetCount;
float expectedChild2Efficiency = (float) child2DependencyCount / child2AssetCount;
Assert.AreEqual(expectedChild1Efficiency, parentBundle.BundleDependencies[0].ExpandedEfficiency);
Assert.AreEqual(expectedChild2Efficiency, parentBundle.BundleDependencies[1].ExpandedEfficiency);
}
[Test]
public void BuildLayoutBundle_CalculateEfficiency_DoesNotDoubleCountDependencies()
{
BuildLayout.Bundle parent = CreateBundleWithFileSize(2);
BuildLayout.Bundle child = CreateBundleWithFileSize(2);
BuildLayout.ExplicitAsset parentAsset1 = CreateExplicitAssetWithParentBundle(parent);
BuildLayout.ExplicitAsset parentAsset2 = CreateExplicitAssetWithParentBundle(parent);
BuildLayout.ExplicitAsset childAsset1 = CreateExplicitAssetWithParentBundle(child);
parent.UpdateBundleDependency(parentAsset1, childAsset1);
parent.UpdateBundleDependency(parentAsset2, childAsset1);
parent.SerializeBundleToBundleDependency();
BuildLayoutGenerationTask.CalculateEfficiency(parent);
float expectedEfficiency = .5f;
Assert.AreEqual(expectedEfficiency, parent.BundleDependencies[0].ExpandedEfficiency, "If multiple assets in a parent bundle depend on a single asset in the child, this reliance should not be double counted.");
Assert.AreEqual(expectedEfficiency, parent.BundleDependencies[0].Efficiency, "If multiple assets in a parent bundle depend on a single asset in the child, this reliance should not be double counted.");
}
[Test]
[TestCase(2, 1, 1, 1, 1)]
[TestCase(2, 5, 5, 2, 3)]
[TestCase(10, 3,3, 3,3)]
[TestCase(30, 30, 30, 20, 20)]
[TestCase(50, 50, 50, 50, 50)]
public void BuildLayoutBundle_CalculateEfficiency_HigherLevelTreesCorrectlyPromulgateLowerLevelEfficiency(
int parentAssetCount,
int child1AssetCount,
int child2AssetCount,
int child1DependencyCount,
int child2DependencyCount)
{
BuildLayout.Bundle grandparent = CreateBundleWithFileSize(1);
BuildLayout.Bundle parent = CreateBundleWithFileSize(parentAssetCount);
BuildLayout.Bundle childBundle1 = CreateBundleWithFileSize(child1AssetCount);
BuildLayout.Bundle childBundle2 = CreateBundleWithFileSize(child2AssetCount);
BuildLayout.ExplicitAsset grandparentAsset = CreateExplicitAssetWithParentBundle(grandparent);
BuildLayout.ExplicitAsset parentAsset = CreateExplicitAssetWithParentBundle(parent);
grandparent.UpdateBundleDependency(grandparentAsset, parentAsset);
for (int i = 0; i < child1DependencyCount; i++)
{
var childAsset = CreateExplicitAssetWithParentBundle(childBundle1);
parent.UpdateBundleDependency(parentAsset, childAsset);
}
for (int i = 0; i < child2DependencyCount; i++)
{
var childAsset = CreateExplicitAssetWithParentBundle(childBundle2);
parent.UpdateBundleDependency(parentAsset, childAsset);
}
grandparent.SerializeBundleToBundleDependency();
parent.SerializeBundleToBundleDependency();
BuildLayoutGenerationTask.CalculateEfficiency(grandparent);
float expectedGrandparentToParentEfficiency = (float) 1 / parentAssetCount;
float expectedGrandparentToParentExpandedEfficiency = (float) (1 + child1DependencyCount + child2DependencyCount) / (parentAssetCount + child1AssetCount + child2AssetCount);
float expectedParentToChild1Efficiency = (float) child1DependencyCount / child1AssetCount;
float expectedParentToChild2Efficiency = (float) child2DependencyCount / child2AssetCount;
Assert.AreEqual(expectedGrandparentToParentEfficiency, grandparent.BundleDependencies[0].Efficiency);
Assert.AreEqual(expectedGrandparentToParentExpandedEfficiency, grandparent.BundleDependencies[0].ExpandedEfficiency);
Assert.AreEqual(expectedParentToChild1Efficiency, parent.BundleDependencies[0].Efficiency);
Assert.AreEqual(expectedParentToChild2Efficiency, parent.BundleDependencies[1].Efficiency);
}
[Test]
[TestCase(5, 10, 10, 3, 5)]
[TestCase(7, 20, 15, 5, 8)]
[TestCase(11, 35, 40, 15, 20)]
public void BuildLayoutBundle_CalculateEfficiency_CacheCorrectlyAvoidsDoubleComputation(
int parentAssetCount,
int child1AssetCount,
int child2AssetCount,
int child1DependencyCount,
int child2DependencyCount)
{
BuildLayout.Bundle grandparent1 = CreateBundleWithFileSize(1);
BuildLayout.Bundle grandparent2 = CreateBundleWithFileSize(1);
BuildLayout.Bundle parent = CreateBundleWithFileSize(parentAssetCount);
BuildLayout.Bundle child1 = CreateBundleWithFileSize(child1AssetCount);
BuildLayout.Bundle child2 = CreateBundleWithFileSize(child2AssetCount);
BuildLayout.ExplicitAsset grandparent1Asset = CreateExplicitAssetWithParentBundle(grandparent1);
BuildLayout.ExplicitAsset grandparent2Asset = CreateExplicitAssetWithParentBundle(grandparent2);
BuildLayout.ExplicitAsset parentAsset = CreateExplicitAssetWithParentBundle(parent);
grandparent1.UpdateBundleDependency(grandparent1Asset, parentAsset);
grandparent2.UpdateBundleDependency(grandparent2Asset, parentAsset);
for (int i = 0; i < child1DependencyCount; i++)
{
var childAsset = CreateExplicitAssetWithParentBundle(child1);
parent.UpdateBundleDependency(parentAsset, childAsset);
}
for (int i = 0; i < child2DependencyCount; i++)
{
var childAsset = CreateExplicitAssetWithParentBundle(child2);
parent.UpdateBundleDependency(parentAsset, childAsset);
}
Dictionary<BuildLayout.Bundle.BundleDependency, BuildLayout.Bundle.EfficiencyInfo> bdCache = new Dictionary<BuildLayout.Bundle.BundleDependency, BuildLayout.Bundle.EfficiencyInfo>();
grandparent1.SerializeBundleToBundleDependency();
grandparent2.SerializeBundleToBundleDependency();
parent.SerializeBundleToBundleDependency();
BuildLayoutGenerationTask.CalculateEfficiency(grandparent1, bdCache);
var ef1 = new BuildLayout.Bundle.EfficiencyInfo
{
totalAssetFileSize = (ulong) child1AssetCount,
referencedAssetFileSize = (ulong) child1DependencyCount
};
var ef2 = new BuildLayout.Bundle.EfficiencyInfo
{
totalAssetFileSize = (ulong) child2AssetCount,
referencedAssetFileSize = (ulong) child2DependencyCount
};
float bd1Efficiency = (float) child1DependencyCount / child1AssetCount;
float bd2Efficiency = (float) child2DependencyCount / child2AssetCount;
float gp1Efficiency = (float) (1 + child1DependencyCount + child2DependencyCount) / (parentAssetCount + child1AssetCount + child2AssetCount);
Assert.IsTrue(bdCache.ContainsKey(parent.BundleDependencies[0]), "BundleDependencyCache not properly populated");
Assert.AreEqual(bdCache[parent.BundleDependencies[0]], ef1);
Assert.AreEqual(parent.BundleDependencies[0].ExpandedEfficiency, bd1Efficiency);
Assert.IsTrue(bdCache.ContainsKey(parent.BundleDependencies[1]), "BundleDependencyCache not properly populated");
Assert.AreEqual(bdCache[parent.BundleDependencies[1]], ef2);
Assert.AreEqual(parent.BundleDependencies[1].ExpandedEfficiency, bd2Efficiency);
Assert.AreEqual(grandparent1.BundleDependencies[0].ExpandedEfficiency, gp1Efficiency);
// Create a new asset that is not cached - we do this to ensure that cached values are used and that we're not recalculating Efficiency
// This will never happen in normal execution - this is just a workaround to make sure the cache is working properly.
var uncachedAsset = CreateExplicitAssetWithParentBundle(child1);
parent.UpdateBundleDependency(parentAsset, uncachedAsset);
BuildLayoutGenerationTask.CalculateEfficiency(grandparent2, bdCache);
Assert.IsTrue(bdCache.ContainsKey(parent.BundleDependencies[0]), "Key should not be removed");
Assert.AreEqual(bdCache[parent.BundleDependencies[0]], ef1, "Efficiency should not change since cached value should be used");
Assert.AreEqual(parent.BundleDependencies[0].ExpandedEfficiency, bd1Efficiency, "Efficiency should not change since cached value should be used.");
Assert.AreEqual(grandparent2.BundleDependencies[0].ExpandedEfficiency, gp1Efficiency, "Efficiency of grandparent2 should be equal to grandparent1, since cache was used.");
//Calculation without cache should be incorrect
BuildLayoutGenerationTask.CalculateEfficiency(grandparent2);
Assert.AreNotEqual(parent.BundleDependencies[0].ExpandedEfficiency, bd1Efficiency, "Efficiency should change since cached value is not used");
Assert.AreNotEqual(grandparent2.BundleDependencies[0].ExpandedEfficiency, gp1Efficiency, "Efficiency of grandparent2 should not be equal to grandparent1 since cache isnt used");
}
[Test]
[TestCase(5, 5, 5, 3, 2, 3, 4)]
[TestCase(50, 2, 10, 10, 1, 2, 4)]
[TestCase(1, 1, 1, 1, 1, 1, 1)]
[TestCase(100, 100, 100, 20, 30, 40, 40)]
public void BuildLayoutBundle_CalculateEfficiency_NonTreeStructureProperlyHandled(
int bundleBAssetCount,
int bundleCAssetCount,
int bundleDAssetCount,
int bundleBDependencyCount,
int bundleBToBundleCDependencyCount,
int bundleCDependencyCount,
int bundleDDependencyCount)
{
BuildLayout.Bundle bundleA = CreateBundleWithFileSize(1);
BuildLayout.Bundle bundleB = CreateBundleWithFileSize(bundleBAssetCount);
BuildLayout.Bundle bundleC = CreateBundleWithFileSize(bundleCAssetCount);
BuildLayout.Bundle bundleD = CreateBundleWithFileSize(bundleDAssetCount);
var assetA = CreateExplicitAssetWithParentBundle(bundleA);
var assetB = CreateExplicitAssetWithParentBundle(bundleB);
var assetC = CreateExplicitAssetWithParentBundle(bundleC);
bundleA.UpdateBundleDependency(assetA, assetB);
for (int i = 0; i < bundleBDependencyCount - 1; i++)
{
var childAsset = CreateExplicitAssetWithParentBundle(bundleB);
bundleA.UpdateBundleDependency(assetA, childAsset);
}
bundleA.UpdateBundleDependency(assetA, assetC);
for (int i = 0; (i < bundleCDependencyCount - 1) || (i < bundleBToBundleCDependencyCount); i++)
{
var childAsset = CreateExplicitAssetWithParentBundle(bundleC);
if (i < bundleCDependencyCount - 1)
bundleA.UpdateBundleDependency(assetA, childAsset);
if (i < bundleBToBundleCDependencyCount)
bundleB.UpdateBundleDependency(assetB, childAsset);
}
for (int i = 0; i < bundleDDependencyCount; i++)
{
var childAsset = CreateExplicitAssetWithParentBundle(bundleD);
bundleC.UpdateBundleDependency(assetC, childAsset);
}
bundleA.SerializeBundleToBundleDependency();
bundleB.SerializeBundleToBundleDependency();
bundleC.SerializeBundleToBundleDependency();
bundleD.SerializeBundleToBundleDependency();
BuildLayoutGenerationTask.CalculateEfficiency(bundleA);
var cToDExpandedEfficiency = (float)bundleDDependencyCount / bundleDAssetCount;
var BToCExpandedEfficiency = (float)(bundleDDependencyCount + bundleBToBundleCDependencyCount) / (bundleCAssetCount + bundleDAssetCount);
var AToBExpandedEfficiency = (float) (bundleBDependencyCount + bundleDDependencyCount + bundleBToBundleCDependencyCount) / (bundleBAssetCount + bundleCAssetCount + bundleDAssetCount);
Assert.AreEqual(bundleC.BundleDependencies[0].ExpandedEfficiency, cToDExpandedEfficiency);
Assert.AreEqual(bundleB.BundleDependencies[0].ExpandedEfficiency, BToCExpandedEfficiency);
Assert.AreEqual(bundleA.BundleDependencies[0].ExpandedEfficiency, AToBExpandedEfficiency);
}
[Test]
[TestCase(20, 20, 20, 5, 5, 5, 5)]
[TestCase(50, 30, 10, 15, 10, 8, 7)]
[TestCase(100, 75, 35, 35, 7, 30, 25)]
public void BuildLayoutBundle_CalculateEfficiency_HandlesCycleWithLeadInByCuttingOffLastNodeConnections(
int bundleBAssetCount,
int bundleCAssetCount,
int bundleDAssetCount,
int bundleAToBDependencyCount,
int bundleBToCDependencyCount,
int bundleCToDDependencyCount,
int bundleDToBDependencyCount)
{
BuildLayout.Bundle bundleA = CreateBundleWithFileSize(1);
BuildLayout.Bundle bundleB = CreateBundleWithFileSize(bundleBAssetCount, "B");
BuildLayout.Bundle bundleC = CreateBundleWithFileSize(bundleCAssetCount, "C");
BuildLayout.Bundle bundleD = CreateBundleWithFileSize(bundleDAssetCount, "D");
var assetA = CreateExplicitAssetWithParentBundle(bundleA);
var assetB = CreateExplicitAssetWithParentBundle(bundleB);
var assetC = CreateExplicitAssetWithParentBundle(bundleC);
var assetD = CreateExplicitAssetWithParentBundle(bundleD);
bundleA.UpdateBundleDependency(assetA, assetB);
bundleB.UpdateBundleDependency(assetB, assetC);
bundleC.UpdateBundleDependency(assetC, assetD);
bundleD.UpdateBundleDependency(assetD, assetB);
for (int i = 0; i < bundleAToBDependencyCount - 1; i++)
{
var childAsset = CreateExplicitAssetWithParentBundle(bundleB);
bundleA.UpdateBundleDependency(assetA, childAsset);
}
for (int i = 0; i < bundleBToCDependencyCount - 1; i++)
{
var childAsset = CreateExplicitAssetWithParentBundle(bundleC);
bundleB.UpdateBundleDependency(assetB, childAsset);
}
for (int i = 0; i < bundleCToDDependencyCount - 1; i++)
{
var childAsset = CreateExplicitAssetWithParentBundle(bundleD);
bundleC.UpdateBundleDependency(assetC, childAsset);
}
for (int i = 0; i < bundleDToBDependencyCount - 1; i++)
{
var childAsset = CreateExplicitAssetWithParentBundle(bundleB);
bundleD.UpdateBundleDependency(assetD, childAsset);
}
bundleA.SerializeBundleToBundleDependency();
bundleB.SerializeBundleToBundleDependency();
bundleC.SerializeBundleToBundleDependency();
bundleD.SerializeBundleToBundleDependency();
BuildLayoutGenerationTask.CalculateEfficiency(bundleA);
float bundleDToBExpandedEfficiency = (float) bundleDToBDependencyCount / bundleBAssetCount;
float bundleCToDExpandedEfficiency = (float) (bundleCToDDependencyCount + bundleDToBDependencyCount) / (bundleDAssetCount + bundleBAssetCount);
float bundleBToCExpandedEfficiency = (float) (bundleBToCDependencyCount + bundleCToDDependencyCount + bundleDToBDependencyCount) / (bundleCAssetCount + bundleDAssetCount + bundleBAssetCount);
float bundleAToBExpandedEfficiency = (float) (bundleAToBDependencyCount + bundleBToCDependencyCount + bundleCToDDependencyCount + bundleDToBDependencyCount) / (bundleBAssetCount + bundleCAssetCount + bundleDAssetCount + bundleBAssetCount);
Assert.AreEqual(bundleAToBExpandedEfficiency, bundleA.BundleDependencies[0].ExpandedEfficiency);
Assert.AreEqual(bundleBToCExpandedEfficiency, bundleB.BundleDependencies[0].ExpandedEfficiency);
Assert.AreEqual(bundleCToDExpandedEfficiency, bundleC.BundleDependencies[0].ExpandedEfficiency);
Assert.AreEqual(bundleDToBExpandedEfficiency, bundleD.BundleDependencies[0].ExpandedEfficiency);
}
BuildLayout CreateTestLayout(DateTime buildDate, string error = null)
{
BuildLayout layout = new BuildLayout();
layout.BuildTarget = BuildTarget.Android;
layout.BuildResultHash = "testHash123";
layout.BuildType = BuildType.UpdateBuild;
layout.BuildStart = buildDate;
layout.Duration = 10;
layout.BuildError = error;
layout.BuildScript = "DefaultBuildScript";
BuildLayout.Bundle bundle = CreateBundleWithFileSize(2);
bundle.Files = new List<BuildLayout.File>();
BuildLayout.File file = new BuildLayout.File();
bundle.Files.Add(file);
file.Assets = new List<BuildLayout.ExplicitAsset>();
file.Assets.Add(CreateExplicitAssetWithParentBundle(bundle));
file.Assets.Add(CreateExplicitAssetWithParentBundle(bundle));
BuildLayout.Group group = new BuildLayout.Group();
group.Bundles = new List<BuildLayout.Bundle>();
group.Bundles.Add(bundle);
layout.Groups = new List<BuildLayout.Group>();
layout.Groups.Add(group);
layout.DefaultGroup = group;
return layout;
}
[Test]
public void BuildLayoutBundle_SaveAndLoad_SavesCorrectlyToDisk()
{
DateTime time = DateTime.Now;
BuildLayout layout = CreateTestLayout(time);
string filePath = $"{Application.dataPath}/testLayout.json";
try
{
layout.WriteToFile(filePath, false);
FileAssert.Exists(filePath, $"Failed to save build layout to {filePath}");
}
finally
{
if (File.Exists(filePath))
File.Delete(filePath);
}
}
[Test]
[TestCase(50UL, 50UL, 20UL, 20UL, 10, 5)]
[TestCase(30UL, 50UL, 10UL, 5UL, 3, 2)]
[TestCase(1UL, 1UL, 1UL, 1UL, 1, 1)]
[TestCase(30UL, 1UL, 30UL, 1UL, 1, 1)]
[TestCase(5000UL, 5000UL, 500UL, 500UL, 30, 50)]
public void BuildLayoutBundle_CalculateEfficiency_CorrectlyUsesFilesizeForEfficiency(
ulong parentTotalFilesize, ulong childTotalFilesize,
ulong parentDepFileSize, ulong childDepFilesize,
int parentDependencyCount, int childDependencyCount)
{
BuildLayout.Bundle grandparent = CreateBundleWithFileSize(1);
BuildLayout.Bundle parent = CreateBundleWithFileSize(parentTotalFilesize);
BuildLayout.Bundle child = CreateBundleWithFileSize(childTotalFilesize);
BuildLayout.ExplicitAsset grandparentAsset = CreateExplicitAssetWithParentBundle(grandparent);
List<BuildLayout.ExplicitAsset> parentAssets = new List<BuildLayout.ExplicitAsset>();
ulong expectedParentDepFileSize = 0;
for (int i = 0; i < parentDependencyCount; i++)
{
var curFileSize = (ulong)parentDependencyCount / parentDepFileSize;
expectedParentDepFileSize += curFileSize;
var parentAsset = CreateExplicitAssetWithParentBundle(parent, curFileSize);
grandparent.UpdateBundleDependency(grandparentAsset, parentAsset);
parentAssets.Add(parentAsset);
}
ulong expectedChildDepFileSize = 0;
for (int i = 0; i < childDependencyCount; i++)
{
var curFileSize = (ulong)childDependencyCount / childDepFilesize;
expectedChildDepFileSize += curFileSize;
var childAsset = CreateExplicitAssetWithParentBundle(child, curFileSize);
parent.UpdateBundleDependency(parentAssets[0], childAsset);
}
grandparent.SerializeBundleToBundleDependency();
parent.SerializeBundleToBundleDependency();
BuildLayoutGenerationTask.CalculateEfficiency(grandparent);
float expectedGrandparentEfficiency = (float) expectedParentDepFileSize / parentTotalFilesize;
float expectedGrandparentExpandedEfficiency = (float) (expectedParentDepFileSize + expectedChildDepFileSize) / (parentTotalFilesize + childTotalFilesize);
float expectedParentEfficiency = (float) expectedChildDepFileSize / childTotalFilesize;
Assert.AreEqual(expectedGrandparentEfficiency, grandparent.BundleDependencies[0].Efficiency, "Grandparent Efficiency not calculated correctly - this should not be affected by the children of parent.");
Assert.AreEqual(expectedGrandparentExpandedEfficiency, grandparent.BundleDependencies[0].ExpandedEfficiency, "Grandparent ExpandedEfficiency not calculated correctly - this should take into account the total Efficiency of both the direct children Dependency Links as well as all BundleDependencies below the child.");
Assert.AreEqual(expectedParentEfficiency, parent.BundleDependencies[0].ExpandedEfficiency, "Parent ExpandedEfficiency not calculated correctly - this should take into account the Efficiency of the direct child only.");
}
[Test]
public void BuildLayoutBundle_SaveAndLoad_ReadsCorrectDataForHeader()
{
DateTime time = DateTime.Now;
BuildLayout layout = CreateTestLayout(time, "testError123");
time = layout.BuildStart; // due to removing miliseconds in the layout
string filePath = $"{Application.dataPath}/testLayout.json";
try
{
layout.WriteToFile(filePath, false);
FileAssert.Exists(filePath, $"Failed to save build layout to {filePath}");
BuildLayout readLayout = BuildLayout.Open(filePath, false, false);
Assert.AreEqual(DateTime.MinValue, readLayout.BuildStart, "StartDate was not expected to have read a valid date");
// test all header values to ensure the values are as expect (not the same as default values)
readLayout.ReadHeader();
Assert.AreEqual(time, readLayout.Header.BuildStart, "Header Data written or Read incorrectly");
Assert.AreEqual(10, readLayout.Header.Duration, "Header Data written or Read incorrectly");
Assert.AreEqual("testError123", readLayout.Header.BuildError, "Header Data written or Read incorrectly");
Assert.AreEqual(BuildTarget.Android, readLayout.Header.BuildTarget, "Header Data written or Read incorrectly");
Assert.AreEqual(BuildType.UpdateBuild, readLayout.Header.BuildType, "Header Data written or Read incorrectly");
Assert.AreEqual("testHash123", readLayout.Header.BuildResultHash, "Header Data written or Read incorrectly");
// that the test groups have not been read
Assert.AreEqual(0, readLayout.Groups.Count, "Expect to have not read any Groups yet with only Header read");
}
finally
{
if (File.Exists(filePath))
File.Delete(filePath);
}
}
[Test]
public void BuildLayoutBundle_SaveAndLoad_ReadsCorrectDataForBody()
{
DateTime time = DateTime.Now;
BuildLayout layout = CreateTestLayout(time);
string filePath = $"{Application.dataPath}/testLayout.json";
try
{
layout.WriteToFile(filePath, false);
FileAssert.Exists(filePath, $"Failed to save build layout to {filePath}");
BuildLayout readLayout = BuildLayout.Open(filePath, false, false);
Assert.AreEqual(0, readLayout.Groups.Count, "Expect to have not read any Groups yet with no data yet read read");
readLayout.ReadHeader();
Assert.AreEqual(0, readLayout.Groups.Count, "Expect to have not read any Groups yet with only Header read");
readLayout.ReadFull();
Assert.AreEqual(1, readLayout.Groups.Count, "Expect to have 1 Groups after doing a full read read");
}
finally
{
if (File.Exists(filePath))
File.Delete(filePath);
}
}
[Test]
[TestCase(typeof(GameObject), AssetType.GameObject)]
[TestCase(typeof(SceneAsset), AssetType.Scene)]
[TestCase(typeof(AnimatorController), AssetType.AnimationController)]
[TestCase(typeof(TestObject), AssetType.ScriptableObject)]
[TestCase(typeof(ObjectReferenceMonoBehaviour), AssetType.MonoBehaviour)]
public void GetAssetType_ReturnsCorrect(System.Type typeIn, AssetType expectedType)
{
AssetType actual = BuildLayoutHelpers.GetAssetType(typeIn);
Assert.AreEqual(expectedType, actual);
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f732c6455ee1417c91ebd421b5ed6f67
timeCreated: 1662495716

View file

@ -0,0 +1,90 @@
using NUnit.Framework;
using UnityEditor.AddressableAssets.Diagnostics.Data;
using UnityEngine.ResourceManagement.Diagnostics;
namespace UnityEditor.AddressableAssets.Tests.Diagnostics
{
public class EventDataPlayerSessionCollectionTests
{
[Test]
public void EventDataPlayerSessionCollection_RecordEvent_ReturnsFalseOnNullEventHandler()
{
EventDataPlayerSessionCollection edpsc = new EventDataPlayerSessionCollection(null);
Assert.IsFalse(edpsc.RecordEvent(new DiagnosticEvent()), "RecordEvent should return null if m_OnRecordEvent is null");
}
[Test]
public void EventDataPlayerSessionCollection_GetPlayerSession_ProperlyCreatesWhenCreateIsTrue()
{
EventDataPlayerSessionCollection edpsc = new EventDataPlayerSessionCollection((DiagnosticEvent x) => true);
EventDataPlayerSession edps = edpsc.GetPlayerSession(0, true);
Assert.NotNull(edps, "New EventDataPlayerSession should have been created.");
Assert.AreEqual("Player 0", edps.EventName);
}
[Test]
public void EventDataPlayerSessionCollection_GetPlayerSession_ReturnsNullOnNoIdMatch()
{
EventDataPlayerSessionCollection edpsc = new EventDataPlayerSessionCollection((DiagnosticEvent x) => true);
EventDataPlayerSession edps = edpsc.GetPlayerSession(0, false);
Assert.IsNull(edps, "New EventDataPlayerSession should not be created when create = false and there is no id match. ");
}
[Test]
public void EventDataPlayerSessionCollection_GetSessionByIndex_ReturnsNullOnInvalidInput()
{
EventDataPlayerSessionCollection edpsc = new EventDataPlayerSessionCollection((DiagnosticEvent x) => true);
Assert.IsNull(edpsc.GetSessionByIndex(0), "Trying to request a session with a nonexistent index should return null. ");
edpsc.AddSession("test session", 0);
Assert.IsNull(edpsc.GetSessionByIndex(2), "Trying to request a session with a nonexistent index should return null. ");
Assert.NotNull(edpsc.GetSessionByIndex(0), "Session not returned properly on valid index. ");
}
[Test]
public void EventDataPlayerSessionCollection_GetSessionIndexById_SimpleCase()
{
EventDataPlayerSessionCollection edpsc = new EventDataPlayerSessionCollection((DiagnosticEvent x) => true);
edpsc.AddSession("Test session", 0);
edpsc.AddSession("Test session 2", 1);
Assert.AreEqual(1, edpsc.GetSessionIndexById(1), "Session index not properly returned. ");
}
[Test]
public void EventDataPlayerSessionCollection_GetSessionIndexById_NullCase()
{
EventDataPlayerSessionCollection edpsc = new EventDataPlayerSessionCollection((DiagnosticEvent x) => true);
edpsc.AddSession("Test session", 0);
edpsc.AddSession("Test session 2", 1);
Assert.AreEqual(-1, edpsc.GetSessionIndexById(10000000), "Incorrect value returned, GetSessionIndexById should return -1 when the queried id does not exist.");
}
[Test]
public void EventDataPlayerSessionCollection_RemoveSession_SimpleCase()
{
EventDataPlayerSessionCollection edpsc = new EventDataPlayerSessionCollection((DiagnosticEvent x) => true);
edpsc.AddSession("Test session", 0);
edpsc.RemoveSession(0);
Assert.AreEqual(0, edpsc.GetSessionCount(), "Session was not properly removed.");
}
[Test]
public void EventDataPlayerSessionCollection_TestPlayerConnection()
{
EventDataPlayerSessionCollection edpsc = new EventDataPlayerSessionCollection((DiagnosticEvent x) => true);
edpsc.AddSession("Default", 0);
edpsc.GetPlayerSession(1000, true).IsActive = true;
Assert.AreEqual(2, edpsc.GetSessionCount(), "Session not properly added. ");
int connectedSessionIndex = edpsc.GetSessionIndexById(1000);
Assert.AreEqual(1, connectedSessionIndex, "Session index not properly set. ");
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 87c0e75886b4481693ca963bc0955c1c
timeCreated: 1595276565

View file

@ -0,0 +1,257 @@
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using UnityEditor.AddressableAssets.Diagnostics.Data;
using UnityEngine.ResourceManagement;
using UnityEngine.ResourceManagement.Diagnostics;
namespace UnityEditor.AddressableAssets.Tests.Diagnostics
{
public class EventDataPlayerSessionTests
{
private DiagnosticEvent CreateNewGenericEvent(ResourceManager.DiagnosticEventType eventType, int frame, int value)
{
return new DiagnosticEvent(null, "GenericEvent", 1000, (int)eventType, frame, value, null);
}
private DiagnosticEvent CreateNewInstantiationEvent(int frame, int value)
{
return new DiagnosticEvent(null, "InstanceEvent", 1000, (int)ResourceManager.DiagnosticEventType.AsyncOperationCreate, frame, value, null);
}
private DiagnosticEvent CreateNewGenericEvent(ResourceManager.DiagnosticEventType eventType, int frame, int value, int id)
{
return new DiagnosticEvent(null, "GenericEvent", id, (int)eventType, frame, value, null);
}
private DiagnosticEvent CreateNewGenericEvent(ResourceManager.DiagnosticEventType eventType, int frame, int value, int id, int[] dependencies)
{
return new DiagnosticEvent(null, "GenericEvent", id, (int)eventType, frame, value, dependencies);
}
[Test]
public void EventDataPlayerSession_GetFrameEvents_TestSimpleCase()
{
EventDataPlayerSession edps = new EventDataPlayerSession();
DiagnosticEvent evt1 = CreateNewGenericEvent(ResourceManager.DiagnosticEventType.AsyncOperationCreate, 0, 5);
DiagnosticEvent evt2 = CreateNewGenericEvent(ResourceManager.DiagnosticEventType.AsyncOperationCreate, 0, 6);
bool entryCreated = false;
edps.AddSample(evt1, true, ref entryCreated);
edps.AddSample(evt2, true, ref entryCreated);
Assert.AreEqual(new List<DiagnosticEvent> {evt1, evt2}, edps.GetFrameEvents(0), "Events were not properly added together in FrameEvents");
Assert.AreEqual(null, edps.GetFrameEvents(1), "FrameEvents for frame 1 should be null. ");
}
[Test]
public void EventDataPlayerSession_AddSample_SimpleRecordEventCase()
{
EventDataPlayerSession edps = new EventDataPlayerSession();
DiagnosticEvent evt1 = CreateNewGenericEvent(ResourceManager.DiagnosticEventType.AsyncOperationReferenceCount, 0, 1);
DiagnosticEvent evt2 = CreateNewGenericEvent(ResourceManager.DiagnosticEventType.AsyncOperationCreate, 0, 2);
DiagnosticEvent evt3 = CreateNewGenericEvent(ResourceManager.DiagnosticEventType.AsyncOperationReferenceCount, 1, 1);
bool entryCreated = false;
edps.AddSample(evt1, true, ref entryCreated);
Assert.IsTrue(entryCreated, "Either a new entry was supposed to be created, but was not, or the value of entryCreated was not properly updated.");
edps.AddSample(evt2, true, ref entryCreated);
Assert.IsFalse(entryCreated, "evt2: Either a new entry wasn't supposed to be created, but was, or the value of entryCreated was not properly updated.");
edps.AddSample(evt3, true, ref entryCreated);
Assert.IsFalse(entryCreated, "evt3: Either a new entry wasn't supposed to be created for, but was, or the value of entryCreated was not properly updated.");
Assert.AreEqual(new List<DiagnosticEvent> {evt1, evt2}, edps.m_FrameEvents[0], "evt1 and evt2 were not properly added to m_FrameEvents");
Assert.AreEqual(2, edps.m_EventCountDataSet.GetStreamValue(0, 0), "Value of the stream for m_EventCountDataSet was not properly set.");
Assert.AreEqual(new List<DiagnosticEvent> {evt3}, edps.m_FrameEvents[1], "evt3 was not properly added to m_FrameEvents");
Assert.IsTrue(edps.m_DataSets.ContainsKey(evt1.ObjectId), "The corresponding EventDataSet for evt1-3 was not added to m_DataSets");
EventDataSet eds = null;
bool edsFound = edps.m_DataSets.TryGetValue(evt1.ObjectId, out eds);
Assert.IsTrue(edsFound);
Assert.AreEqual(2, eds.GetStream((int)ResourceManager.DiagnosticEventType.AsyncOperationReferenceCount).samples.Count);
Assert.AreEqual(1, eds.GetStream((int)ResourceManager.DiagnosticEventType.AsyncOperationCreate).samples.Count);
}
[Test]
public void EventDataPlayerSession_AddSample_SimpleInstantiationCase()
{
EventDataPlayerSession edps = new EventDataPlayerSession();
DiagnosticEvent evt1 = CreateNewInstantiationEvent(0, 1);
DiagnosticEvent evt2 = CreateNewInstantiationEvent(0, 1);
DiagnosticEvent evt3 = CreateNewInstantiationEvent(1, 1);
DiagnosticEvent evt4 = CreateNewInstantiationEvent(2, 0);
bool entryCreated = false;
edps.AddSample(evt1, false, ref entryCreated);
Assert.IsFalse(entryCreated, "evt1: Either a new entry was created when it shouldn't have been, or the value of entryCreated was not properly updated.");
edps.AddSample(evt2, false, ref entryCreated);
Assert.IsFalse(entryCreated, "evt2: Either a new entry was created when it shouldn't have been, or the value of entryCreated was not properly updated.");
edps.AddSample(evt3, false, ref entryCreated);
Assert.IsFalse(entryCreated, "evt3: Either a new entry was created when it shouldn't have been, or the value of entryCreated was not properly updated.");
Assert.AreEqual(2, edps.m_InstantitationCountDataSet.GetStreamValue(0, 0), "Stream value for frame 0 not properly set to 2.");
Assert.AreEqual(2, edps.m_InstantitationCountDataSet.GetStreamValue(0, 1),
"Stream value for frame 1 was updated prematurely - stream values for instantiation counts should not be updated until it is certain that all events for a given frame have been collected. ");
edps.AddSample(evt4, false, ref entryCreated);
Assert.IsFalse(entryCreated, "evt3: Either a new entry was created when it shouldn't have been, or the value of entryCreated was not properly updated.");
Assert.AreEqual(1, edps.m_InstantitationCountDataSet.GetStreamValue(0, 1),
"Stream value for frame 1 was not updated properly, should be updated once the sample is added for the following frame.");
}
[Test]
public void EventDataPlayerSession_AddSample_MultipleObjectCase()
{
EventDataPlayerSession edps = new EventDataPlayerSession();
DiagnosticEvent evt1 = CreateNewGenericEvent(ResourceManager.DiagnosticEventType.AsyncOperationReferenceCount, 0, 1, 1000);
DiagnosticEvent evt2 = CreateNewGenericEvent(ResourceManager.DiagnosticEventType.AsyncOperationReferenceCount, 1, 1, 1001);
bool entryCreated = false;
edps.AddSample(evt1, false, ref entryCreated);
Assert.IsTrue(entryCreated, "evt1: Either a new entry was supposed to be created, but was not, or the value of entryCreated was not properly updated.");
Assert.IsTrue(edps.m_DataSets.ContainsKey(evt1.ObjectId), "Entry for evt1 should have been created, but was not added to m_DataSets");
Assert.AreEqual(1, edps.m_DataSets[evt1.ObjectId].GetStreamValue((int)ResourceManager.DiagnosticEventType.AsyncOperationReferenceCount, 0),
"Value was not correctly set within EventDataSet object for evt1. ");
edps.AddSample(evt2, false, ref entryCreated);
Assert.IsTrue(entryCreated, "evt2: Either a new entry was supposed to be created, but was not, or the value of entryCreated was not properly updated.");
Assert.IsTrue(edps.m_DataSets.ContainsKey(evt2.ObjectId), "Entry for evt2 should have been created, but was not added to m_DataSets");
Assert.AreEqual(1, edps.m_DataSets[evt2.ObjectId].GetStreamValue((int)ResourceManager.DiagnosticEventType.AsyncOperationReferenceCount, 1),
"Value was not correctly set within EventDataSet object for evt2. ");
}
[Test]
public void EventDataPlayerSession_HandleOperationDestroy_NoDependencyCase()
{
EventDataPlayerSession edps = new EventDataPlayerSession();
DiagnosticEvent creationEvt = CreateNewGenericEvent(ResourceManager.DiagnosticEventType.AsyncOperationCreate, 0, 1, 1000);
DiagnosticEvent deletionEvt = CreateNewGenericEvent(ResourceManager.DiagnosticEventType.AsyncOperationDestroy, 1, 1, 1000);
bool entryCreated = false;
edps.AddSample(creationEvt, false, ref entryCreated);
Assert.IsTrue(entryCreated, "Either a new entry was supposed to be created, but was not, or the value of entryCreated was not properly updated.");
edps.AddSample(deletionEvt, false, ref entryCreated);
Assert.IsFalse(entryCreated, "Either a new entry was created when it shouldn't have been, or the value of entryCreated was not properly updated.");
Assert.AreEqual(1, edps.m_Queue.Count, "Deletion event should've been added to the removal queue.");
edps.HandleOperationDestroy(deletionEvt);
Assert.IsFalse(edps.m_DataSets.ContainsKey(creationEvt.ObjectId), "Dataset was not properly removed on deletion.");
}
[Test]
public void EventDataPlayerSession_HandleOperationDestroy_DoesNotDestroyOnNonzeroRefcount()
{
EventDataPlayerSession edps = new EventDataPlayerSession();
DiagnosticEvent creationEvt = CreateNewGenericEvent(ResourceManager.DiagnosticEventType.AsyncOperationCreate, 0, 1, 1000);
DiagnosticEvent refcountEvt = CreateNewGenericEvent(ResourceManager.DiagnosticEventType.AsyncOperationReferenceCount, 0, 1, 1000);
DiagnosticEvent deletionEvt = CreateNewGenericEvent(ResourceManager.DiagnosticEventType.AsyncOperationDestroy, 1, 1, 1000);
bool entryCreated = false;
edps.AddSample(creationEvt, false, ref entryCreated);
Assert.IsTrue(entryCreated, "creationEvt: Either a new entry was supposed to be created, but was not, or the value of entryCreated was not properly updated.");
edps.AddSample(refcountEvt, false, ref entryCreated);
Assert.IsFalse(entryCreated, "refcountEvt: Either a new entry was created when it shouldn't have been, or the value of entryCreated was not properly updated.");
edps.AddSample(deletionEvt, false, ref entryCreated);
Assert.IsFalse(entryCreated, "deletionEvt: Either a new entry was created when it shouldn't have been, or the value of entryCreated was not properly updated.");
Assert.AreEqual(1, edps.m_Queue.Count, "Deletion event should've been added to the removal queue.");
edps.HandleOperationDestroy(deletionEvt);
Assert.IsTrue(edps.m_DataSets.ContainsKey(creationEvt.ObjectId), "Dataset should not have been removed because it's refcount is greater than 0. ");
}
[Test]
public void EventDataPlayerSession_HandleOperationDestroy_DependencyHasNoRefcountCase()
{
EventDataPlayerSession edps = new EventDataPlayerSession();
DiagnosticEvent dependencyEvt = CreateNewGenericEvent(ResourceManager.DiagnosticEventType.AsyncOperationReferenceCount, 0, 0, 1001);
DiagnosticEvent creationEvt = CreateNewGenericEvent(ResourceManager.DiagnosticEventType.AsyncOperationCreate, 0, 1, 1000, new int[] {dependencyEvt.ObjectId});
DiagnosticEvent deletionEvt = CreateNewGenericEvent(ResourceManager.DiagnosticEventType.AsyncOperationDestroy, 1, 1, 1000, new int[] {dependencyEvt.ObjectId});
bool entryCreated = false;
edps.AddSample(dependencyEvt, false, ref entryCreated);
Assert.IsTrue(entryCreated, "Either a new entry was supposed to be created, but was not, or the value of entryCreated was not properly updated.");
edps.AddSample(creationEvt, false, ref entryCreated);
Assert.IsTrue(entryCreated, "Either a new entry was supposed to be created, but was not, or the value of entryCreated was not properly updated.");
edps.AddSample(deletionEvt, false, ref entryCreated);
Assert.IsFalse(entryCreated, "Either a new entry was created when it shouldn't have been, or the value of entryCreated was not properly updated.");
Assert.AreEqual(1, edps.m_RootStreamEntry.Children.Count(), "DependencyEvt's id should have been removed from RootStreamEntry's children because it is a dependency.");
Assert.AreEqual(1, edps.m_Queue.Count, "Deletion event should have been added to the removal queue.");
edps.HandleOperationDestroy(deletionEvt);
Assert.IsFalse(edps.m_DataSets.ContainsKey(deletionEvt.ObjectId), "DataSet was not properly removed after dependency was cleared. ");
Assert.AreEqual(1, edps.m_Queue.Count, "No further deletion events should have been added to the deletion queue.");
}
[Test]
public void EventDataPlayerSession_HandleOperationDestroy_DestroyedEventHasParentCase()
{
EventDataPlayerSession edps = new EventDataPlayerSession();
DiagnosticEvent dependencyEvt = CreateNewGenericEvent(ResourceManager.DiagnosticEventType.AsyncOperationReferenceCount, 0, 0, 1001);
DiagnosticEvent creationEvt = CreateNewGenericEvent(ResourceManager.DiagnosticEventType.AsyncOperationCreate, 0, 1, 1000, new int[] {dependencyEvt.ObjectId});
DiagnosticEvent deletionEvt = CreateNewGenericEvent(ResourceManager.DiagnosticEventType.AsyncOperationDestroy, 1, 1, 1001);
bool entryCreated = false;
edps.AddSample(dependencyEvt, false, ref entryCreated);
Assert.IsTrue(entryCreated, "Either a new entry was supposed to be created, but was not, or the value of entryCreated was not properly updated.");
edps.AddSample(creationEvt, false, ref entryCreated);
Assert.IsTrue(entryCreated, "Either a new entry was supposed to be created, but was not, or the value of entryCreated was not properly updated.");
edps.AddSample(deletionEvt, false, ref entryCreated);
Assert.IsFalse(entryCreated, "Either a new entry was created when it shouldn't have been, or the value of entryCreated was not properly updated.");
Assert.AreEqual(1, edps.m_RootStreamEntry.Children.Count(), "DependencyEvt's id should have been removed from RootStreamEntry's children because it is a dependency.");
Assert.AreEqual(1, edps.m_Queue.Count, "Deletion event should have been added to the removal queue.");
edps.HandleOperationDestroy(deletionEvt);
Assert.IsFalse(edps.m_DataSets.ContainsKey(deletionEvt.ObjectId), "DataSet was not properly removed after dependency was cleared. ");
EventDataSet creationEvtEds = null;
Assert.IsTrue(edps.m_DataSets.TryGetValue(creationEvt.ObjectId, out creationEvtEds), "Parent event was removed from m_DataSets incorrectly.");
Assert.IsNull(creationEvtEds.m_Children, "dependencyEvt's dataset should have been removed from the children of creationEvt's dataset. ");
Assert.AreEqual(1, edps.m_Queue.Count, "No further deletion events should have been added to the deletion queue.");
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 69303074fc8049c794e80a49d142e38d
timeCreated: 1594924812

View file

@ -0,0 +1,91 @@
using NUnit.Framework;
using UnityEditor.AddressableAssets.Diagnostics.Data;
using UnityEngine;
using UnityEngine.TestTools;
namespace UnityEditor.AddressableAssets.Tests.Diagnostics
{
public class EventDataSetStreamTests
{
[Test]
public void EventDataSetStream_AddSample_SimpleAdd()
{
EventDataSetStream testStream = new EventDataSetStream();
testStream.AddSample(0, 5);
Assert.AreEqual(5, testStream.GetValue(0), "Value of added sample was not correctly retrieved. ");
}
[Test]
public void EventDataSetStream_AddSample_OutOfOrderFrameFails()
{
EventDataSetStream testStream = new EventDataSetStream();
testStream.AddSample(5, 5);
testStream.AddSample(0, 0);
Assert.AreEqual(1, testStream.samples.Count, "Sample still added to stream despite the fact that the event should have been ignored.");
}
[Test]
public void EventDataSetStream_AddSample_ReplaceValueOnDuplicateAdd()
{
EventDataSetStream testStream = new EventDataSetStream();
testStream.AddSample(0, 5);
testStream.AddSample(0, 6);
Assert.AreEqual(6, testStream.GetValue(0), "Sample was not properly replaced. ");
Assert.AreEqual(1, testStream.samples.Count, "Sample was not properly replaced.");
}
[Test]
public void EventDataSetStream_GetValue_ReturnsZeroOnInvalidFrame()
{
EventDataSetStream testStream = new EventDataSetStream();
Assert.AreEqual(0, testStream.GetValue(0), "Expected default value of 0 because there are no samples currently in EventDataStream.");
testStream.AddSample(0, 1);
Assert.AreEqual(0, testStream.GetValue(-1), "Expected default value because there is no sample with frame -1.");
}
[Test]
public void EventDataSetStream_GetValue_ReturnsCorrectValueOnMultipleCalls()
{
EventDataSetStream testStream = new EventDataSetStream();
testStream.AddSample(0, 0);
testStream.AddSample(1, 1);
testStream.AddSample(2, 2);
Assert.AreEqual(2, testStream.GetValue(2), "Incorrect value retrieved by GetValue.");
Assert.AreEqual(1, testStream.GetValue(1), "Incorrect value retrieved by GetValue.");
Assert.AreEqual(0, testStream.GetValue(0), "Incorrect value retrieved by GetValue.");
}
[Test]
public void EventDataSetStream_GetValue_ReturnsLastValueOnTooLargeFrame()
{
EventDataSetStream testStream = new EventDataSetStream();
testStream.AddSample(5, 5);
Assert.AreEqual(5, testStream.GetValue(100), "Final contained sample was not returned on too large query frame.");
}
[Test]
public void EventDataSetStream_HasDataAfterFrame_ReturnsFalseOnNoSamples()
{
EventDataSetStream testStream = new EventDataSetStream();
Assert.AreEqual(false, testStream.HasDataAfterFrame(5), "Should have returned true since no samples have been added to the stream. ");
}
[Test]
public void EventDataSetStream_HasDataAfterFrame_ReturnsFalseOnLastSampleEmptyData()
{
EventDataSetStream testStream = new EventDataSetStream();
testStream.AddSample(0, 1);
testStream.AddSample(5, 0);
Assert.AreEqual(false, testStream.HasDataAfterFrame(6), "HasDataAfterFrame returned true when last sample's data is empty and queried frame is past the last sample.");
}
[Test]
public void EventDataSetSTream_HasDataAfterFrame_ReturnsTrueOnLastSampleNonZero()
{
EventDataSetStream testStream = new EventDataSetStream();
testStream.AddSample(0, 1);
testStream.AddSample(2, 1);
Assert.AreEqual(true, testStream.HasDataAfterFrame(1), "HasDataAfterFrame returned false when there should be a sample with data following frame 1.");
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3275c47c6e434362a78bf0ec660eebd0
timeCreated: 1594828580

View file

@ -0,0 +1,186 @@
using NUnit.Framework;
using UnityEditor.AddressableAssets.Diagnostics.Data;
using UnityEngine.ResourceManagement;
namespace UnityEditor.AddressableAssets.Tests.Diagnostics
{
public class EventDataSetTests
{
//Note, we use EventDataSetStream.GetValue for these tests so that we can avoid testing multiple
//EventDataSet methods in the same test
[Test]
public void EventDataSet_AddSample_AddsToCorrectStream()
{
EventDataSet testSet = new EventDataSet();
testSet.AddSample(2, 0, 2);
Assert.NotNull(testSet.m_Streams, "List of streams not properly initialized.");
Assert.AreEqual(true, testSet.m_Streams.Count > 0, "List of streams was initialized, but not assigned to.");
Assert.NotNull(testSet.m_Streams[2], "Stream 2 should not be null, as a sample should've been added to it.");
Assert.AreEqual(2, testSet.m_Streams[2].GetValue(0), "Value retrieved from stream was incorrect.");
}
[Test]
public void EventDataSet_AddSample_ProperlyCreatesNullStreams()
{
EventDataSet testSet = new EventDataSet();
testSet.AddSample(4, 0, 2);
Assert.NotNull(testSet.m_Streams, "List of streams not properly initialized.");
Assert.AreEqual(true, testSet.m_Streams.Count > 0, "List of streams was initialized, but not assigned to.");
Assert.IsNull(testSet.m_Streams[0], "0th stream was not null initialized like expected.");
Assert.IsNull(testSet.m_Streams[1], "1th stream was not null initialized like expected.");
Assert.IsNull(testSet.m_Streams[2], "2nd stream was not null initialized like expected.");
Assert.IsNull(testSet.m_Streams[3], "3rd stream was not null initialized like expected.");
Assert.NotNull(testSet.m_Streams[4], "4th stream was null initialized when it should have had a value added to it.");
Assert.AreEqual(2, testSet.m_Streams[4].GetValue(0), "Value retrieved from stream was incorrect.");
}
//this tests both HasChildren and AddChild
[Test]
public void EventDataSet_AddChild_SimpleAdd()
{
EventDataSet testSet = new EventDataSet();
EventDataSet childSet = new EventDataSet();
testSet.AddChild(childSet);
Assert.AreEqual(true, testSet.HasChildren, "hasChildren not properly updated.");
Assert.AreEqual(childSet.ObjectId, testSet.m_Children[childSet.ObjectId].ObjectId, "Child not successfully retrieved from dictionary. ");
}
[Test]
public void EventDataSet_AddChild_ConfirmChildObjectConsistentWithReference()
{
EventDataSet parentSet1 = new EventDataSet();
EventDataSet parentSet2 = new EventDataSet();
EventDataSet childSet = new EventDataSet();
parentSet1.AddChild(childSet);
parentSet2.AddChild(childSet);
childSet.DisplayName = "SameChild";
Assert.AreEqual("SameChild", parentSet1.m_Children[childSet.ObjectId].DisplayName, "Display name not changed in m_Children despite being changed on child EventDataSet itself.");
Assert.AreEqual("SameChild", parentSet2.m_Children[childSet.ObjectId].DisplayName, "Display name not changed in m_Children despite being changed on child EventDataSet itself.");
}
[Test]
public void EventDataSet_HasDataAfterFrame_ProperBehaviorOnNoChildCase()
{
EventDataSet parentSet = new EventDataSet();
parentSet.AddSample(0, 0, 1);
Assert.AreEqual(true, parentSet.HasDataAfterFrame(0), "Returned false despite the fact that the last frame of the stream should be nonzero.");
}
[Test]
public void EventDataSet_HasDataAfterFrame_ProperBehaviorOnChildHasStreamCase()
{
EventDataSet parentSet = new EventDataSet();
EventDataSet childSet = new EventDataSet();
childSet.AddSample(0, 0, 1);
Assert.AreEqual(false, parentSet.HasDataAfterFrame(0), "HasDataAfterFrame should always be false for a dataset with no streams and no children.");
Assert.AreEqual(true, childSet.HasDataAfterFrame(0), "HasDataAfterFrame should return true because the last sample of one of it's streams is nonzero.");
parentSet.AddChild(childSet);
Assert.AreEqual(true, parentSet.HasDataAfterFrame(0), "HasDataAfterFrame returned false even though a child EventDataSet has data past frame 0.");
}
[Test]
public void EventDataSet_HasDataAfterFrame_ProperBehaviorOnChildHasNoStreamCase()
{
EventDataSet parentSet = new EventDataSet();
EventDataSet childSet = new EventDataSet();
Assert.AreEqual(false, parentSet.HasDataAfterFrame(0), "HasDataAfterFrame should always be false for a dataset with no streams and no children.");
Assert.AreEqual(false, childSet.HasDataAfterFrame(0), "HasDataAfterFrame should always be false for a dataset with no streams and no children.");
parentSet.AddChild(childSet);
Assert.AreEqual(false, parentSet.HasDataAfterFrame(0), "HasDataAfterFrame should always be false for a dataset with no streams and a child that has no samples/streams.");
}
[Test]
public void EventDataSet_RemoveChild_SimpleAddRemove()
{
EventDataSet parentSet = new EventDataSet();
EventDataSet childSet = new EventDataSet();
parentSet.AddChild(childSet);
Assert.AreEqual(true, parentSet.HasChildren, "HasChildren should be true after a child is added. ");
parentSet.RemoveChild(childSet.ObjectId);
Assert.AreEqual(false, parentSet.HasChildren, "HasChildren should be false after child is removed. ");
Assert.IsNull(parentSet.m_Children, "m_Children should be set to null after last child is removed. ");
}
[Test]
public void EventDataSet_GetStreamValue_SimpleGet()
{
EventDataSet testSet = new EventDataSet();
testSet.AddSample(0, 0, 1);
Assert.AreEqual(1, testSet.GetStreamValue(0, 0));
}
[Test]
public void EventDataSet_GetStreamValue_ReturnsZeroOnNullStreamIndex()
{
EventDataSet testSet = new EventDataSet();
//stream number > stream count case
Assert.AreEqual(0, testSet.GetStreamValue(1, 1), "GetStreamValue should return 0 when queried with a stream index greater than the count of total streams. ");
testSet.AddSample(2, 0, 2);
//null stream case
Assert.AreEqual(0, testSet.GetStreamValue(1, 0), "GetStreamValue should return 0 when querying the index of an uninitialized stream. ");
}
[Test]
public void EventDataSet_GetStream_ReturnsNullOnNonexistentStream()
{
EventDataSet testSet = new EventDataSet();
Assert.IsNull(testSet.GetStream(1), "GetStream should return null when queried with a stream index greater than the count of total streams.");
testSet.AddSample(2, 0, 2);
Assert.IsNull(testSet.GetStream(1), "GetStream should return null when querying an uninitialized stream. ");
}
[Test]
public void EventDataSet_GetStream_SimpleGet()
{
EventDataSet testSet = new EventDataSet();
testSet.AddSample(0, 0, 1);
var soughtStream = testSet.m_Streams[0];
Assert.AreEqual(soughtStream, testSet.GetStream(0), "Correct stream not returned by GetStream");
}
[Test]
public void EventDataSet_HasRefcountAfterFrame_ReturnsTrueOnTrivialCase()
{
EventDataSet testSet = new EventDataSet();
//Add sample to the refcount stream
testSet.AddSample((int)ResourceManager.DiagnosticEventType.AsyncOperationReferenceCount, 5, 1);
Assert.AreEqual(true, testSet.HasRefcountAfterFrame(0, true), "Refcount after frame was considered 0 when sample should have been added.");
}
[Test]
public void EventDataSet_HasRefcountAfterFrame_ReturnsTrueOnChildCase()
{
EventDataSet testSet = new EventDataSet();
testSet.AddSample((int)ResourceManager.DiagnosticEventType.AsyncOperationReferenceCount, 2, 1);
testSet.AddSample((int)ResourceManager.DiagnosticEventType.AsyncOperationReferenceCount, 4, 0);
EventDataSet childSet = new EventDataSet();
childSet.AddSample((int)ResourceManager.DiagnosticEventType.AsyncOperationReferenceCount, 5, 1);
testSet.AddChild(childSet);
Assert.AreEqual(true, testSet.HasRefcountAfterFrame(3, true), "Child refcount not properly considered when checking parent's refcount.");
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6665e03593d44dae8f9e2ada8752d2dc
timeCreated: 1594851080

View file

@ -0,0 +1,18 @@
using NUnit.Framework;
using UnityEditor.AddressableAssets.Diagnostics.Data;
using UnityEditor.AddressableAssets.Diagnostics.GUI;
namespace UnityEditor.AddressableAssets.Tests.Diagnostics
{
public class EventGraphListViewTests
{
[Test]
public void DataStreamEntry_IdEqualsDataSetObjectId()
{
EventDataSet eds = new EventDataSet(100, "graph", "name", 0);
EventGraphListView.DataStreamEntry entry = new EventGraphListView.DataStreamEntry(eds, 0);
Assert.AreEqual(eds.ObjectId, entry.id, "Event Hiding functionality relies on DataStreamEntry ids being the same as their underlying ObjectId.");
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1b61a52d425c4e0f990ee2abd92efb46
timeCreated: 1597096123

View file

@ -0,0 +1,25 @@
#if UNITY_2022_2_OR_NEWER
using System;
using System.Collections.Generic;
using System.IO;
using NUnit.Framework;
using UnityEditor.AddressableAssets.Build.Layout;
using UnityEditor.AddressableAssets.Diagnostics;
using UnityEngine;
namespace UnityEditor.AddressableAssets.Tests.Diagnostics
{
internal class ProfilerTests
{
[Test]
public void GUIUtilitiesGetIcon_ThrowsNoErrors()
{
foreach (Enum e in Enum.GetValues(typeof(AssetType)))
{
ProfilerGUIUtilities.GetAssetIcon((AssetType)e);
}
}
}
}
#endif

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3805f04aa43306c4590ee741451aefe3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,85 @@
using System;
using System.Linq;
using NUnit.Framework;
using UnityEditor.AddressableAssets.Diagnostics.Data;
using UnityEditor.AddressableAssets.Diagnostics.GUI.Graph;
namespace UnityEditor.AddressableAssets.Tests.Diagnostics
{
public class SegmentIterationTests
{
static bool IsContinuationOfSegment(int prevData, int newData)
{
return prevData != newData;
}
[Test]
public void EmptyStream_ReturnsNoSegments()
{
Assert.AreEqual(0, GraphUtility.IterateSegments(new EventDataSetStream(), 0, 100, null).Count());
}
[Test]
public void FirstSampleBeforeStartFrame_IsFirstSegmentAndCropped()
{
EventDataSetStream stream = new EventDataSetStream();
stream.AddSample(0, 99);
GraphUtility.Segment[] segs = GraphUtility.IterateSegments(stream, 25, 100, IsContinuationOfSegment).ToArray();
Assert.AreEqual(1, segs.Length);
Assert.AreEqual(25, segs[0].frameStart);
Assert.AreEqual(100, segs[0].frameEnd);
Assert.AreEqual(99, segs[0].data);
}
[Test]
public void LastSampleBeforeLastEndFrame_LastSegmentSpansToEndOfFrame()
{
EventDataSetStream stream = new EventDataSetStream();
stream.AddSample(50, 99);
GraphUtility.Segment[] segs = GraphUtility.IterateSegments(stream, 0, 100, IsContinuationOfSegment).ToArray();
Assert.AreEqual(1, segs.Length);
Assert.AreEqual(50, segs[0].frameStart);
Assert.AreEqual(100, segs[0].frameEnd);
Assert.AreEqual(99, segs[0].data);
}
void AddAlternativeSegments(EventDataSetStream stream, int data1, int data2, int startFrame, int frameIncrement, int count)
{
for (int i = 0; i < count; i++)
{
int sample = (i % 2) == 0 ? data1 : data2;
stream.AddSample(startFrame + i * frameIncrement, sample);
}
}
[Test]
public void MultipleSamples_SegmentPerSample()
{
EventDataSetStream stream = new EventDataSetStream();
const int kSampleCount = 20;
const int kFrameIncrement = 100;
AddAlternativeSegments(stream, -99, 99, 0, kFrameIncrement, kSampleCount);
GraphUtility.Segment[] segs = GraphUtility.IterateSegments(stream, 0, kSampleCount * kFrameIncrement, IsContinuationOfSegment).ToArray();
Assert.AreEqual(kSampleCount, segs.Length);
for (int i = 0; i < segs.Length; i++)
{
Assert.AreEqual(segs[i].data, (i % 2 == 0) ? -99 : 99);
Assert.AreEqual(segs[i].frameStart, i * kFrameIncrement);
Assert.AreEqual(segs[i].frameEnd, (i + 1) * kFrameIncrement);
}
}
[Test]
public void SegmentBeforeStartFrame_IsIgnored()
{
EventDataSetStream stream = new EventDataSetStream();
stream.AddSample(0, 99);
stream.AddSample(50, 0);
GraphUtility.Segment[] segs = GraphUtility.IterateSegments(stream, 100, 200, IsContinuationOfSegment).ToArray();
Assert.AreEqual(1, segs.Length);
Assert.AreEqual(0, segs[0].data);
Assert.AreEqual(100, segs[0].frameStart);
Assert.AreEqual(200, segs[0].frameEnd);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e49dad816ceeeb94386b907d5f361a0d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: