public void WhenMultipleBundlesLoading_BandwidthIsAmortizedAcrossAllBundles([Values(true, false)] bool localBundles)
        {
            const int   kBundleCount = 4;
            const int   kLocalBW     = 800;
            const int   kRemoteBW    = 2000;
            const int   kHeaderSize  = 2000;
            const int   kDataSize    = 4000;
            const float kTimeSlize   = 0.5f;

            int kUpdatesForRemoteDownload = (int)Math.Ceiling((((kDataSize * kBundleCount) / kRemoteBW) / kTimeSlize));
            int kUpdatesLocalLoad         = (int)Math.Ceiling((((kHeaderSize * kBundleCount) / kLocalBW) / kTimeSlize));

            ResourceManager rm = new ResourceManager();

            rm.CallbackHooksEnabled = false;

            VirtualAssetBundleRuntimeData data      = new VirtualAssetBundleRuntimeData(kLocalBW, kRemoteBW);
            List <ResourceLocationBase>   locations = CreateBundleSet(data, kBundleCount, localBundles, kDataSize, kHeaderSize);
            VirtualAssetBundleProvider    provider  = new VirtualAssetBundleProvider(data);

            rm.ResourceProviders.Add(provider);
            var ops = new List <AsyncOperationHandle <VirtualAssetBundle> >();

            foreach (IResourceLocation loc in locations)
            {
                ops.Add(rm.ProvideResource <VirtualAssetBundle>(loc));
            }


            int totalUpdatesNeeded = kUpdatesLocalLoad + (localBundles ? 0 : kUpdatesForRemoteDownload);

            for (int i = 0; i < totalUpdatesNeeded; i++)
            {
                foreach (AsyncOperationHandle <VirtualAssetBundle> op in ops)
                {
                    Assert.IsFalse(op.IsDone);
                    Assert.Less(op.PercentComplete, 1.0f);
                }
                provider.Update(kTimeSlize);
            }

            foreach (var op in ops)
            {
                Assert.IsTrue(op.IsDone);
                Assert.AreEqual(1.0f, op.PercentComplete);
                Assert.AreEqual(AsyncOperationStatus.Succeeded, op.Status);
                op.Release();
            }

            Assert.Zero(rm.OperationCacheCount);
            rm.Dispose();
        }
        public IEnumerator WhenLoadingUnknownBundle_OperationFailsWithMessage()
        {
            ResourceManager rm = new ResourceManager();

            rm.CallbackHooksEnabled = false;

            VirtualAssetBundleRuntimeData data     = new VirtualAssetBundleRuntimeData();
            VirtualAssetBundleProvider    provider = new VirtualAssetBundleProvider(data);

            rm.ResourceProviders.Add(provider);
            ResourceLocationBase unknownLocation = new ResourceLocationBase("unknown", "unknown", typeof(AssetBundleProvider).FullName, typeof(IAssetBundleResource));
            var op = rm.ProvideResource <VirtualAssetBundle>(unknownLocation);

            // wait for delayed action manager.
            // TODO: refactor delayed action manager so we can pump it instead of waiting a frame
            yield return(null);

            Assert.AreEqual(AsyncOperationStatus.Failed, op.Status);
            StringAssert.Contains("Unable to unload virtual bundle", op.OperationException.Message);
            op.Release();

            Assert.Zero(rm.OperationCacheCount);
            rm.Dispose();
        }