using NUnit.Framework; using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.ResourceManagement.ResourceLocations; using UnityEngine.ResourceManagement.ResourceProviders; namespace UnityEngine.ResourceManagement.Tests { internal class ManualPercentCompleteOperation : AsyncOperationBase { public ManualPercentCompleteOperation(float percentComplete) { m_PercentComplete = percentComplete; } public float m_PercentComplete; protected override void Execute() { Complete(new GameObject(), true, ""); } protected override float Progress => m_PercentComplete; } public class ProviderOperationTests { MockProvider m_Provider; MockProvider m_Provider2; Action m_PrevHandler; ResourceManager m_RM; [OneTimeSetUp] public void OneTimeSetup() { m_PrevHandler = ResourceManager.ExceptionHandler; ResourceManager.ExceptionHandler = null; } [OneTimeTearDown] public void OneTimeTeardown() { ResourceManager.ExceptionHandler = m_PrevHandler; } private void ProvideBasicCallback(ProvideHandle provideHandle) { provideHandle.Complete(provideHandle.Location.InternalId, true, null); } [SetUp] public void Setup() { m_RM = new ResourceManager(); m_RM.CallbackHooksEnabled = false; m_RM.postProfilerEvents = true; m_Provider = new MockProvider(); m_Provider.ProvideCallback = ProvideBasicCallback; m_Provider2 = new MockProvider(); m_Provider2._ProviderId = "MockId2"; m_Provider2.ProvideCallback = ProvideBasicCallback; m_RM.ResourceProviders.Add(m_Provider); m_RM.ResourceProviders.Add(m_Provider2); } [TearDown] public void TearDown() { m_RM.ResourceProviders.Remove(m_Provider); m_RM.ResourceProviders.Remove(m_Provider2); Assert.Zero(m_RM.OperationCacheCount); m_RM.Dispose(); m_RM = null; } [Test] public void WhenDependency_ProvideCalledAfterDependencyFinishes() { ProvideHandle provideHandle = default(ProvideHandle); m_Provider2.ProvideCallback = x => { provideHandle = x; }; ResourceLocationBase depLoc = new ResourceLocationBase("dep", "dep", m_Provider2.ProviderId, typeof(object)); ResourceLocationBase loc = new ResourceLocationBase("1", "1", m_Provider.ProviderId, typeof(object), depLoc); var op = m_RM.ProvideResource(loc); m_RM.Update(0.0f); Assert.False(op.IsDone); provideHandle.Complete(2, true, null); m_RM.Update(0.0f); Assert.True(op.IsDone); op.Release(); } [Test] public void OnDestroyed_DepOpReleasedAndProviderReleased() { ResourceLocationBase depLoc = new ResourceLocationBase("dep", "dep", m_Provider2.ProviderId, typeof(object)); ResourceLocationBase loc = new ResourceLocationBase("1", "1", m_Provider.ProviderId, typeof(object), depLoc); ResourceLocationBase loc2 = new ResourceLocationBase("2", "2", m_Provider.ProviderId, typeof(object), depLoc); var op1 = m_RM.ProvideResource(loc); m_RM.Update(0.0f); Assert.AreEqual(1, m_Provider2.ProvideLog.Count); var op2 = m_RM.ProvideResource(loc2); m_RM.Update(0.0f); Assert.AreEqual(1, m_Provider2.ProvideLog.Count); Assert.AreEqual(2, m_Provider.ProvideLog.Count); Assert.AreEqual(AsyncOperationStatus.Succeeded, op1.Status); Assert.AreEqual(AsyncOperationStatus.Succeeded, op2.Status); // decrement the first op. the second op should still be holding the dependency op1.Release(); Assert.AreEqual(0, m_Provider2.ReleaseLog.Count); // decrement the second op. the dependency should now have been released op2.Release(); Assert.AreEqual(1, m_Provider2.ReleaseLog.Count); Assert.AreEqual(2, m_Provider.ReleaseLog.Count); Assert.AreEqual(1, m_Provider2.ReleaseLog.Count); } [Test] public void WhenDependentOpFails_ProvideIsNotCalled() { ResourceLocationBase depLoc = new ResourceLocationBase("dep", "dep", "unknown provider", typeof(object)); ResourceLocationBase loc = new ResourceLocationBase("1", "1", m_Provider.ProviderId, typeof(object), depLoc); var op = m_RM.ProvideResource(loc); m_RM.Update(0.0f); Assert.AreEqual(AsyncOperationStatus.Failed, op.Status); op.Release(); Assert.AreEqual(0, m_Provider.ProvideLog.Count); Assert.AreEqual(0, m_Provider.ReleaseLog.Count); } [Test] public void WhenDependentOpFails_AndProviderSupportsFailedDependencies_OperationContinues() { m_Provider._BehaviourFlags = ProviderBehaviourFlags.CanProvideWithFailedDependencies; ResourceLocationBase depLoc = new ResourceLocationBase("dep", "dep", "unknown provider", typeof(object)); ResourceLocationBase loc = new ResourceLocationBase("1", "1", m_Provider.ProviderId, typeof(object), depLoc); var op = m_RM.ProvideResource(loc); m_RM.Update(0.0f); Assert.AreEqual(AsyncOperationStatus.Succeeded, op.Status); Assert.AreEqual("1", op.Result); op.Release(); Assert.AreEqual(1, m_Provider.ProvideLog.Count); Assert.AreEqual(1, m_Provider.ReleaseLog.Count); } [Test] public void WhenProviderCompletesInsideProvideCall_CallbackIsNotDeferred() { ResourceLocationBase depLoc = new ResourceLocationBase("dep", "dep", m_Provider2.ProviderId, typeof(object)); ResourceLocationBase loc = new ResourceLocationBase("1", "1", m_Provider.ProviderId, typeof(object), depLoc); ProvideHandle depHandle = new ProvideHandle(); m_Provider2.ProvideCallback = (x) => { depHandle = x; }; var op = m_RM.ProvideResource(loc); bool callbackCalled = false; Assert.AreEqual(AsyncOperationStatus.None, op.Status); op.Completed += x => callbackCalled = true; // mark dependency complete depHandle.Complete(1, true, null); Assert.IsTrue(callbackCalled); op.Release(); } [Test] public void WhenProviderCompletesOutsideProvideCall_CallbackIsImmediate() { ResourceLocationBase loc = new ResourceLocationBase("1", "1", m_Provider.ProviderId, typeof(object)); ProvideHandle depHandle = new ProvideHandle(); m_Provider.ProvideCallback = (x) => { depHandle = x; }; var op = m_RM.ProvideResource(loc); bool callbackCalled = false; Assert.AreEqual(AsyncOperationStatus.None, op.Status); op.Completed += x => callbackCalled = true; // mark dependency complete Assert.IsFalse(callbackCalled); depHandle.Complete(1, true, null); Assert.IsTrue(callbackCalled); op.Release(); } [Test] public void UsingProviderHandleWithInvalidVersion_ThrowsException() { ResourceLocationBase loc = new ResourceLocationBase("1", "1", m_Provider.ProviderId, typeof(object)); ProvideHandle handle = new ProvideHandle(); m_Provider.ProvideCallback = (x) => { handle = x; }; var op = m_RM.ProvideResource(loc); handle.Complete(null, true, null); Assert.Catch(() => handle.Complete(null, true, null), ProviderOperation.kInvalidHandleMsg); Assert.Catch(() => handle.GetDependencies(new List()), ProviderOperation.kInvalidHandleMsg); op.Release(); } [Test] public void GetDependency_InsertsDependenciesIntoList() { List deps = new List(); ResourceLocationBase depLoc = new ResourceLocationBase("dep1", "dep1", m_Provider2.ProviderId, typeof(object)); ResourceLocationBase depLoc2 = new ResourceLocationBase("dep2", "dep2", m_Provider2.ProviderId, typeof(object)); ResourceLocationBase loc = new ResourceLocationBase("1", "1", m_Provider.ProviderId, typeof(object), depLoc, depLoc2); m_Provider.ProvideCallback = (handle) => { handle.GetDependencies(deps); handle.Complete(0, true, null); }; var op = m_RM.ProvideResource(loc); m_RM.Update(0.0f); Assert.AreEqual(AsyncOperationStatus.Succeeded, op.Status); Assert.AreEqual(deps[0], "dep1"); Assert.AreEqual(deps[1], "dep2"); op.Release(); } [Test] public void ProviderOperation_PercentComplete_DoesNotDecreaseAfterPercentCallbackIsSet() { var providerOp = new ProviderOperation(); providerOp.m_DepOp = new AsyncOperationHandle>(); providerOp.m_DepOp.m_InternalOp = new ProviderOperation>(); providerOp.m_DepOp.m_InternalOp.Result = new List(); providerOp.m_DepOp.m_InternalOp.Result.Add(new ManualPercentCompleteOperation(1.0f).Handle); Assert.AreEqual(0.5f, providerOp.PercentComplete); providerOp.SetProgressCallback(() => 0.5f); Assert.AreEqual(0.75f, providerOp.PercentComplete); } class Type1 { } class Type2 { } [Test] public void WhenProviderCallsComplete_AndTypeIsIncorrect_Throws() { ResourceLocationBase loc = new ResourceLocationBase("1", "1", m_Provider.ProviderId, typeof(object)); Exception testException = null; m_Provider.ProvideCallback = (x) => { try { x.Complete(new Type2(), true, null); } catch (Exception e) { testException = e; } }; var op = m_RM.ProvideResource(loc); m_RM.Update(0.0f); Assert.IsNotNull(testException); Assert.AreEqual(AsyncOperationStatus.Failed, op.Status); Assert.IsNull(op.Result); Assert.IsTrue(op.OperationException.Message.Contains("Provider of type")); op.Release(); } [Test] public void WhenProviderThrowsExceptionOnProvide_OperationFails() { ResourceLocationBase loc = new ResourceLocationBase("1", "1", m_Provider.ProviderId, typeof(object)); m_Provider.ProvideCallback = (x) => { throw new Exception("I have failed"); }; var op = m_RM.ProvideResource(loc); m_RM.Update(0.0f); Assert.AreEqual(AsyncOperationStatus.Failed, op.Status); op.Release(); } [Test] public void WhenProviderThrowsExceptionInProgressCallback_ProgressReturnsZero() { ResourceLocationBase loc = new ResourceLocationBase("1", "1", m_Provider.ProviderId, typeof(object)); ProvideHandle handle = new ProvideHandle(); bool didThrow = false; m_Provider.ProvideCallback = (x) => { handle = x; handle.SetProgressCallback(() => { didThrow = true; throw new Exception("I have failed"); }); }; var op = m_RM.ProvideResource(loc); Assert.AreEqual(0.0f, op.PercentComplete); Assert.True(didThrow); handle.Complete(null, true, null); op.Release(); } public void ProvideWithoutSpecifiedType_UsesDefaultProviderType() { ResourceLocationBase depLoc = new ResourceLocationBase("dep", "dep", m_Provider2.ProviderId, typeof(object)); ResourceLocationBase loc = new ResourceLocationBase("1", "1", m_Provider.ProviderId, typeof(object), depLoc); ProvideHandle handle = default(ProvideHandle); m_Provider2.ProvideCallback = (x) => { handle = x; }; m_Provider2.DefaultType = typeof(Type2); var op = m_RM.ProvideResource(loc); Assert.AreEqual(typeof(Type2), handle.Type); handle.Complete(new Type2(), true, null); op.Release(); } void ProviderCompleteTypeTest(TResultType result, string exceptionMessage) { ResourceLocationBase loc = new ResourceLocationBase("1", "1", m_Provider.ProviderId, typeof(object)); ProvideHandle handle = default(ProvideHandle); m_Provider.ProvideCallback = (x) => { handle = x; }; var op = m_RM.ProvideResource(loc); if (string.IsNullOrEmpty(exceptionMessage)) { handle.Complete(result, true, null); } else { // TODO: assert contents of exception Assert.Catch(() => handle.Complete(result, true, null)); } Assert.True(op.IsDone); op.Release(); } class Type3 : Type2 { } [Test] public void ProvideHandle_CompleteWithExactType_Succeeds() { ProviderCompleteTypeTest(new Type2(), null); } [Test] public void ProvideHandle_CompleteWithDerivedTypeAsResult_Succeeds() { ProviderCompleteTypeTest(new Type3(), null); } [Test] public void ProvideHandle_CompleteWithBaseTypeAsResult_Succeeds() { ProviderCompleteTypeTest(new Type3(), null); } [Test] public void ProvideHandle_CompleteWithNullForReferencedType_Succeeds() { ProviderCompleteTypeTest(null, null); } [Test] public void ProvideHandle_CompleteWithNonAssignableType_Throws() { ProviderCompleteTypeTest(new Type1(), "Failed"); } [Test] public void ProvideResource_WhenDependencyFailsToLoad_AndProviderCannotLoadWithFailedDependencies_ProvideNotCalled() { m_Provider.ProvideCallback = (pi) => { throw new Exception("This Should Not Have Been Called"); }; m_RM.ResourceProviders.Add(m_Provider); ResourceLocationBase locDep = new ResourceLocationBase("depasset", "depasset", "unkonwn", typeof(object)); ResourceLocationBase locRoot = new ResourceLocationBase("rootasset", "rootasset", m_Provider.ProviderId, typeof(object), locDep); AsyncOperationHandle op = m_RM.ProvideResource(locRoot); m_RM.Update(0.0f); Assert.AreEqual(AsyncOperationStatus.Failed, op.Status); op.Release(); } [Test] public void ProvideResource_WhenDependencyFailsToLoad_AndProviderCanLoadWithFailedDependencies_ProviderStillProvides() { m_Provider._BehaviourFlags = ProviderBehaviourFlags.CanProvideWithFailedDependencies; m_Provider.ProvideCallback = (pi) => { pi.Complete(5, true, null); }; m_RM.ResourceProviders.Add(m_Provider); ResourceLocationBase locDep = new ResourceLocationBase("depasset", "depasset", "unkonwn", typeof(object)); ResourceLocationBase locRoot = new ResourceLocationBase("rootasset", "rootasset", m_Provider.ProviderId, typeof(object), locDep); AsyncOperationHandle op = m_RM.ProvideResource(locRoot); m_RM.Update(0.0f); Assert.AreEqual(AsyncOperationStatus.Succeeded, op.Status); Assert.AreEqual(5, op.Result); op.Release(); } [Test] public void ProvideResource_ReceiveDiagnosticsCallback_IGenericProviderOperationHasLocation() { m_Provider.ProvideCallback = (pi) => { pi.Complete(int.Parse(pi.Location.InternalId), true, null); }; m_RM.ResourceProviders.Add(m_Provider); List eventsRecieved = new List(); m_RM.RegisterDiagnosticCallback(ctx => { eventsRecieved.Add(ctx); }); var locations = new ResourceLocationBase("1", "1", m_Provider.ProviderId, typeof(object)); AsyncOperationHandle op = m_RM.ProvideResource(locations); m_RM.Update(0.0f); m_RM.ClearDiagnosticCallbacks(); for (int i = 0; i < eventsRecieved.Count; ++i) { if (eventsRecieved[i].OperationHandle.m_InternalOp is IGenericProviderOperation) { Assert.NotNull(eventsRecieved[i].Location); Assert.IsTrue(eventsRecieved[i].Location.InternalId == "1"); } } op.Release(); } [Test] public void ProvideResource_ReceiveDiagnosticsCallback_CreateAndComplete() { m_Provider.ProvideCallback = (pi) => { pi.Complete(int.Parse(pi.Location.InternalId), true, null); }; m_RM.ResourceProviders.Add(m_Provider); List eventsRecieved = new List(); m_RM.RegisterDiagnosticCallback(ctx => { eventsRecieved.Add(ctx); }); var locations = new ResourceLocationBase("1", "1", m_Provider.ProviderId, typeof(object)); AsyncOperationHandle op = m_RM.ProvideResource(locations); m_RM.Update(0.0f); m_RM.ClearDiagnosticCallbacks(); bool created = false; bool completed = false; for (int i = 0; i < eventsRecieved.Count; ++i) { if (eventsRecieved[i].Type == ResourceManager.DiagnosticEventType.AsyncOperationCreate) { Assert.NotNull(eventsRecieved[i].Location); Assert.IsTrue(eventsRecieved[i].Location.InternalId == "1"); Assert.IsFalse(completed); Assert.IsFalse(created); created = true; } else if (eventsRecieved[i].Type == ResourceManager.DiagnosticEventType.AsyncOperationComplete) { Assert.NotNull(eventsRecieved[i].Location); Assert.True(eventsRecieved[i].Location.InternalId == "1"); Assert.IsFalse(completed); Assert.IsTrue(created); completed = true; } else if (eventsRecieved[i].Type == ResourceManager.DiagnosticEventType.AsyncOperationDestroy) { Assert.NotNull(eventsRecieved[i].Location); Assert.True(eventsRecieved[i].Location.InternalId == "1"); Assert.IsTrue(completed); Assert.IsTrue(created); } } op.Release(); } [Test] public void ProvideResource_ReceiveDiagnosticsCallback_MultipleCallbacks() { m_Provider.ProvideCallback = (pi) => { pi.Complete(int.Parse(pi.Location.InternalId), true, null); }; m_RM.ResourceProviders.Add(m_Provider); bool callback1 = false, callback2 = false; m_RM.RegisterDiagnosticCallback(ctx => { callback1 = true; }); m_RM.RegisterDiagnosticCallback(ctx => { callback2 = true; }); var locations = new ResourceLocationBase("1", "1", m_Provider.ProviderId, typeof(object)); AsyncOperationHandle op = m_RM.ProvideResource(locations); m_RM.Update(0.0f); m_RM.ClearDiagnosticCallbacks(); Assert.IsTrue(callback1); Assert.IsTrue(callback2); op.Release(); } [Test] public void ProvideResources_CanLoadAndUnloadMultipleResources() { m_Provider.ProvideCallback = (pi) => { pi.Complete(int.Parse(pi.Location.InternalId), true, null); }; m_RM.ResourceProviders.Add(m_Provider); var locations = new List() { new ResourceLocationBase("0", "0", m_Provider.ProviderId, typeof(object)), new ResourceLocationBase("1", "1", m_Provider.ProviderId, typeof(object)), }; AsyncOperationHandle> op = m_RM.ProvideResources(locations); m_RM.Update(0.0f); for (int i = 0; i < locations.Count; i++) { Assert.AreEqual((int)op.Result[i], i); } op.Release(); } [Test] public void ProvideResource_CanLoadNestedDepdendencies() { m_Provider._BehaviourFlags = ProviderBehaviourFlags.CanProvideWithFailedDependencies; List loadOrder = new List(); m_Provider.ProvideCallback = (pi) => { loadOrder.Add(pi.Location); pi.Complete(0, true, null); }; IResourceLocation i3 = new ResourceLocationBase("3", "3", m_Provider.ProviderId, typeof(object)); IResourceLocation i2 = new ResourceLocationBase("2", "2", m_Provider.ProviderId, typeof(object), i3); IResourceLocation i1 = new ResourceLocationBase("1", "1", m_Provider.ProviderId, typeof(object), i2); var op = m_RM.ProvideResource(i1); m_RM.Update(0.0f); Assert.AreEqual(5, m_RM.OperationCacheCount); Assert.AreSame(i3, loadOrder[0]); Assert.AreSame(i2, loadOrder[1]); Assert.AreSame(i1, loadOrder[2]); op.Release(); } [Test] public void ProvideResource_WhenSomeDependenciesFail_SuccessfulDependenciesRelease() { ResourceLocationBase depLoc1 = new ResourceLocationBase("dep1", "dep1", "unknown provider", typeof(object)); ResourceLocationBase depLoc2 = new ResourceLocationBase("dep2", "dep2", m_Provider.ProviderId, typeof(object)); ResourceLocationBase loc = new ResourceLocationBase("1", "1", m_Provider.ProviderId, typeof(object), depLoc1, depLoc2); var op = m_RM.ProvideResource(loc); m_RM.Update(0.0f); Assert.AreEqual(AsyncOperationStatus.Failed, op.Status); Assert.AreEqual(1, m_Provider.ProvideLog.Count); Assert.AreEqual(1, m_Provider.ReleaseLog.Count); Assert.IsNull(op.Result); } [Test] public void ProvideResources_PartialSuccess_AllowsForSomeFailures() { ResourceLocationBase loc_a = new ResourceLocationBase("dep1", "dep1", "unknown provider", typeof(object)); ResourceLocationBase loc_b = new ResourceLocationBase("dep2", "dep2", m_Provider.ProviderId, typeof(object)); var op = m_RM.ProvideResources( new List {loc_a, loc_b}, false, null); m_RM.Update(0.0f); Assert.AreEqual(AsyncOperationStatus.Failed, op.Status); Assert.AreEqual(1, m_Provider.ProvideLog.Count); Assert.AreEqual(0, m_Provider.ReleaseLog.Count); Assert.IsNotNull(op.Result); Assert.AreEqual(2, op.Result.Count); Assert.IsNull(op.Result[0]); Assert.AreEqual("dep2", op.Result[1]); op.Release(); } [Test] public void ProvideResources_ReleaseDependenciesOnFailure_DoesApplyToLocationDependencies() { ResourceLocationBase depLoc1a = new ResourceLocationBase("dep1a", "dep1a", "unknown provider", typeof(object)); ResourceLocationBase depLoc2a = new ResourceLocationBase("dep2a", "dep2a", m_Provider.ProviderId, typeof(object)); ResourceLocationBase loc_a = new ResourceLocationBase("1", "1", m_Provider.ProviderId, typeof(object), depLoc1a, depLoc2a); ResourceLocationBase depLoc1b = new ResourceLocationBase("dep1b", "dep1b", "unknown provider", typeof(object)); ResourceLocationBase depLoc2b = new ResourceLocationBase("dep2b", "dep2b", m_Provider.ProviderId, typeof(object)); ResourceLocationBase loc_b = new ResourceLocationBase("2", "2", m_Provider.ProviderId, typeof(object), depLoc1b, depLoc2b); var op = m_RM.ProvideResources(new List {loc_a, loc_b}, true, null); m_RM.Update(0.0f); Assert.AreEqual(AsyncOperationStatus.Failed, op.Status); Assert.AreEqual(2, m_Provider.ProvideLog.Count); Assert.AreEqual(2, m_Provider.ReleaseLog.Count); Assert.IsNull(op.Result); } [Test] public void ProvideResources_DoNotReleaseDependenciesOnFailure_DoesApplyToLocationDependencies() { ResourceLocationBase depLoc1a = new ResourceLocationBase("dep1a", "dep1a", "unknown provider", typeof(object)); ResourceLocationBase depLoc2a = new ResourceLocationBase("dep2a", "dep2a", m_Provider.ProviderId, typeof(object)); ResourceLocationBase loc_a = new ResourceLocationBase("1", "1", m_Provider.ProviderId, typeof(object), depLoc1a, depLoc2a); ResourceLocationBase depLoc1b = new ResourceLocationBase("dep1b", "dep1b", "unknown provider", typeof(object)); ResourceLocationBase depLoc2b = new ResourceLocationBase("dep2b", "dep2b", m_Provider.ProviderId, typeof(object)); ResourceLocationBase loc_b = new ResourceLocationBase("2", "2", m_Provider.ProviderId, typeof(object), depLoc1b, depLoc2b); var op = m_RM.ProvideResources(new List {loc_a, loc_b}, false, null); m_RM.Update(0.0f); Assert.AreEqual(AsyncOperationStatus.Failed, op.Status); Assert.AreEqual(2, m_Provider.ProvideLog.Count); Assert.AreEqual(0, m_Provider.ReleaseLog.Count); Assert.IsNull(op.Result); op.Release(); } [Test] public void ProvideResources_DoNotReleaseDependenciesOnFailure_ReleaseAllLocationsAfterCallingRelease() { ResourceLocationBase depLoc1a = new ResourceLocationBase("dep1a", "dep1a", "unknown provider", typeof(object)); ResourceLocationBase depLoc2a = new ResourceLocationBase("dep2a", "dep2a", m_Provider.ProviderId, typeof(object)); ResourceLocationBase loc_a = new ResourceLocationBase("1", "1", m_Provider.ProviderId, typeof(object), depLoc1a, depLoc2a); ResourceLocationBase depLoc1b = new ResourceLocationBase("dep1b", "dep1b", "unknown provider", typeof(object)); ResourceLocationBase depLoc2b = new ResourceLocationBase("dep2b", "dep2b", m_Provider.ProviderId, typeof(object)); ResourceLocationBase loc_b = new ResourceLocationBase("2", "2", m_Provider.ProviderId, typeof(object), depLoc1b, depLoc2b); var op = m_RM.ProvideResources(new List {loc_a, loc_b}, false, null); m_RM.Update(0.0f); Assert.AreEqual(AsyncOperationStatus.Failed, op.Status); Assert.AreEqual(2, m_Provider.ProvideLog.Count); Assert.AreEqual(0, m_Provider.ReleaseLog.Count); Assert.IsNull(op.Result); op.Release(); Assert.AreEqual(2, m_Provider.ReleaseLog.Count); } [Test] public void ProvideResources_ReleaseDependenciesOnFailure_DoesNotOverReleaseAfterCallingRelease() { ResourceLocationBase depLoc1a = new ResourceLocationBase("dep1a", "dep1a", "unknown provider", typeof(object)); ResourceLocationBase depLoc2a = new ResourceLocationBase("dep2a", "dep2a", m_Provider.ProviderId, typeof(object)); ResourceLocationBase loc_a = new ResourceLocationBase("loc_a", "1", m_Provider.ProviderId, typeof(object), depLoc1a, depLoc2a); ResourceLocationBase depLoc1b = new ResourceLocationBase("dep1b", "dep1b", "unknown provider", typeof(object)); ResourceLocationBase depLoc2b = new ResourceLocationBase("dep2b", "dep2b", m_Provider.ProviderId, typeof(object)); ResourceLocationBase loc_b = new ResourceLocationBase("loc_b", "2", m_Provider.ProviderId, typeof(object), depLoc1b, depLoc2b); ResourceLocationBase loc_shared = new ResourceLocationBase("loc_shared", "3", m_Provider.ProviderId, typeof(object), depLoc2a); var op_shared = m_RM.ProvideResources(new List {loc_shared}, true, null); var op = m_RM.ProvideResources(new List {loc_a, loc_b}, true, null); m_RM.Update(0.0f); Assert.AreEqual(AsyncOperationStatus.Failed, op.Status); Assert.AreEqual(AsyncOperationStatus.Succeeded, op_shared.Status); Assert.AreEqual(3, m_Provider.ProvideLog.Count); Assert.AreEqual(1, m_Provider.ReleaseLog.Count); Assert.IsNull(op.Result); op.Release(); Assert.AreEqual(1, m_Provider.ReleaseLog.Count); op_shared.Release(); Assert.AreEqual(3, m_Provider.ReleaseLog.Count); } } }