public async Task ConcurrencyLimitIsRespected(SemaphoreOrder order)
        {
            var cycles = 4;

            for (var cycle = 0; cycle < cycles; cycle++)
            {
                var concurrencyLimit = 10;
                var semaphore        = new OrderedSemaphore(concurrencyLimit: concurrencyLimit, order, Context);

                // Use up the semaphore
                for (var i = 0; i < concurrencyLimit; i++)
                {
                    (await semaphore.WaitAsync(Timeout.InfiniteTimeSpan, CancellationToken.None)).Should().BeTrue();
                }

                // Any more should not be immediatelly successful
                var task = semaphore.WaitAsync(Timeout.InfiniteTimeSpan, CancellationToken.None);
                await Task.Delay(TimeSpan.FromMilliseconds(1));

                task.IsCompleted.Should().BeFalse();

                // Releasing at least one space should free up a space.
                semaphore.Release();
                (await task).Should().BeTrue();

                // Clear the semaphore.
                for (var i = 0; i < concurrencyLimit; i++)
                {
                    semaphore.Release();
                }
            }
        }
        public async Task OrderIsRespected(SemaphoreOrder order)
        {
            var semaphore = new OrderedSemaphore(concurrencyLimit: 1, order, Context);

            var amountTasks = 10;
            var results     = new List <int>();

            // Block to make sure that we have time to create all tasks before they start executing; otherwise LIFO will be flaky.
            await semaphore.WaitAsync(Timeout.InfiniteTimeSpan, CancellationToken.None);

            var tasks = Enumerable.Range(0, amountTasks).Select(async num =>
            {
                (await semaphore.WaitAsync(Timeout.InfiniteTimeSpan, CancellationToken.None)).Should().BeTrue();
                results.Add(num);
                semaphore.Release();
            }).ToArray();

            // Tasks should be blocked.
            results.Count.Should().Be(0);

            // Unblock tasks
            semaphore.Release();

            // Wait for tasks to complete and validate results.
            await Task.WhenAll(tasks);

            results.Count.Should().Be(amountTasks);
            for (var i = 0; i < results.Count; i++)
            {
                var expected = order == SemaphoreOrder.FIFO
                    ? i
                    : amountTasks - i - 1;

                results[i].Should().Be(expected);
            }
        }