initial commit
This commit is contained in:
parent
6715289efe
commit
788c3389af
37645 changed files with 2526849 additions and 80 deletions
|
@ -0,0 +1,368 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using UnityEditor.AddressableAssets;
|
||||
using UnityEditor.AddressableAssets.Build;
|
||||
using UnityEditor.AddressableAssets.Build.DataBuilders;
|
||||
using UnityEditor.AddressableAssets.Settings;
|
||||
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
|
||||
using UnityEditor.AddressableAssets.Tests;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Tests.Editor
|
||||
{
|
||||
public class AddressableAnalyticsTests
|
||||
{
|
||||
private AddressablesDataBuilderInput builderInput;
|
||||
private AddressableAssetSettings testSettings;
|
||||
private List<AddressableAssetGroup> groupList;
|
||||
|
||||
private int numberOfGroupsCompressedWithLZ4;
|
||||
private int numberOfGroupsCompressedWithLZMA;
|
||||
private int numberOfGroupsUncompressed;
|
||||
|
||||
private int numberOfGroupsPackedTogether;
|
||||
private int numberOfGroupsPackedSeparately;
|
||||
private int numberOfGroupsPackedTogetherByLabel;
|
||||
|
||||
private int numberOfGroups;
|
||||
|
||||
private AddressableAssetGroup CreateGroupWithCompressionType(string groupName,
|
||||
BundledAssetGroupSchema.BundleCompressionMode compressionMode)
|
||||
{
|
||||
var group = ScriptableObject.CreateInstance<AddressableAssetGroup>();
|
||||
group.Name = "AddressableAnalyticsTestingGroup" + groupName;
|
||||
var schema = group.AddSchema<BundledAssetGroupSchema>();
|
||||
group.Schemas.Add(schema);
|
||||
schema.Compression = compressionMode;
|
||||
return group;
|
||||
}
|
||||
|
||||
private void AddSchemaWithPackingAndBundleMode(AddressableAssetGroup group, BundledAssetGroupSchema.BundleCompressionMode compressionMode,
|
||||
BundledAssetGroupSchema.BundlePackingMode packingMode)
|
||||
{
|
||||
var schema = group.GetSchema<BundledAssetGroupSchema>();
|
||||
schema.Compression = compressionMode;
|
||||
schema.BundleMode = packingMode;
|
||||
}
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void OneTimeSetUp()
|
||||
{
|
||||
//Initialize Settings Object
|
||||
testSettings = AddressableAssetSettings.Create("AddressableAnalyticsTests", "AddressableAnalyticsTestSettings", false, false);
|
||||
var buildScriptPackedMode = ScriptableObject.CreateInstance<BuildScriptPackedMode>();
|
||||
var buildScriptPackedPlayMode = ScriptableObject.CreateInstance<BuildScriptPackedPlayMode>();
|
||||
var buildScriptVirtualMode = ScriptableObject.CreateInstance<BuildScriptVirtualMode>();
|
||||
var buildScriptFastMode = ScriptableObject.CreateInstance<BuildScriptFastMode>();
|
||||
var customBuildScript = ScriptableObject.CreateInstance<BuildScriptTests.BuildScriptTestClass>();
|
||||
|
||||
testSettings.AddDataBuilder(buildScriptPackedMode);
|
||||
testSettings.AddDataBuilder(buildScriptFastMode);
|
||||
testSettings.AddDataBuilder(buildScriptVirtualMode);
|
||||
testSettings.AddDataBuilder(buildScriptPackedPlayMode);
|
||||
testSettings.AddDataBuilder(customBuildScript);
|
||||
|
||||
testSettings.ActivePlayerDataBuilderIndex = 0;
|
||||
testSettings.ActivePlayModeDataBuilderIndex = 0;
|
||||
|
||||
var group0 = testSettings.CreateGroup("LZ4AndPackedTogether", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
var group1 = testSettings.CreateGroup("LZ4AndPackedTogether2", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
var group2 = testSettings.CreateGroup("LZMAAndPackedTogetherByLabel", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
var group3 = testSettings.CreateGroup("LZMAAndPackedTogetherByLabel2", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
var group4 = testSettings.CreateGroup("LZMAAndPackedTogetherByLabel3", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
var group5 = testSettings.CreateGroup("UncompressedAndPackedSeparately", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
//Create Groups with schemas
|
||||
|
||||
AddSchemaWithPackingAndBundleMode(group0, BundledAssetGroupSchema.BundleCompressionMode.LZ4, BundledAssetGroupSchema.BundlePackingMode.PackTogether);
|
||||
AddSchemaWithPackingAndBundleMode(group1, BundledAssetGroupSchema.BundleCompressionMode.LZ4, BundledAssetGroupSchema.BundlePackingMode.PackTogether);
|
||||
AddSchemaWithPackingAndBundleMode(group2, BundledAssetGroupSchema.BundleCompressionMode.LZMA, BundledAssetGroupSchema.BundlePackingMode.PackTogetherByLabel);
|
||||
AddSchemaWithPackingAndBundleMode(group3, BundledAssetGroupSchema.BundleCompressionMode.LZMA, BundledAssetGroupSchema.BundlePackingMode.PackTogetherByLabel);
|
||||
AddSchemaWithPackingAndBundleMode(group4, BundledAssetGroupSchema.BundleCompressionMode.LZMA, BundledAssetGroupSchema.BundlePackingMode.PackTogetherByLabel);
|
||||
AddSchemaWithPackingAndBundleMode(group5, BundledAssetGroupSchema.BundleCompressionMode.Uncompressed, BundledAssetGroupSchema.BundlePackingMode.PackSeparately);
|
||||
|
||||
builderInput = new AddressablesDataBuilderInput(testSettings);
|
||||
numberOfGroupsUncompressed = 1;
|
||||
numberOfGroupsCompressedWithLZ4 = 2;
|
||||
numberOfGroupsCompressedWithLZMA = 3;
|
||||
|
||||
numberOfGroupsPackedSeparately = 1;
|
||||
numberOfGroupsPackedTogether = 2;
|
||||
numberOfGroupsPackedTogetherByLabel = 3;
|
||||
|
||||
numberOfGroups = 6;
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void RemoveAnyAssetEntriesCreated()
|
||||
{
|
||||
if (testSettings.groups.Sum(x => x.entries.Count) > 0)
|
||||
foreach (var group in testSettings.groups)
|
||||
group.RemoveAssetEntries(new List<AddressableAssetEntry>(group.entries));
|
||||
}
|
||||
|
||||
|
||||
[OneTimeTearDown]
|
||||
public void OneTimeTearDown()
|
||||
{
|
||||
foreach (var group in testSettings.groups)
|
||||
group.ClearSchemas(true, false);
|
||||
}
|
||||
|
||||
|
||||
internal AddressableAssetBuildResult CreateTestResult(double duration, bool isPlayMode, string err, long bundleCount = 0)
|
||||
{
|
||||
if (isPlayMode)
|
||||
return CreatePlaymodeResult(duration, err);
|
||||
else
|
||||
{
|
||||
return CreatePlayerBuildResult(duration, err, bundleCount);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dummy constructor for analytics testing purposes
|
||||
/// </summary>
|
||||
/// <param name="duration"></param>
|
||||
/// <param name="err"></param>
|
||||
/// <param name="bundleCount"></param>
|
||||
private AddressablesPlayerBuildResult CreatePlayerBuildResult(double duration, string err, long bundleCount)
|
||||
{
|
||||
var result = new AddressablesPlayerBuildResult();
|
||||
result.Duration = duration;
|
||||
result.Error = err;
|
||||
for (int i = 0; i < bundleCount; i++)
|
||||
{
|
||||
result.m_AssetBundleBuildResults.Add(null);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dummy constructor for analytics testing purposes
|
||||
/// </summary>
|
||||
/// <param name="duration"></param>
|
||||
/// <param name="err"></param>
|
||||
private AddressablesPlayModeBuildResult CreatePlaymodeResult(double duration, string err)
|
||||
{
|
||||
var result = new AddressablesPlayModeBuildResult();
|
||||
result.Duration = duration;
|
||||
result.Error = err;
|
||||
return result;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GenerateBuildData_CorrectlyAcquiresCompressionTypes()
|
||||
{
|
||||
builderInput.IsBuildAndRelease = false;
|
||||
builderInput.IsContentUpdateBuild = false;
|
||||
var buildData = AddressableAnalytics.GenerateBuildData(builderInput, CreateTestResult(0, false, null), AddressableAnalytics.BuildType.Inconclusive);
|
||||
|
||||
Assert.NotNull(buildData, "GenerateBuildData should not return a null value.");
|
||||
Assert.AreEqual(numberOfGroups, buildData.NumberOfGroups, "GenerateBuildData incorrectly retrieves number of groups");
|
||||
Assert.AreEqual(numberOfGroupsUncompressed, buildData.NumberOfGroupsUncompressed, "GenerateBuildData incorrectly retrieves number of uncompressed groups");
|
||||
Assert.AreEqual(numberOfGroupsCompressedWithLZ4, buildData.NumberOfGroupsUsingLZ4, "GenerateBuildData incorrectly retrieves number of groups compressed using LZ4.");
|
||||
Assert.AreEqual(numberOfGroupsCompressedWithLZMA, buildData.NumberOfGroupsUsingLZMA, "GenerateBuildData incorrectly retrieves number of groups compressed using LZMA.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GenerateBuildData_CorrectlyAcquiresBundlePackingMode()
|
||||
{
|
||||
builderInput.IsBuildAndRelease = false;
|
||||
builderInput.IsContentUpdateBuild = false;
|
||||
var buildData = AddressableAnalytics.GenerateBuildData(builderInput, CreateTestResult(0, false, null), AddressableAnalytics.BuildType.Inconclusive);
|
||||
|
||||
Assert.NotNull(buildData, "GenerateBuildData should not return a null value.");
|
||||
Assert.AreEqual(numberOfGroups, buildData.NumberOfGroups, "GenerateBuildData incorrectly retrieves number of groups");
|
||||
Assert.AreEqual(numberOfGroupsPackedSeparately, buildData.NumberOfGroupsPackedSeparately, "GenerateBuildData incorrectly retrieves number of groups packed separately.");
|
||||
Assert.AreEqual(numberOfGroupsPackedTogether, buildData.NumberOfGroupsPackedTogether, "GenerateBuildData incorrectly retrieves number of groups packed together.");
|
||||
Assert.AreEqual(numberOfGroupsPackedTogetherByLabel, buildData.NumberOfGroupsPackedTogetherByLabel, "GenerateBuildData incorrectly retrieves number of groups packed together by label.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GenerateBuildData_CorrectlyCalculatesNumberOfAddressableAssets_SingleGroup()
|
||||
{
|
||||
for (int i = 0; i < 100; i++)
|
||||
testSettings.groups[0].AddAssetEntry(testSettings.CreateEntry(System.Guid.NewGuid().ToString(), "AddressableAnalyticsTest" + i, testSettings.groups[0],
|
||||
false, false));
|
||||
|
||||
builderInput.IsBuildAndRelease = false;
|
||||
builderInput.IsContentUpdateBuild = false;
|
||||
var buildData = AddressableAnalytics.GenerateBuildData(builderInput, CreateTestResult(0, false, null), AddressableAnalytics.BuildType.Inconclusive);
|
||||
|
||||
Assert.NotNull(buildData, "GenerateBuildData should not return a null value.");
|
||||
Assert.AreEqual(numberOfGroups, buildData.NumberOfGroups, "GenerateBuildData incorrectly retrieves number of groups");
|
||||
Assert.AreEqual(100, buildData.NumberOfAddressableAssets, "GenerateBuildData incorrectly retrieves number of AddressableAssets");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GenerateBuildData_CorrectlyCalculatesNumberOfAddressableAssets_MultipleGroups()
|
||||
{
|
||||
foreach (var group in testSettings.groups)
|
||||
for (int i = 0; i < 20; i++)
|
||||
group.AddAssetEntry(testSettings.CreateEntry(System.Guid.NewGuid().ToString(),
|
||||
"AddressableAnalyticsTest" + group.Name + i, group, false));
|
||||
|
||||
builderInput.IsBuildAndRelease = false;
|
||||
builderInput.IsContentUpdateBuild = false;
|
||||
var buildData = AddressableAnalytics.GenerateBuildData(builderInput, CreateTestResult(0, false, null), AddressableAnalytics.BuildType.Inconclusive);
|
||||
Assert.NotNull(buildData, "GenerateBuildData should not return a null value.");
|
||||
Assert.AreEqual(numberOfGroups, buildData.NumberOfGroups, "GenerateBuildData incorrectly retrieves number of groups");
|
||||
Assert.AreEqual(numberOfGroups * 20, buildData.NumberOfAddressableAssets, "GenerateBuildData incorrectly retrieves number of AddressableAssets");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GenerateBuildData_CorrectlyRetrievesMinAndMaxAssetsInGroups()
|
||||
{
|
||||
var group0 = testSettings.groups[0];
|
||||
var group1 = testSettings.groups[1];
|
||||
|
||||
for (int i = 0; i < 30; i++)
|
||||
{
|
||||
group0.AddAssetEntry(testSettings.CreateEntry(System.Guid.NewGuid().ToString(),
|
||||
"AddressableAnalyticsTest" + group0.Name + i, group0, false));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
group1.AddAssetEntry(testSettings.CreateEntry(System.Guid.NewGuid().ToString(),
|
||||
"AddressableAnalyticsTest" + group1.Name + i, group1, false));
|
||||
}
|
||||
|
||||
for (int i = 2; i < 6; i++)
|
||||
{
|
||||
var group = testSettings.groups[i];
|
||||
group.AddAssetEntry(testSettings.CreateEntry(System.Guid.NewGuid().ToString(),
|
||||
"AddressableAnalyticsTest" + group.Name + i, group, false));
|
||||
}
|
||||
|
||||
builderInput.IsBuildAndRelease = false;
|
||||
builderInput.IsContentUpdateBuild = false;
|
||||
var buildData = AddressableAnalytics.GenerateBuildData(builderInput, CreateTestResult(0, false, null), AddressableAnalytics.BuildType.Inconclusive);
|
||||
Assert.NotNull(buildData, "GenerateBuildData should not return a null value.");
|
||||
Assert.AreEqual(30, buildData.MaxNumberOfAddressableAssetsInAGroup, "GenerateBuildData does not properly retrieve Max number of addressable assets in a group");
|
||||
Assert.AreEqual(1, buildData.MinNumberOfAddressableAssetsInAGroup, "GenerateBuildData does not properly retrieve min number of addressable assets in a group");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GenerateBuildData_CorrectlyRetrievesBuildAndReleaseValue()
|
||||
{
|
||||
builderInput.IsBuildAndRelease = true;
|
||||
builderInput.IsContentUpdateBuild = false;
|
||||
var buildData = AddressableAnalytics.GenerateBuildData(builderInput, CreateTestResult(0, false, null), AddressableAnalytics.BuildType.Inconclusive);
|
||||
Assert.IsTrue(buildData.BuildAndRelease, "Value of BuildAndRelease is not properly set");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GenerateBuildData_CorrectlyDeterminesBuildTypeFromInput()
|
||||
{
|
||||
builderInput.IsBuildAndRelease = false;
|
||||
builderInput.IsContentUpdateBuild = false;
|
||||
var buildData1 = AddressableAnalytics.GenerateBuildData(builderInput, CreateTestResult(0, false, null), AddressableAnalytics.BuildType.Inconclusive);
|
||||
Assert.AreEqual(-1, buildData1.IsIncrementalBuild, "BuildType not correctly set by analytics, ensure that an Inconclusive build is associated with an IsIncrementalBuild value of -1");
|
||||
var buildData2 = AddressableAnalytics.GenerateBuildData(builderInput, CreateTestResult(0, false, null), AddressableAnalytics.BuildType.CleanBuild);
|
||||
Assert.AreEqual(0, buildData2.IsIncrementalBuild, "BuildType not correctly set by analytics, ensure that a clean build is associated with an IsIncrementalBuild value of 0");
|
||||
var buildData3 = AddressableAnalytics.GenerateBuildData(builderInput, CreateTestResult(0, false, null), AddressableAnalytics.BuildType.IncrementalBuild);
|
||||
Assert.AreEqual(1, buildData3.IsIncrementalBuild, "BuildType not correctly set by analytics, ensure that a clean build is associated with an IsIncrementalBuild value of 1");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GenerateBuildData_OnlyIncludesBuildScriptNameInPlayModeBuild()
|
||||
{
|
||||
builderInput.IsBuildAndRelease = false;
|
||||
builderInput.IsContentUpdateBuild = false;
|
||||
var buildData = AddressableAnalytics.GenerateBuildData(builderInput, CreateTestResult(0, true, null), AddressableAnalytics.BuildType.Inconclusive);
|
||||
Assert.IsTrue(buildData.IsPlayModeBuild, "IsPlayModeBuild should be true for play mode builds");
|
||||
Assert.AreEqual(0, buildData.NumberOfGroups, "BuildData should be initialized to 0 for play mode builds.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GenerateBuildData_PlayModeScriptIsCorrectlyRetrieved()
|
||||
{
|
||||
var oldActivePlayModeBuildScriptIndex = ProjectConfigData.ActivePlayModeIndex;
|
||||
try
|
||||
{
|
||||
//PackedMode
|
||||
ProjectConfigData.ActivePlayModeIndex = 1;
|
||||
builderInput.IsBuildAndRelease = false;
|
||||
builderInput.IsContentUpdateBuild = false;
|
||||
var buildData1 = AddressableAnalytics.GenerateBuildData(builderInput, CreateTestResult(0, true, null), AddressableAnalytics.BuildType.CleanBuild);
|
||||
Assert.IsTrue(buildData1.IsPlayModeBuild, "IsPlayModeBuild should be true for play mode builds");
|
||||
Assert.AreEqual(2, buildData1.BuildScript, "Fast Mode should correspond to a BuildData.BuildScript value of 2.");
|
||||
//FastMode
|
||||
ProjectConfigData.ActivePlayModeIndex = 2;
|
||||
var buildData2 = AddressableAnalytics.GenerateBuildData(builderInput, CreateTestResult(0, true, null), AddressableAnalytics.BuildType.CleanBuild);
|
||||
Assert.IsTrue(buildData2.IsPlayModeBuild, "IsPlayModeBuild should be true for play mode builds");
|
||||
Assert.AreEqual(3, buildData2.BuildScript, "Virtual mode should correspond to a BuildData.BuildScript value of 3.");
|
||||
//VirtualMode
|
||||
ProjectConfigData.ActivePlayModeIndex = 3;
|
||||
var buildData3 = AddressableAnalytics.GenerateBuildData(builderInput, CreateTestResult(0, true, null), AddressableAnalytics.BuildType.CleanBuild);
|
||||
Assert.IsTrue(buildData3.IsPlayModeBuild, "IsPlayModeBuild should be true for play mode builds");
|
||||
Assert.AreEqual(1, buildData3.BuildScript, "Packed PlayMode should correspond to a BuildData.BuildScript value of 1.");
|
||||
//Custom
|
||||
ProjectConfigData.ActivePlayModeIndex = 4;
|
||||
var buildData4 = AddressableAnalytics.GenerateBuildData(builderInput, CreateTestResult(0, true, null), AddressableAnalytics.BuildType.CleanBuild);
|
||||
Assert.IsTrue(buildData4.IsPlayModeBuild, "IsPlayModeBuild should be true for play mode builds");
|
||||
Assert.AreEqual(4, buildData4.BuildScript, "A custom build script should correspond to a BuildData.BuildScript value of 4.");
|
||||
}
|
||||
finally
|
||||
{
|
||||
ProjectConfigData.ActivePlayModeIndex = oldActivePlayModeBuildScriptIndex;
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GenerateBuildData_ProperlyCollectsDataIfNotPlayModeBuild()
|
||||
{
|
||||
var buildData1 = AddressableAnalytics.GenerateBuildData(builderInput, CreateTestResult(0, false, null), AddressableAnalytics.BuildType.CleanBuild);
|
||||
Assert.AreEqual(0, buildData1.BuildScript, "BuildData should correspond to a BuildData.BuildScript value of 0 because we're using packed mode.");
|
||||
Assert.IsFalse(buildData1.IsPlayModeBuild, "IsPlayModeBuild should be false on player builds.");
|
||||
Assert.AreNotEqual(0, buildData1.NumberOfGroups, "Data should be fully collected in player builds.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GenerateUsageData_UsageEventTypesCorrectlyCorrespondToIntegerValues()
|
||||
{
|
||||
var usageDataGroups =
|
||||
AddressableAnalytics.GenerateUsageData(AddressableAnalytics.UsageEventType.OpenGroupsWindow);
|
||||
var usageDataProfiles =
|
||||
AddressableAnalytics.GenerateUsageData(AddressableAnalytics.UsageEventType.OpenProfilesWindow);
|
||||
var usageDataEventViewer =
|
||||
AddressableAnalytics.GenerateUsageData(AddressableAnalytics.UsageEventType.OpenEventViewerWindow);
|
||||
var usageDataAnalyze =
|
||||
AddressableAnalytics.GenerateUsageData(AddressableAnalytics.UsageEventType.OpenAnalyzeWindow);
|
||||
var usageDataHosting =
|
||||
AddressableAnalytics.GenerateUsageData(AddressableAnalytics.UsageEventType.OpenHostingWindow);
|
||||
|
||||
Assert.AreEqual(0, usageDataGroups.UsageEventType, "Opening the groups window should correspond with an integer value of 0");
|
||||
Assert.AreEqual(1, usageDataProfiles.UsageEventType, "Opening the profiles window should correspond with an integer value of 1");
|
||||
Assert.AreEqual(2, usageDataEventViewer.UsageEventType, "Opening the event viewer window should correspond with an integer value of 2");
|
||||
Assert.AreEqual(3, usageDataAnalyze.UsageEventType, "Opening the analyze window should correspond with an integer value of 3");
|
||||
Assert.AreEqual(4, usageDataHosting.UsageEventType, "Opening the hosting window should correspond with an integer value of 4");
|
||||
}
|
||||
|
||||
// This test is just to lock down behavior, please do not make any changes that would lead to this test failing as it will break analytics!
|
||||
// The analytics platform relies on each of these values being what they are, and any changes will lead to discontinuity in the data.
|
||||
[Test]
|
||||
public void EnsureCheckForContentUpdateRestrictionAndAnalyticsEnumMatch()
|
||||
{
|
||||
Assert.AreEqual((int)CheckForContentUpdateRestrictionsOptions.ListUpdatedAssetsWithRestrictions,
|
||||
(int)AddressableAnalytics.AnalyticsContentUpdateRestriction.ListUpdatedAssetsWithRestrictions,
|
||||
"The ListUpdatedAssetsWithRestrictions member of both enums should correspond to the same integer");
|
||||
Assert.AreEqual(0, (int)CheckForContentUpdateRestrictionsOptions.ListUpdatedAssetsWithRestrictions,
|
||||
"The ListUpdatedAssetsWithRestrictions member should correspond to 0 for consistency with the analytics platform.");
|
||||
|
||||
Assert.AreEqual((int)CheckForContentUpdateRestrictionsOptions.FailBuild,
|
||||
(int)AddressableAnalytics.AnalyticsContentUpdateRestriction.FailBuild, "The FailBuild member of both enums should correspond to the same integer");
|
||||
Assert.AreEqual(1, (int)CheckForContentUpdateRestrictionsOptions.FailBuild, "The FailBuild member should correspond to 1 for consistency with the analytics platform.");
|
||||
|
||||
Assert.AreEqual((int)CheckForContentUpdateRestrictionsOptions.Disabled,
|
||||
(int)AddressableAnalytics.AnalyticsContentUpdateRestriction.Disabled, "The disabled member of both enums should correspond to the same integer");
|
||||
Assert.AreEqual(2, (int)CheckForContentUpdateRestrictionsOptions.Disabled, "The Disabled member should correspond to 2 for consistency with the analytics platform.");
|
||||
|
||||
Assert.AreEqual(-1, (int)AddressableAnalytics.AnalyticsContentUpdateRestriction.NotApplicable,
|
||||
"For non applicable data events, the AnalyticsContentUpdateRestriction enum should correspond to -1");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c349d15a2c35fcb47be33f570820ac4b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,994 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using UnityEditor.AddressableAssets.Settings;
|
||||
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
|
||||
using UnityEditor.Build.Content;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEditor.U2D;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets.ResourceLocators;
|
||||
using UnityEngine.AddressableAssets.Tests;
|
||||
using UnityEngine.ResourceManagement.ResourceProviders;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.TestTools;
|
||||
using UnityEngine.U2D;
|
||||
|
||||
namespace UnityEditor.AddressableAssets.Tests
|
||||
{
|
||||
public class AddressableAssetEntryTests : AddressableAssetTestBase
|
||||
{
|
||||
string m_guid;
|
||||
AddressableAssetGroup m_testGroup;
|
||||
AddressableAssetSettings m_Settings;
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
var path = GetAssetPath("subObjectTest.asset");
|
||||
AssetDatabase.CreateAsset(UnityEngine.AddressableAssets.Tests.TestObject.Create("test"), path);
|
||||
|
||||
AssetDatabase.AddObjectToAsset(UnityEngine.AddressableAssets.Tests.TestObject2.Create("test2"), path);
|
||||
AssetDatabase.AddObjectToAsset(UnityEngine.AddressableAssets.Tests.TestObject2.Create("test3"), path);
|
||||
AssetDatabase.AddObjectToAsset(UnityEngine.AddressableAssets.Tests.TestObject2.Create("test4"), path);
|
||||
AssetDatabase.AddObjectToAsset(UnityEngine.AddressableAssets.Tests.TestObject2.Create("test5"), path);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
m_guid = AssetDatabase.AssetPathToGUID(path);
|
||||
Settings.CreateOrMoveEntry(m_guid, Settings.DefaultGroup);
|
||||
AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceSynchronousImport | ImportAssetOptions.ForceUpdate);
|
||||
AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
|
||||
|
||||
m_testGroup = Settings.CreateGroup("testGroup", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
}
|
||||
|
||||
protected override void OnCleanup()
|
||||
{
|
||||
Settings.RemoveGroup(m_testGroup);
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateKeyList_Returns_ExpectedKeys()
|
||||
{
|
||||
var e = Settings.DefaultGroup.GetAssetEntry(m_guid);
|
||||
e.SetAddress("address");
|
||||
e.SetLabel("label", true, true, true);
|
||||
CollectionAssert.AreEqual(new string[] {"address", m_guid, "label"}, e.CreateKeyList(true, true, true));
|
||||
CollectionAssert.AreEqual(new string[] {m_guid, "label"}, e.CreateKeyList(false, true, true));
|
||||
CollectionAssert.AreEqual(new string[] {"address", "label"}, e.CreateKeyList(true, false, true));
|
||||
CollectionAssert.AreEqual(new string[] {"address", "label"}, e.CreateKeyList(true, false, true));
|
||||
CollectionAssert.AreEqual(new string[] {"label"}, e.CreateKeyList(false, false, true));
|
||||
CollectionAssert.AreEqual(new string[] {"address"}, e.CreateKeyList(true, false, false));
|
||||
CollectionAssert.AreEqual(new string[] {m_guid}, e.CreateKeyList(false, true, false));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EditorInitialization_RemovesAssetEntriesThatDoesNotExistOnDisk()
|
||||
{
|
||||
//setup
|
||||
var group = Settings.DefaultGroup;
|
||||
AddressableAssetEntry assetEntry = new AddressableAssetEntry("fakeguid", "fakeaddress", group, false);
|
||||
assetEntry.m_cachedAssetPath = "Assets/NotARealAssetPath/test.prefab";
|
||||
group.AddAssetEntry(assetEntry, false);
|
||||
|
||||
//test
|
||||
AddressableEditorInitialization.PurgeInvalidAssetEntries(Settings);
|
||||
|
||||
//Assert
|
||||
Assert.IsFalse(group.entries.Contains(assetEntry));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EditorInitialization_DoesNotDeleteFoldersThatAreStillOnDisk()
|
||||
{
|
||||
//Setup
|
||||
string folderPath = "Assets/Temp/FakeAddressablesFolder/";
|
||||
Directory.CreateDirectory(folderPath);
|
||||
AssetDatabase.ImportAsset(folderPath);
|
||||
AddressableAssetEntry entry = new AddressableAssetEntry(AssetDatabase.AssetPathToGUID(folderPath),
|
||||
folderPath, m_testGroup, false);
|
||||
m_testGroup.AddAssetEntry(entry);
|
||||
entry.m_cachedAssetPath = folderPath;
|
||||
|
||||
Assert.IsTrue(m_testGroup.entries.Contains(entry), "Folder entry is no longer in Addressable group before purge.");
|
||||
|
||||
//Test
|
||||
AddressableEditorInitialization.PurgeInvalidAssetEntries(Settings);
|
||||
|
||||
//Assert
|
||||
Assert.IsTrue(m_testGroup.entries.Contains(entry), "Folder entry is no longer in Addressable group after purge.");
|
||||
|
||||
//Cleanup
|
||||
m_testGroup.RemoveAssetEntry(entry);
|
||||
AssetDatabase.DeleteAsset(folderPath);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EditorInitialization_DoesDeleteFoldersThatAreNotOnDisk()
|
||||
{
|
||||
//Setup
|
||||
string folderPath = "Assets/Temp/FakeAddressablesFolder/";
|
||||
AddressableAssetEntry entry = new AddressableAssetEntry(AssetDatabase.AssetPathToGUID(folderPath),
|
||||
folderPath, m_testGroup, false);
|
||||
entry.m_cachedAssetPath = folderPath;
|
||||
m_testGroup.AddAssetEntry(entry);
|
||||
|
||||
//Test
|
||||
AddressableEditorInitialization.PurgeInvalidAssetEntries(Settings);
|
||||
|
||||
//Assert
|
||||
Assert.IsFalse(m_testGroup.entries.Contains(entry), "Invalid asset entry folder is still in Asset Group after purge.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetAssetLoadPath_Returns_ExpectedPath()
|
||||
{
|
||||
var schema = Settings.DefaultGroup.GetSchema<BundledAssetGroupSchema>();
|
||||
var e = Settings.DefaultGroup.GetAssetEntry(m_guid);
|
||||
schema.InternalIdNamingMode = BundledAssetGroupSchema.AssetNamingMode.FullPath;
|
||||
Assert.AreEqual(e.AssetPath, e.GetAssetLoadPath(true, null));
|
||||
schema.InternalIdNamingMode = BundledAssetGroupSchema.AssetNamingMode.Filename;
|
||||
Assert.AreEqual(Path.GetFileName(e.AssetPath), e.GetAssetLoadPath(true, null));
|
||||
schema.InternalIdNamingMode = BundledAssetGroupSchema.AssetNamingMode.GUID;
|
||||
Assert.AreEqual(m_guid, e.GetAssetLoadPath(true, null));
|
||||
schema.InternalIdNamingMode = BundledAssetGroupSchema.AssetNamingMode.Dynamic;
|
||||
Assert.AreEqual(m_guid, e.GetAssetLoadPath(true, null));
|
||||
Assert.AreEqual(m_guid.Substring(0, 1), e.GetAssetLoadPath(true, new HashSet<string>()));
|
||||
var hs = new HashSet<string>();
|
||||
hs.Add(m_guid.Substring(0, 1));
|
||||
Assert.AreEqual(m_guid.Substring(0, 2), e.GetAssetLoadPath(true, hs));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateCatalogEntries_WhenObjectHasMultipleSubObjectWithSameType_OnlyOneSubEntryIsCreated()
|
||||
{
|
||||
var e = Settings.DefaultGroup.GetAssetEntry(m_guid);
|
||||
var entries = new List<ContentCatalogDataEntry>();
|
||||
var providerTypes = new HashSet<Type>();
|
||||
e.CreateCatalogEntries(entries, false, "doesntMatter", null, null, providerTypes);
|
||||
Assert.AreEqual(2, entries.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DefaultTypeAssetEntry_ResetsCachedTypeData()
|
||||
{
|
||||
//Setup
|
||||
var path = GetAssetPath("entry.prefab");
|
||||
PrefabUtility.SaveAsPrefabAsset(new GameObject(), path);
|
||||
string guid = AssetDatabase.AssetPathToGUID(path);
|
||||
|
||||
AddressableAssetEntry entry = new AddressableAssetEntry(guid, "testaddress", Settings.DefaultGroup, false);
|
||||
entry.m_cachedMainAssetType = typeof(DefaultAsset);
|
||||
|
||||
//Test
|
||||
entry.CreateCatalogEntries(new List<ContentCatalogDataEntry>(), false, "fakeProvider", new List<object>(), null, new Dictionary<GUID, AssetLoadInfo>()
|
||||
{
|
||||
{new GUID(guid), new AssetLoadInfo() {includedObjects = new List<ObjectIdentifier>()}}
|
||||
},
|
||||
new HashSet<Type>(), true, false, false, new HashSet<string>());
|
||||
|
||||
//Assert
|
||||
Assert.AreEqual(typeof(GameObject), entry.m_cachedMainAssetType);
|
||||
|
||||
//Cleanup
|
||||
AssetDatabase.DeleteAsset(path);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateCatalogEntries_OverridesMainTypeIfWrong()
|
||||
{
|
||||
var e = Settings.DefaultGroup.GetAssetEntry(m_guid);
|
||||
var entries = new List<ContentCatalogDataEntry>();
|
||||
var providerTypes = new HashSet<Type>();
|
||||
var savedType = e.m_cachedMainAssetType;
|
||||
e.m_cachedMainAssetType = typeof(Texture2D); //something arbitrarily wrong.
|
||||
e.CreateCatalogEntries(entries, false, "doesntMatter", null, null, providerTypes);
|
||||
e.m_cachedMainAssetType = savedType;
|
||||
Assert.AreEqual(2, entries.Count);
|
||||
bool foundOnlyTestObjects = true;
|
||||
foreach (var entry in entries)
|
||||
{
|
||||
if (entry.ResourceType != typeof(UnityEngine.AddressableAssets.Tests.TestObject) &&
|
||||
(entry.ResourceType != typeof(UnityEngine.AddressableAssets.Tests.TestObject2)))
|
||||
{
|
||||
foundOnlyTestObjects = false;
|
||||
}
|
||||
}
|
||||
|
||||
Assert.IsTrue(foundOnlyTestObjects);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateCatalogEntries_EditorTypesShouldBeStripped()
|
||||
{
|
||||
var e = Settings.DefaultGroup.GetAssetEntry(m_guid);
|
||||
var entries = new List<ContentCatalogDataEntry>();
|
||||
var providerTypes = new HashSet<Type>();
|
||||
var savedType = e.m_cachedMainAssetType;
|
||||
e.m_cachedMainAssetType = typeof(UnityEditor.AssetImporter);
|
||||
e.CreateCatalogEntries(entries, false, "doesntMatter", null, null, providerTypes);
|
||||
e.m_cachedMainAssetType = savedType;
|
||||
Assert.AreEqual(0, entries.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateCatalogEntries_NonUnityObjectsTypesAreStripped()
|
||||
{
|
||||
// Init
|
||||
string id = "testObject";
|
||||
var path = GetAssetPath("testObjectWithSerializedClass.asset");
|
||||
var testObject = TestObjectWithSerializableField.Create(id);
|
||||
AssetDatabase.CreateAsset(testObject, path);
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceSynchronousImport | ImportAssetOptions.ForceUpdate);
|
||||
AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
|
||||
|
||||
var e = Settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(path), Settings.DefaultGroup);
|
||||
e.address = id;
|
||||
|
||||
// test
|
||||
try
|
||||
{
|
||||
var entries = new List<ContentCatalogDataEntry>();
|
||||
var providerTypes = new HashSet<Type>();
|
||||
e.CreateCatalogEntries(entries, false, "doesntMatter", null, null, providerTypes);
|
||||
var foundCatalogEntryForSerialisedClass = entries.Find(entry => entry.ResourceType == typeof(SerializableClass));
|
||||
Assert.IsNull(foundCatalogEntryForSerialisedClass,
|
||||
"SerializableClass was found as a catalog entry type. Only Unity Objects are meant to be Assets not serialised objects internal to the type.");
|
||||
}
|
||||
finally
|
||||
{
|
||||
Settings.RemoveAssetEntry(e);
|
||||
AssetDatabase.DeleteAsset(path);
|
||||
UnityEngine.Object.DestroyImmediate(testObject);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateCatalogEntries_IncludesUnityObjectsOnly()
|
||||
{
|
||||
// Init
|
||||
string id = "testObject";
|
||||
var path = GetAssetPath("testObjectWithSerializedClass.asset");
|
||||
var testObject = TestObjectWithSerializableField.Create(id);
|
||||
AssetDatabase.CreateAsset(testObject, path);
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceSynchronousImport | ImportAssetOptions.ForceUpdate);
|
||||
AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
|
||||
|
||||
var e = Settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(path), Settings.DefaultGroup);
|
||||
e.address = id;
|
||||
|
||||
// test
|
||||
try
|
||||
{
|
||||
var entries = new List<ContentCatalogDataEntry>();
|
||||
var providerTypes = new HashSet<Type>();
|
||||
e.CreateCatalogEntries(entries, false, "doesntMatter", null, null, providerTypes);
|
||||
var foundCatalogEntryForTestObject = entries.Find(entry => entry.ResourceType == typeof(TestObjectWithSerializableField));
|
||||
Assert.AreEqual(1, entries.Count, "Too many catalog entries found for TestObjectWithSerializableField Asset created");
|
||||
Assert.IsNotNull(foundCatalogEntryForTestObject, "TestObjectWithSerializableField was not found for catalog entries for the ScriptableObject type.");
|
||||
}
|
||||
finally
|
||||
{
|
||||
Settings.RemoveAssetEntry(e);
|
||||
AssetDatabase.DeleteAsset(path);
|
||||
UnityEngine.Object.DestroyImmediate(testObject);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MainAsset_WhenEntryIsForSubAsset_ShouldReturnMainAsset()
|
||||
{
|
||||
var mainAssetEntry = Settings.DefaultGroup.GetAssetEntry(m_guid);
|
||||
var entries = new List<AddressableAssetEntry>();
|
||||
Settings.DefaultGroup.GatherAllAssets(entries, true, true, true);
|
||||
|
||||
var subAssetEntry = entries.FirstOrDefault(e => e.IsSubAsset);
|
||||
Assert.NotNull(subAssetEntry);
|
||||
Assert.AreEqual(mainAssetEntry.MainAsset, subAssetEntry.MainAsset);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TargetAsset_WhenEntryIsForMainAsset_ShouldReturnMainAsset()
|
||||
{
|
||||
var entry = Settings.DefaultGroup.GetAssetEntry(m_guid);
|
||||
Assert.AreEqual(entry.MainAsset, entry.TargetAsset);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TargetAsset_WhenMainAssetIsSpriteAtlas_ShouldReturnSprite()
|
||||
{
|
||||
var atlasPath = CreateSpriteAtlasWithSprite();
|
||||
var guid = AssetDatabase.AssetPathToGUID(atlasPath);
|
||||
Settings.CreateOrMoveEntry(guid, Settings.DefaultGroup);
|
||||
AssetDatabase.ImportAsset(atlasPath, ImportAssetOptions.ForceSynchronousImport | ImportAssetOptions.ForceUpdate);
|
||||
AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
|
||||
|
||||
var atlas = AssetDatabase.LoadAssetAtPath<SpriteAtlas>(atlasPath);
|
||||
var sprites = new Sprite[atlas.spriteCount];
|
||||
atlas.GetSprites(sprites);
|
||||
|
||||
var mainAssetEntry = Settings.DefaultGroup.GetAssetEntry(guid);
|
||||
var entries = new List<AddressableAssetEntry>();
|
||||
mainAssetEntry.GatherAllAssets(entries, false, true, true);
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(sprites.Length, entries.Count);
|
||||
foreach (var entry in entries)
|
||||
{
|
||||
Assert.IsTrue(sprites.Any(s => s.name == entry.TargetAsset.name));
|
||||
Assert.IsTrue(entry.TargetAsset is Sprite);
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
Settings.RemoveAssetEntry(guid);
|
||||
File.Delete(atlasPath);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TargetAsset_WhenEntryIsForSubAsset_ShouldReturnSubObject()
|
||||
{
|
||||
var mainAssetEntry = Settings.DefaultGroup.GetAssetEntry(m_guid);
|
||||
var entries = new List<AddressableAssetEntry>();
|
||||
Settings.DefaultGroup.GatherAllAssets(entries, false, true, true);
|
||||
var subObjects = AssetDatabase.LoadAllAssetRepresentationsAtPath(mainAssetEntry.AssetPath);
|
||||
Assert.AreEqual(subObjects.Length, entries.Count);
|
||||
foreach (var entry in entries)
|
||||
{
|
||||
Assert.IsTrue(subObjects.Contains(entry.TargetAsset));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenGettingFolderSubEntry_OnlyReturnsIfValidSubEntry()
|
||||
{
|
||||
AddressableAssetEntry mainFolderEntry = null;
|
||||
AddressableAssetEntry subFolderEntry = null;
|
||||
string testAssetFolder = GetAssetPath("TestFolder");
|
||||
|
||||
try
|
||||
{
|
||||
//Setup
|
||||
string testAssetSubFolder = Path.Combine(testAssetFolder, "SubFolder");
|
||||
|
||||
string mainPrefabPath = Path.Combine(testAssetFolder, "mainFolder.prefab").Replace('\\', '/');
|
||||
string subPrefabPath = Path.Combine(testAssetSubFolder, "subFolder.prefab").Replace('\\', '/');
|
||||
|
||||
Directory.CreateDirectory(testAssetFolder);
|
||||
PrefabUtility.SaveAsPrefabAsset(new GameObject("mainFolderAsset"), mainPrefabPath);
|
||||
|
||||
Directory.CreateDirectory(testAssetSubFolder);
|
||||
PrefabUtility.SaveAsPrefabAsset(new GameObject("subFolderAsset"), subPrefabPath);
|
||||
|
||||
string mainFolderGuid = AssetDatabase.AssetPathToGUID(testAssetFolder);
|
||||
string subFolderGuid = AssetDatabase.AssetPathToGUID(testAssetSubFolder);
|
||||
mainFolderEntry = Settings.CreateOrMoveEntry(mainFolderGuid, m_testGroup, false);
|
||||
subFolderEntry = Settings.CreateOrMoveEntry(subFolderGuid, m_testGroup, false);
|
||||
|
||||
//Test
|
||||
var entry = mainFolderEntry.GetFolderSubEntry(AssetDatabase.AssetPathToGUID(mainPrefabPath), mainPrefabPath);
|
||||
Assert.IsNotNull(entry, "Prefab in main folder is expected to be valid subAsset of main folder.");
|
||||
entry = mainFolderEntry.GetFolderSubEntry(AssetDatabase.AssetPathToGUID(subPrefabPath), subPrefabPath);
|
||||
Assert.IsNull(entry, "Prefab in addressable sub folder is not expected to be valid subAsset of main folder.");
|
||||
|
||||
entry = subFolderEntry.GetFolderSubEntry(AssetDatabase.AssetPathToGUID(mainPrefabPath), mainPrefabPath);
|
||||
Assert.IsNull(entry, "Prefab in main folder is not expected to be valid subAsset of sub folder.");
|
||||
entry = subFolderEntry.GetFolderSubEntry(AssetDatabase.AssetPathToGUID(subPrefabPath), subPrefabPath);
|
||||
Assert.IsNotNull(entry, "Prefab in addressable sub folder is expected to be valid subAsset of sub folder.");
|
||||
}
|
||||
finally
|
||||
{
|
||||
//Cleanup
|
||||
Settings.RemoveAssetEntry(mainFolderEntry, false);
|
||||
Settings.RemoveAssetEntry(subFolderEntry, false);
|
||||
Directory.Delete(testAssetFolder, true);
|
||||
}
|
||||
}
|
||||
|
||||
[TestCase(true)]
|
||||
[TestCase(false)]
|
||||
public void WhenGatherFolderEntries_ReturnsCorrectAssetObjects(bool includeSubObjects)
|
||||
{
|
||||
AddressableAssetEntry addrFolderEntry = null;
|
||||
string addressableFolderPath = GetAssetPath("TestFolder");
|
||||
|
||||
try
|
||||
{
|
||||
//Setup
|
||||
string folderGuid = CreateFolderDeep(addressableFolderPath);
|
||||
addrFolderEntry = Settings.CreateOrMoveEntry(folderGuid, m_testGroup, false);
|
||||
|
||||
string testAssetPath = Path.Combine(addressableFolderPath, "testObject.asset").Replace('\\', '/');
|
||||
var testAsset = TestObject.Create("testObject", testAssetPath);
|
||||
testAsset.AddTestSubObject();
|
||||
|
||||
//Test
|
||||
List<AddressableAssetEntry> entries = new List<AddressableAssetEntry>();
|
||||
addrFolderEntry.GatherFolderEntries(entries, true, includeSubObjects, null);
|
||||
if (includeSubObjects)
|
||||
Assert.AreEqual(entries.Count, 2, "GatherFolder entries was expected to return the Asset added and its subObject");
|
||||
else
|
||||
Assert.AreEqual(entries.Count, 1, "GatherFolder entries was expected to only return the Asset added and not its subObject");
|
||||
}
|
||||
finally
|
||||
{
|
||||
//Cleanup
|
||||
Settings.RemoveAssetEntry(addrFolderEntry, false);
|
||||
AssetDatabase.DeleteAsset(addressableFolderPath);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetFolderSubEntry_SetsLabelsCorrectlyOnShortPath()
|
||||
{
|
||||
AddressableAssetEntry mainFolderEntry = null;
|
||||
string testAssetFolder = GetAssetPath("TestFolder");
|
||||
|
||||
try
|
||||
{
|
||||
//Setup
|
||||
string mainPrefabPath = Path.Combine(testAssetFolder, "mainFolder.prefab").Replace('\\', '/');
|
||||
|
||||
Directory.CreateDirectory(testAssetFolder);
|
||||
PrefabUtility.SaveAsPrefabAsset(new GameObject("mainFolderAsset"), mainPrefabPath);
|
||||
|
||||
string mainFolderGuid = AssetDatabase.AssetPathToGUID(testAssetFolder);
|
||||
mainFolderEntry = Settings.CreateOrMoveEntry(mainFolderGuid, m_testGroup, false);
|
||||
|
||||
mainFolderEntry.SetLabel("testlabel", true);
|
||||
|
||||
//Test
|
||||
var entry = mainFolderEntry.GetFolderSubEntry(AssetDatabase.AssetPathToGUID(mainPrefabPath), mainPrefabPath);
|
||||
Assert.IsNotNull(entry, "Prefab in main folder is expected to be valid subAsset of main folder.");
|
||||
Assert.AreEqual(1, entry.labels.Count, "Labels should be correctly copied over when using GetFolderSubEntry");
|
||||
Assert.AreEqual(testAssetFolder + "/mainFolder.prefab", entry.AssetPath, "Asset path should be correctly set when using GetFolderSubEntry");
|
||||
}
|
||||
finally
|
||||
{
|
||||
//Cleanup
|
||||
Settings.RemoveAssetEntry(mainFolderEntry, false);
|
||||
Directory.Delete(testAssetFolder, true);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetFolderSubEntry_SetsLabelsCorrectlyOnLongPath()
|
||||
{
|
||||
AddressableAssetEntry mainFolderEntry = null;
|
||||
string testAssetFolder = GetAssetPath("TestFolder");
|
||||
|
||||
try
|
||||
{
|
||||
//Setup
|
||||
string extraFolderPath = Path.Combine(testAssetFolder, "secondaryFolder").Replace('\\', '/');
|
||||
string mainPrefabPath = Path.Combine(extraFolderPath, "mainFolder.prefab").Replace('\\', '/');
|
||||
|
||||
Directory.CreateDirectory(testAssetFolder);
|
||||
Directory.CreateDirectory(extraFolderPath);
|
||||
PrefabUtility.SaveAsPrefabAsset(new GameObject("mainFolderAsset"), mainPrefabPath);
|
||||
|
||||
string mainFolderGuid = AssetDatabase.AssetPathToGUID(testAssetFolder);
|
||||
mainFolderEntry = Settings.CreateOrMoveEntry(mainFolderGuid, m_testGroup, false);
|
||||
|
||||
mainFolderEntry.SetLabel("testlabel", true);
|
||||
|
||||
//Test
|
||||
var entry = mainFolderEntry.GetFolderSubEntry(AssetDatabase.AssetPathToGUID(mainPrefabPath), mainPrefabPath);
|
||||
Assert.IsNotNull(entry, "Prefab in main folder is expected to be valid subAsset of main folder.");
|
||||
Assert.AreEqual(1, entry.labels.Count, "Labels should be correctly copied over when using GetFolderSubEntry");
|
||||
Assert.AreEqual(extraFolderPath + "/mainFolder.prefab", entry.AssetPath, "Asset path should be correctly set when using GetFolderSubEntry");
|
||||
}
|
||||
finally
|
||||
{
|
||||
//Cleanup
|
||||
Settings.RemoveAssetEntry(mainFolderEntry, false);
|
||||
Directory.Delete(testAssetFolder, true);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenClassReferencedByAddressableAssetEntryIsReloaded_CachedMainAssetTypeIsReset()
|
||||
{
|
||||
// Setup
|
||||
var path = GetAssetPath("resetCachedMainAssetTypeTestGroup.asset");
|
||||
AddressableAssetGroup group = ScriptableObject.CreateInstance<AddressableAssetGroup>();
|
||||
AddressableAssetEntry entry = new AddressableAssetEntry(m_guid, "address", null, false);
|
||||
group.AddAssetEntry(entry);
|
||||
|
||||
Assert.IsNull(entry.m_cachedMainAssetType);
|
||||
Assert.AreEqual(typeof(UnityEngine.AddressableAssets.Tests.TestObject), entry.MainAssetType);
|
||||
|
||||
// Test
|
||||
AssetDatabase.CreateAsset(group, path);
|
||||
Resources.UnloadAsset(group);
|
||||
|
||||
var reloadedGroup = AssetDatabase.LoadAssetAtPath<AddressableAssetGroup>(path);
|
||||
var reloadedEntry = reloadedGroup.GetAssetEntry(m_guid);
|
||||
Assert.IsNull(reloadedEntry.m_cachedMainAssetType);
|
||||
|
||||
// Cleanup
|
||||
AssetDatabase.DeleteAsset(path);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GatherAllAssets_WhenResourcesExist_RecurseAllIsFalse_ReturnsEntriesForValidFilesAndTopFoldersOnly()
|
||||
{
|
||||
using (new HideResourceFoldersScope())
|
||||
{
|
||||
var resourcePath = GetAssetPath("Resources");
|
||||
var subFolderPath = resourcePath + "/Subfolder";
|
||||
Directory.CreateDirectory(subFolderPath);
|
||||
|
||||
var group = Settings.FindGroup(AddressableAssetSettings.PlayerDataGroupName);
|
||||
var resourceEntry = Settings.CreateOrMoveEntry(AddressableAssetEntry.ResourcesName, group, false);
|
||||
int builtInResourcesCount = ResourcesTestUtility.GetResourcesEntryCount(Settings, false);
|
||||
|
||||
var r1GUID = CreateAsset(resourcePath + "/testResource1.prefab", "testResource1");
|
||||
var r2GUID = CreateAsset(subFolderPath + "/testResource2.prefab", "testResource2");
|
||||
|
||||
var entries = new List<AddressableAssetEntry>();
|
||||
resourceEntry.GatherAllAssets(entries, false, false, true);
|
||||
|
||||
// Assert
|
||||
var subFolderGUID = AssetDatabase.AssetPathToGUID(subFolderPath);
|
||||
Assert.AreEqual(2 + builtInResourcesCount, entries.Count);
|
||||
Assert.IsTrue(entries.Any(e => e.guid == r1GUID));
|
||||
Assert.IsFalse(entries.Any(e => e.guid == r2GUID));
|
||||
Assert.IsTrue(entries.Any(e => e.guid == subFolderGUID));
|
||||
|
||||
// Cleanup
|
||||
Directory.Delete(resourcePath, true);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GatherAllAssets_WhenResourcesExist_RecurseAllIsTrue_ReturnsEntriesRecursivelyForValidFilesOnly()
|
||||
{
|
||||
using (new HideResourceFoldersScope())
|
||||
{
|
||||
var resourcePath = GetAssetPath("Resources");
|
||||
var subFolderPath = resourcePath + "/Subfolder";
|
||||
Directory.CreateDirectory(subFolderPath);
|
||||
|
||||
var group = Settings.FindGroup(AddressableAssetSettings.PlayerDataGroupName);
|
||||
var resourceEntry = Settings.CreateOrMoveEntry(AddressableAssetEntry.ResourcesName, group, false);
|
||||
int builtInResourcesCount = ResourcesTestUtility.GetResourcesEntryCount(Settings, true);
|
||||
|
||||
var r1GUID = CreateAsset(resourcePath + "/testResource1.prefab", "testResource1");
|
||||
var r2GUID = CreateAsset(subFolderPath + "/testResource2.prefab", "testResource2");
|
||||
|
||||
var entries = new List<AddressableAssetEntry>();
|
||||
resourceEntry.GatherAllAssets(entries, false, true, true);
|
||||
|
||||
// Assert
|
||||
var subFolderGUID = AssetDatabase.AssetPathToGUID(subFolderPath);
|
||||
Assert.AreEqual(2 + builtInResourcesCount, entries.Count);
|
||||
Assert.IsTrue(entries.Any(e => e.guid == r1GUID));
|
||||
Assert.IsTrue(entries.Any(e => e.guid == r2GUID));
|
||||
Assert.IsFalse(entries.Any(e => e.guid == subFolderGUID));
|
||||
|
||||
// Cleanup
|
||||
Directory.Delete(resourcePath, true);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GatherAllAssets_WhenNonEmptyAddressableFolderExist_RecurseAllIsFalse_ReturnsEntriesForValidFilesAndTopFoldersOnly()
|
||||
{
|
||||
var folderAssetPath = GetAssetPath("folderAsset");
|
||||
var prefabPath1 = folderAssetPath + "/testAsset1_gatherAllAssets.prefab";
|
||||
var subFolderPath = folderAssetPath + "/Subfolder";
|
||||
var prefabPath2 = subFolderPath + "/testAsset2_gatherAllAssets.prefab";
|
||||
Directory.CreateDirectory(subFolderPath);
|
||||
|
||||
var a1GUID = CreateAsset(prefabPath1, Path.GetFileNameWithoutExtension(prefabPath1));
|
||||
var a2GUID = CreateAsset(prefabPath2, Path.GetFileNameWithoutExtension(prefabPath2));
|
||||
|
||||
AssetDatabase.ImportAsset(folderAssetPath, ImportAssetOptions.ForceSynchronousImport | ImportAssetOptions.ForceUpdate);
|
||||
AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
|
||||
|
||||
var folderAssetGUID = AssetDatabase.AssetPathToGUID(folderAssetPath);
|
||||
var folderAssetEntry = Settings.CreateOrMoveEntry(folderAssetGUID, m_testGroup, false);
|
||||
|
||||
var entries = new List<AddressableAssetEntry>();
|
||||
folderAssetEntry.GatherAllAssets(entries, false, false, true);
|
||||
|
||||
// Assert
|
||||
var subFolderGUID = AssetDatabase.AssetPathToGUID(subFolderPath);
|
||||
string csvEntries = "";
|
||||
if (entries.Count != 2)
|
||||
{
|
||||
foreach (AddressableAssetEntry assetEntry in entries)
|
||||
csvEntries += assetEntry.AssetPath + ", ";
|
||||
}
|
||||
|
||||
Assert.AreEqual(2, entries.Count, $"Expected 2 (testAsset1_gatherAllAssets and testAsset2_gatherAllAssets), but was {entries.Count}: ({csvEntries})");
|
||||
Assert.IsTrue(entries.Any(e => e.guid == a1GUID));
|
||||
Assert.IsFalse(entries.Any(e => e.guid == a2GUID));
|
||||
Assert.IsTrue(entries.Any(e => e.guid == subFolderGUID));
|
||||
Assert.IsFalse(entries.Any(e => e.guid == folderAssetGUID));
|
||||
|
||||
// Cleanup
|
||||
Settings.RemoveAssetEntry(folderAssetPath);
|
||||
Directory.Delete(folderAssetPath, true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GatherAllAssets_WhenNonEmptyAddressableFolderExist_RecurseAllIsTrue_ReturnsEntriesRecursivelyForValidFilesOnly()
|
||||
{
|
||||
var folderAssetPath = GetAssetPath("folderAsset");
|
||||
var prefabPath1 = folderAssetPath + "/testAsset1_gatherAllAssets.prefab";
|
||||
var subFolderPath = folderAssetPath + "/Subfolder";
|
||||
var prefabPath2 = subFolderPath + "/testAsset2_gatherAllAssets.prefab";
|
||||
Directory.CreateDirectory(subFolderPath);
|
||||
|
||||
var a1GUID = CreateAsset(prefabPath1, Path.GetFileNameWithoutExtension(prefabPath1));
|
||||
var a2GUID = CreateAsset(prefabPath2, Path.GetFileNameWithoutExtension(prefabPath2));
|
||||
|
||||
AssetDatabase.ImportAsset(folderAssetPath, ImportAssetOptions.ForceSynchronousImport | ImportAssetOptions.ForceUpdate);
|
||||
AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
|
||||
|
||||
var folderAssetGUID = AssetDatabase.AssetPathToGUID(folderAssetPath);
|
||||
var folderAssetEntry = Settings.CreateOrMoveEntry(folderAssetGUID, m_testGroup, false);
|
||||
|
||||
var entries = new List<AddressableAssetEntry>();
|
||||
folderAssetEntry.GatherAllAssets(entries, false, true, true);
|
||||
|
||||
// Assert
|
||||
var subFolderGUID = AssetDatabase.AssetPathToGUID(subFolderPath);
|
||||
Assert.AreEqual(2, entries.Count);
|
||||
Assert.IsTrue(entries.Any(e => e.guid == a1GUID));
|
||||
Assert.IsTrue(entries.Any(e => e.guid == a2GUID));
|
||||
Assert.IsFalse(entries.Any(e => e.guid == folderAssetGUID));
|
||||
Assert.IsFalse(entries.Any(e => e.guid == subFolderGUID));
|
||||
|
||||
// Cleanup
|
||||
Settings.RemoveAssetEntry(folderAssetPath);
|
||||
Directory.Delete(folderAssetPath, true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GatherAllAssetReferenceDrawableEntries_ReturnsBuiltInScenes()
|
||||
{
|
||||
//Setup
|
||||
string scenePath = "TestScenePath";
|
||||
var savedCache = BuiltinSceneCache.scenes;
|
||||
BuiltinSceneCache.scenes = new EditorBuildSettingsScene[]
|
||||
{
|
||||
new EditorBuildSettingsScene(scenePath, true)
|
||||
};
|
||||
AddressableAssetEntry entry = Settings.CreateOrMoveEntry(AddressableAssetEntry.EditorSceneListName, m_testGroup, false);
|
||||
|
||||
//Test
|
||||
List<IReferenceEntryData> results = new List<IReferenceEntryData>();
|
||||
HashSet<string> processed = new HashSet<string>();
|
||||
m_testGroup.GatherAllDirectAssetReferenceEntryData(results, processed);
|
||||
m_testGroup.GatherAllFolderSubAssetReferenceEntryData(results, processed);
|
||||
|
||||
//Assert
|
||||
Assert.AreEqual(0, results.Count);
|
||||
|
||||
//Cleanup
|
||||
BuiltinSceneCache.scenes = savedCache;
|
||||
Settings.RemoveAssetEntry(AddressableAssetEntry.EditorSceneListName, false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GatherAllAssetReferenceDrawableEntries_DoesNotReturnResources()
|
||||
{
|
||||
//Setup
|
||||
string scenePath = "TestScenePath";
|
||||
var savedCache = BuiltinSceneCache.scenes;
|
||||
BuiltinSceneCache.scenes = new EditorBuildSettingsScene[]
|
||||
{
|
||||
new EditorBuildSettingsScene(scenePath, true)
|
||||
};
|
||||
|
||||
AddressableAssetEntry entry = Settings.CreateOrMoveEntry(AddressableAssetEntry.ResourcesName, m_testGroup, false);
|
||||
|
||||
//Test
|
||||
List<IReferenceEntryData> results = new List<IReferenceEntryData>();
|
||||
HashSet<string> processed = new HashSet<string>();
|
||||
m_testGroup.GatherAllDirectAssetReferenceEntryData(results, processed);
|
||||
m_testGroup.GatherAllFolderSubAssetReferenceEntryData(results, processed);
|
||||
|
||||
//Assert
|
||||
Assert.AreEqual(0, results.Count);
|
||||
|
||||
//Cleanup
|
||||
BuiltinSceneCache.scenes = savedCache;
|
||||
Settings.RemoveAssetEntry(AddressableAssetEntry.ResourcesName, false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GatherAllAssetReferenceDrawableEntries_ReturnsFolderSubAssets()
|
||||
{
|
||||
//Setup
|
||||
string testAssetFolder = GetAssetPath("TestFolder");
|
||||
string testAssetSubFolder = Path.Combine(testAssetFolder, "SubFolder");
|
||||
|
||||
string mainPrefabPath = Path.Combine(testAssetFolder, "mainFolder.prefab").Replace('\\', '/');
|
||||
string subPrefabPath = Path.Combine(testAssetSubFolder, "subFolder.prefab").Replace('\\', '/');
|
||||
|
||||
Directory.CreateDirectory(testAssetFolder);
|
||||
PrefabUtility.SaveAsPrefabAsset(new GameObject("mainFolderAsset"), mainPrefabPath);
|
||||
|
||||
Directory.CreateDirectory(testAssetSubFolder);
|
||||
PrefabUtility.SaveAsPrefabAsset(new GameObject("subFolderAsset"), subPrefabPath);
|
||||
|
||||
string guid = AssetDatabase.AssetPathToGUID(testAssetFolder);
|
||||
AddressableAssetEntry entry = Settings.CreateOrMoveEntry(guid, m_testGroup, false);
|
||||
|
||||
//Test
|
||||
List<IReferenceEntryData> results = new List<IReferenceEntryData>();
|
||||
m_testGroup.GatherAllFolderSubAssetReferenceEntryData(results, null);
|
||||
|
||||
//Assert
|
||||
Assert.AreEqual(2, results.Count);
|
||||
Assert.AreEqual(mainPrefabPath, results[0].AssetPath);
|
||||
Assert.AreEqual(subPrefabPath, results[1].AssetPath);
|
||||
|
||||
//Cleanup
|
||||
Directory.Delete(testAssetFolder, true);
|
||||
Settings.RemoveAssetEntry(guid, false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GatherAllAssetReferenceDrawableEntries_DoesNotReturnScenesInFolder_IfSceneIsInBuiltInScenes()
|
||||
{
|
||||
//Setup
|
||||
string testAssetFolder = GetAssetPath("TestFolder");
|
||||
string testAssetSubFolder = Path.Combine(testAssetFolder, "SubFolder");
|
||||
Directory.CreateDirectory(testAssetFolder);
|
||||
Directory.CreateDirectory(testAssetSubFolder);
|
||||
|
||||
AssetDatabase.ImportAsset(testAssetFolder);
|
||||
AssetDatabase.ImportAsset(testAssetSubFolder);
|
||||
|
||||
string mainPrefabPath = Path.Combine(testAssetFolder, "mainFolder.prefab").Replace('\\', '/');
|
||||
string subPrefabPath = Path.Combine(testAssetSubFolder, "subFolder.prefab").Replace('\\', '/');
|
||||
string scenePath = Path.Combine(testAssetFolder, "TestScenePath.unity").Replace('\\', '/');
|
||||
|
||||
var savedCache = BuiltinSceneCache.scenes;
|
||||
BuiltinSceneCache.scenes = new EditorBuildSettingsScene[]
|
||||
{
|
||||
new EditorBuildSettingsScene(scenePath, true)
|
||||
};
|
||||
|
||||
PrefabUtility.SaveAsPrefabAsset(new GameObject("mainFolderAsset"), mainPrefabPath);
|
||||
PrefabUtility.SaveAsPrefabAsset(new GameObject("subFolderAsset"), subPrefabPath);
|
||||
EditorSceneManager.SaveScene(EditorSceneManager.NewScene(NewSceneSetup.EmptyScene), scenePath);
|
||||
|
||||
string guid = AssetDatabase.AssetPathToGUID(testAssetFolder);
|
||||
AddressableAssetEntry entry = Settings.CreateOrMoveEntry(guid, m_testGroup, false);
|
||||
|
||||
//Test
|
||||
List<IReferenceEntryData> results = new List<IReferenceEntryData>();
|
||||
HashSet<string> processed = new HashSet<string>();
|
||||
m_testGroup.GatherAllDirectAssetReferenceEntryData(results, processed);
|
||||
m_testGroup.GatherAllFolderSubAssetReferenceEntryData(results, processed);
|
||||
|
||||
//Assert
|
||||
Assert.AreEqual(2, results.Count);
|
||||
Assert.AreEqual(mainPrefabPath, results[0].AssetPath);
|
||||
Assert.AreEqual(subPrefabPath, results[1].AssetPath);
|
||||
|
||||
//Cleanup
|
||||
DirectoryUtility.DeleteDirectory(testAssetFolder, false);
|
||||
BuiltinSceneCache.scenes = savedCache;
|
||||
Settings.RemoveAssetEntry(guid, false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GatherAllAssetReferenceDrawableEntries_AddsSimpleAssetEntries()
|
||||
{
|
||||
//Setup
|
||||
string guid = "12345698655";
|
||||
AddressableAssetEntry entry = Settings.CreateOrMoveEntry(guid, m_testGroup, false);
|
||||
entry.m_cachedAssetPath = "TestPath";
|
||||
|
||||
//Test
|
||||
try
|
||||
{
|
||||
List<IReferenceEntryData> results = new List<IReferenceEntryData>();
|
||||
m_testGroup.GatherAllDirectAssetReferenceEntryData(results, null);
|
||||
|
||||
//Assert
|
||||
Assert.AreEqual(1, results.Count);
|
||||
Assert.AreEqual(entry.AssetPath, results[0].AssetPath);
|
||||
}
|
||||
// cleanup
|
||||
finally
|
||||
{
|
||||
Settings.RemoveAssetEntry(guid, false);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GatherResourcesEntries_GathersAllResourceEntries_IncludingLowercase()
|
||||
{
|
||||
var resourcePath = GetAssetPath("Resources");
|
||||
string testAssetFolder = GetAssetPath("TestFolder");
|
||||
var subFolderPath = testAssetFolder + "/resources";
|
||||
|
||||
string r1GUID = null;
|
||||
string r2GUID = null;
|
||||
|
||||
try
|
||||
{
|
||||
r1GUID = CreateAsset(resourcePath + "/testResourceupper.prefab", "testResourceupper");
|
||||
r2GUID = CreateAsset(subFolderPath + "/testResourcelower.prefab", "testResourcelower");
|
||||
|
||||
var group = Settings.FindGroup(AddressableAssetSettings.PlayerDataGroupName);
|
||||
var resourceEntry = Settings.CreateOrMoveEntry(AddressableAssetEntry.ResourcesName, group, false);
|
||||
|
||||
var entries = new List<AddressableAssetEntry>();
|
||||
resourceEntry.GatherResourcesEntries(entries, true, null);
|
||||
|
||||
// Assert
|
||||
Assert.IsTrue(entries.Any(e => e.guid == r1GUID));
|
||||
Assert.IsTrue(entries.Any(e => e.guid == r2GUID));
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup
|
||||
if (!string.IsNullOrEmpty(r1GUID))
|
||||
Settings.RemoveAssetEntry(r1GUID);
|
||||
if (!string.IsNullOrEmpty(r2GUID))
|
||||
Settings.RemoveAssetEntry(r2GUID);
|
||||
if (!string.IsNullOrEmpty(AddressableAssetEntry.ResourcesName))
|
||||
Settings.RemoveAssetEntry(AddressableAssetEntry.ResourcesName);
|
||||
AssetDatabase.DeleteAsset(resourcePath);
|
||||
AssetDatabase.DeleteAsset(testAssetFolder);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetRuntimeProviderType_HandlesEmptyProviderString()
|
||||
{
|
||||
AddressableAssetEntry entry = new AddressableAssetEntry("12345698655", "Entry", null, false);
|
||||
Type providerType = entry.GetRuntimeProviderType(null, typeof(GameObject));
|
||||
Assert.IsNull(providerType);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetRuntimeProviderType_ReturnsAtlasProviderForSpriteAtlas()
|
||||
{
|
||||
AddressableAssetEntry entry = new AddressableAssetEntry("12345698655", "Entry", null, false);
|
||||
Type providerType = entry.GetRuntimeProviderType(typeof(AssetDatabaseProvider).FullName, typeof(SpriteAtlas));
|
||||
Assert.AreEqual(typeof(AtlasSpriteProvider), providerType);
|
||||
}
|
||||
|
||||
[TestCase(typeof(AssetDatabaseProvider))]
|
||||
[TestCase(typeof(JsonAssetProvider))]
|
||||
[TestCase(typeof(BundledAssetProvider))]
|
||||
[TestCase(typeof(AssetBundleProvider))]
|
||||
[TestCase(typeof(TextDataProvider))]
|
||||
public void GetRuntimeProviderType_ReturnsProviderTypeForNonAtlas(Type testProviderType)
|
||||
{
|
||||
AddressableAssetEntry entry = new AddressableAssetEntry("12345698655", "Entry", null, false);
|
||||
Type providerType = entry.GetRuntimeProviderType(testProviderType.FullName, typeof(GameObject));
|
||||
Assert.AreEqual(testProviderType, providerType);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetRuntimeProviderType_HandlesInvalidProviderString()
|
||||
{
|
||||
AddressableAssetEntry entry = new AddressableAssetEntry("12345698655", "Entry", null, false);
|
||||
Type providerType = entry.GetRuntimeProviderType("NotARealProvider", typeof(GameObject));
|
||||
Assert.IsNull(providerType);
|
||||
}
|
||||
|
||||
[TestCase(typeof(AssetDatabaseProvider))]
|
||||
[TestCase(typeof(JsonAssetProvider))]
|
||||
[TestCase(typeof(BundledAssetProvider))]
|
||||
[TestCase(typeof(AssetBundleProvider))]
|
||||
[TestCase(typeof(TextDataProvider))]
|
||||
public void GetRuntimeProviderType_HandlesNullAssetType(Type testProviderType)
|
||||
{
|
||||
AddressableAssetEntry entry = new AddressableAssetEntry("12345698655", "Entry", null, false);
|
||||
Type providerType = entry.GetRuntimeProviderType(testProviderType.FullName, null);
|
||||
Assert.AreEqual(testProviderType, providerType);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAddressHasSquareBracketsAndGuidIsNotEmptyString_CreatingNewEntry_ThrowsError()
|
||||
{
|
||||
AddressableAssetEntry entry = new AddressableAssetEntry("12345698655", "[Entry]", null, false);
|
||||
LogAssert.Expect(LogType.Error, $"Address '{entry.address}' cannot contain '[ ]'.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAddressHasSquareBracketsAndGuidIsEmptyString_CreatingNewEntry_ThrowsNothing()
|
||||
{
|
||||
Assert.DoesNotThrow(() => new AddressableAssetEntry("", "[Entry]", null, false));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAddressHasSquareBracketsAndGuidIsNotEmptyString_SettingTheAddressOnExistingEntry_ThrowsError()
|
||||
{
|
||||
AddressableAssetEntry entry = new AddressableAssetEntry("12345698655", "Entry", null, false);
|
||||
entry.SetAddress("[Entry]");
|
||||
LogAssert.Expect(LogType.Error, $"Address '{entry.address}' cannot contain '[ ]'.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAddressHasSquareBracketsAndGuidIsEmptyString_SettingTheAddressOnExistingEntry_ThrowsNothing()
|
||||
{
|
||||
AddressableAssetEntry entry = new AddressableAssetEntry("", "Entry", null, false);
|
||||
Assert.DoesNotThrow(() => entry.SetAddress("[Entry]"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenTargetAssetNotFoundInAssetDatabase_ReloadObject()
|
||||
{
|
||||
var obj = UnityEngine.AddressableAssets.Tests.TestObject.Create("test_targetAsset");
|
||||
var obj2 = UnityEngine.AddressableAssets.Tests.TestObject.Create("test_targetAsset2");
|
||||
string path = GetAssetPath("test_targetAsset.asset");
|
||||
|
||||
AssetDatabase.CreateAsset(obj, path);
|
||||
AssetDatabase.SaveAssets();
|
||||
var entry = new AddressableAssetEntry(AssetDatabase.AssetPathToGUID(path), "Entry", null, false);
|
||||
UnityEngine.Object targetAsset = entry.TargetAsset;
|
||||
|
||||
AssetDatabase.CreateAsset(obj2, path);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
Assert.IsFalse(AssetDatabase.TryGetGUIDAndLocalFileIdentifier(targetAsset, out string guid, out long localId));
|
||||
UnityEngine.Object targetAsset2 = entry.TargetAsset;
|
||||
Assert.IsTrue(AssetDatabase.TryGetGUIDAndLocalFileIdentifier(targetAsset2, out string guid2, out long localId2));
|
||||
|
||||
AssetDatabase.DeleteAsset(path);
|
||||
}
|
||||
|
||||
#pragma warning disable 0618
|
||||
[Test]
|
||||
public void CanConvertEntryCollectionToEntries()
|
||||
{
|
||||
Settings.DenyEntryCollectionPermission = true;
|
||||
var collectionPath = Path.Combine(TestFolder, "collection.asset").Replace('\\', '/');
|
||||
var collection = ScriptableObject.CreateInstance<AddressableAssetEntryCollection>();
|
||||
|
||||
var assetPath = GetAssetPath("test.prefab");
|
||||
var assetGuid = AssetDatabase.AssetPathToGUID(assetPath);
|
||||
var collectionEntry = new AddressableAssetEntry(assetGuid, "TestAssetEntry", null, false);
|
||||
collectionEntry.m_cachedAssetPath = "TestPath";
|
||||
collection.Entries.Add(collectionEntry);
|
||||
AssetDatabase.CreateAsset(collection, collectionPath);
|
||||
Settings.DenyEntryCollectionPermission = false;
|
||||
|
||||
bool converted = this.Settings.ConvertAssetEntryCollections(new List<string>() {collectionPath});
|
||||
Assert.IsTrue(converted, "Failed to convert AssetEntryCollection to standard Group Entries");
|
||||
var addedEntry = Settings.DefaultGroup.GetAssetEntry(assetGuid);
|
||||
Assert.IsNotNull(addedEntry, "Could not find entry in default Group.");
|
||||
}
|
||||
#pragma warning restore 0618
|
||||
|
||||
string CreateSpriteAtlasWithSprite()
|
||||
{
|
||||
// create a Sprite atlas, + sprite
|
||||
var spriteAtlasPath = GetAssetPath("testAtlas.spriteatlas");
|
||||
SpriteAtlas spriteAtlas = new SpriteAtlas();
|
||||
AssetDatabase.CreateAsset(spriteAtlas, spriteAtlasPath);
|
||||
|
||||
Texture2D texture = Texture2D.whiteTexture;
|
||||
byte[] data = texture.EncodeToPNG();
|
||||
var texturePath = GetAssetPath("testTexture.png");
|
||||
File.WriteAllBytes(texturePath, data);
|
||||
AssetDatabase.ImportAsset(texturePath, ImportAssetOptions.ForceSynchronousImport | ImportAssetOptions.ForceUpdate);
|
||||
|
||||
TextureImporter importer = TextureImporter.GetAtPath(texturePath) as TextureImporter;
|
||||
importer.textureType = TextureImporterType.Sprite;
|
||||
importer.spriteImportMode = SpriteImportMode.Single;
|
||||
importer.SaveAndReimport();
|
||||
|
||||
SpriteAtlasExtensions.Add(spriteAtlas, new[] {AssetDatabase.LoadAssetAtPath<Texture>(texturePath)});
|
||||
SpriteAtlasUtility.PackAtlases(new SpriteAtlas[] {spriteAtlas}, EditorUserBuildSettings.activeBuildTarget, false);
|
||||
|
||||
return spriteAtlasPath;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 38c7e0fdbf240784998304d4d11ed645
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,402 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using UnityEditor.AddressableAssets.GUI;
|
||||
using UnityEditor.AddressableAssets.Settings;
|
||||
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.AddressableAssets.Tests
|
||||
{
|
||||
class AddressableAssetEntryTreeViewTests : EditorAddressableAssetsTestFixture
|
||||
{
|
||||
const string k_TreeViewTestFolderPath = TempPath + "/TreeViewTests";
|
||||
|
||||
[SetUp]
|
||||
public void TestSetup()
|
||||
{
|
||||
Directory.CreateDirectory(k_TreeViewTestFolderPath);
|
||||
ProjectConfigData.HierarchicalSearch = false;
|
||||
ProjectConfigData.ShowGroupsAsHierarchy = false;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildTree_Structure_WhenOnlyWithDefaultGroups_CreatesBuiltInDataAndDefaultGroups()
|
||||
{
|
||||
var tree = CreateExpandedTree();
|
||||
Assert.AreEqual(2, tree.Root.children.Count);
|
||||
|
||||
var playerDataRow = tree.Root.children.First(c => c.displayName == AddressableAssetSettings.PlayerDataGroupName);
|
||||
Assert.AreEqual(2, playerDataRow.children.Count);
|
||||
Assert.IsTrue(playerDataRow.children.Any(c => c.displayName == AddressableAssetEntry.EditorSceneListName));
|
||||
Assert.IsTrue(playerDataRow.children.Any(c => c.displayName == AddressableAssetEntry.ResourcesName));
|
||||
|
||||
var defaultGroupRow = tree.Root.children.First(c => c.displayName == AddressableAssetSettings.DefaultLocalGroupName + " (Default)");
|
||||
Assert.False(defaultGroupRow.hasChildren);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildTree_Structure_WhenGroupHierarchyIsEnabled_CreatesHierarchyFromDashesInGroupName()
|
||||
{
|
||||
var nameWithDashes = "group-name-with-dashes";
|
||||
var group = CreateGroup(nameWithDashes);
|
||||
|
||||
ProjectConfigData.ShowGroupsAsHierarchy = true;
|
||||
var tree = CreateExpandedTree();
|
||||
|
||||
var parts = nameWithDashes.Split('-');
|
||||
TreeViewItem item = tree.Root;
|
||||
for (int i = 0; i < parts.Length - 1; i++)
|
||||
{
|
||||
item = item.children.FirstOrDefault(c => c.displayName == parts[i]);
|
||||
Assert.NotNull(item);
|
||||
}
|
||||
|
||||
// Last child is the complete name of the group
|
||||
Assert.NotNull(item.children.FirstOrDefault(c => c.displayName == nameWithDashes));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildTree_Scenes_CreatesAnEntryOnlyForScenesInBuild()
|
||||
{
|
||||
var scenesBU = EditorBuildSettings.scenes;
|
||||
try
|
||||
{
|
||||
EditorBuildSettings.scenes = new EditorBuildSettingsScene[0];
|
||||
var sceneGuid1 = CreateScene(k_TreeViewTestFolderPath + "/includedScene1.unity", addToBuild: true);
|
||||
var sceneGuid2 = CreateScene(k_TreeViewTestFolderPath + "/excludedScene.unity", addToBuild: false);
|
||||
|
||||
var tree = CreateExpandedTree();
|
||||
|
||||
var scenesListRow = tree.GetRows().First(c => c.displayName == AddressableAssetEntry.EditorSceneListName);
|
||||
Assert.AreEqual(1, scenesListRow.children.Count);
|
||||
Assert.True(scenesListRow.children.Any(r => r.displayName == GetName(sceneGuid1)));
|
||||
}
|
||||
finally
|
||||
{
|
||||
EditorBuildSettings.scenes = scenesBU;
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildTree_Resources_CreatesEntriesForAllFilesInResourcesFolders()
|
||||
{
|
||||
Directory.CreateDirectory(k_TreeViewTestFolderPath + "/Resources");
|
||||
Directory.CreateDirectory(k_TreeViewTestFolderPath + "/SubFolder/Resources");
|
||||
var resourceGuid1 = CreateAsset(k_TreeViewTestFolderPath + "/Resources/testResource1.prefab");
|
||||
var resourceGuid2 = CreateAsset(k_TreeViewTestFolderPath + "/SubFolder/Resources/testResource3.prefab");
|
||||
|
||||
var tree = CreateExpandedTree();
|
||||
|
||||
var resourcesRow = tree.GetRows().First(c => c.displayName == AddressableAssetEntry.ResourcesName);
|
||||
var resourcesCount = ResourcesTestUtility.GetResourcesEntryCount(m_Settings, true);
|
||||
Assert.AreEqual(resourcesCount, resourcesRow.children.Count);
|
||||
Assert.True(resourcesRow.children.Any(r => r.displayName == GetName(resourceGuid1)));
|
||||
Assert.True(resourcesRow.children.Any(r => r.displayName == GetName(resourceGuid2)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildTree_Groups_CreatesEntriesForEachOne()
|
||||
{
|
||||
CreateGroup("testGroup1");
|
||||
CreateGroup("testGroup2");
|
||||
var tree = CreateExpandedTree();
|
||||
Assert.AreEqual(4, tree.Root.children.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildTree_Assets_CreatesEntriesForAddressableAssetsOnly()
|
||||
{
|
||||
var guid1 = CreateAsset(k_TreeViewTestFolderPath + "/testAsset1.prefab");
|
||||
var guid2 = CreateAsset(k_TreeViewTestFolderPath + "/testAsset2.prefab");
|
||||
MakeAddressable(m_Settings.DefaultGroup, guid1);
|
||||
|
||||
var tree = CreateExpandedTree();
|
||||
|
||||
var defaultGroupRow = tree.Root.children.First(c => c.displayName == AddressableAssetSettings.DefaultLocalGroupName + " (Default)");
|
||||
Assert.AreEqual(1, defaultGroupRow.children.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildTree_Assets_SpriteAtlas_CreatesEntriesForAtlasAndAllSprites()
|
||||
{
|
||||
var guid1 = CreateSpriteTexture(k_TreeViewTestFolderPath + "/testTexture1.png");
|
||||
var guid2 = CreateSpriteTexture(k_TreeViewTestFolderPath + "/testTexture2.png");
|
||||
var atlasPath = k_TreeViewTestFolderPath + "/testAtlas.spriteatlas";
|
||||
MakeAddressable(m_Settings.DefaultGroup, CreateSpriteAtlas(atlasPath, new[] {guid1, guid2}));
|
||||
|
||||
var tree = CreateExpandedTree();
|
||||
|
||||
var defaultGroupRow = tree.Root.children.First(c => c.displayName == AddressableAssetSettings.DefaultLocalGroupName + " (Default)");
|
||||
Assert.AreEqual(1, defaultGroupRow.children.Count);
|
||||
var atlasRow = defaultGroupRow.children.First();
|
||||
Assert.AreEqual(2, atlasRow.children.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Search_WhenAssetNameMatches_ReturnsMatchingAssets()
|
||||
{
|
||||
var searchStr = "matchingStr";
|
||||
var entry = MakeAddressable(m_Settings.DefaultGroup, CreateAsset(k_TreeViewTestFolderPath + "/testAsset1.prefab"), "testAsset1-" + searchStr);
|
||||
MakeAddressable(m_Settings.DefaultGroup, CreateAsset(k_TreeViewTestFolderPath + "/testAsset2.prefab"));
|
||||
|
||||
var tree = CreateExpandedTree();
|
||||
ProjectConfigData.HierarchicalSearch = false;
|
||||
var result = tree.Search(searchStr);
|
||||
|
||||
Assert.AreEqual(1, result.Count);
|
||||
Assert.AreEqual(entry.address, result.First().displayName);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Search_WhenAssetFilePathMatches_ReturnsMatchingAssets()
|
||||
{
|
||||
var searchStr = "matchingStr";
|
||||
var entry = MakeAddressable(m_Settings.DefaultGroup, CreateAsset(k_TreeViewTestFolderPath + $"/testAsset1-{searchStr}.prefab"));
|
||||
MakeAddressable(m_Settings.DefaultGroup, CreateAsset(k_TreeViewTestFolderPath + "/testAsset2.prefab"));
|
||||
|
||||
var tree = CreateExpandedTree();
|
||||
ProjectConfigData.HierarchicalSearch = false;
|
||||
var result = tree.Search(searchStr);
|
||||
|
||||
Assert.AreEqual(1, result.Count);
|
||||
Assert.AreEqual(entry.address, result.First().displayName);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Search_WhenGroupMatches_ReturnsMatchingGroups()
|
||||
{
|
||||
var searchStr = "matchingStr";
|
||||
var group = CreateGroup("Group-" + searchStr);
|
||||
MakeAddressable(group, CreateAsset(k_TreeViewTestFolderPath + "/testAsset1.prefab"));
|
||||
|
||||
var tree = CreateExpandedTree();
|
||||
ProjectConfigData.HierarchicalSearch = false;
|
||||
var result = tree.Search(searchStr);
|
||||
|
||||
Assert.AreEqual(1, result.Count);
|
||||
Assert.AreEqual(group.Name, result.First().displayName);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Search_WhenLabelMatch_ReturnsMatchingAssets()
|
||||
{
|
||||
var searchStr = "matchingStr";
|
||||
MakeAddressable(m_Settings.DefaultGroup, CreateAsset(k_TreeViewTestFolderPath + "/testAsset1.prefab"));
|
||||
var entry = MakeAddressable(m_Settings.DefaultGroup, CreateAsset(k_TreeViewTestFolderPath + "/testPrefab2.prefab"));
|
||||
m_Settings.SetLabelValueForEntries(new List<AddressableAssetEntry>() {entry}, "label-" + searchStr, true, true);
|
||||
|
||||
var tree = CreateExpandedTree();
|
||||
ProjectConfigData.HierarchicalSearch = false;
|
||||
var result = tree.Search(searchStr);
|
||||
|
||||
Assert.AreEqual(1, result.Count);
|
||||
Assert.AreEqual(entry.address, result.First().displayName);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Search_Hierarchical_WhenAssetNameMatches_ReturnsMatchingAssetsAndContainingGroups()
|
||||
{
|
||||
var searchStr = "matchingStr";
|
||||
var entry = MakeAddressable(m_Settings.DefaultGroup, CreateAsset(k_TreeViewTestFolderPath + "/testAsset1.prefab"), "testAsset1-" + searchStr);
|
||||
MakeAddressable(m_Settings.DefaultGroup, CreateAsset(k_TreeViewTestFolderPath + "/testAsset2.prefab"));
|
||||
|
||||
ProjectConfigData.HierarchicalSearch = true;
|
||||
var tree = CreateExpandedTree();
|
||||
var result = tree.Search(searchStr);
|
||||
|
||||
Assert.AreEqual(2, result.Count);
|
||||
Assert.NotNull(result.FirstOrDefault(r => r.displayName == m_Settings.DefaultGroup.Name + " (Default)"));
|
||||
Assert.NotNull(result.FirstOrDefault(r => r.displayName == entry.address));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Search_Hierarchical_WhenAssetFilePathMatches_ReturnsMatchingAssetsAndContainingGroups()
|
||||
{
|
||||
var searchStr = "matchingStr";
|
||||
var entry = MakeAddressable(m_Settings.DefaultGroup, CreateAsset(k_TreeViewTestFolderPath + $"/testAsset1-{searchStr}.prefab"));
|
||||
MakeAddressable(m_Settings.DefaultGroup, CreateAsset(k_TreeViewTestFolderPath + "/testAsset2.prefab"));
|
||||
|
||||
ProjectConfigData.HierarchicalSearch = true;
|
||||
var tree = CreateExpandedTree();
|
||||
var result = tree.Search(searchStr);
|
||||
|
||||
Assert.AreEqual(2, result.Count);
|
||||
Assert.NotNull(result.FirstOrDefault(r => r.displayName == m_Settings.DefaultGroup.Name + " (Default)"));
|
||||
Assert.NotNull(result.FirstOrDefault(r => r.displayName == entry.address));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Search_Hierarchical_WhenGroupMatches_ReturnsGroupAndItsAssets()
|
||||
{
|
||||
var searchStr = "matchingStr";
|
||||
var groupName = "Group-" + searchStr;
|
||||
var group = CreateGroup(groupName);
|
||||
MakeAddressable(group, CreateAsset(k_TreeViewTestFolderPath + "/testAsset1.prefab"));
|
||||
MakeAddressable(group, CreateAsset(k_TreeViewTestFolderPath + "/testAsset2.prefab"));
|
||||
|
||||
ProjectConfigData.HierarchicalSearch = true;
|
||||
var tree = CreateExpandedTree();
|
||||
var result = tree.Search(searchStr);
|
||||
|
||||
Assert.AreEqual(3, result.Count);
|
||||
Assert.NotNull(result.FirstOrDefault(r => r.displayName == groupName));
|
||||
foreach (var entry in group.entries)
|
||||
Assert.NotNull(result.FirstOrDefault(r => r.displayName == entry.address));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Search_Hierarchical_WhenLabelMatches_ReturnsMatchingAssetsAndContainingGroups()
|
||||
{
|
||||
var searchStr = "matchingStr";
|
||||
MakeAddressable(m_Settings.DefaultGroup, CreateAsset(k_TreeViewTestFolderPath + "/testAsset1.prefab"));
|
||||
var entry = MakeAddressable(m_Settings.DefaultGroup, CreateAsset(k_TreeViewTestFolderPath + "/testPrefab2.prefab"));
|
||||
m_Settings.SetLabelValueForEntries(new List<AddressableAssetEntry>() {entry}, "label-" + searchStr, true, true);
|
||||
|
||||
ProjectConfigData.HierarchicalSearch = true;
|
||||
var tree = CreateExpandedTree();
|
||||
var result = tree.Search(searchStr);
|
||||
|
||||
Assert.AreEqual(2, result.Count);
|
||||
Assert.NotNull(result.FirstOrDefault(r => r.displayName == m_Settings.DefaultGroup.Name + " (Default)"));
|
||||
Assert.NotNull(result.FirstOrDefault(r => r.displayName == entry.address));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Search_Hierarchical_WithGroupHierarchyEnabled_WhenAssetFilePathMatches_ReturnsMatchingAssetsAndHierarchy()
|
||||
{
|
||||
var nameWithDashes = "group-name-with-dashes";
|
||||
var searchStr = "matchingStr";
|
||||
var group = CreateGroup(nameWithDashes);
|
||||
var entry = MakeAddressable(group, CreateAsset(k_TreeViewTestFolderPath + "/testAsset1.prefab"), searchStr);
|
||||
MakeAddressable(group, CreateAsset(k_TreeViewTestFolderPath + "/testPrefab2.prefab"));
|
||||
|
||||
ProjectConfigData.HierarchicalSearch = true;
|
||||
ProjectConfigData.ShowGroupsAsHierarchy = true;
|
||||
var tree = CreateExpandedTree();
|
||||
var result = tree.Search(searchStr);
|
||||
|
||||
var parts = nameWithDashes.Split('-');
|
||||
Assert.AreEqual(parts.Length + 1, result.Count);
|
||||
Assert.NotNull(result.FirstOrDefault(c => c.displayName == entry.address));
|
||||
for (int i = 0; i < parts.Length - 1; i++)
|
||||
{
|
||||
Assert.NotNull(result.FirstOrDefault(c => c.displayName == parts[i]));
|
||||
}
|
||||
|
||||
// Last child is the full name of the group
|
||||
Assert.NotNull(result.FirstOrDefault(c => c.displayName == nameWithDashes));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CopyAddressesToClipboard_Simple()
|
||||
{
|
||||
List<AssetEntryTreeViewItem> nodesToSelect = new List<AssetEntryTreeViewItem>();
|
||||
|
||||
AddressableAssetEntry entry1 = new AddressableAssetEntry("0001", "address1", null, false);
|
||||
|
||||
nodesToSelect.Add(new AssetEntryTreeViewItem(entry1, 0));
|
||||
|
||||
//Save users previous clipboard so it doesn't get eaten during test
|
||||
string previousClipboard = GUIUtility.systemCopyBuffer;
|
||||
|
||||
AddressableAssetEntryTreeView.CopyAddressesToClipboard(nodesToSelect);
|
||||
|
||||
string result = GUIUtility.systemCopyBuffer;
|
||||
GUIUtility.systemCopyBuffer = previousClipboard;
|
||||
|
||||
Assert.AreEqual("address1", result, "Entry's address was incorrectly copied.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CopyAddressesToClipboard_Multiple()
|
||||
{
|
||||
List<AssetEntryTreeViewItem> nodesToSelect = new List<AssetEntryTreeViewItem>();
|
||||
|
||||
AddressableAssetEntry entry1 = new AddressableAssetEntry("0001", "address1", null, false);
|
||||
AddressableAssetEntry entry2 = new AddressableAssetEntry("0002", "address2", null, false);
|
||||
AddressableAssetEntry entry3 = new AddressableAssetEntry("0003", "address3", null, false);
|
||||
|
||||
nodesToSelect.Add(new AssetEntryTreeViewItem(entry1, 0));
|
||||
nodesToSelect.Add(new AssetEntryTreeViewItem(entry2, 0));
|
||||
nodesToSelect.Add(new AssetEntryTreeViewItem(entry3, 0));
|
||||
|
||||
//Save users previous clipboard so it doesn't get eaten during test
|
||||
string previousClipboard = GUIUtility.systemCopyBuffer;
|
||||
|
||||
AddressableAssetEntryTreeView.CopyAddressesToClipboard(nodesToSelect);
|
||||
|
||||
string result = GUIUtility.systemCopyBuffer;
|
||||
GUIUtility.systemCopyBuffer = previousClipboard;
|
||||
|
||||
Assert.AreEqual("address1,address2,address3", result, "Entry's address was incorrectly copied.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CopyAddressesToClipboard_MaintainsOrder()
|
||||
{
|
||||
List<AssetEntryTreeViewItem> nodesToSelect = new List<AssetEntryTreeViewItem>();
|
||||
|
||||
AddressableAssetEntry entry1 = new AddressableAssetEntry("0001", "address1", null, false);
|
||||
AddressableAssetEntry entry2 = new AddressableAssetEntry("0002", "address2", null, false);
|
||||
AddressableAssetEntry entry3 = new AddressableAssetEntry("0003", "address3", null, false);
|
||||
|
||||
nodesToSelect.Add(new AssetEntryTreeViewItem(entry2, 0));
|
||||
nodesToSelect.Add(new AssetEntryTreeViewItem(entry3, 0));
|
||||
nodesToSelect.Add(new AssetEntryTreeViewItem(entry1, 0));
|
||||
|
||||
//Save users previous clipboard so it doesn't get eaten during test
|
||||
string previousClipboard = GUIUtility.systemCopyBuffer;
|
||||
|
||||
AddressableAssetEntryTreeView.CopyAddressesToClipboard(nodesToSelect);
|
||||
|
||||
string result = GUIUtility.systemCopyBuffer;
|
||||
GUIUtility.systemCopyBuffer = previousClipboard;
|
||||
|
||||
Assert.AreEqual("address2,address3,address1", result, "Entry's address was incorrectly copied.");
|
||||
}
|
||||
|
||||
|
||||
List<AddressableAssetEntry> GetAllEntries(bool includeSubObjects = false)
|
||||
{
|
||||
var entries = new List<AddressableAssetEntry>();
|
||||
m_Settings.GetAllAssets(entries, includeSubObjects);
|
||||
return entries;
|
||||
}
|
||||
|
||||
AddressableAssetEntryTreeView CreateExpandedTree()
|
||||
{
|
||||
var tree = new AddressableAssetEntryTreeView(m_Settings);
|
||||
tree.Reload();
|
||||
var count = tree.GetRows().Count;
|
||||
tree.ExpandAll();
|
||||
while (count != tree.GetRows().Count)
|
||||
{
|
||||
tree.Reload();
|
||||
count = tree.GetRows().Count;
|
||||
tree.ExpandAll();
|
||||
}
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
AddressableAssetEntry MakeAddressable(AddressableAssetGroup group, string guid, string address = null)
|
||||
{
|
||||
AddressableAssetEntry entry = m_Settings.CreateOrMoveEntry(guid, group, false, false);
|
||||
entry.address = address == null ? Path.GetFileNameWithoutExtension(entry.AssetPath) : address;
|
||||
return entry;
|
||||
}
|
||||
|
||||
AddressableAssetGroup CreateGroup(string name)
|
||||
{
|
||||
return m_Settings.CreateGroup(name, false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
}
|
||||
|
||||
string GetName(string assetGuid)
|
||||
{
|
||||
return Path.GetFileNameWithoutExtension(AssetDatabase.GUIDToAssetPath(assetGuid));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 06afb4c0c7e547af92b449eb353c0cb8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,271 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using UnityEditor.AddressableAssets.Build;
|
||||
using UnityEditor.AddressableAssets.Settings;
|
||||
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
|
||||
using UnityEngine;
|
||||
using static UnityEditor.AddressableAssets.Settings.AddressablesFileEnumeration;
|
||||
|
||||
namespace UnityEditor.AddressableAssets.Tests
|
||||
{
|
||||
public class AddressableAssetFolderSubfolderTests : AddressableAssetTestBase
|
||||
{
|
||||
string m_TestFolderPath;
|
||||
|
||||
string m_AddrParentFolderPath;
|
||||
string m_AddrChildSubfolderPath;
|
||||
|
||||
string m_ParentObjPath;
|
||||
string m_AddrParentObjPath;
|
||||
string m_ChildObjPath;
|
||||
|
||||
AddressableAssetGroup m_ParentGroup;
|
||||
AddressableAssetGroup m_ChildGroup;
|
||||
|
||||
/* Creates the following folder structure
|
||||
* /AddrParentFolder/
|
||||
* parentObj.prefab
|
||||
* addrParentObj.prefab
|
||||
* /AddrChildSubfolder/
|
||||
* childObj.prefab
|
||||
*/
|
||||
protected override void OnInit()
|
||||
{
|
||||
// Create directories
|
||||
m_TestFolderPath = TestFolder;
|
||||
m_AddrParentFolderPath = m_TestFolderPath + "/AddrParentFolder";
|
||||
m_AddrChildSubfolderPath = m_AddrParentFolderPath + "/AddrChildSubfolder";
|
||||
|
||||
string addrParentFolderGuid = AssetDatabase.CreateFolder(m_TestFolderPath, "AddrParentFolder");
|
||||
string addrChildFolderGuid = AssetDatabase.CreateFolder(m_AddrParentFolderPath, "AddrChildSubfolder");
|
||||
|
||||
// Create prefabs
|
||||
GameObject parentObj = new GameObject("ParentObject");
|
||||
GameObject addrParentObj = new GameObject("AddrParentObject");
|
||||
GameObject childObj = new GameObject("ChildObject");
|
||||
|
||||
m_ParentObjPath = m_AddrParentFolderPath + "/parentObj.prefab";
|
||||
m_AddrParentObjPath = m_AddrParentFolderPath + "/addrParentObj.prefab";
|
||||
m_ChildObjPath = m_AddrChildSubfolderPath + "/childObj.prefab";
|
||||
|
||||
PrefabUtility.SaveAsPrefabAsset(parentObj, m_ParentObjPath);
|
||||
PrefabUtility.SaveAsPrefabAsset(addrParentObj, m_AddrParentObjPath);
|
||||
PrefabUtility.SaveAsPrefabAsset(childObj, m_ChildObjPath);
|
||||
|
||||
// Create groups
|
||||
const string parentGroupName = "ParentGroup";
|
||||
const string childGroupName = "ChildGroup";
|
||||
|
||||
m_ParentGroup = Settings.CreateGroup(parentGroupName, false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
m_ChildGroup = Settings.CreateGroup(childGroupName, false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
|
||||
// Create entries
|
||||
Settings.CreateOrMoveEntry(addrParentFolderGuid, m_ParentGroup);
|
||||
|
||||
Settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(m_AddrParentObjPath), m_ChildGroup);
|
||||
Settings.CreateOrMoveEntry(addrChildFolderGuid, m_ChildGroup);
|
||||
}
|
||||
|
||||
protected override void OnCleanup()
|
||||
{
|
||||
Settings.RemoveGroup(m_ParentGroup);
|
||||
Settings.RemoveGroup(m_ChildGroup);
|
||||
|
||||
AssetDatabase.DeleteAsset(m_TestFolderPath + "/");
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
List<string> GetValidAssetPaths(string path, AddressableAssetSettings settings)
|
||||
{
|
||||
List<string> pathsWithCache;
|
||||
using (var cache = new AddressablesFileEnumerationCache(settings, true, null))
|
||||
{
|
||||
pathsWithCache = EnumerateAddressableFolder(path, settings, true).ToList<string>();
|
||||
}
|
||||
|
||||
List<string> pathsWithoutCache = EnumerateAddressableFolder(path, settings, true).ToList<string>();
|
||||
|
||||
// Compare the results of two different code paths: with cache and without cache
|
||||
Assert.AreEqual(pathsWithCache.Count, pathsWithoutCache.Count);
|
||||
for (int i = 0; i < pathsWithCache.Count; i++)
|
||||
{
|
||||
Assert.AreEqual(pathsWithCache[i], pathsWithoutCache[i]);
|
||||
}
|
||||
|
||||
return pathsWithCache;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Build_WithAddrParentFolderAndAddrSubfolders_InSeparateGroups_Succeeds()
|
||||
{
|
||||
var context = new AddressablesDataBuilderInput(Settings);
|
||||
foreach (IDataBuilder db in Settings.DataBuilders)
|
||||
{
|
||||
if (db.CanBuildData<AddressablesPlayerBuildResult>())
|
||||
db.BuildData<AddressablesPlayerBuildResult>(context);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenSubfolderIsAddr_AddrParentFolder_DoesNotInclude_SubfolderContents()
|
||||
{
|
||||
List<string> assetPaths = GetValidAssetPaths(m_AddrParentFolderPath, Settings);
|
||||
Assert.IsFalse(assetPaths.Contains(m_ChildObjPath));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAssetIsAddr_AssetIsNotIncludedInParentAddrFolder()
|
||||
{
|
||||
List<string> assetPaths = GetValidAssetPaths(m_AddrParentFolderPath, Settings);
|
||||
Assert.IsFalse(assetPaths.Contains(m_AddrParentObjPath));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EnumerateFiles_ReturnsFilesOnly()
|
||||
{
|
||||
List<string> assetPaths = EnumerateAddressableFolder(m_AddrParentFolderPath, Settings, true);
|
||||
foreach (string path in assetPaths)
|
||||
{
|
||||
Assert.IsFalse(Directory.Exists(path));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenEmptyFolderIsAddr_EnumerateFiles_ReturnsNothing()
|
||||
{
|
||||
string path = m_TestFolderPath + "/AddrEmptyFolder";
|
||||
string guid = AssetDatabase.CreateFolder(m_TestFolderPath, "AddrEmptyFolder");
|
||||
Settings.CreateOrMoveEntry(guid, m_ParentGroup);
|
||||
|
||||
List<string> assetPaths = EnumerateAddressableFolder(path, Settings, true);
|
||||
Assert.AreEqual(0, assetPaths.Count);
|
||||
|
||||
Settings.RemoveAssetEntry(guid);
|
||||
AssetDatabase.DeleteAsset(path);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenEnumerateFilesIsNonRecursive_ReturnTopLevelAssetsOnly()
|
||||
{
|
||||
string path = m_AddrParentFolderPath + "/ChildFolder";
|
||||
string guid = AssetDatabase.CreateFolder(m_AddrParentFolderPath, "ChildFolder");
|
||||
|
||||
GameObject obj = new GameObject("TestObject");
|
||||
string objPath = path + "/childObj.prefab";
|
||||
|
||||
PrefabUtility.SaveAsPrefabAsset(obj, objPath);
|
||||
|
||||
List<string> assetPaths = EnumerateAddressableFolder(m_AddrParentFolderPath, Settings, false);
|
||||
Assert.AreEqual(1, assetPaths.Count);
|
||||
Assert.AreEqual(m_ParentObjPath, assetPaths[0]);
|
||||
|
||||
AssetDatabase.DeleteAsset(path);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenPathDoesNotExist_EnumerateFiles_ThrowsException()
|
||||
{
|
||||
string path = "PathDoesntExist";
|
||||
Exception ex = Assert.Throws<Exception>(() => { EnumerateAddressableFolder(path, Settings, false); });
|
||||
Assert.AreEqual($"Path {path} cannot be enumerated because it does not exist", ex.Message);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenPathIsNotInTree_EnumerateFiles_ReturnsFiles()
|
||||
{
|
||||
string path = m_AddrParentFolderPath + "/ChildFolder";
|
||||
string guid = AssetDatabase.CreateFolder(m_AddrParentFolderPath, "ChildFolder");
|
||||
|
||||
GameObject obj = new GameObject("TestObject");
|
||||
string objPath = path + "/childObj.prefab";
|
||||
PrefabUtility.SaveAsPrefabAsset(obj, objPath);
|
||||
List<string> assetPaths = EnumerateAddressableFolder(path, Settings, true);
|
||||
Assert.AreEqual(1, assetPaths.Count);
|
||||
Assert.AreEqual(objPath, assetPaths[0]);
|
||||
|
||||
AssetDatabase.DeleteAsset(path);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenFileIsNotInAssetDatabase_EnumerateFiles_DoesNotReturnPath()
|
||||
{
|
||||
string folderPath = m_TestFolderPath + "/TestFolder";
|
||||
AssetDatabase.CreateFolder(m_TestFolderPath, "TestFolder");
|
||||
string filePath = Path.Combine(folderPath, ".hiddenfile");
|
||||
File.Create(filePath).Close();
|
||||
|
||||
List<string> assetPaths = EnumerateAddressableFolder(folderPath, Settings, true);
|
||||
Assert.AreEqual(0, assetPaths.Count);
|
||||
|
||||
File.Delete(filePath);
|
||||
AssetDatabase.DeleteAsset(folderPath);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenNoFolderIsAddressable_EnumerateFiles_ReturnsNothing()
|
||||
{
|
||||
string parentFolderGuid = AssetDatabase.AssetPathToGUID(m_AddrParentFolderPath);
|
||||
string childFolderGuid = AssetDatabase.AssetPathToGUID(m_AddrChildSubfolderPath);
|
||||
Settings.RemoveAssetEntry(parentFolderGuid);
|
||||
Settings.RemoveAssetEntry(childFolderGuid);
|
||||
|
||||
using (var cache = new AddressablesFileEnumerationCache(Settings, true, null))
|
||||
{
|
||||
List<string> assetPaths = EnumerateAddressableFolder(m_TestFolderPath, Settings, false);
|
||||
Assert.AreEqual(0, assetPaths.Count);
|
||||
}
|
||||
|
||||
Settings.CreateOrMoveEntry(parentFolderGuid, m_ParentGroup);
|
||||
Settings.CreateOrMoveEntry(childFolderGuid, m_ChildGroup);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAFolderIsAddressable_FileEnumerationCache_CreatesFileTree()
|
||||
{
|
||||
using (var cache = new AddressablesFileEnumerationCache(Settings, false, null))
|
||||
{
|
||||
Assert.IsTrue(m_PrecomputedTree != null);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenNoFolderIsAddressable_FileEnumerationCache_DoesNotCreateFileTree()
|
||||
{
|
||||
string parentFolderGuid = AssetDatabase.AssetPathToGUID(m_AddrParentFolderPath);
|
||||
string childFolderGuid = AssetDatabase.AssetPathToGUID(m_AddrChildSubfolderPath);
|
||||
Settings.RemoveAssetEntry(parentFolderGuid);
|
||||
Settings.RemoveAssetEntry(childFolderGuid);
|
||||
|
||||
using (var cache = new AddressablesFileEnumerationCache(Settings, true, null))
|
||||
{
|
||||
Assert.IsTrue(m_PrecomputedTree == null);
|
||||
}
|
||||
|
||||
Settings.CreateOrMoveEntry(parentFolderGuid, m_ParentGroup);
|
||||
Settings.CreateOrMoveEntry(childFolderGuid, m_ChildGroup);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenPrepopulateAssetsIsTrue_FileEnumerationCache_AddsAllAssetsToTree()
|
||||
{
|
||||
using (var cache = new AddressablesFileEnumerationCache(Settings, true, null))
|
||||
{
|
||||
AddressableAssetTree.TreeNode node = m_PrecomputedTree.FindNode(m_ChildObjPath, false);
|
||||
Assert.IsTrue(node != null);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenPrepopulateAssetsIsFalse_FileEnumerationCache_OnlyAddsAddressablesToTree()
|
||||
{
|
||||
using (var cache = new AddressablesFileEnumerationCache(Settings, false, null))
|
||||
{
|
||||
AddressableAssetTree.TreeNode node = m_PrecomputedTree.FindNode(m_ChildObjPath, false);
|
||||
Assert.IsTrue(node == null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 392da734bbda8ef48a14423bb399280e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,269 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using UnityEditor.AddressableAssets.Settings;
|
||||
using UnityEditor.U2D;
|
||||
using UnityEngine.U2D;
|
||||
|
||||
namespace UnityEditor.AddressableAssets.Tests
|
||||
{
|
||||
public class AddressableAssetReferenceTests : AddressableAssetTestBase
|
||||
{
|
||||
private string m_ScriptableObjectPath;
|
||||
private string m_SpriteAtlasPath;
|
||||
private string m_TexturePath;
|
||||
TestObject mainSO;
|
||||
TestSubObject subSO;
|
||||
TestSubObject subSO2;
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
mainSO = ScriptableObject.CreateInstance<TestObject>();
|
||||
subSO = ScriptableObject.CreateInstance<TestSubObject>();
|
||||
subSO2 = ScriptableObject.CreateInstance<TestSubObject>();
|
||||
subSO.name = "sub";
|
||||
|
||||
m_ScriptableObjectPath = GetAssetPath("testScriptableObject.asset");
|
||||
AssetDatabase.CreateAsset(mainSO, m_ScriptableObjectPath);
|
||||
AssetDatabase.AddObjectToAsset(subSO, m_ScriptableObjectPath);
|
||||
AssetDatabase.AddObjectToAsset(subSO2, m_ScriptableObjectPath);
|
||||
AssetDatabase.ImportAsset(m_ScriptableObjectPath, ImportAssetOptions.ForceSynchronousImport | ImportAssetOptions.ForceUpdate);
|
||||
|
||||
// create a Sprite atlas, + sprite
|
||||
m_SpriteAtlasPath = GetAssetPath("testAtlas.spriteatlas");
|
||||
SpriteAtlas spriteAtlas = new SpriteAtlas();
|
||||
AssetDatabase.CreateAsset(spriteAtlas, m_SpriteAtlasPath);
|
||||
|
||||
Texture2D texture = Texture2D.whiteTexture;
|
||||
byte[] data = texture.EncodeToPNG();
|
||||
m_TexturePath = GetAssetPath("testTexture.png");
|
||||
File.WriteAllBytes(m_TexturePath, data);
|
||||
AssetDatabase.ImportAsset(m_TexturePath, ImportAssetOptions.ForceSynchronousImport | ImportAssetOptions.ForceUpdate);
|
||||
|
||||
TextureImporter importer = TextureImporter.GetAtPath(m_TexturePath) as TextureImporter;
|
||||
importer.textureType = TextureImporterType.Sprite;
|
||||
importer.spriteImportMode = SpriteImportMode.Single;
|
||||
importer.SaveAndReimport();
|
||||
|
||||
SpriteAtlasExtensions.Add(spriteAtlas, new[] {AssetDatabase.LoadAssetAtPath<Texture>(m_TexturePath)});
|
||||
SpriteAtlasUtility.PackAtlases(new SpriteAtlas[] {spriteAtlas}, EditorUserBuildSettings.activeBuildTarget, false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VerifySetEditorAsset_DoesNotMakeRefAssetDirty()
|
||||
{
|
||||
//Setup
|
||||
AssetReference reference = new AssetReference();
|
||||
string path = AssetDatabase.GUIDToAssetPath(m_AssetGUID.ToString());
|
||||
GameObject o = AssetDatabase.LoadAssetAtPath(path, typeof(GameObject)) as GameObject;
|
||||
|
||||
//Test
|
||||
Assert.IsFalse(EditorUtility.IsDirty(reference.editorAsset)); // IsDirty(Object o) only available in 2019.1 or newer
|
||||
reference.SetEditorAsset(o);
|
||||
Assert.IsFalse(EditorUtility.IsDirty(reference.editorAsset));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AssetReference_SetMainAsset_ResetsSubAsset()
|
||||
{
|
||||
var guid = AssetDatabase.AssetPathToGUID(m_ScriptableObjectPath);
|
||||
AssetReference typeReference = new AssetReference(guid);
|
||||
typeReference.SubObjectName = "sub";
|
||||
typeReference.SetEditorAsset(AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(AssetDatabase.GUIDToAssetPath(m_AssetGUID.ToString())));
|
||||
Assert.IsNull(typeReference.SubObjectName);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AssetReference_SetEditorAsset_NullsOnAttemptWithWrongTypeFromDerivedType()
|
||||
{
|
||||
var guid = AssetDatabase.AssetPathToGUID(m_ScriptableObjectPath);
|
||||
AssetReference typeConflictReference = new AssetReferenceT<Animation>("badguid");
|
||||
typeConflictReference.SetEditorAsset(mainSO);
|
||||
Assert.IsNull(typeConflictReference.editorAsset, "Attempting to set editor asset on an AssetReferenceT should return null if the types do not match.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AssetReference_SetEditorAsset_SucceedsOnMatchedTypeAssetReference()
|
||||
{
|
||||
AssetReference typeCorrectReference = new AssetReferenceT<TestSubObject>("badguid");
|
||||
typeCorrectReference.SetEditorAsset(subSO);
|
||||
Assert.NotNull(typeCorrectReference.editorAsset, "Attempting to set editor asset on an AssetReferenceT should return the first matching object at the guid");
|
||||
Assert.AreEqual(subSO, typeCorrectReference.editorAsset, "Attempting to set editor asset on an AssetReferenceT should return the first matching object at the guid");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AssetReference_SetEditorAsset_GetsRequestedAssetTypeOnUntypedAssetReference()
|
||||
{
|
||||
AssetReference untypedAssetReference = new AssetReference("badguid");
|
||||
untypedAssetReference.SetEditorAsset(mainSO);
|
||||
Assert.AreEqual(mainSO, untypedAssetReference.editorAsset, "Attempting to set editor asset on an untyped AssetReference should return the requested object");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AssetReference_SetEditorAsset_CorrectlyRetrievesSubAsset()
|
||||
{
|
||||
AssetReference untypedAssetReference = new AssetReference("badguid");
|
||||
untypedAssetReference.SetEditorAsset(subSO);
|
||||
Assert.AreEqual(mainSO, untypedAssetReference.editorAsset, "Attempting to use SetEditorAsset on untyped AssetReference should give main asset as editorAsset, subAsset as subAsset");
|
||||
Assert.AreEqual(subSO.name, untypedAssetReference.SubObjectName,
|
||||
"Attempting to use SetEditorAsset on a subObject in an untyped AssetReference should make the requested asset the subasset of the assetReference.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AssetReference_SetEditorAsset_CorrectlySetsSubAssetWhenUsingTypedReference()
|
||||
{
|
||||
AssetReferenceT<TestSubObject> typedAssetReference = new AssetReferenceT<TestSubObject>("badguid");
|
||||
typedAssetReference.SetEditorAsset(subSO);
|
||||
Assert.AreEqual(subSO, typedAssetReference.editorAsset, "When using a typed asset reference, the editor asset should be set to the requested object even if its a subobject.");
|
||||
AssetReference typedAssetReference2 = new AssetReferenceT<TestSubObject>("badguid");
|
||||
typedAssetReference2.SetEditorAsset(subSO);
|
||||
Assert.AreEqual(subSO, typedAssetReference2.editorAsset, "When using a typed asset reference, the editor asset should be set to the requested object even if its a subobject.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AssetReference_SetEditorAsset_ReturnsNullIfObjectTypeIsIncorrect()
|
||||
{
|
||||
AssetReferenceT<Sprite> incorrectlyTypedAssetReference = new AssetReferenceT<Sprite>("badguid");
|
||||
incorrectlyTypedAssetReference.SetEditorAsset(subSO);
|
||||
Assert.IsNull(incorrectlyTypedAssetReference.editorAsset, "Attempting to set an editor asset of an incorrect type should return null.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AssetReference_SetEditorAsset_ReturnsCorrectObjectIfMultipleOfSameTypeExist()
|
||||
{
|
||||
AssetReferenceT<TestSubObject> typedAssetReference = new AssetReferenceT<TestSubObject>("badguid");
|
||||
typedAssetReference.SetEditorAsset(subSO2);
|
||||
Assert.AreEqual(subSO2, typedAssetReference.editorAsset, "When using a typed asset reference, the editor asset should be set to the requested object even if its a subobject.");
|
||||
Assert.AreNotEqual(subSO, typedAssetReference.editorAsset,
|
||||
"When using a typed asset reference, the editor asset should be set to specifically the requested object, not just an object with the same type and guid.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AssetReferenceSprite_SetEditorAsset_CorrectlySetsSprite()
|
||||
{
|
||||
AssetReferenceSprite spriteAssetReference = new AssetReferenceSprite("badguid");
|
||||
var sprite = AssetDatabase.LoadAssetAtPath(m_TexturePath, typeof(Sprite));
|
||||
spriteAssetReference.SetEditorAsset(sprite);
|
||||
Assert.AreEqual(sprite, spriteAssetReference.editorAsset, "When using an AssetReferenceSprite, the editor asset can be set to a Sprite or a SpriteAtlas.");
|
||||
|
||||
spriteAssetReference.CachedAsset = null;
|
||||
Assert.AreEqual(sprite, ((AssetReference)spriteAssetReference).editorAsset,
|
||||
"When an AssetReferenceSprite has its editor asset set to a Sprite, the base class editor asset accessor should be a Sprite.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AssetReferenceSprite_SetEditorAsset_CorrectlySetsAtlas()
|
||||
{
|
||||
AssetReferenceSprite spriteAssetReference = new AssetReferenceSprite("badguid");
|
||||
var atlas = AssetDatabase.LoadAssetAtPath(m_SpriteAtlasPath, typeof(SpriteAtlas));
|
||||
spriteAssetReference.SetEditorAsset(atlas);
|
||||
Assert.AreEqual(atlas, spriteAssetReference.editorAsset, "When using an AssetReferenceSprite, the editor asset can be set to a Sprite or a SpriteAtlas.");
|
||||
|
||||
spriteAssetReference.CachedAsset = null;
|
||||
Assert.AreEqual(atlas, ((AssetReference)spriteAssetReference).editorAsset,
|
||||
"When an AssetReferenceSprite has its editor asset set to a SpriteAtlas, the base class editor asset accessor should be a SpriteAtlas.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AssetReferenceAtlasedSprite_SetEditorAsset_CorrectlySetsAtlas()
|
||||
{
|
||||
AssetReferenceAtlasedSprite atlasedSpriteAssetReference = new AssetReferenceAtlasedSprite("badguid");
|
||||
var atlas = AssetDatabase.LoadAssetAtPath(m_SpriteAtlasPath, typeof(SpriteAtlas));
|
||||
atlasedSpriteAssetReference.SetEditorAsset(atlas);
|
||||
Assert.AreEqual(atlas, atlasedSpriteAssetReference.editorAsset, "When using an AssetReferenceAtlasedSprite, the editor asset can only be set to a SpriteAtlas.");
|
||||
|
||||
atlasedSpriteAssetReference.CachedAsset = null;
|
||||
Assert.AreEqual(atlas, ((AssetReference)atlasedSpriteAssetReference).editorAsset,
|
||||
"When an AssetReferenceSprite has its editor asset set to a SpriteAtlas, the base class editor asset accessor should be a SpriteAtlas.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AssetReferenceEditorAssetForSubObject_DifferentType()
|
||||
{
|
||||
var guid = AssetDatabase.AssetPathToGUID(m_ScriptableObjectPath);
|
||||
AssetReferenceT<TestSubObject> typeReference = new AssetReferenceT<TestSubObject>(guid);
|
||||
typeReference.SubObjectName = "sub";
|
||||
|
||||
//Test
|
||||
Assert.AreEqual(typeReference.editorAsset, AssetDatabase.LoadAssetAtPath<TestSubObject>(m_ScriptableObjectPath),
|
||||
"AssetReference with explicit type should get first instance of that type at that guid.");
|
||||
AssetReference asBase = typeReference;
|
||||
Assert.IsNotNull(asBase.editorAsset);
|
||||
Assert.AreEqual(asBase.editorAsset, AssetDatabase.LoadAssetAtPath<TestSubObject>(m_ScriptableObjectPath),
|
||||
"AssetReference with explicit type declared under generic AssetReference should still get the first instance of the specific type at the guid.");
|
||||
AssetReference baseReference = new AssetReference(guid);
|
||||
Assert.AreEqual(baseReference.editorAsset, AssetDatabase.LoadAssetAtPath<TestObject>(m_ScriptableObjectPath), "Generic AssetReference should get the asset of the main type at the guid.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AssetReferenceEditorAssetForSubObject_NullIfIncorrectType()
|
||||
{
|
||||
var guid = AssetDatabase.AssetPathToGUID(m_ScriptableObjectPath);
|
||||
AssetReferenceT<Animation> typeReference = new AssetReferenceT<Animation>(guid);
|
||||
typeReference.SubObjectName = "sub";
|
||||
|
||||
//Test
|
||||
Assert.IsNull(typeReference.editorAsset, "Attempting to get an object of a type not located at a guid should return a null value.");
|
||||
AssetReference asBase = typeReference;
|
||||
Assert.IsNull(asBase.editorAsset,
|
||||
"Attempting to get an object type not located at a guid should return a null value even if the method of the generic AssetReference class is being called.");
|
||||
AssetReference baseReference = new AssetReference(guid);
|
||||
Assert.AreEqual(baseReference.editorAsset, AssetDatabase.LoadAssetAtPath<TestObject>(m_ScriptableObjectPath), "Generic AssetReference should get the asset of the main type at the guid.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AssetReferenceEditorAssetForSubObject_Sprite()
|
||||
{
|
||||
var guid = AssetDatabase.AssetPathToGUID(m_TexturePath);
|
||||
AssetReferenceSprite atlasReference = new AssetReferenceSprite(guid);
|
||||
atlasReference.SubObjectName = "testTexture";
|
||||
|
||||
//Test
|
||||
Assert.IsNotNull(atlasReference.editorAsset);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AssetReferenceEditorAssetForSubObject_AtlasedSprite()
|
||||
{
|
||||
var guid = AssetDatabase.AssetPathToGUID(m_SpriteAtlasPath);
|
||||
AssetReferenceAtlasedSprite atlasReference = new AssetReferenceAtlasedSprite(guid);
|
||||
atlasReference.SubObjectName = "testTexture";
|
||||
|
||||
//Test
|
||||
Assert.IsNotNull(atlasReference.editorAsset);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AssetReferenceNoAsset_CreatesCorrectLabelForType()
|
||||
{
|
||||
// Base Types
|
||||
string expected = "None (Addressable Asset)";
|
||||
string val = AssetReferenceDrawerUtilities.ConstructNoAssetLabel(typeof(AssetReference));
|
||||
Assert.AreEqual(expected, val, "General Asset string expected for an unrestricted AssetReference");
|
||||
val = AssetReferenceDrawerUtilities.ConstructNoAssetLabel(typeof(AssetReference[]));
|
||||
Assert.AreEqual(expected, val, "General Asset string expected for an unrestricted AssetReference");
|
||||
val = AssetReferenceDrawerUtilities.ConstructNoAssetLabel(typeof(List<AssetReference>));
|
||||
Assert.AreEqual(expected, val, "General Asset string expected for an unrestricted AssetReference");
|
||||
|
||||
expected = "None (Addressable GameObject)";
|
||||
// generic types
|
||||
val = AssetReferenceDrawerUtilities.ConstructNoAssetLabel(typeof(AssetReferenceT<GameObject>));
|
||||
Assert.AreEqual(expected, val, "Type restricted is expected in display string shown");
|
||||
val = AssetReferenceDrawerUtilities.ConstructNoAssetLabel(typeof(AssetReferenceT<GameObject>[]));
|
||||
Assert.AreEqual(expected, val, "Type restricted is expected in display string shown");
|
||||
val = AssetReferenceDrawerUtilities.ConstructNoAssetLabel(typeof(List<AssetReferenceT<GameObject>>));
|
||||
Assert.AreEqual(expected, val, "Type restricted is expected in display string shown");
|
||||
|
||||
// inherited types
|
||||
val = AssetReferenceDrawerUtilities.ConstructNoAssetLabel(typeof(AssetReferenceGameObject));
|
||||
Assert.AreEqual(expected, val, "Type restricted is expected in display string shown");
|
||||
val = AssetReferenceDrawerUtilities.ConstructNoAssetLabel(typeof(AssetReferenceGameObject[]));
|
||||
Assert.AreEqual(expected, val, "Type restricted is expected in display string shown");
|
||||
val = AssetReferenceDrawerUtilities.ConstructNoAssetLabel(typeof(List<AssetReferenceGameObject>));
|
||||
Assert.AreEqual(expected, val, "Type restricted is expected in display string shown");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8ea72f96947844c99a3bf31644980db9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,624 @@
|
|||
#if UNITY_2020_1_OR_NEWER
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEditor.AddressableAssets.Build;
|
||||
using UnityEditor.AddressableAssets.Build.DataBuilders;
|
||||
using UnityEditor.AddressableAssets.Settings;
|
||||
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
|
||||
using UnityEditor.Build.Pipeline.Utilities;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using UnityEngine.AddressableAssets.ResourceLocators;
|
||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||
using UnityEngine.ResourceManagement.ResourceProviders;
|
||||
using UnityEngine.ResourceManagement.Util;
|
||||
using UnityEngine.TestTools;
|
||||
|
||||
namespace UnityEditor.AddressableAssets.Tests
|
||||
{
|
||||
public class AddressableAssetSettingsLocatorTests
|
||||
{
|
||||
AddressableAssetSettings m_Settings;
|
||||
const string TempPath = "TempGen";
|
||||
string GetPath(string a) => $"Assets/{TempPath}/{a}";
|
||||
EditorBuildSettingsScene[] m_PreviousScenes;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
if (AssetDatabase.IsValidFolder($"Assets/{TempPath}"))
|
||||
{
|
||||
AssetDatabase.DeleteAsset($"Assets/{TempPath}");
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
AssetDatabase.CreateFolder("Assets", "TempGen");
|
||||
m_PreviousScenes = EditorBuildSettings.scenes;
|
||||
m_Settings = AddressableAssetSettings.Create(GetPath("Settings"), "AddressableAssetSettings.Tests", true, true);
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void Teardown()
|
||||
{
|
||||
AssetDatabase.Refresh();
|
||||
// Many of the tests keep recreating assets in the same path, so we need to unload them completely so they don't get reused by the next test
|
||||
AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(m_Settings));
|
||||
Resources.UnloadAsset(m_Settings);
|
||||
if (AssetDatabase.IsValidFolder($"Assets/{TempPath}"))
|
||||
AssetDatabase.DeleteAsset($"Assets/{TempPath}");
|
||||
EditorBuildSettings.scenes = m_PreviousScenes;
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
string CreateAsset(string assetName, string path)
|
||||
{
|
||||
AssetDatabase.CreateAsset(UnityEngine.AddressableAssets.Tests.TestObject.Create(assetName), path);
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceSynchronousImport | ImportAssetOptions.ForceUpdate);
|
||||
AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
|
||||
return AssetDatabase.AssetPathToGUID(path);
|
||||
}
|
||||
|
||||
string CreateScene(string path)
|
||||
{
|
||||
var scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
|
||||
EditorSceneManager.SaveScene(scene, path);
|
||||
return AssetDatabase.AssetPathToGUID(path);
|
||||
}
|
||||
|
||||
string CreateFolder(string folderName, string[] assetNames, HashSet<object> guids = null)
|
||||
{
|
||||
var path = GetPath(folderName);
|
||||
Directory.CreateDirectory(path);
|
||||
foreach (var a in assetNames)
|
||||
{
|
||||
var guid = a.EndsWith(".unity", StringComparison.OrdinalIgnoreCase) ? CreateScene(Path.Combine(path, a)) : CreateAsset(a, Path.Combine(path, a));
|
||||
guids?.Add(guid);
|
||||
}
|
||||
|
||||
AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceSynchronousImport | ImportAssetOptions.ForceUpdate);
|
||||
AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
|
||||
return AssetDatabase.AssetPathToGUID(path);
|
||||
}
|
||||
|
||||
void AssertLocateResult<T>(IResourceLocator locator, object key, params string[] expectedInternalIds)
|
||||
{
|
||||
var type = typeof(T);
|
||||
Assert.IsTrue(locator.Locate(key, type, out var locations));
|
||||
Assert.IsNotNull(locations);
|
||||
if (type != typeof(object))
|
||||
{
|
||||
foreach (var l in locations)
|
||||
Assert.IsTrue(type.IsAssignableFrom(l.ResourceType));
|
||||
}
|
||||
|
||||
Assert.AreEqual(expectedInternalIds.Length, locations.Count);
|
||||
foreach (var e in expectedInternalIds)
|
||||
Assert.NotNull(locations.FirstOrDefault(s => s.InternalId == e), $"Locations do not contain entry with internal id of {e}");
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator CanLoadAssetAsync_InEditMode()
|
||||
{
|
||||
var entry = m_Settings.CreateOrMoveEntry(CreateAsset("x", GetPath("x.asset")), m_Settings.DefaultGroup).address = "x";
|
||||
Addressables.Instance.hasStartedInitialization = false;
|
||||
Addressables.Instance.InitializeAsync($"GUID:{AssetDatabase.AssetPathToGUID(m_Settings.AssetPath)}");
|
||||
var op = Addressables.LoadAssetAsync<UnityEngine.AddressableAssets.Tests.TestObject>("x");
|
||||
while (!op.IsDone)
|
||||
yield return null;
|
||||
Assert.IsNotNull(op.Result);
|
||||
op.Release();
|
||||
m_Settings.RemoveAssetEntry(entry);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanLoadAssetSync_InEditMode()
|
||||
{
|
||||
var entry = m_Settings.CreateOrMoveEntry(CreateAsset("y", GetPath("y.asset")), m_Settings.DefaultGroup).address = "y";
|
||||
Addressables.Instance.hasStartedInitialization = false;
|
||||
Addressables.Instance.InitializeAsync($"GUID:{AssetDatabase.AssetPathToGUID(m_Settings.AssetPath)}");
|
||||
var op = Addressables.LoadAssetAsync<UnityEngine.AddressableAssets.Tests.TestObject>("y");
|
||||
op.WaitForCompletion();
|
||||
Assert.IsNotNull(op.Result);
|
||||
op.Release();
|
||||
m_Settings.RemoveAssetEntry(entry);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenLocatorWithSingleAsset_LocateWithAddress_ReturnsSingleLocation()
|
||||
{
|
||||
var path = GetPath("asset1.asset");
|
||||
m_Settings.CreateOrMoveEntry(CreateAsset("asset1", path), m_Settings.DefaultGroup).address = "address1";
|
||||
AssertLocateResult<UnityEngine.AddressableAssets.Tests.TestObject>(new AddressableAssetSettingsLocator(m_Settings), "address1", path);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenLocatorWithSingleMonoscript_LocateReturnsSingleLocation()
|
||||
{
|
||||
string id = "mono";
|
||||
var path = GetPath("mono.asset");
|
||||
AssetDatabase.CreateAsset(UnityEngine.AddressableAssets.Tests.TestObjectWithSerializableField.Create(id), path);
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceSynchronousImport | ImportAssetOptions.ForceUpdate);
|
||||
AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
|
||||
|
||||
m_Settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(path), m_Settings.DefaultGroup).address = id;
|
||||
var locator = new AddressableAssetSettingsLocator(m_Settings);
|
||||
|
||||
Assert.IsTrue(locator.Locate(id, null, out var locs));
|
||||
Assert.IsNotNull(locs);
|
||||
Assert.AreEqual(1, locs.Count);
|
||||
Assert.AreEqual(path, locs[0].InternalId, $"Locations do not contain entry with internal id of {path}");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenLocatorWithSingleAsset_LocateWithSameAddressAsLabel_ReturnsSingleLocation()
|
||||
{
|
||||
var path = GetPath("asset1.asset");
|
||||
var e = m_Settings.CreateOrMoveEntry(CreateAsset("asset1", path), m_Settings.DefaultGroup);
|
||||
e.address = "address1";
|
||||
e.SetLabel("address1", true, true);
|
||||
AssertLocateResult<UnityEngine.AddressableAssets.Tests.TestObject>(new AddressableAssetSettingsLocator(m_Settings), "address1", path);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenLocatorWithSingleAsset_LocateWithInvalidKeyReturnsFalse()
|
||||
{
|
||||
m_Settings.CreateOrMoveEntry(CreateAsset("asset1", GetPath("asset1.asset")), m_Settings.DefaultGroup).address = "address1";
|
||||
var locator = new AddressableAssetSettingsLocator(m_Settings);
|
||||
Assert.IsFalse(locator.Locate("invalid", null, out var locs));
|
||||
Assert.IsNull(locs);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenLocatorWithSingleAsset_LocateWithGuidReturnsSingleLocation()
|
||||
{
|
||||
var guid = CreateAsset("asset1", GetPath("asset1.asset"));
|
||||
m_Settings.CreateOrMoveEntry(guid, m_Settings.DefaultGroup).address = "address1";
|
||||
AssertLocateResult<UnityEngine.AddressableAssets.Tests.TestObject>(new AddressableAssetSettingsLocator(m_Settings), guid, GetPath("asset1.asset"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenLocatorWithMultipeAssets_LocateWithAddressReturnsSingleLocation()
|
||||
{
|
||||
m_Settings.CreateOrMoveEntry(CreateAsset("asset1", GetPath("asset1.asset")), m_Settings.DefaultGroup).address = "address1";
|
||||
m_Settings.CreateOrMoveEntry(CreateAsset("asset2", GetPath("asset2.asset")), m_Settings.DefaultGroup).address = "address2";
|
||||
AssertLocateResult<UnityEngine.AddressableAssets.Tests.TestObject>(new AddressableAssetSettingsLocator(m_Settings), "address1", GetPath("asset1.asset"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenLocatorWithMultipeAssets_LocateWithSharedAddressReturnsMultipleLocations()
|
||||
{
|
||||
m_Settings.CreateOrMoveEntry(CreateAsset("asset1", GetPath("asset1.asset")), m_Settings.DefaultGroup).address = "address1";
|
||||
m_Settings.CreateOrMoveEntry(CreateAsset("asset2", GetPath("asset2.asset")), m_Settings.DefaultGroup).address = "address1";
|
||||
AssertLocateResult<UnityEngine.AddressableAssets.Tests.TestObject>(new AddressableAssetSettingsLocator(m_Settings), "address1", GetPath("asset1.asset"), GetPath("asset2.asset"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenLocatorWithMultipeAssets_LocateWithSharedLabelReturnsMultipleLocations()
|
||||
{
|
||||
m_Settings.CreateOrMoveEntry(CreateAsset("asset1", GetPath("asset1.asset")), m_Settings.DefaultGroup).SetLabel("label", true, true);
|
||||
m_Settings.CreateOrMoveEntry(CreateAsset("asset2", GetPath("asset2.asset")), m_Settings.DefaultGroup).SetLabel("label", true, true);
|
||||
AssertLocateResult<UnityEngine.AddressableAssets.Tests.TestObject>(new AddressableAssetSettingsLocator(m_Settings), "label", GetPath("asset1.asset"), GetPath("asset2.asset"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenLocatorWithAssetsThatMatchAssetsInFolderAndResources_LocateAllMatches()
|
||||
{
|
||||
CreateFolder("Resources/TestFolder", new string[] {"asset1.asset"});
|
||||
var folderGUID = CreateFolder("TestFolder", new string[] {"asset1.asset"});
|
||||
m_Settings.CreateOrMoveEntry(folderGUID, m_Settings.DefaultGroup).address = "TestFolder";
|
||||
var assetGUID = CreateAsset("asset1", GetPath("asset1.asset"));
|
||||
m_Settings.CreateOrMoveEntry(assetGUID, m_Settings.DefaultGroup).address = "TestFolder/asset1.asset";
|
||||
AssertLocateResult<UnityEngine.AddressableAssets.Tests.TestObject>(new AddressableAssetSettingsLocator(m_Settings), "TestFolder/asset1.asset",
|
||||
"TestFolder/asset1",
|
||||
GetPath("TestFolder/asset1.asset"),
|
||||
GetPath("asset1.asset")
|
||||
);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenLocatorWithAssetsInMarkedFolder_LocateWithAssetReferenceSucceeds()
|
||||
{
|
||||
CreateFolder("TestFolder1/TestFolder2", new string[] {"asset1.asset", "asset2.asset", "asset3.asset"});
|
||||
var folderGUID = AssetDatabase.AssetPathToGUID(GetPath("TestFolder1"));
|
||||
m_Settings.CreateOrMoveEntry(folderGUID, m_Settings.DefaultGroup).address = "TF1";
|
||||
var assetRef = m_Settings.CreateAssetReference(AssetDatabase.AssetPathToGUID(GetPath("TestFolder1/TestFolder2/asset1.asset")));
|
||||
AssertLocateResult<UnityEngine.AddressableAssets.Tests.TestObject>(new AddressableAssetSettingsLocator(m_Settings), assetRef.RuntimeKey, GetPath("TestFolder1/TestFolder2/asset1.asset"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenLocatorWithAssetsInFolder_LocateWithAssetKeySucceeds()
|
||||
{
|
||||
var folderGUID = CreateFolder("TestFolder", new string[] {"asset1.asset", "asset2.asset", "asset3.asset"});
|
||||
m_Settings.CreateOrMoveEntry(folderGUID, m_Settings.DefaultGroup).address = "TF";
|
||||
AssertLocateResult<UnityEngine.AddressableAssets.Tests.TestObject>(new AddressableAssetSettingsLocator(m_Settings), "TF/asset1.asset", GetPath("TestFolder/asset1.asset"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenLocatorWithAssetsInMatchingFolders_LocateWithAssetKeySucceeds()
|
||||
{
|
||||
var folderGUID1 = CreateFolder("TestFolder1", new string[] {"asset1_1.asset", "asset2_1.asset", "asset3_1.asset"});
|
||||
var folderGUID2 = CreateFolder("TestFolder2", new string[] {"asset1_2.asset", "asset2_2.asset", "asset3_2.asset"});
|
||||
m_Settings.CreateOrMoveEntry(folderGUID1, m_Settings.DefaultGroup).address = "TF";
|
||||
m_Settings.CreateOrMoveEntry(folderGUID2, m_Settings.DefaultGroup).address = "TF";
|
||||
AssertLocateResult<UnityEngine.AddressableAssets.Tests.TestObject>(new AddressableAssetSettingsLocator(m_Settings), "TF/asset1_1.asset", GetPath("TestFolder1/asset1_1.asset"));
|
||||
AssertLocateResult<UnityEngine.AddressableAssets.Tests.TestObject>(new AddressableAssetSettingsLocator(m_Settings), "TF/asset1_2.asset", GetPath("TestFolder2/asset1_2.asset"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenLocatorWithAssetsInMatchingFolderAndAssets_LocateWithAssetKeySucceeds()
|
||||
{
|
||||
var folderGUID1 = CreateFolder("TestFolder1", new string[] {"asset1.asset", "asset2.asset", "asset3.asset"});
|
||||
var folderGUID2 = CreateFolder("TestFolder2", new string[] {"asset1.asset", "asset2.asset", "asset3.asset"});
|
||||
m_Settings.CreateOrMoveEntry(folderGUID1, m_Settings.DefaultGroup).address = "TF";
|
||||
m_Settings.CreateOrMoveEntry(folderGUID2, m_Settings.DefaultGroup).address = "TF";
|
||||
AssertLocateResult<UnityEngine.AddressableAssets.Tests.TestObject>(new AddressableAssetSettingsLocator(m_Settings), "TF/asset1.asset", GetPath("TestFolder1/asset1.asset"),
|
||||
GetPath("TestFolder2/asset1.asset"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenLocatorWithAssetAndFolderNameMatch_LocateWithAssetKeySucceeds()
|
||||
{
|
||||
var folderGUID = CreateFolder("TestName", new string[] {"TestName.asset"});
|
||||
m_Settings.CreateOrMoveEntry(folderGUID, m_Settings.DefaultGroup).address = "TF";
|
||||
AssertLocateResult<UnityEngine.AddressableAssets.Tests.TestObject>(new AddressableAssetSettingsLocator(m_Settings), "TF/TestName.asset", GetPath("TestName/TestName.asset"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenLocatorWithAssetAndFolderAddrMatch_LocateWithAssetKeySucceeds()
|
||||
{
|
||||
var folderGUID = CreateFolder("TestName", new string[] {"TF.asset"});
|
||||
m_Settings.CreateOrMoveEntry(folderGUID, m_Settings.DefaultGroup).address = "TF";
|
||||
AssertLocateResult<UnityEngine.AddressableAssets.Tests.TestObject>(new AddressableAssetSettingsLocator(m_Settings), "TF/TF.asset", GetPath("TestName/TF.asset"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenLocatorWithAssetsInFolder_LocateWithFolderKeyFails()
|
||||
{
|
||||
var folderGUID = CreateFolder("TestFolder", new string[] {"asset1.asset", "asset2.asset", "asset3.asset"});
|
||||
m_Settings.CreateOrMoveEntry(folderGUID, m_Settings.DefaultGroup).address = "TF";
|
||||
var locator = new AddressableAssetSettingsLocator(m_Settings);
|
||||
Assert.IsFalse(locator.Locate("TF", null, out var locations));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenLocatorWithAssetsInFolder_LocateWithFolderLabelSucceeds()
|
||||
{
|
||||
var folderGUID = CreateFolder("TestFolder", new string[] {"asset1.asset", "asset2.asset", "asset3.asset"});
|
||||
var folderEntry = m_Settings.CreateOrMoveEntry(folderGUID, m_Settings.DefaultGroup);
|
||||
folderEntry.address = "TF";
|
||||
folderEntry.SetLabel("FolderLabel", true, true, true);
|
||||
AssertLocateResult<UnityEngine.AddressableAssets.Tests.TestObject>(new AddressableAssetSettingsLocator(m_Settings), "FolderLabel", GetPath("TestFolder/asset1.asset"),
|
||||
GetPath("TestFolder/asset2.asset"), GetPath("TestFolder/asset3.asset"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenLocatorWithAssetsInFolderWithSimilarNames_LocateWithAssetKeySucceeds()
|
||||
{
|
||||
var folderGUID = CreateFolder("TestFolder", new string[] {"asset1.asset", "asset.asset", "asset1_more.asset"});
|
||||
m_Settings.CreateOrMoveEntry(folderGUID, m_Settings.DefaultGroup).address = "TF";
|
||||
AssertLocateResult<UnityEngine.AddressableAssets.Tests.TestObject>(new AddressableAssetSettingsLocator(m_Settings), "TF/asset1.asset", GetPath("TestFolder/asset1.asset"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenLocatorWithAssetsInNestedFolders_LocateWithAssetKeySucceeds()
|
||||
{
|
||||
var folderGUID1 = CreateFolder("TestFolder", new string[] {"asset1.asset", "asset2.asset", "asset3.asset"});
|
||||
var folderGUID2 = CreateFolder("TestFolder/TestSubFolder1", new string[] {"asset1.asset", "asset2.asset", "asset3.asset"});
|
||||
var folderGUID3 = CreateFolder("TestFolder/TestSubFolder1/TestSubFolder2", new string[] {"asset1.asset", "asset2.asset", "asset3.asset"});
|
||||
m_Settings.CreateOrMoveEntry(folderGUID1, m_Settings.DefaultGroup).address = "TF";
|
||||
var locator = new AddressableAssetSettingsLocator(m_Settings);
|
||||
AssertLocateResult<UnityEngine.AddressableAssets.Tests.TestObject>(locator, "TF/asset1.asset", GetPath("TestFolder/asset1.asset"));
|
||||
AssertLocateResult<UnityEngine.AddressableAssets.Tests.TestObject>(locator, "TF/TestSubFolder1/asset1.asset", GetPath("TestFolder/TestSubFolder1/asset1.asset"));
|
||||
AssertLocateResult<UnityEngine.AddressableAssets.Tests.TestObject>(locator, "TF/TestSubFolder1/TestSubFolder2/asset1.asset",
|
||||
GetPath("TestFolder/TestSubFolder1/TestSubFolder2/asset1.asset"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenLocatorWithAssetsInNestedFoldersThatAreBothAddressable_LocateWithAssetKeySucceeds()
|
||||
{
|
||||
var folderGUID1 = CreateFolder("TestFolder", new string[] {"asset1.asset", "asset2.asset", "asset3.asset"});
|
||||
var folderGUID2 = CreateFolder("TestFolder/TestSubFolder1", new string[] {"asset1.asset", "asset2.asset", "asset3.asset"});
|
||||
var folderGUID3 = CreateFolder("TestFolder/TestSubFolder1/TestSubFolder2", new string[] {"asset1.asset", "asset2.asset", "asset3.asset"});
|
||||
m_Settings.CreateOrMoveEntry(folderGUID1, m_Settings.DefaultGroup).address = "TF";
|
||||
m_Settings.CreateOrMoveEntry(folderGUID2, m_Settings.DefaultGroup).address = "TF2";
|
||||
var locator = new AddressableAssetSettingsLocator(m_Settings);
|
||||
AssertLocateResult<UnityEngine.AddressableAssets.Tests.TestObject>(locator, "TF/asset1.asset", GetPath("TestFolder/asset1.asset"));
|
||||
AssertLocateResult<UnityEngine.AddressableAssets.Tests.TestObject>(locator, "TF2/asset1.asset", GetPath("TestFolder/TestSubFolder1/asset1.asset"));
|
||||
AssertLocateResult<UnityEngine.AddressableAssets.Tests.TestObject>(locator, "TF2/TestSubFolder2/asset1.asset", GetPath("TestFolder/TestSubFolder1/TestSubFolder2/asset1.asset"));
|
||||
}
|
||||
|
||||
void CreateAndAddScenesToEditorBuildSettings(string scenePrefix, int count, HashSet<object> guids = null)
|
||||
{
|
||||
var sceneList = new List<EditorBuildSettingsScene>();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var path = GetPath($"{scenePrefix}{i}.unity");
|
||||
var scene = EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects, i == 0 ? NewSceneMode.Single : NewSceneMode.Additive);
|
||||
EditorSceneManager.SaveScene(scene, path);
|
||||
var guid = AssetDatabase.AssetPathToGUID(path);
|
||||
guids?.Add(guid);
|
||||
sceneList.Add(new EditorBuildSettingsScene(path, true));
|
||||
}
|
||||
|
||||
EditorBuildSettings.scenes = sceneList.ToArray();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenLocatorWithScenesInSceneList_LocateWithSceneIndexKeyReturnsLocationForScene()
|
||||
{
|
||||
CreateAndAddScenesToEditorBuildSettings("testScene", 3);
|
||||
var locator = new AddressableAssetSettingsLocator(m_Settings);
|
||||
for (int i = 0; i < 3; i++)
|
||||
AssertLocateResult<SceneInstance>(locator, i, GetPath($"testScene{i}.unity"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenLocatorWithScenesInSceneList_LocateWithSceneGUIDKeyReturnsLocationForScene()
|
||||
{
|
||||
CreateAndAddScenesToEditorBuildSettings("testScene", 3);
|
||||
var locator = new AddressableAssetSettingsLocator(m_Settings);
|
||||
for (int i = 0; i < EditorBuildSettings.scenes.Length; i++)
|
||||
AssertLocateResult<SceneInstance>(locator, EditorBuildSettings.scenes[i].guid.ToString(), GetPath($"testScene{i}.unity"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenLocatorWithScenesInSceneList_LocateWithSceneNameKeyReturnsLocationForScene()
|
||||
{
|
||||
CreateAndAddScenesToEditorBuildSettings("testScene", 3);
|
||||
var locator = new AddressableAssetSettingsLocator(m_Settings);
|
||||
for (int i = 0; i < EditorBuildSettings.scenes.Length; i++)
|
||||
AssertLocateResult<SceneInstance>(locator, $"testScene{i}", GetPath($"testScene{i}.unity"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void LocateWithSceneInstanceType_DoesNotReturnNonSceneLocations()
|
||||
{
|
||||
CreateAndAddScenesToEditorBuildSettings("test", 1);
|
||||
var guid = CreateAsset("test0", GetPath("asset1.asset"));
|
||||
m_Settings.CreateOrMoveEntry(guid, m_Settings.DefaultGroup).address = "test0";
|
||||
var locator = new AddressableAssetSettingsLocator(m_Settings);
|
||||
Assert.IsTrue(locator.Locate("test0", typeof(SceneInstance), out var locations));
|
||||
Assert.AreEqual(1, locations.Count);
|
||||
Assert.AreEqual(typeof(SceneInstance), locations[0].ResourceType);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void LocateWithSceneInstanceType_ReturnsLocationsWhenTypeNull()
|
||||
{
|
||||
CreateAndAddScenesToEditorBuildSettings("test", 1);
|
||||
var guid = CreateAsset("test0", GetPath("asset1.asset"));
|
||||
m_Settings.CreateOrMoveEntry(guid, m_Settings.DefaultGroup).address = "test0";
|
||||
var locator = new AddressableAssetSettingsLocator(m_Settings);
|
||||
Assert.IsTrue(locator.Locate("test0", null, out var locations));
|
||||
Assert.AreEqual(2, locations.Count);
|
||||
Assert.AreEqual(typeof(SceneInstance), locations[0].ResourceType);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void LocateWithNonSceneInstanceType_DoesNotReturnSceneLocations()
|
||||
{
|
||||
CreateAndAddScenesToEditorBuildSettings("test", 1);
|
||||
var guid = CreateAsset("test0", GetPath("asset1.asset"));
|
||||
m_Settings.CreateOrMoveEntry(guid, m_Settings.DefaultGroup).address = "test0";
|
||||
var locator = new AddressableAssetSettingsLocator(m_Settings);
|
||||
Assert.IsTrue(locator.Locate("test0", typeof(UnityEngine.AddressableAssets.Tests.TestObject), out var locations));
|
||||
Assert.AreEqual(1, locations.Count);
|
||||
Assert.AreEqual(typeof(UnityEngine.AddressableAssets.Tests.TestObject), locations[0].ResourceType);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenLocatorWithScenesInSceneList_LocateWithISceneInstanceType_ReturnsLocationForScene()
|
||||
{
|
||||
CreateAndAddScenesToEditorBuildSettings("testScene", 3);
|
||||
var locator = new AddressableAssetSettingsLocator(m_Settings);
|
||||
for (int i = 0; i < EditorBuildSettings.scenes.Length; i++)
|
||||
AssertLocateResult<SceneInstance>(locator, $"testScene{i}", GetPath($"testScene{i}.unity"));
|
||||
}
|
||||
|
||||
public void RunResourcesTestWithAsset(bool IncludeResourcesFolders)
|
||||
{
|
||||
int builtInResourceCount = ResourcesTestUtility.GetResourcesEntryCount(m_Settings, true);
|
||||
var path = GetPath("Resources/test.asset");
|
||||
var dir = Path.GetDirectoryName(path);
|
||||
Directory.CreateDirectory(dir);
|
||||
AssetDatabase.CreateAsset(UnityEngine.AddressableAssets.Tests.TestObject.Create("test"), path);
|
||||
AssetDatabase.SaveAssets();
|
||||
m_Settings.FindGroup(g => g.HasSchema<PlayerDataGroupSchema>()).GetSchema<PlayerDataGroupSchema>().IncludeResourcesFolders = IncludeResourcesFolders;
|
||||
var locator = new AddressableAssetSettingsLocator(m_Settings);
|
||||
var res = locator.Locate("test", null, out var locations);
|
||||
Assert.AreEqual(res, IncludeResourcesFolders);
|
||||
if (IncludeResourcesFolders)
|
||||
Assert.AreEqual(1 + builtInResourceCount, locations.Count + builtInResourceCount);
|
||||
else
|
||||
Assert.IsNull(locations);
|
||||
AssetDatabase.DeleteAsset(path);
|
||||
Directory.Delete(dir);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAGroupHasIncludeResourcesFoldersEnabled_LocateFindsAssetInResourcesFolder()
|
||||
{
|
||||
RunResourcesTestWithAsset(true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAGroupHasIncludeResourcesFoldersDisabled_LocateFailesForAssetInResourcesFolder()
|
||||
{
|
||||
RunResourcesTestWithAsset(false);
|
||||
}
|
||||
|
||||
static HashSet<object> ExpectedKeys = new HashSet<object>(new object[]
|
||||
{
|
||||
"TestScene0", //scene name in build settings
|
||||
0, //index if TestScene0
|
||||
"TestScene1",
|
||||
1,
|
||||
"TestScene2",
|
||||
2,
|
||||
//assets in a folder with an address
|
||||
"AssetAddress",
|
||||
"AssetLabel",
|
||||
"TF/asset2.asset",
|
||||
"TF/asset3.asset",
|
||||
//scenes in a folder
|
||||
"TF/TestSubFolder2/scene1.unity",
|
||||
"TF/TestSubFolder2/scene2.unity",
|
||||
"TF/TestSubFolder2/scene3.unity",
|
||||
//label applied to folder
|
||||
"FolderLabel1",
|
||||
//assets in subfolder without address
|
||||
"TestFolder/TestSubFolder1/asset1.asset",
|
||||
"TestFolder/TestSubFolder1/asset2.asset",
|
||||
"TestFolder/TestSubFolder1/asset3.asset",
|
||||
//assets in resource in subfolder with address
|
||||
"TestFolder/TestSubFolder1/Resources/asset1.asset",
|
||||
"TestFolder/TestSubFolder1/Resources/asset2.asset",
|
||||
"TestFolder/TestSubFolder1/Resources/asset3.asset",
|
||||
//resources keys
|
||||
"asset1",
|
||||
"asset2",
|
||||
"asset3",
|
||||
});
|
||||
|
||||
void SetupLocatorAssets()
|
||||
{
|
||||
var folderGUID1 = CreateFolder("TestFolder",
|
||||
new string[] {"asset1.asset", "asset2.asset", "asset3.asset"}, ExpectedKeys);
|
||||
var folderGUID2 = CreateFolder("TestFolder/TestSubFolder1",
|
||||
new string[] {"asset1.asset", "asset2.asset", "asset3.asset"}, ExpectedKeys);
|
||||
var folderGUID3 = CreateFolder("TestFolder/TestSubFolder1/Resources",
|
||||
new string[] {"asset1.asset", "asset2.asset", "asset3.asset"}, ExpectedKeys);
|
||||
var folderGUID4 = CreateFolder("TestFolder/TestSubFolder2",
|
||||
new string[] {"scene1.unity", "scene2.unity", "scene3.unity"}, ExpectedKeys);
|
||||
CreateAndAddScenesToEditorBuildSettings("TestScene", 3, ExpectedKeys);
|
||||
var assetInFolder = m_Settings.CreateOrMoveEntry(
|
||||
AssetDatabase.AssetPathToGUID(GetPath("TestFolder/asset1.asset")), m_Settings.DefaultGroup);
|
||||
assetInFolder.address = "AssetAddress";
|
||||
assetInFolder.SetLabel("AssetLabel", true, true, true);
|
||||
var tf = m_Settings.CreateOrMoveEntry(folderGUID1, m_Settings.DefaultGroup);
|
||||
tf.address = "TF";
|
||||
tf.SetLabel("FolderLabel1", true, true, true);
|
||||
var tf2 = m_Settings.CreateOrMoveEntry(folderGUID2, m_Settings.DefaultGroup);
|
||||
tf2.address = "TestFolder/TestSubFolder1";
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator Locator_KeysProperty_Contains_Expected_Keys_ForAllBuildScripts()
|
||||
{
|
||||
using (new HideResourceFoldersScope())
|
||||
{
|
||||
SetupLocatorAssets();
|
||||
|
||||
AddressablesDataBuilderInput input = new AddressablesDataBuilderInput(m_Settings);
|
||||
input.Logger = new BuildLog();
|
||||
|
||||
var fastMode = ScriptableObject.CreateInstance<BuildScriptFastMode>();
|
||||
var virtualMode = ScriptableObject.CreateInstance<BuildScriptVirtualMode>();
|
||||
var packedMode = ScriptableObject.CreateInstance<BuildScriptPackedMode>();
|
||||
var packedPlayMode = ScriptableObject.CreateInstance<BuildScriptPackedPlayMode>();
|
||||
|
||||
AddressablesImpl fastModeImpl = new AddressablesImpl(new DefaultAllocationStrategy());
|
||||
fastModeImpl.AddResourceLocator(new AddressableAssetSettingsLocator(m_Settings));
|
||||
|
||||
var fastModeSettingsPath = fastMode.BuildData<AddressableAssetBuildResult>(input).OutputPath;
|
||||
var virtualModeSettingsPath = virtualMode.BuildData<AddressableAssetBuildResult>(input).OutputPath;
|
||||
var packedModeSettingsPath = packedMode.BuildData<AddressableAssetBuildResult>(input).OutputPath;
|
||||
var packedPlayModeSettingsPath = packedPlayMode.BuildData<AddressableAssetBuildResult>(input).OutputPath;
|
||||
|
||||
AddressablesImpl fmImpl = new AddressablesImpl(new DefaultAllocationStrategy());
|
||||
AddressablesImpl virtualImpl = new AddressablesImpl(new DefaultAllocationStrategy());
|
||||
AddressablesImpl packedImpl = new AddressablesImpl(new DefaultAllocationStrategy());
|
||||
AddressablesImpl packedPlayImpl = new AddressablesImpl(new DefaultAllocationStrategy());
|
||||
|
||||
fmImpl.AddResourceLocator(new AddressableAssetSettingsLocator(m_Settings));
|
||||
virtualImpl.AddResourceLocator(new AddressableAssetSettingsLocator(m_Settings));
|
||||
packedImpl.AddResourceLocator(new AddressableAssetSettingsLocator(m_Settings));
|
||||
packedPlayImpl.AddResourceLocator(new AddressableAssetSettingsLocator(m_Settings));
|
||||
|
||||
var fastModeHandle = fmImpl.ResourceManager.StartOperation(new FastModeInitializationOperation(fmImpl, m_Settings), default(AsyncOperationHandle));
|
||||
var virtualHandle = virtualImpl.InitializeAsync(virtualModeSettingsPath);
|
||||
var packedHandle = packedImpl.InitializeAsync(packedModeSettingsPath);
|
||||
var packedPlayHandle = packedPlayImpl.InitializeAsync(packedPlayModeSettingsPath);
|
||||
while (!fastModeHandle.IsDone && !virtualHandle.IsDone && !packedHandle.IsDone &&
|
||||
!packedPlayHandle.IsDone)
|
||||
yield return null;
|
||||
|
||||
var fastModeKeys = fmImpl.ResourceLocators.First(l => l.GetType() == typeof(AddressableAssetSettingsLocator)).Keys;
|
||||
var virtualModeKeys = virtualImpl.ResourceLocators.First(l => l.GetType() == typeof(AddressableAssetSettingsLocator)).Keys;
|
||||
var packedModeKeys = packedImpl.ResourceLocators.First(l => l.GetType() == typeof(AddressableAssetSettingsLocator)).Keys;
|
||||
var packedPlayKeys = packedPlayImpl.ResourceLocators.First(l => l.GetType() == typeof(AddressableAssetSettingsLocator)).Keys;
|
||||
|
||||
|
||||
var builtInPackageResourcesEntries = ResourcesTestUtility.GetResourcesEntries(m_Settings, true);
|
||||
foreach (var key in builtInPackageResourcesEntries)
|
||||
{
|
||||
ExpectedKeys.Add(key.guid);
|
||||
ExpectedKeys.Add(key.address);
|
||||
}
|
||||
|
||||
//Get our baseline
|
||||
Assert.AreEqual(ExpectedKeys.Count, fastModeKeys.Count());
|
||||
foreach (var key in fastModeKeys)
|
||||
Assert.IsTrue(ExpectedKeys.Contains(key));
|
||||
|
||||
//Transitive property to check other build scripts
|
||||
CollectionAssert.AreEqual(fastModeKeys, virtualModeKeys);
|
||||
CollectionAssert.AreEqual(fastModeKeys, packedPlayKeys);
|
||||
CollectionAssert.AreEqual(fastModeKeys, packedModeKeys);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Locator_KeysProperty_Contains_Expected_Keys()
|
||||
{
|
||||
using (new HideResourceFoldersScope())
|
||||
{
|
||||
SetupLocatorAssets();
|
||||
var locator = new AddressableAssetSettingsLocator(m_Settings);
|
||||
if (ExpectedKeys.Count != locator.Keys.Count())
|
||||
{
|
||||
Debug.Log("GENERATED");
|
||||
int i = 0;
|
||||
foreach (var k in locator.Keys)
|
||||
{
|
||||
Debug.Log($"[{i}] {k}");
|
||||
i++;
|
||||
}
|
||||
|
||||
Debug.Log("EXPECTED");
|
||||
i = 0;
|
||||
foreach (var k in ExpectedKeys)
|
||||
{
|
||||
Debug.Log($"[{i}] {k}");
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
var builtInPackageResourcesEntries = ResourcesTestUtility.GetResourcesEntries(m_Settings, true);
|
||||
foreach (var key in builtInPackageResourcesEntries)
|
||||
{
|
||||
ExpectedKeys.Add(key.guid);
|
||||
ExpectedKeys.Add(key.address);
|
||||
}
|
||||
|
||||
Assert.AreEqual(ExpectedKeys.Count, locator.Keys.Count());
|
||||
int index = 0;
|
||||
foreach (var k in locator.Keys)
|
||||
{
|
||||
Assert.IsTrue(ExpectedKeys.Contains(k), $"Cannot find key {k}, index={index} in expected keys");
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f4d7d9f74fa394649b729102066b4b96
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3a04deffd16d96345b57337ce2b4d075
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,208 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using NUnit.Framework;
|
||||
using UnityEditor.AddressableAssets.Settings;
|
||||
using UnityEditor.Build.Pipeline.Utilities;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.TestTools;
|
||||
|
||||
namespace UnityEditor.AddressableAssets.Tests
|
||||
{
|
||||
public abstract class AddressableAssetTestBase
|
||||
{
|
||||
protected const string k_TestConfigName = "AddressableAssetSettings.Tests";
|
||||
|
||||
protected string TestFolder => $"Assets/{TestFolderName}";
|
||||
protected string TestFolderName => $"{GetType()}_Tests";
|
||||
protected string ConfigFolder => TestFolder + "/Config";
|
||||
protected string AddressablesFolder => $"Assets/AddressableAssetsData";
|
||||
|
||||
|
||||
protected string GetAssetPath(string assetName)
|
||||
{
|
||||
return $"{TestFolder}/{assetName}";
|
||||
}
|
||||
|
||||
private AddressableAssetSettings m_Settings;
|
||||
|
||||
protected AddressableAssetSettings Settings
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!m_Settings || m_Settings.groups.IsNullOrEmpty())
|
||||
m_Settings = AddressableAssetSettings.Create(ConfigFolder, k_TestConfigName, true, PersistSettings);
|
||||
return m_Settings;
|
||||
}
|
||||
}
|
||||
|
||||
protected string m_AssetGUID;
|
||||
protected string[] m_SceneGuids;
|
||||
|
||||
protected virtual bool PersistSettings
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void Init()
|
||||
{
|
||||
//TODO: Remove when NSImage warning issue on bokken is fixed
|
||||
Application.logMessageReceived += CheckLogForWarning;
|
||||
|
||||
if (Directory.Exists(TestFolder))
|
||||
{
|
||||
Debug.Log($"{GetType()} (init) - deleting {TestFolder}");
|
||||
if (!AssetDatabase.DeleteAsset(TestFolder))
|
||||
Directory.Delete(TestFolder);
|
||||
}
|
||||
|
||||
if (Directory.Exists(AddressablesFolder))
|
||||
{
|
||||
Debug.Log($"{GetType()} (init) - deleting {AddressablesFolder}");
|
||||
if (!AssetDatabase.DeleteAsset(AddressablesFolder))
|
||||
Directory.Delete(AddressablesFolder);
|
||||
}
|
||||
|
||||
Debug.Log($"{GetType()} (init) - creating {TestFolder}");
|
||||
AssetDatabase.CreateFolder("Assets", TestFolderName);
|
||||
AssetDatabase.CreateFolder(TestFolder, "Config");
|
||||
|
||||
Settings.labelTable.labelNames.Clear();
|
||||
GameObject testObject = new GameObject("TestObject");
|
||||
GameObject testObject1 = new GameObject("TestObject 1");
|
||||
GameObject testObject2 = new GameObject("TestObject 2");
|
||||
|
||||
PrefabUtility.SaveAsPrefabAsset(testObject, TestFolder + "/test.prefab");
|
||||
PrefabUtility.SaveAsPrefabAsset(testObject1, TestFolder + "/test 1.prefab");
|
||||
PrefabUtility.SaveAsPrefabAsset(testObject2, TestFolder + "/test 2.prefab");
|
||||
m_AssetGUID = AssetDatabase.AssetPathToGUID(TestFolder + "/test.prefab");
|
||||
|
||||
string scene1Path = TestFolder + "/contentUpdateScene1.unity";
|
||||
string scene2Path = TestFolder + "/contentUpdateScene2.unity";
|
||||
string scene3Path = TestFolder + "/contentUpdateScene3.unity";
|
||||
|
||||
Scene scene1 = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
|
||||
EditorSceneManager.SaveScene(scene1, scene1Path);
|
||||
|
||||
Scene scene2 = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
|
||||
EditorSceneManager.SaveScene(scene2, scene2Path);
|
||||
|
||||
Scene scene3 = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
|
||||
EditorSceneManager.SaveScene(scene3, scene3Path);
|
||||
|
||||
//Clear out the active scene so it doesn't affect tests
|
||||
EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
|
||||
|
||||
m_SceneGuids = new string[]
|
||||
{
|
||||
AssetDatabase.AssetPathToGUID(scene1Path),
|
||||
AssetDatabase.AssetPathToGUID(scene2Path),
|
||||
AssetDatabase.AssetPathToGUID(scene3Path)
|
||||
};
|
||||
|
||||
OnInit();
|
||||
|
||||
//TODO: Remove when NSImage warning issue on bokken is fixed
|
||||
//Removing here in the event we didn't recieve any messages during the setup, we can respond appropriately to
|
||||
//logs in the tests.
|
||||
Application.logMessageReceived -= CheckLogForWarning;
|
||||
if (resetFailingMessages)
|
||||
LogAssert.ignoreFailingMessages = false;
|
||||
}
|
||||
|
||||
private bool resetFailingMessages = false;
|
||||
|
||||
//TODO: Remove when NSImage warning issue on bokken is fixed
|
||||
private void CheckLogForWarning(string condition, string stackTrace, LogType type)
|
||||
{
|
||||
LogAssert.ignoreFailingMessages = true;
|
||||
resetFailingMessages = true;
|
||||
}
|
||||
|
||||
protected virtual void OnInit()
|
||||
{
|
||||
}
|
||||
|
||||
[OneTimeTearDown]
|
||||
public void Cleanup()
|
||||
{
|
||||
OnCleanup();
|
||||
if (Directory.Exists(TestFolder))
|
||||
{
|
||||
Debug.Log($"{GetType()} - (cleanup) deleting {TestFolder}");
|
||||
AssetDatabase.DeleteAsset(TestFolder);
|
||||
}
|
||||
|
||||
if (Directory.Exists(AddressablesFolder))
|
||||
{
|
||||
Debug.Log($"{GetType()} (init) - deleting {AddressablesFolder}");
|
||||
if (!AssetDatabase.DeleteAsset(AddressablesFolder))
|
||||
Directory.Delete(AddressablesFolder);
|
||||
}
|
||||
|
||||
EditorBuildSettings.RemoveConfigObject(k_TestConfigName);
|
||||
}
|
||||
|
||||
protected virtual void OnCleanup()
|
||||
{
|
||||
}
|
||||
|
||||
protected string CreateAsset(string assetPath, string objectName = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(objectName))
|
||||
objectName = Path.GetFileNameWithoutExtension(assetPath);
|
||||
|
||||
GameObject go = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
go.name = objectName;
|
||||
//this is to ensure that bundles are different for every run.
|
||||
go.transform.localPosition = UnityEngine.Random.onUnitSphere;
|
||||
|
||||
string directoryName = Path.GetDirectoryName(assetPath);
|
||||
CreateFolderDeep(directoryName);
|
||||
try
|
||||
{
|
||||
Assert.IsTrue(AssetDatabase.IsValidFolder(directoryName), "Attempting to save prefab to invalid Folder : " + directoryName);
|
||||
Assert.IsTrue(Directory.Exists(directoryName), "Folder is not in FileSystem, but is in ADB : " + directoryName);
|
||||
Assert.IsNotNull(go, "Attempting to save null GameObject to Prefab");
|
||||
PrefabUtility.SaveAsPrefabAsset(go, assetPath);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"Error while attempting to save prefab {objectName} to {assetPath} with Exception message {e.Message}");
|
||||
throw e;
|
||||
}
|
||||
|
||||
UnityEngine.Object.DestroyImmediate(go, false);
|
||||
return AssetDatabase.AssetPathToGUID(assetPath);
|
||||
}
|
||||
|
||||
protected string CreateFolderDeep(string path)
|
||||
{
|
||||
path = path.Replace('\\', '/');
|
||||
if (!path.StartsWith("Assets/", StringComparison.Ordinal))
|
||||
return null;
|
||||
|
||||
if (Directory.Exists(path))
|
||||
{
|
||||
if (AssetDatabase.IsValidFolder(path))
|
||||
return AssetDatabase.AssetPathToGUID(path);
|
||||
AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport);
|
||||
return AssetDatabase.AssetPathToGUID(path);
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(path);
|
||||
AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport);
|
||||
return AssetDatabase.AssetPathToGUID(path);
|
||||
}
|
||||
|
||||
protected void ReloadSettings()
|
||||
{
|
||||
m_Settings = null;
|
||||
EditorBuildSettings.RemoveConfigObject(AddressableAssetSettingsDefaultObject.kDefaultConfigAssetName);
|
||||
EditorBuildSettings.TryGetConfigObject(AddressableAssetSettingsDefaultObject.kDefaultConfigAssetName, out m_Settings);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f9508f7aaece47b45a0d499d7c67a777
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,504 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
using UnityEditor.AddressableAssets.Settings;
|
||||
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
|
||||
using UnityEditor.Build.Utilities;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Audio;
|
||||
|
||||
namespace UnityEditor.AddressableAssets.Tests
|
||||
{
|
||||
public class AddressableAssetUtilityTests : AddressableAssetTestBase
|
||||
{
|
||||
static string CreateTestPrefabAsset(string assetPath, string objectName)
|
||||
{
|
||||
GameObject go = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
go.name = objectName;
|
||||
PrefabUtility.SaveAsPrefabAsset(go, assetPath);
|
||||
UnityEngine.Object.DestroyImmediate(go, false);
|
||||
return AssetDatabase.AssetPathToGUID(assetPath);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetPathAndGUIDFromTarget_FromPrefabAsset_ReturnsCorrectPathGUIDType()
|
||||
{
|
||||
var expectedGUID = CreateTestPrefabAsset(GetAssetPath("prefab1.prefab"), "prefab1");
|
||||
var expectedPath = AssetDatabase.GUIDToAssetPath(expectedGUID);
|
||||
var obj = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(expectedPath);
|
||||
Assert.IsTrue(AddressableAssetUtility.IsPathValidForEntry(expectedPath), $"Asset is not a valid Addressable Entry path : {expectedPath}");
|
||||
Assert.IsTrue(AddressableAssetUtility.TryGetPathAndGUIDFromTarget(obj, out var actualPath, out var actualGUID), "Could not get Path and Guid from Target at expectedPath " + expectedPath);
|
||||
Assert.AreEqual(expectedPath, actualPath);
|
||||
Assert.AreEqual(expectedGUID, actualGUID);
|
||||
AssetDatabase.DeleteAsset(expectedPath);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetPathAndGUIDFromTarget_FromPrefabObject_Fails()
|
||||
{
|
||||
var obj = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
Assert.IsFalse(AddressableAssetUtility.TryGetPathAndGUIDFromTarget(obj, out var actualPath, out var actualGUID));
|
||||
Assert.IsEmpty(actualPath);
|
||||
Assert.IsEmpty(actualGUID);
|
||||
Assert.IsEmpty(actualGUID);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetPathAndGUIDFromTarget_FromNullObject_Fails()
|
||||
{
|
||||
Assert.IsFalse(AddressableAssetUtility.TryGetPathAndGUIDFromTarget(null, out var actualPath, out var actualGUID));
|
||||
Assert.IsEmpty(actualPath);
|
||||
Assert.IsEmpty(actualGUID);
|
||||
Assert.IsEmpty(actualGUID);
|
||||
}
|
||||
|
||||
public class TestBaseClass
|
||||
{
|
||||
}
|
||||
|
||||
[System.ComponentModel.DisplayName("TestSubClass_DisplayName")]
|
||||
public class TestSubClass : TestBaseClass
|
||||
{
|
||||
}
|
||||
|
||||
public abstract class TestAbstractSubClass : TestBaseClass
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetTypesGeneric_ReturnsOnly_NonAbstractSubTypes()
|
||||
{
|
||||
var types = AddressableAssetUtility.GetTypes<TestBaseClass>();
|
||||
Assert.AreEqual(1, types.Count);
|
||||
Assert.AreEqual(types[0], typeof(TestSubClass));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetTypes_ReturnsOnly_NonAbstractSubTypes()
|
||||
{
|
||||
var types = AddressableAssetUtility.GetTypes(typeof(TestBaseClass));
|
||||
Assert.AreEqual(1, types.Count);
|
||||
Assert.AreEqual(types[0], typeof(TestSubClass));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetCachedTypeDisplayName_WithNoAttribute_ReturnsTypeName()
|
||||
{
|
||||
var name = AddressableAssetUtility.GetCachedTypeDisplayName(typeof(TestBaseClass));
|
||||
Assert.AreEqual(typeof(TestBaseClass).Name, name);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetCachedTypeDisplayName_WithAttribute_ReturnsAttributeValue()
|
||||
{
|
||||
var subName = AddressableAssetUtility.GetCachedTypeDisplayName(typeof(TestSubClass));
|
||||
Assert.AreEqual("TestSubClass_DisplayName", subName);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetCachedTypeDisplayName_WithNullType_ReturnsNONE()
|
||||
{
|
||||
var subName = AddressableAssetUtility.GetCachedTypeDisplayName(null);
|
||||
Assert.AreEqual("<none>", subName);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsInResourcesProperlyHandlesCase()
|
||||
{
|
||||
Assert.IsTrue(AddressableAssetUtility.IsInResources("/rEsOurces/"));
|
||||
Assert.IsTrue(AddressableAssetUtility.IsInResources("/resources/"));
|
||||
Assert.IsTrue(AddressableAssetUtility.IsInResources("/RESOURCES/"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsInResourcesHandlesExtraPathing()
|
||||
{
|
||||
Assert.IsTrue(AddressableAssetUtility.IsInResources("path/path/resources/path"));
|
||||
Assert.IsTrue(AddressableAssetUtility.IsInResources("path/path/resources/"));
|
||||
Assert.IsTrue(AddressableAssetUtility.IsInResources("/resources/path"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsInResourcesHandlesResourcesInWrongContext()
|
||||
{
|
||||
Assert.IsFalse(AddressableAssetUtility.IsInResources("resources/"));
|
||||
Assert.IsFalse(AddressableAssetUtility.IsInResources("/resources"));
|
||||
Assert.IsFalse(AddressableAssetUtility.IsInResources("path/resourcesOther/path"));
|
||||
Assert.IsFalse(AddressableAssetUtility.IsInResources("/path/res/ources/path"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsPathValidBlocksCommonStrings()
|
||||
{
|
||||
Assert.IsFalse(AddressableAssetUtility.IsPathValidForEntry(string.Empty));
|
||||
Assert.IsFalse(AddressableAssetUtility.IsPathValidForEntry(CommonStrings.UnityEditorResourcePath));
|
||||
Assert.IsFalse(AddressableAssetUtility.IsPathValidForEntry(CommonStrings.UnityDefaultResourcePath));
|
||||
Assert.IsFalse(AddressableAssetUtility.IsPathValidForEntry(CommonStrings.UnityBuiltInExtraPath));
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase("Assets/Editor/Resources/fake_asset.png")]
|
||||
[TestCase("Assets/Editor/Resources/fake_asset.png")]
|
||||
[TestCase("Assets/Editor/Editor/fake_asset.png")]
|
||||
[TestCase("Assets\\Editor\\Resources\\fake_asset.png")]
|
||||
[TestCase("Assets\\Editor\\Editor\\Resources\\fake_asset.png")]
|
||||
[TestCase("Assets\\Editor\\Resources\\Editor\\Resources\\fake_asset.png")]
|
||||
public void IsPathValidBlocksEditorPaths(string path)
|
||||
{
|
||||
Assert.IsFalse(AddressableAssetUtility.IsPathValidForEntry(path));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsPathValidBlocksBadExtensions()
|
||||
{
|
||||
Assert.IsFalse(AddressableAssetUtility.IsPathValidForEntry("Assets/file.cs"));
|
||||
Assert.IsFalse(AddressableAssetUtility.IsPathValidForEntry("Assets/file.js"));
|
||||
Assert.IsFalse(AddressableAssetUtility.IsPathValidForEntry("Assets/file.boo"));
|
||||
Assert.IsFalse(AddressableAssetUtility.IsPathValidForEntry("Assets/file.exe"));
|
||||
Assert.IsFalse(AddressableAssetUtility.IsPathValidForEntry("Assets/file.dll"));
|
||||
Assert.IsFalse(AddressableAssetUtility.IsPathValidForEntry("Assets/file.preset"));
|
||||
Assert.IsFalse(AddressableAssetUtility.IsPathValidForEntry("Assets/file.asmdef"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsPathValidAllowsBasicTypes()
|
||||
{
|
||||
Assert.IsTrue(AddressableAssetUtility.IsPathValidForEntry("Assets/file.asset"));
|
||||
Assert.IsTrue(AddressableAssetUtility.IsPathValidForEntry("Assets/file.png"));
|
||||
Assert.IsTrue(AddressableAssetUtility.IsPathValidForEntry("Assets/file.bin"));
|
||||
Assert.IsTrue(AddressableAssetUtility.IsPathValidForEntry("Assets/file.txt"));
|
||||
Assert.IsTrue(AddressableAssetUtility.IsPathValidForEntry("Assets/file.prefab"));
|
||||
Assert.IsTrue(AddressableAssetUtility.IsPathValidForEntry("Assets/file.mat"));
|
||||
Assert.IsTrue(AddressableAssetUtility.IsPathValidForEntry("Assets/file.wav"));
|
||||
Assert.IsTrue(AddressableAssetUtility.IsPathValidForEntry("Assets/file.jpg"));
|
||||
Assert.IsTrue(AddressableAssetUtility.IsPathValidForEntry("Assets/file.avi"));
|
||||
Assert.IsTrue(AddressableAssetUtility.IsPathValidForEntry("Assets/file.controller"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenPathIsInUnityAuthoredPackage_IsPathValidForEntry_ReturnsTrue()
|
||||
{
|
||||
Assert.IsTrue(AddressableAssetUtility.IsPathValidForEntry("Packages/com.unity.demo/file.asset"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenPathIsPackageImportFile_IsPathValidForEntry_ReturnsFalse()
|
||||
{
|
||||
Assert.IsFalse(AddressableAssetUtility.IsPathValidForEntry("Packages/com.company.demo/package.json"));
|
||||
}
|
||||
|
||||
public void WhenPathIsNotPackageImportFile_IsPathValidForEntry_ReturnsTrue()
|
||||
{
|
||||
Assert.IsTrue(AddressableAssetUtility.IsPathValidForEntry("Packages/com.company.demo/folder/package.json"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAssetIsNotInPackageFolder_IsPathValidPackageAsset_ReturnsFalse()
|
||||
{
|
||||
Assert.IsFalse(AddressableAssetUtility.IsPathValidPackageAsset("assets/file.asset"));
|
||||
Assert.IsFalse(AddressableAssetUtility.IsPathValidPackageAsset("packages/com.company.demo"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsEditorTypeRemappedToNull()
|
||||
{
|
||||
Assert.IsNull(AddressableAssetUtility.MapEditorTypeToRuntimeType(typeof(UnityEditor.AssetImporter), false));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsRuntimeTypeNotRemapped()
|
||||
{
|
||||
Assert.AreEqual(AddressableAssetUtility.MapEditorTypeToRuntimeType(typeof(UnityEngine.Vector3), false), typeof(UnityEngine.Vector3));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AreConvertableEditorAssemblyTypesConverted()
|
||||
{
|
||||
Assembly asm = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.FullName == "UnityEditor, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
|
||||
var conversionMapping = new Dictionary<Type, Type>()
|
||||
{
|
||||
{asm.GetType("UnityEditor.Audio.AudioMixerGroupController"), typeof(AudioMixerGroup)},
|
||||
{asm.GetType("UnityEditor.Audio.AudioMixerController"), typeof(AudioMixer)},
|
||||
{typeof(UnityEditor.SceneAsset), typeof(UnityEngine.ResourceManagement.ResourceProviders.SceneInstance)},
|
||||
{typeof(UnityEditor.Animations.AnimatorController), typeof(RuntimeAnimatorController)}
|
||||
};
|
||||
|
||||
foreach (Type key in conversionMapping.Keys)
|
||||
{
|
||||
var type = AddressableAssetUtility.MapEditorTypeToRuntimeType(key, false);
|
||||
Assert.AreEqual(type, conversionMapping[key]);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SafeMoveResourcesToGroup_ResourcesMovedToNewFolderAndGroup()
|
||||
{
|
||||
var folderPath = AssetDatabase.GUIDToAssetPath(AssetDatabase.CreateFolder(TestFolder, "Resources"));
|
||||
var g1 = CreateTestPrefabAsset(folderPath + "/p1.prefab", "p1");
|
||||
var g2 = CreateTestPrefabAsset(folderPath + "/p2.prefab", "p2");
|
||||
Assert.AreEqual(0, Settings.DefaultGroup.entries.Count);
|
||||
var result = AddressableAssetUtility.SafeMoveResourcesToGroup(Settings, Settings.DefaultGroup, new List<string> {AssetDatabase.GUIDToAssetPath(g1), AssetDatabase.GUIDToAssetPath(g2)},
|
||||
null, false);
|
||||
Assert.IsTrue(result);
|
||||
Assert.AreEqual(2, Settings.DefaultGroup.entries.Count);
|
||||
var ap = $"{TestFolder}_Resources_moved";
|
||||
Assert.IsTrue(AssetDatabase.IsValidFolder($"{TestFolder}/Resources_moved"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SafeMoveResourcesToGroup_WithInvalidParameters_Fails()
|
||||
{
|
||||
Assert.IsFalse(AddressableAssetUtility.SafeMoveResourcesToGroup(Settings, null, null, null, false));
|
||||
Assert.IsFalse(AddressableAssetUtility.SafeMoveResourcesToGroup(Settings, Settings.DefaultGroup, null, null, false));
|
||||
}
|
||||
|
||||
HashSet<string> otherInternaIds = new HashSet<string>(new string[] {"a", "ab", "abc"});
|
||||
|
||||
[TestCase(BundledAssetGroupSchema.AssetNamingMode.FullPath, "Assets/blah/something.asset", "", "Assets/blah/something.asset")]
|
||||
[TestCase(BundledAssetGroupSchema.AssetNamingMode.Filename, "Assets/blah/something.asset", "", "something.asset")]
|
||||
[TestCase(BundledAssetGroupSchema.AssetNamingMode.Filename, "Assets/blah/somescene.unity", "", "somescene")]
|
||||
[TestCase(BundledAssetGroupSchema.AssetNamingMode.GUID, "Assets/blah/something.asset", "guidstring", "guidstring")]
|
||||
[TestCase(BundledAssetGroupSchema.AssetNamingMode.Dynamic, "Assets/blah/something.asset", "guidstring", "g")]
|
||||
[TestCase(BundledAssetGroupSchema.AssetNamingMode.Dynamic, "Assets/blah/something.asset", "abcd_guidstring", "abcd")]
|
||||
[Test]
|
||||
public void BundledAssetGroupSchema_GetAssetLoadPath_Returns_ExpectedId(int imode, string assetPath, string guid, string expectedId)
|
||||
{
|
||||
var mode = (BundledAssetGroupSchema.AssetNamingMode)imode;
|
||||
var bas = Settings.DefaultGroup.GetSchema<BundledAssetGroupSchema>();
|
||||
bas.InternalIdNamingMode = mode;
|
||||
var actualId = bas.GetAssetLoadPath(assetPath, otherInternaIds, s => guid);
|
||||
Assert.AreEqual(expectedId, actualId);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InspectorGUI_GatherTargetinfo_AllAddressable()
|
||||
{
|
||||
string path1 = GetAssetPath("test.prefab");
|
||||
string guid1 = AssetDatabase.AssetPathToGUID(path1);
|
||||
Settings.CreateOrMoveEntry(guid1, Settings.DefaultGroup);
|
||||
string path2 = GetAssetPath("test 1.prefab");
|
||||
string guid2 = AssetDatabase.AssetPathToGUID(path2);
|
||||
Settings.CreateOrMoveEntry(guid2, Settings.DefaultGroup);
|
||||
|
||||
UnityEngine.Object[] targets = new UnityEngine.Object[2];
|
||||
targets[0] = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(path1);
|
||||
targets[1] = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(path2);
|
||||
var infos = UnityEditor.AddressableAssets.GUI.AddressableAssetInspectorGUI.GatherTargetInfos(targets, Settings);
|
||||
|
||||
Assert.AreEqual(2, infos.Count);
|
||||
Assert.NotNull(infos[0].MainAssetEntry);
|
||||
Assert.NotNull(infos[1].MainAssetEntry);
|
||||
|
||||
// clean up
|
||||
Settings.RemoveAssetEntry(guid1);
|
||||
Settings.RemoveAssetEntry(guid2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InspectorGUI_GatherTargetinfo_MixedAddressable()
|
||||
{
|
||||
string path1 = GetAssetPath("test.prefab");
|
||||
string guid1 = AssetDatabase.AssetPathToGUID(path1);
|
||||
Settings.CreateOrMoveEntry(guid1, Settings.DefaultGroup);
|
||||
string path2 = GetAssetPath("test 1.prefab");
|
||||
|
||||
UnityEngine.Object[] targets = new UnityEngine.Object[2];
|
||||
targets[0] = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(path1);
|
||||
targets[1] = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(path2);
|
||||
var infos = UnityEditor.AddressableAssets.GUI.AddressableAssetInspectorGUI.GatherTargetInfos(targets, Settings);
|
||||
|
||||
Assert.AreEqual(2, infos.Count);
|
||||
Assert.NotNull(infos[0].MainAssetEntry);
|
||||
Assert.IsNull(infos[1].MainAssetEntry);
|
||||
|
||||
// clean up
|
||||
Settings.RemoveAssetEntry(guid1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InspectorGUI_FindUniqueAssetGuids_CorrectAssetCount()
|
||||
{
|
||||
string path1 = GetAssetPath("test.prefab");
|
||||
string guid1 = AssetDatabase.AssetPathToGUID(path1);
|
||||
Settings.CreateOrMoveEntry(guid1, Settings.DefaultGroup);
|
||||
string path2 = GetAssetPath("test 1.prefab");
|
||||
|
||||
UnityEngine.Object[] targets = new UnityEngine.Object[2];
|
||||
targets[0] = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(path1);
|
||||
targets[1] = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(path2);
|
||||
var infos = UnityEditor.AddressableAssets.GUI.AddressableAssetInspectorGUI.GatherTargetInfos(targets, Settings);
|
||||
|
||||
Assert.AreEqual(2, infos.Count);
|
||||
Assert.NotNull(infos[0].MainAssetEntry);
|
||||
Assert.IsNull(infos[1].MainAssetEntry);
|
||||
|
||||
infos.Add(infos[0]);
|
||||
infos.Add(infos[1]);
|
||||
UnityEditor.AddressableAssets.GUI.AddressableAssetInspectorGUI.FindUniqueAssetGuids(infos, out var uniqueAssetGuids, out var uniqueAddressableAssetGuids);
|
||||
|
||||
Assert.AreEqual(2, uniqueAssetGuids.Count);
|
||||
Assert.AreEqual(1, uniqueAddressableAssetGuids.Count);
|
||||
|
||||
// clean up
|
||||
Settings.RemoveAssetEntry(guid1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GivenFunction_ParallelForEachAsync_ReturnsCompletedTask()
|
||||
{
|
||||
//two identical lists
|
||||
var originalNums = new List<int>() {1, 2, 3, 4, 5};
|
||||
var nums = new List<int>() {1, 2, 3, 4, 5};
|
||||
|
||||
//function modifies original list by adding one
|
||||
AddressableAssetUtility.ParallelForEachAsync(nums, 5, (num) =>
|
||||
{
|
||||
originalNums[num - 1] += 1;
|
||||
return Task.FromResult(originalNums[num - 1]);
|
||||
}).GetAwaiter().GetResult();
|
||||
|
||||
//validate that the modified number matches
|
||||
for (var i = 0; i < originalNums.Count; i++)
|
||||
{
|
||||
Assert.AreEqual(nums[i] + 1, originalNums[i]);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetMD5Hash_ReturnsValidMD5Hash()
|
||||
{
|
||||
const string FilePath = "test_file";
|
||||
var file = File.Create(FilePath);
|
||||
var content = "12345";
|
||||
var contentBytes = Encoding.ASCII.GetBytes(content);
|
||||
file.Write(contentBytes, 0, contentBytes.Length);
|
||||
file.Close();
|
||||
|
||||
var hashString = AddressableAssetUtility.GetMd5Hash(FilePath);
|
||||
File.Delete(FilePath);
|
||||
|
||||
Assert.NotNull(hashString);
|
||||
Assert.AreEqual("827ccb0eea8a706c4c34a16891f84e7b", hashString);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetPackageVersion_ReturnsAValidVersion()
|
||||
{
|
||||
string v = AddressableAssetUtility.GetVersionFromPackageData();
|
||||
Assert.IsTrue(v.StartsWith("1."), $"Failed to get a valid version from package.json data. Expected 1.X but was {v}");
|
||||
Assert.IsTrue(v.Split('.').Length == 2,
|
||||
$"Format from GetVersionFromPackageData, produced {v} which is incorrectly formatted");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SortedDelegate_InvokesMultipleRegisters()
|
||||
{
|
||||
AddressableAssetUtility.SortedDelegate<string[], string[], string[], string[]> handler =
|
||||
new AddressableAssetUtility.SortedDelegate<string[], string[], string[], string[]>();
|
||||
|
||||
calledOrder.Clear();
|
||||
handler.Register(Callback1, 0);
|
||||
handler.Register(Callback2, 0);
|
||||
handler.Invoke(null, null, null, null);
|
||||
Assert.AreEqual(2, calledOrder.Count, "Expected to have had two callbacks triggered");
|
||||
}
|
||||
|
||||
private List<int> calledOrder = new List<int>();
|
||||
|
||||
[Test]
|
||||
public void SortedDelegate_InvokesMultipleRegisters_CorrectOrder()
|
||||
{
|
||||
AddressableAssetUtility.SortedDelegate<string[], string[], string[], string[]> handler =
|
||||
new AddressableAssetUtility.SortedDelegate<string[], string[], string[], string[]>();
|
||||
|
||||
calledOrder.Clear();
|
||||
handler.Register(Callback1, 1);
|
||||
handler.Register(Callback2, 0);
|
||||
|
||||
handler.Invoke(null, null, null, null);
|
||||
Assert.AreEqual(2, calledOrder.Count, "Expected to have had two callbacks triggered");
|
||||
Assert.AreEqual(2, calledOrder[0], "Callback2 was expected to be called first, but was not");
|
||||
Assert.AreEqual(1, calledOrder[1], "Callback1 was expected to be called second, but was not");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SortedDelegate_InvokesMultipleRegisters_RemovesCallbacks()
|
||||
{
|
||||
AddressableAssetUtility.SortedDelegate<string[], string[], string[], string[]> handler =
|
||||
new AddressableAssetUtility.SortedDelegate<string[], string[], string[], string[]>();
|
||||
|
||||
calledOrder.Clear();
|
||||
handler.Register(Callback1, 0);
|
||||
handler.Register(Callback2, 0);
|
||||
handler.Invoke(null, null, null, null);
|
||||
Assert.AreEqual(2, calledOrder.Count, "Expected to have two callbacks Invoked");
|
||||
|
||||
calledOrder.Clear();
|
||||
handler.Unregister(Callback1);
|
||||
handler.Invoke(null, null, null, null);
|
||||
Assert.AreEqual(1, calledOrder.Count, "Expected to have one callbacks Invoked");
|
||||
|
||||
calledOrder.Clear();
|
||||
handler -= Callback2;
|
||||
handler.Invoke(null, null, null, null);
|
||||
Assert.AreEqual(0, calledOrder.Count, "Expected to have no callbacks Invoked");
|
||||
Assert.IsTrue(handler == null, "Equalto to return true to null when no callbacks are available"); // doesn't work with Assert.IsNull
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SortedDelegate_RegisterDuringInvocationDoesNotThrow()
|
||||
{
|
||||
var handler = new AddressableAssetUtility.SortedDelegate<string[], string[], string[], string[]>();
|
||||
|
||||
handler.Register((a, b, c, d) =>
|
||||
{
|
||||
Assert.DoesNotThrow(() => handler.Register(Callback1, 0));
|
||||
}, 0);
|
||||
|
||||
handler.Invoke(null, null, null, null);
|
||||
}
|
||||
|
||||
private void Callback1(string[] arg1, string[] arg2, string[] arg3, string[] arg4)
|
||||
{
|
||||
calledOrder.Add(1);
|
||||
}
|
||||
|
||||
private void Callback2(string[] arg1, string[] arg2, string[] arg3, string[] arg4)
|
||||
{
|
||||
calledOrder.Add(2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanMoveEntriesToGroup()
|
||||
{
|
||||
string guid1 = "guid1";
|
||||
string guid2 = "guid2";
|
||||
string guid3 = "guid3";
|
||||
var oldGroup = Settings.CreateGroup("MoveEntriesToGroup_Old", false, false, true, new List<AddressableAssetGroupSchema>());
|
||||
var newGroup = Settings.CreateGroup("MoveEntriesToGroup_New", false, false, true, new List<AddressableAssetGroupSchema>());
|
||||
|
||||
var entries = new List<AddressableAssetEntry>();
|
||||
entries.Add(Settings.CreateEntry(guid1, "addr1", oldGroup, false));
|
||||
entries.Add(Settings.CreateEntry(guid2, "addr2", oldGroup, false));
|
||||
entries.Add(Settings.CreateEntry(guid3, "addr3", oldGroup, false));
|
||||
|
||||
AddressableAssetUtility.MoveEntriesToGroup(Settings, entries, newGroup);
|
||||
|
||||
Assert.IsTrue(oldGroup.GetAssetEntry(guid1) == null);
|
||||
Assert.IsTrue(oldGroup.GetAssetEntry(guid2) == null);
|
||||
Assert.IsTrue(oldGroup.GetAssetEntry(guid3) == null);
|
||||
|
||||
Assert.IsTrue(newGroup.GetAssetEntry(guid1) != null);
|
||||
Assert.IsTrue(newGroup.GetAssetEntry(guid2) != null);
|
||||
Assert.IsTrue(newGroup.GetAssetEntry(guid3) != null);
|
||||
|
||||
Settings.RemoveGroup(oldGroup);
|
||||
Settings.RemoveGroup(newGroup);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ea375d4d72197e143ba4ebfe5d21ed7c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,108 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using NUnit.Framework;
|
||||
using UnityEditor.AddressableAssets.Settings;
|
||||
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
|
||||
using UnityEngine.TestTools;
|
||||
using UnityEditor.AddressableAssets.Build.DataBuilders;
|
||||
using UnityEditor.Build.Content;
|
||||
using BuildCompression = UnityEngine.BuildCompression;
|
||||
|
||||
namespace UnityEditor.AddressableAssets.Tests
|
||||
{
|
||||
public class AddressableAssetsBundleBuildParametersTests : AddressableAssetTestBase
|
||||
{
|
||||
protected override bool PersistSettings
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
static IEnumerable<Enum> GetValues(Type t)
|
||||
{
|
||||
List<Enum> enumerations = new List<Enum>();
|
||||
foreach (FieldInfo fieldInfo in t.GetFields(BindingFlags.Static | BindingFlags.Public))
|
||||
enumerations.Add((Enum)fieldInfo.GetValue(null));
|
||||
return enumerations;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenNonRecursiveBuildingSet_BuildParametersHaveCorrectValue()
|
||||
{
|
||||
#if !NONRECURSIVE_DEPENDENCY_DATA
|
||||
Assert.Ignore($"Skipping test {nameof(WhenNonRecursiveBuildingSet_BuildParametersHaveCorrectValue)}.");
|
||||
#else
|
||||
var bundleToAssetGroup = new Dictionary<string, string>();
|
||||
|
||||
Settings.NonRecursiveBuilding = true;
|
||||
var testParams = new AddressableAssetsBundleBuildParameters(Settings, bundleToAssetGroup, BuildTarget.StandaloneWindows64, BuildTargetGroup.Standalone, "Unused");
|
||||
Assert.AreEqual(testParams.NonRecursiveDependencies, Settings.NonRecursiveBuilding);
|
||||
|
||||
Settings.NonRecursiveBuilding = false;
|
||||
testParams = new AddressableAssetsBundleBuildParameters(Settings, bundleToAssetGroup, BuildTarget.StandaloneWindows64, BuildTargetGroup.Standalone, "Unused");
|
||||
Assert.AreEqual(testParams.NonRecursiveDependencies, Settings.NonRecursiveBuilding);
|
||||
#endif
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenCompressionSetForGroups_GetCompressionForIdentifier_ReturnsExpectedCompression()
|
||||
{
|
||||
var bundleToAssetGroup = new Dictionary<string, string>();
|
||||
var expectedValues = new BuildCompression[] {BuildCompression.Uncompressed, BuildCompression.LZ4, BuildCompression.LZMA, BuildCompression.UncompressedRuntime, BuildCompression.LZ4Runtime};
|
||||
var bundleNames = new List<string>();
|
||||
|
||||
foreach (var en in GetValues(typeof(BundledAssetGroupSchema.BundleCompressionMode)))
|
||||
{
|
||||
var g = Settings.CreateGroup(en.ToString(), true, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
g.GetSchema<BundledAssetGroupSchema>().Compression = (BundledAssetGroupSchema.BundleCompressionMode)en;
|
||||
var bName = "bundle_" + en;
|
||||
bundleToAssetGroup.Add(bName, g.Guid);
|
||||
bundleNames.Add(bName);
|
||||
}
|
||||
|
||||
var testParams = new AddressableAssetsBundleBuildParameters(Settings, bundleToAssetGroup, BuildTarget.StandaloneWindows64, BuildTargetGroup.Standalone, "Unused");
|
||||
|
||||
for (int i = 0; i < bundleNames.Count; i++)
|
||||
{
|
||||
var comp = testParams.GetCompressionForIdentifier(bundleNames[i]);
|
||||
Assert.AreEqual(expectedValues[i].blockSize, comp.blockSize);
|
||||
Assert.AreEqual(expectedValues[i].compression, comp.compression);
|
||||
Assert.AreEqual(expectedValues[i].level, comp.level);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(true)]
|
||||
[TestCase(false)]
|
||||
public void StripUnityVersion_SetsBuildFlagCorrectly(bool stripUnityVersion)
|
||||
{
|
||||
bool oldValue = Settings.StripUnityVersionFromBundleBuild;
|
||||
Settings.StripUnityVersionFromBundleBuild = stripUnityVersion;
|
||||
|
||||
var testParams = new AddressableAssetsBundleBuildParameters(Settings, new Dictionary<string, string>(),
|
||||
BuildTarget.StandaloneWindows64, BuildTargetGroup.Standalone, "Unused");
|
||||
|
||||
var buildSettings = testParams.GetContentBuildSettings();
|
||||
|
||||
Assert.AreEqual(stripUnityVersion, (buildSettings.buildFlags & ContentBuildFlags.StripUnityVersion) != 0);
|
||||
|
||||
Settings.StripUnityVersionFromBundleBuild = oldValue;
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(true)]
|
||||
[TestCase(false)]
|
||||
public void WhenDisableVisibleSubAssetRepresentationsSet_BuildParametersHaveCorrectValue(bool disableVisibleSubAssetRepresentations)
|
||||
{
|
||||
bool oldValue = Settings.DisableVisibleSubAssetRepresentations;
|
||||
Settings.DisableVisibleSubAssetRepresentations = disableVisibleSubAssetRepresentations;
|
||||
|
||||
var testParams = new AddressableAssetsBundleBuildParameters(Settings, new Dictionary<string, string>(),
|
||||
BuildTarget.StandaloneWindows64, BuildTargetGroup.Standalone, "Unused");
|
||||
|
||||
Assert.AreEqual(disableVisibleSubAssetRepresentations, testParams.DisableVisibleSubAssetRepresentations);
|
||||
|
||||
Settings.DisableVisibleSubAssetRepresentations = oldValue;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bb04252b53f48b349a901615af6a84fe
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,135 @@
|
|||
using NUnit.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEditor.AddressableAssets.GUI;
|
||||
using UnityEditor.AddressableAssets.Settings;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.AddressableAssets.Tests
|
||||
{
|
||||
public class AddressableAssetWindowTests : AddressableAssetTestBase
|
||||
{
|
||||
[Test]
|
||||
public void AddressableAssetWindow_OfferToConvert_CantConvertWithNoBundles()
|
||||
{
|
||||
AddressableAssetsWindow aaWindow = ScriptableObject.CreateInstance<AddressableAssetsWindow>();
|
||||
var prevGroupCount = Settings.groups.Count;
|
||||
aaWindow.OfferToConvert(Settings);
|
||||
Assert.AreEqual(prevGroupCount, Settings.groups.Count);
|
||||
Object.DestroyImmediate(aaWindow);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddressableAssetWindow_SimplifyAddress_ReturnsFileNameOnly()
|
||||
{
|
||||
string assetPath = AssetDatabase.GUIDToAssetPath(m_AssetGUID);
|
||||
var entry = Settings.CreateOrMoveEntry(m_AssetGUID, Settings.DefaultGroup);
|
||||
Assert.AreEqual(assetPath, entry.address);
|
||||
|
||||
AddressableAssetEntryTreeView treeView = new AddressableAssetEntryTreeView(Settings);
|
||||
treeView.SimplifyAddressesImpl(new List<AssetEntryTreeViewItem>() {new AssetEntryTreeViewItem(entry, 1)});
|
||||
|
||||
Assert.AreEqual(Path.GetFileNameWithoutExtension(assetPath), entry.address);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddressableAssetWindow_RemovedEntries_AreNoLongerPresent()
|
||||
{
|
||||
var entry = Settings.CreateOrMoveEntry(m_AssetGUID, Settings.DefaultGroup);
|
||||
|
||||
AddressableAssetEntryTreeView treeView = new AddressableAssetEntryTreeView(Settings);
|
||||
treeView.RemoveEntryImpl(new List<AssetEntryTreeViewItem>() {new AssetEntryTreeViewItem(entry, 1)}, true);
|
||||
|
||||
Assert.IsNull(Settings.FindAssetEntry(m_AssetGUID));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddressableAssetWindow_RemoveGroup_GroupGetsRemovedCorrectly()
|
||||
{
|
||||
var group = Settings.CreateGroup("RemoveMeGroup", false, false, true, new List<AddressableAssetGroupSchema>());
|
||||
AddressableAssetEntryTreeView treeView = new AddressableAssetEntryTreeView(Settings);
|
||||
treeView.RemoveGroupImpl(new List<AssetEntryTreeViewItem>() {new AssetEntryTreeViewItem(group, 1)}, true);
|
||||
Assert.IsNull(Settings.FindGroup("RemoveMeGroup"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddressableAssetWindow_RemoveMissingReferences_RemovesAllNullReferences()
|
||||
{
|
||||
Settings.groups.Add(null);
|
||||
Settings.groups.Add(null);
|
||||
|
||||
AddressableAssetEntryTreeView treeView = new AddressableAssetEntryTreeView(Settings);
|
||||
treeView.RemoveMissingReferencesImpl();
|
||||
foreach (var group in Settings.groups)
|
||||
Assert.IsNotNull(group);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddressableAssetWindow_SetDefaultGroup_SetsTheSpecifiedGroupToDefault()
|
||||
{
|
||||
var savedDefaultGroup = Settings.DefaultGroup;
|
||||
var newDefaultGroup = Settings.CreateGroup("NewDefaultGroup", false, false, true, new List<AddressableAssetGroupSchema>());
|
||||
AddressableAssetEntryTreeView treeView = new AddressableAssetEntryTreeView(Settings);
|
||||
|
||||
treeView.SetGroupAsDefault(new List<AssetEntryTreeViewItem>() {new AssetEntryTreeViewItem(newDefaultGroup, 1)});
|
||||
|
||||
Assert.AreEqual(newDefaultGroup, Settings.DefaultGroup);
|
||||
|
||||
Settings.DefaultGroup = savedDefaultGroup;
|
||||
Settings.RemoveGroup(newDefaultGroup);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddressableAssetWindow_CanSelectGroupTreeViewByAddressableAssetEntries()
|
||||
{
|
||||
//Setup
|
||||
var defaultGroup = Settings.DefaultGroup;
|
||||
Assert.IsNotNull(defaultGroup, "Default Group is not found");
|
||||
ProjectConfigData.ShowSubObjectsInGroupView = true;
|
||||
|
||||
string path0 = GetAssetPath("test.prefab");
|
||||
string p0 = AssetDatabase.AssetPathToGUID(path0);
|
||||
Assert.IsFalse(string.IsNullOrEmpty(p0), "Could not setup for Asset \"test.prefab\"");
|
||||
Texture t = new Texture2D(4, 4);
|
||||
t.name = "tex";
|
||||
AssetDatabase.AddObjectToAsset(t, path0);
|
||||
AssetDatabase.SaveAssets();
|
||||
string p1 = AssetDatabase.AssetPathToGUID(GetAssetPath("test 1.prefab"));
|
||||
Assert.IsFalse(string.IsNullOrEmpty(p1), "Could not setup for Asset \"test 1.prefab\"");
|
||||
string p2 = AssetDatabase.AssetPathToGUID(GetAssetPath("test 2.prefab"));
|
||||
Assert.IsFalse(string.IsNullOrEmpty(p2), "Could not setup for Asset \"test 2.prefab\"");
|
||||
|
||||
var e0 = Settings.CreateOrMoveEntry(p0, defaultGroup);
|
||||
List<AddressableAssetEntry> gathered = new List<AddressableAssetEntry>();
|
||||
e0.GatherAllAssets(gathered, false, true, true);
|
||||
Assert.AreEqual(1, gathered.Count, "Incorrect subObject count for Asset at " + path0);
|
||||
|
||||
var e1 = Settings.CreateOrMoveEntry(p1, defaultGroup);
|
||||
var e2 = Settings.CreateOrMoveEntry(p2, defaultGroup);
|
||||
|
||||
AddressableAssetsWindow aaWindow = ScriptableObject.CreateInstance<AddressableAssetsWindow>();
|
||||
aaWindow.m_GroupEditor = new AddressableAssetsSettingsGroupEditor(aaWindow);
|
||||
aaWindow.m_GroupEditor.OnDisable();
|
||||
aaWindow.m_GroupEditor.settings = Settings;
|
||||
var entryTree = aaWindow.m_GroupEditor.InitialiseEntryTree();
|
||||
|
||||
//Test
|
||||
Assert.AreEqual(0, entryTree.GetSelection().Count, "entryTree is not expected to have anything select at creation");
|
||||
aaWindow.SelectAssetsInGroupEditor(new List<AddressableAssetEntry>() {e1});
|
||||
Assert.AreEqual(1, entryTree.GetSelection().Count, "Expecting to have \"test 1.prefab\" selected.");
|
||||
aaWindow.SelectAssetsInGroupEditor(new List<AddressableAssetEntry>() {e2});
|
||||
Assert.AreEqual(1, entryTree.GetSelection().Count, "Expecting to have \"test 2.prefab\" selected.");
|
||||
aaWindow.SelectAssetsInGroupEditor(new List<AddressableAssetEntry>() {e1, e2});
|
||||
Assert.AreEqual(2, entryTree.GetSelection().Count, "Expecting to have \"test 1.prefab\" and \"test 2.prefab\" selected.");
|
||||
|
||||
Assert.IsTrue(ProjectConfigData.ShowSubObjectsInGroupView, "Need to display subObjects to test that they are being shown");
|
||||
aaWindow.SelectAssetsInGroupEditor(new List<AddressableAssetEntry>() {gathered[0]});
|
||||
Assert.AreEqual(1, entryTree.GetSelection().Count, "Expecting to have \"test.prefab[SubObject]\" selected.");
|
||||
|
||||
//Cleanup
|
||||
Assert.IsTrue(Settings.RemoveAssetEntry(e1, false), "Failed to cleanup AssetEntry \"test 1.prefab\" from test settings.");
|
||||
Assert.IsTrue(Settings.RemoveAssetEntry(e2, false), "Failed to cleanup AssetEntry \"test 2.prefab\" from test settings.");
|
||||
Object.DestroyImmediate(aaWindow);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7ba37647c6bae7846b28d56e45adee11
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: cf99c4b78a1e287498efd1df562f6347
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,141 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using NUnit.Framework;
|
||||
using UnityEditor.AddressableAssets.Build;
|
||||
using UnityEditor.AddressableAssets.Build.AnalyzeRules;
|
||||
using UnityEditor.AddressableAssets.Build.BuildPipelineTasks;
|
||||
using UnityEditor.AddressableAssets.Build.DataBuilders;
|
||||
using UnityEditor.AddressableAssets.Settings;
|
||||
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
|
||||
using UnityEditor.AddressableAssets.Tests;
|
||||
using UnityEditor.Build.Pipeline;
|
||||
using UnityEditor.Build.Pipeline.Injector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.AddressableAssets.Tests.AnalyzeRules
|
||||
{
|
||||
[TestFixture]
|
||||
public class AnalyzeRuleBaseTests : AddressableAssetTestBase
|
||||
{
|
||||
[Test]
|
||||
public void ConvertBundleNamesToGroupNames()
|
||||
{
|
||||
var bundleName = "2398471298347129034_bundlename_1";
|
||||
var fakeFileName = "archive://3912983hf9sdf902340jidf";
|
||||
var convertedBundleName = "group1_bundlename_1";
|
||||
|
||||
var group = Settings.CreateGroup("group1", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
|
||||
AddressableAssetsBuildContext context = new AddressableAssetsBuildContext();
|
||||
context.Settings = Settings;
|
||||
context.assetGroupToBundles = new Dictionary<AddressableAssetGroup, List<string>>()
|
||||
{
|
||||
{group, new List<string>() {bundleName}}
|
||||
};
|
||||
|
||||
BundleRuleBase baseRule = new BundleRuleBase();
|
||||
baseRule.m_ExtractData = new ExtractDataTask();
|
||||
|
||||
var field = typeof(ExtractDataTask).GetField("m_WriteData", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
field.SetValue(baseRule.m_ExtractData, new BundleWriteData());
|
||||
|
||||
baseRule.m_AllBundleInputDefs.Add(new AssetBundleBuild()
|
||||
{
|
||||
assetBundleName = bundleName
|
||||
});
|
||||
|
||||
baseRule.m_ExtractData.WriteData.FileToBundle.Add(fakeFileName, bundleName);
|
||||
baseRule.ConvertBundleNamesToGroupNames(context);
|
||||
|
||||
Assert.AreEqual(convertedBundleName, baseRule.m_ExtractData.WriteData.FileToBundle[fakeFileName]);
|
||||
|
||||
Settings.RemoveGroup(group);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BaseAnalyzeRule_DoesNotThrowOnFix()
|
||||
{
|
||||
BundleRuleBase baseRule = new BundleRuleBase();
|
||||
Assert.DoesNotThrow(() => baseRule.FixIssues(Settings));
|
||||
}
|
||||
|
||||
class TestBaseRule : BundleRuleBase
|
||||
{
|
||||
public override string ruleName => "TestBaseRule";
|
||||
}
|
||||
|
||||
class TestInheritedRule : TestBaseRule
|
||||
{
|
||||
public override string ruleName => "TestInheritedRule";
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AnalyzeSystem_CanRegisterInheritedRule()
|
||||
{
|
||||
int currentCount = AnalyzeSystem.Rules.Count;
|
||||
|
||||
AnalyzeSystem.RegisterNewRule<TestBaseRule>();
|
||||
AnalyzeSystem.RegisterNewRule<TestInheritedRule>();
|
||||
|
||||
Assert.AreEqual(currentCount + 2, AnalyzeSystem.Rules.Count);
|
||||
Assert.AreEqual(typeof(TestBaseRule), AnalyzeSystem.Rules[currentCount].GetType());
|
||||
Assert.AreEqual(typeof(TestInheritedRule), AnalyzeSystem.Rules[currentCount + 1].GetType());
|
||||
|
||||
AnalyzeSystem.Rules.RemoveAt(currentCount + 1);
|
||||
AnalyzeSystem.Rules.RemoveAt(currentCount);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AnalyzeSystem_CannotRegisterDuplicateRule()
|
||||
{
|
||||
int currentCount = AnalyzeSystem.Rules.Count;
|
||||
|
||||
AnalyzeSystem.RegisterNewRule<TestBaseRule>();
|
||||
AnalyzeSystem.RegisterNewRule<TestBaseRule>();
|
||||
Assert.AreEqual(currentCount + 1, AnalyzeSystem.Rules.Count);
|
||||
|
||||
AnalyzeSystem.Rules.RemoveAt(currentCount);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AnalyzeSystem_CanSaveAndLoad()
|
||||
{
|
||||
string path = GetAssetPath("analysis.json");
|
||||
if (File.Exists(path))
|
||||
File.Delete(path);
|
||||
|
||||
int currentCount = AnalyzeSystem.Rules.Count;
|
||||
AnalyzeSystem.RegisterNewRule<TestBaseRule>();
|
||||
AnalyzeSystem.ClearAnalysis<TestBaseRule>();
|
||||
try
|
||||
{
|
||||
AnalyzeSystem.SerializeData(path);
|
||||
Assert.IsTrue(File.Exists(path));
|
||||
string json = File.ReadAllText(path);
|
||||
Assert.IsTrue(json.Contains("\"RuleName\":\"TestBaseRule\",\"Results\":[]"));
|
||||
json = json.Replace("\"TestBaseRule\",\"Results\":[", "\"TestBaseRule\",\"Results\":[{\"m_ResultName\":\"someFakeResult\",\"m_Severity\":0}");
|
||||
File.WriteAllText(path, json);
|
||||
|
||||
AnalyzeSystem.AnalyzeData.Data.TryGetValue(
|
||||
"TestBaseRule", out var results);
|
||||
Assert.IsFalse(results.Any(r => r.resultName == "someFakeResult"));
|
||||
|
||||
AnalyzeSystem.DeserializeData(path);
|
||||
Assert.IsTrue(AnalyzeSystem.AnalyzeData.Data.TryGetValue(
|
||||
"TestBaseRule", out results));
|
||||
Assert.IsTrue(results.Count > 0);
|
||||
Assert.AreEqual("someFakeResult", results[0].resultName);
|
||||
}
|
||||
finally
|
||||
{
|
||||
//cleanup
|
||||
AnalyzeSystem.Rules.RemoveAt(currentCount);
|
||||
if (File.Exists(path))
|
||||
File.Delete(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 774cd729e4d232a45a38ea35fed32c81
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,331 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using NUnit.Framework;
|
||||
using UnityEditor.AddressableAssets.Build;
|
||||
using UnityEditor.AddressableAssets.Build.AnalyzeRules;
|
||||
using UnityEditor.AddressableAssets.Build.DataBuilders;
|
||||
using UnityEditor.AddressableAssets.GUI;
|
||||
using UnityEditor.AddressableAssets.Settings;
|
||||
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
|
||||
using UnityEditor.Build.Pipeline;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets.Initialization;
|
||||
|
||||
namespace UnityEditor.AddressableAssets.Tests.AnalyzeRules
|
||||
{
|
||||
class CheckBundleDupeDependencyTests : AddressableAssetTestBase
|
||||
{
|
||||
string k_CheckDupePrefabA => GetAssetPath("checkDupe_prefabA.prefab");
|
||||
string k_CheckDupePrefabB => GetAssetPath("checkDupe_prefabB.prefab");
|
||||
string k_CheckDupeMyMaterial => GetAssetPath("checkDupe_myMaterial.mat");
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
base.OnInit();
|
||||
|
||||
GameObject prefabA = new GameObject("PrefabA");
|
||||
GameObject prefabB = new GameObject("PrefabB");
|
||||
var meshA = prefabA.AddComponent<MeshRenderer>();
|
||||
var meshB = prefabB.AddComponent<MeshRenderer>();
|
||||
|
||||
|
||||
var mat = new Material(Shader.Find("Unlit/Color"));
|
||||
AssetDatabase.CreateAsset(mat, k_CheckDupeMyMaterial);
|
||||
meshA.sharedMaterial = mat;
|
||||
meshB.sharedMaterial = mat;
|
||||
|
||||
PrefabUtility.SaveAsPrefabAsset(prefabA, k_CheckDupePrefabA);
|
||||
PrefabUtility.SaveAsPrefabAsset(prefabB, k_CheckDupePrefabB);
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
private AddressableAssetsBuildContext GetAddressableAssetsBuildContext(CheckBundleDupeDependencies rule)
|
||||
{
|
||||
ResourceManagerRuntimeData runtimeData = new ResourceManagerRuntimeData();
|
||||
runtimeData.LogResourceManagerExceptions = Settings.buildSettings.LogResourceManagerExceptions;
|
||||
var aaContext = new AddressableAssetsBuildContext
|
||||
{
|
||||
Settings = Settings,
|
||||
runtimeData = runtimeData,
|
||||
bundleToAssetGroup = rule.m_BundleToAssetGroup,
|
||||
locations = rule.m_Locations,
|
||||
assetEntries = new List<AddressableAssetEntry>()
|
||||
};
|
||||
return aaContext;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CheckDupeCanFixIssues()
|
||||
{
|
||||
var duplicateGroups = Settings.groups.Where(group => group.Name.Contains("Duplicate Asset Isolation"));
|
||||
foreach (AddressableAssetGroup group in duplicateGroups)
|
||||
Settings.groups.Remove(group);
|
||||
|
||||
var group1 = Settings.CreateGroup("CheckDupeDepencency1", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
var group2 = Settings.CreateGroup("CheckDupeDepencency2", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
|
||||
Settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(k_CheckDupePrefabA), group1, false, false);
|
||||
Settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(k_CheckDupePrefabB), group2, false, false);
|
||||
|
||||
var matGuid = AssetDatabase.AssetPathToGUID(k_CheckDupeMyMaterial);
|
||||
Assert.IsNull(group1.GetAssetEntry(matGuid));
|
||||
Assert.IsNull(group2.GetAssetEntry(matGuid));
|
||||
|
||||
var groupCount = Settings.groups.Count;
|
||||
|
||||
var rule = new CheckBundleDupeDependencies();
|
||||
rule.FixIssues(Settings);
|
||||
|
||||
Assert.AreEqual(groupCount + 1, Settings.groups.Count);
|
||||
|
||||
var dupeGroup = Settings.FindGroup("Duplicate Asset Isolation");
|
||||
Assert.IsNotNull(dupeGroup);
|
||||
Assert.IsNotNull(dupeGroup.GetAssetEntry(matGuid));
|
||||
|
||||
//Cleanup
|
||||
Settings.RemoveGroup(group1);
|
||||
Settings.RemoveGroup(group2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CheckDupeNoIssuesIfValid()
|
||||
{
|
||||
var group1 = Settings.CreateGroup("CheckDupeDepencency1", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
var group2 = Settings.CreateGroup("CheckDupeDepencency2", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
|
||||
Settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(k_CheckDupePrefabA), group1, false, false);
|
||||
Settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(k_CheckDupePrefabB), group2, false, false);
|
||||
Settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(k_CheckDupeMyMaterial), group2, false, false);
|
||||
|
||||
var groupCount = Settings.groups.Count;
|
||||
|
||||
var rule = new CheckBundleDupeDependencies();
|
||||
rule.FixIssues(Settings);
|
||||
|
||||
Assert.AreEqual(groupCount, Settings.groups.Count);
|
||||
|
||||
//Cleanup
|
||||
Settings.RemoveGroup(group1);
|
||||
Settings.RemoveGroup(group2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UniqueAssetBundleBuild_IsCreatedWithCorrectData()
|
||||
{
|
||||
string bundleName = "myBundleName.bundle";
|
||||
string assetGroup = "assetGroup";
|
||||
|
||||
var rule = new CheckBundleDupeDependencies();
|
||||
rule.m_BundleToAssetGroup.Add(bundleName, assetGroup);
|
||||
|
||||
AssetBundleBuild build = new AssetBundleBuild {assetBundleName = bundleName};
|
||||
|
||||
for (int i = 1; i < 500; i++)
|
||||
{
|
||||
AssetBundleBuild uniqueBundle = rule.CreateUniqueBundle(build);
|
||||
Assert.AreEqual(string.Format("myBundleName{0}.bundle", i), uniqueBundle.assetBundleName);
|
||||
rule.m_BundleToAssetGroup.Add(uniqueBundle.assetBundleName, assetGroup);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RefreshBuild_ReturnsSuccess()
|
||||
{
|
||||
var rule = new CheckBundleDupeDependencies();
|
||||
AddressableAssetsBuildContext context = GetAddressableAssetsBuildContext(rule);
|
||||
Assert.AreEqual(ReturnCode.Success, rule.RefreshBuild(context));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildImplicitDuplicatedAssetsSet_BuildCorrectImplicitAssets()
|
||||
{
|
||||
//Setup
|
||||
var group1 = Settings.CreateGroup("CheckDupeDepencency1", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
var group2 = Settings.CreateGroup("CheckDupeDepencency2", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
|
||||
Settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(k_CheckDupePrefabA), group1, false, false);
|
||||
Settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(k_CheckDupePrefabB), group2, false, false);
|
||||
|
||||
GUID matGuid;
|
||||
var matGuidString = AssetDatabase.AssetPathToGUID(k_CheckDupeMyMaterial);
|
||||
GUID.TryParse(matGuidString, out matGuid);
|
||||
|
||||
var rule = new CheckBundleDupeDependencies();
|
||||
var buildContext = rule.GetBuildContext(Settings);
|
||||
|
||||
rule.CalculateInputDefinitions(Settings);
|
||||
rule.RefreshBuild(buildContext);
|
||||
|
||||
var implicitGuids = rule.GetImplicitGuidToFilesMap();
|
||||
var results = rule.CalculateDuplicates(implicitGuids, buildContext);
|
||||
|
||||
//Test
|
||||
rule.BuildImplicitDuplicatedAssetsSet(results);
|
||||
|
||||
//Assert
|
||||
Assert.AreEqual(1, rule.m_ImplicitAssets.Count);
|
||||
Assert.IsTrue(rule.m_ImplicitAssets.Contains(matGuid));
|
||||
|
||||
//Cleanup
|
||||
Settings.RemoveGroup(group1);
|
||||
Settings.RemoveGroup(group2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CalculateDuplicates_DoesNotIncludeSameBundleReferencedMultipleTimes()
|
||||
{
|
||||
//Setup
|
||||
var group1 = Settings.CreateGroup("CheckDupeDepencency1", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
|
||||
Settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(k_CheckDupePrefabA), group1, false, false);
|
||||
|
||||
var rule = new CheckBundleDupeDependencies();
|
||||
var buildContext = rule.GetBuildContext(Settings);
|
||||
|
||||
rule.CalculateInputDefinitions(Settings);
|
||||
rule.RefreshBuild(buildContext);
|
||||
|
||||
var implicitGuids = rule.GetImplicitGuidToFilesMap();
|
||||
var key = implicitGuids.Keys.First();
|
||||
implicitGuids[key].Add(implicitGuids[key][0]);
|
||||
|
||||
//Test
|
||||
var results = rule.CalculateDuplicates(implicitGuids, buildContext).ToList();
|
||||
|
||||
//Assert
|
||||
Assert.AreEqual(0, results.Count);
|
||||
|
||||
//Cleanup
|
||||
Settings.RemoveGroup(group1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CalculateInputDefinitions_CalculatesAllInputDefintions()
|
||||
{
|
||||
//Setup
|
||||
var group1 = Settings.CreateGroup("CheckDupeDepencency1", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
var group2 = Settings.CreateGroup("CheckDupeDepencency2", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
|
||||
Settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(k_CheckDupePrefabA), group1, false, false);
|
||||
Settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(k_CheckDupePrefabB), group2, false, false);
|
||||
|
||||
GUID matGuid;
|
||||
var matGuidString = AssetDatabase.AssetPathToGUID(k_CheckDupeMyMaterial);
|
||||
GUID.TryParse(matGuidString, out matGuid);
|
||||
|
||||
var rule = new CheckBundleDupeDependencies();
|
||||
|
||||
//Test
|
||||
rule.CalculateInputDefinitions(Settings);
|
||||
|
||||
//Assert
|
||||
Assert.AreEqual(2, rule.m_AllBundleInputDefs.Count);
|
||||
|
||||
//Cleanup
|
||||
Settings.RemoveGroup(group1);
|
||||
Settings.RemoveGroup(group2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CalculateDuplicates_ReturnsCorrectCheckDupeResultList()
|
||||
{
|
||||
//Setup
|
||||
var group1 = Settings.CreateGroup("CheckDupeDepencency1", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
var group2 = Settings.CreateGroup("CheckDupeDepencency2", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
|
||||
Settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(k_CheckDupePrefabA), group1, false, false);
|
||||
Settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(k_CheckDupePrefabB), group2, false, false);
|
||||
|
||||
GUID matGuid;
|
||||
var matGuidString = AssetDatabase.AssetPathToGUID(k_CheckDupeMyMaterial);
|
||||
GUID.TryParse(matGuidString, out matGuid);
|
||||
|
||||
var rule = new CheckBundleDupeDependencies();
|
||||
|
||||
var buildContext = rule.GetBuildContext(Settings);
|
||||
rule.CalculateInputDefinitions(Settings);
|
||||
rule.RefreshBuild(buildContext);
|
||||
var implicitGuids = rule.GetImplicitGuidToFilesMap();
|
||||
|
||||
//Test
|
||||
var dupeResults = rule.CalculateDuplicates(implicitGuids, buildContext).ToList();
|
||||
|
||||
//Assert
|
||||
Assert.AreEqual(2, dupeResults.Count);
|
||||
|
||||
Assert.AreEqual(group1.Name, dupeResults[0].Group.Name);
|
||||
Assert.AreEqual(k_CheckDupeMyMaterial, dupeResults[0].AssetPath);
|
||||
|
||||
Assert.AreEqual(group2.Name, dupeResults[1].Group.Name);
|
||||
Assert.AreEqual(k_CheckDupeMyMaterial, dupeResults[1].AssetPath);
|
||||
|
||||
//Cleanup
|
||||
Settings.RemoveGroup(group1);
|
||||
Settings.RemoveGroup(group2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DupeGroupHasContentUpdateSchema()
|
||||
{
|
||||
//Setup
|
||||
var group1 = Settings.CreateGroup("CheckDupeDepencency1", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
var group2 = Settings.CreateGroup("CheckDupeDepencency2", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
|
||||
Settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(k_CheckDupePrefabA), group1, false, false);
|
||||
Settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(k_CheckDupePrefabB), group2, false, false);
|
||||
|
||||
var rule = new CheckBundleDupeDependencies();
|
||||
|
||||
//Test
|
||||
rule.FixIssues(Settings);
|
||||
AddressableAssetGroup group = Settings.FindGroup("Duplicate Asset Isolation");
|
||||
|
||||
//Assert
|
||||
Assert.IsNotNull(group);
|
||||
Assert.IsTrue(group.HasSchema<ContentUpdateGroupSchema>());
|
||||
Assert.IsTrue(group.GetSchema<ContentUpdateGroupSchema>().StaticContent);
|
||||
|
||||
//Cleanup
|
||||
Settings.RemoveGroup(group);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CheckForDuplicateDependencies_WorksWithNoAddressableAssets()
|
||||
{
|
||||
//Setup
|
||||
var settings = AddressableAssetSettings.Create(ConfigFolder, k_TestConfigName + "_NoAssets", false, false);
|
||||
//Test
|
||||
var rule = new CheckBundleDupeDependencies();
|
||||
//Assert
|
||||
Assert.DoesNotThrow(() => rule.FixIssues(settings));
|
||||
}
|
||||
|
||||
#if CI_TESTRUNNER_PROJECT
|
||||
[Test]
|
||||
public void GatherModifiedEntriesOnDupeGroup_DoesNotThrow()
|
||||
{
|
||||
//Setup
|
||||
var group1 = Settings.CreateGroup("CheckDupeDepencency1", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
var group2 = Settings.CreateGroup("CheckDupeDepencency2", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
|
||||
Settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(k_CheckDupePrefabA), group1, false, false);
|
||||
Settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(k_CheckDupePrefabB), group2, false, false);
|
||||
|
||||
var rule = new CheckBundleDupeDependencies();
|
||||
|
||||
//Test
|
||||
rule.FixIssues(Settings);
|
||||
|
||||
var path = "Assets/addressables_content_state.bin";
|
||||
Assert.DoesNotThrow(() =>
|
||||
{
|
||||
ContentUpdateScript.GatherModifiedEntries(Settings, path);
|
||||
});
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6719223fb1e7d804091db79ce4200b50
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,113 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using NUnit.Framework;
|
||||
using UnityEditor.AddressableAssets.Build.AnalyzeRules;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.AddressableAssets.Tests.AnalyzeRules
|
||||
{
|
||||
public class CheckResourcesDupeDependenciesTests : AddressableAssetTestBase
|
||||
{
|
||||
string k_CheckDupePrefabA => GetAssetPath("checkDupe_prefabA.prefab");
|
||||
string k_CheckDupePrefabB => GetAssetPath("checkDupe_prefabB.prefab");
|
||||
string k_CheckDupeMyMaterial => GetAssetPath("checkDupe_myMaterial.mat");
|
||||
string k_PrefabWithMaterialPath => GetAssetPath("checkDupe_prefabWithMaterial.prefab");
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
base.OnInit();
|
||||
|
||||
GameObject prefabA = new GameObject("PrefabA");
|
||||
GameObject prefabB = new GameObject("PrefabB");
|
||||
GameObject prefabWithMaterial = new GameObject("PrefabWithMaterial");
|
||||
var meshA = prefabA.AddComponent<MeshRenderer>();
|
||||
var meshB = prefabB.AddComponent<MeshRenderer>();
|
||||
|
||||
var mat = new Material(Shader.Find("Unlit/Color"));
|
||||
AssetDatabase.CreateAsset(mat, k_CheckDupeMyMaterial);
|
||||
meshA.sharedMaterial = mat;
|
||||
meshB.sharedMaterial = mat;
|
||||
|
||||
var meshPrefabWithMaterial = prefabWithMaterial.AddComponent<MeshRenderer>();
|
||||
meshPrefabWithMaterial.material = AssetDatabase.LoadAssetAtPath<Material>(k_CheckDupeMyMaterial);
|
||||
|
||||
PrefabUtility.SaveAsPrefabAsset(prefabA, k_CheckDupePrefabA);
|
||||
PrefabUtility.SaveAsPrefabAsset(prefabB, k_CheckDupePrefabB);
|
||||
PrefabUtility.SaveAsPrefabAsset(prefabWithMaterial, k_PrefabWithMaterialPath);
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CheckResourcesDupe_GetsCorrectResourcePaths()
|
||||
{
|
||||
string resourcesPath = GetAssetPath("Resources");
|
||||
if (!Directory.Exists(resourcesPath))
|
||||
Directory.CreateDirectory(resourcesPath);
|
||||
string prefabPath = GetAssetPath("Resources/PrefabA.prefab");
|
||||
GameObject prefabA = new GameObject("PrefabA");
|
||||
PrefabUtility.SaveAsPrefabAsset(prefabA, prefabPath);
|
||||
|
||||
var rule = new CheckResourcesDupeDependencies();
|
||||
var paths = rule.GetResourcePaths();
|
||||
bool success = false;
|
||||
foreach (var p in paths)
|
||||
{
|
||||
if (p.EndsWith("PrefabA.prefab"))
|
||||
{
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Assert.IsTrue(success, "CheckResourcesDupeDependencies ResourcePaths did not find the created prefab for test as expect.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CheckResourcesDupe_ResourcesDependenciesMatchWithExplicitBundleDependencies()
|
||||
{
|
||||
var rule = new CheckResourcesDupeDependencies();
|
||||
rule.BuiltInResourcesToDependenciesMap(new string[] {k_CheckDupePrefabA});
|
||||
rule.IntersectResourcesDepedenciesWithBundleDependencies(new List<GUID>()
|
||||
{
|
||||
new GUID(AssetDatabase.AssetPathToGUID(k_CheckDupePrefabA))
|
||||
});
|
||||
|
||||
Assert.IsTrue(rule.m_ResourcesToDependencies.ContainsKey(k_CheckDupePrefabA));
|
||||
Assert.AreEqual(1, rule.m_ResourcesToDependencies[k_CheckDupePrefabA].Count);
|
||||
Assert.AreEqual(AssetDatabase.AssetPathToGUID(k_CheckDupePrefabA), rule.m_ResourcesToDependencies[k_CheckDupePrefabA][0].ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CheckResourcesDupe_ResourcesDependenciesMatchWithImplicitBundleDependencies()
|
||||
{
|
||||
var rule = new CheckResourcesDupeDependencies();
|
||||
rule.BuiltInResourcesToDependenciesMap(new string[] {k_PrefabWithMaterialPath});
|
||||
rule.IntersectResourcesDepedenciesWithBundleDependencies(new List<GUID>()
|
||||
{
|
||||
new GUID(AssetDatabase.AssetPathToGUID(k_CheckDupeMyMaterial))
|
||||
});
|
||||
|
||||
Assert.IsTrue(rule.m_ResourcesToDependencies.ContainsKey(k_PrefabWithMaterialPath));
|
||||
Assert.AreEqual(1, rule.m_ResourcesToDependencies[k_PrefabWithMaterialPath].Count);
|
||||
Assert.AreEqual(AssetDatabase.AssetPathToGUID(k_CheckDupeMyMaterial), rule.m_ResourcesToDependencies[k_PrefabWithMaterialPath][0].ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CheckResourcesDupe_AllResourcesDependenciesAreReturned()
|
||||
{
|
||||
var rule = new CheckResourcesDupeDependencies();
|
||||
rule.BuiltInResourcesToDependenciesMap(new string[] {k_PrefabWithMaterialPath, k_CheckDupePrefabA});
|
||||
rule.IntersectResourcesDepedenciesWithBundleDependencies(new List<GUID>()
|
||||
{
|
||||
new GUID(AssetDatabase.AssetPathToGUID(k_CheckDupeMyMaterial)),
|
||||
new GUID(AssetDatabase.AssetPathToGUID(k_CheckDupePrefabA))
|
||||
});
|
||||
|
||||
Assert.IsTrue(rule.m_ResourcesToDependencies[k_PrefabWithMaterialPath].Contains(new GUID(AssetDatabase.AssetPathToGUID(k_CheckDupeMyMaterial))));
|
||||
|
||||
Assert.IsTrue(rule.m_ResourcesToDependencies[k_CheckDupePrefabA].Contains(new GUID(AssetDatabase.AssetPathToGUID(k_CheckDupeMyMaterial))));
|
||||
Assert.IsTrue(rule.m_ResourcesToDependencies[k_CheckDupePrefabA].Contains(new GUID(AssetDatabase.AssetPathToGUID(k_CheckDupePrefabA))));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d370242d9a79ba64cb55333c896bfdb0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,207 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using NUnit.Framework;
|
||||
using UnityEditor.AddressableAssets.Build.AnalyzeRules;
|
||||
using UnityEditor.AddressableAssets.Build.DataBuilders;
|
||||
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEditor.VersionControl;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets.Initialization;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace UnityEditor.AddressableAssets.Tests.AnalyzeRules
|
||||
{
|
||||
public class CheckSceneDupeDependenciesTests : AddressableAssetTestBase
|
||||
{
|
||||
string k_CheckDupePrefabA => GetAssetPath("checkDupe_prefabA.prefab");
|
||||
string k_CheckDupePrefabB => GetAssetPath("checkDupe_prefabB.prefab");
|
||||
string k_CheckDupeMyMaterial => GetAssetPath("checkDupe_myMaterial.mat");
|
||||
string k_ScenePath => GetAssetPath("dupeSceneTest.unity");
|
||||
string k_PrefabWithMaterialPath => GetAssetPath("checkDupe_prefabWithMaterial.prefab");
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
base.OnInit();
|
||||
|
||||
GameObject prefabA = new GameObject("PrefabA");
|
||||
GameObject prefabB = new GameObject("PrefabB");
|
||||
GameObject prefabWithMaterial = new GameObject("PrefabWithMaterial");
|
||||
var meshA = prefabA.AddComponent<MeshRenderer>();
|
||||
var meshB = prefabB.AddComponent<MeshRenderer>();
|
||||
|
||||
var mat = new Material(Shader.Find("Unlit/Color"));
|
||||
AssetDatabase.CreateAsset(mat, k_CheckDupeMyMaterial);
|
||||
meshA.sharedMaterial = mat;
|
||||
meshB.sharedMaterial = mat;
|
||||
|
||||
var meshPrefabWithMaterial = prefabWithMaterial.AddComponent<MeshRenderer>();
|
||||
meshPrefabWithMaterial.material = AssetDatabase.LoadAssetAtPath<Material>(k_CheckDupeMyMaterial);
|
||||
|
||||
prefabA.AddComponent<TestBehaviourWithReference>();
|
||||
|
||||
PrefabUtility.SaveAsPrefabAsset(prefabA, k_CheckDupePrefabA);
|
||||
PrefabUtility.SaveAsPrefabAsset(prefabB, k_CheckDupePrefabB);
|
||||
PrefabUtility.SaveAsPrefabAsset(prefabWithMaterial, k_PrefabWithMaterialPath);
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CheckSceneDupe_GetsCorrectResourcePaths()
|
||||
{
|
||||
Scene scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
|
||||
EditorSceneManager.SaveScene(scene, k_ScenePath);
|
||||
EditorBuildSettingsScene editorScene = new EditorBuildSettingsScene(k_ScenePath, true);
|
||||
|
||||
var sceneBU = EditorBuildSettings.scenes;
|
||||
EditorBuildSettings.scenes = new EditorBuildSettingsScene[1] {editorScene};
|
||||
try
|
||||
{
|
||||
var rule = new CheckSceneDupeDependencies();
|
||||
var paths = rule.GetResourcePaths();
|
||||
bool success = false;
|
||||
foreach (var p in paths)
|
||||
{
|
||||
if (p.Contains(editorScene.path))
|
||||
{
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Assert.IsTrue(success, "CheckSceneDupeDependencies ResourcePaths did not find the created Scene for test as expected.");
|
||||
}
|
||||
finally
|
||||
{
|
||||
//Cleanup
|
||||
EditorBuildSettings.scenes = sceneBU;
|
||||
EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
|
||||
AssetDatabase.DeleteAsset(k_ScenePath);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CheckSceneDupe_SceneDependenciesMatchWithExplicitBundleDependencies()
|
||||
{
|
||||
Scene scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
|
||||
GameObject go = AssetDatabase.LoadAssetAtPath<GameObject>(k_CheckDupePrefabA);
|
||||
|
||||
GameObject n = new GameObject("TestGameObject");
|
||||
var refer = n.AddComponent<TestBehaviourWithReference>();
|
||||
refer.Reference = go;
|
||||
SceneManager.MoveGameObjectToScene(n, scene);
|
||||
EditorSceneManager.SaveScene(scene, k_ScenePath);
|
||||
|
||||
var rule = new CheckSceneDupeDependencies();
|
||||
|
||||
EditorBuildSettingsScene editorScene = new EditorBuildSettingsScene(k_ScenePath, true);
|
||||
rule.BuiltInResourcesToDependenciesMap(new string[] {editorScene.path});
|
||||
rule.IntersectResourcesDepedenciesWithBundleDependencies(new List<GUID>() {new GUID(AssetDatabase.AssetPathToGUID(k_CheckDupePrefabA))});
|
||||
|
||||
Assert.IsTrue(rule.m_ResourcesToDependencies.ContainsKey(editorScene.path));
|
||||
Assert.AreEqual(1, rule.m_ResourcesToDependencies[editorScene.path].Count);
|
||||
Assert.AreEqual(AssetDatabase.AssetPathToGUID(k_CheckDupePrefabA), rule.m_ResourcesToDependencies[editorScene.path][0].ToString());
|
||||
|
||||
//Cleanup
|
||||
EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CheckSceneDupe_SceneDependenciesMatchWithImplicitBundleDependencies()
|
||||
{
|
||||
Scene scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
|
||||
PrefabUtility.InstantiatePrefab(AssetDatabase.LoadAssetAtPath<GameObject>(k_PrefabWithMaterialPath), scene);
|
||||
EditorSceneManager.SaveScene(scene, k_ScenePath);
|
||||
|
||||
var rule = new CheckSceneDupeDependencies();
|
||||
|
||||
EditorBuildSettingsScene editorScene = new EditorBuildSettingsScene(k_ScenePath, true);
|
||||
rule.BuiltInResourcesToDependenciesMap(new string[] {editorScene.path});
|
||||
rule.IntersectResourcesDepedenciesWithBundleDependencies(new List<GUID>() {new GUID(AssetDatabase.AssetPathToGUID(k_CheckDupeMyMaterial))});
|
||||
|
||||
Assert.IsTrue(rule.m_ResourcesToDependencies.ContainsKey(editorScene.path));
|
||||
Assert.AreEqual(1, rule.m_ResourcesToDependencies[editorScene.path].Count);
|
||||
Assert.AreEqual(AssetDatabase.AssetPathToGUID(k_CheckDupeMyMaterial), rule.m_ResourcesToDependencies[editorScene.path][0].ToString());
|
||||
|
||||
//Cleanup
|
||||
EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CheckSceneDupe_SceneDependenciesDoNotIncludeEditorOnly()
|
||||
{
|
||||
Scene scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
|
||||
GameObject go = PrefabUtility.InstantiatePrefab(AssetDatabase.LoadAssetAtPath<GameObject>(k_PrefabWithMaterialPath), scene) as GameObject;
|
||||
go.tag = "EditorOnly";
|
||||
EditorSceneManager.SaveScene(scene, k_ScenePath);
|
||||
|
||||
var rule = new CheckSceneDupeDependencies();
|
||||
|
||||
EditorBuildSettingsScene editorScene = new EditorBuildSettingsScene(k_ScenePath, true);
|
||||
rule.BuiltInResourcesToDependenciesMap(new string[] {editorScene.path});
|
||||
rule.IntersectResourcesDepedenciesWithBundleDependencies(new List<GUID>() {new GUID(AssetDatabase.AssetPathToGUID(k_CheckDupeMyMaterial))});
|
||||
|
||||
Assert.IsTrue(rule.m_ResourcesToDependencies.ContainsKey(editorScene.path));
|
||||
Assert.AreEqual(0, rule.m_ResourcesToDependencies[editorScene.path].Count);
|
||||
|
||||
//Cleanup
|
||||
EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CheckSceneDupe_AllSceneToBundleDependenciesAreReturned()
|
||||
{
|
||||
Scene scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
|
||||
PrefabUtility.InstantiatePrefab(AssetDatabase.LoadAssetAtPath<GameObject>(k_PrefabWithMaterialPath), scene);
|
||||
EditorSceneManager.SaveScene(scene, k_ScenePath);
|
||||
|
||||
var rule = new CheckSceneDupeDependencies();
|
||||
|
||||
EditorBuildSettingsScene editorScene = new EditorBuildSettingsScene(k_ScenePath, true);
|
||||
rule.BuiltInResourcesToDependenciesMap(new string[] {editorScene.path});
|
||||
rule.IntersectResourcesDepedenciesWithBundleDependencies(new List<GUID>()
|
||||
{
|
||||
new GUID(AssetDatabase.AssetPathToGUID(k_CheckDupeMyMaterial))
|
||||
});
|
||||
|
||||
Assert.IsTrue(rule.m_ResourcesToDependencies.ContainsKey(editorScene.path));
|
||||
Assert.AreEqual(1, rule.m_ResourcesToDependencies[editorScene.path].Count);
|
||||
Assert.IsTrue(rule.m_ResourcesToDependencies[editorScene.path].Contains(new GUID(AssetDatabase.AssetPathToGUID(k_CheckDupeMyMaterial))));
|
||||
|
||||
//Cleanup
|
||||
EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CheckSceneDupe_SceneDependenciesDoNotIncludeScripts()
|
||||
{
|
||||
Scene scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
|
||||
GameObject go = AssetDatabase.LoadAssetAtPath<GameObject>(k_CheckDupePrefabA);
|
||||
GameObject g = PrefabUtility.InstantiatePrefab(go, scene) as GameObject;
|
||||
g.AddComponent<TestBehaviourWithReference>();
|
||||
EditorSceneManager.SaveScene(scene, k_ScenePath);
|
||||
|
||||
var rule = new CheckSceneDupeDependencies();
|
||||
|
||||
EditorBuildSettingsScene editorScene = new EditorBuildSettingsScene(k_ScenePath, true);
|
||||
rule.BuiltInResourcesToDependenciesMap(new string[] {editorScene.path});
|
||||
|
||||
Assert.IsTrue(rule.m_ResourcesToDependencies.ContainsKey(editorScene.path));
|
||||
bool containsAnyScripts = false;
|
||||
foreach (GUID guid in rule.m_ResourcesToDependencies[editorScene.path])
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid.ToString());
|
||||
if (path.EndsWith(".cs") || path.EndsWith(".dll"))
|
||||
{
|
||||
containsAnyScripts = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Assert.IsFalse(containsAnyScripts, "Scripts were included as a duplciate dependency");
|
||||
|
||||
//Cleanup
|
||||
EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e054c3274b8fb154c876b5be5db09359
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,225 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using NUnit.Framework;
|
||||
using UnityEditor.AddressableAssets.GUI;
|
||||
using UnityEditor.AddressableAssets.Settings;
|
||||
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
|
||||
namespace UnityEditor.AddressableAssets.Tests
|
||||
{
|
||||
public class AssetGroupTests : AddressableAssetTestBase
|
||||
{
|
||||
[Test]
|
||||
public void AddRemoveEntry()
|
||||
{
|
||||
var group = Settings.FindGroup(AddressableAssetSettings.DefaultLocalGroupName);
|
||||
Assert.IsNotNull(group);
|
||||
var entry = new AddressableAssetEntry(m_AssetGUID, "test", group, false);
|
||||
group.AddAssetEntry(entry);
|
||||
Assert.IsNotNull(group.GetAssetEntry(m_AssetGUID));
|
||||
group.RemoveAssetEntry(entry);
|
||||
Assert.IsNull(group.GetAssetEntry(m_AssetGUID));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RenameSlashesBecomeDashes()
|
||||
{
|
||||
var group = Settings.FindGroup(AddressableAssetSettings.DefaultLocalGroupName);
|
||||
var oldName = group.Name;
|
||||
group.Name = "folder/name";
|
||||
Assert.AreEqual("folder-name", group.Name);
|
||||
group.Name = oldName;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RenameInvalidCharactersFails()
|
||||
{
|
||||
var group = Settings.FindGroup(AddressableAssetSettings.DefaultLocalGroupName);
|
||||
var oldName = group.Name;
|
||||
string badName = "*#?@>!@*@(#";
|
||||
LogAssert.Expect(LogType.Error, "Rename of Group failed. Invalid file name: '" + badName + ".asset'");
|
||||
group.Name = badName;
|
||||
Assert.AreEqual(oldName, group.Name);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RenameAlwaysSetsObjectName()
|
||||
{
|
||||
var group = Settings.FindGroup(AddressableAssetSettings.DefaultLocalGroupName);
|
||||
var oldName = group.Name;
|
||||
group.name = "mismatchName";
|
||||
Assert.AreNotEqual(oldName, group.name);
|
||||
group.Name = oldName;
|
||||
Assert.AreEqual(oldName, group.name);
|
||||
Assert.AreEqual(oldName, group.Name);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DedupeEntries_WhenGroupsHaveOverlappingAssetEntries_RemovesEntries()
|
||||
{
|
||||
const string guid = "0000";
|
||||
const string address = "not/a/real/address";
|
||||
AddressableAssetGroup group1 = Settings.CreateGroup("group1", false, false, true, null, new Type[] { });
|
||||
AddressableAssetGroup group2 = Settings.CreateGroup("group2", false, false, true, null, new Type[] { });
|
||||
|
||||
//We're making 2 identical enteries. This is to simulate each group having it's own copy of an AA Entry that references the same object.
|
||||
//If we use the same object the call to AddAssetEntry won't give us the state we're looking for.
|
||||
AddressableAssetEntry entry = new AddressableAssetEntry(guid, address, group1, false);
|
||||
AddressableAssetEntry entry2 = new AddressableAssetEntry(guid, address, group2, false);
|
||||
|
||||
group1.AddAssetEntry(entry);
|
||||
group2.AddAssetEntry(entry2);
|
||||
|
||||
//Ensuring our setup is correct
|
||||
Assert.IsNotNull(group1.GetAssetEntry(guid));
|
||||
Assert.IsNotNull(group2.GetAssetEntry(guid));
|
||||
|
||||
group1.DedupeEnteries(); //We setup our entry with group1 so it should retain its reference
|
||||
group2.DedupeEnteries(); //The entry was added to group2 afterwards and should lose its reference
|
||||
|
||||
Assert.IsNotNull(group1.GetAssetEntry(guid));
|
||||
Assert.IsNull(group2.GetAssetEntry(guid));
|
||||
|
||||
//Cleanup
|
||||
Settings.RemoveGroup(group1);
|
||||
Settings.RemoveGroup(group2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveEntries_InvokesModificationNotification()
|
||||
{
|
||||
AddressableAssetGroup group1 = Settings.CreateGroup("group1", false, false, true, null, new Type[] { });
|
||||
|
||||
List<AddressableAssetEntry> entries = new List<AddressableAssetEntry>();
|
||||
for (int i = 0; i < 10; i++)
|
||||
group1.AddAssetEntry(new AddressableAssetEntry("000" + i.ToString(), "unknown" + i.ToString(), group1, false));
|
||||
|
||||
|
||||
List<AddressableAssetEntry> callbackEntries = new List<AddressableAssetEntry>();
|
||||
Action<AddressableAssetSettings, AddressableAssetSettings.ModificationEvent, object> callback = (x, y, z) => callbackEntries.AddRange((AddressableAssetEntry[])z);
|
||||
AddressableAssetSettings.OnModificationGlobal += callback;
|
||||
|
||||
group1.RemoveAssetEntries(entries.ToArray());
|
||||
|
||||
for (int i = 0; i < entries.Count; i++)
|
||||
Assert.AreEqual(entries[i], callbackEntries[i]);
|
||||
|
||||
//Cleanup
|
||||
AddressableAssetSettings.OnModificationGlobal -= callback;
|
||||
Settings.RemoveGroup(group1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SupportsPeriodInName()
|
||||
{
|
||||
//Setup
|
||||
var group = Settings.CreateGroup("name1", false, false, false, new List<AddressableAssetGroupSchema>());
|
||||
|
||||
//Test
|
||||
string testName = group.Name = "test1.test";
|
||||
|
||||
//Assert
|
||||
Assert.AreEqual(group.name, group.Name);
|
||||
Assert.AreEqual(testName, group.Name);
|
||||
|
||||
//Cleanup
|
||||
Settings.RemoveGroup(group);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CannotSetInvalidGroupAsDefault()
|
||||
{
|
||||
AddressableAssetGroup group1 = Settings.CreateGroup("group1", false, true, true, null, new Type[] { });
|
||||
LogAssert.Expect(LogType.Error, "Unable to set " + group1.Name + " as the Default Group. Default Groups must not be ReadOnly.");
|
||||
Settings.DefaultGroup = group1;
|
||||
Assert.AreNotEqual(Settings.DefaultGroup, group1);
|
||||
|
||||
//Cleanup
|
||||
Settings.RemoveGroup(group1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DefaultGroupContainsCorrectProperties()
|
||||
{
|
||||
Assert.IsFalse(Settings.DefaultGroup.ReadOnly);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DefaultGroupChangesToValidDefaultGroup()
|
||||
{
|
||||
LogAssert.ignoreFailingMessages = true;
|
||||
AddressableAssetGroup oldDefault = Settings.DefaultGroup;
|
||||
oldDefault.m_ReadOnly = true;
|
||||
AddressableAssetGroup newDefault = Settings.DefaultGroup;
|
||||
|
||||
Assert.AreNotEqual(oldDefault, newDefault);
|
||||
Assert.IsFalse(Settings.DefaultGroup.ReadOnly);
|
||||
|
||||
//Cleanup
|
||||
oldDefault.AddSchema<BundledAssetGroupSchema>();
|
||||
Settings.DefaultGroup = oldDefault;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PreventNullDefaultGroup()
|
||||
{
|
||||
LogAssert.Expect(LogType.Error, "Unable to set null as the Default Group. Default Groups must not be ReadOnly.");
|
||||
Settings.DefaultGroup = null;
|
||||
Assert.IsNotNull(Settings.DefaultGroup);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ValidGroupsCanBeSetAsDefault()
|
||||
{
|
||||
AddressableAssetGroup oldDefault = Settings.DefaultGroup;
|
||||
AddressableAssetGroup group1 = Settings.CreateGroup("group1", false, false, true, null, new Type[] {typeof(BundledAssetGroupSchema)});
|
||||
Settings.DefaultGroup = group1;
|
||||
Assert.AreEqual(group1, Settings.DefaultGroup);
|
||||
|
||||
//Cleanup
|
||||
Settings.DefaultGroup = oldDefault;
|
||||
Settings.RemoveGroup(group1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ResourcesEntry_AddsCorrectTreeViewItem_ForSubobjects()
|
||||
{
|
||||
using (new HideResourceFoldersScope())
|
||||
{
|
||||
//Setup
|
||||
string assetPath = "SubFolder/Cube.prefab";
|
||||
int builtInPackagesResourcesCount = ResourcesTestUtility.GetResourcesEntryCount(Settings, true);
|
||||
CreatePrefabInResourcesSubFolder(assetPath);
|
||||
AddressableAssetEntryTreeView treeView = new AddressableAssetEntryTreeView(
|
||||
new TreeViewState(),
|
||||
new MultiColumnHeaderState(new MultiColumnHeaderState.Column[2]),
|
||||
new AddressableAssetsSettingsGroupEditor(new AddressableAssetsWindow()));
|
||||
|
||||
//Test
|
||||
AddressableAssetEntry entry = Settings.FindAssetEntry("Resources");
|
||||
AssetEntryTreeViewItem treeViewItem = new AssetEntryTreeViewItem(entry, 0);
|
||||
treeView.RecurseEntryChildren(entry, treeViewItem, 0);
|
||||
|
||||
//Assert
|
||||
Assert.AreEqual(1 + builtInPackagesResourcesCount, treeViewItem.children.Count);
|
||||
Assert.AreEqual(assetPath.Replace(".prefab", ""), treeViewItem.children[0].displayName);
|
||||
|
||||
//Cleanup
|
||||
AssetDatabase.DeleteAsset("Assets/Resources/");
|
||||
}
|
||||
}
|
||||
|
||||
void CreatePrefabInResourcesSubFolder(string subFolderAssetPath)
|
||||
{
|
||||
string path = $"Assets/Resources/{subFolderAssetPath}";
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
||||
GameObject go = new GameObject();
|
||||
PrefabUtility.SaveAsPrefabAsset(go, path);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3b8b37f5037b1e945af5621a67f45bc0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a972530fcd6a48b4480b570f902b2e19
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,474 @@
|
|||
#if UNITY_2020_1_OR_NEWER
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets.ResourceLocators;
|
||||
using UnityEngine.ResourceManagement.Util;
|
||||
using Debug = UnityEngine.Debug;
|
||||
|
||||
namespace UnityEditor.AddressableAssets.Tests
|
||||
{
|
||||
public class BinaryStorageBufferTests
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct SimpleStruct : IEquatable<SimpleStruct>
|
||||
{
|
||||
public int intVal;
|
||||
public float floatVal;
|
||||
public byte byteVal;
|
||||
public short shortVal;
|
||||
public long longVal;
|
||||
public char charVal;
|
||||
public SimpleStruct(int multiple)
|
||||
{
|
||||
intVal = 8 * multiple;
|
||||
floatVal = 3.14f * multiple;
|
||||
byteVal = (byte)(16 * multiple);
|
||||
shortVal = (short)(125 * multiple);
|
||||
longVal = 10000000 * multiple;
|
||||
charVal = 'u';
|
||||
}
|
||||
|
||||
public bool Equals(SimpleStruct other)
|
||||
{
|
||||
return intVal.Equals(other.intVal) && floatVal.Equals(other.floatVal) && byteVal.Equals(other.byteVal) && shortVal.Equals(other.shortVal) && longVal.Equals(other.longVal) && charVal.Equals(other.charVal);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestValueTypes([Values(1024, 1024 * 1024)]int chunkSize, [Values(0, 10, 1024)]int cacheSize)
|
||||
{
|
||||
var wr = new BinaryStorageBuffer.Writer(chunkSize);
|
||||
var intID = wr.Write(5);
|
||||
var floatId = wr.Write(3.14f);
|
||||
var boolId = wr.Write(true);
|
||||
var structId1 = wr.Write(new SimpleStruct(1));
|
||||
var structId2 = wr.Write(new SimpleStruct(2));
|
||||
|
||||
var bytes = wr.SerializeToByteArray();
|
||||
var re = new BinaryStorageBuffer.Reader(bytes, cacheSize);
|
||||
Assert.AreEqual(5, re.ReadValue<int>(intID));
|
||||
Assert.AreEqual(true, re.ReadValue<bool>(boolId));
|
||||
Assert.AreEqual(new SimpleStruct(1), re.ReadValue<SimpleStruct>(structId1));
|
||||
Assert.AreEqual(new SimpleStruct(2), re.ReadValue<SimpleStruct>(structId2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestValueTypesWithReserve([Values(1024, 1024 * 1024)]int chunkSize, [Values(0, 10, 1024)]int cacheSize)
|
||||
{
|
||||
var wr = new BinaryStorageBuffer.Writer(chunkSize);
|
||||
var intID = wr.Write(wr.Reserve<int>(), 5);
|
||||
var floatId = wr.Write(wr.Reserve<float>(), 3.14f);
|
||||
var boolId = wr.Write(wr.Reserve<bool>(), true);
|
||||
var structId1 = wr.Write(wr.Reserve<SimpleStruct>(), new SimpleStruct(1));
|
||||
var structId2 = wr.Write(wr.Reserve<SimpleStruct>(), new SimpleStruct(2));
|
||||
|
||||
var bytes = wr.SerializeToByteArray();
|
||||
var re = new BinaryStorageBuffer.Reader(bytes, cacheSize);
|
||||
Assert.AreEqual(5, re.ReadValue<int>(intID));
|
||||
Assert.AreEqual(true, re.ReadValue<bool>(boolId));
|
||||
Assert.AreEqual(new SimpleStruct(1), re.ReadValue<SimpleStruct>(structId1));
|
||||
Assert.AreEqual(new SimpleStruct(2), re.ReadValue<SimpleStruct>(structId2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestValueTypesWithUnorderedReserve([Values(1024, 1024 * 1024)]int chunkSize, [Values(0, 10, 1024)]int cacheSize)
|
||||
{
|
||||
var wr = new BinaryStorageBuffer.Writer(chunkSize);
|
||||
var intID = wr.Reserve<int>();
|
||||
var floatId = wr.Reserve<float>();
|
||||
var boolId = wr.Write(wr.Reserve<bool>(), true);
|
||||
var structId1 = wr.Reserve<SimpleStruct>();
|
||||
var structId2 = wr.Write(wr.Reserve<SimpleStruct>(), new SimpleStruct(2));
|
||||
wr.Write(floatId, 3.14f);
|
||||
wr.Write(intID, 5);
|
||||
wr.Write(structId1, new SimpleStruct(1));
|
||||
wr.Write(structId1, new SimpleStruct(1));
|
||||
var bytes = wr.SerializeToByteArray();
|
||||
var re = new BinaryStorageBuffer.Reader(bytes, cacheSize);
|
||||
Assert.AreEqual(5, re.ReadValue<int>(intID));
|
||||
Assert.AreEqual(true, re.ReadValue<bool>(boolId));
|
||||
Assert.AreEqual(new SimpleStruct(1), re.ReadValue<SimpleStruct>(structId1));
|
||||
Assert.AreEqual(new SimpleStruct(2), re.ReadValue<SimpleStruct>(structId2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestValueTypeArrays([Values(1024, 1024 * 1024)]int chunkSize, [Values(0, 1, 32, 256, 1024)]int count, [Values(0, 10, 1024)]int cacheSize)
|
||||
{
|
||||
var array = new SimpleStruct[count];
|
||||
var array2 = new SimpleStruct[count];
|
||||
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
array2[i] = new SimpleStruct(array2.Length - i);
|
||||
array[i] = new SimpleStruct(i);
|
||||
}
|
||||
|
||||
var wr = new BinaryStorageBuffer.Writer(chunkSize);
|
||||
var arrayId2 = wr.Reserve<SimpleStruct>((uint)count);
|
||||
var arrayId = wr.Write(array);
|
||||
wr.Write(arrayId2, array2);
|
||||
|
||||
var re = new BinaryStorageBuffer.Reader(wr.SerializeToByteArray(), cacheSize);
|
||||
var a1 = re.ReadValueArray<SimpleStruct>(arrayId);
|
||||
var a2 = re.ReadValueArray<SimpleStruct>(arrayId2);
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
Assert.AreEqual(array[i], a1[i]);
|
||||
Assert.AreEqual(array2[i], a2[i]);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestValueTypeDeduplication([Values(1024, 1024 * 1024)]int chunkSize)
|
||||
{
|
||||
var wr = new BinaryStorageBuffer.Writer(chunkSize);
|
||||
wr.Write(new SimpleStruct(1));
|
||||
wr.Write(new SimpleStruct(2));
|
||||
wr.Write(new SimpleStruct(3));
|
||||
wr.Write(new SimpleStruct(4));
|
||||
wr.Write(new SimpleStruct(5));
|
||||
var size = wr.Length;
|
||||
wr.Write(new SimpleStruct(5));
|
||||
wr.Write(new SimpleStruct(4));
|
||||
wr.Write(new SimpleStruct(3));
|
||||
wr.Write(new SimpleStruct(2));
|
||||
wr.Write(new SimpleStruct(1));
|
||||
Assert.AreEqual(size, wr.Length);
|
||||
}
|
||||
[Test]
|
||||
public void TestValueArrayTypeDeduplication([Values(1024, 1024 * 1024)]int chunkSize, [Values(0, 1, 32, 256, 1024)]int count)
|
||||
{
|
||||
var array = new SimpleStruct[count];
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
array[i] = new SimpleStruct(i);
|
||||
|
||||
var wr = new BinaryStorageBuffer.Writer(chunkSize);
|
||||
wr.Write(array);
|
||||
var size = wr.Length;
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
wr.Write(array[i]);
|
||||
Assert.AreEqual(size, wr.Length);
|
||||
}
|
||||
|
||||
const string ucSample = "Ё Ђ Ѓ Є Ѕ І Ї Ј Љ Њ Ћ Ќ Ў Џ А Б В Г Д Е Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Ъ Ы Ь Э Ю Я а б в г д е ж з и й к л м н о п р с т у ф х ц ч ш щ ъ ы ь э ю я ё ђ ѓ є ѕ і ї ј љ њ ћ ќ ў џ Ѡ ѡ Ѣ ѣ Ѥ ѥ Ѧ ѧ Ѩ ѩ Ѫ ѫ Ѭ ѭ Ѯ ѯ Ѱ ѱ Ѳ ѳ Ѵ ѵ Ѷ ѷ Ѹ ѹ Ѻ ѻ Ѽ ѽ Ѿ ѿ Ҁ ҁ ҂ ҃ ...";
|
||||
string RandomText(int len, bool unicode, char sep)
|
||||
{
|
||||
var sb = new StringBuilder(len);
|
||||
var appendCount = 0;
|
||||
if (unicode)
|
||||
{
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
if (appendCount++ > UnityEngine.Random.Range(10, 30))
|
||||
{
|
||||
sb.Append(sep);
|
||||
appendCount = 0;
|
||||
}
|
||||
else
|
||||
sb.Append(ucSample[UnityEngine.Random.Range(0, ucSample.Length)]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
if (appendCount++ > UnityEngine.Random.Range(10, 30))
|
||||
{
|
||||
sb.Append(sep);
|
||||
appendCount = 0;
|
||||
}
|
||||
else
|
||||
sb.Append((char)UnityEngine.Random.Range((int)'a', (int)'z'));
|
||||
}
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestStringAsObject()
|
||||
{
|
||||
var txt = RandomText(1000, false, '/');
|
||||
var objTxt = txt as object;
|
||||
var wr = new BinaryStorageBuffer.Writer(1024, new ComplexObject.Serializer());
|
||||
var headerOffset = wr.Reserve<DateTime>();
|
||||
var reserve2 = wr.Reserve<DateTime>(100000);
|
||||
wr.Write(new int[100000]);
|
||||
for (int i = 0; i < 100000; i++)
|
||||
wr.WriteString(txt);
|
||||
//wr.WriteObject(new ComplexObject(i), true);
|
||||
var str = wr.WriteObject(objTxt, true);
|
||||
var bytes = wr.SerializeToByteArray();
|
||||
var re = new BinaryStorageBuffer.Reader(wr.SerializeToByteArray(), 1024);
|
||||
var rStr = re.ReadObject(str) as string;
|
||||
//var rStr = re.ReadString(
|
||||
Assert.AreEqual(txt, rStr);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestASCIIStrings([Values(1024, 1024 * 1024)]int chunkSize, [Values(0, 1, 10, 100, 1000, 5000)]int strLen, [Values(0, 10, 1024)]int cacheSize)
|
||||
{
|
||||
var txt = RandomText(strLen, false, '/');
|
||||
var sep = (char)UnityEngine.Random.Range((int)'a', (int)'z');
|
||||
var wr = new BinaryStorageBuffer.Writer(chunkSize);
|
||||
var str = wr.WriteString(txt, sep);
|
||||
var bytes = wr.SerializeToByteArray();
|
||||
var re = new BinaryStorageBuffer.Reader(bytes, cacheSize);
|
||||
var strRes = re.ReadString(str, sep);
|
||||
Assert.AreEqual(txt, strRes);
|
||||
}
|
||||
[Test]
|
||||
public void TestASCIIStringsDeduplication([Values(1024, 1024 * 1024)]int chunkSize, [Values(0, 1, 10, 100, 1000, 5000)]int strLen, [Values(0, 10, 1024)]int cacheSize)
|
||||
{
|
||||
var txt = RandomText(strLen, false, '/');
|
||||
var sep = (char)UnityEngine.Random.Range((int)'a', (int)'z');
|
||||
var wr = new BinaryStorageBuffer.Writer(chunkSize);
|
||||
var str = wr.WriteString(txt, sep);
|
||||
var size = wr.Length;
|
||||
var str2 = wr.WriteString(txt, sep);
|
||||
Assert.AreEqual(size, wr.Length);
|
||||
Assert.AreEqual(str, str2);
|
||||
|
||||
var re = new BinaryStorageBuffer.Reader(wr.SerializeToByteArray(), cacheSize);
|
||||
Assert.AreEqual(txt, re.ReadString(str, sep));
|
||||
Assert.AreEqual(txt, re.ReadString(str2, sep));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUnicodeStrings([Values(1024, 1024 * 1024)]int chunkSize, [Values(0, 1, 10, 100, 1000, 5000)]int strLen, [Values(0, 10, 1024)]int cacheSize)
|
||||
{
|
||||
var txt = RandomText(strLen, true, '/');
|
||||
var sep = (char)UnityEngine.Random.Range((int)'a', (int)'z');
|
||||
var wr = new BinaryStorageBuffer.Writer(chunkSize);
|
||||
var str = wr.WriteString(txt, sep);
|
||||
var bytes = wr.SerializeToByteArray();
|
||||
var re = new BinaryStorageBuffer.Reader(bytes, cacheSize);
|
||||
var strRes = re.ReadString(str, sep);
|
||||
Assert.AreEqual(txt, strRes);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestStringExamples(
|
||||
[Values(8, 256, 1024)]int chunkSize,
|
||||
[Values(
|
||||
null,
|
||||
"",
|
||||
"1",
|
||||
"string",
|
||||
"a/b/c/d/f/g/h/i/j/k",
|
||||
"rootfolder1/rootfolder2/rootfolder3/long file name",
|
||||
"rootfolder1/rootЁfolder2/rootfolder3_withЁ/long file name",
|
||||
"a/b/wergwegbwethgrwtherth/c/e/ffdsfsrgwetghwthwrh/e/s/wergwethgwrthrewthwer",
|
||||
"a/b/wergwegbwethgrwtherth/Ёc/e/ffdsfsЁrgwetghwthwrh/e/s/wergwethgwrthrewthweЁr"
|
||||
)]string str, [Values(0, 10, 1024)]int cacheSize)
|
||||
{
|
||||
var wr = new BinaryStorageBuffer.Writer(chunkSize);
|
||||
var id = wr.WriteString(str, '/');
|
||||
var r = new BinaryStorageBuffer.Reader(wr.SerializeToByteArray(), cacheSize);
|
||||
var str2 = r.ReadString(id, '/');
|
||||
Assert.AreEqual(str, str2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PerfTestStringExamples()
|
||||
{
|
||||
var wr = new BinaryStorageBuffer.Writer(1024);
|
||||
var unicodeStr = "unicode string = Ё";
|
||||
var asciiStr = "ascii string";
|
||||
|
||||
int count = 10000;
|
||||
var ids = new uint[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var sb = new StringBuilder(1000);
|
||||
var partCount = UnityEngine.Random.Range(2, 10);
|
||||
for (int j = 0; j < partCount; j++)
|
||||
{
|
||||
var v = UnityEngine.Random.Range(0, 10);
|
||||
if (v > 4)
|
||||
sb.Append($"{asciiStr} - {v}");
|
||||
else
|
||||
sb.Append($"{unicodeStr} - {v}");
|
||||
sb.Append('/');
|
||||
}
|
||||
|
||||
ids[i] = wr.WriteString(sb.ToString(), '/');
|
||||
}
|
||||
|
||||
var r = new BinaryStorageBuffer.Reader(wr.SerializeToByteArray(), 1024);
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
for (int i = 0; i < 100000; i++)
|
||||
r.ReadString(ids[UnityEngine.Random.Range(0, ids.Length)], '/');
|
||||
sw.Stop();
|
||||
Debug.Log($"ReadString time: {sw.ElapsedMilliseconds}ms.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
class ComplexObject : IEquatable<ComplexObject>
|
||||
{
|
||||
public class ComplexSubClass : IEquatable<ComplexSubClass>
|
||||
{
|
||||
public string stringVal;
|
||||
public float floatV;
|
||||
public bool Equals(ComplexSubClass other) => stringVal.Equals(other.stringVal) && floatV.Equals(other.floatV);
|
||||
}
|
||||
public int intVal;
|
||||
public string stringVal;
|
||||
public ComplexSubClass sub;
|
||||
public ComplexObject() { }
|
||||
public ComplexObject(int seed)
|
||||
{
|
||||
UnityEngine.Random.InitState(seed);
|
||||
intVal = UnityEngine.Random.Range(1, 1000);
|
||||
stringVal = $"string value {UnityEngine.Random.Range(1, 1000)}";
|
||||
sub = new ComplexSubClass { floatV = UnityEngine.Random.Range(.1f, 10000f), stringVal = $"sub string value {UnityEngine.Random.Range(10000, 100000)}" };
|
||||
}
|
||||
|
||||
public bool Equals(ComplexObject other) => intVal.Equals(other.intVal) && stringVal.Equals(other.stringVal) && sub.Equals(other.sub);
|
||||
|
||||
public class Serializer : BinaryStorageBuffer.ISerializationAdapter<ComplexObject>
|
||||
{
|
||||
public IEnumerable<BinaryStorageBuffer.ISerializationAdapter> Dependencies => null;
|
||||
|
||||
struct Data
|
||||
{
|
||||
public struct Sub
|
||||
{
|
||||
public uint stringId;
|
||||
public float floatVal;
|
||||
}
|
||||
public int intVal;
|
||||
public uint stringId;
|
||||
public uint subId;
|
||||
}
|
||||
|
||||
public object Deserialize(BinaryStorageBuffer.Reader reader, Type type, uint offset)
|
||||
{
|
||||
var data = reader.ReadValue<Data>(offset);
|
||||
var sub = reader.ReadValue<Data.Sub>(data.subId);
|
||||
return new ComplexObject
|
||||
{
|
||||
intVal = data.intVal,
|
||||
stringVal = reader.ReadString(data.stringId),
|
||||
sub = new ComplexSubClass
|
||||
{
|
||||
floatV = sub.floatVal,
|
||||
stringVal = reader.ReadString(sub.stringId)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public uint Serialize(BinaryStorageBuffer.Writer writer, object val)
|
||||
{
|
||||
var co = val as ComplexObject;
|
||||
var id = writer.Reserve<Data>();
|
||||
var data = new Data
|
||||
{
|
||||
intVal = co.intVal,
|
||||
stringId = writer.WriteString(co.stringVal),
|
||||
subId = writer.Write(new Data.Sub
|
||||
{
|
||||
floatVal = co.sub.floatV,
|
||||
stringId = writer.WriteString(co.sub.stringVal)
|
||||
})
|
||||
};
|
||||
return writer.Write(id, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestStringsAsObjects([Values("ascii string", "unicode string")] string expected, [Values(0, 10, 1024)]int cacheSize)
|
||||
{
|
||||
var wr = new BinaryStorageBuffer.Writer(1024);
|
||||
var id = wr.WriteObject(expected, false);
|
||||
var id2 = wr.WriteObject(expected, true);
|
||||
var r = new BinaryStorageBuffer.Reader(wr.SerializeToByteArray(), cacheSize);
|
||||
var str = r.ReadObject<string>(id);
|
||||
Assert.AreEqual(expected, str);
|
||||
var strObj = r.ReadObject(id2);
|
||||
Assert.AreEqual(expected, strObj);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMixedObjectArray([Values(0, 10, 1024)]int cacheSize)
|
||||
{
|
||||
var wr = new BinaryStorageBuffer.Writer(1024, new ComplexObject.Serializer());
|
||||
var objs = new object[] { "string val", new ComplexObject(1) };
|
||||
var id = wr.WriteObjects(objs, true);
|
||||
var r = new BinaryStorageBuffer.Reader(wr.SerializeToByteArray(), cacheSize, new ComplexObject.Serializer());
|
||||
var objs2 = r.ReadObjectArray(id);
|
||||
for (int i = 0; i < objs.Length; i++)
|
||||
Assert.AreEqual(objs[i], objs2[i]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestComplexObjectDeduplication([Values(1024, 1024 * 1024)]int chunkSize, [Values(1, 32, 256, 1024)]int count, [Values(0, 10, 1024)]int cacheSize)
|
||||
{
|
||||
var wr = new BinaryStorageBuffer.Writer(chunkSize, new ComplexObject.Serializer());
|
||||
var ids = new uint[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
ids[i] = wr.WriteObject(new ComplexObject(i), false);
|
||||
var size = wr.Length;
|
||||
for (int i = 0; i < count; i++)
|
||||
wr.WriteObject(new ComplexObject(i), false);
|
||||
Assert.Less(wr.Length, size * 2);
|
||||
var re = new BinaryStorageBuffer.Reader(wr.SerializeToByteArray(), cacheSize, new ComplexObject.Serializer());
|
||||
for (int i = 0; i < ids.Length; i++)
|
||||
Assert.AreEqual(new ComplexObject(i), re.ReadObject<ComplexObject>(ids[i]));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestComplexObjectArray([Values(1024, 1024 * 1024)]int chunkSize, [Values(1, 32, 256, 1024)]int count, [Values(0, 10, 1024)]int cacheSize)
|
||||
{
|
||||
var wr = new BinaryStorageBuffer.Writer(chunkSize, new ComplexObject.Serializer());
|
||||
var objs = new ComplexObject[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
objs[i] = new ComplexObject(i);
|
||||
uint objArrayWithoutType = wr.WriteObjects(objs, false);
|
||||
uint objArrayWithType = wr.WriteObjects(objs, true);
|
||||
var re = new BinaryStorageBuffer.Reader(wr.SerializeToByteArray(), cacheSize, new ComplexObject.Serializer());
|
||||
var typedObjs = re.ReadObjectArray<ComplexObject>(objArrayWithoutType);
|
||||
for (int i = 0; i < count; i++)
|
||||
Assert.AreEqual(objs[i], typedObjs[i]);
|
||||
var untypedObjs = re.ReadObjectArray(objArrayWithType);
|
||||
for (int i = 0; i < count; i++)
|
||||
Assert.AreEqual(objs[i], untypedObjs[i]);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void TestManyComplexObjectsAndStrings([Values(1024, 1024 * 1024)]int chunkSize, [Values(1024, 10 * 1024, 100 * 1024)]int count, [Values(0, 10, 1024)]int cacheSize)
|
||||
{
|
||||
var wr = new BinaryStorageBuffer.Writer(chunkSize, new ComplexObject.Serializer());
|
||||
var ids = new uint[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
ids[i] = wr.WriteObject(new ComplexObject(i), true);
|
||||
else
|
||||
ids[i] = wr.WriteString($"very long start of string/a middle part that is also somewhat long/almost done.../this part is unique{i}...../this part has unicode characters, see ЁЁЁЁЁЁЁ", '/');
|
||||
}
|
||||
|
||||
|
||||
var r = new BinaryStorageBuffer.Reader(wr.SerializeToByteArray(), cacheSize, new ComplexObject.Serializer());
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
Assert.AreEqual(new ComplexObject(i), r.ReadObject(ids[i], false));
|
||||
else
|
||||
Assert.AreEqual($"very long start of string/a middle part that is also somewhat long/almost done.../this part is unique{i}...../this part has unicode characters, see ЁЁЁЁЁЁЁ", r.ReadString(ids[i], '/'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f3b9de71a388cba4c81fbdaf789def84
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 142f7d4eae11d5b41a02b71169f6b854
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,81 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using NUnit.Framework;
|
||||
using UnityEditor;
|
||||
using UnityEditor.AddressableAssets.Build.BuildPipelineTasks;
|
||||
using UnityEditor.AddressableAssets.Build.DataBuilders;
|
||||
using UnityEditor.AddressableAssets.Settings;
|
||||
using UnityEditor.Build.Content;
|
||||
using UnityEditor.Build.Pipeline;
|
||||
using UnityEditor.Build.Pipeline.Interfaces;
|
||||
using UnityEditor.Build.Pipeline.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
public class AddHashToBundleNameTaskTests : AddressableBuildTaskTestBase
|
||||
{
|
||||
[Test]
|
||||
public void AddHashToBundleNameTask_DoesNotChangeHash_WhenAssetsChangeOrder()
|
||||
{
|
||||
//Setup
|
||||
string path1 = $"{TempPath}/test1.prefab";
|
||||
string path2 = $"{TempPath}/test2.prefab";
|
||||
string path3 = $"{TempPath}/test3.prefab";
|
||||
|
||||
GUID guid1 = new GUID(CreateAsset(path1, "1"));
|
||||
GUID guid2 = new GUID(CreateAsset(path2, "2"));
|
||||
GUID guid3 = new GUID(CreateAsset(path3, "3"));
|
||||
|
||||
List<GUID> list1 = new List<GUID>()
|
||||
{
|
||||
guid1,
|
||||
guid2,
|
||||
guid3
|
||||
};
|
||||
|
||||
List<GUID> list2 = new List<GUID>()
|
||||
{
|
||||
guid2,
|
||||
guid1,
|
||||
guid3
|
||||
};
|
||||
|
||||
AddressableAssetGroup group = m_Settings.CreateGroup("AddHashTestGroup", false, false, false,
|
||||
new List<AddressableAssetGroupSchema>());
|
||||
m_Settings.CreateOrMoveEntry(guid1.ToString(), group);
|
||||
m_Settings.CreateOrMoveEntry(guid2.ToString(), group);
|
||||
m_Settings.CreateOrMoveEntry(guid3.ToString(), group);
|
||||
|
||||
IDependencyData dependencyData = new BuildDependencyData()
|
||||
{
|
||||
AssetInfo =
|
||||
{
|
||||
{guid1, new AssetLoadInfo() {referencedObjects = ContentBuildInterface.GetPlayerObjectIdentifiersInAsset(guid1, EditorUserBuildSettings.activeBuildTarget).ToList()}},
|
||||
{guid2, new AssetLoadInfo() {referencedObjects = ContentBuildInterface.GetPlayerObjectIdentifiersInAsset(guid2, EditorUserBuildSettings.activeBuildTarget).ToList()}},
|
||||
{
|
||||
guid3, new AssetLoadInfo() {referencedObjects = ContentBuildInterface.GetPlayerObjectIdentifiersInAsset(guid3, EditorUserBuildSettings.activeBuildTarget).ToList()}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
AddressableAssetsBuildContext context = new AddressableAssetsBuildContext()
|
||||
{
|
||||
Settings = m_Settings
|
||||
};
|
||||
|
||||
AddHashToBundleNameTask addHashTask = new AddHashToBundleNameTask();
|
||||
var field = typeof(AddHashToBundleNameTask).GetField("m_DependencyData", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
field.SetValue(addHashTask, dependencyData);
|
||||
|
||||
//Test
|
||||
RawHash hash1 = addHashTask.GetAssetsHash(list1, context);
|
||||
RawHash hash2 = addHashTask.GetAssetsHash(list2, context);
|
||||
|
||||
//Assert
|
||||
Assert.AreEqual(hash1, hash2);
|
||||
|
||||
//Cleanup
|
||||
m_Settings.RemoveGroup(group);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 47c8f9980c2f63349a8fb20e6e1b5013
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,54 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using NUnit.Framework;
|
||||
using UnityEditor;
|
||||
using UnityEditor.AddressableAssets.Build.BuildPipelineTasks;
|
||||
using UnityEditor.AddressableAssets.Settings;
|
||||
using UnityEngine;
|
||||
|
||||
public class AddressableBuildTaskTestBase
|
||||
{
|
||||
protected AddressableAssetSettings m_Settings;
|
||||
|
||||
protected string TempPath
|
||||
{
|
||||
get { return $"Assets/{GetType().Name}TestData"; }
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
using (new IgnoreFailingLogMessage())
|
||||
{
|
||||
if (AssetDatabase.IsValidFolder(TempPath))
|
||||
AssetDatabase.DeleteAsset(TempPath);
|
||||
Directory.CreateDirectory(TempPath);
|
||||
|
||||
m_Settings = AddressableAssetSettings.Create(Path.Combine(TempPath, "Settings"),
|
||||
"AddressableAssetSettings.Tests", false, true);
|
||||
}
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void Teardown()
|
||||
{
|
||||
// Many of the tests keep recreating assets in the same path, so we need to unload them completely so they don't get reused by the next test
|
||||
AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(m_Settings));
|
||||
Resources.UnloadAsset(m_Settings);
|
||||
if (Directory.Exists(TempPath))
|
||||
Directory.Delete(TempPath, true);
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
protected static string CreateAsset(string assetPath, string objectName)
|
||||
{
|
||||
GameObject go = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
go.name = objectName;
|
||||
//this is to ensure that bundles are different for every run.
|
||||
go.transform.localPosition = UnityEngine.Random.onUnitSphere;
|
||||
PrefabUtility.SaveAsPrefabAsset(go, assetPath);
|
||||
UnityEngine.Object.DestroyImmediate(go, false);
|
||||
return AssetDatabase.AssetPathToGUID(assetPath);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0fc8c72284fb9414ca3384e659772838
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,146 @@
|
|||
#if UNITY_2021_2_OR_NEWER
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEditor.AddressableAssets;
|
||||
using UnityEditor.AddressableAssets.Settings;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
|
||||
public class AddressablesPlayerBuildProcessorTests
|
||||
{
|
||||
protected static string TestFolder => $"Assets/AddressablesPlayerBuildProcessor_Tests";
|
||||
protected static string ConfigFolder => TestFolder + "/Config";
|
||||
|
||||
AddressableAssetSettings m_Settings;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
DirectoryUtility.DeleteDirectory(TestFolder, false);
|
||||
Directory.CreateDirectory(ConfigFolder);
|
||||
m_Settings = AddressableAssetSettings.Create(ConfigFolder, "AddressableAssetSettings.Tests", true, true);
|
||||
CreateAddressablePrefab("test");
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void Teardown()
|
||||
{
|
||||
AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(m_Settings));
|
||||
Resources.UnloadAsset(m_Settings);
|
||||
DirectoryUtility.DeleteDirectory(TestFolder, false);
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
AddressableAssetEntry CreateAddressablePrefab(string name, AddressableAssetGroup group = null)
|
||||
{
|
||||
string guid = CreateAsset(name);
|
||||
return MakeAddressable(guid, null, group);
|
||||
}
|
||||
|
||||
static string CreateAsset(string name)
|
||||
{
|
||||
string assetPath = $"{TestFolder}/{name}.prefab";
|
||||
return CreateAsset(assetPath, name);
|
||||
}
|
||||
|
||||
static string CreateAsset(string assetPath, string objectName)
|
||||
{
|
||||
GameObject go = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
go.name = objectName;
|
||||
//this is to ensure that bundles are different for every run.
|
||||
go.transform.localPosition = UnityEngine.Random.onUnitSphere;
|
||||
PrefabUtility.SaveAsPrefabAsset(go, assetPath);
|
||||
UnityEngine.Object.DestroyImmediate(go, false);
|
||||
return AssetDatabase.AssetPathToGUID(assetPath);
|
||||
}
|
||||
|
||||
AddressableAssetEntry MakeAddressable(string guid, string address = null, AddressableAssetGroup group = null)
|
||||
{
|
||||
if (group == null)
|
||||
{
|
||||
if (m_Settings.DefaultGroup == null)
|
||||
throw new System.Exception("No DefaultGroup to assign Addressable to");
|
||||
group = m_Settings.DefaultGroup;
|
||||
}
|
||||
|
||||
var entry = m_Settings.CreateOrMoveEntry(guid, group, false, false);
|
||||
entry.address = address == null ? entry.AssetPath : address;
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
[TestCase(AddressableAssetSettings.PlayerBuildOption.DoNotBuildWithPlayer, false)]
|
||||
[TestCase(AddressableAssetSettings.PlayerBuildOption.BuildWithPlayer, false)]
|
||||
[TestCase(AddressableAssetSettings.PlayerBuildOption.PreferencesValue, false)]
|
||||
[TestCase(AddressableAssetSettings.PlayerBuildOption.PreferencesValue, true)]
|
||||
public void PrepareAddressableBuildForPlayerBuild_ShouldBuildAddressables_CorrectForSettings(int settingValue, bool preferencesValue)
|
||||
{
|
||||
// Setup
|
||||
m_Settings.BuildAddressablesWithPlayerBuild = (AddressableAssetSettings.PlayerBuildOption)settingValue;
|
||||
bool deleteKey = !EditorPrefs.HasKey(AddressablesPreferences.kBuildAddressablesWithPlayerBuildKey);
|
||||
bool previousPrefValue = EditorPrefs.GetBool(AddressablesPreferences.kBuildAddressablesWithPlayerBuildKey, true);
|
||||
EditorPrefs.SetBool(AddressablesPreferences.kBuildAddressablesWithPlayerBuildKey, preferencesValue);
|
||||
|
||||
try
|
||||
{
|
||||
bool result = AddressablesPlayerBuildProcessor.ShouldBuildAddressablesForPlayerBuild(m_Settings);
|
||||
if (m_Settings.BuildAddressablesWithPlayerBuild == AddressableAssetSettings.PlayerBuildOption.BuildWithPlayer)
|
||||
Assert.IsTrue(result, "Addressables build was expected to set to build when preparing a Player Build");
|
||||
else if (m_Settings.BuildAddressablesWithPlayerBuild == AddressableAssetSettings.PlayerBuildOption.DoNotBuildWithPlayer)
|
||||
Assert.IsFalse(result, "Addressables build is not expected to set be build when preparing a Player Build");
|
||||
else if (m_Settings.BuildAddressablesWithPlayerBuild == AddressableAssetSettings.PlayerBuildOption.DoNotBuildWithPlayer)
|
||||
{
|
||||
if (preferencesValue)
|
||||
Assert.IsTrue(result, "Addressables build was expected to set to build when preparing a Player Build");
|
||||
else
|
||||
Assert.IsFalse(result, "Addressables build is not expected to set be build when preparing a Player Build");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Assert.Fail("Unhandled Exception in Preparing for Addressables - With Exception: " + e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (deleteKey)
|
||||
EditorPrefs.DeleteKey(AddressablesPreferences.kBuildAddressablesWithPlayerBuildKey);
|
||||
else
|
||||
EditorPrefs.SetBool(AddressablesPreferences.kBuildAddressablesWithPlayerBuildKey, previousPrefValue);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PrepareAddressableBuildForPlayerBuild_LinkXML_CopiedCorrectly()
|
||||
{
|
||||
string buildPath = Addressables.BuildPath + "/AddressablesLink/link.xml";
|
||||
Directory.CreateDirectory(Addressables.BuildPath + "/AddressablesLink");
|
||||
bool preexistingFile = File.Exists(buildPath);
|
||||
|
||||
if (!preexistingFile)
|
||||
{
|
||||
var textStream = File.CreateText(buildPath);
|
||||
textStream.Write("link test file");
|
||||
textStream.Close();
|
||||
}
|
||||
|
||||
// do the test
|
||||
string projectPath = Path.Combine(m_Settings.ConfigFolder, "link.xml");
|
||||
try
|
||||
{
|
||||
AddressablesPlayerBuildProcessor.PrepareForPlayerbuild(m_Settings, null, false);
|
||||
Assert.IsTrue(File.Exists(projectPath), "Link.xml file not found at project path when preparing for build");
|
||||
}
|
||||
// clean up
|
||||
finally
|
||||
{
|
||||
AddressablesPlayerBuildProcessor.RemovePlayerBuildLinkXML(m_Settings);
|
||||
if (!preexistingFile)
|
||||
File.Delete(buildPath);
|
||||
Assert.IsFalse(File.Exists(projectPath), "Link.xml file remains at the ProjectPath, link.xml expected to be deleted");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 41f1a51b4873d473d81bc70abb55d198
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,719 @@
|
|||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEditor;
|
||||
using UnityEditor.AddressableAssets.Build.BuildPipelineTasks;
|
||||
using UnityEditor.AddressableAssets.Build.DataBuilders;
|
||||
using UnityEditor.AddressableAssets.Build.Layout;
|
||||
using UnityEditor.AddressableAssets.Settings;
|
||||
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
|
||||
using UnityEditor.AddressableAssets.Tests;
|
||||
using UnityEditor.Build.Pipeline.Utilities;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.U2D;
|
||||
using UnityEditor.U2D;
|
||||
using UnityEditor.Presets;
|
||||
|
||||
public class BuildLayoutGenerationTaskTests
|
||||
{
|
||||
AddressableAssetSettings m_Settings;
|
||||
|
||||
AddressableAssetSettings Settings
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_Settings == null)
|
||||
{
|
||||
var path = Path.Combine(TempPath, "Settings", "/AddressableAssetSettings.Tests.asset");
|
||||
m_Settings = AssetDatabase.LoadAssetAtPath<AddressableAssetSettings>(path);
|
||||
}
|
||||
|
||||
return m_Settings;
|
||||
}
|
||||
}
|
||||
|
||||
static string kTempPath = "Assets/BuildLayoutGenerationTaskTestsData";
|
||||
static string TempPath;
|
||||
static int ExecCount;
|
||||
bool m_PrevGenerateBuildLayout;
|
||||
ProjectConfigData.ReportFileFormat m_PrevFileFormat;
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void OneTimeSetup()
|
||||
{
|
||||
ExecCount = 0;
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
TempPath = kTempPath + (ExecCount++).ToString();
|
||||
foreach (var fileFormat in Enum.GetValues(typeof(ProjectConfigData.ReportFileFormat)))
|
||||
{
|
||||
string layoutFile = BuildLayoutGenerationTask.GetLayoutFilePathForFormat((ProjectConfigData.ReportFileFormat)fileFormat);
|
||||
if (File.Exists(layoutFile))
|
||||
File.Delete(layoutFile);
|
||||
}
|
||||
|
||||
m_PrevGenerateBuildLayout = ProjectConfigData.GenerateBuildLayout;
|
||||
m_PrevFileFormat = ProjectConfigData.BuildLayoutReportFileFormat;
|
||||
BuildScriptPackedMode.s_SkipCompilePlayerScripts = true;
|
||||
ProjectConfigData.GenerateBuildLayout = true;
|
||||
if (Directory.Exists(TempPath))
|
||||
Directory.Delete(TempPath, true);
|
||||
Directory.CreateDirectory(TempPath);
|
||||
|
||||
m_Settings = AddressableAssetSettings.Create(Path.Combine(TempPath, "Settings"), "AddressableAssetSettings.Tests", false, true);
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void Teardown()
|
||||
{
|
||||
BuildScriptPackedMode.s_SkipCompilePlayerScripts = false;
|
||||
ProjectConfigData.GenerateBuildLayout = m_PrevGenerateBuildLayout;
|
||||
ProjectConfigData.BuildLayoutReportFileFormat = m_PrevFileFormat;
|
||||
// Many of the tests keep recreating assets in the same path, so we need to unload them completely so they don't get reused by the next test
|
||||
AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(Settings));
|
||||
Resources.UnloadAsset(Settings);
|
||||
|
||||
FileUtil.DeleteFileOrDirectory(TempPath);
|
||||
FileUtil.DeleteFileOrDirectory(TempPath + ".meta");
|
||||
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
string MakeAddressable(AddressableAssetGroup group, string guid, string address = null)
|
||||
{
|
||||
var entry = Settings.CreateOrMoveEntry(guid, group, false, false);
|
||||
entry.address = address == null ? Path.GetFileNameWithoutExtension(entry.AssetPath) : address;
|
||||
entry.BundleFileId = "GenericFileId";
|
||||
return guid;
|
||||
}
|
||||
|
||||
// Prefab asset emthods
|
||||
|
||||
static string CreatePrefabAsset(string name)
|
||||
{
|
||||
return CreatePrefabAsset($"{TempPath}/{name}.prefab", name);
|
||||
}
|
||||
|
||||
static string CreatePrefabAsset(string assetPath, string objectName)
|
||||
{
|
||||
GameObject go = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
go.name = objectName;
|
||||
//this is to ensure that bundles are different for every run.
|
||||
go.transform.localPosition = UnityEngine.Random.onUnitSphere;
|
||||
PrefabUtility.SaveAsPrefabAsset(go, assetPath);
|
||||
UnityEngine.Object.DestroyImmediate(go, false);
|
||||
return AssetDatabase.AssetPathToGUID(assetPath);
|
||||
}
|
||||
|
||||
static string CreateScriptableObjectAsset(string assetPath, string objectName)
|
||||
{
|
||||
TestObject.Create(objectName, assetPath);
|
||||
return AssetDatabase.AssetPathToGUID(assetPath);
|
||||
}
|
||||
|
||||
string CreateAddressablePrefab(string name, AddressableAssetGroup group)
|
||||
{
|
||||
string guid = CreatePrefabAsset($"{TempPath}/{name}.prefab", name);
|
||||
return MakeAddressable(group, guid);
|
||||
}
|
||||
|
||||
string CreateAddressableScriptableObject(string name, AddressableAssetGroup group)
|
||||
{
|
||||
string guid = CreateScriptableObjectAsset($"{TempPath}/{name}.asset", name);
|
||||
return MakeAddressable(group, guid);
|
||||
}
|
||||
|
||||
bool DeletePrefab(string name)
|
||||
{
|
||||
string path = $"{TempPath}/{name}.prefab";
|
||||
return AssetDatabase.DeleteAsset(path);
|
||||
}
|
||||
|
||||
bool DeleteScriptableObject(string name)
|
||||
{
|
||||
string path = $"{TempPath}/{name}.asset";
|
||||
return AssetDatabase.DeleteAsset(path);
|
||||
}
|
||||
|
||||
// Texture asset creation
|
||||
|
||||
static string CreateTexture(string name, int size = 32)
|
||||
{
|
||||
string assetPath = $"{TempPath}/{name}.png";
|
||||
var texture = new Texture2D(size, size);
|
||||
var data = ImageConversion.EncodeToPNG(texture);
|
||||
UnityEngine.Object.DestroyImmediate(texture);
|
||||
File.WriteAllBytes(assetPath, data);
|
||||
AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceSynchronousImport | ImportAssetOptions.ForceUpdate);
|
||||
return AssetDatabase.AssetPathToGUID(assetPath);
|
||||
}
|
||||
|
||||
string CreateAddressableTexture(string name, AddressableAssetGroup group, int size = 32)
|
||||
{
|
||||
string guid = CreateTexture(name, size);
|
||||
TextureImporter ti = (TextureImporter)AssetImporter.GetAtPath(AssetDatabase.GUIDToAssetPath(guid));
|
||||
ti.isReadable = false;
|
||||
ti.SaveAndReimport();
|
||||
return MakeAddressable(group, guid);
|
||||
}
|
||||
|
||||
static string CreateSpriteAtlas(string name, string guidTargetTexture)
|
||||
{
|
||||
var sa = new SpriteAtlas();
|
||||
var targetObjects = new UnityEngine.Object[] {AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath(guidTargetTexture))};
|
||||
sa.Add(targetObjects);
|
||||
string saPath = $"{TempPath}/{name}.spriteAtlas";
|
||||
AssetDatabase.CreateAsset(sa, saPath);
|
||||
AssetDatabase.Refresh();
|
||||
return AssetDatabase.AssetPathToGUID(saPath);
|
||||
}
|
||||
|
||||
bool DeleteSpriteAtlas(string name)
|
||||
{
|
||||
string assetPath = $"{TempPath}/{name}.spriteAtlas";
|
||||
return AssetDatabase.DeleteAsset(assetPath);
|
||||
}
|
||||
|
||||
static string CreateSpriteTexture(string name, int size, bool includesSource)
|
||||
{
|
||||
string guid = CreateTexture(name, size);
|
||||
string texturePath = AssetDatabase.GUIDToAssetPath(guid);
|
||||
TextureImporter importer = (TextureImporter)AssetImporter.GetAtPath(AssetDatabase.GUIDToAssetPath(guid));
|
||||
importer.textureType = TextureImporterType.Sprite; // creates a sprite subobject
|
||||
importer.spriteImportMode = SpriteImportMode.Single;
|
||||
importer.SaveAndReimport();
|
||||
return guid;
|
||||
}
|
||||
|
||||
bool DeleteTexture(string name)
|
||||
{
|
||||
string assetPath = $"{TempPath}/{name}.png";
|
||||
return AssetDatabase.DeleteAsset(assetPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a component to Prefab that references assetToReference
|
||||
/// </summary>
|
||||
/// <param name="prefabGUID"></param>
|
||||
/// <param name="assetToReferenceGUID"></param>
|
||||
void MakePefabReference(string prefabGUID, string assetToReferenceGUID)
|
||||
{
|
||||
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(AssetDatabase.GUIDToAssetPath(prefabGUID));
|
||||
UnityEngine.Object target = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(AssetDatabase.GUIDToAssetPath(assetToReferenceGUID));
|
||||
prefab.AddComponent<TestBehaviourWithReference>().Reference = target;
|
||||
}
|
||||
|
||||
AddressableAssetGroup CreateGroup(string name)
|
||||
{
|
||||
return Settings.CreateGroup(name, false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
}
|
||||
|
||||
void PrintText(BuildLayout layout)
|
||||
{
|
||||
MemoryStream stream = new MemoryStream();
|
||||
BuildLayoutPrinter.WriteBundleLayout(stream, layout);
|
||||
string report = Encoding.ASCII.GetString(stream.ToArray());
|
||||
Debug.Log(report);
|
||||
}
|
||||
|
||||
internal BuildLayout BuildAndExtractLayout()
|
||||
{
|
||||
try
|
||||
{
|
||||
BuildLayout layout = null;
|
||||
BuildLayoutGenerationTask.s_LayoutCompleteCallback = (x, y) => layout = y;
|
||||
Settings.BuildPlayerContentImpl();
|
||||
return layout;
|
||||
}
|
||||
finally
|
||||
{
|
||||
BuildLayoutGenerationTask.s_LayoutCompleteCallback = null;
|
||||
}
|
||||
}
|
||||
|
||||
class WebExtractSession : IDisposable
|
||||
{
|
||||
public string DataDirectory;
|
||||
public string[] Files;
|
||||
|
||||
public WebExtractSession(string filePath)
|
||||
{
|
||||
DataDirectory = filePath + "_data";
|
||||
if (Directory.Exists(DataDirectory))
|
||||
throw new Exception("Bundle data directory already exists");
|
||||
|
||||
var baseDir = Path.GetDirectoryName(EditorApplication.applicationPath);
|
||||
var webExtractFiles = Directory.GetFiles(baseDir, "WebExtract*", SearchOption.AllDirectories);
|
||||
string webExtractPath = webExtractFiles[0];
|
||||
|
||||
Assert.IsTrue(File.Exists(filePath), "Param filePath does not point to an existing file.");
|
||||
|
||||
var process = new System.Diagnostics.Process
|
||||
{
|
||||
StartInfo =
|
||||
{
|
||||
FileName = webExtractPath,
|
||||
Arguments = string.Format(@"""{0}""", filePath),
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true
|
||||
}
|
||||
};
|
||||
process.Start();
|
||||
|
||||
var output = process.StandardOutput.ReadToEnd();
|
||||
process.WaitForExit();
|
||||
|
||||
var exitCode = process.ExitCode;
|
||||
process.Close();
|
||||
|
||||
Assert.AreEqual(0, exitCode);
|
||||
Files = Directory.GetFiles(DataDirectory);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Directory.Delete(DataDirectory, true);
|
||||
}
|
||||
}
|
||||
|
||||
internal void AssertEditorBundleDetailsMatchPhysicalBundle(string bundlePath, BuildLayout.Bundle bundle)
|
||||
{
|
||||
Assert.AreEqual(new FileInfo(bundlePath).Length, bundle.FileSize);
|
||||
using (var wes = new WebExtractSession(bundlePath))
|
||||
{
|
||||
Assert.AreEqual(bundle.Files.Sum(x => x.SubFiles.Count), wes.Files.Length);
|
||||
foreach (BuildLayout.SubFile sf in bundle.Files.SelectMany(x => x.SubFiles))
|
||||
{
|
||||
string filename = Path.Combine(wes.DataDirectory, sf.Name);
|
||||
Assert.AreEqual(sf.Size, new FileInfo(filename).Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenBundleReferencesAnotherBundle_ExternalReferenceExists()
|
||||
{
|
||||
string layoutFilePath = BuildLayoutGenerationTask.GetLayoutFilePathForFormat(ProjectConfigData.BuildLayoutReportFileFormat);
|
||||
AddressableAssetGroup group = null;
|
||||
AddressableAssetGroup group2 = null;
|
||||
|
||||
try
|
||||
{
|
||||
// setup
|
||||
group = CreateGroup("Group1");
|
||||
string prefabGUID = CreateAddressablePrefab("p1", group);
|
||||
group2 = CreateGroup("Group2");
|
||||
string g2p1GUID = CreateAddressablePrefab("g2p1", group2);
|
||||
MakePefabReference(prefabGUID, g2p1GUID);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
BuildLayout layout = BuildAndExtractLayout();
|
||||
|
||||
// Test
|
||||
CollectionAssert.Contains(layout.Groups[0].Bundles[0].Dependencies, layout.Groups[1].Bundles[0]);
|
||||
Assert.AreEqual(layout.Groups[0].Bundles[0].Files[0].Assets[0].ExternallyReferencedAssets[0], layout.Groups[1].Bundles[0].Files[0].Assets[0]);
|
||||
}
|
||||
finally // cleanup
|
||||
{
|
||||
if (group != null)
|
||||
Settings.RemoveGroup(group);
|
||||
if (group2 != null)
|
||||
Settings.RemoveGroup(group2);
|
||||
if (File.Exists(layoutFilePath))
|
||||
File.Delete(layoutFilePath);
|
||||
DeletePrefab("p1");
|
||||
DeletePrefab("g2p1");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAssetImplicitlyPulledIntoBundle_ImplicitEntryAndReferencesCreated()
|
||||
{
|
||||
string layoutFilePath = BuildLayoutGenerationTask.GetLayoutFilePathForFormat(ProjectConfigData.BuildLayoutReportFileFormat);
|
||||
AddressableAssetGroup group = null;
|
||||
|
||||
try
|
||||
{
|
||||
// setup
|
||||
group = CreateGroup("Group1");
|
||||
string prefabGUID = CreateAddressablePrefab("p1", group);
|
||||
string aGUID = CreatePrefabAsset("p2");
|
||||
MakePefabReference(prefabGUID, aGUID);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
BuildLayout layout = BuildAndExtractLayout();
|
||||
|
||||
// Test
|
||||
BuildLayout.DataFromOtherAsset oa = layout.Groups[0].Bundles[0].Files[0].OtherAssets.First(x => x.AssetPath.Contains("p2.prefab"));
|
||||
Assert.AreEqual(aGUID, oa.AssetGuid);
|
||||
}
|
||||
finally // cleanup
|
||||
{
|
||||
if (group != null)
|
||||
Settings.RemoveGroup(group);
|
||||
if (File.Exists(layoutFilePath))
|
||||
File.Delete(layoutFilePath);
|
||||
DeletePrefab("p1");
|
||||
DeletePrefab("p2");
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenBundleContainsMultipleFiles_FilesAndSizesMatchArchiveContent()
|
||||
{
|
||||
string layoutFilePath = BuildLayoutGenerationTask.GetLayoutFilePathForFormat(ProjectConfigData.BuildLayoutReportFileFormat);
|
||||
string scenePath = $"{TempPath}/scene.unity";
|
||||
AddressableAssetGroup groupScenes = null;
|
||||
AddressableAssetGroup textureGroup = null;
|
||||
|
||||
try
|
||||
{
|
||||
// setup
|
||||
groupScenes = CreateGroup("SceneGroup");
|
||||
textureGroup = CreateGroup("TextureGroup");
|
||||
|
||||
Scene scene1 = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
|
||||
new GameObject().AddComponent<TestBehaviourWithReference>();
|
||||
EditorSceneManager.SaveScene(scene1, scenePath);
|
||||
Settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(scenePath), groupScenes);
|
||||
EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
|
||||
CreateAddressableTexture("t1", textureGroup, 256);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
BuildLayout layout = BuildAndExtractLayout();
|
||||
|
||||
// Test
|
||||
BundledAssetGroupSchema schema = Settings.groups.First(x => x.HasSchema<BundledAssetGroupSchema>()).GetSchema<BundledAssetGroupSchema>();
|
||||
string path = schema.BuildPath.GetValue(Settings);
|
||||
foreach (BuildLayout.Bundle bundle in layout.Groups.SelectMany(x => x.Bundles))
|
||||
AssertEditorBundleDetailsMatchPhysicalBundle(Path.Combine(path, bundle.Name), bundle);
|
||||
}
|
||||
finally // cleanup
|
||||
{
|
||||
if (groupScenes != null)
|
||||
Settings.RemoveGroup(groupScenes);
|
||||
if (textureGroup != null)
|
||||
Settings.RemoveGroup(textureGroup);
|
||||
if (File.Exists(layoutFilePath))
|
||||
File.Delete(layoutFilePath);
|
||||
AssetDatabase.DeleteAsset(scenePath);
|
||||
DeleteTexture("t1");
|
||||
}
|
||||
}
|
||||
|
||||
// Even though slim writes is true, the system will enable it if it needs to generate a build layout report
|
||||
[Test]
|
||||
public void WhenSlimWriteResultsIsTrue_LayoutStillGenerated()
|
||||
{
|
||||
ProjectConfigData.ReportFileFormat fileFormat = ProjectConfigData.ReportFileFormat.TXT;
|
||||
string layoutFilePath = BuildLayoutGenerationTask.GetLayoutFilePathForFormat(fileFormat);
|
||||
AddressableAssetGroup group = null;
|
||||
bool prevSlim = ScriptableBuildPipeline.slimWriteResults;
|
||||
ProjectConfigData.ReportFileFormat prevFileFormat = ProjectConfigData.BuildLayoutReportFileFormat;
|
||||
|
||||
try
|
||||
{
|
||||
// setup
|
||||
ScriptableBuildPipeline.slimWriteResults = true;
|
||||
ProjectConfigData.BuildLayoutReportFileFormat = fileFormat;
|
||||
group = CreateGroup("Group1");
|
||||
CreateAddressablePrefab("p1", group);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
BuildAndExtractLayout();
|
||||
|
||||
FileAssert.Exists(layoutFilePath);
|
||||
}
|
||||
finally // cleanup
|
||||
{
|
||||
ScriptableBuildPipeline.slimWriteResults = prevSlim;
|
||||
ProjectConfigData.BuildLayoutReportFileFormat = prevFileFormat;
|
||||
if (group != null)
|
||||
Settings.RemoveGroup(group);
|
||||
if (File.Exists(layoutFilePath))
|
||||
File.Delete(layoutFilePath);
|
||||
DeletePrefab("p1");
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenBuildLayoutIsDisabled_BuildLayoutIsNotGenerated()
|
||||
{
|
||||
ProjectConfigData.ReportFileFormat fileFormat = ProjectConfigData.ReportFileFormat.TXT;
|
||||
string layoutFilePath = BuildLayoutGenerationTask.GetLayoutFilePathForFormat(fileFormat);
|
||||
AddressableAssetGroup group = null;
|
||||
bool prevGenerateBuildLayout = ProjectConfigData.GenerateBuildLayout;
|
||||
ProjectConfigData.ReportFileFormat prevFileFormat = ProjectConfigData.BuildLayoutReportFileFormat;
|
||||
|
||||
try
|
||||
{
|
||||
// setup
|
||||
ProjectConfigData.GenerateBuildLayout = false;
|
||||
ProjectConfigData.BuildLayoutReportFileFormat = fileFormat;
|
||||
group = CreateGroup("Group1");
|
||||
CreateAddressablePrefab("p1", group);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
BuildAndExtractLayout();
|
||||
|
||||
// Test
|
||||
FileAssert.DoesNotExist(layoutFilePath);
|
||||
}
|
||||
finally // cleanup
|
||||
{
|
||||
ProjectConfigData.GenerateBuildLayout = prevGenerateBuildLayout;
|
||||
ProjectConfigData.BuildLayoutReportFileFormat = prevFileFormat;
|
||||
if (group != null)
|
||||
Settings.RemoveGroup(group);
|
||||
if (File.Exists(layoutFilePath))
|
||||
File.Delete(layoutFilePath);
|
||||
DeletePrefab("p1");
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(ProjectConfigData.ReportFileFormat.TXT)]
|
||||
[TestCase(ProjectConfigData.ReportFileFormat.JSON)]
|
||||
public void WhenBuildLayoutIsEnabled_BuildLayoutIsGenerated(ProjectConfigData.ReportFileFormat format)
|
||||
{
|
||||
string layoutFilePath = BuildLayoutGenerationTask.GetLayoutFilePathForFormat(format);
|
||||
AddressableAssetGroup group = null;
|
||||
bool prevGenerateBuildLayout = ProjectConfigData.GenerateBuildLayout;
|
||||
ProjectConfigData.ReportFileFormat prevFileFormat = ProjectConfigData.BuildLayoutReportFileFormat;
|
||||
|
||||
try
|
||||
{
|
||||
// setup
|
||||
ProjectConfigData.GenerateBuildLayout = true;
|
||||
ProjectConfigData.BuildLayoutReportFileFormat = format;
|
||||
group = CreateGroup("Group1");
|
||||
CreateAddressablePrefab("p1", group);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
BuildAndExtractLayout();
|
||||
|
||||
// Test
|
||||
FileAssert.Exists(layoutFilePath);
|
||||
if (format == ProjectConfigData.ReportFileFormat.JSON)
|
||||
{
|
||||
string text = File.ReadAllText(layoutFilePath);
|
||||
var layout = JsonUtility.FromJson<BuildLayout>(text);
|
||||
Assert.IsNotNull(layout);
|
||||
}
|
||||
}
|
||||
finally // cleanup
|
||||
{
|
||||
ProjectConfigData.GenerateBuildLayout = prevGenerateBuildLayout;
|
||||
ProjectConfigData.BuildLayoutReportFileFormat = prevFileFormat;
|
||||
if (group != null)
|
||||
Settings.RemoveGroup(group);
|
||||
if (File.Exists(layoutFilePath))
|
||||
File.Delete(layoutFilePath);
|
||||
DeletePrefab("p1");
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAssetHasStreamedData_IsReportedCorrectly()
|
||||
{
|
||||
string layoutFilePath = BuildLayoutGenerationTask.GetLayoutFilePathForFormat(ProjectConfigData.BuildLayoutReportFileFormat);
|
||||
AddressableAssetGroup group = null;
|
||||
|
||||
try
|
||||
{
|
||||
// setup
|
||||
group = CreateGroup("Group1");
|
||||
CreateAddressableTexture("t1", group, 256);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
BuildLayout layout = BuildAndExtractLayout();
|
||||
|
||||
// Test
|
||||
Assert.IsTrue(layout.Groups[0].Bundles[0].Files[0].Assets[0].StreamedSize != 0);
|
||||
BuildLayout.SubFile f = layout.Groups[0].Bundles[0].Files[0].SubFiles.First(x => x.Name.EndsWith(".resS"));
|
||||
Assert.IsFalse(f.IsSerializedFile);
|
||||
}
|
||||
finally // cleanup
|
||||
{
|
||||
if (group != null)
|
||||
Settings.RemoveGroup(group);
|
||||
if (File.Exists(layoutFilePath))
|
||||
File.Delete(layoutFilePath);
|
||||
DeleteTexture("t1");
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAllContentsOfAnAssetAreStripped_ExplicitAssetHasNoObjects()
|
||||
{
|
||||
string layoutFilePath = BuildLayoutGenerationTask.GetLayoutFilePathForFormat(ProjectConfigData.BuildLayoutReportFileFormat);
|
||||
AddressableAssetGroup group = null;
|
||||
string assetPath = $"{TempPath}/testpreset.preset";
|
||||
|
||||
try
|
||||
{
|
||||
// setup
|
||||
Material obj = new Material(Shader.Find("Transparent/Diffuse"));
|
||||
Preset myPreset = new Preset(obj);
|
||||
AssetDatabase.CreateAsset(myPreset, assetPath);
|
||||
GameObject.DestroyImmediate(obj);
|
||||
AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceSynchronousImport | ImportAssetOptions.ForceUpdate);
|
||||
string guid = AssetDatabase.AssetPathToGUID(assetPath);
|
||||
group = CreateGroup("Group1");
|
||||
MakeAddressable(group, guid);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
BuildLayout layout = BuildAndExtractLayout();
|
||||
|
||||
// Test
|
||||
Assert.AreEqual(0, layout.Groups[0].Bundles[0].Files[0].Assets[0].SerializedSize);
|
||||
}
|
||||
finally // cleanup
|
||||
{
|
||||
if (group != null)
|
||||
Settings.RemoveGroup(group);
|
||||
if (File.Exists(layoutFilePath))
|
||||
File.Delete(layoutFilePath);
|
||||
AssetDatabase.DeleteAsset(assetPath);
|
||||
}
|
||||
}
|
||||
|
||||
class SpritePackerScope : IDisposable
|
||||
{
|
||||
SpritePackerMode m_PrevMode;
|
||||
|
||||
public SpritePackerScope(SpritePackerMode mode)
|
||||
{
|
||||
m_PrevMode = EditorSettings.spritePackerMode;
|
||||
EditorSettings.spritePackerMode = mode;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
EditorSettings.spritePackerMode = m_PrevMode;
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenReferencedObjectIdentifiedWithFilename_ObjectRepresentedInDataFromOtherAssets()
|
||||
{
|
||||
using (new SpritePackerScope(SpritePackerMode.BuildTimeOnlyAtlas))
|
||||
{
|
||||
string layoutFilePath = BuildLayoutGenerationTask.GetLayoutFilePathForFormat(ProjectConfigData.BuildLayoutReportFileFormat);
|
||||
AddressableAssetGroup group = null;
|
||||
|
||||
try
|
||||
{
|
||||
// setup
|
||||
BuildCache.PurgeCache(false);
|
||||
group = CreateGroup("Group1");
|
||||
string textureGUID = CreateSpriteTexture("spritetexture", 256, false);
|
||||
MakeAddressable(group, CreateSpriteAtlas("atlas", textureGUID));
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
BuildLayout layout = BuildAndExtractLayout();
|
||||
|
||||
// Test
|
||||
BuildLayout.DataFromOtherAsset otherAssets = layout.Groups[0].Bundles[0].Files[0].Assets[0].InternalReferencedOtherAssets[0];
|
||||
Assert.AreEqual(2, layout.Groups[0].Bundles[0].Files[0].Assets[0].InternalReferencedOtherAssets.Count);
|
||||
CollectionAssert.Contains(otherAssets.ReferencingAssets, layout.Groups[0].Bundles[0].Files[0].Assets[0]);
|
||||
}
|
||||
finally // cleanup
|
||||
{
|
||||
if (group != null)
|
||||
Settings.RemoveGroup(group);
|
||||
if (File.Exists(layoutFilePath))
|
||||
File.Delete(layoutFilePath);
|
||||
DeleteSpriteAtlas("atlas");
|
||||
DeleteTexture("spritetexture");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenBuildRemoteCatalogIsDisabled_BuildLayoutContainsCatalogHash()
|
||||
{
|
||||
string layoutFilePath = BuildLayoutGenerationTask.GetLayoutFilePathForFormat(ProjectConfigData.BuildLayoutReportFileFormat);
|
||||
AddressableAssetGroup group = null;
|
||||
bool prevBuildRemoteCatalog = Settings.BuildRemoteCatalog;
|
||||
|
||||
try
|
||||
{
|
||||
// setup
|
||||
group = CreateGroup("Group1");
|
||||
CreateAddressablePrefab("p1", group);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
BuildLayout layout = BuildAndExtractLayout();
|
||||
|
||||
// Test
|
||||
Assert.IsFalse(string.IsNullOrEmpty(layout.AddressablesRuntimeSettings.CatalogHash), "Catalog Hash was not correctly written to the Layout");
|
||||
Assert.AreEqual(32, layout.AddressablesRuntimeSettings.CatalogHash.Length, "Catalog Hash was not correctly written to the Layout, incorrect size for hash");
|
||||
Assert.AreEqual(32, layout.BuildResultHash.Length, "Build is expected to have a result hash for the build");
|
||||
}
|
||||
finally // cleanup
|
||||
{
|
||||
Settings.BuildRemoteCatalog = prevBuildRemoteCatalog;
|
||||
if (group != null)
|
||||
Settings.RemoveGroup(group);
|
||||
if (File.Exists(layoutFilePath))
|
||||
File.Delete(layoutFilePath);
|
||||
DeletePrefab("p1");
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenBuildContainsMonoScripts_LayoutDoesNotHaveReferencesToMonoScriptAssets()
|
||||
{
|
||||
string layoutFilePath = BuildLayoutGenerationTask.GetLayoutFilePathForFormat(ProjectConfigData.BuildLayoutReportFileFormat);
|
||||
AddressableAssetGroup group = null;
|
||||
bool prevBuildRemoteCatalog = Settings.BuildRemoteCatalog;
|
||||
|
||||
try
|
||||
{
|
||||
// setup
|
||||
group = CreateGroup("Group1");
|
||||
CreateAddressableScriptableObject("so1", group);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
BuildLayout layout = BuildAndExtractLayout();
|
||||
|
||||
// Test
|
||||
foreach (BuildLayout.ExplicitAsset explicitAsset in BuildLayoutHelpers.EnumerateAssets(layout))
|
||||
{
|
||||
foreach (var referencedAsset in explicitAsset.InternalReferencedExplicitAssets)
|
||||
{
|
||||
Assert.IsNotNull(referencedAsset, "Referenced Asset was null, this was likely a stripped MonoScript");
|
||||
Assert.IsTrue(!referencedAsset.AssetPath.EndsWith(".cs") && referencedAsset.AssetPath.EndsWith(".dll"));
|
||||
}
|
||||
foreach (var referencedAsset in explicitAsset.ExternallyReferencedAssets)
|
||||
{
|
||||
Assert.IsNotNull(referencedAsset, "Referenced Asset was null, this was likely a stripped MonoScript");
|
||||
Assert.IsTrue(!referencedAsset.AssetPath.EndsWith(".cs") && referencedAsset.AssetPath.EndsWith(".dll"));
|
||||
}
|
||||
foreach (var referencedAsset in explicitAsset.InternalReferencedOtherAssets)
|
||||
{
|
||||
Assert.IsNotNull(referencedAsset, "Referenced Asset was null, this was likely a stripped MonoScript");
|
||||
Assert.IsTrue(!referencedAsset.AssetPath.EndsWith(".cs") && referencedAsset.AssetPath.EndsWith(".dll"));
|
||||
}
|
||||
}
|
||||
}
|
||||
finally // cleanup
|
||||
{
|
||||
Settings.BuildRemoteCatalog = prevBuildRemoteCatalog;
|
||||
if (group != null)
|
||||
Settings.RemoveGroup(group);
|
||||
if (File.Exists(layoutFilePath))
|
||||
File.Delete(layoutFilePath);
|
||||
DeleteScriptableObject("so1");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 041ea21fa30a4a34fa6cfe55505b452c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,131 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using UnityEditor.AddressableAssets.Build;
|
||||
using UnityEditor.AddressableAssets.GUI;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using static UnityEditor.AddressableAssets.GUI.AddressableAssetsSettingsGroupEditor;
|
||||
|
||||
namespace UnityEditor.AddressableAssets.Tests
|
||||
{
|
||||
public class BuildMenuTests : AddressableAssetTestBase
|
||||
{
|
||||
[HideBuildMenuInUI]
|
||||
public class BaseTestBuildMenu : AddressableAssetsSettingsGroupEditor.IAddressablesBuildMenu
|
||||
{
|
||||
public virtual string BuildMenuPath
|
||||
{
|
||||
get => "";
|
||||
}
|
||||
|
||||
public virtual bool SelectableBuildScript
|
||||
{
|
||||
get => true;
|
||||
}
|
||||
|
||||
public virtual int Order
|
||||
{
|
||||
get => 0;
|
||||
}
|
||||
|
||||
public virtual bool OnPrebuild(AddressablesDataBuilderInput input)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual bool OnPostbuild(AddressablesDataBuilderInput input, AddressablesPlayerBuildResult result)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public class TestBuildMenu : BaseTestBuildMenu
|
||||
{
|
||||
public override bool OnPrebuild(AddressablesDataBuilderInput input)
|
||||
{
|
||||
Debug.Log("Pre Invoked");
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool OnPostbuild(AddressablesDataBuilderInput input, AddressablesPlayerBuildResult result)
|
||||
{
|
||||
Debug.Log("Post Invoked");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public class TestBuildMenuOrderZero : BaseTestBuildMenu
|
||||
{
|
||||
public override string BuildMenuPath => "Zero";
|
||||
public override int Order => 0;
|
||||
}
|
||||
|
||||
public class TestBuildMenuOrderMinusOne : BaseTestBuildMenu
|
||||
{
|
||||
public override string BuildMenuPath => "MinusOne";
|
||||
public override int Order => -1;
|
||||
}
|
||||
|
||||
public class TestBuildMenuOrderOne : BaseTestBuildMenu
|
||||
{
|
||||
public override string BuildMenuPath => "One";
|
||||
public override int Order => 1;
|
||||
}
|
||||
|
||||
public class TestBuildMenu1_BuildPathTest : BaseTestBuildMenu
|
||||
{
|
||||
public override string BuildMenuPath => "Test";
|
||||
}
|
||||
|
||||
public class TestBuildMenu2_BuildPathTest : BaseTestBuildMenu
|
||||
{
|
||||
public override string BuildMenuPath => "Test";
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildMenu_BuildCorrectlyCallPreAndPost()
|
||||
{
|
||||
AddressableAssetsSettingsGroupEditor.BuildMenuContext context =
|
||||
new AddressableAssetsSettingsGroupEditor.BuildMenuContext();
|
||||
context.BuildMenu = new TestBuildMenu();
|
||||
context.buildScriptIndex = -1;
|
||||
context.Settings = Settings;
|
||||
|
||||
// Test
|
||||
LogAssert.Expect(LogType.Log, "Pre Invoked");
|
||||
LogAssert.Expect(LogType.Log, "Post Invoked");
|
||||
AddressableAssetsSettingsGroupEditor.OnBuildAddressables(context);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildMenu_CreateBuildMenus_CorrectOrder()
|
||||
{
|
||||
List<Type> menuTypes = new List<Type>();
|
||||
// 1, -1, 0
|
||||
menuTypes.Add(typeof(TestBuildMenuOrderOne));
|
||||
menuTypes.Add(typeof(TestBuildMenuOrderMinusOne));
|
||||
menuTypes.Add(typeof(TestBuildMenuOrderZero));
|
||||
var menus = AddressableAssetsSettingsGroupEditor.CreateBuildMenus(menuTypes, true);
|
||||
|
||||
Assert.AreEqual(3, menus.Count, "Failed to get the correct number of build menus");
|
||||
string orderStr = menus[0].Order.ToString();
|
||||
orderStr += "," + menus[1].Order.ToString();
|
||||
orderStr += "," + menus[2].Order.ToString();
|
||||
Assert.AreEqual("-1,0,1", orderStr, "Menus not in the correct order");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildMenu_RemovesConflictingBuildPaths()
|
||||
{
|
||||
List<Type> menuTypes = new List<Type>();
|
||||
menuTypes.Add(typeof(TestBuildMenu1_BuildPathTest));
|
||||
menuTypes.Add(typeof(TestBuildMenu2_BuildPathTest));
|
||||
LogAssert.Expect(LogType.Warning,
|
||||
"Trying to new build menu [UnityEditor.AddressableAssets.Tests.BuildMenuTests+TestBuildMenu2_BuildPathTest] with path \"Test\". But an existing type already exists with that path, [UnityEditor.AddressableAssets.Tests.BuildMenuTests+TestBuildMenu1_BuildPathTest].");
|
||||
var menus = AddressableAssetsSettingsGroupEditor.CreateBuildMenus(menuTypes, true);
|
||||
|
||||
Assert.AreEqual(1, menus.Count, "Failed to get the correct number of build menus");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3331e5d5506b4b59975f5b7aee249b67
|
||||
timeCreated: 1649164850
|
|
@ -0,0 +1,22 @@
|
|||
using System;
|
||||
using NUnit.Framework;
|
||||
using UnityEditor.AddressableAssets.Build;
|
||||
using UnityEditor.AddressableAssets.Build.DataBuilders;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.AddressableAssets.Tests
|
||||
{
|
||||
public class BuildScriptFastTests : AddressableAssetTestBase
|
||||
{
|
||||
[Test]
|
||||
public void FastModeScript_CannotBuildPlayerContent()
|
||||
{
|
||||
var buildScript = ScriptableObject.CreateInstance<BuildScriptFastMode>();
|
||||
|
||||
Assert.IsFalse(buildScript.CanBuildData<AddressablesPlayerBuildResult>());
|
||||
|
||||
Assert.IsTrue(buildScript.CanBuildData<AddressableAssetBuildResult>());
|
||||
Assert.IsTrue(buildScript.CanBuildData<AddressablesPlayModeBuildResult>());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f1a1c0162fa02cb42ae827251833e0bb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,126 @@
|
|||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEditor.AddressableAssets.Build;
|
||||
using UnityEditor.AddressableAssets.Build.DataBuilders;
|
||||
using UnityEditor.AddressableAssets.Settings;
|
||||
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
|
||||
using UnityEditor.Build.Pipeline.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
public class BuildScriptPackedIntegrationTests
|
||||
{
|
||||
string CreateTexture(string path)
|
||||
{
|
||||
var data = ImageConversion.EncodeToPNG(new Texture2D(32, 32));
|
||||
File.WriteAllBytes(path, data);
|
||||
AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceSynchronousImport | ImportAssetOptions.ForceUpdate);
|
||||
return AssetDatabase.AssetPathToGUID(path);
|
||||
}
|
||||
|
||||
static IDataBuilder GetBuilderOfType(AddressableAssetSettings settings, Type modeType)
|
||||
{
|
||||
foreach (var db in settings.DataBuilders)
|
||||
{
|
||||
var b = db;
|
||||
if (b.GetType() == modeType)
|
||||
return b as IDataBuilder;
|
||||
}
|
||||
|
||||
throw new Exception("DataBuilder not found");
|
||||
}
|
||||
|
||||
protected string m_SingleTestBuildFolder;
|
||||
protected string m_SingleTestAssetFolder;
|
||||
|
||||
void DeleteSingleTestDirectories()
|
||||
{
|
||||
if (Directory.Exists(m_SingleTestBuildFolder))
|
||||
Directory.Delete(m_SingleTestBuildFolder, true);
|
||||
|
||||
if (Directory.Exists(m_SingleTestAssetFolder))
|
||||
Directory.Delete(m_SingleTestAssetFolder, true);
|
||||
}
|
||||
|
||||
string m_SettingsPath;
|
||||
AddressableAssetSettings m_Settings;
|
||||
|
||||
AddressableAssetSettings Settings
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_Settings == null)
|
||||
m_Settings = AssetDatabase.LoadAssetAtPath<AddressableAssetSettings>(m_SettingsPath);
|
||||
return m_Settings;
|
||||
}
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
m_SingleTestBuildFolder = "Temp/TestBuild";
|
||||
m_SingleTestAssetFolder = "Assets/SingleTestFolder";
|
||||
DeleteSingleTestDirectories();
|
||||
Directory.CreateDirectory(m_SingleTestBuildFolder);
|
||||
Directory.CreateDirectory(m_SingleTestAssetFolder);
|
||||
AddressableAssetSettings settings = AddressableAssetSettings.Create(Path.Combine(m_SingleTestAssetFolder, "Settings"), "AddressableAssetSettings.Tests", false, true);
|
||||
m_SettingsPath = settings.AssetPath;
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
DeleteSingleTestDirectories();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IncrementalBuild_WhenBundleTimestampUnchanged_DoesNotCopy()
|
||||
{
|
||||
AddressableAssetBuildResult result;
|
||||
var group = Settings.CreateGroup("MyTestGroup", true, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
|
||||
var spriteEntry = Settings.CreateOrMoveEntry(CreateTexture($"{m_SingleTestAssetFolder}/testTexture.png"), group, false, false);
|
||||
Settings.profileSettings.SetValue(Settings.activeProfileId, AddressableAssetSettings.kLocalBuildPath, m_SingleTestBuildFolder);
|
||||
Settings.profileSettings.SetValue(Settings.activeProfileId, AddressableAssetSettings.kLocalLoadPath, "Library/LocalLoadPath");
|
||||
|
||||
IDataBuilder b = GetBuilderOfType(Settings, typeof(BuildScriptPackedMode));
|
||||
b.BuildData<AddressableAssetBuildResult>(new AddressablesDataBuilderInput(Settings));
|
||||
|
||||
string[] buildFiles = Directory.GetFiles(m_SingleTestBuildFolder);
|
||||
|
||||
// Build again with a lock on the output bundle. This is how we ensure that the bundle is not written again
|
||||
using (File.Open(buildFiles[0], FileMode.Open, FileAccess.ReadWrite, FileShare.None))
|
||||
result = b.BuildData<AddressableAssetBuildResult>(new AddressablesDataBuilderInput(Settings));
|
||||
|
||||
Assert.AreEqual(1, buildFiles.Length, "There should only be one bundle file in the build output folder");
|
||||
Assert.IsTrue(string.IsNullOrEmpty(result.Error));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IncrementalBuild_WhenBundleTimestampChanges_CopiesNewFile()
|
||||
{
|
||||
var group = Settings.CreateGroup("MyTestGroup", true, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
|
||||
var spriteEntry = Settings.CreateOrMoveEntry(CreateTexture($"{m_SingleTestAssetFolder}/testTexture.png"), group, false, false);
|
||||
Settings.profileSettings.SetValue(Settings.activeProfileId, AddressableAssetSettings.kLocalBuildPath, m_SingleTestBuildFolder);
|
||||
Settings.profileSettings.SetValue(Settings.activeProfileId, AddressableAssetSettings.kLocalLoadPath, "Library/LocalLoadPath");
|
||||
|
||||
IDataBuilder b = GetBuilderOfType(Settings, typeof(BuildScriptPackedMode));
|
||||
b.BuildData<AddressableAssetBuildResult>(new AddressablesDataBuilderInput(Settings));
|
||||
|
||||
string[] buildFiles = Directory.GetFiles(m_SingleTestBuildFolder);
|
||||
|
||||
byte[] initialBundleBytes = File.ReadAllBytes(buildFiles[0]);
|
||||
File.Delete(buildFiles[0]);
|
||||
File.WriteAllText(buildFiles[0], "content");
|
||||
File.SetLastWriteTime(buildFiles[0], new DateTime(2019, 1, 1));
|
||||
|
||||
b.BuildData<AddressableAssetBuildResult>(new AddressablesDataBuilderInput(Settings));
|
||||
|
||||
Assert.AreEqual(1, buildFiles.Length, "There should only be one bundle file in the build output folder");
|
||||
CollectionAssert.AreEqual(initialBundleBytes, File.ReadAllBytes(buildFiles[0]));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b47f3ece14ba6b74e883481b6ef86d53
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,86 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using NUnit.Framework;
|
||||
using UnityEditor.AddressableAssets.Build;
|
||||
using UnityEditor.AddressableAssets.Build.DataBuilders;
|
||||
using UnityEditor.AddressableAssets.Settings;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using UnityEngine.AddressableAssets.Initialization;
|
||||
|
||||
namespace UnityEditor.AddressableAssets.Tests
|
||||
{
|
||||
public class BuildScriptPackedPlayTests : AddressableAssetTestBase
|
||||
{
|
||||
protected override void OnInit()
|
||||
{
|
||||
//Player data must be built before PackPlaymode can be used.
|
||||
var input = new AddressablesDataBuilderInput(Settings);
|
||||
ScriptableObject.CreateInstance<BuildScriptPackedMode>().BuildData<AddressableAssetBuildResult>(input);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PackedPlayModeScript_CannotBuildPlayerContent()
|
||||
{
|
||||
var buildScript = ScriptableObject.CreateInstance<BuildScriptPackedPlayMode>();
|
||||
|
||||
Assert.IsFalse(buildScript.CanBuildData<AddressablesPlayerBuildResult>());
|
||||
|
||||
Assert.IsTrue(buildScript.CanBuildData<AddressableAssetBuildResult>());
|
||||
Assert.IsTrue(buildScript.CanBuildData<AddressablesPlayModeBuildResult>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PackedPlayModeScript_AppendsBuildLog_ForNonStandaloneBuildTarget()
|
||||
{
|
||||
//Setup
|
||||
BuildScriptPackedPlayMode buildScript = ScriptableObject.CreateInstance<BuildScriptPackedPlayMode>();
|
||||
AddressablesDataBuilderInput input = new AddressablesDataBuilderInput(Settings);
|
||||
input.SetAllValues(Settings, BuildTargetGroup.Android, BuildTarget.Android, "");
|
||||
ScriptableObject.CreateInstance<BuildScriptPackedMode>().BuildData<AddressableAssetBuildResult>(input);
|
||||
|
||||
//Test
|
||||
buildScript.BuildData<AddressablesPlayModeBuildResult>(input);
|
||||
var buildLogPath = Addressables.BuildPath + "/buildLogs.json";
|
||||
var logs = JsonUtility.FromJson<PackedPlayModeBuildLogs>(File.ReadAllText(buildLogPath));
|
||||
|
||||
//Cleanup (done early in case of test failure)
|
||||
File.Delete(buildLogPath);
|
||||
|
||||
//Assert
|
||||
Assert.AreEqual(1, logs.RuntimeBuildLogs.Count);
|
||||
Assert.AreEqual(LogType.Warning, logs.RuntimeBuildLogs[0].Type);
|
||||
Assert.AreEqual($"Asset bundles built with build target {input.Target} may not be compatible with running in the Editor.", logs.RuntimeBuildLogs[0].Message);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PackedPlayModeScript_AppendsBuildLog_ForInvalidBuildTarget()
|
||||
{
|
||||
//Setup
|
||||
BuildScriptPackedPlayMode buildScript = ScriptableObject.CreateInstance<BuildScriptPackedPlayMode>();
|
||||
AddressablesDataBuilderInput input = new AddressablesDataBuilderInput(Settings);
|
||||
var settingsPath = Addressables.BuildPath + "/settings.json";
|
||||
var rtd = JsonUtility.FromJson<ResourceManagerRuntimeData>(File.ReadAllText(settingsPath));
|
||||
var buildLogPath = Addressables.BuildPath + "/buildLogs.json";
|
||||
|
||||
string storedBuildTarget = rtd.BuildTarget;
|
||||
string invalidTarget = rtd.BuildTarget = "NotAValidBuildTarget";
|
||||
File.WriteAllText(settingsPath, JsonUtility.ToJson(rtd));
|
||||
|
||||
//Test
|
||||
buildScript.BuildData<AddressablesPlayModeBuildResult>(input);
|
||||
var logs = JsonUtility.FromJson<PackedPlayModeBuildLogs>(File.ReadAllText(buildLogPath));
|
||||
|
||||
//Cleanup (done early in case of test failure)
|
||||
File.Delete(buildLogPath);
|
||||
rtd.BuildTarget = storedBuildTarget;
|
||||
File.WriteAllText(settingsPath, JsonUtility.ToJson(rtd));
|
||||
|
||||
//Assert
|
||||
Assert.AreEqual(1, logs.RuntimeBuildLogs.Count);
|
||||
Assert.AreEqual(LogType.Warning, logs.RuntimeBuildLogs[0].Type);
|
||||
Assert.AreEqual($"Unable to parse build target from initialization data: '{invalidTarget}'.", logs.RuntimeBuildLogs[0].Message);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 49c2c229315d04249b13bbf17069f486
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1f2eff97e91ec624b8d35cecfb1ccf38
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,632 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using NUnit.Framework;
|
||||
using UnityEditor.AddressableAssets.Build;
|
||||
using UnityEditor.AddressableAssets.Build.DataBuilders;
|
||||
using UnityEditor.AddressableAssets.Settings;
|
||||
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
|
||||
using UnityEditor.Build.Pipeline.Utilities;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using UnityEngine.TestTools;
|
||||
|
||||
namespace UnityEditor.AddressableAssets.Tests
|
||||
{
|
||||
public class BuildScriptTests : AddressableAssetTestBase
|
||||
{
|
||||
[TestFixture]
|
||||
class StreamingAssetTests : AddressableAssetTestBase
|
||||
{
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
DirectoryUtility.DeleteDirectory(Application.streamingAssetsPath, recursiveDelete: true);
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
DirectoryUtility.DeleteDirectory(Application.streamingAssetsPath, recursiveDelete: true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ClearCachedData_CleansStreamingAssetFolder()
|
||||
{
|
||||
var context = new AddressablesDataBuilderInput(Settings);
|
||||
|
||||
int builderCount = 0;
|
||||
for (int i = 0; i < Settings.DataBuilders.Count; i++)
|
||||
{
|
||||
var builder = Settings.DataBuilders[i] as IDataBuilder;
|
||||
if (builder.CanBuildData<AddressablesPlayerBuildResult>())
|
||||
{
|
||||
builderCount++;
|
||||
var existingFiles = new HashSet<string>();
|
||||
if (System.IO.Directory.Exists("Assets/StreamingAssets"))
|
||||
{
|
||||
foreach (var f in System.IO.Directory.GetFiles("Assets/StreamingAssets"))
|
||||
existingFiles.Add(f);
|
||||
}
|
||||
|
||||
builder.BuildData<AddressablesPlayerBuildResult>(context);
|
||||
builder.ClearCachedData();
|
||||
if (System.IO.Directory.Exists("Assets/StreamingAssets"))
|
||||
{
|
||||
foreach (var f in System.IO.Directory.GetFiles("Assets/StreamingAssets"))
|
||||
Assert.IsTrue(existingFiles.Contains(f), string.Format("Data Builder {0} did not clean up file {1}", builder.Name, f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Assert.IsTrue(builderCount > 0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Folder_WithSubAssets_GetsBundleFileIdAssigned_DuringBuild()
|
||||
{
|
||||
var context = new AddressablesDataBuilderInput(Settings);
|
||||
string folderGuid = AssetDatabase.CreateFolder(TestFolder, "FolderAsset");
|
||||
string folderPath = $"{TestFolder}/FolderAsset";
|
||||
PrefabUtility.SaveAsPrefabAsset(new GameObject(), $"{folderPath}/subfolderprefab.prefab");
|
||||
|
||||
AddressableAssetEntry folderEntry = Settings.CreateOrMoveEntry(folderGuid, Settings.DefaultGroup);
|
||||
|
||||
Assert.IsTrue(string.IsNullOrEmpty(folderEntry.BundleFileId));
|
||||
|
||||
Settings.ActivePlayerDataBuilder.BuildData<AddressablesPlayerBuildResult>(context);
|
||||
|
||||
Assert.IsTrue(folderEntry.IsFolder);
|
||||
Assert.IsFalse(string.IsNullOrEmpty(folderEntry.BundleFileId));
|
||||
|
||||
//Cleanup
|
||||
AssetDatabase.DeleteAsset(folderPath);
|
||||
Settings.RemoveAssetEntry(folderEntry);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Folder_WithNoSubAssets_DoesNotThrowErrorDuringBuild()
|
||||
{
|
||||
var context = new AddressablesDataBuilderInput(Settings);
|
||||
string folderGuid = AssetDatabase.CreateFolder(TestFolder, "FolderAsset");
|
||||
string folderPath = $"{TestFolder}/FolderAsset";
|
||||
|
||||
AddressableAssetEntry folderEntry = Settings.CreateOrMoveEntry(folderGuid, Settings.DefaultGroup);
|
||||
|
||||
Assert.IsTrue(string.IsNullOrEmpty(folderEntry.BundleFileId));
|
||||
|
||||
Settings.ActivePlayerDataBuilder.BuildData<AddressablesPlayerBuildResult>(context);
|
||||
|
||||
Assert.IsTrue(folderEntry.IsFolder);
|
||||
Assert.IsTrue(string.IsNullOrEmpty(folderEntry.BundleFileId));
|
||||
|
||||
//Cleanup
|
||||
AssetDatabase.DeleteAsset(folderPath);
|
||||
Settings.RemoveAssetEntry(folderEntry);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Folder_DoesNotAssignBundleFileId_ForDynamicallyCreatedSubEntries()
|
||||
{
|
||||
var context = new AddressablesDataBuilderInput(Settings);
|
||||
string folderGuid = AssetDatabase.CreateFolder(TestFolder, "FolderAsset");
|
||||
string folderPath = $"{TestFolder}/FolderAsset";
|
||||
PrefabUtility.SaveAsPrefabAsset(new GameObject(), $"{folderPath}/subfolderprefab.prefab");
|
||||
|
||||
AddressableAssetEntry folderEntry = Settings.CreateOrMoveEntry(folderGuid, Settings.DefaultGroup);
|
||||
|
||||
Settings.ActivePlayerDataBuilder.BuildData<AddressablesPlayerBuildResult>(context);
|
||||
|
||||
Assert.True(string.IsNullOrEmpty(folderEntry.SubAssets[0].BundleFileId));
|
||||
|
||||
//Cleanup
|
||||
AssetDatabase.DeleteAsset(folderPath);
|
||||
Settings.RemoveAssetEntry(folderEntry);
|
||||
}
|
||||
|
||||
#if !UNITY_2021_2_OR_NEWER
|
||||
[Test]
|
||||
public void CopiedStreamingAssetAreCorrectlyDeleted_DirectoriesWithoutImport()
|
||||
{
|
||||
var context = new AddressablesDataBuilderInput(Settings);
|
||||
|
||||
int builderCount = 0;
|
||||
for (int i = 0; i < Settings.DataBuilders.Count; i++)
|
||||
{
|
||||
var builder = Settings.DataBuilders[i] as IDataBuilder;
|
||||
if (builder.CanBuildData<AddressablesPlayerBuildResult>())
|
||||
{
|
||||
builderCount++;
|
||||
|
||||
// confirm that StreamingAssets does not exists before the test
|
||||
Assert.IsFalse(Directory.Exists("Assets/StreamingAssets"));
|
||||
builder.BuildData<AddressablesPlayerBuildResult>(context);
|
||||
|
||||
Assert.IsTrue(Directory.Exists(Addressables.BuildPath));
|
||||
AddressablesPlayerBuildProcessor.CopyTemporaryPlayerBuildData();
|
||||
builder.ClearCachedData();
|
||||
|
||||
Assert.IsTrue(Directory.Exists(Addressables.PlayerBuildDataPath));
|
||||
AddressablesPlayerBuildProcessor.CleanTemporaryPlayerBuildData();
|
||||
Assert.IsFalse(Directory.Exists(Addressables.PlayerBuildDataPath));
|
||||
Assert.IsFalse(Directory.Exists("Assets/StreamingAssets"));
|
||||
}
|
||||
}
|
||||
|
||||
Assert.IsTrue(builderCount > 0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CopiedStreamingAssetAreCorrectlyDeleted_MetaFilesWithImport()
|
||||
{
|
||||
var context = new AddressablesDataBuilderInput(Settings);
|
||||
|
||||
int builderCount = 0;
|
||||
for (int i = 0; i < Settings.DataBuilders.Count; i++)
|
||||
{
|
||||
var builder = Settings.DataBuilders[i] as IDataBuilder;
|
||||
if (builder.CanBuildData<AddressablesPlayerBuildResult>())
|
||||
{
|
||||
builderCount++;
|
||||
|
||||
// confirm that StreamingAssets does not exists before the test
|
||||
DirectoryUtility.DeleteDirectory(Application.streamingAssetsPath, recursiveDelete: true);
|
||||
Assert.IsFalse(Directory.Exists("Assets/StreamingAssets"));
|
||||
builder.BuildData<AddressablesPlayerBuildResult>(context);
|
||||
|
||||
Assert.IsTrue(Directory.Exists(Addressables.BuildPath));
|
||||
AddressablesPlayerBuildProcessor.CopyTemporaryPlayerBuildData();
|
||||
builder.ClearCachedData();
|
||||
|
||||
// confirm that PlayerBuildDataPath is imported to AssetDatabase
|
||||
AssetDatabase.Refresh();
|
||||
Assert.IsTrue(Directory.Exists(Addressables.PlayerBuildDataPath));
|
||||
Assert.IsTrue(File.Exists(Addressables.PlayerBuildDataPath + ".meta"));
|
||||
string relativePath = Addressables.PlayerBuildDataPath.Replace(Application.dataPath, "Assets");
|
||||
Assert.IsTrue(AssetDatabase.IsValidFolder(relativePath), "Copied StreamingAssets folder was not importer as expected");
|
||||
|
||||
AddressablesPlayerBuildProcessor.CleanTemporaryPlayerBuildData();
|
||||
Assert.IsFalse(Directory.Exists(Addressables.PlayerBuildDataPath));
|
||||
Assert.IsFalse(Directory.Exists("Assets/StreamingAssets"));
|
||||
}
|
||||
}
|
||||
|
||||
Assert.IsTrue(builderCount > 0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CopiedStreamingAssetAreCorrectlyDeleted_WithExistingFiles()
|
||||
{
|
||||
var context = new AddressablesDataBuilderInput(Settings);
|
||||
|
||||
int builderCount = 0;
|
||||
for (int i = 0; i < Settings.DataBuilders.Count; i++)
|
||||
{
|
||||
var builder = Settings.DataBuilders[i] as IDataBuilder;
|
||||
if (builder.CanBuildData<AddressablesPlayerBuildResult>())
|
||||
{
|
||||
builderCount++;
|
||||
|
||||
// confirm that StreamingAssets does not exists before the test
|
||||
DirectoryUtility.DeleteDirectory(Application.streamingAssetsPath, recursiveDelete: true);
|
||||
Assert.IsFalse(Directory.Exists("Assets/StreamingAssets"));
|
||||
|
||||
// create StreamingAssets and an extra folder as existing content
|
||||
AssetDatabase.CreateFolder("Assets", "StreamingAssets");
|
||||
AssetDatabase.CreateFolder("Assets/StreamingAssets", "extraFolder");
|
||||
|
||||
builder.BuildData<AddressablesPlayerBuildResult>(context);
|
||||
|
||||
Assert.IsTrue(Directory.Exists(Addressables.BuildPath));
|
||||
AddressablesPlayerBuildProcessor.CopyTemporaryPlayerBuildData();
|
||||
builder.ClearCachedData();
|
||||
|
||||
Assert.IsTrue(Directory.Exists(Addressables.PlayerBuildDataPath));
|
||||
AddressablesPlayerBuildProcessor.CleanTemporaryPlayerBuildData();
|
||||
Assert.IsFalse(Directory.Exists(Addressables.PlayerBuildDataPath));
|
||||
Assert.IsTrue(Directory.Exists("Assets/StreamingAssets"));
|
||||
Assert.IsTrue(Directory.Exists("Assets/StreamingAssets/extraFolder"));
|
||||
|
||||
AssetDatabase.DeleteAsset("Assets/StreamingAssets");
|
||||
}
|
||||
}
|
||||
|
||||
Assert.IsTrue(builderCount > 0);
|
||||
}
|
||||
|
||||
#else
|
||||
[Test]
|
||||
public void AddressablesBuildPlayerProcessor_IncludeAdditionalStreamingAssetsWhenExist()
|
||||
{
|
||||
string path = Addressables.BuildPath;
|
||||
Directory.CreateDirectory(path);
|
||||
var paths = AddressablesPlayerBuildProcessor.GetStreamingAssetPaths();
|
||||
Assert.AreEqual(1, paths.Count, "StreamingAssets paths expected to include Addressables.BuildPath");
|
||||
|
||||
// cleanup
|
||||
Directory.Delete(path);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddressablesBuildPlayerProcessor_DoesntIncludeAdditionalStreamingAssetsWhenDontExist()
|
||||
{
|
||||
if (Directory.Exists(Addressables.BuildPath))
|
||||
DirectoryUtility.DeleteDirectory(Addressables.BuildPath, false);
|
||||
var paths = AddressablesPlayerBuildProcessor.GetStreamingAssetPaths();
|
||||
Assert.AreEqual(0, paths.Count, "StreamingAssets paths are expected to be empty");
|
||||
|
||||
// cleanup
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildScriptBase_FailsCanBuildData()
|
||||
{
|
||||
var buildScript = ScriptableObject.CreateInstance<BuildScriptBase>();
|
||||
Assert.IsFalse(buildScript.CanBuildData<IDataBuilderResult>());
|
||||
Assert.IsFalse(buildScript.CanBuildData<AddressableAssetBuildResult>());
|
||||
Assert.IsFalse(buildScript.CanBuildData<AddressablesPlayModeBuildResult>());
|
||||
Assert.IsFalse(buildScript.CanBuildData<AddressablesPlayerBuildResult>());
|
||||
}
|
||||
|
||||
internal class BuildScriptTestClass : BuildScriptBase
|
||||
{
|
||||
public override string Name
|
||||
{
|
||||
get { return "Test Script"; }
|
||||
}
|
||||
|
||||
public override bool CanBuildData<T>()
|
||||
{
|
||||
return typeof(T).IsAssignableFrom(typeof(AddressablesPlayModeBuildResult));
|
||||
}
|
||||
|
||||
protected override TResult BuildDataImplementation<TResult>(AddressablesDataBuilderInput builderInput)
|
||||
{
|
||||
Debug.LogError("Inside BuildDataInternal for test script!");
|
||||
return base.BuildDataImplementation<TResult>(builderInput);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildScript_DoesNotBuildWrongDataType()
|
||||
{
|
||||
var context = new AddressablesDataBuilderInput(Settings);
|
||||
|
||||
var baseScript = ScriptableObject.CreateInstance<BuildScriptTestClass>();
|
||||
baseScript.BuildData<AddressablesPlayerBuildResult>(context);
|
||||
LogAssert.Expect(LogType.Error, new Regex("Data builder Test Script cannot build requested type.*"));
|
||||
|
||||
baseScript.BuildData<AddressablesPlayModeBuildResult>(context);
|
||||
LogAssert.Expect(LogType.Error, "Inside BuildDataInternal for test script!");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetNameWithHashNaming_ReturnsNoChangeIfNoHash()
|
||||
{
|
||||
string source = "x/y.bundle";
|
||||
string hash = "123abc";
|
||||
string expected = "x/y.bundle";
|
||||
|
||||
var actual = BuildUtility.GetNameWithHashNaming(BundledAssetGroupSchema.BundleNamingStyle.NoHash, hash, source);
|
||||
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetNameWithHashNaming_CanAppendHash()
|
||||
{
|
||||
string source = "x/y.bundle";
|
||||
string hash = "123abc";
|
||||
string expected = "x/y_123abc.bundle";
|
||||
|
||||
var actual = BuildUtility.GetNameWithHashNaming(BundledAssetGroupSchema.BundleNamingStyle.AppendHash, hash, source);
|
||||
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetNameWithHashNaming_CanReplaceFileNameWithHash()
|
||||
{
|
||||
string source = "x/y.bundle";
|
||||
string hash = "123abc";
|
||||
string expected = "123abc.bundle";
|
||||
|
||||
var actual = BuildUtility.GetNameWithHashNaming(BundledAssetGroupSchema.BundleNamingStyle.OnlyHash, hash, source);
|
||||
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetNameWithHashNaming_CanReplaceFileNameWithFileNameHash()
|
||||
{
|
||||
string source = "x/y.bundle";
|
||||
string hash = HashingMethods.Calculate(source).ToString();
|
||||
string expected = hash + ".bundle";
|
||||
|
||||
var actual = BuildUtility.GetNameWithHashNaming(BundledAssetGroupSchema.BundleNamingStyle.FileNameHash, hash, source);
|
||||
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
|
||||
// regression test for https://jira.unity3d.com/browse/ADDR-1292
|
||||
[Test]
|
||||
public void BuildScriptBaseWriteBuildLog_WhenDirectoryDoesNotExist_DirectoryCreated()
|
||||
{
|
||||
string dirName = "SomeTestDir";
|
||||
string logFile = Path.Combine(dirName, "AddressablesBuildTEP.json");
|
||||
try
|
||||
{
|
||||
BuildLog log = new BuildLog();
|
||||
BuildScriptBase.WriteBuildLog(log, dirName);
|
||||
FileAssert.Exists(logFile);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Directory.Delete(dirName, true);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Building_CreatesPerformanceReportWithMetaData()
|
||||
{
|
||||
Settings.BuildPlayerContentImpl();
|
||||
string path = Addressables.LibraryPath + "AddressablesBuildTEP.json";
|
||||
FileAssert.Exists(path);
|
||||
string text = File.ReadAllText(path);
|
||||
StringAssert.Contains("com.unity.addressables", text);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Build_WithInvalidAssetInResourcesFolder_Succeeds()
|
||||
{
|
||||
var path = GetAssetPath("Resources/unknownAsset.plist");
|
||||
if (!System.IO.Directory.Exists(System.IO.Path.GetDirectoryName(path)))
|
||||
System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(path));
|
||||
System.IO.File.WriteAllText(path, "nothing");
|
||||
AssetDatabase.ImportAsset(path);
|
||||
var context = new AddressablesDataBuilderInput(Settings);
|
||||
foreach (IDataBuilder db in Settings.DataBuilders)
|
||||
if (db.CanBuildData<AddressablesPlayerBuildResult>())
|
||||
db.BuildData<AddressablesPlayerBuildResult>(context);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Build_GroupWithPlayerDataGroupSchemaAndBundledAssetGroupSchema_LogsError()
|
||||
{
|
||||
const string groupName = "NewGroup";
|
||||
var schemas = new List<AddressableAssetGroupSchema> {ScriptableObject.CreateInstance<PlayerDataGroupSchema>(), ScriptableObject.CreateInstance<BundledAssetGroupSchema>()};
|
||||
AddressableAssetGroup group = Settings.CreateGroup(groupName, false, false, false, schemas);
|
||||
|
||||
var context = new AddressablesDataBuilderInput(Settings);
|
||||
foreach (IDataBuilder db in Settings.DataBuilders)
|
||||
{
|
||||
if (db.CanBuildData<AddressablesPlayerBuildResult>())
|
||||
{
|
||||
AddressablesPlayerBuildResult result = db.BuildData<AddressablesPlayerBuildResult>(context);
|
||||
Assert.AreEqual(result.Error, $"Addressable group {groupName} cannot have both a {typeof(PlayerDataGroupSchema).Name} and a {typeof(BundledAssetGroupSchema).Name}");
|
||||
}
|
||||
}
|
||||
|
||||
Settings.RemoveGroup(group);
|
||||
}
|
||||
|
||||
// ADDR-1755
|
||||
[Test]
|
||||
public void WhenBundleLocalCatalogEnabled_BuildScriptPacked_DoesNotCreatePerformanceLogReport()
|
||||
{
|
||||
string logPath = $"Library/com.unity.addressables/aa/{PlatformMappingService.GetPlatformPathSubFolder()}/buildlogtep.json";
|
||||
|
||||
if (File.Exists(logPath))
|
||||
File.Delete(logPath);
|
||||
|
||||
Settings.BundleLocalCatalog = true;
|
||||
|
||||
var context = new AddressablesDataBuilderInput(Settings);
|
||||
BuildScriptBase db = (BuildScriptBase)Settings.DataBuilders.Find(x => x.GetType() == typeof(BuildScriptPackedMode));
|
||||
|
||||
Assert.IsFalse(File.Exists(logPath)); // make sure file does not exist before build
|
||||
|
||||
var res = db.BuildData<AddressablesPlayerBuildResult>(context);
|
||||
Assert.IsFalse(File.Exists(logPath));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Build_WithDeletedAsset_Succeeds()
|
||||
{
|
||||
var context = new AddressablesDataBuilderInput(Settings);
|
||||
|
||||
//make an entry with no actual AssetPath
|
||||
Settings.CreateOrMoveEntry("abcde", Settings.DefaultGroup);
|
||||
Settings.CreateOrMoveEntry(m_AssetGUID, Settings.DefaultGroup);
|
||||
foreach (BuildScriptBase db in Settings.DataBuilders.OfType<BuildScriptBase>())
|
||||
{
|
||||
if (db is BuildScriptPackedPlayMode)
|
||||
continue;
|
||||
|
||||
if (db.CanBuildData<AddressablesPlayerBuildResult>())
|
||||
{
|
||||
var res = db.BuildData<AddressablesPlayerBuildResult>(context);
|
||||
Assert.IsTrue(db.IsDataBuilt());
|
||||
Assert.IsTrue(string.IsNullOrEmpty(res.Error));
|
||||
}
|
||||
else if (db.CanBuildData<AddressablesPlayModeBuildResult>())
|
||||
{
|
||||
var res = db.BuildData<AddressablesPlayModeBuildResult>(context);
|
||||
Assert.IsTrue(db.IsDataBuilt());
|
||||
Assert.IsTrue(string.IsNullOrEmpty(res.Error));
|
||||
}
|
||||
}
|
||||
|
||||
Settings.RemoveAssetEntry("abcde", false);
|
||||
Settings.RemoveAssetEntry(m_AssetGUID, false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAddressHasSquareBrackets_AndContentCatalogsAreCreated_BuildFails()
|
||||
{
|
||||
var context = new AddressablesDataBuilderInput(Settings);
|
||||
|
||||
AddressableAssetEntry entry = Settings.CreateOrMoveEntry(m_AssetGUID, Settings.DefaultGroup);
|
||||
entry.address = "[test]";
|
||||
LogAssert.Expect(LogType.Error, $"Address '{entry.address}' cannot contain '[ ]'.");
|
||||
foreach (IDataBuilder db in Settings.DataBuilders)
|
||||
{
|
||||
if (db.GetType() == typeof(BuildScriptFastMode) || db.GetType() == typeof(BuildScriptPackedPlayMode))
|
||||
continue;
|
||||
|
||||
if (db.CanBuildData<AddressablesPlayerBuildResult>())
|
||||
db.BuildData<AddressablesPlayerBuildResult>(context);
|
||||
else if (db.CanBuildData<AddressablesPlayModeBuildResult>())
|
||||
db.BuildData<AddressablesPlayModeBuildResult>(context);
|
||||
LogAssert.Expect(LogType.Error, "Address '[test]' cannot contain '[ ]'.");
|
||||
}
|
||||
|
||||
Settings.RemoveAssetEntry(m_AssetGUID, false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenFileTypeIsInvalid_AndContentCatalogsAreCreated_BuildFails()
|
||||
{
|
||||
var context = new AddressablesDataBuilderInput(Settings);
|
||||
|
||||
string path = GetAssetPath("fake.file");
|
||||
FileStream fs = File.Create(path);
|
||||
fs.Close();
|
||||
AssetDatabase.ImportAsset(path);
|
||||
string guid = AssetDatabase.AssetPathToGUID(path);
|
||||
|
||||
AddressableAssetEntry entry = Settings.CreateOrMoveEntry(guid, Settings.DefaultGroup);
|
||||
|
||||
foreach (IDataBuilder db in Settings.DataBuilders)
|
||||
{
|
||||
if (db.GetType() == typeof(BuildScriptFastMode) ||
|
||||
db.GetType() == typeof(BuildScriptPackedPlayMode))
|
||||
continue;
|
||||
|
||||
if (db.CanBuildData<AddressablesPlayerBuildResult>())
|
||||
db.BuildData<AddressablesPlayerBuildResult>(context);
|
||||
else if (db.CanBuildData<AddressablesPlayModeBuildResult>())
|
||||
db.BuildData<AddressablesPlayModeBuildResult>(context);
|
||||
LogAssert.Expect(LogType.Error,
|
||||
"Cannot recognize file type for entry located at 'Assets/UnityEditor.AddressableAssets.Tests.BuildScriptTests_Tests/fake.file'. Asset import failed for using an unsupported file type.");
|
||||
}
|
||||
|
||||
Settings.RemoveAssetEntry(guid, false);
|
||||
AssetDatabase.DeleteAsset(path);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenFileTypeIsInvalid_AndContentCatalogsAreCreated_IgnoreUnsupportedFilesInBuildIsSet_BuildSucceedWithWarning()
|
||||
{
|
||||
bool oldValue = Settings.IgnoreUnsupportedFilesInBuild;
|
||||
Settings.IgnoreUnsupportedFilesInBuild = true;
|
||||
|
||||
var context = new AddressablesDataBuilderInput(Settings);
|
||||
|
||||
string path = GetAssetPath("fake.file");
|
||||
FileStream fs = File.Create(path);
|
||||
fs.Close();
|
||||
AssetDatabase.ImportAsset(path);
|
||||
string guid = AssetDatabase.AssetPathToGUID(path);
|
||||
|
||||
AddressableAssetEntry entry = Settings.CreateOrMoveEntry(guid, Settings.DefaultGroup);
|
||||
|
||||
foreach (BuildScriptBase db in Settings.DataBuilders.OfType<BuildScriptBase>())
|
||||
{
|
||||
if (db.GetType() == typeof(BuildScriptFastMode) || db.GetType() == typeof(BuildScriptPackedPlayMode))
|
||||
continue;
|
||||
|
||||
if (db.CanBuildData<AddressablesPlayerBuildResult>())
|
||||
{
|
||||
var res = db.BuildData<AddressablesPlayerBuildResult>(context);
|
||||
Assert.IsTrue(db.IsDataBuilt());
|
||||
Assert.IsTrue(string.IsNullOrEmpty(res.Error));
|
||||
}
|
||||
else if (db.CanBuildData<AddressablesPlayModeBuildResult>())
|
||||
{
|
||||
var res = db.BuildData<AddressablesPlayModeBuildResult>(context);
|
||||
Assert.IsTrue(db.IsDataBuilt());
|
||||
Assert.IsTrue(string.IsNullOrEmpty(res.Error));
|
||||
}
|
||||
|
||||
LogAssert.Expect(LogType.Warning, new Regex($".*{path}.*ignored"));
|
||||
LogAssert.Expect(LogType.Warning, new Regex($".*{path}.*stripped"));
|
||||
}
|
||||
|
||||
Settings.RemoveAssetEntry(guid, false);
|
||||
AssetDatabase.DeleteAsset(path);
|
||||
Settings.IgnoreUnsupportedFilesInBuild = oldValue;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenLoadPathUsesHttp_AndInsecureHttpNotAllowed_BuildLogsWarning()
|
||||
{
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
InsecureHttpOption oldHttpOption = PlayerSettings.insecureHttpOption;
|
||||
PlayerSettings.insecureHttpOption = InsecureHttpOption.NotAllowed;
|
||||
|
||||
string remoteLoadPathId = Settings.profileSettings.GetProfileDataByName(AddressableAssetSettings.kRemoteLoadPath).Id;
|
||||
string oldRemoteLoadPath = Settings.profileSettings.GetValueById(Settings.activeProfileId, remoteLoadPathId);
|
||||
Settings.profileSettings.SetValue(Settings.activeProfileId, AddressableAssetSettings.kRemoteLoadPath, "http://insecureconnection/");
|
||||
|
||||
AddressableAssetGroup assetGroup = Settings.CreateGroup("InsecureConnections", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
assetGroup.GetSchema<BundledAssetGroupSchema>().BuildPath.SetVariableById(Settings, Settings.profileSettings.GetProfileDataByName(AddressableAssetSettings.kRemoteBuildPath).Id);
|
||||
assetGroup.GetSchema<BundledAssetGroupSchema>().LoadPath.SetVariableById(Settings, Settings.profileSettings.GetProfileDataByName(AddressableAssetSettings.kRemoteLoadPath).Id);
|
||||
|
||||
string assetPath = Path.Combine(TestFolder, "insecureConnectionsTest.prefab");
|
||||
PrefabUtility.SaveAsPrefabAsset(new GameObject(), assetPath);
|
||||
Settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(assetPath), assetGroup, false, false);
|
||||
|
||||
var context = new AddressablesDataBuilderInput(Settings);
|
||||
BuildScriptBase db = (BuildScriptBase)Settings.DataBuilders.Find(x => x.GetType() == typeof(BuildScriptPackedMode));
|
||||
db.BuildData<AddressablesPlayerBuildResult>(context);
|
||||
LogAssert.Expect(LogType.Warning, $"Addressable group {assetGroup.Name} uses insecure http for its load path. To allow http connections for UnityWebRequests, change your settings in Edit > Project Settings > Player > Other Settings > Configuration > Allow downloads over HTTP.");
|
||||
|
||||
Settings.RemoveGroup(assetGroup);
|
||||
Settings.profileSettings.SetValue(Settings.activeProfileId, AddressableAssetSettings.kRemoteLoadPath, oldRemoteLoadPath);
|
||||
AssetDatabase.DeleteAsset(assetPath);
|
||||
PlayerSettings.insecureHttpOption = oldHttpOption;
|
||||
#else
|
||||
Assert.Ignore($"Skipping test {nameof(WhenLoadPathUsesHttp_AndInsecureHttpNotAllowed_BuildLogsWarning)}.");
|
||||
#endif
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenLoadPathUsesHttp_AndInsecureHttpAllowed_BuildSucceeds()
|
||||
{
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
InsecureHttpOption oldHttpOption = PlayerSettings.insecureHttpOption;
|
||||
PlayerSettings.insecureHttpOption = InsecureHttpOption.AlwaysAllowed;
|
||||
|
||||
string remoteLoadPathId = Settings.profileSettings.GetProfileDataByName(AddressableAssetSettings.kRemoteLoadPath).Id;
|
||||
string oldRemoteLoadPath = Settings.profileSettings.GetValueById(Settings.activeProfileId, remoteLoadPathId);
|
||||
Settings.profileSettings.SetValue(Settings.activeProfileId, AddressableAssetSettings.kRemoteLoadPath, "http://insecureconnection/");
|
||||
|
||||
AddressableAssetGroup assetGroup = Settings.CreateGroup("InsecureConnections", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
assetGroup.GetSchema<BundledAssetGroupSchema>().BuildPath.SetVariableById(Settings, Settings.profileSettings.GetProfileDataByName(AddressableAssetSettings.kRemoteBuildPath).Id);
|
||||
assetGroup.GetSchema<BundledAssetGroupSchema>().LoadPath.SetVariableById(Settings, Settings.profileSettings.GetProfileDataByName(AddressableAssetSettings.kRemoteLoadPath).Id);
|
||||
|
||||
string assetPath = Path.Combine(TestFolder, "insecureConnectionsTest.prefab");
|
||||
PrefabUtility.SaveAsPrefabAsset(new GameObject(), assetPath);
|
||||
Settings.CreateOrMoveEntry(AssetDatabase.AssetPathToGUID(assetPath), assetGroup, false, false);
|
||||
|
||||
var context = new AddressablesDataBuilderInput(Settings);
|
||||
BuildScriptBase db = (BuildScriptBase)Settings.DataBuilders.Find(x => x.GetType() == typeof(BuildScriptPackedMode));
|
||||
db.BuildData<AddressablesPlayerBuildResult>(context);
|
||||
LogAssert.NoUnexpectedReceived();
|
||||
|
||||
Settings.RemoveGroup(assetGroup);
|
||||
Settings.profileSettings.SetValue(Settings.activeProfileId, AddressableAssetSettings.kRemoteLoadPath, oldRemoteLoadPath);
|
||||
AssetDatabase.DeleteAsset(assetPath);
|
||||
PlayerSettings.insecureHttpOption = oldHttpOption;
|
||||
#else
|
||||
Assert.Ignore($"Skipping test {nameof(WhenLoadPathUsesHttp_AndInsecureHttpAllowed_BuildSucceeds)}.");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e3e97670d537e784e9f104552b533056
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,22 @@
|
|||
using System;
|
||||
using NUnit.Framework;
|
||||
using UnityEditor.AddressableAssets.Build;
|
||||
using UnityEditor.AddressableAssets.Build.DataBuilders;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.AddressableAssets.Tests
|
||||
{
|
||||
public class BuildScriptVirtualTests : AddressableAssetTestBase
|
||||
{
|
||||
[Test]
|
||||
public void VirtualModeScript_CannotBuildPlayerContent()
|
||||
{
|
||||
var buildScript = ScriptableObject.CreateInstance<BuildScriptVirtualMode>();
|
||||
|
||||
Assert.IsFalse(buildScript.CanBuildData<AddressablesPlayerBuildResult>());
|
||||
|
||||
Assert.IsTrue(buildScript.CanBuildData<AddressableAssetBuildResult>());
|
||||
Assert.IsTrue(buildScript.CanBuildData<AddressablesPlayModeBuildResult>());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b644b787231a1784ab6bbb39217a63b9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,68 @@
|
|||
using System;
|
||||
using NUnit.Framework;
|
||||
using UnityEditor.AddressableAssets.Build;
|
||||
using UnityEditor.AddressableAssets.Settings;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
|
||||
namespace UnityEditor.AddressableAssets.Tests
|
||||
{
|
||||
public class DataBuilderInputTests : AddressableAssetTestBase
|
||||
{
|
||||
[Test]
|
||||
public void BuildInput_FailsWithNullSettings()
|
||||
{
|
||||
var input = new AddressablesDataBuilderInput(null);
|
||||
LogAssert.Expect(LogType.Error, "Attempting to set up AddressablesDataBuilderInput with null settings.");
|
||||
Assert.AreEqual(string.Empty, input.PlayerVersion);
|
||||
input = new AddressablesDataBuilderInput(null, "123");
|
||||
LogAssert.Expect(LogType.Error, "Attempting to set up AddressablesDataBuilderInput with null settings.");
|
||||
Assert.AreEqual("123", input.PlayerVersion);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildInput_CreatesProperBuildData()
|
||||
{
|
||||
var input = new AddressablesDataBuilderInput(Settings);
|
||||
Assert.AreEqual(EditorUserBuildSettings.activeBuildTarget, input.Target);
|
||||
Assert.AreEqual(BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget), input.TargetGroup);
|
||||
Assert.AreEqual(Settings.PlayerBuildVersion, input.PlayerVersion);
|
||||
|
||||
|
||||
input = new AddressablesDataBuilderInput(Settings, "1234");
|
||||
Assert.AreEqual(EditorUserBuildSettings.activeBuildTarget, input.Target);
|
||||
Assert.AreEqual(BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget), input.TargetGroup);
|
||||
Assert.AreEqual("1234", input.PlayerVersion);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildInput_ReadsProfilerEventState()
|
||||
{
|
||||
var oldState = ProjectConfigData.PostProfilerEvents;
|
||||
ProjectConfigData.PostProfilerEvents = true;
|
||||
var input = new AddressablesDataBuilderInput(Settings);
|
||||
Assert.AreEqual(true, input.ProfilerEventsEnabled);
|
||||
|
||||
ProjectConfigData.PostProfilerEvents = false;
|
||||
input = new AddressablesDataBuilderInput(Settings);
|
||||
Assert.AreEqual(false, input.ProfilerEventsEnabled);
|
||||
|
||||
|
||||
ProjectConfigData.PostProfilerEvents = oldState;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateResult_AssignsAllCorrectData()
|
||||
{
|
||||
string settingsPath = "Settings/Path";
|
||||
int locCount = 2;
|
||||
string error = "Test Error";
|
||||
|
||||
var result = AddressableAssetBuildResult.CreateResult<AddressableAssetBuildResult>(settingsPath, locCount, error);
|
||||
|
||||
Assert.AreEqual(result.OutputPath, settingsPath);
|
||||
Assert.AreEqual(result.LocationCount, locCount);
|
||||
Assert.AreEqual(result.Error, error);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1575d1c3656610c40ad50c15e8f5855a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,314 @@
|
|||
using NUnit.Framework;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEditor.AddressableAssets.Build.BuildPipelineTasks;
|
||||
using UnityEditor.AddressableAssets.Build.DataBuilders;
|
||||
using UnityEditor.AddressableAssets.Settings;
|
||||
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
|
||||
using UnityEditor.Build.Pipeline;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets.ResourceLocators;
|
||||
using UnityEngine.ResourceManagement.ResourceProviders;
|
||||
|
||||
public class GenerateLocationListsTaskTests : AddressableBuildTaskTestBase
|
||||
{
|
||||
GenerateLocationListsTask.Input GenerateDefaultInput()
|
||||
{
|
||||
var input = new GenerateLocationListsTask.Input();
|
||||
input.AssetToFiles = new Dictionary<GUID, List<string>>();
|
||||
input.FileToBundle = new Dictionary<string, string>();
|
||||
input.Settings = m_Settings;
|
||||
input.BundleToAssetGroup = new Dictionary<string, string>();
|
||||
input.Target = EditorUserBuildSettings.activeBuildTarget;
|
||||
return input;
|
||||
}
|
||||
|
||||
private bool FindLocationEntry(List<ContentCatalogDataEntry> locations, string key, out ContentCatalogDataEntry entry)
|
||||
{
|
||||
foreach (ContentCatalogDataEntry e in locations)
|
||||
if (e.Keys.Contains(key))
|
||||
{
|
||||
entry = e;
|
||||
return true;
|
||||
}
|
||||
|
||||
entry = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
static K GetKeyForValue<K, V>(Dictionary<K, V> dict, V value) where V : class
|
||||
{
|
||||
foreach (var kvp in dict)
|
||||
{
|
||||
if (kvp.Value == value)
|
||||
return kvp.Key;
|
||||
}
|
||||
|
||||
throw new System.Exception("Couldn't find value");
|
||||
}
|
||||
|
||||
string CreateAddressablePrefab(GenerateLocationListsTask.Input input, string name, AddressableAssetGroup group, params string[] depFiles)
|
||||
{
|
||||
string guid = CreateAsset($"{TempPath}/{name}.prefab", name);
|
||||
var entry = m_Settings.CreateOrMoveEntry(guid, group, false, false);
|
||||
entry.address = Path.GetFileNameWithoutExtension(entry.AssetPath);
|
||||
input.AssetToFiles[new GUID(guid)] = new List<string>(depFiles);
|
||||
return guid;
|
||||
}
|
||||
|
||||
AddressableAssetGroup CreateGroupMappedToBundle(GenerateLocationListsTask.Input input, string postfix)
|
||||
{
|
||||
AddressableAssetGroup group = m_Settings.CreateGroup($"testGroup{postfix}", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
input.BundleToAssetGroup[$"bundle{postfix}"] = group.Guid;
|
||||
input.FileToBundle[$"file{postfix}"] = $"bundle{postfix}";
|
||||
return group;
|
||||
}
|
||||
|
||||
void AssertLocationDependencies(GenerateLocationListsTask.Output output, string location, params string[] deps)
|
||||
{
|
||||
FindLocationEntry(output.Locations, location, out ContentCatalogDataEntry e1);
|
||||
CollectionAssert.AreEquivalent(e1.Dependencies, deps);
|
||||
}
|
||||
|
||||
static List<AddressableAssetEntry> BuildAddressableAssetEntryList(AddressableAssetSettings settings)
|
||||
{
|
||||
List<AddressableAssetEntry> entries = new List<AddressableAssetEntry>();
|
||||
foreach (AddressableAssetGroup group in settings.groups)
|
||||
{
|
||||
group.GatherAllAssets(entries, true, true, false);
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAssetLoadsFromBundle_ProviderTypesIncludesBundledAssetProvider()
|
||||
{
|
||||
GenerateLocationListsTask.Input input = GenerateDefaultInput();
|
||||
AddressableAssetGroup groupX = CreateGroupMappedToBundle(input, "X");
|
||||
CreateAddressablePrefab(input, "p1", groupX, "fileX");
|
||||
input.AddressableAssetEntries = BuildAddressableAssetEntryList(input.Settings);
|
||||
GenerateLocationListsTask.Output output = GenerateLocationListsTask.ProcessInput(input);
|
||||
CollectionAssert.Contains(output.ProviderTypes, typeof(BundledAssetProvider));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenIncludeGUIDInCatalog_SetFalse_GUIDSNotIncluded()
|
||||
{
|
||||
GenerateLocationListsTask.Input input = GenerateDefaultInput();
|
||||
AddressableAssetGroup groupX = CreateGroupMappedToBundle(input, "X");
|
||||
var schema = groupX.GetSchema<BundledAssetGroupSchema>();
|
||||
var guid = CreateAddressablePrefab(input, "p1", groupX, "fileX");
|
||||
input.AddressableAssetEntries = BuildAddressableAssetEntryList(input.Settings);
|
||||
schema.IncludeGUIDInCatalog = true;
|
||||
foreach (var l in GenerateLocationListsTask.ProcessInput(input).Locations)
|
||||
if (l.Provider == typeof(BundledAssetProvider).FullName)
|
||||
CollectionAssert.Contains(l.Keys, guid);
|
||||
|
||||
schema.IncludeGUIDInCatalog = false;
|
||||
foreach (var l in GenerateLocationListsTask.ProcessInput(input).Locations)
|
||||
if (l.Provider == typeof(BundledAssetProvider).FullName)
|
||||
CollectionAssert.DoesNotContain(l.Keys, guid);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CollectsGuidMapping_WhenCatalogKeysNotIncluded()
|
||||
{
|
||||
GenerateLocationListsTask.Input input = GenerateDefaultInput();
|
||||
AddressableAssetGroup groupX = CreateGroupMappedToBundle(input, "X");
|
||||
var schema = groupX.GetSchema<BundledAssetGroupSchema>();
|
||||
schema.IncludeAddressInCatalog = false;
|
||||
schema.IncludeGUIDInCatalog = false;
|
||||
schema.IncludeLabelsInCatalog = false;
|
||||
|
||||
var guid = CreateAddressablePrefab(input, "p1", groupX, "fileX");
|
||||
if (!GUID.TryParse(guid, out GUID g))
|
||||
Assert.IsFalse(g.Empty());
|
||||
|
||||
input.AddressableAssetEntries = BuildAddressableAssetEntryList(input.Settings);
|
||||
schema.IncludeGUIDInCatalog = true;
|
||||
var output = GenerateLocationListsTask.ProcessInput(input);
|
||||
Assert.AreEqual(1, output.GuidToLocation.Count, "Did not gather guid to catalog mapping");
|
||||
Assert.AreEqual(1, output.GuidToLocation[g].Count);
|
||||
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
Assert.AreEqual(path, output.GuidToLocation[g][0].InternalId);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenIncludeAddressOptionChanged_LocationsKeysAreSetCorrectly()
|
||||
{
|
||||
GenerateLocationListsTask.Input input = GenerateDefaultInput();
|
||||
AddressableAssetGroup groupX = CreateGroupMappedToBundle(input, "X");
|
||||
var schema = groupX.GetSchema<BundledAssetGroupSchema>();
|
||||
var guid = CreateAddressablePrefab(input, "p1", groupX, "fileX");
|
||||
input.AddressableAssetEntries = BuildAddressableAssetEntryList(input.Settings);
|
||||
|
||||
schema.IncludeAddressInCatalog = true;
|
||||
foreach (var l in GenerateLocationListsTask.ProcessInput(input).Locations)
|
||||
if (l.Provider == typeof(BundledAssetProvider).FullName)
|
||||
CollectionAssert.Contains(l.Keys, "p1");
|
||||
|
||||
schema.IncludeAddressInCatalog = false;
|
||||
foreach (var l in GenerateLocationListsTask.ProcessInput(input).Locations)
|
||||
if (l.Provider == typeof(BundledAssetProvider).FullName)
|
||||
CollectionAssert.DoesNotContain(l.Keys, "p1");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenIncludeLabelsOptionChanged_LocationsKeysAreSetCorrectly()
|
||||
{
|
||||
GenerateLocationListsTask.Input input = GenerateDefaultInput();
|
||||
AddressableAssetGroup groupX = CreateGroupMappedToBundle(input, "X");
|
||||
var schema = groupX.GetSchema<BundledAssetGroupSchema>();
|
||||
var guid = CreateAddressablePrefab(input, "p1", groupX, "fileX");
|
||||
groupX.GetAssetEntry(guid).SetLabel("LABEL1", true, true, true);
|
||||
input.AddressableAssetEntries = BuildAddressableAssetEntryList(input.Settings);
|
||||
|
||||
schema.IncludeLabelsInCatalog = true;
|
||||
foreach (var l in GenerateLocationListsTask.ProcessInput(input).Locations)
|
||||
if (l.Provider == typeof(BundledAssetProvider).FullName)
|
||||
CollectionAssert.Contains(l.Keys, "LABEL1");
|
||||
|
||||
schema.IncludeLabelsInCatalog = false;
|
||||
foreach (var l in GenerateLocationListsTask.ProcessInput(input).Locations)
|
||||
if (l.Provider == typeof(BundledAssetProvider).FullName)
|
||||
CollectionAssert.DoesNotContain(l.Keys, "LABEL1");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenGroupCreatesMultipleBundles_AllBundlesInAssetGroupToBundlesMap()
|
||||
{
|
||||
GenerateLocationListsTask.Input input = GenerateDefaultInput();
|
||||
AddressableAssetGroup group = m_Settings.CreateGroup($"groupX", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
input.BundleToAssetGroup["bundleX"] = group.Guid;
|
||||
input.BundleToAssetGroup["bundleY"] = group.Guid;
|
||||
input.FileToBundle["fileX"] = "bundle1";
|
||||
input.FileToBundle["fileY"] = "bundle2";
|
||||
CreateAddressablePrefab(input, "p1", group, "fileX");
|
||||
CreateAddressablePrefab(input, "p2", group, "fileY");
|
||||
input.AddressableAssetEntries = BuildAddressableAssetEntryList(input.Settings);
|
||||
GenerateLocationListsTask.Output output = GenerateLocationListsTask.ProcessInput(input);
|
||||
CollectionAssert.AreEquivalent(new string[] {"bundle1", "bundle2"}, output.AssetGroupToBundles[group]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenAssetHasDependencyOnBundle_AssetLocationIncludesRecursiveBundleDependencies()
|
||||
{
|
||||
GenerateLocationListsTask.Input input = GenerateDefaultInput();
|
||||
|
||||
AddressableAssetGroup groupX = CreateGroupMappedToBundle(input, "X");
|
||||
AddressableAssetGroup groupY = CreateGroupMappedToBundle(input, "Y");
|
||||
AddressableAssetGroup groupZ = CreateGroupMappedToBundle(input, "Z");
|
||||
AddressableAssetGroup groupW = CreateGroupMappedToBundle(input, "W");
|
||||
|
||||
CreateAddressablePrefab(input, "p1", groupX, "fileX", "fileY");
|
||||
CreateAddressablePrefab(input, "p2", groupY, "fileY");
|
||||
CreateAddressablePrefab(input, "p3", groupY, "fileY", "fileZ");
|
||||
CreateAddressablePrefab(input, "p4", groupZ, "fileZ");
|
||||
CreateAddressablePrefab(input, "p5", groupZ, "fileZ", "fileW");
|
||||
CreateAddressablePrefab(input, "p6", groupW, "fileW");
|
||||
|
||||
input.AddressableAssetEntries = BuildAddressableAssetEntryList(input.Settings);
|
||||
GenerateLocationListsTask.Output output = GenerateLocationListsTask.ProcessInput(input);
|
||||
|
||||
AssertLocationDependencies(output, "p1", "bundleX", "bundleY", "bundleZ", "bundleW");
|
||||
AssertLocationDependencies(output, "p2", "bundleY", "bundleZ", "bundleW");
|
||||
AssertLocationDependencies(output, "p3", "bundleY", "bundleZ", "bundleW");
|
||||
AssertLocationDependencies(output, "p4", "bundleZ", "bundleW");
|
||||
AssertLocationDependencies(output, "p5", "bundleZ", "bundleW");
|
||||
AssertLocationDependencies(output, "p6", "bundleW");
|
||||
}
|
||||
|
||||
//static
|
||||
[Test]
|
||||
[TestCase("abc", BuildTarget.XboxOne, @"\abc")]
|
||||
[TestCase("abc", BuildTarget.StandaloneWindows64, @"\abc")]
|
||||
[TestCase("abc", BuildTarget.iOS, @"/abc")]
|
||||
[TestCase("abc", BuildTarget.Android, @"/abc")]
|
||||
[TestCase("abc", BuildTarget.StandaloneLinux64, @"/abc")]
|
||||
[TestCase("abc", BuildTarget.Switch, @"/abc")]
|
||||
[TestCase("abc", BuildTarget.StandaloneOSX, @"/abc")]
|
||||
public void WhenBuildTargetIsWindowsOrXBox_BackSlashUsedInLoadPath(string id, BuildTarget target, string expected)
|
||||
{
|
||||
AddressableAssetGroup group = m_Settings.CreateGroup($"xyz", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
var bag = group.GetSchema<BundledAssetGroupSchema>();
|
||||
var expectedPath = $"{bag.LoadPath.GetValue(m_Settings)}{expected}".Replace('/', GenerateLocationListsTask.PathSeparatorForPlatform(target));
|
||||
var path = GenerateLocationListsTask.GetLoadPath(group, id, target);
|
||||
Assert.AreEqual(expectedPath, path);
|
||||
m_Settings.RemoveGroup(group);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase("abc", BuildTarget.XboxOne)]
|
||||
[TestCase("abc", BuildTarget.StandaloneWindows64)]
|
||||
[TestCase("abc", BuildTarget.iOS)]
|
||||
[TestCase("abc", BuildTarget.Android)]
|
||||
[TestCase("abc", BuildTarget.StandaloneLinux64)]
|
||||
[TestCase("abc", BuildTarget.Switch)]
|
||||
[TestCase("abc", BuildTarget.StandaloneOSX)]
|
||||
public void WhenPathIsRemote_WithTrailingSlash_PathIsNotMalformed(string id, BuildTarget target)
|
||||
{
|
||||
//Setup
|
||||
string baseId = m_Settings.profileSettings.Reset();
|
||||
string profileId = m_Settings.profileSettings.AddProfile("remote", baseId);
|
||||
m_Settings.profileSettings.SetValue(profileId, AddressableAssetSettings.kRemoteLoadPath, "http://127.0.0.1:80/");
|
||||
m_Settings.activeProfileId = profileId;
|
||||
AddressableAssetGroup group = m_Settings.CreateGroup($"xyz", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
var bag = group.GetSchema<BundledAssetGroupSchema>();
|
||||
bag.LoadPath.Id = m_Settings.profileSettings.GetVariableId(AddressableAssetSettings.kRemoteLoadPath);
|
||||
|
||||
//Test
|
||||
var path = GenerateLocationListsTask.GetLoadPath(group, id, target);
|
||||
string pahWithoutHttp = path.Replace("http://", "");
|
||||
|
||||
//Assert
|
||||
Assert.IsFalse(path.Contains("/\\"));
|
||||
Assert.IsFalse(pahWithoutHttp.Contains("//"));
|
||||
|
||||
//Cleanup
|
||||
m_Settings.RemoveGroup(group);
|
||||
m_Settings.activeProfileId = baseId;
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase("abc", BuildTarget.XboxOne)]
|
||||
[TestCase("abc", BuildTarget.StandaloneWindows64)]
|
||||
[TestCase("abc", BuildTarget.iOS)]
|
||||
[TestCase("abc", BuildTarget.Android)]
|
||||
[TestCase("abc", BuildTarget.StandaloneLinux64)]
|
||||
[TestCase("abc", BuildTarget.Switch)]
|
||||
[TestCase("abc", BuildTarget.StandaloneOSX)]
|
||||
public void WhenPathIsRemote_WithoutTrailingSlash_PathIsNotMalformed(string id, BuildTarget target)
|
||||
{
|
||||
//Setup
|
||||
string baseId = m_Settings.profileSettings.Reset();
|
||||
string profileId = m_Settings.profileSettings.AddProfile("remote", baseId);
|
||||
m_Settings.profileSettings.SetValue(profileId, AddressableAssetSettings.kRemoteLoadPath, "http://127.0.0.1:80");
|
||||
m_Settings.activeProfileId = profileId;
|
||||
AddressableAssetGroup group = m_Settings.CreateGroup($"xyz", false, false, false, null, typeof(BundledAssetGroupSchema));
|
||||
var bag = group.GetSchema<BundledAssetGroupSchema>();
|
||||
bag.LoadPath.Id = m_Settings.profileSettings.GetVariableId(AddressableAssetSettings.kRemoteLoadPath);
|
||||
|
||||
//Test
|
||||
var path = GenerateLocationListsTask.GetLoadPath(group, id, target);
|
||||
string pahWithoutHttp = path.Replace("http://", "");
|
||||
|
||||
//Assert
|
||||
Assert.IsFalse(path.Contains("/\\"));
|
||||
Assert.IsFalse(pahWithoutHttp.Contains("//"));
|
||||
|
||||
//Cleanup
|
||||
m_Settings.RemoveGroup(group);
|
||||
m_Settings.activeProfileId = baseId;
|
||||
}
|
||||
|
||||
//[Test]
|
||||
//public void WhenEntryAddressContainsBrackets_ExceptionIsThrown()
|
||||
//{
|
||||
// TODO:
|
||||
//}
|
||||
//}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 28e27e70c0f8cee45a62f86887957a0f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,121 @@
|
|||
#if UNITY_2022_2_OR_NEWER
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using UnityEditor.AddressableAssets.BuildReportVisualizer;
|
||||
|
||||
namespace UnityEditor.AddressableAssets.Tests
|
||||
{
|
||||
public class BuildReportWindowTests
|
||||
{
|
||||
public class TimeAgoGetStringTests
|
||||
{
|
||||
[Test]
|
||||
public void SecondLevelGranularitySingularWorks()
|
||||
{
|
||||
var current = DateTime.UtcNow;
|
||||
var input = current.AddSeconds(-1);
|
||||
var expected = "Just now";
|
||||
var actual = BuildReportUtility.TimeAgo.GetString(input);
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MinuteLevelGranularitySingularWorks()
|
||||
{
|
||||
var current = DateTime.UtcNow;
|
||||
var input = current.AddSeconds(-60);
|
||||
var expected = "a minute ago";
|
||||
var actual = BuildReportUtility.TimeAgo.GetString(input);
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MinuteLevelGranularityPluralWorks()
|
||||
{
|
||||
var current = DateTime.UtcNow;
|
||||
var input = current.AddSeconds(-60 * 16);
|
||||
var expected = "16 minutes ago";
|
||||
var actual = BuildReportUtility.TimeAgo.GetString(input);
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HourLevelGranularitySingularWorks()
|
||||
{
|
||||
var current = DateTime.UtcNow;
|
||||
var input = current.AddSeconds(-60 * 60 * 1);
|
||||
var expected = "an hour ago";
|
||||
var actual = BuildReportUtility.TimeAgo.GetString(input);
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HourLevelGranularityPluralWorks()
|
||||
{
|
||||
var current = DateTime.UtcNow;
|
||||
var input = current.AddSeconds(-60 * 60 * 5);
|
||||
var expected = "5 hours ago";
|
||||
var actual = BuildReportUtility.TimeAgo.GetString(input);
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
[Test]
|
||||
public void DayLevelGranularitySingularWorks()
|
||||
{
|
||||
var current = DateTime.UtcNow;
|
||||
var input = current.AddSeconds(-60 * 60 * 24);
|
||||
var expected = "yesterday";
|
||||
var actual = BuildReportUtility.TimeAgo.GetString(input);
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DayLevelGranularityPluralWorks()
|
||||
{
|
||||
var current = DateTime.UtcNow;
|
||||
var input = current.AddSeconds(-60 * 60 * 24 * 5);
|
||||
var expected = "5 days ago";
|
||||
var actual = BuildReportUtility.TimeAgo.GetString(input);
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
[Test]
|
||||
public void MonthLevelGranularitySingularWorks()
|
||||
{
|
||||
var current = DateTime.UtcNow;
|
||||
var input = current.AddSeconds(-60 * 60 * 24 * 30);
|
||||
var expected = "a month ago";
|
||||
var actual = BuildReportUtility.TimeAgo.GetString(input);
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MonthLevelGranularityPluralWorks()
|
||||
{
|
||||
var current = DateTime.UtcNow;
|
||||
var input = current.AddSeconds(-60 * 60 * 24 * 30 * 5);
|
||||
var expected = "5 months ago";
|
||||
var actual = BuildReportUtility.TimeAgo.GetString(input);
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
[Test]
|
||||
public void YearLevelGranularitySingularWorks()
|
||||
{
|
||||
var current = DateTime.UtcNow;
|
||||
var input = current.AddSeconds(-60 * 60 * 24 * 365);
|
||||
var expected = "one year ago";
|
||||
var actual = BuildReportUtility.TimeAgo.GetString(input);
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void YearLevelGranularityPluralWorks()
|
||||
{
|
||||
var current = DateTime.UtcNow;
|
||||
var input = current.AddSeconds(-60 * 60 * 24 * 365 * 5);
|
||||
var expected = "5 years ago";
|
||||
var actual = BuildReportUtility.TimeAgo.GetString(input);
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0a6d54cc4a4cbec4db6e4c14b3f92c22
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,107 @@
|
|||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace UnityEditor.AddressableAssets.Settings.Tests
|
||||
{
|
||||
public class BuiltinSceneCacheTests
|
||||
{
|
||||
const string kTestScenePath = "Assets/TestScenes";
|
||||
const int kTestSceneCount = 3;
|
||||
private EditorBuildSettingsScene[] m_OldScenes;
|
||||
private GUID[] m_TestGUIDs;
|
||||
|
||||
private static string GetTestScenePath(int index)
|
||||
{
|
||||
return string.Format("{0}/myscene{1}.unity", kTestScenePath, index);
|
||||
}
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void OneTimeSetUp()
|
||||
{
|
||||
// Since this system is a global. We need to shutdown global state
|
||||
GlobalInitialization.ShutdownGlobalState();
|
||||
|
||||
// Create folder for test scenes
|
||||
Directory.CreateDirectory("Assets/TestScenes");
|
||||
m_OldScenes = EditorBuildSettings.scenes;
|
||||
Scene scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
|
||||
for (int i = 0; i < kTestSceneCount; i++)
|
||||
EditorSceneManager.SaveScene(scene, GetTestScenePath(i), true);
|
||||
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
m_TestGUIDs = new GUID[kTestSceneCount];
|
||||
for (int i = 0; i < kTestSceneCount; i++)
|
||||
m_TestGUIDs[i] = new GUID(AssetDatabase.AssetPathToGUID(GetTestScenePath(i)));
|
||||
}
|
||||
|
||||
[OneTimeTearDown]
|
||||
public void OneTimeTearDown()
|
||||
{
|
||||
EditorBuildSettings.scenes = m_OldScenes;
|
||||
Directory.Delete(kTestScenePath, true);
|
||||
GlobalInitialization.InitializeGlobalState();
|
||||
}
|
||||
|
||||
private void SetupBuildScenes()
|
||||
{
|
||||
EditorBuildSettingsScene[] scenes = new EditorBuildSettingsScene[2];
|
||||
scenes[0] = new EditorBuildSettingsScene(GetTestScenePath(0), true);
|
||||
scenes[1] = new EditorBuildSettingsScene(GetTestScenePath(1), true);
|
||||
EditorBuildSettings.scenes = scenes;
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
SetupBuildScenes();
|
||||
BuiltinSceneCache.ClearState(true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanAccessSceneData()
|
||||
{
|
||||
Assert.AreEqual(m_TestGUIDs[0], BuiltinSceneCache.scenes[0].guid);
|
||||
Assert.AreEqual(m_TestGUIDs[1], BuiltinSceneCache.scenes[1].guid);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenScenesChange_CallbackInvoked()
|
||||
{
|
||||
int[] called = new int[] {0};
|
||||
Action callback = () => called[0]++;
|
||||
EditorBuildSettingsScene[] scenes = BuiltinSceneCache.scenes;
|
||||
scenes[0].enabled = !scenes[0].enabled;
|
||||
BuiltinSceneCache.sceneListChanged += callback;
|
||||
BuiltinSceneCache.scenes = scenes;
|
||||
Assert.AreEqual(1, called[0]);
|
||||
|
||||
// Set Directly through API
|
||||
scenes[0].enabled = !scenes[0].enabled;
|
||||
EditorBuildSettings.scenes = scenes;
|
||||
Assert.AreEqual(2, called[0]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenSceneOrderChanges_GetSceneIndexCacheUpdates()
|
||||
{
|
||||
Assert.AreEqual(0, BuiltinSceneCache.GetSceneIndex(m_TestGUIDs[0]));
|
||||
Assert.AreEqual(1, BuiltinSceneCache.GetSceneIndex(m_TestGUIDs[1]));
|
||||
|
||||
// Insert new scene
|
||||
List<EditorBuildSettingsScene> list = new List<EditorBuildSettingsScene>(BuiltinSceneCache.scenes);
|
||||
list.Insert(0, new EditorBuildSettingsScene(m_TestGUIDs[2], true));
|
||||
BuiltinSceneCache.scenes = list.ToArray();
|
||||
|
||||
Assert.AreEqual(1, BuiltinSceneCache.GetSceneIndex(m_TestGUIDs[0]));
|
||||
Assert.AreEqual(2, BuiltinSceneCache.GetSceneIndex(m_TestGUIDs[1]));
|
||||
Assert.AreEqual(0, BuiltinSceneCache.GetSceneIndex(m_TestGUIDs[2]));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bbc66e9c19bb4284686b4dbce7530ccf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,115 @@
|
|||
using System.Collections;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.ResourceManagement.Util;
|
||||
using UnityEngine.TestTools;
|
||||
|
||||
namespace UnityEditor.AddressableAssets.Tests
|
||||
{
|
||||
public class ComponentSingletonTests
|
||||
{
|
||||
const string kTestSingletonName = "Test Singleton";
|
||||
|
||||
public class TestSingletonWithName : ComponentSingleton<TestSingletonWithName>
|
||||
{
|
||||
protected override string GetGameObjectName() => kTestSingletonName;
|
||||
}
|
||||
|
||||
public class TestSingletonWithDefaultName : ComponentSingleton<TestSingletonWithDefaultName>
|
||||
{
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void Teardown()
|
||||
{
|
||||
TestSingletonWithName.DestroySingleton();
|
||||
TestSingletonWithDefaultName.DestroySingleton();
|
||||
EditorApplication.isPlaying = false;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CallingInstanceInstantiatesSingleton()
|
||||
{
|
||||
Assert.False(TestSingletonWithName.Exists);
|
||||
Assert.NotNull(TestSingletonWithName.Instance, "Expected singleton instance to be returned.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SingletonIsDestroyedWhenCallingDestroySingleton()
|
||||
{
|
||||
Assert.NotNull(TestSingletonWithName.Instance);
|
||||
TestSingletonWithName.DestroySingleton();
|
||||
Assert.False(TestSingletonWithName.Exists);
|
||||
Assert.IsEmpty(Object.FindObjectsOfType<TestSingletonWithName>(), "Expected no singleton objects to exists after destroy was called");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InstantiatingSingletonCausesItToBeDestroyedWhenOneAlreadyExists()
|
||||
{
|
||||
var singleton = TestSingletonWithName.Instance;
|
||||
var go = new GameObject("Duplicate");
|
||||
var duplicate = go.AddComponent<TestSingletonWithName>();
|
||||
Assert.Null(duplicate, "Expected the duplicate singleton to be destroyed when one already exists");
|
||||
Assert.AreEqual(singleton, TestSingletonWithName.Instance);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GameObjectNameMatchesOverridenGetGameObjectNameValue()
|
||||
{
|
||||
Assert.AreEqual(kTestSingletonName, TestSingletonWithName.Instance.gameObject.name);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GameObjectNameMatchesClassName()
|
||||
{
|
||||
Assert.AreEqual(nameof(TestSingletonWithDefaultName), TestSingletonWithDefaultName.Instance.gameObject.name);
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator ExitingPlayModeDestroysSingleton()
|
||||
{
|
||||
yield return new EnterPlayMode();
|
||||
|
||||
var instance = TestSingletonWithName.Instance;
|
||||
Assert.NotNull(instance);
|
||||
|
||||
yield return new ExitPlayMode();
|
||||
|
||||
// We cant use Assert.Null as we need the override that compares against null when using ==
|
||||
Assert.True(instance == null, "Expected singleton instance to be destroyed when leaving play mode.");
|
||||
Assert.False(TestSingletonWithName.Exists);
|
||||
Assert.IsEmpty(Object.FindObjectsOfType<TestSingletonWithName>(), "Expected no singleton objects to exists after leaving play mode.");
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator EnteringPlayModeDestroysEditorSingleton()
|
||||
{
|
||||
var instance = TestSingletonWithName.Instance;
|
||||
Assert.NotNull(instance);
|
||||
|
||||
yield return new EnterPlayMode();
|
||||
|
||||
// We cant use Assert.Null as we need the override that compares against null when using ==
|
||||
Assert.True(instance == null, "Expected editor singleton instance to be destroyed when entering play mode.");
|
||||
Assert.False(TestSingletonWithName.Exists);
|
||||
Assert.IsEmpty(Object.FindObjectsOfType<TestSingletonWithName>(), "Expected no singleton objects to exists after leaving play mode.");
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator PlaymodeSingletonHasHideFlags_DontSave()
|
||||
{
|
||||
yield return new EnterPlayMode();
|
||||
Assert.True(Application.isPlaying);
|
||||
var instance = TestSingletonWithName.Instance;
|
||||
Assert.AreEqual(HideFlags.DontSave, instance.hideFlags);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EditmodeSingletonHasHideFlags_HideAndDontSave()
|
||||
{
|
||||
Assert.False(Application.isPlaying);
|
||||
var instance = TestSingletonWithName.Instance;
|
||||
Assert.AreEqual(HideFlags.HideAndDontSave, instance.hideFlags);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d91d0dd2a4ed2df41b742f33881892a2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d65991d4bb3d75541bf06688c370ff05
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3c09a39d41a474a4a886225f2513ed5e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
using UnityEditor.AddressableAssets.Settings;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.AddressableAssets.Tests
|
||||
{
|
||||
class CustomTestSchema : AddressableAssetGroupSchema
|
||||
{
|
||||
public string customField = null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 632c145638f685b4883fbd81884e496a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,10 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.AddressableAssets.Tests
|
||||
{
|
||||
class CustomTestSchemaSubClass : CustomTestSchema
|
||||
{
|
||||
public string customField2 = null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2c53f1cace3a81a4bbe8280d05abda4e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3ee6f25a9e02fee4197773346feb1015
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f732c6455ee1417c91ebd421b5ed6f67
|
||||
timeCreated: 1662495716
|
|
@ -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. ");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 87c0e75886b4481693ca963bc0955c1c
|
||||
timeCreated: 1595276565
|
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 69303074fc8049c794e80a49d142e38d
|
||||
timeCreated: 1594924812
|
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3275c47c6e434362a78bf0ec660eebd0
|
||||
timeCreated: 1594828580
|
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6665e03593d44dae8f9e2ada8752d2dc
|
||||
timeCreated: 1594851080
|
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1b61a52d425c4e0f990ee2abd92efb46
|
||||
timeCreated: 1597096123
|
|
@ -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
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3805f04aa43306c4590ee741451aefe3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e49dad816ceeeb94386b907d5f361a0d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 08e15d16f0070d0429a6ec852ac78abe
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,29 @@
|
|||
namespace AddressableAssets.DocExampleCode
|
||||
{
|
||||
#region doc_AddExceptionHandler
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using UnityEngine.ResourceManagement;
|
||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||
|
||||
internal class AddExceptionHandler : MonoBehaviour
|
||||
{
|
||||
void Start()
|
||||
{
|
||||
ResourceManager.ExceptionHandler = CustomExceptionHandler;
|
||||
}
|
||||
|
||||
// Gets called for every error scenario encountered during an operation.
|
||||
// A common use case for this is having InvalidKeyExceptions fail silently when
|
||||
// a location is missing for a given key.
|
||||
void CustomExceptionHandler(AsyncOperationHandle handle, Exception exception)
|
||||
{
|
||||
if (exception.GetType() != typeof(InvalidKeyException))
|
||||
Addressables.LogException(handle, exception);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 97ad6dc3d3427a04082f57c44933e71c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,48 @@
|
|||
namespace AddressableAssets.DocExampleCode
|
||||
{
|
||||
#region doc_asyncload
|
||||
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||
|
||||
internal class AsynchronousLoading : MonoBehaviour
|
||||
{
|
||||
private string address = "tree";
|
||||
private AsyncOperationHandle loadHandle;
|
||||
|
||||
// always minimum of 1 frame
|
||||
IEnumerator LoadAssetCoroutine()
|
||||
{
|
||||
loadHandle = Addressables.LoadAssetAsync<GameObject>(address);
|
||||
yield return loadHandle;
|
||||
}
|
||||
|
||||
// minimum of 1 frame for new asset loads
|
||||
// callback called in current frame for already loaded assets
|
||||
void LoadAssetCallback()
|
||||
{
|
||||
loadHandle = Addressables.LoadAssetAsync<GameObject>(address);
|
||||
loadHandle.Completed += h =>
|
||||
{
|
||||
// Loaded here
|
||||
};
|
||||
}
|
||||
|
||||
// minimum of 1 frame for new asset loads
|
||||
// await completes in current frame for already loaded assets
|
||||
async void LoadAssetWait()
|
||||
{
|
||||
loadHandle = Addressables.LoadAssetAsync<GameObject>(address);
|
||||
await loadHandle.Task;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
Addressables.Release(loadHandle);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4ac2fef2444fc40e1be92d0423a6587a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue