public void WaitForNewItemsAsync_should_not_block_after_partial_drain()
        {
            for (var i = 0; i < Capacity; i++)
            {
                queue.TryAdd(i.ToString()).Should().BeTrue();
            }

            queue.WaitForNewItemsAsync().Wait(1.Seconds()).Should().BeTrue();

            queue.Drain(drainResult, 0, 1);

            queue.WaitForNewItemsAsync().Wait(1.Seconds()).Should().BeTrue();
        }
        public void Should_not_have_race_between_Add_and_Drain_that_turns_queue_wait_task_to_inconsistent_state()
        {
            for (var j = 0; j < 10; ++j)
            {
                var queue = new ConcurrentBoundedQueue <object>(100);
                var o     = new object();

                var addTask = Task.Run(
                    () =>
                {
                    for (var i = 0; i < 1000000; i++)
                    {
                        if (!queue.TryAdd(o))
                        {
                            i--;
                        }
                    }
                });

                var drainTask = Task.Run(
                    () =>
                {
                    var arr = new object[1000];
                    while (true)
                    {
                        var drained = queue.Drain(arr, 0, arr.Length);
                        if (drained == 0 && addTask.IsCompleted)
                        {
                            return;
                        }
                    }
                });

                Task.WhenAll(drainTask, addTask).GetAwaiter().GetResult();

                if (queue.WaitForNewItemsAsync().IsCompleted&& queue.Count == 0)
                {
                    Assert.Fail("Queue is broken: TryWaitForNewItemsAsync is completed, but queue is empty.");
                }
            }
        }