276 lines
12 KiB
C#
276 lines
12 KiB
C#
|
using System.Collections;
|
||
|
using System.Collections.Generic;
|
||
|
using System.IO;
|
||
|
using System.Linq;
|
||
|
using System.Text.RegularExpressions;
|
||
|
using NUnit.Framework;
|
||
|
#if UNITY_EDITOR
|
||
|
using UnityEditor.AddressableAssets.Settings;
|
||
|
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
|
||
|
#endif
|
||
|
using UnityEngine;
|
||
|
using UnityEngine.AddressableAssets;
|
||
|
using UnityEngine.Networking;
|
||
|
using UnityEngine.ResourceManagement;
|
||
|
using UnityEngine.ResourceManagement.AsyncOperations;
|
||
|
using UnityEngine.ResourceManagement.ResourceLocations;
|
||
|
using UnityEngine.ResourceManagement.ResourceProviders;
|
||
|
using UnityEngine.ResourceManagement.Util;
|
||
|
using UnityEngine.SceneManagement;
|
||
|
using UnityEngine.TestTools;
|
||
|
|
||
|
namespace AddressableTests.SyncAddressables
|
||
|
{
|
||
|
public abstract class AssetBundleProviderTests : AddressablesTestFixture
|
||
|
{
|
||
|
protected string m_PrefabKey = "syncprefabkey";
|
||
|
protected string m_InvalidKey = "notarealkey";
|
||
|
protected string m_SceneKey = "syncscenekey";
|
||
|
|
||
|
const int kForceUWRBundleCount = 10;
|
||
|
const int kMaxConcurrentRequests = 3;
|
||
|
|
||
|
string GetForceUWRAddrName(int i)
|
||
|
{
|
||
|
return $"forceuwrasset{i}";
|
||
|
}
|
||
|
|
||
|
#if UNITY_EDITOR
|
||
|
internal override void Setup(AddressableAssetSettings settings, string tempAssetFolder)
|
||
|
{
|
||
|
AddressableAssetGroup regGroup = settings.CreateGroup("localNoUWRGroup", false, false, true,
|
||
|
new List<AddressableAssetGroupSchema>(), typeof(BundledAssetGroupSchema));
|
||
|
regGroup.GetSchema<BundledAssetGroupSchema>().BundleNaming = BundledAssetGroupSchema.BundleNamingStyle.OnlyHash;
|
||
|
|
||
|
AddressableAssetGroup forceUWRGroup = settings.CreateGroup("ForceUWRGroup", false, false, true,
|
||
|
new List<AddressableAssetGroupSchema>(), typeof(BundledAssetGroupSchema));
|
||
|
forceUWRGroup.GetSchema<BundledAssetGroupSchema>().UseUnityWebRequestForLocalBundles = true;
|
||
|
forceUWRGroup.GetSchema<BundledAssetGroupSchema>().BundleMode = BundledAssetGroupSchema.BundlePackingMode.PackSeparately;
|
||
|
forceUWRGroup.GetSchema<BundledAssetGroupSchema>().BundleNaming = BundledAssetGroupSchema.BundleNamingStyle.OnlyHash;
|
||
|
|
||
|
settings.MaxConcurrentWebRequests = kMaxConcurrentRequests;
|
||
|
|
||
|
for (int i = 0; i < kForceUWRBundleCount; i++)
|
||
|
{
|
||
|
string s = GetForceUWRAddrName(i);
|
||
|
string guid = CreatePrefab(tempAssetFolder + $"/{s}.prefab");
|
||
|
AddressableAssetEntry entry = settings.CreateOrMoveEntry(guid, forceUWRGroup);
|
||
|
entry.address = s;
|
||
|
}
|
||
|
|
||
|
{
|
||
|
string guid = CreatePrefab(tempAssetFolder + $"/testprefab.prefab");
|
||
|
AddressableAssetEntry entry = settings.CreateOrMoveEntry(guid, regGroup);
|
||
|
entry.address = "testprefab";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
[SetUp]
|
||
|
public void Setup()
|
||
|
{
|
||
|
#if ENABLE_CACHING
|
||
|
Caching.ClearCache();
|
||
|
#endif
|
||
|
if (m_Addressables != null)
|
||
|
m_Addressables.WebRequestOverride = null;
|
||
|
}
|
||
|
|
||
|
[UnityTest]
|
||
|
[Platform(Exclude = "PS5")]
|
||
|
public IEnumerator WhenUWRExceedsMaxLimit_UWRAreQueued()
|
||
|
{
|
||
|
List<AsyncOperationHandle<GameObject>> l =
|
||
|
Enumerable.Range(0, kForceUWRBundleCount).Select(x => m_Addressables.LoadAssetAsync<GameObject>(GetForceUWRAddrName(x))).ToList();
|
||
|
Assert.AreEqual(kMaxConcurrentRequests, WebRequestQueue.s_ActiveRequests.Count);
|
||
|
Assert.AreEqual((kForceUWRBundleCount - kMaxConcurrentRequests), WebRequestQueue.s_QueuedOperations.Count);
|
||
|
foreach (AsyncOperationHandle<GameObject> h in l)
|
||
|
{
|
||
|
yield return h;
|
||
|
h.Release();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[UnityTest]
|
||
|
[Platform(Exclude = "PS5")]
|
||
|
public IEnumerator WhenUWRExceedsMaxLimit_CompletesSynchronously()
|
||
|
{
|
||
|
List<AsyncOperationHandle<GameObject>> loadOps =
|
||
|
Enumerable.Range(0, kForceUWRBundleCount).Select(x => m_Addressables.LoadAssetAsync<GameObject>(GetForceUWRAddrName(x))).ToList();
|
||
|
|
||
|
AsyncOperationHandle<GameObject> lastHandle = loadOps[kForceUWRBundleCount - 1];
|
||
|
lastHandle.WaitForCompletion();
|
||
|
lastHandle.Release();
|
||
|
|
||
|
for (int i = 0; i < kForceUWRBundleCount - 1; i++)
|
||
|
{
|
||
|
AsyncOperationHandle<GameObject> handle = loadOps[i];
|
||
|
yield return loadOps[i];
|
||
|
handle.Release();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[Test]
|
||
|
[Platform(Exclude = "PS5")]
|
||
|
public void WhenUWRIsUsed_CompletesSynchronously()
|
||
|
{
|
||
|
AsyncOperationHandle<GameObject> h = m_Addressables.LoadAssetAsync<GameObject>(GetForceUWRAddrName(0));
|
||
|
h.WaitForCompletion();
|
||
|
h.Release();
|
||
|
}
|
||
|
|
||
|
[UnityTest]
|
||
|
[Platform(Exclude = "PS5")]
|
||
|
public IEnumerator WhenAssetBundleIsLocal_AndForceUWRIsEnabled_UWRIsUsed()
|
||
|
{
|
||
|
AsyncOperationHandle<GameObject> h = m_Addressables.LoadAssetAsync<GameObject>(GetForceUWRAddrName(0));
|
||
|
Assert.AreEqual(1, WebRequestQueue.s_ActiveRequests.Count);
|
||
|
yield return h;
|
||
|
h.Release();
|
||
|
}
|
||
|
|
||
|
[UnityTest]
|
||
|
[Platform(Exclude = "PS5")]
|
||
|
public IEnumerator WhenAssetBundleIsLocal_AndForceUWRIsDisabled_UWRIsNotUsed()
|
||
|
{
|
||
|
AsyncOperationHandle<GameObject> h = m_Addressables.LoadAssetAsync<GameObject>("testprefab");
|
||
|
Assert.AreEqual(0, WebRequestQueue.s_ActiveRequests.Count);
|
||
|
yield return h;
|
||
|
h.Release();
|
||
|
}
|
||
|
|
||
|
[UnityTest]
|
||
|
[Platform(Exclude = "PS5")]
|
||
|
public IEnumerator WhenWebRequestOverrideIsSet_CallbackIsCalled_AssetBundleProvider()
|
||
|
{
|
||
|
bool webRequestOverrideCalled = false;
|
||
|
m_Addressables.WebRequestOverride = request => webRequestOverrideCalled = true;
|
||
|
|
||
|
var prev = LogAssert.ignoreFailingMessages;
|
||
|
LogAssert.ignoreFailingMessages = true;
|
||
|
|
||
|
var nonExistingPath = "http://127.0.0.1/non-existing-bundle";
|
||
|
var loc = new ResourceLocationBase(nonExistingPath, nonExistingPath, typeof(AssetBundleProvider).FullName, typeof(AssetBundleResource));
|
||
|
loc.Data = new AssetBundleRequestOptions();
|
||
|
var h = m_Addressables.ResourceManager.ProvideResource<AssetBundleResource>(loc);
|
||
|
yield return h;
|
||
|
|
||
|
if (h.IsValid()) h.Release();
|
||
|
LogAssert.ignoreFailingMessages = prev;
|
||
|
Assert.IsTrue(webRequestOverrideCalled);
|
||
|
}
|
||
|
|
||
|
[UnityTest]
|
||
|
[Platform(Exclude = "PS5")]
|
||
|
public IEnumerator WhenWebRequestFails_RetriesCorrectAmount_AssetBundleProvider()
|
||
|
{
|
||
|
var prev = LogAssert.ignoreFailingMessages;
|
||
|
LogAssert.ignoreFailingMessages = true;
|
||
|
|
||
|
var nonExistingPath = "http://127.0.0.1/non-existing-bundle";
|
||
|
var loc = new ResourceLocationBase(nonExistingPath, nonExistingPath, typeof(AssetBundleProvider).FullName, typeof(AssetBundleResource));
|
||
|
var d = new AssetBundleRequestOptions();
|
||
|
d.RetryCount = 3;
|
||
|
loc.Data = d;
|
||
|
|
||
|
LogAssert.Expect(LogType.Log, new Regex(@"^(Web request failed, retrying \(0/3)"));
|
||
|
LogAssert.Expect(LogType.Log, new Regex(@"^(Web request failed, retrying \(1/3)"));
|
||
|
LogAssert.Expect(LogType.Log, new Regex(@"^(Web request failed, retrying \(2/3)"));
|
||
|
var h = m_Addressables.ResourceManager.ProvideResource<AssetBundleResource>(loc);
|
||
|
yield return h;
|
||
|
|
||
|
if (h.IsValid()) h.Release();
|
||
|
LogAssert.ignoreFailingMessages = prev;
|
||
|
}
|
||
|
|
||
|
[Test]
|
||
|
[Platform(Exclude = "PS5")]
|
||
|
[TestCase("Relative/Local/Path", true, false)]
|
||
|
[TestCase("Relative/Local/Path", true, true)]
|
||
|
[TestCase("http://127.0.0.1/Web/Path", false, true)]
|
||
|
[TestCase("jar:file://Local/Path", true, false)]
|
||
|
[TestCase("jar:file://Local/Path", true, true)]
|
||
|
public void AssetBundleLoadPathsCorrectForGetLoadInfo(string internalId, bool isLocal, bool useUnityWebRequestForLocalBundles)
|
||
|
{
|
||
|
if (internalId.StartsWith("jar") && Application.platform != RuntimePlatform.Android)
|
||
|
Assert.Ignore($"Skipping test {TestContext.CurrentContext.Test.Name} due jar based tests are only for running on Android Platform.");
|
||
|
|
||
|
var loc = new ResourceLocationBase("dummy", internalId, "dummy", typeof(Object));
|
||
|
loc.Data = new AssetBundleRequestOptions {UseUnityWebRequestForLocalBundles = useUnityWebRequestForLocalBundles};
|
||
|
ProviderOperation<Object> op = new ProviderOperation<Object>();
|
||
|
op.Init(m_Addressables.ResourceManager, null, loc, new AsyncOperationHandle<IList<AsyncOperationHandle>>());
|
||
|
ProvideHandle h = new ProvideHandle(m_Addressables.ResourceManager, op);
|
||
|
|
||
|
AssetBundleResource.GetLoadInfo(h, out AssetBundleResource.LoadType loadType, out string path);
|
||
|
var expectedLoadType = isLocal ? useUnityWebRequestForLocalBundles ? AssetBundleResource.LoadType.Web : AssetBundleResource.LoadType.Local : AssetBundleResource.LoadType.Web;
|
||
|
Assert.AreEqual(expectedLoadType, loadType, "Incorrect load type found for internalId " + internalId);
|
||
|
var expectedPath = internalId;
|
||
|
if (isLocal && useUnityWebRequestForLocalBundles)
|
||
|
{
|
||
|
expectedPath = internalId.StartsWith("jar") ? internalId : "file:///" + Path.GetFullPath(internalId);
|
||
|
}
|
||
|
|
||
|
Assert.AreEqual(expectedPath, path);
|
||
|
}
|
||
|
|
||
|
[UnityTest]
|
||
|
public IEnumerator LoadBundleAsync_WithUnfinishedUnload_WaitsForUnloadAndCompletes()
|
||
|
{
|
||
|
var h = m_Addressables.LoadAssetAsync<GameObject>("testprefab");
|
||
|
yield return h;
|
||
|
Assert.IsNotNull(h.Result);
|
||
|
h.Release();
|
||
|
h = m_Addressables.LoadAssetAsync<GameObject>("testprefab");
|
||
|
yield return h;
|
||
|
Assert.IsNotNull(h.Result);
|
||
|
h.Release();
|
||
|
}
|
||
|
|
||
|
[UnityTest]
|
||
|
public IEnumerator LoadBundleSync_WithUnfinishedUnload_WaitsForUnloadAndCompletes()
|
||
|
{
|
||
|
var h = m_Addressables.LoadAssetAsync<GameObject>("testprefab");
|
||
|
yield return h;
|
||
|
Assert.IsNotNull(h.Result);
|
||
|
h.Release();
|
||
|
h = m_Addressables.LoadAssetAsync<GameObject>("testprefab");
|
||
|
h.WaitForCompletion();
|
||
|
Assert.IsNotNull(h.Result);
|
||
|
h.Release();
|
||
|
}
|
||
|
|
||
|
[Test]
|
||
|
// Only testing against important errors instead of full list
|
||
|
[TestCase("", true)]
|
||
|
[TestCase("Unknown error", true)]
|
||
|
[TestCase("Request aborted", false)]
|
||
|
[TestCase("Unable to write data", false)]
|
||
|
public void UnityWebRequestResult_ShouldRetryReturnsExpected(string error, bool expected)
|
||
|
{
|
||
|
UnityWebRequestResult rst = new UnityWebRequestResult(new UnityWebRequest());
|
||
|
rst.Error = error;
|
||
|
bool result = rst.ShouldRetryDownloadError();
|
||
|
Assert.AreEqual(expected, result, "Unexpected retry value for the input error.");
|
||
|
}
|
||
|
}
|
||
|
#if UNITY_EDITOR
|
||
|
class AssetBundleProviderTests_PackedPlaymodeMode : AssetBundleProviderTests
|
||
|
{
|
||
|
protected override TestBuildScriptMode BuildScriptMode
|
||
|
{
|
||
|
get { return TestBuildScriptMode.PackedPlaymode; }
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
[UnityPlatform(exclude = new[] {RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor})]
|
||
|
class AssetBundleProviderTests_PackedMode : AssetBundleProviderTests
|
||
|
{
|
||
|
protected override TestBuildScriptMode BuildScriptMode
|
||
|
{
|
||
|
get { return TestBuildScriptMode.Packed; }
|
||
|
}
|
||
|
}
|
||
|
}
|