Adding some tests for Http11
Requires updating to test utilities Adding initial EventSource to try to see some order of events
This commit is contained in:
parent
660babcd7f
commit
9c7cb6a958
|
|
@ -54,6 +54,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
|
||||
private readonly UvStreamHandle _socket;
|
||||
private Frame _frame;
|
||||
long _connectionId;
|
||||
|
||||
public Connection(ListenerContext context, UvStreamHandle socket) : base(context)
|
||||
{
|
||||
|
|
@ -63,6 +64,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
|
||||
public void Start()
|
||||
{
|
||||
KestrelTrace.Log.ConnectionStart(_connectionId);
|
||||
|
||||
SocketInput = new SocketInput(Memory);
|
||||
SocketOutput = new SocketOutput(Thread, _socket);
|
||||
_frame = new Frame(this);
|
||||
|
|
@ -85,6 +88,11 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
if (nread == 0)
|
||||
{
|
||||
SocketInput.RemoteIntakeFin = true;
|
||||
KestrelTrace.Log.ConnectionReadFin(_connectionId);
|
||||
}
|
||||
else
|
||||
{
|
||||
KestrelTrace.Log.ConnectionRead(_connectionId, nread);
|
||||
}
|
||||
|
||||
_frame.Consume();
|
||||
|
|
@ -92,11 +100,13 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
|
||||
void IConnectionControl.Pause()
|
||||
{
|
||||
KestrelTrace.Log.ConnectionPause(_connectionId);
|
||||
_socket.ReadStop();
|
||||
}
|
||||
|
||||
void IConnectionControl.Resume()
|
||||
{
|
||||
KestrelTrace.Log.ConnectionResume(_connectionId);
|
||||
_socket.ReadStart(_allocCallback, _readCallback, this);
|
||||
}
|
||||
|
||||
|
|
@ -105,25 +115,37 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
switch (endType)
|
||||
{
|
||||
case ProduceEndType.SocketShutdownSend:
|
||||
KestrelTrace.Log.ConnectionWriteFin(_connectionId, 0);
|
||||
Thread.Post(
|
||||
x =>
|
||||
{
|
||||
KestrelTrace.Log.ConnectionWriteFin(_connectionId, 1);
|
||||
var self = (Connection)x;
|
||||
var shutdown = new UvShutdownReq();
|
||||
shutdown.Init(self.Thread.Loop);
|
||||
shutdown.Shutdown(self._socket, (req, status, state) => req.Dispose(), null);
|
||||
shutdown.Shutdown(self._socket, (req, status, state) =>
|
||||
{
|
||||
KestrelTrace.Log.ConnectionWriteFin(_connectionId, 1);
|
||||
req.Dispose();
|
||||
}, null);
|
||||
},
|
||||
this);
|
||||
break;
|
||||
case ProduceEndType.ConnectionKeepAlive:
|
||||
KestrelTrace.Log.ConnectionKeepAlive(_connectionId);
|
||||
_frame = new Frame(this);
|
||||
Thread.Post(
|
||||
x => ((Frame)x).Consume(),
|
||||
_frame);
|
||||
break;
|
||||
case ProduceEndType.SocketDisconnect:
|
||||
KestrelTrace.Log.ConnectionDisconnect(_connectionId);
|
||||
Thread.Post(
|
||||
x => ((UvHandle)x).Dispose(),
|
||||
x =>
|
||||
{
|
||||
KestrelTrace.Log.ConnectionStop(_connectionId);
|
||||
((UvHandle)x).Dispose();
|
||||
},
|
||||
_socket);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -321,8 +321,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
ConnectionControl.End(ProduceEndType.SocketShutdownSend);
|
||||
}
|
||||
|
||||
_messageBody.Drain(() =>
|
||||
ConnectionControl.End(_keepAlive ? ProduceEndType.ConnectionKeepAlive : ProduceEndType.SocketDisconnect));
|
||||
//NOTE: must finish reading request body
|
||||
ConnectionControl.End(_keepAlive ? ProduceEndType.ConnectionKeepAlive : ProduceEndType.SocketDisconnect);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3,13 +3,12 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||
{
|
||||
public abstract class MessageBody : MessageBodyExchanger
|
||||
{
|
||||
private Action _continuation = () => { };
|
||||
|
||||
public bool RequestKeepAlive { get; protected set; }
|
||||
|
||||
protected MessageBody(FrameContext context) : base(context)
|
||||
|
|
@ -24,10 +23,6 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
public void IntakeFin(int count)
|
||||
{
|
||||
Transfer(count, true);
|
||||
if (_continuation != null)
|
||||
{
|
||||
_continuation.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void Consume();
|
||||
|
|
@ -90,12 +85,6 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
return true;
|
||||
}
|
||||
|
||||
public void Drain(Action continuation)
|
||||
{
|
||||
_continuation = continuation;
|
||||
_continuation.Invoke();
|
||||
}
|
||||
|
||||
|
||||
class ForRemainingData : MessageBody
|
||||
{
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
|
||||
public void Write(ArraySegment<byte> buffer, Action<object> callback, object state)
|
||||
{
|
||||
KestrelTrace.Log.ConnectionWrite(0, buffer.Count);
|
||||
var req = new ThisWriteReq();
|
||||
req.Init(_thread.Loop);
|
||||
req.Contextualize(this, _socket, buffer, callback, state);
|
||||
|
|
@ -87,6 +88,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
private void OnWrite(UvWriteReq req, int status)
|
||||
{
|
||||
_pin.Free();
|
||||
KestrelTrace.Log.ConnectionWriteCallback(0, status);
|
||||
//NOTE: pool this?
|
||||
Dispose();
|
||||
_callback(_state);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,83 @@
|
|||
using System;
|
||||
using System.Diagnostics.Tracing;
|
||||
|
||||
namespace Microsoft.AspNet.Server.Kestrel
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for KestrelTrace
|
||||
/// </summary>
|
||||
public class KestrelTrace : EventSource
|
||||
{
|
||||
public static KestrelTrace Log = new KestrelTrace();
|
||||
static EventTask Connection = (EventTask)1;
|
||||
static EventTask Frame = (EventTask)1;
|
||||
|
||||
|
||||
[Event(13, Level = EventLevel.Informational, Message = "Id {0}")]
|
||||
public void ConnectionStart(long connectionId)
|
||||
{
|
||||
WriteEvent(13, connectionId);
|
||||
}
|
||||
|
||||
[Event(14, Level = EventLevel.Informational, Message = "Id {0}")]
|
||||
public void ConnectionStop(long connectionId)
|
||||
{
|
||||
WriteEvent(14, connectionId);
|
||||
}
|
||||
|
||||
|
||||
[Event(4, Message = "Id {0} Status {1}")]
|
||||
internal void ConnectionRead(long connectionId, int status)
|
||||
{
|
||||
WriteEvent(4, connectionId, status);
|
||||
}
|
||||
|
||||
[Event(5, Message = "Id {0}")]
|
||||
internal void ConnectionPause(long connectionId)
|
||||
{
|
||||
WriteEvent(5, connectionId);
|
||||
}
|
||||
|
||||
[Event(6, Message = "Id {0}")]
|
||||
internal void ConnectionResume(long connectionId)
|
||||
{
|
||||
WriteEvent(6, connectionId);
|
||||
}
|
||||
|
||||
[Event(7, Message = "Id {0}")]
|
||||
internal void ConnectionReadFin(long connectionId)
|
||||
{
|
||||
WriteEvent(7, connectionId);
|
||||
}
|
||||
|
||||
[Event(8, Message = "Id {0} Step {1}")]
|
||||
internal void ConnectionWriteFin(long connectionId, int step)
|
||||
{
|
||||
WriteEvent(8, connectionId, step);
|
||||
}
|
||||
|
||||
[Event(9, Message = "Id {0}")]
|
||||
internal void ConnectionKeepAlive(long connectionId)
|
||||
{
|
||||
WriteEvent(9, connectionId);
|
||||
}
|
||||
|
||||
[Event(10, Message = "Id {0}")]
|
||||
internal void ConnectionDisconnect(long connectionId)
|
||||
{
|
||||
WriteEvent(10, connectionId);
|
||||
}
|
||||
|
||||
[Event(11, Message = "Id {0} Count {1}")]
|
||||
internal void ConnectionWrite(long connectionId, int count)
|
||||
{
|
||||
WriteEvent(11, connectionId, count);
|
||||
}
|
||||
|
||||
[Event(12, Message = "Id {0} Status {1}")]
|
||||
internal void ConnectionWriteCallback(long connectionId, int status)
|
||||
{
|
||||
WriteEvent(12, connectionId, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -42,6 +42,7 @@
|
|||
<Compile Include="Http\SocketOutput.cs" />
|
||||
<Compile Include="Infrastructure\Disposable.cs" />
|
||||
<Compile Include="Infrastructure\KestrelThread.cs" />
|
||||
<Compile Include="Infrastructure\KestrelTrace.cs" />
|
||||
<Compile Include="Networking\UcAsyncHandle.cs" />
|
||||
<Compile Include="Networking\UvMemory.cs" />
|
||||
<Compile Include="Networking\UvShutdownReq.cs" />
|
||||
|
|
@ -54,4 +55,4 @@
|
|||
<Compile Include="Networking\UvWriteRequest.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
@ -12,7 +12,8 @@
|
|||
"System.Threading.Thread": "4.0.0.0",
|
||||
"System.Diagnostics.TraceSource": "4.0.0.0",
|
||||
"System.Text.Encoding": "4.0.20.0",
|
||||
"System.Threading.Tasks": "4.0.10.0"
|
||||
"System.Threading.Tasks": "4.0.10.0",
|
||||
"System.Diagnostics.Tracing": "4.0.10.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -95,226 +95,204 @@ namespace Microsoft.AspNet.Server.KestralTests
|
|||
[Fact]
|
||||
public async Task Http10()
|
||||
{
|
||||
var engine = new KestrelEngine();
|
||||
engine.Start(1);
|
||||
var started = engine.CreateServer(App);
|
||||
|
||||
Transceive(
|
||||
@"POST / HTTP/1.0
|
||||
|
||||
Hello World",
|
||||
@"HTTP/1.0 200 OK
|
||||
|
||||
Hello World");
|
||||
started.Dispose();
|
||||
engine.Stop();
|
||||
using (var server = new TestServer(App))
|
||||
{
|
||||
using (var connection = new TestConnection())
|
||||
{
|
||||
await connection.SendEnd(
|
||||
"POST / HTTP/1.0",
|
||||
"",
|
||||
"Hello World");
|
||||
await connection.ReceiveEnd(
|
||||
"HTTP/1.0 200 OK",
|
||||
"",
|
||||
"Hello World");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Http11()
|
||||
{
|
||||
using (var server = new TestServer(AppChunked))
|
||||
{
|
||||
using (var connection = new TestConnection())
|
||||
{
|
||||
await connection.SendEnd(
|
||||
"GET / HTTP/1.1",
|
||||
"",
|
||||
"GET / HTTP/1.1",
|
||||
"Connection: close",
|
||||
"",
|
||||
"Goodbye");
|
||||
await connection.ReceiveEnd(
|
||||
"HTTP/1.1 200 OK",
|
||||
"Content-Length: 0",
|
||||
"",
|
||||
"HTTP/1.1 200 OK",
|
||||
"Content-Length: 7",
|
||||
"Connection: close",
|
||||
"",
|
||||
"Goodbye");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public async Task Http10ContentLength()
|
||||
{
|
||||
var engine = new KestrelEngine();
|
||||
engine.Start(1);
|
||||
var started = engine.CreateServer(App);
|
||||
|
||||
Transceive(
|
||||
@"POST / HTTP/1.0
|
||||
Content-Length: 11
|
||||
|
||||
Hello World",
|
||||
@"HTTP/1.0 200 OK
|
||||
|
||||
Hello World");
|
||||
started.Dispose();
|
||||
engine.Stop();
|
||||
using (var server = new TestServer(App))
|
||||
{
|
||||
using (var connection = new TestConnection())
|
||||
{
|
||||
await connection.Send(
|
||||
"POST / HTTP/1.0",
|
||||
"Content-Length: 11",
|
||||
"",
|
||||
"Hello World");
|
||||
await connection.ReceiveEnd(
|
||||
"HTTP/1.0 200 OK",
|
||||
"",
|
||||
"Hello World");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Http10TransferEncoding()
|
||||
{
|
||||
var engine = new KestrelEngine();
|
||||
engine.Start(1);
|
||||
var started = engine.CreateServer(App);
|
||||
|
||||
using (var connection = new TestConnection())
|
||||
using (var server = new TestServer(App))
|
||||
{
|
||||
await connection.Send(
|
||||
"POST / HTTP/1.0",
|
||||
"Transfer-Encoding: chunked",
|
||||
"",
|
||||
"5", "Hello", "6", " World", "0\r\n");
|
||||
await connection.ReceiveEnd(
|
||||
"HTTP/1.0 200 OK",
|
||||
"",
|
||||
"Hello World");
|
||||
using (var connection = new TestConnection())
|
||||
{
|
||||
await connection.Send(
|
||||
"POST / HTTP/1.0",
|
||||
"Transfer-Encoding: chunked",
|
||||
"",
|
||||
"5", "Hello", "6", " World", "0\r\n");
|
||||
await connection.ReceiveEnd(
|
||||
"HTTP/1.0 200 OK",
|
||||
"",
|
||||
"Hello World");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
started.Dispose();
|
||||
engine.Stop();
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public async Task Http10KeepAlive()
|
||||
{
|
||||
var engine = new KestrelEngine();
|
||||
engine.Start(1);
|
||||
var started = engine.CreateServer(AppChunked);
|
||||
|
||||
using (var connection = new TestConnection())
|
||||
using (var server = new TestServer(AppChunked))
|
||||
{
|
||||
await connection.SendEnd(
|
||||
"GET / HTTP/1.0",
|
||||
"Connection: keep-alive",
|
||||
"",
|
||||
"POST / HTTP/1.0",
|
||||
"",
|
||||
"Goodbye");
|
||||
await connection.Receive(
|
||||
"HTTP/1.0 200 OK",
|
||||
"Content-Length: 0",
|
||||
"Connection: keep-alive",
|
||||
"\r\n");
|
||||
await connection.ReceiveEnd(
|
||||
"HTTP/1.0 200 OK",
|
||||
"Content-Length: 7",
|
||||
"",
|
||||
"Goodbye");
|
||||
using (var connection = new TestConnection())
|
||||
{
|
||||
await connection.SendEnd(
|
||||
"GET / HTTP/1.0",
|
||||
"Connection: keep-alive",
|
||||
"",
|
||||
"POST / HTTP/1.0",
|
||||
"",
|
||||
"Goodbye");
|
||||
await connection.Receive(
|
||||
"HTTP/1.0 200 OK",
|
||||
"Content-Length: 0",
|
||||
"Connection: keep-alive",
|
||||
"\r\n");
|
||||
await connection.ReceiveEnd(
|
||||
"HTTP/1.0 200 OK",
|
||||
"Content-Length: 7",
|
||||
"",
|
||||
"Goodbye");
|
||||
}
|
||||
}
|
||||
|
||||
started.Dispose();
|
||||
engine.Stop();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Http10KeepAliveContentLength()
|
||||
{
|
||||
var engine = new KestrelEngine();
|
||||
engine.Start(1);
|
||||
var started = engine.CreateServer(AppChunked);
|
||||
|
||||
using (var connection = new TestConnection())
|
||||
using (var server = new TestServer(AppChunked))
|
||||
{
|
||||
await connection.SendEnd(
|
||||
"POST / HTTP/1.0",
|
||||
"Connection: keep-alive",
|
||||
"Content-Length: 11",
|
||||
"",
|
||||
"Hello WorldPOST / HTTP/1.0",
|
||||
"",
|
||||
"Goodbye");
|
||||
await connection.Receive(
|
||||
"HTTP/1.0 200 OK",
|
||||
"Content-Length: 11",
|
||||
"Connection: keep-alive",
|
||||
"",
|
||||
"Hello World");
|
||||
await connection.ReceiveEnd(
|
||||
"HTTP/1.0 200 OK",
|
||||
"Content-Length: 7",
|
||||
"",
|
||||
"Goodbye");
|
||||
using (var connection = new TestConnection())
|
||||
{
|
||||
await connection.SendEnd(
|
||||
"POST / HTTP/1.0",
|
||||
"Connection: keep-alive",
|
||||
"Content-Length: 11",
|
||||
"",
|
||||
"Hello WorldPOST / HTTP/1.0",
|
||||
"",
|
||||
"Goodbye");
|
||||
await connection.Receive(
|
||||
"HTTP/1.0 200 OK",
|
||||
"Content-Length: 11",
|
||||
"Connection: keep-alive",
|
||||
"",
|
||||
"Hello World");
|
||||
await connection.ReceiveEnd(
|
||||
"HTTP/1.0 200 OK",
|
||||
"Content-Length: 7",
|
||||
"",
|
||||
"Goodbye");
|
||||
}
|
||||
}
|
||||
started.Dispose();
|
||||
engine.Stop();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Http10KeepAliveTransferEncoding()
|
||||
{
|
||||
var engine = new KestrelEngine();
|
||||
engine.Start(1);
|
||||
var started = engine.CreateServer(AppChunked);
|
||||
|
||||
using (var connection = new TestConnection())
|
||||
using (var server = new TestServer(AppChunked))
|
||||
{
|
||||
await connection.SendEnd(
|
||||
"POST / HTTP/1.0",
|
||||
"Transfer-Encoding: chunked",
|
||||
"Connection: keep-alive",
|
||||
"",
|
||||
"5", "Hello", "6", " World", "0",
|
||||
"POST / HTTP/1.0",
|
||||
"",
|
||||
"Goodbye");
|
||||
await connection.Receive(
|
||||
"HTTP/1.0 200 OK",
|
||||
"Content-Length: 11",
|
||||
"Connection: keep-alive",
|
||||
"",
|
||||
"Hello World");
|
||||
await connection.ReceiveEnd(
|
||||
"HTTP/1.0 200 OK",
|
||||
"Content-Length: 7",
|
||||
"",
|
||||
"Goodbye");
|
||||
using (var connection = new TestConnection())
|
||||
{
|
||||
await connection.SendEnd(
|
||||
"POST / HTTP/1.0",
|
||||
"Transfer-Encoding: chunked",
|
||||
"Connection: keep-alive",
|
||||
"",
|
||||
"5", "Hello", "6", " World", "0",
|
||||
"POST / HTTP/1.0",
|
||||
"",
|
||||
"Goodbye");
|
||||
await connection.Receive(
|
||||
"HTTP/1.0 200 OK",
|
||||
"Content-Length: 11",
|
||||
"Connection: keep-alive",
|
||||
"",
|
||||
"Hello World");
|
||||
await connection.ReceiveEnd(
|
||||
"HTTP/1.0 200 OK",
|
||||
"Content-Length: 7",
|
||||
"",
|
||||
"Goodbye");
|
||||
}
|
||||
}
|
||||
|
||||
started.Dispose();
|
||||
engine.Stop();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Expect100ContinueForBody()
|
||||
{
|
||||
var engine = new KestrelEngine();
|
||||
engine.Start(1);
|
||||
var started = engine.CreateServer(AppChunked);
|
||||
|
||||
using (var connection = new TestConnection())
|
||||
using (var server = new TestServer(AppChunked))
|
||||
{
|
||||
await connection.Send(
|
||||
"POST / HTTP/1.1",
|
||||
"Expect: 100-continue",
|
||||
"Content-Length: 11",
|
||||
"Connection: close",
|
||||
"\r\n");
|
||||
await connection.Receive("HTTP/1.1 100 Continue", "\r\n");
|
||||
await connection.SendEnd("Hello World");
|
||||
await connection.Receive(
|
||||
"HTTP/1.1 200 OK",
|
||||
"Content-Length: 11",
|
||||
"Connection: close",
|
||||
"",
|
||||
"Hello World");
|
||||
using (var connection = new TestConnection())
|
||||
{
|
||||
await connection.Send(
|
||||
"POST / HTTP/1.1",
|
||||
"Expect: 100-continue",
|
||||
"Content-Length: 11",
|
||||
"Connection: close",
|
||||
"\r\n");
|
||||
await connection.Receive("HTTP/1.1 100 Continue", "\r\n");
|
||||
await connection.SendEnd("Hello World");
|
||||
await connection.Receive(
|
||||
"HTTP/1.1 200 OK",
|
||||
"Content-Length: 11",
|
||||
"Connection: close",
|
||||
"",
|
||||
"Hello World");
|
||||
}
|
||||
}
|
||||
|
||||
started.Dispose();
|
||||
engine.Stop();
|
||||
}
|
||||
|
||||
private void Transceive(string send, string expected)
|
||||
{
|
||||
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
socket.Connect(new IPEndPoint(IPAddress.Loopback, 4001));
|
||||
|
||||
var stream = new NetworkStream(socket, false);
|
||||
Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var writer = new StreamWriter(stream, Encoding.ASCII);
|
||||
foreach (var ch in send)
|
||||
{
|
||||
await writer.WriteAsync(ch);
|
||||
await writer.FlushAsync();
|
||||
await Task.Delay(TimeSpan.FromMilliseconds(5));
|
||||
}
|
||||
writer.Flush();
|
||||
stream.Flush();
|
||||
socket.Shutdown(SocketShutdown.Send);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
}
|
||||
});
|
||||
|
||||
var reader = new StreamReader(stream, Encoding.ASCII);
|
||||
var actual = reader.ReadToEnd();
|
||||
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
|
@ -40,8 +41,9 @@ namespace Microsoft.AspNet.Server.KestralTests
|
|||
{
|
||||
var text = String.Join("\r\n", lines);
|
||||
var writer = new StreamWriter(_stream, Encoding.ASCII);
|
||||
foreach (var ch in text)
|
||||
for (var index = 0; index != text.Length; ++index)
|
||||
{
|
||||
var ch = text[index];
|
||||
await writer.WriteAsync(ch);
|
||||
await writer.FlushAsync();
|
||||
await Task.Delay(TimeSpan.FromMilliseconds(5));
|
||||
|
|
@ -64,7 +66,10 @@ namespace Microsoft.AspNet.Server.KestralTests
|
|||
while (offset < expected.Length)
|
||||
{
|
||||
var task = _reader.ReadAsync(actual, offset, actual.Length - offset);
|
||||
// Assert.True(task.Wait(1000), "timeout");
|
||||
if (!Debugger.IsAttached)
|
||||
{
|
||||
Assert.True(task.Wait(1000), "timeout");
|
||||
}
|
||||
var count = await task;
|
||||
if (count == 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
using Microsoft.AspNet.Server.Kestrel;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNet.Server.KestralTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for TestServer
|
||||
/// </summary>
|
||||
public class TestServer : IDisposable
|
||||
{
|
||||
private KestrelEngine _engine;
|
||||
private IDisposable _server;
|
||||
|
||||
public TestServer(Func<object, Task> app)
|
||||
{
|
||||
Create(app);
|
||||
}
|
||||
|
||||
public void Create(Func<object,Task> app)
|
||||
{
|
||||
_engine = new KestrelEngine();
|
||||
_engine.Start(1);
|
||||
_server = _engine.CreateServer(app);
|
||||
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_server.Dispose();
|
||||
_engine.Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue