public void Closing_DisallowsFurtherRequests()
        {
            var exceptions = new ExceptionSink();
            var requests   = new RequestRunner(TaskScheduler.Default, exceptions);

            requests.Close(() => Task.Delay(50));

            Assert.That(
                () => requests.Perform(() => Task.CompletedTask),
                Throws.Exception.InstanceOf <RequestRunnerClosedException>());
        }
        public async Task Closing_IsAwaitable()
        {
            var exceptions = new ExceptionSink();
            var requests   = new RequestRunner(TaskScheduler.Default, exceptions);

            bool completed = false;

            await requests.Close(() => Task.Delay(500).ContinueWith(_ => completed = true));

            Assert.That(completed);
        }
        public async Task Closes_Immediately_WhenNoneWaiting()
        {
            var exceptions = new ExceptionSink();
            var requests   = new RequestRunner(TaskScheduler.Default, exceptions);

            bool closed = false;

            requests.Close(() => {
                closed = true;
                return(Task.CompletedTask);
            });

            await requests.WhenIdle();

            exceptions.RethrowAll();

            Assert.That(closed, Is.True);
        }
        public async Task WhenIdle_AwaitsCompletionOfDeactivation()
        {
            var exceptions = new ExceptionSink();
            var requests   = new RequestRunner(TaskScheduler.Default, exceptions);

            bool closed = false;

            requests.Close(async() => {
                await Task.Delay(100);
                closed = true;
            });

            await requests.WhenIdle();

            exceptions.RethrowAll();

            Assert.That(closed, Is.True);
        }
        public async Task Closing_Performed()
        {
            var exceptions = new ExceptionSink();
            var requests   = new RequestRunner(TaskScheduler.Default, exceptions);

            bool closed = false;

            requests.PerformAndForget(() => Task.Delay(50));

            requests.Close(() => {
                closed = true;
                return(Task.CompletedTask);
            });

            await requests.WhenIdle();

            exceptions.RethrowAll();

            Assert.That(closed, Is.True);
        }
        public async Task Closes_OnlyAfter_PreviouslyScheduledPerformances()
        {
            var exceptions = new ExceptionSink();
            var requests   = new RequestRunner(TaskScheduler.Default, exceptions);

            int calls = 0;

            Enumerable.Range(0, 100)
            .Select(_ => requests.Perform(async() => {
                Interlocked.Increment(ref calls);
                await Task.Delay(30);
                Interlocked.Decrement(ref calls);
            }))
            .ToArray();

            requests.Close(() => {
                Assert.That(calls, Is.EqualTo(0));
                return(Task.CompletedTask);
            });

            await requests.WhenIdle();

            exceptions.RethrowAll();
        }