public override async Task GetStatisticsWithZeroPermitCount()
        {
            var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions
            {
                PermitLimit          = 100,
                QueueProcessingOrder = QueueProcessingOrder.OldestFirst,
                QueueLimit           = 50
            });
            var lease = limiter.AttemptAcquire(0);

            Assert.True(lease.IsAcquired);
            Assert.Equal(1, limiter.GetStatistics().TotalSuccessfulLeases);
            Assert.Equal(100, limiter.GetStatistics().CurrentAvailablePermits);

            lease = await limiter.AcquireAsync(0);

            Assert.True(lease.IsAcquired);
            Assert.Equal(2, limiter.GetStatistics().TotalSuccessfulLeases);
            Assert.Equal(100, limiter.GetStatistics().CurrentAvailablePermits);

            lease = limiter.AttemptAcquire(100);
            Assert.True(lease.IsAcquired);
            Assert.Equal(3, limiter.GetStatistics().TotalSuccessfulLeases);
            Assert.Equal(0, limiter.GetStatistics().CurrentAvailablePermits);

            var lease2 = limiter.AttemptAcquire(0);

            Assert.False(lease2.IsAcquired);
            Assert.Equal(3, limiter.GetStatistics().TotalSuccessfulLeases);
            Assert.Equal(1, limiter.GetStatistics().TotalFailedLeases);
            Assert.Equal(0, limiter.GetStatistics().CurrentAvailablePermits);
        }
        public override void GetStatisticsReturnsNewInstances()
        {
            var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions
            {
                PermitLimit          = 1,
                QueueProcessingOrder = QueueProcessingOrder.OldestFirst,
                QueueLimit           = 1
            });

            var stats = limiter.GetStatistics();

            Assert.Equal(1, stats.CurrentAvailablePermits);

            var lease = limiter.AttemptAcquire(1);

            var stats2 = limiter.GetStatistics();

            Assert.NotSame(stats, stats2);
            Assert.Equal(1, stats.CurrentAvailablePermits);
            Assert.Equal(0, stats2.CurrentAvailablePermits);
        }
        public override async Task CanCancelAcquireAsyncBeforeQueuing()
        {
            var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions
            {
                PermitLimit          = 1,
                QueueProcessingOrder = QueueProcessingOrder.OldestFirst,
                QueueLimit           = 1
            });
            var lease = limiter.AttemptAcquire(1);

            Assert.True(lease.IsAcquired);

            var cts = new CancellationTokenSource();

            cts.Cancel();

            var ex = await Assert.ThrowsAsync <TaskCanceledException>(() => limiter.AcquireAsync(1, cts.Token).AsTask());

            Assert.Equal(cts.Token, ex.CancellationToken);

            lease.Dispose();

            Assert.Equal(1, limiter.GetStatistics()?.CurrentAvailablePermits);
        }
        public override async Task GetStatisticsHasCorrectValues()
        {
            var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions
            {
                PermitLimit          = 100,
                QueueProcessingOrder = QueueProcessingOrder.OldestFirst,
                QueueLimit           = 50
            });

            var stats = limiter.GetStatistics();

            Assert.Equal(100, stats.CurrentAvailablePermits);
            Assert.Equal(0, stats.CurrentQueuedCount);
            Assert.Equal(0, stats.TotalFailedLeases);
            Assert.Equal(0, stats.TotalSuccessfulLeases);

            // success from acquire + available
            var lease1 = limiter.AttemptAcquire(60);

            stats = limiter.GetStatistics();
            Assert.Equal(40, stats.CurrentAvailablePermits);
            Assert.Equal(0, stats.CurrentQueuedCount);
            Assert.Equal(0, stats.TotalFailedLeases);
            Assert.Equal(1, stats.TotalSuccessfulLeases);

            // queue
            var lease2Task = limiter.AcquireAsync(50);

            stats = limiter.GetStatistics();
            Assert.Equal(40, stats.CurrentAvailablePermits);
            Assert.Equal(50, stats.CurrentQueuedCount);
            Assert.Equal(0, stats.TotalFailedLeases);
            Assert.Equal(1, stats.TotalSuccessfulLeases);

            // failure from wait
            var lease3 = await limiter.AcquireAsync(1);

            Assert.False(lease3.IsAcquired);
            stats = limiter.GetStatistics();
            Assert.Equal(40, stats.CurrentAvailablePermits);
            Assert.Equal(50, stats.CurrentQueuedCount);
            Assert.Equal(1, stats.TotalFailedLeases);
            Assert.Equal(1, stats.TotalSuccessfulLeases);

            // failure from acquire
            var lease4 = limiter.AttemptAcquire(100);

            Assert.False(lease4.IsAcquired);
            stats = limiter.GetStatistics();
            Assert.Equal(40, stats.CurrentAvailablePermits);
            Assert.Equal(50, stats.CurrentQueuedCount);
            Assert.Equal(2, stats.TotalFailedLeases);
            Assert.Equal(1, stats.TotalSuccessfulLeases);

            lease1.Dispose();
            await lease2Task;

            // success from wait + available + queue
            stats = limiter.GetStatistics();
            Assert.Equal(50, stats.CurrentAvailablePermits);
            Assert.Equal(0, stats.CurrentQueuedCount);
            Assert.Equal(2, stats.TotalFailedLeases);
            Assert.Equal(2, stats.TotalSuccessfulLeases);
        }