public void TryCompleteReturnsFalseIfChannelIsAlreadyCompleted()
        {
            var sut = new BufferedChannel <int>(2);

            sut.TryComplete().ShouldBe(true);
            sut.TryComplete().ShouldBe(false);
        }
        public void CompleteThrowsExceptionIfChannelIsAlreadyCompleted()
        {
            var sut = new BufferedChannel <int>(2);

            sut.TryComplete().ShouldBe(true);
            Should.Throw <OperationCanceledException>(() => sut.Complete());
        }
#pragma warning disable xUnit1026 // Theory methods should use all of their parameters
        public void CanWriteAndReadFromSeveralThreadsConcurrently(int writeThreads, int readThreads, int bufferSize)
#pragma warning restore xUnit1026 // Theory methods should use all of their parameters
        {
            var writeCount = readThreads * 100;
            var readCount  = writeThreads * 100;
            var sut        = new BufferedChannel <int>(bufferSize);

            async Task WriteWorker()
            {
                for (var i = 0; i < writeCount; i++)
                {
                    await sut.WriteAsync(i).ConfigureAwait(false);
                }
            }

            async Task ReadWorker()
            {
                for (var i = 0; i < readCount; i++)
                {
                    await sut.ReadAsync().ConfigureAwait(false);
                }
            }

            var writeTasks = Enumerable.Range(0, writeThreads).Select(_ => Task.Run(WriteWorker));
            var readTasks  = Enumerable.Range(0, readThreads).Select(_ => Task.Run(ReadWorker));
            var allTasks   = writeTasks.Concat(readTasks).ToArray();

            Task.WhenAll(allTasks).ShouldCompleteIn(Timeout10Sec);

            sut.TryRead(out int _).ShouldBe(false);
            sut.TryComplete().ShouldBe(true);
        }
        public void CompletionSuccessfulAfterTryCompleteCalledWithoutException()
        {
            var sut = new BufferedChannel <int>(2);

            sut.TryComplete();
            sut.Completion.Status.ShouldBe(TaskStatus.RanToCompletion);
        }
        public void CanReadAfterCompletionUntilBufferIsEmpty()
        {
            var sut = new BufferedChannel <int>(2);

            sut.TryWrite(1);
            sut.TryWrite(2);
            sut.TryComplete();
            sut.Completion.IsCompleted.ShouldBe(false);
            sut.TryRead(out int _).ShouldBe(true);
            sut.Completion.IsCompleted.ShouldBe(false);
            sut.TryRead(out int _).ShouldBe(true);
            sut.Completion.IsCompleted.ShouldBe(true);
            sut.TryRead(out int _).ShouldBe(false);
            Should.Throw <TaskCanceledException>(() => sut.ReadAsync().AsTask());
        }