public void TestDoubleAsyncLoad()
        {
            var loadable   = new DelayedTestBoxAsync();
            var loadTarget = new LoadTarget(loadable);

            Assert.DoesNotThrow(() =>
            {
                runGameWithLogic(g =>
                {
                    g.Add(loadTarget);
                    loadTarget.PerformAsyncLoad();
                    loadTarget.PerformAsyncLoad(false);
                }, g => loadable.Parent == loadTarget);
            });
        }
        public void TestDoubleAsyncAddFails()
        {
            Assert.Throws <InvalidOperationException>(() =>
            {
                runGameWithLogic(g =>
                {
                    var loadable   = new DelayedTestBoxAsync();
                    var loadTarget = new LoadTarget(loadable);

                    g.Add(loadTarget);

                    loadTarget.PerformAsyncLoad();
                    loadTarget.PerformAsyncLoad();
                });
            });
        }
        public void TestLoadIntoInvalidTarget()
        {
            var loadable   = new DelayedTestBoxAsync();
            var loadTarget = new LoadTarget(loadable);

            Assert.Throws <InvalidOperationException>(() => loadTarget.PerformAsyncLoad());
        }
        public void TestTargetDisposedDuringAsyncLoad()
        {
            Assert.Throws <ObjectDisposedException>(() =>
            {
                runGameWithLogic(g =>
                {
                    var loadable   = new DelayedTestBoxAsync();
                    var loadTarget = new LoadTarget(loadable);

                    g.Add(loadTarget);

                    loadTarget.PerformAsyncLoad();

                    while (loadable.LoadState < LoadState.Loading)
                    {
                        Thread.Sleep(1);
                    }

                    g.Dispose();
                });
            });
        }
        public void TestDisposeAfterLoad()
        {
            Assert.DoesNotThrow(() =>
            {
                var loadTarget = new LoadTarget(new DelayedTestBoxAsync());

                bool allowDispose        = false;
                bool disposeTriggered    = false;
                bool updatedAfterDispose = false;

                runGameWithLogic(g =>
                {
                    g.Add(loadTarget);
                    loadTarget.PerformAsyncLoad().ContinueWith(t => allowDispose = true);
                }, g =>
                {
                    // The following code is done here for a very specific reason, but can occur naturally in normal use
                    // This delegate is essentially the first item in the game's scheduler, so it will always run PRIOR to the async callback

                    if (disposeTriggered)
                    {
                        updatedAfterDispose = true;
                    }

                    if (allowDispose)
                    {
                        // Async load has complete, the callback has been scheduled but NOT run yet
                        // Dispose the parent container - this is done by clearing the game
                        g.Clear(true);
                        disposeTriggered = true;
                    }

                    // After disposing the parent, one update loop is required
                    return(updatedAfterDispose);
                });
            });
        }