104 lines
3.3 KiB
C#
104 lines
3.3 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using FlowScope.Resources;
|
|
using NUnit.Framework;
|
|
using UnityEngine.TestTools;
|
|
|
|
namespace FlowScope.Tests.PlayMode.Resources
|
|
{
|
|
public sealed class AddressablesResourceServiceTests
|
|
{
|
|
[UnityTest]
|
|
public IEnumerator LoadAsync_WhenSameKeyLoadsConcurrently_SharesOneBackendLoad()
|
|
{
|
|
var backendLoads = 0;
|
|
var releaseCount = 0;
|
|
var gate = new TaskCompletionSource<object>();
|
|
var service = new AddressablesResourceService(
|
|
async (_, _, _) =>
|
|
{
|
|
backendLoads++;
|
|
return await gate.Task;
|
|
},
|
|
(_, _) => releaseCount++);
|
|
|
|
var first = service.LoadAsync<TestAsset>("shared", CancellationToken.None);
|
|
var second = service.LoadAsync<TestAsset>("shared", CancellationToken.None);
|
|
|
|
gate.SetResult(new TestAsset());
|
|
IResourceHandle<TestAsset> firstHandle = null;
|
|
IResourceHandle<TestAsset> secondHandle = null;
|
|
yield return AwaitTask(first, handle => firstHandle = handle);
|
|
yield return AwaitTask(second, handle => secondHandle = handle);
|
|
|
|
Assert.AreEqual(1, backendLoads);
|
|
Assert.AreSame(firstHandle.Asset, secondHandle.Asset);
|
|
|
|
firstHandle.Dispose();
|
|
Assert.AreEqual(0, releaseCount);
|
|
secondHandle.Dispose();
|
|
Assert.AreEqual(1, releaseCount);
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator LoadAsync_WhenBackendFails_IncludesKeyAndBackend()
|
|
{
|
|
var service = new AddressablesResourceService(
|
|
(_, _, _) => throw new InvalidOperationException("missing"),
|
|
(_, _) => { });
|
|
|
|
InvalidOperationException exception = null;
|
|
yield return ThrowsAsync<InvalidOperationException>(
|
|
() => service.LoadAsync<TestAsset>("missing-key", CancellationToken.None),
|
|
caught => exception = caught);
|
|
|
|
StringAssert.Contains("missing-key", exception.Message);
|
|
StringAssert.Contains("Addressables", exception.Message);
|
|
}
|
|
|
|
private static IEnumerator ThrowsAsync<TException>(Func<Task> action, Action<TException> onCaught)
|
|
where TException : Exception
|
|
{
|
|
var task = action();
|
|
while (!task.IsCompleted)
|
|
{
|
|
yield return null;
|
|
}
|
|
|
|
if (task.IsFaulted && task.Exception?.GetBaseException() is TException exception)
|
|
{
|
|
onCaught(exception);
|
|
yield break;
|
|
}
|
|
|
|
Assert.Fail($"Expected {typeof(TException).Name}.");
|
|
}
|
|
|
|
private static IEnumerator AwaitTask<T>(Task<T> task, Action<T> onCompleted)
|
|
{
|
|
while (!task.IsCompleted)
|
|
{
|
|
yield return null;
|
|
}
|
|
|
|
if (task.IsFaulted)
|
|
{
|
|
throw task.Exception.GetBaseException();
|
|
}
|
|
|
|
if (task.IsCanceled)
|
|
{
|
|
throw new OperationCanceledException();
|
|
}
|
|
|
|
onCompleted(task.Result);
|
|
}
|
|
|
|
private sealed class TestAsset
|
|
{
|
|
}
|
|
}
|
|
}
|