Esempio n. 1
0
        public void ProducingStartAndProducingCompleteCanBeCalledAfterConnectionClose()
        {
            var mockLibuv = new MockLibuv();

            using (var memory = new MemoryPool())
                using (var kestrelEngine = new KestrelEngine(mockLibuv, new TestServiceContext()))
                {
                    kestrelEngine.Start(count: 1);

                    var kestrelThread = kestrelEngine.Threads[0];
                    var socket        = new MockSocket(mockLibuv, kestrelThread.Loop.ThreadId, new TestKestrelTrace());
                    var trace         = new KestrelTrace(new TestKestrelTrace());
                    var ltp           = new LoggingThreadPool(trace);
                    var connection    = new MockConnection();
                    var socketOutput  = new SocketOutput(kestrelThread, socket, memory, connection, "0", trace, ltp, new Queue <UvWriteReq>());

                    // Close SocketOutput
                    var cleanupTask = socketOutput.WriteAsync(
                        default(ArraySegment <byte>), default(CancellationToken), socketDisconnect: true);

                    Assert.True(connection.SocketClosed.Wait(1000));

                    var start = socketOutput.ProducingStart();

                    Assert.True(start.IsDefault);
                    // ProducingComplete should not throw given a default iterator
                    socketOutput.ProducingComplete(start);
                }
        }
Esempio n. 2
0
        public void ProducingStartAndProducingCompleteCanBeUsedDirectly()
        {
            int nBuffers  = 0;
            var nBufferWh = new ManualResetEventSlim();

            var mockLibuv = new MockLibuv
            {
                OnWrite = (socket, buffers, triggerCompleted) =>
                {
                    nBuffers = buffers;
                    nBufferWh.Set();
                    triggerCompleted(0);
                    return(0);
                }
            };

            using (var memory = new MemoryPool())
                using (var kestrelEngine = new KestrelEngine(mockLibuv, new TestServiceContext()))
                {
                    kestrelEngine.Start(count: 1);

                    var kestrelThread = kestrelEngine.Threads[0];
                    var socket        = new MockSocket(mockLibuv, kestrelThread.Loop.ThreadId, new TestKestrelTrace());
                    var trace         = new KestrelTrace(new TestKestrelTrace());
                    var ltp           = new LoggingThreadPool(trace);
                    var socketOutput  = new SocketOutput(kestrelThread, socket, memory, new MockConnection(), "0", trace, ltp, new Queue <UvWriteReq>());

                    // block 1
                    var start = socketOutput.ProducingStart();
                    start.Block.End = start.Block.Data.Offset + start.Block.Data.Count;

                    // block 2
                    var block2 = memory.Lease();
                    block2.End       = block2.Data.Offset + block2.Data.Count;
                    start.Block.Next = block2;

                    var end = new MemoryPoolIterator(block2, block2.End);

                    socketOutput.ProducingComplete(end);

                    // A call to Write is required to ensure a write is scheduled
                    socketOutput.WriteAsync(default(ArraySegment <byte>), default(CancellationToken));

                    Assert.True(nBufferWh.Wait(1000));
                    Assert.Equal(2, nBuffers);

                    // Cleanup
                    var cleanupTask = socketOutput.WriteAsync(
                        default(ArraySegment <byte>), default(CancellationToken), socketDisconnect: true);
                }
        }
Esempio n. 3
0
        public void WritesDontCompleteImmediatelyWhenTooManyBytesIncludingNonImmediateAreAlreadyPreCompleted()
        {
            // This should match _maxBytesPreCompleted in SocketOutput
            var maxBytesPreCompleted = 65536;
            var completeQueue        = new Queue <Action <int> >();
            var writeRequestedWh     = new ManualResetEventSlim();

            // Arrange
            var mockLibuv = new MockLibuv
            {
                OnWrite = (socket, buffers, triggerCompleted) =>
                {
                    completeQueue.Enqueue(triggerCompleted);
                    writeRequestedWh.Set();
                    return(0);
                }
            };

            using (var memory = new MemoryPool())
                using (var kestrelEngine = new KestrelEngine(mockLibuv, new TestServiceContext()))
                {
                    kestrelEngine.Start(count: 1);

                    var kestrelThread = kestrelEngine.Threads[0];
                    var socket        = new MockSocket(mockLibuv, kestrelThread.Loop.ThreadId, new TestKestrelTrace());
                    var trace         = new KestrelTrace(new TestKestrelTrace());
                    var ltp           = new LoggingThreadPool(trace);
                    var socketOutput  = new SocketOutput(kestrelThread, socket, memory, new MockConnection(), "0", trace, ltp, new Queue <UvWriteReq>());

                    var bufferSize            = maxBytesPreCompleted / 2;
                    var data                  = new byte[bufferSize];
                    var halfWriteBehindBuffer = new ArraySegment <byte>(data, 0, bufferSize);

                    // Act
                    var writeTask1 = socketOutput.WriteAsync(halfWriteBehindBuffer, default(CancellationToken));
                    // Assert
                    // The first write should pre-complete since it is <= _maxBytesPreCompleted.
                    Assert.Equal(TaskStatus.RanToCompletion, writeTask1.Status);
                    Assert.True(writeRequestedWh.Wait(1000));
                    writeRequestedWh.Reset();

                    // Add more bytes to the write-behind buffer to prevent the next write from
                    var iter = socketOutput.ProducingStart();
                    iter.CopyFrom(halfWriteBehindBuffer);
                    socketOutput.ProducingComplete(iter);

                    // Act
                    var writeTask2 = socketOutput.WriteAsync(halfWriteBehindBuffer, default(CancellationToken));
                    // Assert
                    // Too many bytes are already pre-completed for the fourth write to pre-complete.
                    Assert.True(writeRequestedWh.Wait(1000));
                    Assert.False(writeTask2.IsCompleted);

                    // 2 calls have been made to uv_write
                    Assert.Equal(2, completeQueue.Count);

                    // Act
                    completeQueue.Dequeue()(0);

                    // Assert
                    // Finishing the first write should allow the second write to pre-complete.
                    Assert.True(writeTask2.Wait(1000));

                    // Cleanup
                    var cleanupTask = socketOutput.WriteAsync(
                        default(ArraySegment <byte>), default(CancellationToken), socketDisconnect: true);

                    foreach (var triggerCompleted in completeQueue)
                    {
                        triggerCompleted(0);
                    }
                }
        }