using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement; using UnityEngine.TestTools; using NUnit.Framework; using System.Collections; using System.IO; using UnityEngine.SceneManagement; using UnityEngine.AddressableAssets.Initialization; using UnityEngine.ResourceManagement.ResourceLocations; using UnityEngine.ResourceManagement.ResourceProviders; using UnityEngine.AddressableAssets.ResourceLocators; using UnityEngine.AddressableAssets.ResourceProviders; using UnityEngine.AddressableAssets.Utility; using UnityEngine.ResourceManagement.AsyncOperations; using System.Text.RegularExpressions; using System.Linq; using System.Text; using UnityEngine.AddressableAssets.ResourceProviders.Tests; using UnityEngine.AddressableAssets.Tests; using UnityEngine.Lumin; using UnityEngine.Networking; using UnityEngine.U2D; using Object = UnityEngine.Object; using Texture2D = UnityEngine.Texture2D; namespace AddressableAssetsIntegrationTests { internal abstract partial class AddressablesIntegrationTests : IPrebuildSetup { [UnityTest] public IEnumerator AsyncCache_IsCleaned_OnFailedOperation() { yield return Init(); AsyncOperationHandle op; using (new IgnoreFailingLogMessage()) op = m_Addressables.LoadAssetAsync("notARealKey"); op.Completed += handle => { Assert.AreEqual(0, m_Addressables.ResourceManager.CachedOperationCount()); }; yield return op; } [UnityTest] public IEnumerator LoadResourceLocations_InvalidKeyDoesNotThrow() { //Setup yield return Init(); //Test Assert.DoesNotThrow(() => { var handle = m_Addressables.LoadResourceLocationsAsync("noSuchLabel", typeof(object)); handle.WaitForCompletion(); handle.Release(); }); } [UnityTest] public IEnumerator LoadResourceLocations_ValidKeyDoesNotThrow() { //Setup yield return Init(); //Test Assert.DoesNotThrow(() => { m_Addressables.LoadResourceLocationsAsync(AddressablesTestUtility.GetPrefabLabel("BASE"), typeof(GameObject)); }); } [UnityTest] public IEnumerator LoadResourceLocations_SubObjects_ReturnsCorrectResourceTypes() { yield return Init(); string subObjectsAddress = "assetWithDifferentTypedSubAssets"; var loadLocsHandle = m_Addressables.LoadResourceLocationsAsync(subObjectsAddress, typeof(object)); yield return loadLocsHandle; Assert.AreEqual(3, loadLocsHandle.Result.Count); Assert.IsTrue(loadLocsHandle.Result.Any(loc => loc.ResourceType == typeof(Mesh))); Assert.IsTrue(loadLocsHandle.Result.Any(loc => loc.ResourceType == typeof(Material))); Assert.IsTrue(loadLocsHandle.Result.Any(loc => loc.ResourceType == typeof(TestObject))); loadLocsHandle.Release(); } [UnityTest] public IEnumerator LoadResourceLocations_ReturnsCorrectResourceTypes() { yield return Init(); string spriteAddress = "sprite"; var loadLocsHandle = m_Addressables.LoadResourceLocationsAsync(spriteAddress, typeof(object)); yield return loadLocsHandle; Assert.AreEqual(2, loadLocsHandle.Result.Count); Assert.IsTrue(loadLocsHandle.Result.Any(loc => loc.ResourceType == typeof(Texture2D))); Assert.IsTrue(loadLocsHandle.Result.Any(loc => loc.ResourceType == typeof(Sprite))); loadLocsHandle.Release(); } [UnityTest] public IEnumerator LoadResourceLocations_SpecificType_ReturnsCorrectResourceTypes() { yield return Init(); string spriteAddress = "sprite"; var loadLocsHandle = m_Addressables.LoadResourceLocationsAsync(spriteAddress, typeof(Sprite)); yield return loadLocsHandle; Assert.AreEqual(1, loadLocsHandle.Result.Count); Assert.AreEqual(typeof(Sprite), loadLocsHandle.Result[0].ResourceType); loadLocsHandle.Release(); loadLocsHandle = m_Addressables.LoadResourceLocationsAsync(spriteAddress, typeof(Texture2D)); yield return loadLocsHandle; Assert.AreEqual(1, loadLocsHandle.Result.Count); Assert.AreEqual(typeof(Texture2D), loadLocsHandle.Result[0].ResourceType); loadLocsHandle.Release(); } [UnityTest] public IEnumerator LoadPrefabWithComponentType_Fails() { //Setup yield return Init(); //Test AsyncOperationHandle op = new AsyncOperationHandle(); using (new IgnoreFailingLogMessage()) { op = m_Addressables.LoadAssetAsync("test0BASE"); } yield return op; Assert.IsNull(op.Result); } const string InvalidKeyExceptionBaseMessage = "Exception of type 'UnityEngine.AddressableAssets.InvalidKeyException' was thrown."; [UnityTest] public IEnumerator InvalidKeyException_LoadAsset_NoKeyFound() { //Setup yield return Init(); string keyString = "noSuchLabel"; AsyncOperationHandle handle = default(AsyncOperationHandle); try { //Test using (new IgnoreFailingLogMessage()) { handle = m_Addressables.LoadAssetAsync(keyString); yield return handle; } string message = $"{InvalidKeyExceptionBaseMessage} No Location found for Key={keyString}"; Assert.AreEqual(message, handle.OperationException.Message, "InvalidKeyException message not the same as expected for when the Location does not exist"); } finally { //Cleanup if (handle.IsValid()) handle.Release(); } } [UnityTest] public IEnumerator InvalidKeyException_LoadAsset_KeyFoundWithOtherType() { //Setup yield return Init(); string keyString = "test0BASE"; AsyncOperationHandle handle = new AsyncOperationHandle(); try { //Test using (new IgnoreFailingLogMessage()) { handle = m_Addressables.LoadAssetAsync(keyString); yield return handle; } string message = $"{InvalidKeyExceptionBaseMessage} No Asset found with for Key={keyString}. Key exists as Type={typeof(GameObject)}, which is not assignable from the requested Type={typeof(TextAsset)}"; Assert.AreEqual(message, handle.OperationException.Message, "InvalidKeyException message not the same as expected for when a similar Location exists with same key and a different type"); } finally { //Cleanup if (handle.IsValid()) handle.Release(); } } [UnityTest] public IEnumerator InvalidKeyException_LoadAsset_KeyFoundWithMultipleOtherType() { //Setup yield return Init(); string keyString = "mixed"; string otherAvailableTypesForKey = "UnityEngine.GameObject, UnityEngine.AddressableAssets.Tests.TestObject"; AsyncOperationHandle handle = new AsyncOperationHandle(); try //Test { using (new IgnoreFailingLogMessage()) { handle = m_Addressables.LoadAssetAsync(keyString); yield return handle; } string message = $"{InvalidKeyExceptionBaseMessage} No Asset found with for Key={keyString}. Key exists as multiple Types={otherAvailableTypesForKey}, which is not assignable from the requested Type={typeof(TextAsset)}"; bool isEqual = message == handle.OperationException.Message; if (!isEqual) { // order isn't guaranteed message = message.Replace("UnityEngine.GameObject, UnityEngine.AddressableAssets.Tests.TestObject", "UnityEngine.AddressableAssets.Tests.TestObject, UnityEngine.GameObject"); isEqual = message == handle.OperationException.Message; } Assert.IsTrue(isEqual, $"InvalidKeyException message not the same as expected for when a similar Location exists with same key and a different type. Was expecting {message.ToString()}, but was {handle.OperationException.Message}"); } finally // Cleanup { if (handle.IsValid()) handle.Release(); } } [UnityTest] public IEnumerator InvalidKeyException_LoadAsset__AssetFromGUIDFoundWithDifferentType() { if (string.IsNullOrEmpty(TypeName) || TypeName != "BuildScriptFastMode" || TypeName == "BuildScriptVirtualMode") { Assert.Ignore($"Skipping test {nameof(InvalidKeyException_LoadAsset__AssetFromGUIDFoundWithDifferentType)} for {TypeName}, Editor AssetDatabase based test."); } //Setup yield return Init(); #if UNITY_EDITOR string keyString = "test0BASE"; AsyncOperationHandle handle = new AsyncOperationHandle(); AsyncOperationHandle goLoadHandle = new AsyncOperationHandle(); try { //Test goLoadHandle = m_Addressables.LoadAssetAsync(keyString); yield return goLoadHandle; Assert.AreEqual(goLoadHandle.Status, AsyncOperationStatus.Succeeded); bool foundGuid = UnityEditor.AssetDatabase.TryGetGUIDAndLocalFileIdentifier(goLoadHandle.Result, out string guid, out long id); Assert.IsTrue(foundGuid, "Failed to get the Guid for loaded Object"); goLoadHandle.Release(); using (new IgnoreFailingLogMessage()) { handle = m_Addressables.LoadAssetAsync(guid); yield return handle; } string path = UnityEditor.AssetDatabase.GUIDToAssetPath(guid); string message = $"{InvalidKeyExceptionBaseMessage} Could not load Asset with GUID={guid}, Path={path}. Asset exists with main Type={typeof(GameObject)}, which is not assignable from the requested Type={typeof(TextAsset)}"; Assert.AreEqual(message, handle.OperationException.Message, "InvalidKeyException message not the same as expected for when a similar Location exists with same key and a different type"); } finally { //Cleanup if (handle.IsValid()) handle.Release(); if (goLoadHandle.IsValid()) goLoadHandle.Release(); } #endif } [UnityTest] public IEnumerator InvalidKeyException_LoadAssets_MixedTypesGivesCorrectError() { //Setup yield return Init(); object[] keys = new object[] {"noSuchKey", 123}; AsyncOperationHandle handle = default(AsyncOperationHandle); //Test try { using (new IgnoreFailingLogMessage()) { handle = m_Addressables.LoadAssetsAsync(keys, null, Addressables.MergeMode.Union, true); } string message = handle.OperationException.Message; string types = "Types=System.String, System.Int32"; string expected = $"{InvalidKeyExceptionBaseMessage} Enumerable key contains multiple Types. {types}, all Keys are expected to be strings"; bool equalOne = message == expected; bool equalTwo = message == expected.Replace("Types=System.String, System.Int32", "System.Int32, Types=System.String"); Assert.IsTrue(equalOne || equalTwo, $"Failed to get correct message for mixedTypes being requested. was {message}. But expected {expected}"); yield return handle; } finally { //Cleanup handle.Release(); } } [UnityTest] public IEnumerator InvalidKeyException_LoadAsset_MultipleKeysNoMergeMode() { //Setup yield return Init(); string[] keysArray = new string[] {"noSuchKey1", "noSuchKey2"}; //Test AsyncOperationHandle handle = default(AsyncOperationHandle); using (new IgnoreFailingLogMessage()) { handle = m_Addressables.LoadAssetAsync(keysArray); } string keysErrorString = "Exception of type 'UnityEngine.AddressableAssets.InvalidKeyException' was thrown. No MergeMode is set to merge the multiple keys requested. Keys=noSuchKey1, noSuchKey2, Type=UnityEngine.GameObject"; Assert.AreEqual(keysErrorString, handle.OperationException.Message); yield return handle; //Cleanup handle.Release(); } [UnityTest] public IEnumerator InvalidKeyException_LoadAssets_Union_NoKeysFound() { //Setup yield return Init(); string[] keysArray = new[] {"noSuchKey1", "noSuchKey2"}; AsyncOperationHandle handle = default(AsyncOperationHandle); try { //Test using (new IgnoreFailingLogMessage()) { handle = m_Addressables.LoadAssetsAsync(keysArray, null, Addressables.MergeMode.Union, true); } string expected = "Exception of type 'UnityEngine.AddressableAssets.InvalidKeyException' was thrown. " + "No Union of Assets between Keys=noSuchKey1, noSuchKey2 with Type=UnityEngine.TextAsset" + "\nNo Location found for Key=noSuchKey1" + "\nNo Location found for Key=noSuchKey2"; Assert.AreEqual(expected, handle.OperationException.Message, "Incorrect invalidKeyMessage. Expected to inform the two locations have for other type"); yield return handle; } finally { //Cleanup handle.Release(); } } [UnityTest] public IEnumerator InvalidKeyException_LoadAssets_Union_IncorrectType() { //Setup yield return Init(); string[] keysArray = new[] {"test0BASE", "test1BASE"}; AsyncOperationHandle handle = default(AsyncOperationHandle); try { //Test using (new IgnoreFailingLogMessage()) { handle = m_Addressables.LoadAssetsAsync(keysArray, null, Addressables.MergeMode.Union, true); } string expected = "Exception of type 'UnityEngine.AddressableAssets.InvalidKeyException' was thrown. " + "No Union of Assets between Keys=test0BASE, test1BASE with Type=UnityEngine.TextAsset" + "\nUnion of Type=UnityEngine.GameObject found with Keys=test0BASE, test1BASE"; Assert.AreEqual(expected, handle.OperationException.Message, "Incorrect invalidKeyMessage. Expected to inform the two locations have for other type"); yield return handle; } finally { //Cleanup handle.Release(); } } [UnityTest] public IEnumerator InvalidKeyException_LoadAssets_Union_MultipleTypesAvailable() { //Setup yield return Init(); string[] keysArray = new[] {"test0BASE", "assetWithSubObjects"}; AsyncOperationHandle handle = default(AsyncOperationHandle); try { //Test using (new IgnoreFailingLogMessage()) { handle = m_Addressables.LoadAssetsAsync(keysArray, null, Addressables.MergeMode.Union, true); } string expected = "Exception of type 'UnityEngine.AddressableAssets.InvalidKeyException' was thrown. " + "No Union of Assets between Keys=test0BASE, assetWithSubObjects with Type=UnityEngine.TextAsset" + "\nUnion of Type=UnityEngine.GameObject found with Key=test0BASE. Without Key=assetWithSubObjects" + "\nUnion of Type=UnityEngine.AddressableAssets.Tests.TestObject found with Key=assetWithSubObjects. Without Key=test0BASE"; Assert.AreEqual(expected, handle.OperationException.Message, "Incorrect invalidKeyMessage. Expected to inform that a merge could be made for two different types"); yield return handle; } finally { //Cleanup handle.Release(); } } [UnityTest] public IEnumerator InvalidKeyException_LoadAssets_Intersection_OneMissingKey() { //Setup yield return Init(); string[] keysArray = new[] {"test0BASE", "noSuchKey"}; AsyncOperationHandle handle = default(AsyncOperationHandle); try { //Test using (new IgnoreFailingLogMessage()) { handle = m_Addressables.LoadAssetsAsync(keysArray, null, Addressables.MergeMode.Intersection, true); } string expected = "Exception of type 'UnityEngine.AddressableAssets.InvalidKeyException' was thrown. " + "No Intersection of Assets between Keys=test0BASE, noSuchKey with Type=UnityEngine.GameObject" + "\nNo Location found for Key=noSuchKey"; Assert.AreEqual(expected, handle.OperationException.Message, "Incorrect invalidKeyMessage. Expected to error due to noSuchKey"); yield return handle; } finally { //Cleanup handle.Release(); } } [UnityTest] public IEnumerator InvalidKeyException_LoadAssets_Intersection_PossibleForAnotherType() { //Setup yield return Init(); string[] keysArray = new[] {"test0BASE", "mixed"}; AsyncOperationHandle handle = default(AsyncOperationHandle); try { //Test using (new IgnoreFailingLogMessage()) { handle = m_Addressables.LoadAssetsAsync(keysArray, null, Addressables.MergeMode.Intersection, true); } string expected = "Exception of type 'UnityEngine.AddressableAssets.InvalidKeyException' was thrown. " + "No Intersection of Assets between Keys=test0BASE, mixed with Type=UnityEngine.TextAsset" + "\nAn Intersection exists for Type=UnityEngine.GameObject"; Assert.AreEqual(expected, handle.OperationException.Message, "Incorrect invalidKeyMessage. Expected to inform that an intersection exists with GameObject"); yield return handle; } finally { //Cleanup handle.Release(); } } [UnityTest] public IEnumerator InvalidKeyException_LoadAssets_UseFirst_NoLocations() { //Setup yield return Init(); string[] keysArray = new[] {"noSuchKey1", "noSuchKey2"}; AsyncOperationHandle handle = default(AsyncOperationHandle); try { //Test using (new IgnoreFailingLogMessage()) { handle = m_Addressables.LoadAssetsAsync(keysArray, null, Addressables.MergeMode.UseFirst, true); } string expected = "Exception of type 'UnityEngine.AddressableAssets.InvalidKeyException' was thrown. " + "No UseFirst Asset within Keys=noSuchKey1, noSuchKey2 with Type=UnityEngine.GameObject" + "\nNo Location found for Key=noSuchKey1" + "\nNo Location found for Key=noSuchKey2"; Assert.AreEqual(expected, handle.OperationException.Message, "Incorrect invalidKeyMessage. Expected to inform that all keys have no location"); yield return handle; } finally { //Cleanup handle.Release(); } } [UnityTest] public IEnumerator InvalidKeyException_LoadAssets_UseFirst_PossibleForAnotherType() { //Setup yield return Init(); string[] keysArray = new[] {"test0BASE", "noSuchKey"}; AsyncOperationHandle handle = default(AsyncOperationHandle); try { //Test using (new IgnoreFailingLogMessage()) { handle = m_Addressables.LoadAssetsAsync(keysArray, null, Addressables.MergeMode.UseFirst, true); } string expected = "Exception of type 'UnityEngine.AddressableAssets.InvalidKeyException' was thrown. " + "No UseFirst Asset within Keys=test0BASE, noSuchKey with Type=UnityEngine.TextAsset" + "\nNo Location found for Key=noSuchKey" + "\nType=UnityEngine.GameObject exists for Key=test0BASE"; Assert.AreEqual(expected, handle.OperationException.Message, "Incorrect invalidKeyMessage. Expected to inform that one key has no location and the other can be loaded with GameObject"); yield return handle; } finally { //Cleanup handle.Release(); } } [UnityTest] public IEnumerator CanLoadTextureAsSprite() { //Setup yield return Init(); var op = m_Addressables.LoadAssetAsync("sprite"); yield return op; Assert.IsNotNull(op.Result); Assert.AreEqual(typeof(Sprite), op.Result.GetType()); op.Release(); } [UnityTest] public IEnumerator CanLoadSpriteByName() { //Setup yield return Init(); var op = m_Addressables.LoadAssetAsync("sprite[botright]"); yield return op; Assert.IsNotNull(op.Result); Assert.AreEqual(typeof(Sprite), op.Result.GetType()); Assert.AreEqual("botright", op.Result.name); op.Release(); var op2 = m_Addressables.LoadAssetAsync("sprite[topleft]"); yield return op2; Assert.IsNotNull(op2.Result); Assert.AreEqual(typeof(Sprite), op2.Result.GetType()); Assert.AreEqual("topleft", op2.Result.name); op2.Release(); } [UnityTest] public IEnumerator CanLoadFromFolderEntry_SpriteAtlas() { //Setup yield return Init(); var op = m_Addressables.LoadAssetAsync("folderEntry/atlas.spriteatlas"); yield return op; Assert.IsNotNull(op.Result); Assert.AreEqual(typeof(SpriteAtlas), op.Result.GetType()); op.Release(); } [UnityTest] public IEnumerator CanLoadFromFolderEntry_SpriteFromSpriteAtlas() { //Setup yield return Init(); var op = m_Addressables.LoadAssetAsync("folderEntry/atlas.spriteatlas[sprite]"); yield return op; Assert.IsNotNull(op.Result); Assert.AreEqual(typeof(Sprite), op.Result.GetType()); op.Release(); } [UnityTest] public IEnumerator CanLoadFromFolderEntry_Texture() { //Setup yield return Init(); var op = m_Addressables.LoadAssetAsync("folderEntry/spritesheet.png"); yield return op; Assert.IsNotNull(op.Result); Assert.AreEqual(typeof(Texture2D), op.Result.GetType()); op.Release(); } [UnityTest] public IEnumerator CanLoadFromFolderEntry_SpriteFromTexture() { //Setup yield return Init(); var op = m_Addressables.LoadAssetAsync("folderEntry/spritesheet.png[topleft]"); yield return op; Assert.IsNotNull(op.Result); Assert.AreEqual(typeof(Sprite), op.Result.GetType()); op.Release(); } [UnityTest] public IEnumerator CanLoadAllSpritesAsArray() { //Setup yield return Init(); var op = m_Addressables.LoadAssetAsync("sprite"); yield return op; Assert.IsNotNull(op.Result); Assert.AreEqual(typeof(Sprite[]), op.Result.GetType()); Assert.AreEqual(2, op.Result.Length); op.Release(); } [UnityTest] public IEnumerator CanLoadAllSpritesAsList() { //Setup yield return Init(); var op = m_Addressables.LoadAssetAsync>("sprite"); yield return op; Assert.IsNotNull(op.Result); Assert.IsTrue(typeof(IList).IsAssignableFrom(op.Result.GetType())); Assert.AreEqual(2, op.Result.Count); op.Release(); } #if !ENABLE_BINARY_CATALOG [UnityTest] public IEnumerator CanUseCustomAssetBundleResource_LoadFromCustomProvider() { //Setup yield return Init(); if (string.IsNullOrEmpty(TypeName) || TypeName == "BuildScriptFastMode") { Assert.Ignore($"Skipping test {nameof(CanUseCustomAssetBundleResource_LoadFromCustomProvider)} for {TypeName}, AssetBundle based test."); } string hash = "123456789"; string bundleName = $"test_{hash}"; string key = "lockey_key"; ResourceLocationBase location = null; TestCatalogProviderCustomAssetBundleResource testProvider; SetupBundleForProviderTests(bundleName, "bundle", key, out location, out testProvider); var op = m_Addressables.LoadAssetAsync(key); yield return op; Assert.IsTrue(testProvider.TestInternalOp.Result.WasUsed); op.Release(); } #endif string TransFunc(IResourceLocation loc) { return "transformed"; } [UnityTest] public IEnumerator InternalIdTranslationTest() { //Setup yield return Init(); m_Addressables.InternalIdTransformFunc = TransFunc; var loc = new ResourceLocationBase("none", "original", "none", typeof(object)); var transformedId = m_Addressables.ResourceManager.TransformInternalId(loc); Assert.AreEqual("transformed", transformedId); m_Addressables.InternalIdTransformFunc = null; var originalId = m_Addressables.ResourceManager.TransformInternalId(loc); Assert.AreEqual("original", originalId); } [UnityTest] public IEnumerator WebRequestOverrideTest() { yield return Init(); var originalUrl = "http://127.0.0.1/original.asset"; var replacedUrl = "http://127.0.0.1/replaced.asset"; var uwr = new UnityWebRequest(originalUrl); m_Addressables.WebRequestOverride = request => request.url = replacedUrl; m_Addressables.ResourceManager.WebRequestOverride(uwr); var currentUrl = uwr.url; uwr.Dispose(); m_Addressables.WebRequestOverride = null; Assert.AreEqual(replacedUrl, currentUrl); } [UnityTest] public IEnumerator CanLoadTextureAsTexture() { //Setup yield return Init(); var op = m_Addressables.LoadAssetAsync("sprite"); yield return op; Assert.IsNotNull(op.Result); Assert.AreEqual(typeof(Texture2D), op.Result.GetType()); op.Release(); } [UnityTest] public IEnumerator LoadAsset_ValidKeyDoesNotThrow() { //Setup yield return Init(); //Test AsyncOperationHandle handle = default(AsyncOperationHandle); Assert.DoesNotThrow(() => { handle = m_Addressables.LoadAssetAsync(AddressablesTestUtility.GetPrefabLabel("BASE")); }); yield return handle; //Cleanup handle.Release(); } [UnityTest] public IEnumerator VerifyChainOpPercentCompleteCalculation() { //Setup yield return Init(); AsyncOperationHandle op = m_Addressables.LoadAssetAsync(AddressablesTestUtility.GetPrefabLabel("BASE")); //Test while (op.PercentComplete < 1) { Assert.False(op.IsDone); yield return null; } yield return null; Assert.True(op.PercentComplete == 1 && op.IsDone); yield return op; //Cleanup op.Release(); } [UnityTest] public IEnumerator LoadResourceLocationsAsync_ReturnsCorrectNumberOfLocationsForStringKey() { yield return Init(); var handle = m_Addressables.LoadResourceLocationsAsync("assetWithDifferentTypedSubAssets"); yield return handle; Assert.AreEqual(3, handle.Result.Count); HashSet typesSeen = new HashSet(); foreach (var result in handle.Result) { Assert.IsNotNull(result.ResourceType); typesSeen.Add(result.ResourceType); } Assert.AreEqual(3, typesSeen.Count); m_Addressables.Release(handle); } [UnityTest] public IEnumerator LoadResourceLocationsAsync_ReturnsCorrectNumberOfLocationsForSubStringKey() { yield return Init(); var handle = m_Addressables.LoadResourceLocationsAsync("assetWithDifferentTypedSubAssets[Mesh]"); yield return handle; Assert.AreEqual(3, handle.Result.Count); HashSet typesSeen = new HashSet(); foreach (var result in handle.Result) { Assert.IsNotNull(result.ResourceType); typesSeen.Add(result.ResourceType); } Assert.AreEqual(3, typesSeen.Count); m_Addressables.Release(handle); } [UnityTest] public IEnumerator LoadResourceLocationsAsync_ReturnsCorrectNumberOfLocationsForSubStringKey_WhenTypeIsPassedIn() { yield return Init(); var handle = m_Addressables.LoadResourceLocationsAsync("assetWithDifferentTypedSubAssets[Mesh]", typeof(Mesh)); yield return handle; Assert.AreEqual(1, handle.Result.Count); Assert.AreEqual(typeof(Mesh), handle.Result[0].ResourceType); m_Addressables.Release(handle); } [UnityTest] public IEnumerator LoadResourceLocationsAsync_ReturnsCorrectNumberOfLocationsForAssetReference() { yield return Init(); AsyncOperationHandle assetReferenceHandle = m_Addressables.InstantiateAsync(AssetReferenceObjectKey); yield return assetReferenceHandle; Assert.IsNotNull(assetReferenceHandle.Result as GameObject); AssetReferenceTestBehavior behavior = (assetReferenceHandle.Result as GameObject).GetComponent(); var handle = m_Addressables.LoadResourceLocationsAsync(behavior.ReferenceWithMultiTypedSubObject); yield return handle; Assert.AreEqual(3, handle.Result.Count); HashSet typesSeen = new HashSet(); foreach (var result in handle.Result) { Assert.IsNotNull(result.ResourceType); typesSeen.Add(result.ResourceType); } Assert.AreEqual(3, typesSeen.Count); m_Addressables.Release(assetReferenceHandle); m_Addressables.Release(handle); } [UnityTest] public IEnumerator LoadResourceLocationsAsync_ReturnsCorrectNumberOfLocationsForSubAssetReference() { yield return Init(); AsyncOperationHandle assetReferenceHandle = m_Addressables.InstantiateAsync(AssetReferenceObjectKey); yield return assetReferenceHandle; Assert.IsNotNull(assetReferenceHandle.Result as GameObject); AssetReferenceTestBehavior behavior = (assetReferenceHandle.Result as GameObject).GetComponent(); var handle = m_Addressables.LoadResourceLocationsAsync(behavior.ReferenceWithMultiTypedSubObjectSubReference); yield return handle; Assert.AreEqual(1, handle.Result.Count); Assert.AreEqual(typeof(Material), handle.Result[0].ResourceType); m_Addressables.Release(assetReferenceHandle); m_Addressables.Release(handle); } [UnityTest] public IEnumerator PercentComplete_NeverHasDecreasedValue_WhenLoadingAsset() { //Setup yield return Init(); AsyncOperationHandle op = m_Addressables.LoadAssetAsync(AddressablesTestUtility.GetPrefabLabel("BASE")); //Test float lastPercentComplete = 0f; while (!op.IsDone) { Assert.IsFalse(lastPercentComplete > op.PercentComplete); lastPercentComplete = op.PercentComplete; yield return null; } Assert.True(op.PercentComplete == 1 && op.IsDone); yield return op; //Cleanup op.Release(); } #if !UNITY_SWITCH [UnityTest] [Platform(Exclude = "Switch")] public IEnumerator LoadContentCatalogAsync_SetsUpLocalAndRemoteLocations() { yield return Init(); string catalogPath = "fakeCatalogPath" + kCatalogExt; string catalogHashPath = "fakeCatalogPath.hash"; var loc = m_Addressables.CreateCatalogLocationWithHashDependencies(catalogPath); Assert.AreEqual(2, loc.Dependencies.Count); var remoteLocation = loc.Dependencies[(int)ContentCatalogProvider.DependencyHashIndex.Remote]; var cacheLocation = loc.Dependencies[(int)ContentCatalogProvider.DependencyHashIndex.Cache]; Assert.AreEqual(catalogHashPath, remoteLocation.ToString()); Assert.AreEqual(m_Addressables.ResolveInternalId(AddressablesImpl.kCacheDataFolder + catalogHashPath.GetHashCode() + catalogHashPath.Substring(catalogHashPath.LastIndexOf("."))), cacheLocation.ToString()); } #endif [UnityTest] public IEnumerator IsCatalogCached_ReturnsFalse_WhenCatalogLocationDoesNotHaveDependencies() { yield return Init(); ResourceLocationBase fakeCatlaogLoc = new ResourceLocationBase("name", "FakeCatalogID", typeof(ContentCatalogProvider).FullName, typeof(ContentCatalogProvider)); Hash128 hash = Hash128.Parse("1234"); var result = m_Addressables.IsCatalogCached(fakeCatlaogLoc, hash); Assert.IsFalse(result); } [UnityTest] public IEnumerator IsCatalogCached_ReturnsFalse_WhenCatalogLocationDoesNotHaveRemoteHashFileDependency() { yield return Init(); ResourceLocationBase fakeCatlaogLoc = new ResourceLocationBase("name", "FakeCatalogID", typeof(ContentCatalogProvider).FullName, typeof(ContentCatalogProvider), new ResourceLocationBase("dep", "fakedep", typeof(ContentCatalogProvider).FullName, typeof(ContentCatalogProvider))); Hash128 hash = Hash128.Parse("1234"); var result = m_Addressables.IsCatalogCached(fakeCatlaogLoc, hash); Assert.IsFalse(result); } [UnityTest] public IEnumerator IsCatalogCached_ReturnsFalse_WhenCatalogLocationCacheFileDoesNotExist() { yield return Init(); ResourceLocationBase fakeCatlaogLoc = new ResourceLocationBase("name", "FakeCatalogID", typeof(ContentCatalogProvider).FullName, typeof(ContentCatalogProvider), new ResourceLocationBase("dep", "notarealfilepath", typeof(ContentCatalogProvider).FullName, typeof(ContentCatalogProvider)), new ResourceLocationBase("dep", "fakedep", typeof(ContentCatalogProvider).FullName, typeof(ContentCatalogProvider))); Hash128 hash = Hash128.Parse("1234"); var result = m_Addressables.IsCatalogCached(fakeCatlaogLoc, hash); Assert.IsFalse(result); } #if UNITY_EDITOR //these tests involve writing files, which can have problems on some of the consoles [UnityTest] public IEnumerator IsCatalogCached_ReturnsFalse_WhenCatalogLocationCacheFileHashDoesNotMatchProvdedRemoteHash() { yield return Init(); Hash128 cacheHash = Hash128.Parse("1234"); Hash128 remoteHash = Hash128.Parse("5678"); string cacheHashFilePath = Path.Combine(kCatalogFolderPath, "CachedFilePath.hash"); WriteHashFileForCatalog(cacheHashFilePath, cacheHash.ToString()); ResourceLocationBase fakeCatlaogLoc = new ResourceLocationBase("name", "FakeCatalogID", typeof(ContentCatalogProvider).FullName, typeof(ContentCatalogProvider), new ResourceLocationBase("dep", "fakedep", typeof(ContentCatalogProvider).FullName, typeof(ContentCatalogProvider)), new ResourceLocationBase("dep", cacheHashFilePath, typeof(ContentCatalogProvider).FullName, typeof(ContentCatalogProvider))); var result = m_Addressables.IsCatalogCached(fakeCatlaogLoc, remoteHash); Assert.IsFalse(result); File.Delete(cacheHashFilePath); } [UnityTest] public IEnumerator IsCatalogCached_ReturnsTrue_WhenCatalogLocationCacheFileHashMatchesProvdedRemoteHash() { yield return Init(); Hash128 cacheHash = Hash128.Parse("1234"); Hash128 remoteHash = Hash128.Parse("1234"); string cacheHashFilePath = Path.Combine(kCatalogFolderPath, "CachedFilePath.hash"); WriteHashFileForCatalog(cacheHashFilePath, cacheHash.ToString()); ResourceLocationBase fakeCatlaogLoc = new ResourceLocationBase("name", "FakeCatalogID", typeof(ContentCatalogProvider).FullName, typeof(ContentCatalogProvider), new ResourceLocationBase("dep", "fakedep", typeof(ContentCatalogProvider).FullName, typeof(ContentCatalogProvider)), new ResourceLocationBase("dep", cacheHashFilePath, typeof(ContentCatalogProvider).FullName, typeof(ContentCatalogProvider))); var result = m_Addressables.IsCatalogCached(fakeCatlaogLoc, remoteHash); Assert.IsTrue(result); File.Delete(cacheHashFilePath); } #endif #if !UNITY_SWITCH [UnityTest] public IEnumerator LoadContentCatalogAsync_LocationsHaveTimeout() { yield return Init(); string catalogPath = "fakeCatalogPath" + kCatalogExt; m_Addressables.CatalogRequestsTimeout = 13; var loc = m_Addressables.CreateCatalogLocationWithHashDependencies(catalogPath); Assert.AreEqual(2, loc.Dependencies.Count); var remoteLocation = loc.Dependencies[(int)ContentCatalogProvider.DependencyHashIndex.Remote]; var cacheLocation = loc.Dependencies[(int)ContentCatalogProvider.DependencyHashIndex.Cache]; var data = loc.Data as ProviderLoadRequestOptions; Assert.IsNotNull(data); Assert.AreEqual(data.WebRequestTimeout, m_Addressables.CatalogRequestsTimeout); data = remoteLocation.Data as ProviderLoadRequestOptions; Assert.IsNotNull(data); Assert.AreEqual(data.WebRequestTimeout, m_Addressables.CatalogRequestsTimeout); data = cacheLocation.Data as ProviderLoadRequestOptions; Assert.IsNotNull(data); Assert.AreEqual(data.WebRequestTimeout, m_Addressables.CatalogRequestsTimeout); } #endif #if UNITY_EDITOR [UnityTest] public IEnumerator LoadingContentCatalogTwice_DoesNotThrowException_WhenHandleIsntReleased() { yield return Init(); string fullRemotePath = Path.Combine(kCatalogFolderPath, kCatalogRemotePath); Directory.CreateDirectory(kCatalogFolderPath); if (m_Addressables.m_ResourceLocators[0].CatalogLocation == null) { ContentCatalogData data = new ContentCatalogData("test_catalog"); data.SetData(new List { new ContentCatalogDataEntry(typeof(string), "testString", "test.provider", new[] {"key"}) }); data.SaveToFile(fullRemotePath); } else { string baseCatalogPath = m_Addressables.m_ResourceLocators[0].CatalogLocation.InternalId; if (baseCatalogPath.StartsWith("file://")) baseCatalogPath = new Uri(m_Addressables.m_ResourceLocators[0].CatalogLocation.InternalId).AbsolutePath; File.Copy(baseCatalogPath, fullRemotePath); } var op1 = m_Addressables.LoadContentCatalogAsync(fullRemotePath, false); yield return op1; var op2 = m_Addressables.LoadContentCatalogAsync(fullRemotePath, false); yield return op2; Assert.AreEqual(AsyncOperationStatus.Succeeded, op1.Status); Assert.AreEqual(AsyncOperationStatus.Succeeded, op2.Status); m_Addressables.Release(op1); m_Addressables.Release(op2); if (Directory.Exists(kCatalogFolderPath)) Directory.Delete(kCatalogFolderPath, true); } #endif #if UNITY_EDITOR [UnityTest] public IEnumerator LoadingContentCatalogWithCacheTwice_DoesNotThrowException_WhenHandleIsntReleased() { yield return Init(); string fullRemotePath = Path.Combine(kCatalogFolderPath, kCatalogRemotePath); Directory.CreateDirectory(kCatalogFolderPath); if (m_Addressables.m_ResourceLocators[0].CatalogLocation == null) { ContentCatalogData data = new ContentCatalogData("test_catalog"); data.SetData(new List { new ContentCatalogDataEntry(typeof(string), "testString", "test.provider", new[] {"key"}) }); data.SaveToFile(fullRemotePath); } else { string baseCatalogPath = m_Addressables.m_ResourceLocators[0].CatalogLocation.InternalId; if (baseCatalogPath.StartsWith("file://")) baseCatalogPath = new Uri(m_Addressables.m_ResourceLocators[0].CatalogLocation.InternalId).AbsolutePath; File.Copy(baseCatalogPath, fullRemotePath); } WriteHashFileForCatalog(fullRemotePath, "123"); var op1 = m_Addressables.LoadContentCatalogAsync(fullRemotePath, false); yield return op1; var op2 = m_Addressables.LoadContentCatalogAsync(fullRemotePath, false); yield return op2; Assert.AreEqual(AsyncOperationStatus.Succeeded, op1.Status); Assert.AreEqual(AsyncOperationStatus.Succeeded, op2.Status); m_Addressables.Release(op1); m_Addressables.Release(op2); if (Directory.Exists(kCatalogFolderPath)) Directory.Delete(kCatalogFolderPath, true); } #endif [UnityTest] public IEnumerator LoadingContentCatalog_WithInvalidCatalogPath_Fails() { yield return Init(); bool ignoreValue = LogAssert.ignoreFailingMessages; LogAssert.ignoreFailingMessages = true; var op1 = m_Addressables.LoadContentCatalogAsync("notarealpath" + kCatalogExt, false); yield return op1; Assert.AreEqual(AsyncOperationStatus.Failed, op1.Status); m_Addressables.Release(op1); LogAssert.ignoreFailingMessages = ignoreValue; } private const string kCatalogRemotePath = "remotecatalog" + kCatalogExt; private const string kCatalogFolderPath = "Assets/CatalogTestFolder"; bool CreateCatalogAtFakeRemotePath(string fakeRemotePath, string catalogFolderPath = kCatalogFolderPath) { Directory.CreateDirectory(catalogFolderPath); if (m_Addressables.m_ResourceLocators[0].CatalogLocation == null) { #if UNITY_EDITOR ContentCatalogData data = new ContentCatalogData("test_catalog"); data.SetData(new List { new ContentCatalogDataEntry(typeof(string), "testString", "test.provider", new[] {"key"}) }); data.SaveToFile(fakeRemotePath); #else return false; #endif } else { string baseCatalogPath = m_Addressables.m_ResourceLocators[0].CatalogLocation.InternalId; if (baseCatalogPath.StartsWith("file://")) baseCatalogPath = new Uri(m_Addressables.m_ResourceLocators[0].CatalogLocation.InternalId).AbsolutePath; File.Copy(baseCatalogPath, fakeRemotePath); } return true; } private string WriteHashFileForCatalog(string catalogPath, string hash) { string hashPath = catalogPath.Replace(kCatalogExt, ".hash"); Directory.CreateDirectory(Path.GetDirectoryName(hashPath)); File.WriteAllText(hashPath, hash); return hashPath; } void StubTextAndJsonProviders() { var textProvider = m_Addressables.ResourceManager.ResourceProviders.FirstOrDefault(rp => rp.GetType() == typeof(TextDataProvider)) as TextDataProvider; var jsonProvider = m_Addressables.ResourceManager.ResourceProviders.FirstOrDefault(rp => rp.GetType() == typeof(JsonAssetProvider)) as JsonAssetProvider; var textDataProviderStub = new TextDataProviderStub(kCatalogFolderPath, textProvider); var jsonAssetProviderStub = new JsonAssetProviderStub(kCatalogFolderPath, jsonProvider); m_Addressables.ResourceManager.ResourceProviders.Remove(textProvider); m_Addressables.ResourceManager.ResourceProviders.Remove(jsonProvider); m_Addressables.ResourceManager.ResourceProviders.Add(textDataProviderStub); m_Addressables.ResourceManager.ResourceProviders.Add(jsonAssetProviderStub); m_Addressables.ResourceManager.m_providerMap.Clear(); } #if UNITY_EDITOR [UnityTest] public IEnumerator LoadingContentCatalog_CachesCatalogData_IfValidHashFound() { yield return Init(); string fullRemotePath = Path.Combine(kCatalogFolderPath, kCatalogRemotePath); Directory.CreateDirectory(kCatalogFolderPath); if (m_Addressables.m_ResourceLocators[0].CatalogLocation == null) { ContentCatalogData data = new ContentCatalogData("test_catalog"); data.SetData(new List { new ContentCatalogDataEntry(typeof(string), "testString", "test.provider", new[] {"key"}) }); data.SaveToFile(fullRemotePath); } else { string baseCatalogPath = m_Addressables.m_ResourceLocators[0].CatalogLocation.InternalId; if (baseCatalogPath.StartsWith("file://")) baseCatalogPath = new Uri(m_Addressables.m_ResourceLocators[0].CatalogLocation.InternalId).AbsolutePath; File.Copy(baseCatalogPath, fullRemotePath); } WriteHashFileForCatalog(fullRemotePath, "123"); var op1 = m_Addressables.LoadContentCatalogAsync(fullRemotePath, false); yield return op1; string fullRemoteHashPath = fullRemotePath.Replace(kCatalogExt, ".hash"); string cachedDataPath = m_Addressables.ResolveInternalId(AddressablesImpl.kCacheDataFolder + fullRemoteHashPath.GetHashCode() + fullRemotePath.Substring(fullRemotePath.LastIndexOf("."))); string cachedHashPath = cachedDataPath.Replace(kCatalogExt, ".hash"); Assert.IsTrue(File.Exists(cachedDataPath)); Assert.IsTrue(File.Exists(cachedHashPath)); Assert.AreEqual("123", File.ReadAllText(cachedHashPath)); m_Addressables.Release(op1); Directory.Delete(kCatalogFolderPath, true); File.Delete(cachedDataPath); File.Delete(cachedHashPath); } #endif #if UNITY_EDITOR [UnityTest] public IEnumerator LoadingContentCatalog_CachesCatalogData_IfValidHashFoundAndRemotePathContainsQueryParameters() { yield return Init(); string fakeFullRemotePath = Path.Combine(kCatalogFolderPath, kCatalogRemotePath); if (!CreateCatalogAtFakeRemotePath(fakeFullRemotePath)) Assert.Ignore($"Skipping test {TestContext.CurrentContext.Test.Name} due to missing CatalogLocation."); WriteHashFileForCatalog(fakeFullRemotePath, "123"); StubTextAndJsonProviders(); string catalogRemotePath = "http://127.0.0.1/" + kCatalogRemotePath; string catalogRemotePathWithQueryParams = catalogRemotePath + "?param1=value1¶m2=value2:date=number"; var op1 = m_Addressables.LoadContentCatalogAsync(catalogRemotePathWithQueryParams, false); yield return op1; var expectedHash = catalogRemotePath.Replace(kCatalogExt, ".hash").GetHashCode(); string expectedCatalogName = expectedHash + kCatalogExt; string cachedDataPath = m_Addressables.ResolveInternalId(AddressablesImpl.kCacheDataFolder + expectedCatalogName); string cachedHashPath = cachedDataPath.Replace(kCatalogExt, ".hash"); Assert.IsTrue(File.Exists(cachedDataPath)); Assert.IsTrue(File.Exists(cachedHashPath)); Assert.AreEqual("123", File.ReadAllText(cachedHashPath)); m_Addressables.Release(op1); Directory.Delete(kCatalogFolderPath, true); File.Delete(cachedDataPath); File.Delete(cachedHashPath); } [UnityTest] public IEnumerator LoadingContentCatalog_CachesCatalogData_ForTwoCatalogsWithSameName() { yield return Init(); string fullRemotePath = Path.Combine(kCatalogFolderPath, kCatalogRemotePath); string fullRemotePathTwo = Path.Combine(kCatalogFolderPath, "secondCatalog", kCatalogRemotePath); Directory.CreateDirectory(kCatalogFolderPath); Directory.CreateDirectory(Path.Combine(kCatalogFolderPath, "secondCatalog")); if (m_Addressables.m_ResourceLocators[0].CatalogLocation == null) { ContentCatalogData data = new ContentCatalogData("test_catalog"); data.SetData(new List { new ContentCatalogDataEntry(typeof(string), "testString", "test.provider", new[] {"key"}) }); data.SaveToFile(fullRemotePath); data.SaveToFile(fullRemotePathTwo); } else { string baseCatalogPath = m_Addressables.m_ResourceLocators[0].CatalogLocation.InternalId; if (baseCatalogPath.StartsWith("file://")) baseCatalogPath = new Uri(m_Addressables.m_ResourceLocators[0].CatalogLocation.InternalId).AbsolutePath; File.Copy(baseCatalogPath, fullRemotePath); } ContentCatalogData catalogData = new ContentCatalogData("test_catalog"); catalogData.SetData(new List { new ContentCatalogDataEntry(typeof(string), "testString", "test.provider", new[] {"key"}) }); catalogData.SaveToFile(fullRemotePathTwo); WriteHashFileForCatalog(fullRemotePath, "123"); WriteHashFileForCatalog(fullRemotePathTwo, "123"); var op1 = m_Addressables.LoadContentCatalogAsync(fullRemotePath, false); yield return op1; var op2 = m_Addressables.LoadContentCatalogAsync(fullRemotePathTwo, false); yield return op2; string fullRemoteHashPath = fullRemotePath.Replace(kCatalogExt, ".hash"); string fullRemoteHashPathTwo = fullRemotePathTwo.Replace(kCatalogExt, ".hash"); string cachedDataPath = m_Addressables.ResolveInternalId(AddressablesImpl.kCacheDataFolder + fullRemoteHashPath.GetHashCode() + fullRemotePath.Substring(fullRemotePath.LastIndexOf("."))); string cachedDataPathTwo = m_Addressables.ResolveInternalId(AddressablesImpl.kCacheDataFolder + fullRemoteHashPathTwo.GetHashCode() + fullRemotePathTwo.Substring(fullRemotePathTwo.LastIndexOf("."))); string cachedHashPath = cachedDataPath.Replace(kCatalogExt, ".hash"); string cachedHashPathTwo = cachedDataPathTwo.Replace(kCatalogExt, ".hash"); Assert.IsTrue(File.Exists(cachedDataPath)); Assert.IsTrue(File.Exists(cachedDataPathTwo)); Assert.IsTrue(File.Exists(cachedHashPath)); Assert.IsTrue(File.Exists(cachedHashPathTwo)); Assert.AreEqual("123", File.ReadAllText(cachedHashPath)); Assert.AreEqual("123", File.ReadAllText(cachedHashPathTwo)); m_Addressables.Release(op1); m_Addressables.Release(op2); Directory.Delete(kCatalogFolderPath, true); File.Delete(cachedDataPath); File.Delete(cachedHashPath); File.Delete(cachedDataPathTwo); File.Delete(cachedHashPathTwo); } #endif #if UNITY_EDITOR [UnityTest] public IEnumerator LoadingContentCatalog_IfNoCachedHashFound_Succeeds() { yield return Init(); ResourceManager.ExceptionHandler = m_PrevHandler; string fullRemotePath = Path.Combine(kCatalogFolderPath, kCatalogRemotePath); Directory.CreateDirectory(kCatalogFolderPath); if (m_Addressables.m_ResourceLocators[0].CatalogLocation == null) { ContentCatalogData data = new ContentCatalogData("test_catalog"); data.SetData(new List { new ContentCatalogDataEntry(typeof(string), "testString", "test.provider", new[] {"key"}) }); data.SaveToFile(fullRemotePath); } else { string baseCatalogPath = m_Addressables.m_ResourceLocators[0].CatalogLocation.InternalId; if (baseCatalogPath.StartsWith("file://")) baseCatalogPath = new Uri(m_Addressables.m_ResourceLocators[0].CatalogLocation.InternalId).AbsolutePath; File.Copy(baseCatalogPath, fullRemotePath); } WriteHashFileForCatalog(fullRemotePath, "123"); string cachedDataPath = m_Addressables.ResolveInternalId(AddressablesImpl.kCacheDataFolder + Path.GetFileName(kCatalogRemotePath)); string cachedHashPath = cachedDataPath.Replace(kCatalogExt, ".hash"); if (File.Exists(cachedDataPath)) File.Delete(cachedDataPath); if (File.Exists(cachedHashPath)) File.Delete(cachedHashPath); var op1 = m_Addressables.LoadContentCatalogAsync(fullRemotePath, false); yield return op1; Assert.IsTrue(op1.IsValid()); Assert.AreEqual(AsyncOperationStatus.Succeeded, op1.Status); Assert.NotNull(op1.Result); // Cleanup Addressables.Release(op1); Directory.Delete(kCatalogFolderPath, true); File.Delete(cachedDataPath); File.Delete(cachedHashPath); } [UnityTest] public IEnumerator LoadingContentCatalog_IfNoHashFileForCatalog_DoesntThrowException() { yield return Init(); ResourceManager.ExceptionHandler = m_PrevHandler; string fullRemotePath = Path.Combine(kCatalogFolderPath, kCatalogRemotePath); Directory.CreateDirectory(kCatalogFolderPath); if (m_Addressables.m_ResourceLocators[0].CatalogLocation == null) { ContentCatalogData data = new ContentCatalogData("test_catalog"); data.SetData(new List { new ContentCatalogDataEntry(typeof(string), "testString", "test.provider", new[] {"key"}) }); data.SaveToFile(fullRemotePath); } else { string baseCatalogPath = m_Addressables.m_ResourceLocators[0].CatalogLocation.InternalId; if (baseCatalogPath.StartsWith("file://")) baseCatalogPath = new Uri(m_Addressables.m_ResourceLocators[0].CatalogLocation.InternalId).AbsolutePath; File.Copy(baseCatalogPath, fullRemotePath); } string cachedDataPath = m_Addressables.ResolveInternalId(AddressablesImpl.kCacheDataFolder + Path.GetFileName(kCatalogRemotePath)); string cachedHashPath = cachedDataPath.Replace(kCatalogExt, ".hash"); if (File.Exists(cachedDataPath)) File.Delete(cachedDataPath); if (File.Exists(cachedHashPath)) File.Delete(cachedHashPath); var op1 = m_Addressables.LoadContentCatalogAsync(fullRemotePath, false); yield return op1; Assert.IsTrue(op1.IsValid()); Assert.AreEqual(AsyncOperationStatus.Succeeded, op1.Status); Assert.NotNull(op1.Result); Assert.IsFalse(File.Exists(cachedHashPath)); // Cleanup Addressables.Release(op1); Directory.Delete(kCatalogFolderPath, true); File.Delete(cachedDataPath); File.Delete(cachedHashPath); } #endif [UnityTest] public IEnumerator IResourceLocationComparing_SameKeySameTypeDifferentInternalId_ReturnsFalse() { yield return Init(); IResourceLocation loc1 = new ResourceLocationBase("address", "internalid1", typeof(BundledAssetProvider).FullName, typeof(GameObject)); IResourceLocation loc2 = new ResourceLocationBase("address", "internalid2", typeof(BundledAssetProvider).FullName, typeof(GameObject)); Assert.IsFalse(m_Addressables.Equals(loc1, loc2)); } [UnityTest] public IEnumerator IResourceLocationComparing_SameKeyTypeAndInternalId_ReturnsTrue() { yield return Init(); IResourceLocation loc1 = new ResourceLocationBase("address", "internalid1", typeof(BundledAssetProvider).FullName, typeof(GameObject)); IResourceLocation loc2 = new ResourceLocationBase("address", "internalid1", typeof(BundledAssetProvider).FullName, typeof(GameObject)); Assert.IsTrue(m_Addressables.Equals(loc1, loc2)); } #if UNITY_EDITOR [UnityTest] public IEnumerator LoadingContentCatalog_UpdatesCachedData_IfHashFileUpdates() { yield return Init(); if (m_Addressables.m_ResourceLocators[0].CatalogLocation == null) { UnityEngine.Debug.Log($"Skipping test {nameof(LoadingContentCatalog_UpdatesCachedData_IfHashFileUpdates)} due to missing CatalogLocation."); yield break; } Directory.CreateDirectory(kCatalogFolderPath); string fullRemotePath = Path.Combine(kCatalogFolderPath, kCatalogRemotePath); string fullRemoteHashPath = fullRemotePath.Replace(kCatalogExt, ".hash"); string cachedDataPath = m_Addressables.ResolveInternalId(AddressablesImpl.kCacheDataFolder + fullRemoteHashPath.GetHashCode() + fullRemotePath.Substring(fullRemotePath.LastIndexOf("."))); string cachedHashPath = cachedDataPath.Replace(kCatalogExt, ".hash"); string remoteHashPath = WriteHashFileForCatalog(fullRemotePath, "123"); string baseCatalogPath = m_Addressables.m_ResourceLocators[0].CatalogLocation.InternalId; if (baseCatalogPath.StartsWith("file://")) baseCatalogPath = new Uri(m_Addressables.m_ResourceLocators[0].CatalogLocation.InternalId).AbsolutePath; File.Copy(baseCatalogPath, fullRemotePath); var op1 = m_Addressables.LoadContentCatalogAsync(fullRemotePath, false); yield return op1; m_Addressables.Release(op1); Assert.IsTrue(File.Exists(cachedDataPath)); Assert.IsTrue(File.Exists(cachedHashPath)); Assert.AreEqual("123", File.ReadAllText(cachedHashPath)); remoteHashPath = WriteHashFileForCatalog(fullRemotePath, "456"); var op2 = m_Addressables.LoadContentCatalogAsync(fullRemotePath, false); yield return op2; Assert.AreEqual("456", File.ReadAllText(cachedHashPath)); m_Addressables.Release(op2); Directory.Delete(kCatalogFolderPath, true); File.Delete(cachedDataPath); File.Delete(cachedHashPath); } [UnityTest] public IEnumerator UpdateContentCatalog_UpdatesCachedData_IfCacheCorrupted() { yield return Init(); if (m_Addressables.m_ResourceLocators[0].CatalogLocation == null) { UnityEngine.Debug.Log($"Skipping test {nameof(LoadingContentCatalog_UpdatesCachedData_IfHashFileUpdates)} due to missing CatalogLocation."); yield break; } Directory.CreateDirectory(kCatalogFolderPath); string fullRemotePath = Path.Combine(kCatalogFolderPath, kCatalogRemotePath); string fullRemoteHashPath = fullRemotePath.Replace(kCatalogExt, ".hash"); string cachedDataPath = m_Addressables.ResolveInternalId(AddressablesImpl.kCacheDataFolder + fullRemoteHashPath.GetHashCode() + fullRemotePath.Substring(fullRemotePath.LastIndexOf("."))); string cachedHashPath = cachedDataPath.Replace(kCatalogExt, ".hash"); string remoteHashPath = WriteHashFileForCatalog(fullRemoteHashPath, "123"); string baseCatalogPath = m_Addressables.m_ResourceLocators[0].CatalogLocation.InternalId; if (baseCatalogPath.StartsWith("file://")) baseCatalogPath = new Uri(m_Addressables.m_ResourceLocators[0].CatalogLocation.InternalId).AbsolutePath; File.Copy(baseCatalogPath, fullRemotePath); File.WriteAllText(remoteHashPath, File.ReadAllText(cachedHashPath)); File.WriteAllText(cachedDataPath, "corrupted content"); //load from fullRemotePath will first load cachedDataPath, then load fullRemotePath on error var op = m_Addressables.LoadContentCatalogAsync(fullRemotePath, false); LogAssert.Expect(LogType.Exception, new Regex(".*JSON parse error.*")); yield return op; Assert.IsTrue(File.Exists(cachedDataPath)); Assert.IsTrue(File.Exists(cachedHashPath)); Assert.AreEqual(File.ReadAllText(cachedDataPath), File.ReadAllText(fullRemotePath)); m_Addressables.Release(op); Directory.Delete(kCatalogFolderPath, true); File.Delete(cachedDataPath); File.Delete(cachedHashPath); } [UnityTest] public IEnumerator LoadingContentCatalog_NoCacheDataCreated_IfRemoteHashDoesntExist() { yield return Init(); if (m_Addressables.m_ResourceLocators[0].CatalogLocation == null) { UnityEngine.Debug.Log($"Skipping test {nameof(LoadingContentCatalog_NoCacheDataCreated_IfRemoteHashDoesntExist)} due to missing CatalogLocation."); yield break; } Directory.CreateDirectory(kCatalogFolderPath); string fullRemotePath = Path.Combine(kCatalogFolderPath, kCatalogRemotePath); string cachedDataPath = m_Addressables.ResolveInternalId(AddressablesImpl.kCacheDataFolder + Path.GetFileName(kCatalogRemotePath)); string cachedHashPath = cachedDataPath.Replace(kCatalogExt, ".hash"); string baseCatalogPath = m_Addressables.m_ResourceLocators[0].CatalogLocation.InternalId; if (baseCatalogPath.StartsWith("file://")) baseCatalogPath = new Uri(m_Addressables.m_ResourceLocators[0].CatalogLocation.InternalId).AbsolutePath; File.Copy(baseCatalogPath, fullRemotePath); var op1 = m_Addressables.LoadContentCatalogAsync(fullRemotePath, false); yield return op1; m_Addressables.Release(op1); Assert.IsFalse(File.Exists(cachedDataPath)); Assert.IsFalse(File.Exists(cachedHashPath)); Directory.Delete(kCatalogFolderPath, true); } [UnityTest] public IEnumerator ContentCatalogData_IsCleared_WhenInitializationOperationLoadContentCatalogOp_IsReleased() { yield return Init(); if (m_Addressables.m_ResourceLocators[0].CatalogLocation == null) { UnityEngine.Debug.Log($"Skipping test {nameof(ContentCatalogData_IsCleared_WhenInitializationOperationLoadContentCatalogOp_IsReleased)} due to missing CatalogLocation."); yield break; } string baseCatalogPath = m_Addressables.m_ResourceLocators[0].CatalogLocation.InternalId; if (baseCatalogPath.StartsWith("file://")) baseCatalogPath = new Uri(m_Addressables.m_ResourceLocators[0].CatalogLocation.InternalId).AbsolutePath; var location = m_Addressables.CreateCatalogLocationWithHashDependencies(baseCatalogPath); var loadCatalogHandle = InitializationOperation.LoadContentCatalog(m_Addressables, location, string.Empty); yield return loadCatalogHandle; ContentCatalogProvider ccp = m_Addressables.ResourceManager.ResourceProviders .FirstOrDefault(rp => rp.GetType() == typeof(ContentCatalogProvider)) as ContentCatalogProvider; var ccd = ccp.m_LocationToCatalogLoadOpMap[location].m_ContentCatalogData; Assert.IsFalse(CatalogDataWasCleaned(ccd)); loadCatalogHandle.Release(); Assert.IsTrue(CatalogDataWasCleaned(ccd)); PostTearDownEvent = ResetAddressables; } #endif internal bool CatalogDataWasCleaned(ContentCatalogData data) { #if ENABLE_BINARY_CATALOG return string.IsNullOrEmpty(data.m_LocatorId); #else return string.IsNullOrEmpty(data.m_KeyDataString) && string.IsNullOrEmpty(data.m_BucketDataString) && string.IsNullOrEmpty(data.m_EntryDataString) && string.IsNullOrEmpty(data.m_ExtraDataString) && data.m_InternalIds == null && string.IsNullOrEmpty(data.m_LocatorId) && data.m_ProviderIds == null && data.m_ResourceProviderData == null && data.m_resourceTypes == null; #endif } #if UNITY_EDITOR [UnityTest] public IEnumerator ContentCatalogData_IsCleared_ForCorrectCatalogLoadOp_WhenOpIsReleased() { yield return Init(); if (m_Addressables.m_ResourceLocators[0].CatalogLocation == null) { UnityEngine.Debug.Log($"Skipping test {nameof(ContentCatalogData_IsCleared_ForCorrectCatalogLoadOp_WhenOpIsReleased)} due to missing CatalogLocation."); yield break; } Directory.CreateDirectory(kCatalogFolderPath); string fullRemotePath = Path.Combine(kCatalogFolderPath, kCatalogRemotePath); string baseCatalogPath = m_Addressables.m_ResourceLocators[0].CatalogLocation.InternalId; if (baseCatalogPath.StartsWith("file://")) baseCatalogPath = new Uri(m_Addressables.m_ResourceLocators[0].CatalogLocation.InternalId).AbsolutePath; File.Copy(baseCatalogPath, fullRemotePath); var location = m_Addressables.CreateCatalogLocationWithHashDependencies(baseCatalogPath); var location2 = m_Addressables.CreateCatalogLocationWithHashDependencies(fullRemotePath); var loadCatalogHandle = InitializationOperation.LoadContentCatalog(m_Addressables, location, string.Empty); yield return loadCatalogHandle; var loadCatalogHandle2 = InitializationOperation.LoadContentCatalog(m_Addressables, location2, string.Empty); yield return loadCatalogHandle2; ContentCatalogProvider ccp = m_Addressables.ResourceManager.ResourceProviders .FirstOrDefault(rp => rp.GetType() == typeof(ContentCatalogProvider)) as ContentCatalogProvider; var ccd = ccp.m_LocationToCatalogLoadOpMap[location].m_ContentCatalogData; var ccd2 = ccp.m_LocationToCatalogLoadOpMap[location2].m_ContentCatalogData; Assert.IsFalse(CatalogDataWasCleaned(ccd)); Assert.IsFalse(CatalogDataWasCleaned(ccd2)); loadCatalogHandle.Release(); Assert.IsTrue(CatalogDataWasCleaned(ccd)); Assert.IsFalse(CatalogDataWasCleaned(ccd2)); Directory.Delete(kCatalogFolderPath, true); loadCatalogHandle2.Release(); PostTearDownEvent = ResetAddressables; } #endif [UnityTest] public IEnumerator ContentCatalogProvider_RemovesEntryFromMap_WhenOperationHandleReleased() { yield return Init(); if (m_Addressables.m_ResourceLocators[0].CatalogLocation == null) { UnityEngine.Debug.Log($"Skipping test {nameof(ContentCatalogProvider_RemovesEntryFromMap_WhenOperationHandleReleased)} due to missing CatalogLocation."); yield break; } string baseCatalogPath = m_Addressables.m_ResourceLocators[0].CatalogLocation.InternalId; if (baseCatalogPath.StartsWith("file://")) baseCatalogPath = new Uri(m_Addressables.m_ResourceLocators[0].CatalogLocation.InternalId).AbsolutePath; var handle = m_Addressables.LoadContentCatalogAsync(baseCatalogPath, false); yield return handle; ContentCatalogProvider ccp = m_Addressables.ResourceManager.ResourceProviders .FirstOrDefault(rp => rp.GetType() == typeof(ContentCatalogProvider)) as ContentCatalogProvider; Assert.AreEqual(1, ccp.m_LocationToCatalogLoadOpMap.Count); handle.Release(); Assert.AreEqual(0, ccp.m_LocationToCatalogLoadOpMap.Count); PostTearDownEvent = ResetAddressables; } [UnityTest] public IEnumerator VerifyProfileVariableEvaluation() { yield return Init(); Assert.AreEqual(string.Format("{0}", m_Addressables.RuntimePath), AddressablesRuntimeProperties.EvaluateString("{UnityEngine.AddressableAssets.Addressables.RuntimePath}")); } [UnityTest] public IEnumerator VerifyDownloadSize() { yield return Init(); long expectedSize = 0; var locMap = new ResourceLocationMap("TestLocator"); var bundleLoc1 = new ResourceLocationBase("sizeTestBundle1", "http://nonExistingUrlForAddressableTests1337.com/mybundle1.bundle", typeof(AssetBundleProvider).FullName, typeof(object)); var sizeData1 = (bundleLoc1.Data = CreateLocationSizeData("sizeTestBundle1", 1000, 123, "hashstring1")) as ILocationSizeData; if (sizeData1 != null) expectedSize += sizeData1.ComputeSize(bundleLoc1, null); var bundleLoc2 = new ResourceLocationBase("sizeTestBundle2", "http://nonExistingUrlForAddressableTests1337.com/mybundle2.bundle", typeof(AssetBundleProvider).FullName, typeof(object)); var sizeData2 = (bundleLoc2.Data = CreateLocationSizeData("sizeTestBundle2", 500, 123, "hashstring2")) as ILocationSizeData; if (sizeData2 != null) expectedSize += sizeData2.ComputeSize(bundleLoc2, null); var assetLoc = new ResourceLocationBase("sizeTestAsset", "myASset.asset", typeof(BundledAssetProvider).FullName, typeof(object), bundleLoc1, bundleLoc2); locMap.Add("sizeTestBundle1", bundleLoc1); locMap.Add("sizeTestBundle2", bundleLoc2); locMap.Add("sizeTestAsset", assetLoc); m_Addressables.AddResourceLocator(locMap); var dOp = m_Addressables.GetDownloadSizeAsync((object)"sizeTestAsset"); yield return dOp; Assert.AreEqual(expectedSize, dOp.Result); dOp.Release(); } public IEnumerator GetDownloadSize_CalculatesCachedBundlesInternal() { #if ENABLE_CACHING yield return Init(); long expectedSize = 0; long bundleSize1 = 1000; long bundleSize2 = 500; var locMap = new ResourceLocationMap("TestLocator"); Caching.ClearCache(); //Simulating a cached bundle string fakeCachePath = CreateFakeCachedBundle("cachedSizeTestBundle1", "be38e35d2177c282d5d6a2e54a803aab"); var bundleLoc1 = new ResourceLocationBase("cachedSizeTestBundle1", "http://nonExistingUrlForAddressableTests1337.com/GetDownloadSize_CalculatesCachedBundlesBundle1.bundle", typeof(AssetBundleProvider).FullName, typeof(object)); var sizeData1 = (bundleLoc1.Data = CreateLocationSizeData("cachedSizeTestBundle1", bundleSize1, 123, "be38e35d2177c282d5d6a2e54a803aab")) as ILocationSizeData; if (sizeData1 != null) expectedSize += sizeData1.ComputeSize(bundleLoc1, null); var bundleLoc2 = new ResourceLocationBase("sizeTestBundle2", "http://nonExistingUrlForAddressableTests1337.com/GetDownloadSize_CalculatesCachedBundlesBundle2.bundle", typeof(AssetBundleProvider).FullName, typeof(object)); var sizeData2 = (bundleLoc2.Data = CreateLocationSizeData("sizeTestBundle2", bundleSize2, 123, "d9fe965a6b253fb9dbd3e1cb08b7d66f")) as ILocationSizeData; if (sizeData2 != null) expectedSize += sizeData2.ComputeSize(bundleLoc2, null); var assetLoc = new ResourceLocationBase("cachedSizeTestAsset", "myASset.asset", typeof(BundledAssetProvider).FullName, typeof(object), bundleLoc1, bundleLoc2); locMap.Add("cachedSizeTestBundle1", bundleLoc1); locMap.Add("cachedSizeTestBundle2", bundleLoc2); locMap.Add("cachedSizeTestAsset", assetLoc); m_Addressables.AddResourceLocator(locMap); var dOp = m_Addressables.GetDownloadSizeAsync((object)"cachedSizeTestAsset"); yield return dOp; Assert.IsTrue((bundleSize1 + bundleSize2) > dOp.Result); Assert.AreEqual(expectedSize, dOp.Result); dOp.Release(); m_Addressables.RemoveResourceLocator(locMap); Directory.Delete(fakeCachePath, true); #else Assert.Ignore(); yield break; #endif } public IEnumerator GetDownloadSize_WithList_CalculatesCachedBundlesInternal() { #if ENABLE_CACHING yield return Init(); long expectedSize = 0; long bundleSize1 = 1000; long bundleSize2 = 500; var locMap = new ResourceLocationMap("TestLocator"); Assert.IsTrue(Caching.ClearCache(), "Was unable to clear the cache. Test results are affected"); //Simulating a cached bundle string fakeCachePath = CreateFakeCachedBundle("cachedSizeTestBundle1", "0e38e35d2177c282d5d6a2e54a803aab"); var bundleLoc1 = new ResourceLocationBase("cachedSizeTestBundle1", "http://nonExistingUrlForAddressableTests1337.com/GetDownloadSize_WithList_CalculatesCachedBundlesBundle1.bundle", typeof(AssetBundleProvider).FullName, typeof(object)); var sizeData1 = (bundleLoc1.Data = CreateLocationSizeData("cachedSizeTestBundle1", bundleSize1, 123, "0e38e35d2177c282d5d6a2e54a803aab")) as ILocationSizeData; if (sizeData1 != null) expectedSize += sizeData1.ComputeSize(bundleLoc1, null); var bundleLoc2 = new ResourceLocationBase("sizeTestBundle2", "http://nonExistingUrlForAddressableTests1337.com/GetDownloadSize_WithList_CalculatesCachedBundlesBundle2.bundle", typeof(AssetBundleProvider).FullName, typeof(object)); var sizeData2 = (bundleLoc2.Data = CreateLocationSizeData("sizeTestBundle2", bundleSize2, 123, "09fe965a6b253fb9dbd3e1cb08b7d66f")) as ILocationSizeData; if (sizeData2 != null) expectedSize += sizeData2.ComputeSize(bundleLoc2, null); var assetLoc = new ResourceLocationBase("cachedSizeTestAsset", "myASset.asset", typeof(BundledAssetProvider).FullName, typeof(object), bundleLoc1, bundleLoc2); locMap.Add("cachedSizeTestBundle1", bundleLoc1); locMap.Add("cachedSizeTestBundle2", bundleLoc2); locMap.Add("cachedSizeTestAsset", assetLoc); m_Addressables.AddResourceLocator(locMap); var dOp = m_Addressables.GetDownloadSizeAsync(new List() { "cachedSizeTestAsset", bundleLoc1, bundleLoc2 } ); yield return dOp; Assert.IsTrue((bundleSize1 + bundleSize2) > dOp.Result); Assert.AreEqual(expectedSize, dOp.Result); dOp.Release(); m_Addressables.RemoveResourceLocator(locMap); Directory.Delete(fakeCachePath, true); #else Assert.Ignore(); yield break; #endif } public IEnumerator GetDownloadSize_WithList_CalculatesCorrectSize_WhenAssetsReferenceSameBundleInternal() { #if ENABLE_CACHING yield return Init(); long bundleSize1 = 1000; long expectedSize = 0; var bundleLoc1 = new ResourceLocationBase("sizeTestBundle1", "http://nonExistingUrlForAddressableTests1337.com/GetDownloadSize_WithList_CalculatesCachedBundlesBundle1.bundle", typeof(AssetBundleProvider).FullName, typeof(object)); var sizeData1 = (bundleLoc1.Data = CreateLocationSizeData("cachedSizeTestBundle1", bundleSize1, 123, "0e38e35d2177c282d5d6a2e54a803aab")) as ILocationSizeData; if (sizeData1 != null) expectedSize += sizeData1.ComputeSize(bundleLoc1, null); var assetLoc1 = new ResourceLocationBase("cachedSizeTestAsset1", "myAsset1.asset", typeof(BundledAssetProvider).FullName, typeof(object), bundleLoc1); var assetLoc2 = new ResourceLocationBase("cachedSizeTestAsset2", "myAsset2.asset", typeof(BundledAssetProvider).FullName, typeof(object), bundleLoc1); var dOp = m_Addressables.GetDownloadSizeAsync(new List() { assetLoc1, assetLoc2 } ); yield return dOp; Assert.IsTrue(bundleSize1 >= dOp.Result); Assert.AreEqual(expectedSize, dOp.Result); #else Assert.Ignore(); yield break; #endif } [UnityTest] public IEnumerator GetDownloadSize_WithList_CalculatesCorrectSize_WhenAssetsReferenceDifferentBundle() { #if ENABLE_CACHING yield return Init(); long bundleSize1 = 1000; long bundleSize2 = 250; long expectedSize = 0; var bundleLoc1 = new ResourceLocationBase("sizeTestBundle1", "http://nonExistingUrlForAddressableTests1337.com/GetDownloadSize_WithList_CalculatesCachedBundlesBundle1.bundle", typeof(AssetBundleProvider).FullName, typeof(object)); var sizeData1 = (bundleLoc1.Data = CreateLocationSizeData("cachedSizeTestBundle1", bundleSize1, 123, "0e38e35d2177c282d5d6a2e54a803aab")) as ILocationSizeData; if (sizeData1 != null) expectedSize += sizeData1.ComputeSize(bundleLoc1, null); var bundleLoc2 = new ResourceLocationBase("cachedSizeTestBundle2", "http://nonExistingUrlForAddressableTests1337.com/GetDownloadSize_WithList_CalculatesCachedBundlesBundle2.bundle", typeof(AssetBundleProvider).FullName, typeof(object)); var sizeData2 = (bundleLoc2.Data = CreateLocationSizeData("cachedSizeTestBundle2", bundleSize2, 123, "09fe965a6b253fb9dbd3e1cb08b7d66f")) as ILocationSizeData; if (sizeData2 != null) expectedSize += sizeData2.ComputeSize(bundleLoc2, null); var assetLoc1 = new ResourceLocationBase("cachedSizeTestAsset1", "myAsset1.asset", typeof(BundledAssetProvider).FullName, typeof(object), bundleLoc1); var assetLoc2 = new ResourceLocationBase("cachedSizeTestAsset2", "myAsset2.asset", typeof(BundledAssetProvider).FullName, typeof(object), bundleLoc2); var dOp = m_Addressables.GetDownloadSizeAsync(new List() { assetLoc1, assetLoc2 } ); yield return dOp; Assert.IsTrue((bundleSize1 + bundleSize2) >= dOp.Result); Assert.AreEqual(expectedSize, dOp.Result); #else Assert.Ignore(); yield break; #endif } [UnityTest] public IEnumerator GetResourceLocationsWithCorrectKeyAndWrongTypeReturnsEmptyResult() { yield return Init(); AsyncOperationHandle> op = m_Addressables.LoadResourceLocationsAsync("prefabs_evenBASE", typeof(Texture2D)); yield return op; Assert.AreEqual(AsyncOperationStatus.Succeeded, op.Status); Assert.IsNotNull(op.Result); Assert.AreEqual(op.Result.Count, 0); op.Release(); } [UnityTest] public IEnumerator CanGetResourceLocationsWithSingleKey() { yield return Init(); int loadCount = 0; int loadedCount = 0; var ops = new List>>(); foreach (var k in m_KeysHashSet) { loadCount++; AsyncOperationHandle> op = m_Addressables.LoadResourceLocationsAsync(k.Key, typeof(object)); ops.Add(op); op.Completed += op2 => { loadedCount++; Assert.IsNotNull(op2.Result); Assert.AreEqual(k.Value, op2.Result.Count); }; } foreach (var op in ops) { yield return op; op.Release(); } } [UnityTest] public IEnumerator GetResourceLocationsMergeModesFailsWithNoKeys( [Values(Addressables.MergeMode.UseFirst, Addressables.MergeMode.Intersection, Addressables.MergeMode.Union)] Addressables.MergeMode mode) { yield return Init(); IList results; var ret = m_Addressables.GetResourceLocations(new object[] { }, typeof(GameObject), mode, out results); Assert.IsFalse(ret); Assert.IsNull(results); } [UnityTest] public IEnumerator GetResourceLocationsMergeModesSucceedsWithSingleKey( [Values(Addressables.MergeMode.UseFirst, Addressables.MergeMode.Intersection, Addressables.MergeMode.Union)] Addressables.MergeMode mode) { yield return Init(); IList results; var ret = m_Addressables.GetResourceLocations(new object[] {"prefabs_evenBASE"}, typeof(GameObject), mode, out results); Assert.IsTrue(ret); Assert.NotNull(results); Assert.GreaterOrEqual(results.Count, 1); } [UnityTest] public IEnumerator GetResourceLocationsMergeModeUnionSucceedsWithValidKeys() { yield return Init(); IList results; var ret = m_Addressables.GetResourceLocations(new object[] {"prefabs_evenBASE"}, typeof(GameObject), Addressables.MergeMode.Intersection, out results); Assert.IsTrue(ret); Assert.NotNull(results); Assert.GreaterOrEqual(results.Count, 1); var evenCount = results.Count; ret = m_Addressables.GetResourceLocations(new object[] {"prefabs_oddBASE"}, typeof(GameObject), Addressables.MergeMode.Intersection, out results); Assert.IsTrue(ret); Assert.NotNull(results); Assert.GreaterOrEqual(results.Count, 1); var oddCount = results.Count; ret = m_Addressables.GetResourceLocations(new object[] {"prefabs_evenBASE", "prefabs_oddBASE"}, typeof(GameObject), Addressables.MergeMode.Union, out results); Assert.IsTrue(ret); Assert.NotNull(results); Assert.GreaterOrEqual(results.Count, 1); Assert.AreEqual(oddCount + evenCount, results.Count); } [UnityTest] public IEnumerator GetResourceLocationsMergeModeUnionSucceedsWithInvalidKeys() { yield return Init(); IList results; var ret = m_Addressables.GetResourceLocations(new object[] {"prefabs_evenBASE"}, typeof(GameObject), Addressables.MergeMode.Intersection, out results); Assert.IsTrue(ret); Assert.NotNull(results); Assert.GreaterOrEqual(results.Count, 1); var evenCount = results.Count; ret = m_Addressables.GetResourceLocations(new object[] {"prefabs_oddBASE"}, typeof(GameObject), Addressables.MergeMode.Intersection, out results); Assert.IsTrue(ret); Assert.NotNull(results); Assert.GreaterOrEqual(results.Count, 1); var oddCount = results.Count; ret = m_Addressables.GetResourceLocations(new object[] {"prefabs_evenBASE", "prefabs_oddBASE", "INVALIDKEY"}, typeof(GameObject), Addressables.MergeMode.Union, out results); Assert.IsTrue(ret); Assert.NotNull(results); Assert.GreaterOrEqual(results.Count, 1); Assert.AreEqual(oddCount + evenCount, results.Count); } [UnityTest] public IEnumerator GetResourceLocationsMergeModeIntersectionFailsIfNoResultsDueToIntersection() { yield return Init(); IList results; var ret = m_Addressables.GetResourceLocations(new object[] {"prefabs_evenBASE"}, typeof(GameObject), Addressables.MergeMode.Intersection, out results); Assert.IsTrue(ret); Assert.NotNull(results); Assert.GreaterOrEqual(results.Count, 1); ret = m_Addressables.GetResourceLocations(new object[] {"prefabs_oddBASE"}, typeof(GameObject), Addressables.MergeMode.Intersection, out results); Assert.IsTrue(ret); Assert.NotNull(results); Assert.GreaterOrEqual(results.Count, 1); ret = m_Addressables.GetResourceLocations(new object[] {"prefabs_evenBASE", "prefabs_oddBASE"}, typeof(GameObject), Addressables.MergeMode.Intersection, out results); Assert.IsFalse(ret); Assert.IsNull(results); } [UnityTest] public IEnumerator GetResourceLocationsMergeModeIntersectionFailsIfNoResultsDueToInvalidKey() { yield return Init(); IList results; var ret = m_Addressables.GetResourceLocations(new object[] {"prefabs_evenBASE"}, typeof(GameObject), Addressables.MergeMode.Intersection, out results); Assert.IsTrue(ret); Assert.NotNull(results); Assert.GreaterOrEqual(results.Count, 1); ret = m_Addressables.GetResourceLocations(new object[] {"prefabs_oddBASE"}, typeof(GameObject), Addressables.MergeMode.Intersection, out results); Assert.IsTrue(ret); Assert.NotNull(results); Assert.GreaterOrEqual(results.Count, 1); ret = m_Addressables.GetResourceLocations(new object[] {"prefabs_evenBASE", "prefabs_oddBASE", "INVALIDKEY"}, typeof(GameObject), Addressables.MergeMode.Intersection, out results); Assert.IsFalse(ret); Assert.IsNull(results); ret = m_Addressables.GetResourceLocations(new object[] {"prefabs_evenBASE", "INVALIDKEY"}, typeof(GameObject), Addressables.MergeMode.Intersection, out results); Assert.IsFalse(ret); Assert.IsNull(results); ret = m_Addressables.GetResourceLocations(new object[] {"INVALIDKEY"}, typeof(GameObject), Addressables.MergeMode.Intersection, out results); Assert.IsFalse(ret); Assert.IsNull(results); } [UnityTest] public IEnumerator WhenLoadWithInvalidKey_ReturnedOpIsFailed() { yield return Init(); List keys = new List() {"INVALID1", "INVALID2"}; AsyncOperationHandle> gop = new AsyncOperationHandle>(); using (new IgnoreFailingLogMessage()) { gop = m_Addressables.LoadAssetsAsync(keys, null, Addressables.MergeMode.Intersection, true); } while (!gop.IsDone) yield return null; Assert.IsTrue(gop.IsDone); Assert.AreEqual(AsyncOperationStatus.Failed, gop.Status); m_Addressables.Release(gop); } [UnityTest] public IEnumerator CanLoadAssetsWithMultipleKeysMerged() { yield return Init(); List keys = new List() {AddressablesTestUtility.GetPrefabLabel("BASE"), AddressablesTestUtility.GetPrefabUniqueLabel("BASE", 0)}; AsyncOperationHandle> gop = m_Addressables.LoadAssetsAsync(keys, null, Addressables.MergeMode.Intersection, true); while (!gop.IsDone) yield return null; Assert.IsTrue(gop.IsDone); Assert.AreEqual(AsyncOperationStatus.Succeeded, gop.Status); Assert.NotNull(gop.Result); Assert.AreEqual(1, gop.Result.Count); Assert.AreEqual(AsyncOperationStatus.Succeeded, gop.Status); m_Addressables.Release(gop); } [UnityTest] public IEnumerator Release_WhenObjectIsUnknown_LogsErrorAndDoesNotDestroy() { yield return Init(); GameObject go = Object.Instantiate(GameObject.CreatePrimitive(PrimitiveType.Cube)); go.name = "TestCube"; m_Addressables.Release(go); LogAssert.Expect(LogType.Error, new Regex("Addressables.Release was called on.*")); yield return null; GameObject foundObj = GameObject.Find("TestCube"); Assert.IsNotNull(foundObj); Object.Destroy(foundObj); } [UnityTest] public IEnumerator ReleaseInstance_WhenObjectIsUnknown_LogsErrorAndDestroys() { yield return Init(); GameObject go = Object.Instantiate(GameObject.CreatePrimitive(PrimitiveType.Cube)); go.name = "TestCube"; Assert.IsFalse(m_Addressables.ReleaseInstance(go)); } [UnityTest] public IEnumerator LoadAsset_WhenEntryExists_ReturnsAsset() { yield return Init(); string label = AddressablesTestUtility.GetPrefabUniqueLabel("BASE", 0); AsyncOperationHandle op = m_Addressables.LoadAssetAsync(label); yield return op; Assert.AreEqual(AsyncOperationStatus.Succeeded, op.Status); Assert.IsTrue(op.Result != null); op.Release(); } [UnityTest] public IEnumerator LoadAsset_SuccessfulWhenLoadAssetMode_LoadAllAssets() { yield return Init(); if (string.IsNullOrEmpty(TypeName) || TypeName == "BuildScriptFastMode" || TypeName == "BuildScriptVirtualMode") { Assert.Ignore($"Skipping test {nameof(LoadAsset_SuccessfulWhenLoadAssetMode_LoadAllAssets)} for {TypeName}, AssetBundle based test."); } string label = AddressablesTestUtility.GetPrefabUniqueLabel("BASE", 0); var locationHandle = m_Addressables.LoadResourceLocationsAsync(label); yield return locationHandle; Assert.IsTrue(locationHandle.Result != null, "Failed to get Location for " + label); Assert.AreEqual(1, locationHandle.Result.Count, "Failed to get Location for " + label); IResourceLocation loc = locationHandle.Result[0]; Addressables.Release(locationHandle); foreach (IResourceLocation dependency in loc.Dependencies) { var locOptions = dependency.Data as AssetBundleRequestOptions; Assert.IsNotNull(locOptions, "Location dependency did not contain expected AssetBundleRequestOptions data"); locOptions.AssetLoadMode = AssetLoadMode.AllPackedAssetsAndDependencies; } AsyncOperationHandle op = m_Addressables.LoadAssetAsync(loc); yield return op; Assert.AreEqual(AsyncOperationStatus.Succeeded, op.Status, "Loading of " + label + " failed."); Assert.IsTrue(op.Result != null, "Loading of " + label + " was successful, but result was null."); op.Release(); } [UnityTest] public IEnumerator LoadAssetWithWrongType_WhenEntryExists_Fails() { yield return Init(); string label = AddressablesTestUtility.GetPrefabUniqueLabel("BASE", 0); AsyncOperationHandle op = new AsyncOperationHandle(); using (new IgnoreFailingLogMessage()) { op = m_Addressables.LoadAssetAsync(label); yield return op; } Assert.AreEqual(AsyncOperationStatus.Failed, op.Status); Assert.IsNull(op.Result); op.Release(); } [UnityTest] public IEnumerator LoadAsset_WhenEntryDoesNotExist_OperationFails() { yield return Init(); AsyncOperationHandle op = new AsyncOperationHandle(); using (new IgnoreFailingLogMessage()) { op = m_Addressables.LoadAssetAsync("unknownlabel"); } yield return op; Assert.AreEqual(AsyncOperationStatus.Failed, op.Status); Assert.IsTrue(op.Result == null); op.Release(); } [UnityTest] public IEnumerator LoadAsset_CanReleaseThroughAddressablesInCallback([Values(true, false)] bool addressableRelease) { yield return Init(); var op = m_Addressables.LoadAssetAsync(m_PrefabKeysList[0]); op.Completed += x => { Assert.IsNotNull(x.Result); if (addressableRelease) m_Addressables.Release(x.Result); else op.Release(); }; yield return op; } [UnityTest] public IEnumerator LoadAsset_WhenPrefabLoadedAsMultipleTypes_ResultIsEqual() { yield return Init(); string label = AddressablesTestUtility.GetPrefabUniqueLabel("BASE", 0); AsyncOperationHandle op1 = m_Addressables.LoadAssetAsync(label); AsyncOperationHandle op2 = m_Addressables.LoadAssetAsync(label); yield return op1; yield return op2; Assert.AreEqual(op1.Result, op2.Result); Assert.AreEqual(AsyncOperationStatus.Succeeded, op1.Status); Assert.AreEqual(AsyncOperationStatus.Succeeded, op2.Status); op1.Release(); op2.Release(); } [UnityTest] public IEnumerator LoadAssets_InvokesCallbackPerAsset() { yield return Init(); string label = AddressablesTestUtility.GetPrefabLabel("BASE"); HashSet ops = new HashSet(); var gop = m_Addressables.LoadAssetsAsync(label, x => { ops.Add(x); }, true); yield return gop; Assert.AreEqual(AddressablesTestUtility.kPrefabCount, ops.Count); for (int i = 0; i < ops.Count; i++) Assert.IsTrue(ops.Contains(gop.Result[i])); gop.Release(); } [UnityTest] public IEnumerator LoadAssets_InvokesCallbackPerAssetBeforeCompletedCallback() { yield return Init(); string label = AddressablesTestUtility.GetPrefabLabel("BASE"); HashSet ops = new HashSet(); int opsCompletedOnCompleted = 0; var gop = m_Addressables.LoadAssetsAsync(label, x => { ops.Add(x); }, true); gop.Completed += handle => { opsCompletedOnCompleted = ops.Count; }; yield return gop; Assert.AreEqual(AddressablesTestUtility.kPrefabCount, ops.Count); Assert.AreEqual(AddressablesTestUtility.kPrefabCount, opsCompletedOnCompleted); for (int i = 0; i < ops.Count; i++) Assert.IsTrue(ops.Contains(gop.Result[i])); gop.Release(); } // TODO: this doesn't actually check that something was downloaded. It is more: can load dependencies. // We really need to address the downloading feature [UnityTest] public IEnumerator DownloadDependencies_CanDownloadDependencies() { yield return Init(); string label = AddressablesTestUtility.GetPrefabLabel("BASE"); AsyncOperationHandle op = m_Addressables.DownloadDependenciesAsync(label); yield return op; op.Release(); } [UnityTest] public IEnumerator DownloadDependencies_AutoReleaseHandle_ReleasesOnCompletion() { yield return Init(); string label = AddressablesTestUtility.GetPrefabLabel("BASE"); AsyncOperationHandle op = m_Addressables.DownloadDependenciesAsync(label, true); yield return op; Assert.IsFalse(op.IsValid()); } [UnityTest] public IEnumerator DownloadDependenciesWithAddress_AutoReleaseHandle_ReleasesOnCompletion() { yield return Init(); AsyncOperationHandle op = m_Addressables.DownloadDependenciesAsync(m_PrefabKeysList[0], true); yield return op; Assert.IsFalse(op.IsValid()); } [UnityTest] public IEnumerator DownloadDependencies_DoesNotRetainLoadedBundles_WithAutoRelease() { yield return Init(); int bundleCountBefore = AssetBundle.GetAllLoadedAssetBundles().Count(); string label = AddressablesTestUtility.GetPrefabLabel("BASE"); AsyncOperationHandle op = m_Addressables.DownloadDependenciesAsync(label, true); yield return op; AssetBundleProvider.WaitForAllUnloadingBundlesToComplete(); #if UNITY_2022_1_OR_NEWER Assert.AreEqual(bundleCountBefore, AssetBundleProvider.AssetBundleCount); #else Assert.AreEqual(bundleCountBefore, AssetBundle.GetAllLoadedAssetBundles().Count()); #endif } [Test] public void AssetBundleProvider_CanSet_UnloadingBundles() { #if UNITY_2022_1_OR_NEWER var unloadingBundles = AssetBundleProvider.UnloadingBundles; string key = "op1"; var newBundles = new Dictionary() {{ key, new AssetBundleUnloadOperation() }}; AssetBundleProvider.UnloadingBundles = newBundles; Assert.IsTrue(AssetBundleProvider.UnloadingBundles.ContainsKey(key)); AssetBundleProvider.UnloadingBundles = unloadingBundles; #else Assert.Ignore($"Skipping test {nameof(AssetBundleProvider_CanSet_UnloadingBundles)}. Requires 2022.1+"); #endif } [UnityTest] [Ignore("Test is unstable until task refactor is finished.")] public IEnumerator DownloadDependencies_ReturnsValidTask() { yield return Init(); string label = AddressablesTestUtility.GetPrefabLabel("BASE"); AsyncOperationHandle op = m_Addressables.DownloadDependenciesAsync(label); Assert.IsNotNull(op.Task); yield return op; Assert.IsNotNull(op.Task); op.Release(); } [UnityTest] public IEnumerator StressInstantiation() { yield return Init(); // TODO: move this safety check to test fixture base var objs = SceneManager.GetActiveScene().GetRootGameObjects(); foreach (var r in objs) Assert.False(r.name.EndsWith("(Clone)"), "All instances from previous test were not cleaned up"); var ops = new List>(); for (int i = 0; i < 50; i++) { var key = m_PrefabKeysList[i % m_PrefabKeysList.Count]; ops.Add(m_Addressables.InstantiateAsync(key)); } foreach (AsyncOperationHandle op in ops) yield return op; foreach (AsyncOperationHandle op in ops) m_Addressables.ReleaseInstance(op.Result); yield return null; objs = SceneManager.GetActiveScene().GetRootGameObjects(); foreach (var r in objs) Assert.False(r.name.EndsWith("(Clone)"), "All instances from this test were not cleaned up"); } [UnityTest] public IEnumerator AssetReference_HandleIsInvalidated_WhenReleasingLoadOperation() { yield return Init(); AsyncOperationHandle handle = m_Addressables.InstantiateAsync(AssetReferenceObjectKey); yield return handle; Assert.IsNotNull(handle.Result as GameObject); AssetReferenceTestBehavior behavior = (handle.Result as GameObject).GetComponent(); using (new IgnoreFailingLogMessage()) yield return behavior.Reference.LoadAssetAsync(); AsyncOperationHandle referenceHandle = behavior.Reference.OperationHandle; Assert.IsTrue(behavior.Reference.IsValid()); m_Addressables.Release(referenceHandle); yield return referenceHandle; Assert.IsFalse(behavior.Reference.IsValid()); handle.Release(); } [UnityTest] public IEnumerator CanUnloadAssetReference_WithAddressables() { yield return Init(); AsyncOperationHandle handle = m_Addressables.InstantiateAsync(AssetReferenceObjectKey); yield return handle; Assert.IsNotNull(handle.Result as GameObject); AssetReferenceTestBehavior behavior = (handle.Result as GameObject).GetComponent(); AsyncOperationHandle assetRefHandle = m_Addressables.InstantiateAsync(behavior.Reference); yield return assetRefHandle; Assert.IsNotNull(assetRefHandle.Result); string name = assetRefHandle.Result.name; Assert.IsNotNull(GameObject.Find(name)); m_Addressables.ReleaseInstance(assetRefHandle.Result); yield return null; Assert.IsNull(GameObject.Find(name)); handle.Release(); } [UnityTest] public IEnumerator CanloadAssetReferenceSubObject() { yield return Init(); var handle = m_Addressables.InstantiateAsync(AssetReferenceObjectKey); yield return handle; Assert.IsNotNull(handle.Result); AssetReferenceTestBehavior behavior = handle.Result.GetComponent(); AsyncOperationHandle assetRefHandle = m_Addressables.LoadAssetAsync(behavior.ReferenceWithSubObject); yield return assetRefHandle; Assert.IsNotNull(assetRefHandle.Result); m_Addressables.Release(assetRefHandle); handle.Release(); } [UnityTest] public IEnumerator AddressablesIntegration_LoadAssetAsync_CanLoadAssetReferenceObjectList() { yield return Init(); var assetRefHandle = m_Addressables.LoadAssetAsync("assetWithSubObjects"); yield return assetRefHandle; Assert.IsNotNull(assetRefHandle.Result); Assert.AreEqual(assetRefHandle.Result.Length, 2); Assert.AreEqual(assetRefHandle.Result[0].name, "assetWithSubObjects"); Assert.AreEqual(assetRefHandle.Result[1].name, "sub-shown"); m_Addressables.Release(assetRefHandle); } [UnityTest] public IEnumerator LoadAssets_WithHiddenSubObjects_OnlyReturnsNonHidden_WithMainAssetFirst() { yield return Init(); var handle = m_Addressables.LoadAssetAsync>("assetWithSubObjects"); yield return handle; Assert.IsNotNull(handle.Result); Assert.AreEqual(handle.Result.Count, 2); Assert.AreEqual(handle.Result[0].name, "assetWithSubObjects"); Assert.AreEqual(handle.Result[1].name, "sub-shown"); handle.Release(); } [UnityTest] public IEnumerator RuntimeKeyIsValid_ReturnsTrueForSubObjects() { yield return Init(); var handle = m_Addressables.InstantiateAsync(AssetReferenceObjectKey); yield return handle; Assert.IsNotNull(handle.Result); AssetReferenceTestBehavior behavior = handle.Result.GetComponent(); Assert.IsTrue(behavior.ReferenceWithSubObject.RuntimeKeyIsValid()); handle.Release(); } [UnityTest] public IEnumerator RuntimeKeyIsValid_ReturnsTrueForValidKeys() { yield return Init(); AsyncOperationHandle handle = m_Addressables.InstantiateAsync(AssetReferenceObjectKey); yield return handle; Assert.IsNotNull(handle.Result as GameObject); AssetReferenceTestBehavior behavior = (handle.Result as GameObject).GetComponent(); Assert.IsTrue((behavior.Reference as IKeyEvaluator).RuntimeKeyIsValid()); Assert.IsTrue((behavior.LabelReference as IKeyEvaluator).RuntimeKeyIsValid()); handle.Release(); } [UnityTest] public IEnumerator PercentComplete_CalculationIsCorrect_WhenInAGroupOperation() { yield return Init(); GroupOperation groupOp = new GroupOperation(); float handle1PercentComplete = 0.22f; float handle2PercentComplete = 0.78f; float handle3PercentComplete = 1.0f; float handle4PercentComplete = 0.35f; List handles = new List() { new ManualPercentCompleteOperation(handle1PercentComplete).Handle, new ManualPercentCompleteOperation(handle2PercentComplete).Handle, new ManualPercentCompleteOperation(handle3PercentComplete).Handle, new ManualPercentCompleteOperation(handle4PercentComplete).Handle }; groupOp.Init(handles); Assert.AreEqual((handle1PercentComplete + handle2PercentComplete + handle3PercentComplete + handle4PercentComplete) / 4, groupOp.PercentComplete); } [UnityTest] public IEnumerator ResourceManagerDiagnostics_SumDependencyNameHashCodes_ProperlyCalculatesForOneLayerOfDependencies() { yield return Init(); var rmd = new ResourceManagerDiagnostics(m_Addressables.ResourceManager); GroupOperation groupOp = new GroupOperation(); float handle1PercentComplete = 0.22f; float handle2PercentComplete = 0.78f; float handle3PercentComplete = 1.0f; float handle4PercentComplete = 0.35f; List handles = new List() { new ManualPercentCompleteOperation(handle1PercentComplete).Handle, new ManualPercentCompleteOperation(handle2PercentComplete).Handle, new ManualPercentCompleteOperation(handle3PercentComplete).Handle, new ManualPercentCompleteOperation(handle4PercentComplete).Handle }; groupOp.Init(handles); var handle = groupOp.Handle; var dependencyNameHashSum = handle.DebugName.GetHashCode() + rmd.SumDependencyNameHashCodes(handle); var manualDepNameHashSum = handle.DebugName.GetHashCode(); foreach (var h in handles) manualDepNameHashSum += h.DebugName.GetHashCode(); Assert.AreEqual(manualDepNameHashSum, dependencyNameHashSum, "Calculation of hashcode was not completed as expected."); } [UnityTest] public IEnumerator ResourceManagerDiagnostics_SumDependencyNameHashCodes_ProperlyCalculatesForMultipleLayersOfDependencies() { yield return Init(); var rmd = new ResourceManagerDiagnostics(m_Addressables.ResourceManager); GroupOperation groupOp = new GroupOperation(); GroupOperation embeddedOp = new GroupOperation(); float handle1PercentComplete = 0.22f; float handle2PercentComplete = 0.78f; float handle3PercentComplete = 1.0f; float handle4PercentComplete = 0.35f; List embeddedHandles = new List() { new ManualPercentCompleteOperation(handle1PercentComplete).Handle, new ManualPercentCompleteOperation(handle2PercentComplete).Handle, new ManualPercentCompleteOperation(handle3PercentComplete).Handle, new ManualPercentCompleteOperation(handle4PercentComplete).Handle }; embeddedOp.Init(embeddedHandles); List handles = new List() { embeddedOp.Handle, new ManualPercentCompleteOperation(handle1PercentComplete).Handle, new ManualPercentCompleteOperation(handle2PercentComplete).Handle, new ManualPercentCompleteOperation(handle3PercentComplete).Handle, new ManualPercentCompleteOperation(handle4PercentComplete).Handle }; groupOp.Init(handles); var dependencyNameHashSum = groupOp.Handle.DebugName.GetHashCode() + rmd.SumDependencyNameHashCodes(groupOp.Handle); int manualDepNameHashSum; unchecked { manualDepNameHashSum = groupOp.Handle.DebugName.GetHashCode(); foreach (var h in handles) manualDepNameHashSum += h.DebugName.GetHashCode(); foreach (var h in embeddedHandles) manualDepNameHashSum += h.DebugName.GetHashCode(); } Assert.AreEqual(dependencyNameHashSum, manualDepNameHashSum, "Calculation of hashcode was not completed as expected."); } [UnityTest] public IEnumerator ResourceManagerDiagnostics_CalculateHashCode_NonChangingNameCase() { yield return Init(); var rmd = new ResourceManagerDiagnostics(m_Addressables.ResourceManager); GroupOperation groupOp = new GroupOperation(); float handle1PercentComplete = 0.22f; float handle2PercentComplete = 0.78f; float handle3PercentComplete = 1.0f; float handle4PercentComplete = 0.35f; List handles = new List() { new ManualPercentCompleteOperation(handle1PercentComplete).Handle, new ManualPercentCompleteOperation(handle2PercentComplete).Handle, new ManualPercentCompleteOperation(handle3PercentComplete).Handle, new ManualPercentCompleteOperation(handle4PercentComplete).Handle }; groupOp.Init(handles); var handle = groupOp.Handle; var dependencyNameHashSum = rmd.CalculateHashCode(handle); var manualDepNameHashSum = handle.DebugName.GetHashCode(); foreach (var h in handles) manualDepNameHashSum += h.DebugName.GetHashCode(); Assert.AreEqual(manualDepNameHashSum, dependencyNameHashSum, "Calculation of hashcode was not completed as expected."); } [UnityTest] public IEnumerator ResourceManagerDiagnostics_CalculateCompletedOperationHashcode_DoesNotErrorOnNullResult() { yield return Init(); var rmd = new ResourceManagerDiagnostics(m_Addressables.ResourceManager); var completedOp = m_Addressables.ResourceManager.CreateCompletedOperation(null, "x"); int hashcode = rmd.CalculateCompletedOperationHashcode(completedOp); Assert.NotNull(hashcode, "CalculateCompletedOperationHashcode should not error when a completedOperation with a null result is passed in."); } [UnityTest] public IEnumerator ResourceManagerDiagnostics_CalculateCompletedOperationHashcode_DoesNotErrorOnEmptyResultList() { yield return Init(); var rmd = new ResourceManagerDiagnostics(m_Addressables.ResourceManager); var completedOp = m_Addressables.ResourceManager.CreateCompletedOperation>(new List(), null); int hashcode = rmd.CalculateCompletedOperationHashcode(completedOp); Assert.NotNull(hashcode, "CalculateCompletedOperationHashcode should not error when a completedOperation with an empty list is passed in."); } [UnityTest] public IEnumerator ResourceManagerDiagnostics_GenerateCompletedOperationDisplayName_DoesNotErrorOnEmptyResultList() { yield return Init(); var rmd = new ResourceManagerDiagnostics(m_Addressables.ResourceManager); var completedOp = m_Addressables.ResourceManager.CreateCompletedOperation>(new List(), null); string displayName = rmd.GenerateCompletedOperationDisplayName(completedOp); Assert.NotNull(displayName, "GenerateCompletedOperationDisplayName should not run into issues when an empty string is passed in."); } [UnityTest] public IEnumerator ResourceManagerDiagnostics_GenerateCompletedOperationDisplayName_DoesNotErrorOnTrivialList() { yield return Init(); var rmd = new ResourceManagerDiagnostics(m_Addressables.ResourceManager); var list = new List(); list.Add("x"); var completedOp = m_Addressables.ResourceManager.CreateCompletedOperation>(list, null); string displayName = rmd.GenerateCompletedOperationDisplayName(completedOp); Assert.NotNull(displayName, "GenerateCompletedOperationDisplayName should not run into issues when a simple string is passed in."); } [UnityTest] public IEnumerator ResourceManagerDiagnostics_GenerateCompletedOperationDisplayName_DoesNotErrorOnListWithEmptyElement() { yield return Init(); var rmd = new ResourceManagerDiagnostics(m_Addressables.ResourceManager); var list = new List(); list.Add(""); var completedOp = m_Addressables.ResourceManager.CreateCompletedOperation>(list, null); string displayName = rmd.GenerateCompletedOperationDisplayName(completedOp); Assert.NotNull(displayName, "GenerateCompletedOperationDisplayName should not run into issues when an empty string is passed in."); } [UnityTest] public IEnumerator ResourceManagerDiagnostics_GenerateCompletedOperationDisplayName_DoesNotErrorOnListWithManyEmptyElements() { yield return Init(); var rmd = new ResourceManagerDiagnostics(m_Addressables.ResourceManager); var list = new List(); for (int i = 0; i < 20; i++) list.Add(""); var completedOp = m_Addressables.ResourceManager.CreateCompletedOperation>(list, null); string displayName = rmd.GenerateCompletedOperationDisplayName(completedOp); Assert.NotNull(displayName, "GenerateCompletedOperationDisplayName should not run into issues when many empty strings are passed in."); } [UnityTest] public IEnumerator ResourceManagerDiagnostics_CalculateCompletedOperationDisplayName_DoesNotErrorOnNullResult() { yield return Init(); var rmd = new ResourceManagerDiagnostics(m_Addressables.ResourceManager); var completedOp = m_Addressables.ResourceManager.CreateCompletedOperation(null, "x"); string displayName = rmd.GenerateCompletedOperationDisplayName(completedOp); Assert.NotNull(displayName, "GenerateCompletedOperationDisplayName should not error when a completedOperation with a null result is passed in."); } [UnityTest] public IEnumerator ResourceManagerDiagnostics_GenerateCompletedOperationDisplayName_DoesNotErrorOnReallyLongList() { yield return Init(); var rmd = new ResourceManagerDiagnostics(m_Addressables.ResourceManager); var list = new List(); for (int i = 0; i < 20; i++) list.Add("this is a really long string used for illustrative purposes"); var completedOp = m_Addressables.ResourceManager.CreateCompletedOperation>(list, null); string displayName = rmd.GenerateCompletedOperationDisplayName(completedOp); Assert.NotNull(displayName, "GenerateCompletedOperationDisplayName should not run into issues when a bunch of long strings are passed in."); } private class DebugNameTestOperation : AsyncOperationBase { string m_DebugName; List m_Dependencies; protected override void Execute() { } internal DebugNameTestOperation(string debugName) { m_DebugName = debugName; m_Dependencies = new List(); } internal DebugNameTestOperation(string debugName, List deps) { m_DebugName = debugName; m_Dependencies = deps; } /// public override void GetDependencies(List dependencies) { foreach (var handle in m_Dependencies) dependencies.Add(handle); } protected override string DebugName { get { return m_DebugName; } } } [UnityTest] public IEnumerator ResourceManagerDiagnostics_CalculateHashCode_NameChangingCase() { yield return Init(); var rmd = new ResourceManagerDiagnostics(m_Addressables.ResourceManager); AsyncOperationHandle changingHandle = new ManualPercentCompleteOperation(0.22f).Handle; Assert.AreEqual(changingHandle.GetHashCode(), rmd.CalculateHashCode(changingHandle), "Default hashcode should have been used since ManualPercentCompleteOperation includes its status in its DebugName"); } [UnityTest] public IEnumerator ResourceManagerDiagnostics_CalculateHashCode_SameNameGivesSameHashcode() { yield return Init(); var rmd = new ResourceManagerDiagnostics(m_Addressables.ResourceManager); DebugNameTestOperation op1 = new DebugNameTestOperation("Same name"); AsyncOperationHandle handle1 = new AsyncOperationHandle(op1); DebugNameTestOperation op2 = new DebugNameTestOperation("Same name"); AsyncOperationHandle handle2 = new AsyncOperationHandle(op2); Assert.AreEqual(rmd.CalculateHashCode(handle1), rmd.CalculateHashCode(handle2), "Two separate handles with the same DebugName should have the same hashcode. "); } [UnityTest] public IEnumerator ResourceManagerDiagnostics_CalculateHashCode_SimilarNameGivesDifHashcode() { yield return Init(); var rmd = new ResourceManagerDiagnostics(m_Addressables.ResourceManager); DebugNameTestOperation op1 = new DebugNameTestOperation("Same name"); AsyncOperationHandle handle1 = new AsyncOperationHandle(op1); DebugNameTestOperation op2 = new DebugNameTestOperation("SaMe name"); AsyncOperationHandle handle2 = new AsyncOperationHandle(op2); Assert.AreNotEqual(rmd.CalculateHashCode(handle1), rmd.CalculateHashCode(handle2), "Two similar, but different names should have different hashcodes. "); } [UnityTest] public IEnumerator ResourceManagerDiagnostics_CalculateHashCode_SameNameDifDepsGivesDifHashcode() { yield return Init(); var rmd = new ResourceManagerDiagnostics(m_Addressables.ResourceManager); var dependency1 = new DebugNameTestOperation("Dependency 1"); var dependency2 = new DebugNameTestOperation("Dependency 2"); var depList1 = new List {new AsyncOperationHandle(dependency1)}; var depList2 = new List {new AsyncOperationHandle(dependency2)}; DebugNameTestOperation op1 = new DebugNameTestOperation("Same name", depList1); AsyncOperationHandle handle1 = new AsyncOperationHandle(op1); DebugNameTestOperation op2 = new DebugNameTestOperation("Same name", depList2); AsyncOperationHandle handle2 = new AsyncOperationHandle(op2); Assert.AreNotEqual(rmd.CalculateHashCode(handle1), rmd.CalculateHashCode(handle2), "Two separate handles with the same DebugName, but different dependency names should not have the same hashcode."); } [UnityTest] public IEnumerator ResourceManagerDiagnostics_CalculateHashCode_SameNameSameDepNamesGivesSameHashcode() { yield return Init(); var rmd = new ResourceManagerDiagnostics(m_Addressables.ResourceManager); var dependency1 = new DebugNameTestOperation("Dependency 1"); var dependency2 = new DebugNameTestOperation("Dependency 2"); var depList1 = new List {new AsyncOperationHandle(dependency1), new AsyncOperationHandle(dependency2)}; var depList2 = new List {new AsyncOperationHandle(dependency2), new AsyncOperationHandle(dependency1)}; DebugNameTestOperation op1 = new DebugNameTestOperation("Same name", depList1); AsyncOperationHandle handle1 = new AsyncOperationHandle(op1); DebugNameTestOperation op2 = new DebugNameTestOperation("Same name", depList2); AsyncOperationHandle handle2 = new AsyncOperationHandle(op2); Assert.AreEqual(rmd.CalculateHashCode(handle1), rmd.CalculateHashCode(handle2), "Two handles with the same DebugName and same dependency names should have the same hashcode."); } [UnityTest] public IEnumerator PercentComplete_CalculationIsCorrect_WhenInAChainOperation() { yield return Init(); float handle1PercentComplete = 0.6f; float handle2PercentComplete = 0.98f; AsyncOperationHandle slowHandle1 = new ManualPercentCompleteOperation(handle1PercentComplete, new DownloadStatus() {DownloadedBytes = 1, IsDone = false, TotalBytes = 2}) .Handle; AsyncOperationHandle slowHandle2 = new ManualPercentCompleteOperation(handle2PercentComplete, new DownloadStatus() {DownloadedBytes = 1, IsDone = false, TotalBytes = 2}) .Handle; slowHandle1.m_InternalOp.m_RM = m_Addressables.ResourceManager; slowHandle2.m_InternalOp.m_RM = m_Addressables.ResourceManager; var chainOperation = m_Addressables.ResourceManager.CreateChainOperation(slowHandle1, (op) => { return slowHandle2; }); chainOperation.m_InternalOp.Start(m_Addressables.ResourceManager, default, null); Assert.AreEqual((handle1PercentComplete + handle2PercentComplete) / 2, chainOperation.PercentComplete); } [UnityTest] public IEnumerator RuntimeKeyIsValid_ReturnsFalseForInValidKeys() { yield return Init(); AsyncOperationHandle handle = m_Addressables.InstantiateAsync(AssetReferenceObjectKey); yield return handle; Assert.IsNotNull(handle.Result as GameObject); AssetReferenceTestBehavior behavior = (handle.Result as GameObject).GetComponent(); Assert.IsFalse((behavior.InValidAssetReference as IKeyEvaluator).RuntimeKeyIsValid()); Assert.IsFalse((behavior.InvalidLabelReference as IKeyEvaluator).RuntimeKeyIsValid()); handle.Release(); } #if !ENABLE_BINARY_CATALOG static ResourceLocationMap GetRLM(AddressablesImpl addr) { foreach (var rl in addr.m_ResourceLocators) { if (rl.Locator is ResourceLocationMap) return rl.Locator as ResourceLocationMap; } return null; } #endif private void SetupBundleForCacheDependencyClearTests(string bundleName, string depName, string hash, string key, out ResourceLocationBase location) { CreateFakeCachedBundle(bundleName, hash); location = new ResourceLocationBase(key, bundleName, typeof(AssetBundleProvider).FullName, typeof(IAssetBundleResource), new ResourceLocationBase(depName, bundleName, typeof(AssetBundleProvider).FullName, typeof(IAssetBundleResource))); (location.Dependencies[0] as ResourceLocationBase).Data = location.Data = new AssetBundleRequestOptions() { BundleName = bundleName }; } class TestCatalogProviderCustomAssetBundleResource : BundledAssetProvider { public TestAssetBundleResourceInternalOp TestInternalOp; internal class TestAssetBundleResourceInternalOp : AsyncOperationBase { TestAssetBundleResource m_Resource; public TestAssetBundleResourceInternalOp(TestAssetBundleResource resource) { m_Resource = resource; } protected override void Execute() { Complete(m_Resource, m_Resource != null, m_Resource != null ? "" : "TestAssetBundleResource was null"); } } /// public override string ProviderId { get { if (string.IsNullOrEmpty(m_ProviderId)) m_ProviderId = typeof(TestCatalogProviderCustomAssetBundleResource).FullName; return m_ProviderId; } } public override void Provide(ProvideHandle provideHandle) { ProviderOperation op = new ProviderOperation(); GroupOperation group = new GroupOperation(); TestInternalOp = new TestAssetBundleResourceInternalOp(new TestAssetBundleResource()); provideHandle.ResourceManager.Acquire(TestInternalOp.Handle); provideHandle.ResourceManager.Acquire(TestInternalOp.Handle); group.Init(new List() {new AsyncOperationHandle(TestInternalOp)}); op.Init(provideHandle.ResourceManager, null, provideHandle.Location, group.Handle); ProvideHandle handle = new ProvideHandle(provideHandle.ResourceManager, op); TestInternalOp.InvokeExecute(); base.Provide(handle); } internal class TestAssetBundleResource : IAssetBundleResource { public bool WasUsed = false; public AssetBundle GetAssetBundle() { WasUsed = true; return null; } } } #if !ENABLE_BINARY_CATALOG private void SetupBundleForProviderTests(string bundleName, string depName, string key, out ResourceLocationBase location, out TestCatalogProviderCustomAssetBundleResource testProvider) { testProvider = new TestCatalogProviderCustomAssetBundleResource(); m_Addressables.ResourceManager.ResourceProviders.Add(testProvider); location = new ResourceLocationBase(key, bundleName, typeof(TestCatalogProviderCustomAssetBundleResource).FullName, typeof(TestCatalogProviderCustomAssetBundleResource.TestAssetBundleResource), new ResourceLocationBase(depName, bundleName, typeof(TestCatalogProviderCustomAssetBundleResource).FullName, typeof(TestCatalogProviderCustomAssetBundleResource.TestAssetBundleResource))); (location.Dependencies[0] as ResourceLocationBase).Data = location.Data = new AssetBundleRequestOptions() { BundleName = bundleName }; GetRLM(m_Addressables).Add(key, new List() {location}); } #endif #if !ENABLE_BINARY_CATALOG [UnityTest] [Platform(Exclude = "PS5")] public IEnumerator ClearDependencyCache_ClearsAllCachedFilesForKey() { yield return Init(); var rlm = GetRLM(m_Addressables); if (rlm == null) yield break; #if ENABLE_CACHING string hash = "123456789"; string bundleName = $"test_{hash}"; string key = "lockey_key"; List versions = new List(); ResourceLocationBase location = null; SetupBundleForCacheDependencyClearTests(bundleName, "bundle", hash, key, out location); Caching.GetCachedVersions(bundleName, versions); Assert.AreEqual(1, versions.Count); versions.Clear(); rlm.Add(location.PrimaryKey, new List() {location}); yield return m_Addressables.ClearDependencyCacheAsync((object)key, true); Caching.GetCachedVersions(bundleName, versions); Assert.AreEqual(0, versions.Count); #else Assert.Ignore("Caching not enabled."); yield return null; #endif } [UnityTest] public IEnumerator ClearDependencyCache_ClearsAllCachedFilesForKeyWithDependencies() { yield return Init(); var rlm = GetRLM(m_Addressables); if (rlm == null) yield break; #if ENABLE_CACHING string hash = "123456789"; string bundleName = $"test_{hash}"; string depHash = "97564231"; string depBundleName = $"test_{depHash}"; ResourceLocationBase depLocation = null; string key = "lockey_deps_key"; SetupBundleForCacheDependencyClearTests(depBundleName, "test", depHash, "depKey", out depLocation); CreateFakeCachedBundle(bundleName, hash); ResourceLocationBase location = new ResourceLocationBase(key, bundleName, typeof(AssetBundleProvider).FullName, typeof(IAssetBundleResource), new ResourceLocationBase("bundle", bundleName, typeof(AssetBundleProvider).FullName, typeof(IAssetBundleResource)), depLocation); (location.Dependencies[0] as ResourceLocationBase).Data = location.Data = new AssetBundleRequestOptions() { BundleName = bundleName }; rlm.Add(location.PrimaryKey, new List() {location}); yield return m_Addressables.ClearDependencyCacheAsync((object)key, true); List versions = new List(); Caching.GetCachedVersions(bundleName, versions); Assert.AreEqual(0, versions.Count); versions.Clear(); Caching.GetCachedVersions(depBundleName, versions); Assert.AreEqual(0, versions.Count); #else Assert.Ignore("Caching not enabled."); yield return null; #endif } [UnityTest] public IEnumerator ClearDependencyCache_ClearsAllCachedFilesForLocationWithDependencies() { yield return Init(); var rlm = GetRLM(m_Addressables); if (rlm == null) yield break; #if ENABLE_CACHING string hash = "123456789"; string bundleName = $"test_{hash}"; string key = "lockey_deps_location"; string depHash = "97564231"; string depBundleName = $"test_{depHash}"; ResourceLocationBase depLocation = null; SetupBundleForCacheDependencyClearTests(depBundleName, "test", depHash, "depKey", out depLocation); CreateFakeCachedBundle(bundleName, hash); ResourceLocationBase location = new ResourceLocationBase(key, bundleName, typeof(AssetBundleProvider).FullName, typeof(IAssetBundleResource), new ResourceLocationBase("bundle", bundleName, typeof(AssetBundleProvider).FullName, typeof(IAssetBundleResource)), depLocation); (location.Dependencies[0] as ResourceLocationBase).Data = location.Data = new AssetBundleRequestOptions() { BundleName = bundleName }; rlm.Add(location.PrimaryKey, new List() {location}); yield return m_Addressables.ClearDependencyCacheAsync(location, true); List versions = new List(); Caching.GetCachedVersions(bundleName, versions); Assert.AreEqual(0, versions.Count); versions.Clear(); Caching.GetCachedVersions(depBundleName, versions); Assert.AreEqual(0, versions.Count); #else Assert.Ignore("Caching not enabled."); yield return null; #endif } [UnityTest] [Platform(Exclude = "PS5")] public IEnumerator ClearDependencyCache_ClearsAllCachedFilesForLocationList() { yield return Init(); var rlm = GetRLM(m_Addressables); if (rlm == null) yield break; #if ENABLE_CACHING string hash = "123456789"; string bundleName = $"test_{hash}"; string key = "lockey_location_list"; ResourceLocationBase location = null; SetupBundleForCacheDependencyClearTests(bundleName, "bundle", hash, key, out location); List versions = new List(); Caching.GetCachedVersions(bundleName, versions); Assert.AreEqual(1, versions.Count); versions.Clear(); rlm.Add(location.PrimaryKey, new List() {location}); yield return m_Addressables.ClearDependencyCacheAsync(new List() {location}, true); Caching.GetCachedVersions(bundleName, versions); Assert.AreEqual(0, versions.Count); #else Assert.Ignore("Caching not enabled."); yield return null; #endif } [UnityTest] [Platform(Exclude = "PS5")] public IEnumerator ClearDependencyCache_ClearsAllCachedFilesForKeyList() { yield return Init(); var rlm = GetRLM(m_Addressables); if (rlm == null) yield break; #if ENABLE_CACHING string hash = "123456789"; string bundleName = $"test_{hash}"; string key = "lockey_key_list"; ResourceLocationBase location = null; SetupBundleForCacheDependencyClearTests(bundleName, "bundle", hash, key, out location); List versions = new List(); Caching.GetCachedVersions(bundleName, versions); Assert.AreEqual(1, versions.Count); versions.Clear(); rlm.Add(location.PrimaryKey, new List() {location}); yield return m_Addressables.ClearDependencyCacheAsync(new List() {(object)key}, true); Caching.GetCachedVersions(bundleName, versions); Assert.AreEqual(0, versions.Count); #else Assert.Ignore("Caching not enabled."); yield return null; #endif } [UnityTest] public IEnumerator ClearDependencyCache_ClearsAllCachedFilesForLocationListWithDependencies() { yield return Init(); var rlm = GetRLM(m_Addressables); if (rlm == null) yield break; #if ENABLE_CACHING string hash = "123456789"; string bundleName = $"test_{hash}"; string key = "lockey_deps_location_list"; string depHash = "97564231"; string depBundleName = $"test_{depHash}"; ResourceLocationBase depLocation = null; SetupBundleForCacheDependencyClearTests(depBundleName, "test", depHash, "depKey", out depLocation); CreateFakeCachedBundle(bundleName, hash); ResourceLocationBase location = new ResourceLocationBase(key, bundleName, typeof(AssetBundleProvider).FullName, typeof(IAssetBundleResource), new ResourceLocationBase("bundle", bundleName, typeof(AssetBundleProvider).FullName, typeof(IAssetBundleResource)), depLocation); (location.Dependencies[0] as ResourceLocationBase).Data = location.Data = new AssetBundleRequestOptions() { BundleName = bundleName }; rlm.Add(location.PrimaryKey, new List() {location}); yield return m_Addressables.ClearDependencyCacheAsync(new List() {location}, true); List versions = new List(); Caching.GetCachedVersions(bundleName, versions); Assert.AreEqual(0, versions.Count); versions.Clear(); Caching.GetCachedVersions(depBundleName, versions); Assert.AreEqual(0, versions.Count); #else Assert.Ignore("Caching not enabled."); yield return null; #endif } [UnityTest] public IEnumerator ClearDependencyCache_ClearsAllCachedFilesForKeyListWithDependencies() { yield return Init(); var rlm = GetRLM(m_Addressables); if (rlm == null) yield break; #if ENABLE_CACHING string hash = "123456789"; string bundleName = $"test_{hash}"; string key = "lockey_deps_key_list"; string depHash = "97564231"; string depBundleName = $"test_{depHash}"; ResourceLocationBase depLocation = null; SetupBundleForCacheDependencyClearTests(depBundleName, "test", depHash, "depKey", out depLocation); CreateFakeCachedBundle(bundleName, hash); ResourceLocationBase location = new ResourceLocationBase(key, bundleName, typeof(AssetBundleProvider).FullName, typeof(IAssetBundleResource), new ResourceLocationBase("bundle", bundleName, typeof(AssetBundleProvider).FullName, typeof(IAssetBundleResource)), depLocation); (location.Dependencies[0] as ResourceLocationBase).Data = location.Data = new AssetBundleRequestOptions() { BundleName = bundleName }; rlm.Add(location.PrimaryKey, new List() {location}); yield return m_Addressables.ClearDependencyCacheAsync(new List() {key}, true); List versions = new List(); Caching.GetCachedVersions(bundleName, versions); Assert.AreEqual(0, versions.Count); #else Assert.Ignore("Caching not enabled."); yield return null; #endif } #endif [UnityTest] public IEnumerator AssetBundleRequestOptions_ComputesCorrectSize_WhenLocationDoesNotMatchBundleName_WithoutHash() { #if ENABLE_CACHING yield return Init(); //Setup string bundleName = "bundle"; string bundleLocation = "http://fake.com/default-bundle"; long size = 123; IResourceLocation location = new ResourceLocationBase("test", bundleLocation, typeof(AssetBundleProvider).FullName, typeof(GameObject)); Hash128 hash = Hash128.Compute("213412341242134"); AssetBundleRequestOptions abro = new AssetBundleRequestOptions() { BundleName = bundleName, BundleSize = size, }; //Test Assert.AreEqual(size, abro.ComputeSize(location, m_Addressables.ResourceManager)); CreateFakeCachedBundle(bundleName, hash.ToString()); // No hash, so the bundle should be downloaded Assert.AreEqual(size, abro.ComputeSize(location, m_Addressables.ResourceManager)); //Cleanup Caching.ClearAllCachedVersions(bundleName); #else Assert.Ignore("Caching not enabled."); yield return null; #endif } [UnityTest] public IEnumerator Autorelease_False_ClearDependencyCache_WithChainOperation_DoesNotThrowInvalidHandleError() { yield return Init(); //This is to make sure we use the ShouldChainRequest var dumbUpdate = new DumbUpdateOperation(); m_Addressables.m_ActiveUpdateOperation = new AsyncOperationHandle>(dumbUpdate); var clearCache = m_Addressables.ClearDependencyCacheAsync("NotARealKey", false); dumbUpdate.CallComplete(); yield return clearCache; Assert.IsTrue(clearCache.IsValid()); m_Addressables.Release(clearCache); Assert.IsFalse(clearCache.IsValid()); } [UnityTest] public IEnumerator Autorelease_True_ClearDependencyCache_WithChainOperation_DoesNotThrowInvalidHandleError() { yield return Init(); //This is to make sure we use the ShouldChainRequest var dumbUpdate = new DumbUpdateOperation(); m_Addressables.m_ActiveUpdateOperation = new AsyncOperationHandle>(dumbUpdate); var clearCache = m_Addressables.ClearDependencyCacheAsync("NotARealKey", true); dumbUpdate.CallComplete(); yield return clearCache; Assert.IsFalse(clearCache.IsValid()); } [UnityTest] public IEnumerator Autorelease_False_ClearDependencyCacheList_WithChainOperation_DoesNotThrowInvalidHandleError() { yield return Init(); //This is to make sure we use the ShouldChainRequest var dumbUpdate = new DumbUpdateOperation(); m_Addressables.m_ActiveUpdateOperation = new AsyncOperationHandle>(dumbUpdate); var clearCache = m_Addressables.ClearDependencyCacheAsync(new List {"NotARealKey"}, false); dumbUpdate.CallComplete(); yield return clearCache; Assert.IsTrue(clearCache.IsValid()); m_Addressables.Release(clearCache); Assert.IsFalse(clearCache.IsValid()); } [UnityTest] public IEnumerator Autorelease_True_ClearDependencyCacheList_WithChainOperation_DoesNotThrowInvalidHandleError() { yield return Init(); //This is to make sure we use the ShouldChainRequest var dumbUpdate = new DumbUpdateOperation(); m_Addressables.m_ActiveUpdateOperation = new AsyncOperationHandle>(dumbUpdate); var clearCache = m_Addressables.ClearDependencyCacheAsync(new List {"NotARealKey"}, true); dumbUpdate.CallComplete(); yield return clearCache; Assert.IsFalse(clearCache.IsValid()); } public IEnumerator Autorelease_False_ClearDependencyCacheObject_WithChainOperation_DoesNotThrowInvalidHandleError() { yield return Init(); //This is to make sure we use the ShouldChainRequest var dumbUpdate = new DumbUpdateOperation(); m_Addressables.m_ActiveUpdateOperation = new AsyncOperationHandle>(dumbUpdate); var clearCache = m_Addressables.ClearDependencyCacheAsync((object)"NotARealKey", false); dumbUpdate.CallComplete(); yield return clearCache; Assert.IsTrue(clearCache.IsValid()); m_Addressables.Release(clearCache); Assert.IsFalse(clearCache.IsValid()); } [UnityTest] public IEnumerator Autorelease_True_ClearDependencyCacheObject_WithChainOperation_DoesNotThrowInvalidHandleError() { yield return Init(); //This is to make sure we use the ShouldChainRequest var dumbUpdate = new DumbUpdateOperation(); m_Addressables.m_ActiveUpdateOperation = new AsyncOperationHandle>(dumbUpdate); var clearCache = m_Addressables.ClearDependencyCacheAsync((object)"NotARealKey", true); dumbUpdate.CallComplete(); yield return clearCache; Assert.IsFalse(clearCache.IsValid()); } [UnityTest] public IEnumerator Autorelease_False_ClearDependencyCacheListIResourceLocs_WithChainOperation_DoesNotThrowInvalidHandleError() { yield return Init(); //This is to make sure we use the ShouldChainRequest var dumbUpdate = new DumbUpdateOperation(); m_Addressables.m_ActiveUpdateOperation = new AsyncOperationHandle>(dumbUpdate); List locations = new List() { new ResourceLocationBase("NotARealKey", "NotARealKey", typeof(BundledAssetProvider).FullName, typeof(ResourceLocationBase)) }; var clearCache = m_Addressables.ClearDependencyCacheAsync(locations, false); dumbUpdate.CallComplete(); yield return clearCache; Assert.IsTrue(clearCache.IsValid()); m_Addressables.Release(clearCache); Assert.IsFalse(clearCache.IsValid()); } [UnityTest] public IEnumerator Autorelease_True_ClearDependencyCacheListIResourceLocs_WithChainOperation_DoesNotThrowInvalidHandleError() { yield return Init(); //This is to make sure we use the ShouldChainRequest var dumbUpdate = new DumbUpdateOperation(); m_Addressables.m_ActiveUpdateOperation = new AsyncOperationHandle>(dumbUpdate); List locations = new List() { new ResourceLocationBase("NotARealKey", "NotARealKey", typeof(BundledAssetProvider).FullName, typeof(ResourceLocationBase)) }; var clearCache = m_Addressables.ClearDependencyCacheAsync(locations, true); dumbUpdate.CallComplete(); yield return clearCache; Assert.IsFalse(clearCache.IsValid()); } [UnityTest] [Platform(Exclude ="PS5")] public IEnumerator AssetBundleRequestOptions_ComputesCorrectSize_WhenLocationDoesNotMatchBundleName_WithHash() { #if ENABLE_CACHING yield return Init(); //Setup string bundleName = "bundle"; string bundleLocation = "http://fake.com/default-bundle"; long size = 123; IResourceLocation location = new ResourceLocationBase("test", bundleLocation, typeof(AssetBundleProvider).FullName, typeof(GameObject)); Hash128 hash = Hash128.Compute("213412341242134"); AssetBundleRequestOptions abro = new AssetBundleRequestOptions() { BundleName = bundleName, BundleSize = size, Hash = hash.ToString() }; //Test Assert.AreEqual(size, abro.ComputeSize(location, m_Addressables.ResourceManager)); CreateFakeCachedBundle(bundleName, hash.ToString()); Assert.AreEqual(0, abro.ComputeSize(location, m_Addressables.ResourceManager)); //Cleanup Caching.ClearAllCachedVersions(bundleName); #else Assert.Ignore("Caching not enabled."); yield return null; #endif } [UnityTest] [Platform(Exclude ="PS5")] public IEnumerator AssetBundleResource_RemovesCachedBundle_OnLoadFailure() { #if ENABLE_CACHING yield return Init(); string bundleName = "bundleName"; Hash128 hash = Hash128.Parse("123456"); uint crc = 1; AssetBundleResource abr = new AssetBundleResource(); abr.m_ProvideHandle = new ProvideHandle(m_Addressables.ResourceManager, new ProviderOperation()); abr.m_Options = new AssetBundleRequestOptions() { BundleName = bundleName, Hash = hash.ToString(), Crc = crc, RetryCount = 3 }; CreateFakeCachedBundle(bundleName, hash.ToString()); CachedAssetBundle cab = new CachedAssetBundle(bundleName, hash); var request = abr.CreateWebRequest(new ResourceLocationBase("testName", bundleName, typeof(AssetBundleProvider).FullName, typeof(IAssetBundleResource))); Assert.IsTrue(Caching.IsVersionCached(cab)); yield return request.SendWebRequest(); Assert.IsFalse(Caching.IsVersionCached(cab)); #else Assert.Ignore("Caching not enabled."); yield return null; #endif } [UnityTest] [Platform(Exclude ="PS5")] public IEnumerator AssetBundleResource_RemovesCachedBundle_OnLoadFailure_WhenRetryCountIsZero() { #if ENABLE_CACHING yield return Init(); string bundleName = "bundleName"; Hash128 hash = Hash128.Parse("123456"); uint crc = 1; AssetBundleResource abr = new AssetBundleResource(); abr.m_ProvideHandle = new ProvideHandle(m_Addressables.ResourceManager, new ProviderOperation()); abr.m_Options = new AssetBundleRequestOptions() { BundleName = bundleName, Hash = hash.ToString(), Crc = crc, RetryCount = 0 }; CreateFakeCachedBundle(bundleName, hash.ToString()); CachedAssetBundle cab = new CachedAssetBundle(bundleName, hash); var request = abr.CreateWebRequest(new ResourceLocationBase("testName", bundleName, typeof(AssetBundleProvider).FullName, typeof(IAssetBundleResource))); Assert.IsTrue(Caching.IsVersionCached(cab)); yield return request.SendWebRequest(); Assert.IsFalse(Caching.IsVersionCached(cab)); #else Assert.Ignore("Caching not enabled."); yield return null; #endif } [Test] [Platform(Exclude ="PS5")] public void AssetBundleResource_WhenNotLoaded_GetAssetPreloadRequest_ReturnsNull() { AssetBundleResource abr = new AssetBundleResource(); Assert.AreEqual(null, abr.GetAssetPreloadRequest()); } [Test] public void WebRequestQueueOperation_CanSetWebRequest() { string url = "https://www.mynewsite.com/"; var op = new WebRequestQueueOperation(new UnityWebRequest("https://www.myoldsite.com/")); op.WebRequest = new UnityWebRequest(url); Assert.AreEqual(url, op.WebRequest.url); } [UnityTest] public IEnumerator WebRequestQueue_GetsSetOnInitialization_FromRuntimeData() { yield return Init(); Assert.AreEqual(AddressablesTestUtility.kMaxWebRequestCount, WebRequestQueue.s_MaxRequest); } [Test] public void WebRequestQueue_WhenMaxConcurrentRequests_SetToZero_ThrowsException() { Assert.Throws(() => WebRequestQueue.SetMaxConcurrentRequests(0), "MaxRequests must be 1 or greater."); } internal static string CreateFakeCachedBundle(string bundleName, string hash) { #if ENABLE_CACHING string fakeCachePath = string.Format("{0}/{1}/{2}", Caching.currentCacheForWriting.path, bundleName, hash); Directory.CreateDirectory(fakeCachePath); var dataFile = File.Create(Path.Combine(fakeCachePath, "__data")); var infoFile = File.Create(Path.Combine(fakeCachePath, "__info")); byte[] info = new UTF8Encoding(true).GetBytes( @"-1 1554740658 1 __data"); infoFile.Write(info, 0, info.Length); dataFile.Dispose(); infoFile.Dispose(); return fakeCachePath; #else return null; #endif } class AsyncWaitForCompletion : MonoBehaviour { public string key1; public string key2; public bool done = false; public AsyncOperationHandle> op; public AsyncOperationHandle op2; public AddressablesImpl addressables; public string errorMsg; async void Start() { try { op = addressables.LoadResourceLocationsAsync(key1, typeof(Texture2D)); await op.Task; op2 = addressables.LoadAssetAsync(key2); op2.WaitForCompletion(); } catch (Exception e) { errorMsg = e.Message; } finally { done = true; } } } [UnityTest] public IEnumerator WhenCallingWaitForCompletion_InAsyncMethod_NoExceptionIsThrown() { yield return Init(); var go = new GameObject("test", typeof(AsyncWaitForCompletion)); var comp = go.GetComponent(); comp.addressables = m_Addressables; comp.key1 = "prefabs_evenBASE"; comp.key2 = AddressablesTestUtility.GetPrefabLabel("BASE"); while (!comp.done) yield return null; Assert.IsTrue(string.IsNullOrEmpty(comp.errorMsg), comp.errorMsg); comp.op.Release(); comp.op2.Release(); GameObject.Destroy(go); } } }