コード例 #1
0
#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);
        }
コード例 #2
0
        public void TryReadReturnsTrueWhenBufferIsNotEmpty()
        {
            var sut = new BufferedChannel <int>(1);

            sut.TryWrite(1).ShouldBe(true);
            sut.TryRead(out int _).ShouldBe(true);
        }
コード例 #3
0
        public void TryCompleteReturnsFalseIfChannelIsAlreadyCompleted()
        {
            var sut = new BufferedChannel <int>(2);

            sut.TryComplete().ShouldBe(true);
            sut.TryComplete().ShouldBe(false);
        }
コード例 #4
0
        public void CompletionSuccessfulAfterTryCompleteCalledWithoutException()
        {
            var sut = new BufferedChannel <int>(2);

            sut.TryComplete();
            sut.Completion.Status.ShouldBe(TaskStatus.RanToCompletion);
        }
コード例 #5
0
        public void CompleteThrowsExceptionIfChannelIsAlreadyCompleted()
        {
            var sut = new BufferedChannel <int>(2);

            sut.TryComplete().ShouldBe(true);
            Should.Throw <OperationCanceledException>(() => sut.Complete());
        }
コード例 #6
0
        public void CompletionIsCanceledAfterCancellation()
        {
            var sut = new BufferedChannel <int>(2);

            sut.Terminate();
            sut.Completion.IsCanceled.ShouldBe(true);
            sut.Completion.Exception.ShouldBeNull();
        }
コード例 #7
0
        public void ReadsSynchronouslyWhenThereIsPendingWriteTask()
        {
            var sut       = new BufferedChannel <int>(0);
            var writeTask = sut.WriteAsync(3);

            sut.TryReadSafe(out int item).ShouldBe(true);
            item.ShouldBe(3);
            Should.CompleteIn(writeTask, TimeSpan.FromSeconds(1));
        }
コード例 #8
0
        public void CannotWriteAfterCompletion()
        {
            var sut = new BufferedChannel <int>(2);

            sut.TryWrite(1);
            sut.Complete();
            sut.TryWrite(2).ShouldBe(false);
            Should.Throw <OperationCanceledException>(() => sut.WriteAsync(2));
        }
コード例 #9
0
        public void CompletionHasErrorAfterFail()
        {
            var sut       = new BufferedChannel <int>(2);
            var exception = new ArgumentOutOfRangeException();

            sut.Terminate(exception);
            sut.Completion.IsFaulted.ShouldBe(true);
            sut.Completion.Exception.ShouldNotBe(null);
            sut.Completion.Exception.InnerException.ShouldBe(exception);
        }
コード例 #10
0
        public void FailCancelsWriteTasks()
        {
            var sut   = new BufferedChannel <int>(0);
            var task1 = sut.TryWriteSafeAsync(1);
            var task2 = sut.TryWriteSafeAsync(1);

            sut.Terminate(new InvalidOperationException());
            task1.Result.ShouldBeFalse();
            task2.Result.ShouldBeFalse();
        }
コード例 #11
0
        public void FailCancelsReadTasks()
        {
            var sut   = new BufferedChannel <int>(0);
            var task1 = sut.TryReadAsync();
            var task2 = sut.TryReadAsync();

            sut.Terminate(new InvalidOperationException());
            Should.Throw <InvalidOperationException>(task1.AsTask(), Timeout1Sec);
            Should.Throw <InvalidOperationException>(task2.AsTask(), Timeout1Sec);
        }
コード例 #12
0
        public void CompleteAbortsPendingReadTasks()
        {
            var sut       = new BufferedChannel <int>(0);
            var readTask1 = sut.ReadAsync();
            var readTask2 = sut.ReadAsync();

            sut.Complete();
            Should.Throw <TaskCanceledException>(() => readTask1.AsTask(), Timeout1Sec);
            Should.Throw <TaskCanceledException>(() => readTask2.AsTask(), Timeout1Sec);
        }
コード例 #13
0
        public void CancellationCancelsReadTasks()
        {
            var sut   = new BufferedChannel <int>(0);
            var task1 = sut.TryReadSafeAsync();
            var task2 = sut.TryReadSafeAsync();

            sut.Terminate();
            task1.Result.HasValue.ShouldBeFalse();
            task2.Result.HasValue.ShouldBeFalse();
        }
コード例 #14
0
        public void ResetCancelsWriteTasks()
        {
            var sut        = new BufferedChannel <int>(0);
            var writeTask1 = sut.TryWriteSafeAsync(1);
            var writeTask2 = sut.TryWriteSafeAsync(2);

            sut.Reset();
            writeTask1.Result.ShouldBeFalse();
            writeTask2.Result.ShouldBeFalse();
        }
コード例 #15
0
        public void CancellationCancelsWriteTasks()
        {
            var sut   = new BufferedChannel <int>(0);
            var task1 = sut.TryWriteSafeAsync(1);
            var task2 = sut.TryWriteSafeAsync(1);

            sut.Terminate();
            task1.Result.ShouldBeFalse();
            task2.Result.ShouldBeFalse();
        }
コード例 #16
0
        public void FailCancelsWriteTasks()
        {
            var sut   = new BufferedChannel <int>(0);
            var task1 = sut.TryWriteAsync(1);
            var task2 = sut.TryWriteAsync(1);

            sut.Terminate(new InvalidOperationException());
            Should.Throw <InvalidOperationException>(task1, Timeout1Sec);
            Should.Throw <InvalidOperationException>(task2, Timeout1Sec);
        }
コード例 #17
0
        public void CancellationCancelsWriteTasks()
        {
            var sut   = new BufferedChannel <int>(0);
            var task1 = sut.TryWriteAsync(1);
            var task2 = sut.TryWriteAsync(1);

            sut.Terminate();
            Should.Throw <OperationCanceledException>(task1, Timeout1Sec);
            Should.Throw <OperationCanceledException>(task2, Timeout1Sec);
        }
コード例 #18
0
        public void WritesSynchronouslyWhenThereIsPendingReadTask()
        {
            var sut      = new BufferedChannel <int>(0);
            var readTask = sut.ReadAsync();

            sut.TryWriteSafe(1).ShouldBe(false);
            sut.WriteAsync(1).ShouldCompleteIn(Timeout1Sec);
            Should.CompleteIn(readTask.AsTask(), TimeSpan.FromSeconds(1));
            readTask.Result.ShouldBe(1);
        }
コード例 #19
0
        public void CancellationCancelsReadTasks()
        {
            var sut   = new BufferedChannel <int>(0);
            var task1 = sut.TryReadAsync();
            var task2 = sut.TryReadAsync();

            sut.Terminate();
            Should.Throw <OperationCanceledException>(task1.AsTask(), Timeout1Sec);
            Should.Throw <OperationCanceledException>(task2.AsTask(), Timeout1Sec);
        }
コード例 #20
0
        public void ResetCancelsReadTasks()
        {
            var sut       = new BufferedChannel <int>(0);
            var readTask1 = sut.TryReadSafeAsync();
            var readTask2 = sut.TryReadSafeAsync();

            sut.Reset();
            readTask1.Result.HasValue.ShouldBeFalse();
            readTask2.Result.HasValue.ShouldBeFalse();
        }
コード例 #21
0
        public void CompleteAbortsPendingWriteTasks()
        {
            var sut        = new BufferedChannel <int>(0);
            var writeTask1 = sut.WriteAsync(1);
            var writeTask2 = sut.WriteAsync(2);

            sut.Complete();
            Should.Throw <TaskCanceledException>(() => writeTask1, Timeout1Sec);
            Should.Throw <TaskCanceledException>(() => writeTask2, Timeout1Sec);
        }
コード例 #22
0
        public void WritesSynchronouslyWhenBufferHasSpace()
        {
            var sut = new BufferedChannel <int>(2);

            sut.TryWrite(1).ShouldBe(true);
            sut.TryWrite(2).ShouldBe(true);
            sut.TryWrite(3).ShouldBe(false);
            sut.TryRead(out int item).ShouldBe(true);
            item.ShouldBe(1);
            sut.TryWrite(4).ShouldBe(true);
        }
コード例 #23
0
        public void TerminatesOnWriteTimeout()
        {
            var sut = new BufferedChannel <int>(1, Timeout100Ms);

            Should.NotThrow(sut.WriteAsync(1), Timeout1Sec);
            sut.TryWrite(1).ShouldBe(false);
            Should.Throw <ChannelWriteTimeoutException>(sut.WaitWriteAvailableAsync(), Timeout1Sec);
            Should.Throw <ChannelWriteTimeoutException>(sut.Out.Completion, Timeout1Sec);
            sut.TryRead(out _).ShouldBe(true);
            Should.Throw <Exception>(sut.Completion, Timeout1Sec);
        }
コード例 #24
0
        public void CancellationCompletesChannel()
        {
            var sut = new BufferedChannel <int>(2);

            sut.TryWrite(1);
            sut.TryWrite(2);
            sut.Terminate();
            sut.Completion.IsCompleted.ShouldBe(false);
            sut.TryRead(out int _).ShouldBe(true);
            sut.TryRead(out int _).ShouldBe(true);
            Should.Throw <TaskCanceledException>(sut.TryReadAsync().AsTask(), Timeout1Sec);
            sut.Completion.IsCanceled.ShouldBeTrue();
        }
コード例 #25
0
        public void TerminationCompletesChannelWithException()
        {
            var sut = new BufferedChannel <int>(2);

            sut.TryWrite(1);
            sut.TryWrite(2);
            sut.Terminate(new InvalidOperationException());
            sut.Completion.IsCompleted.ShouldBe(false);
            sut.TryRead(out int _).ShouldBe(true);
            sut.TryRead(out int _).ShouldBe(true);
            Should.Throw <InvalidOperationException>(() => sut.TryReadAsync().AsTask(), Timeout1Sec);
            sut.Completion.IsFaulted.ShouldBeTrue();
        }
コード例 #26
0
        public void WriteAsyncCompletesWhenThereIsBufferSpaceAvailable()
        {
            var sut = new BufferedChannel <int>(1);

            Should.CompleteIn(sut.WriteAsync(1), Timeout1Sec);
            var writeTask = sut.WriteAsync(2);

            writeTask.IsCompleted.ShouldBe(false);
            sut.TryRead(out var item).ShouldBe(true);
            item.ShouldBe(1);
            Should.CompleteIn(writeTask, Timeout1Sec);
            sut.TryRead(out item).ShouldBe(true);
            item.ShouldBe(2);
        }
コード例 #27
0
        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());
        }
コード例 #28
0
        public void FailCompletesChannelEvenIfBufferIsNotEmpty()
        {
            var sut = new BufferedChannel <int>(2);

            sut.TryWriteSafe(1);
            sut.TryWriteSafe(2);
            sut.Terminate(new InvalidOperationException());
            sut.Completion.IsCompleted.ShouldBe(false);
            sut.TryReadSafe(out int _).ShouldBe(true);
            sut.TryReadSafe(out int _).ShouldBe(true);
            var result = Should.CompleteIn(() => sut.TryReadSafeAsync().AsTask(), TimeSpan.FromSeconds(1));

            result.HasValue.ShouldBeFalse();
            sut.Completion.IsFaulted.ShouldBeTrue();
        }
コード例 #29
0
        public void CancellationCompletesChannel()
        {
            var sut = new BufferedChannel <int>(2);

            sut.TryWriteSafe(1);
            sut.TryWriteSafe(2);
            sut.Terminate();
            sut.Completion.IsCompleted.ShouldBe(false);
            sut.TryReadSafe(out int _).ShouldBe(true);
            sut.TryReadSafe(out int _).ShouldBe(true);
            var result = sut.TryReadSafeAsync().ShouldCompleteIn(Timeout1Sec);

            result.HasValue.ShouldBeFalse();
            sut.Completion.IsCanceled.ShouldBeTrue();
        }
コード例 #30
0
        public async Task SlidesWriteTimeoutAfterWriteAvailable()
        {
            var sut = new BufferedChannel <int>(1, Timeout50Ms);

            sut.TryWrite(1).ShouldBe(true);
            await Task.Delay(Timeout10Ms).ConfigureAwait(false);

            sut.TryRead(out _).ShouldBe(true);
            await Task.Delay(Timeout100Ms).ConfigureAwait(false);

            sut.Out.Completion.IsCompleted.ShouldBeFalse();
            Should.NotThrow(() => sut.WriteAsync(1), Timeout1Sec);
            await Task.Delay(Timeout10Ms).ConfigureAwait(false);

            sut.TryRead(out _).ShouldBe(true);
        }