Signed-off-by: Mike Parker <michael.parker@docker.com>
This commit is contained in:
Mike Parker 2019-06-25 17:25:21 +01:00
Родитель 3730157307
Коммит dd6b5d8271
29 изменённых файлов: 1359 добавлений и 1359 удалений

2
.gitattributes поставляемый
Просмотреть файл

@ -1 +1 @@
* text=auto
* text=auto

18
.gitignore поставляемый
Просмотреть файл

@ -1,10 +1,10 @@
################################################################################
# This .gitignore file was automatically created by Microsoft(R) Visual Studio.
################################################################################
/**/.vs/
/**/bin/
/**/obj/
/src/packages/
/src/TestResults/
################################################################################
# This .gitignore file was automatically created by Microsoft(R) Visual Studio.
################################################################################
/**/.vs/
/**/bin/
/**/obj/
/src/packages/
/src/TestResults/
/src/tools/

Просмотреть файл

@ -1,19 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\HttpOverStream\HttpOverStream.csproj" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\HttpOverStream\HttpOverStream.csproj" />
</ItemGroup>
</Project>

Просмотреть файл

@ -1,76 +1,76 @@
using HttpOverStream.Client;
using HttpOverStream.NamedPipe;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using System.Net.Http;
using System.Reflection;
using System.Threading.Tasks;
using Xunit;
namespace HttpOverStream.Server.AspnetCore.Tests
{
public class PersonMessage
{
public string Name { get; set; }
}
public class WelcomeMessage
{
public string Text { get; set; }
}
[Route("api/e2e-tests")]
public class EndToEndApiController : ControllerBase
{
[HttpGet("hello-world")]
public string HelloWorld()
{
return "Hello World";
}
[HttpPost("hello")]
public WelcomeMessage Hello([FromBody] PersonMessage person)
{
return new WelcomeMessage { Text = $"Hello {person.Name}" };
}
}
public class EndToEndTests
{
[Fact]
public async Task TestHelloWorld()
{
var builder = new WebHostBuilder().Configure(app => app.UseMvc())
.ConfigureServices(svc => svc.AddMvc().AddApplicationPart(Assembly.GetAssembly(typeof(EndToEndApiController))))
.UseServer(new CustomListenerHost(new NamedPipeListener("test-core-get")));
var host = builder.Build();
await host.StartAsync();
var client = new HttpClient(new DialMessageHandler(new NamedPipeDialer("test-core-get")));
var result = await client.GetStringAsync("http://localhost/api/e2e-tests/hello-world");
Assert.Equal("Hello World", result);
await host.StopAsync();
}
[Fact]
public async Task TestHelloPost()
{
var builder = new WebHostBuilder().Configure(app => app.UseMvc())
.ConfigureServices(svc => svc.AddMvc().AddApplicationPart(Assembly.GetAssembly(typeof(EndToEndApiController))))
.UseServer(new CustomListenerHost(new NamedPipeListener("test-core-post")));
var host = builder.Build();
await host.StartAsync();
var client = new HttpClient(new DialMessageHandler(new NamedPipeDialer("test-core-post")));
var result = await client.PostAsJsonAsync("http://localhost/api/e2e-tests/hello", new PersonMessage { Name = "Test" });
var wlcMsg = await result.Content.ReadAsAsync<WelcomeMessage>();
Assert.Equal("Hello Test", wlcMsg.Text);
await host.StopAsync();
}
}
}
using HttpOverStream.Client;
using HttpOverStream.NamedPipe;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using System.Net.Http;
using System.Reflection;
using System.Threading.Tasks;
using Xunit;
namespace HttpOverStream.Server.AspnetCore.Tests
{
public class PersonMessage
{
public string Name { get; set; }
}
public class WelcomeMessage
{
public string Text { get; set; }
}
[Route("api/e2e-tests")]
public class EndToEndApiController : ControllerBase
{
[HttpGet("hello-world")]
public string HelloWorld()
{
return "Hello World";
}
[HttpPost("hello")]
public WelcomeMessage Hello([FromBody] PersonMessage person)
{
return new WelcomeMessage { Text = $"Hello {person.Name}" };
}
}
public class EndToEndTests
{
[Fact]
public async Task TestHelloWorld()
{
var builder = new WebHostBuilder().Configure(app => app.UseMvc())
.ConfigureServices(svc => svc.AddMvc().AddApplicationPart(Assembly.GetAssembly(typeof(EndToEndApiController))))
.UseServer(new CustomListenerHost(new NamedPipeListener("test-core-get")));
var host = builder.Build();
await host.StartAsync();
var client = new HttpClient(new DialMessageHandler(new NamedPipeDialer("test-core-get")));
var result = await client.GetStringAsync("http://localhost/api/e2e-tests/hello-world");
Assert.Equal("Hello World", result);
await host.StopAsync();
}
[Fact]
public async Task TestHelloPost()
{
var builder = new WebHostBuilder().Configure(app => app.UseMvc())
.ConfigureServices(svc => svc.AddMvc().AddApplicationPart(Assembly.GetAssembly(typeof(EndToEndApiController))))
.UseServer(new CustomListenerHost(new NamedPipeListener("test-core-post")));
var host = builder.Build();
await host.StartAsync();
var client = new HttpClient(new DialMessageHandler(new NamedPipeDialer("test-core-post")));
var result = await client.PostAsJsonAsync("http://localhost/api/e2e-tests/hello", new PersonMessage { Name = "Test" });
var wlcMsg = await result.Content.ReadAsAsync<WelcomeMessage>();
Assert.Equal("Hello Test", wlcMsg.Text);
await host.StopAsync();
}
}
}

Просмотреть файл

@ -1,25 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.7" />
<PackageReference Include="Microsoft.AspNetCore" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.1.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\HttpOverStream.NamedPipe\HttpOverStream.NamedPipe.csproj" />
<ProjectReference Include="..\HttpOverStream.Server.AspnetCore\HttpOverStream.Server.AspnetCore.csproj" />
<ProjectReference Include="..\HttpOverStream.Client\HttpOverStream.Client.csproj" />
<ProjectReference Include="..\HttpOverStream\HttpOverStream.csproj" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.7" />
<PackageReference Include="Microsoft.AspNetCore" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.1.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\HttpOverStream.NamedPipe\HttpOverStream.NamedPipe.csproj" />
<ProjectReference Include="..\HttpOverStream.Server.AspnetCore\HttpOverStream.Server.AspnetCore.csproj" />
<ProjectReference Include="..\HttpOverStream.Client\HttpOverStream.Client.csproj" />
<ProjectReference Include="..\HttpOverStream\HttpOverStream.csproj" />
</ItemGroup>
</Project>

Просмотреть файл

@ -1,104 +1,104 @@
using Microsoft.AspNetCore.Hosting.Internal;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace HttpOverStream.Server.AspnetCore
{
public class CustomListenerHost : IServer
{
private readonly IListen _listener;
public CustomListenerHost( IListen listener)
: this( new FeatureCollection(), listener)
{
}
public CustomListenerHost( IFeatureCollection featureCollection, IListen listener)
{
Features = featureCollection ?? throw new ArgumentNullException(nameof(featureCollection));
_listener = listener ?? throw new ArgumentNullException(nameof(listener));
}
public Task StartAsync<TContext>(IHttpApplication<TContext> application, CancellationToken cancellationToken)
{
var app = (IHttpApplication<HostingApplication.Context>)application;
return _listener.StartAsync(stream => {
HandleClientStream(stream, app);
}, cancellationToken);
}
async void HandleClientStream(Stream stream, IHttpApplication<HostingApplication.Context> application)
{
try
{
using (stream)
{
var httpCtx = new DefaultHttpContext();
var requestFeature = await CreateRequestAsync(stream, CancellationToken.None).ConfigureAwait(false);
httpCtx.Features.Set<IHttpRequestFeature>(requestFeature);
var responseFeature = new HttpResponseFeature();
httpCtx.Features.Set<IHttpResponseFeature>(responseFeature);
var ctx = application.CreateContext(httpCtx.Features);
var body = new MemoryStream();
responseFeature.Body = body;
await application.ProcessRequestAsync(ctx).ConfigureAwait(false);
await stream.WriteServerResponseStatusAndHeadersAsync(requestFeature.Protocol, responseFeature.StatusCode.ToString(), responseFeature.ReasonPhrase, responseFeature.Headers.Select(i => new KeyValuePair<string, IEnumerable<string>>(i.Key, i.Value)), _=>{}, CancellationToken.None).ConfigureAwait(false);
body.Position = 0;
await body.CopyToAsync(stream).ConfigureAwait(false);
await stream.FlushAsync().ConfigureAwait(false);
}
}
catch (Exception e)
{
Console.WriteLine($"[CustomListenerHost]: error handling client stream: {e.Message}");
}
}
static Uri _localhostUri = new Uri("http://localhost/");
async Task<HttpRequestFeature> CreateRequestAsync(Stream stream, CancellationToken cancellationToken)
{
var firstLine = await stream.ReadLineAsync(cancellationToken).ConfigureAwait(false);
var parts = firstLine.Split(' ');
var result = new HttpRequestFeature();
result.Method = parts[0];
var uri = new Uri(parts[1], UriKind.RelativeOrAbsolute);
if (!uri.IsAbsoluteUri)
{
uri = new Uri(_localhostUri, uri);
}
result.Protocol = parts[2];
for(; ; )
{
var line = await stream.ReadLineAsync(cancellationToken).ConfigureAwait(false);
if(line.Length == 0)
{
break;
}
(var name, var values) = HttpParser.ParseHeaderNameValues(line);
result.Headers.Add(name, new Microsoft.Extensions.Primitives.StringValues(values.ToArray()));
}
result.Scheme = uri.Scheme;
result.Path = PathString.FromUriComponent(uri);
result.QueryString = QueryString.FromUriComponent(uri).Value;
result.Body = new BodyStream(stream, result.Headers.ContentLength);
return result;
}
public Task StopAsync(CancellationToken cancellationToken)
{
return _listener.StopAsync(cancellationToken);
}
public IFeatureCollection Features { get; }
public void Dispose() { }
}
}
using Microsoft.AspNetCore.Hosting.Internal;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace HttpOverStream.Server.AspnetCore
{
public class CustomListenerHost : IServer
{
private readonly IListen _listener;
public CustomListenerHost( IListen listener)
: this( new FeatureCollection(), listener)
{
}
public CustomListenerHost( IFeatureCollection featureCollection, IListen listener)
{
Features = featureCollection ?? throw new ArgumentNullException(nameof(featureCollection));
_listener = listener ?? throw new ArgumentNullException(nameof(listener));
}
public Task StartAsync<TContext>(IHttpApplication<TContext> application, CancellationToken cancellationToken)
{
var app = (IHttpApplication<HostingApplication.Context>)application;
return _listener.StartAsync(stream => {
HandleClientStream(stream, app);
}, cancellationToken);
}
async void HandleClientStream(Stream stream, IHttpApplication<HostingApplication.Context> application)
{
try
{
using (stream)
{
var httpCtx = new DefaultHttpContext();
var requestFeature = await CreateRequestAsync(stream, CancellationToken.None).ConfigureAwait(false);
httpCtx.Features.Set<IHttpRequestFeature>(requestFeature);
var responseFeature = new HttpResponseFeature();
httpCtx.Features.Set<IHttpResponseFeature>(responseFeature);
var ctx = application.CreateContext(httpCtx.Features);
var body = new MemoryStream();
responseFeature.Body = body;
await application.ProcessRequestAsync(ctx).ConfigureAwait(false);
await stream.WriteServerResponseStatusAndHeadersAsync(requestFeature.Protocol, responseFeature.StatusCode.ToString(), responseFeature.ReasonPhrase, responseFeature.Headers.Select(i => new KeyValuePair<string, IEnumerable<string>>(i.Key, i.Value)), _=>{}, CancellationToken.None).ConfigureAwait(false);
body.Position = 0;
await body.CopyToAsync(stream).ConfigureAwait(false);
await stream.FlushAsync().ConfigureAwait(false);
}
}
catch (Exception e)
{
Console.WriteLine($"[CustomListenerHost]: error handling client stream: {e.Message}");
}
}
static Uri _localhostUri = new Uri("http://localhost/");
async Task<HttpRequestFeature> CreateRequestAsync(Stream stream, CancellationToken cancellationToken)
{
var firstLine = await stream.ReadLineAsync(cancellationToken).ConfigureAwait(false);
var parts = firstLine.Split(' ');
var result = new HttpRequestFeature();
result.Method = parts[0];
var uri = new Uri(parts[1], UriKind.RelativeOrAbsolute);
if (!uri.IsAbsoluteUri)
{
uri = new Uri(_localhostUri, uri);
}
result.Protocol = parts[2];
for(; ; )
{
var line = await stream.ReadLineAsync(cancellationToken).ConfigureAwait(false);
if(line.Length == 0)
{
break;
}
(var name, var values) = HttpParser.ParseHeaderNameValues(line);
result.Headers.Add(name, new Microsoft.Extensions.Primitives.StringValues(values.ToArray()));
}
result.Scheme = uri.Scheme;
result.Path = PathString.FromUriComponent(uri);
result.QueryString = QueryString.FromUriComponent(uri).Value;
result.Body = new BodyStream(stream, result.Headers.ContentLength);
return result;
}
public Task StopAsync(CancellationToken cancellationToken)
{
return _listener.StopAsync(cancellationToken);
}
public IFeatureCollection Features { get; }
public void Dispose() { }
}
}

Просмотреть файл

@ -1,16 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.1.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\HttpOverStream\HttpOverStream.csproj" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.1.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\HttpOverStream\HttpOverStream.csproj" />
</ItemGroup>
</Project>

Просмотреть файл

@ -1,360 +1,360 @@
using HttpOverStream.Client;
using HttpOverStream.NamedPipe;
using Microsoft.Owin.Logging;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Owin;
using System;
using System.Diagnostics;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
namespace HttpOverStream.Server.Owin.Tests
{
[RoutePrefix("api/e2e-tests")]
public class EndToEndApiController : ApiController
{
[Route("hello-world")]
[HttpGet()]
public string GetHelloWorld()
{
return "Hello World";
}
[Route("hello")]
[HttpPost()]
public WelcomeMessage PostHello([FromBody] PersonMessage person)
{
return new WelcomeMessage { Text = $"Hello {person.Name}" };
}
[Route("timeout")]
[HttpGet()]
public async Task<string> GetTimeoutAsync()
{
await Task.Delay(TimeSpan.FromSeconds(5));
return "This should have timed out.";
}
}
public class PersonMessage
{
public string Name { get; set; }
}
public class WelcomeMessage
{
public string Text { get; set; }
}
[TestClass]
public class EndToEndTests
{
public TestContext TestContext { get; set; }
[TestMethod]
public async Task TestGet()
{
await TestGet_Impl();
}
[TestMethod]
public async Task TestGetStressTest()
{
for (int i = 0; i < 100; i++)
{
await TestGet_Impl();
GC.Collect();
GC.WaitForPendingFinalizers();
if (Debug.Listeners.Count > 1)
{
Debug.Listeners.RemoveAt(1);
}
}
}
[TestMethod]
public async Task TestGetStressTest_SingleServer()
{
for (int i = 0; i < 5; i++)
{
await TestGet_Impl(100);
GC.Collect();
GC.WaitForPendingFinalizers();
if (Debug.Listeners.Count > 1)
{
Debug.Listeners.RemoveAt(1);
}
}
}
private async Task TestGet_Impl(int numberOfRequests = 1)
{
using (CustomListenerHost.Start(SetupDefaultAppBuilder, new NamedPipeListener(TestContext.TestName)))
{
for (int i = 0; i < numberOfRequests; i++)
{
var client = new HttpClient(new DialMessageHandler(new NamedPipeDialer(TestContext.TestName)));
client.Timeout = TimeSpan.FromSeconds(5);
var result = await client.GetAsync("http://localhost/api/e2e-tests/hello-world");
Assert.AreEqual("Hello World", await result.Content.ReadAsAsync<string>());
}
}
}
[TestMethod]
public async Task TestGetStressTest_ClientBeforeServer()
{
for (int i = 0; i < 5; i++)
{
await TestClientStartsFirst_ServerDropsClientButComesUpAfterwards_Impl(100);
GC.Collect();
GC.WaitForPendingFinalizers();
if (Debug.Listeners.Count > 1)
{
Debug.Listeners.RemoveAt(1);
}
}
}
private async Task TestClientStartsFirst_ServerDropsClientButComesUpAfterwards_Impl(int numberOfRequests)
{
var client = new HttpClient(new DialMessageHandler(new NamedPipeDialer(TestContext.TestName, (int)TimeSpan.FromSeconds(30).TotalMilliseconds)));
client.Timeout = TimeSpan.FromSeconds(30);
var clientTask = client.GetAsync("http://localhost/api/e2e-tests/hello-world");
using (CustomListenerHost.Start(SetupDefaultAppBuilder, new NamedPipeListener(TestContext.TestName)))
{
for (int i = 0; i < numberOfRequests; i++)
{
var client2 = new HttpClient(new DialMessageHandler(new NamedPipeDialer(TestContext.TestName)));
client2.Timeout = TimeSpan.FromSeconds(5);
var result = await client2.GetAsync("http://localhost/api/e2e-tests/hello-world");
Assert.AreEqual("Hello World", await result.Content.ReadAsAsync<string>());
}
}
}
[TestMethod]
public async Task TestBadRequestStressTest()
{
for (int i = 0; i < 5; i++)
{
await TestBadRequest_BadMediaType_Impl();
}
}
private async Task TestBadRequest_BadMediaType_Impl()
{
using (CustomListenerHost.Start(SetupDefaultAppBuilder, new NamedPipeListener(TestContext.TestName)))
{
var client = new HttpClient(new DialMessageHandler(new NamedPipeDialer(TestContext.TestName)));
client.Timeout = TimeSpan.FromSeconds(1);
var badContent = new StringContent("{ ", Encoding.UTF8, "application/broken");
var result = await client.PostAsJsonAsync("http://localhost/api/e2e-tests/hello", badContent);
var wlcMsg = await result.Content.ReadAsAsync<WelcomeMessage>();
Assert.AreEqual("Hello ", wlcMsg.Text);
}
}
[TestMethod]
public async Task TestBadRequest_NonexistentEndpoint_StressTest()
{
for (int i = 0; i < 5; i++)
{
Debug.WriteLine(i);
await TestBadRequest_NonexistentEndpoint_Impl();
}
}
[TestMethod]
public async Task TestBadRequest_NonexistentEndpoint()
{
await TestBadRequest_NonexistentEndpoint_Impl();
}
private async Task TestBadRequest_NonexistentEndpoint_Impl()
{
using (CustomListenerHost.Start(SetupDefaultAppBuilder, new NamedPipeListener(TestContext.TestName)))
{
var client = new HttpClient(new DialMessageHandler(new NamedPipeDialer(TestContext.TestName)));
try
{
var badContent = new StringContent("{ }");
var result = await client.PostAsJsonAsync("http://localhost/api/this-doesnt-exist", badContent);
Debug.WriteLine("Client: Posted Json ");
Assert.AreEqual(result.StatusCode, System.Net.HttpStatusCode.NotFound);
}
catch(Exception e)
{
Debug.WriteLine("EXCEPTION " + e);
throw;
}
}
}
[TestMethod]
public async Task TestBodyStream()
{
await TestBodyStream_Impl();
}
[TestMethod]
public async Task TestBodyStreamStressTest()
{
for (int i = 0; i < 50; i++)
{
await TestBodyStream_Impl();
}
}
private async Task TestBodyStream_Impl()
{
var listener = new NamedPipeListener(TestContext.TestName);
var payload = Encoding.UTF8.GetBytes("Hello world");
await listener.StartAsync(con =>
{
Task.Run(async () =>
{
try
{
await con.WriteAsync(payload, 0, payload.Length);
}
catch (Exception e)
{
Debug.WriteLine("... WriteAsync exception:" + e.Message);
}
});
}, CancellationToken.None);
var dialer = new NamedPipeDialer(TestContext.TestName);
var stream = await dialer.DialAsync(new HttpRequestMessage(), CancellationToken.None);
var bodyStream = new BodyStream(stream, payload.Length);
var data = new byte[4096];
var read = await bodyStream.ReadAsync(data, 0, data.Length);
Assert.AreEqual(payload.Length, read);
read = await bodyStream.ReadAsync(data, 0, data.Length);
Assert.AreEqual(0, read);
// Clean up
await listener.StopAsync(CancellationToken.None);
}
[TestMethod]
public async Task TestPost()
{
await TestPost_Impl();
}
[TestMethod]
public async Task TestPostStressTest()
{
for (int i = 0; i < 50; i++)
{
await TestPost_Impl();
}
}
private async Task TestPost_Impl()
{
using (CustomListenerHost.Start(SetupDefaultAppBuilder, new NamedPipeListener(TestContext.TestName)))
{
var client = new HttpClient(new DialMessageHandler(new NamedPipeDialer(TestContext.TestName)));
var result = await client.PostAsJsonAsync("http://localhost/api/e2e-tests/hello", new PersonMessage { Name = "Test" });
var wlcMsg = await result.Content.ReadAsAsync<WelcomeMessage>();
Assert.AreEqual("Hello Test", wlcMsg.Text);
}
}
[TestMethod]
public async Task TestStreamInteruption()
{
await TestStreamInterruption_Impl();
}
[TestMethod]
public async Task TestStreamInteruptionStressTest()
{
for (int i = 0; i < 50; i++)
{
await TestStreamInterruption_Impl();
}
}
private async Task TestStreamInterruption_Impl()
{
var logFactory = new TestLoggerFactory();
using (CustomListenerHost.Start(app =>
{
SetupDefaultAppBuilder(app);
app.SetLoggerFactory(logFactory);
}, new NamedPipeListener(TestContext.TestName)))
{
var dialer = new NamedPipeDialer(TestContext.TestName);
using (var fuzzyStream = await dialer.DialAsync(new HttpRequestMessage(), CancellationToken.None))
{
// just write the first line of a valid http request, and drop the connection
var payload = Encoding.ASCII.GetBytes("GET /docs/index.html HTTP/1.0\n");
await fuzzyStream.WriteAsync(payload, 0, payload.Length);
}
var ex = await logFactory.ExceptionReceived.Task;
Assert.IsInstanceOfType(ex, typeof(EndOfStreamException));
// Test the stream still works afterwards
var client = new HttpClient(new DialMessageHandler(dialer));
var result = await client.PostAsJsonAsync("http://localhost/api/e2e-tests/hello", new PersonMessage { Name = "Test" });
var wlcMsg = await result.Content.ReadAsAsync<WelcomeMessage>();
Assert.AreEqual("Hello Test", wlcMsg.Text);
}
}
[TestMethod]
public async Task TestClientTimeoutIsRespectedWhenServerTakesTooLong()
{
using (CustomListenerHost.Start(SetupDefaultAppBuilder, new NamedPipeListener(TestContext.TestName)))
{
var client = new HttpClient(new DialMessageHandler(new NamedPipeDialer(TestContext.TestName)));
client.Timeout = TimeSpan.FromMilliseconds(100);
var sw = Stopwatch.StartNew();
await Assert.ThrowsExceptionAsync<TaskCanceledException>(async () =>
{
await client.GetAsync("http://localhost/api/e2e-tests/timeout");
});
sw.Stop();
Assert.IsTrue(sw.ElapsedMilliseconds < 1000, $"Client Timeout wasn't respected - GetAsync took too long ({sw.ElapsedMilliseconds} ms)");
}
}
private static void SetupDefaultAppBuilder(IAppBuilder appBuilder)
{
HttpConfiguration config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
config.SuppressDefaultHostAuthentication();
config.SuppressHostPrincipal();
appBuilder.UseWebApi(config);
}
class TestLoggerFactory : ILoggerFactory, ILogger
{
public TaskCompletionSource<Exception> ExceptionReceived { get; } = new TaskCompletionSource<Exception>();
public ILogger Create(string name) => this;
public bool WriteCore(TraceEventType eventType, int eventId, object state, Exception exception, Func<object, Exception, string> formatter)
{
if (exception != null)
{
ExceptionReceived.TrySetResult(exception);
}
return true;
}
}
}
}
using HttpOverStream.Client;
using HttpOverStream.NamedPipe;
using Microsoft.Owin.Logging;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Owin;
using System;
using System.Diagnostics;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
namespace HttpOverStream.Server.Owin.Tests
{
[RoutePrefix("api/e2e-tests")]
public class EndToEndApiController : ApiController
{
[Route("hello-world")]
[HttpGet()]
public string GetHelloWorld()
{
return "Hello World";
}
[Route("hello")]
[HttpPost()]
public WelcomeMessage PostHello([FromBody] PersonMessage person)
{
return new WelcomeMessage { Text = $"Hello {person.Name}" };
}
[Route("timeout")]
[HttpGet()]
public async Task<string> GetTimeoutAsync()
{
await Task.Delay(TimeSpan.FromSeconds(5));
return "This should have timed out.";
}
}
public class PersonMessage
{
public string Name { get; set; }
}
public class WelcomeMessage
{
public string Text { get; set; }
}
[TestClass]
public class EndToEndTests
{
public TestContext TestContext { get; set; }
[TestMethod]
public async Task TestGet()
{
await TestGet_Impl();
}
[TestMethod]
public async Task TestGetStressTest()
{
for (int i = 0; i < 100; i++)
{
await TestGet_Impl();
GC.Collect();
GC.WaitForPendingFinalizers();
if (Debug.Listeners.Count > 1)
{
Debug.Listeners.RemoveAt(1);
}
}
}
[TestMethod]
public async Task TestGetStressTest_SingleServer()
{
for (int i = 0; i < 5; i++)
{
await TestGet_Impl(100);
GC.Collect();
GC.WaitForPendingFinalizers();
if (Debug.Listeners.Count > 1)
{
Debug.Listeners.RemoveAt(1);
}
}
}
private async Task TestGet_Impl(int numberOfRequests = 1)
{
using (CustomListenerHost.Start(SetupDefaultAppBuilder, new NamedPipeListener(TestContext.TestName)))
{
for (int i = 0; i < numberOfRequests; i++)
{
var client = new HttpClient(new DialMessageHandler(new NamedPipeDialer(TestContext.TestName)));
client.Timeout = TimeSpan.FromSeconds(5);
var result = await client.GetAsync("http://localhost/api/e2e-tests/hello-world");
Assert.AreEqual("Hello World", await result.Content.ReadAsAsync<string>());
}
}
}
[TestMethod]
public async Task TestGetStressTest_ClientBeforeServer()
{
for (int i = 0; i < 5; i++)
{
await TestClientStartsFirst_ServerDropsClientButComesUpAfterwards_Impl(100);
GC.Collect();
GC.WaitForPendingFinalizers();
if (Debug.Listeners.Count > 1)
{
Debug.Listeners.RemoveAt(1);
}
}
}
private async Task TestClientStartsFirst_ServerDropsClientButComesUpAfterwards_Impl(int numberOfRequests)
{
var client = new HttpClient(new DialMessageHandler(new NamedPipeDialer(TestContext.TestName, (int)TimeSpan.FromSeconds(30).TotalMilliseconds)));
client.Timeout = TimeSpan.FromSeconds(30);
var clientTask = client.GetAsync("http://localhost/api/e2e-tests/hello-world");
using (CustomListenerHost.Start(SetupDefaultAppBuilder, new NamedPipeListener(TestContext.TestName)))
{
for (int i = 0; i < numberOfRequests; i++)
{
var client2 = new HttpClient(new DialMessageHandler(new NamedPipeDialer(TestContext.TestName)));
client2.Timeout = TimeSpan.FromSeconds(5);
var result = await client2.GetAsync("http://localhost/api/e2e-tests/hello-world");
Assert.AreEqual("Hello World", await result.Content.ReadAsAsync<string>());
}
}
}
[TestMethod]
public async Task TestBadRequestStressTest()
{
for (int i = 0; i < 5; i++)
{
await TestBadRequest_BadMediaType_Impl();
}
}
private async Task TestBadRequest_BadMediaType_Impl()
{
using (CustomListenerHost.Start(SetupDefaultAppBuilder, new NamedPipeListener(TestContext.TestName)))
{
var client = new HttpClient(new DialMessageHandler(new NamedPipeDialer(TestContext.TestName)));
client.Timeout = TimeSpan.FromSeconds(1);
var badContent = new StringContent("{ ", Encoding.UTF8, "application/broken");
var result = await client.PostAsJsonAsync("http://localhost/api/e2e-tests/hello", badContent);
var wlcMsg = await result.Content.ReadAsAsync<WelcomeMessage>();
Assert.AreEqual("Hello ", wlcMsg.Text);
}
}
[TestMethod]
public async Task TestBadRequest_NonexistentEndpoint_StressTest()
{
for (int i = 0; i < 5; i++)
{
Debug.WriteLine(i);
await TestBadRequest_NonexistentEndpoint_Impl();
}
}
[TestMethod]
public async Task TestBadRequest_NonexistentEndpoint()
{
await TestBadRequest_NonexistentEndpoint_Impl();
}
private async Task TestBadRequest_NonexistentEndpoint_Impl()
{
using (CustomListenerHost.Start(SetupDefaultAppBuilder, new NamedPipeListener(TestContext.TestName)))
{
var client = new HttpClient(new DialMessageHandler(new NamedPipeDialer(TestContext.TestName)));
try
{
var badContent = new StringContent("{ }");
var result = await client.PostAsJsonAsync("http://localhost/api/this-doesnt-exist", badContent);
Debug.WriteLine("Client: Posted Json ");
Assert.AreEqual(result.StatusCode, System.Net.HttpStatusCode.NotFound);
}
catch(Exception e)
{
Debug.WriteLine("EXCEPTION " + e);
throw;
}
}
}
[TestMethod]
public async Task TestBodyStream()
{
await TestBodyStream_Impl();
}
[TestMethod]
public async Task TestBodyStreamStressTest()
{
for (int i = 0; i < 50; i++)
{
await TestBodyStream_Impl();
}
}
private async Task TestBodyStream_Impl()
{
var listener = new NamedPipeListener(TestContext.TestName);
var payload = Encoding.UTF8.GetBytes("Hello world");
await listener.StartAsync(con =>
{
Task.Run(async () =>
{
try
{
await con.WriteAsync(payload, 0, payload.Length);
}
catch (Exception e)
{
Debug.WriteLine("... WriteAsync exception:" + e.Message);
}
});
}, CancellationToken.None);
var dialer = new NamedPipeDialer(TestContext.TestName);
var stream = await dialer.DialAsync(new HttpRequestMessage(), CancellationToken.None);
var bodyStream = new BodyStream(stream, payload.Length);
var data = new byte[4096];
var read = await bodyStream.ReadAsync(data, 0, data.Length);
Assert.AreEqual(payload.Length, read);
read = await bodyStream.ReadAsync(data, 0, data.Length);
Assert.AreEqual(0, read);
// Clean up
await listener.StopAsync(CancellationToken.None);
}
[TestMethod]
public async Task TestPost()
{
await TestPost_Impl();
}
[TestMethod]
public async Task TestPostStressTest()
{
for (int i = 0; i < 50; i++)
{
await TestPost_Impl();
}
}
private async Task TestPost_Impl()
{
using (CustomListenerHost.Start(SetupDefaultAppBuilder, new NamedPipeListener(TestContext.TestName)))
{
var client = new HttpClient(new DialMessageHandler(new NamedPipeDialer(TestContext.TestName)));
var result = await client.PostAsJsonAsync("http://localhost/api/e2e-tests/hello", new PersonMessage { Name = "Test" });
var wlcMsg = await result.Content.ReadAsAsync<WelcomeMessage>();
Assert.AreEqual("Hello Test", wlcMsg.Text);
}
}
[TestMethod]
public async Task TestStreamInteruption()
{
await TestStreamInterruption_Impl();
}
[TestMethod]
public async Task TestStreamInteruptionStressTest()
{
for (int i = 0; i < 50; i++)
{
await TestStreamInterruption_Impl();
}
}
private async Task TestStreamInterruption_Impl()
{
var logFactory = new TestLoggerFactory();
using (CustomListenerHost.Start(app =>
{
SetupDefaultAppBuilder(app);
app.SetLoggerFactory(logFactory);
}, new NamedPipeListener(TestContext.TestName)))
{
var dialer = new NamedPipeDialer(TestContext.TestName);
using (var fuzzyStream = await dialer.DialAsync(new HttpRequestMessage(), CancellationToken.None))
{
// just write the first line of a valid http request, and drop the connection
var payload = Encoding.ASCII.GetBytes("GET /docs/index.html HTTP/1.0\n");
await fuzzyStream.WriteAsync(payload, 0, payload.Length);
}
var ex = await logFactory.ExceptionReceived.Task;
Assert.IsInstanceOfType(ex, typeof(EndOfStreamException));
// Test the stream still works afterwards
var client = new HttpClient(new DialMessageHandler(dialer));
var result = await client.PostAsJsonAsync("http://localhost/api/e2e-tests/hello", new PersonMessage { Name = "Test" });
var wlcMsg = await result.Content.ReadAsAsync<WelcomeMessage>();
Assert.AreEqual("Hello Test", wlcMsg.Text);
}
}
[TestMethod]
public async Task TestClientTimeoutIsRespectedWhenServerTakesTooLong()
{
using (CustomListenerHost.Start(SetupDefaultAppBuilder, new NamedPipeListener(TestContext.TestName)))
{
var client = new HttpClient(new DialMessageHandler(new NamedPipeDialer(TestContext.TestName)));
client.Timeout = TimeSpan.FromMilliseconds(100);
var sw = Stopwatch.StartNew();
await Assert.ThrowsExceptionAsync<TaskCanceledException>(async () =>
{
await client.GetAsync("http://localhost/api/e2e-tests/timeout");
});
sw.Stop();
Assert.IsTrue(sw.ElapsedMilliseconds < 1000, $"Client Timeout wasn't respected - GetAsync took too long ({sw.ElapsedMilliseconds} ms)");
}
}
private static void SetupDefaultAppBuilder(IAppBuilder appBuilder)
{
HttpConfiguration config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
config.SuppressDefaultHostAuthentication();
config.SuppressHostPrincipal();
appBuilder.UseWebApi(config);
}
class TestLoggerFactory : ILoggerFactory, ILogger
{
public TaskCompletionSource<Exception> ExceptionReceived { get; } = new TaskCompletionSource<Exception>();
public ILogger Create(string name) => this;
public bool WriteCore(TraceEventType eventType, int eventId, object state, Exception exception, Func<object, Exception, string> formatter)
{
if (exception != null)
{
ExceptionReceived.TrySetResult(exception);
}
return true;
}
}
}
}

Просмотреть файл

@ -1,121 +1,121 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\MSTest.TestAdapter.1.4.0\build\net45\MSTest.TestAdapter.props" Condition="Exists('..\packages\MSTest.TestAdapter.1.4.0\build\net45\MSTest.TestAdapter.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{96388CE9-B97A-4754-A3B3-C898CD195969}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>HttpOverStream.Server.Owin.Tests</RootNamespace>
<AssemblyName>HttpOverStream.Server.Owin.Tests</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
<IsCodedUITest>False</IsCodedUITest>
<TestProjectType>UnitTest</TestProjectType>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=4.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Owin.4.0.1\lib\net45\Microsoft.Owin.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.1.4.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.1.4.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Net.Http.Formatting, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebApi.Client.5.2.7\lib\net45\System.Net.Http.Formatting.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.1\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Web.Http, Version=5.2.6.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebApi.Core.5.2.6\lib\net45\System.Web.Http.dll</HintPath>
</Reference>
<Reference Include="System.Web.Http.Owin, Version=5.2.6.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebApi.Owin.5.2.6\lib\net45\System.Web.Http.Owin.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="EndToEndTests.cs" />
<Compile Include="OnceTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\HttpOverStream.NamedPipe\HttpOverStream.NamedPipe.csproj">
<Project>{03090A81-4647-47BC-93BE-49D36484C94C}</Project>
<Name>HttpOverStream.NamedPipe</Name>
</ProjectReference>
<ProjectReference Include="..\HttpOverStream\HttpOverStream.csproj">
<Project>{8e94720f-04f5-4734-ac2d-e14d208af59e}</Project>
<Name>HttpOverStream</Name>
</ProjectReference>
<ProjectReference Include="..\HttpOverStream.Client\HttpOverStream.Client.csproj">
<Project>{fd513277-f032-4106-abcd-9719ada8f3db}</Project>
<Name>HttpOverStream.Client</Name>
</ProjectReference>
<ProjectReference Include="..\HttpOverStream.Server.Owin\HttpOverStream.Server.Owin.csproj">
<Project>{008edf79-f050-49c8-bf5f-25842466369b}</Project>
<Name>HttpOverStream.Server.Owin</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="pack">
</Target>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.1.4.0\build\net45\MSTest.TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.1.4.0\build\net45\MSTest.TestAdapter.props'))" />
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.1.4.0\build\net45\MSTest.TestAdapter.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.1.4.0\build\net45\MSTest.TestAdapter.targets'))" />
</Target>
<Import Project="..\packages\MSTest.TestAdapter.1.4.0\build\net45\MSTest.TestAdapter.targets" Condition="Exists('..\packages\MSTest.TestAdapter.1.4.0\build\net45\MSTest.TestAdapter.targets')" />
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\MSTest.TestAdapter.1.4.0\build\net45\MSTest.TestAdapter.props" Condition="Exists('..\packages\MSTest.TestAdapter.1.4.0\build\net45\MSTest.TestAdapter.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{96388CE9-B97A-4754-A3B3-C898CD195969}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>HttpOverStream.Server.Owin.Tests</RootNamespace>
<AssemblyName>HttpOverStream.Server.Owin.Tests</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
<IsCodedUITest>False</IsCodedUITest>
<TestProjectType>UnitTest</TestProjectType>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=4.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Owin.4.0.1\lib\net45\Microsoft.Owin.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.1.4.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.1.4.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Net.Http.Formatting, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebApi.Client.5.2.7\lib\net45\System.Net.Http.Formatting.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.1\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Web.Http, Version=5.2.6.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebApi.Core.5.2.6\lib\net45\System.Web.Http.dll</HintPath>
</Reference>
<Reference Include="System.Web.Http.Owin, Version=5.2.6.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebApi.Owin.5.2.6\lib\net45\System.Web.Http.Owin.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="EndToEndTests.cs" />
<Compile Include="OnceTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\HttpOverStream.NamedPipe\HttpOverStream.NamedPipe.csproj">
<Project>{03090A81-4647-47BC-93BE-49D36484C94C}</Project>
<Name>HttpOverStream.NamedPipe</Name>
</ProjectReference>
<ProjectReference Include="..\HttpOverStream\HttpOverStream.csproj">
<Project>{8e94720f-04f5-4734-ac2d-e14d208af59e}</Project>
<Name>HttpOverStream</Name>
</ProjectReference>
<ProjectReference Include="..\HttpOverStream.Client\HttpOverStream.Client.csproj">
<Project>{fd513277-f032-4106-abcd-9719ada8f3db}</Project>
<Name>HttpOverStream.Client</Name>
</ProjectReference>
<ProjectReference Include="..\HttpOverStream.Server.Owin\HttpOverStream.Server.Owin.csproj">
<Project>{008edf79-f050-49c8-bf5f-25842466369b}</Project>
<Name>HttpOverStream.Server.Owin</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="pack">
</Target>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.1.4.0\build\net45\MSTest.TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.1.4.0\build\net45\MSTest.TestAdapter.props'))" />
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.1.4.0\build\net45\MSTest.TestAdapter.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.1.4.0\build\net45\MSTest.TestAdapter.targets'))" />
</Target>
<Import Project="..\packages\MSTest.TestAdapter.1.4.0\build\net45\MSTest.TestAdapter.targets" Condition="Exists('..\packages\MSTest.TestAdapter.1.4.0\build\net45\MSTest.TestAdapter.targets')" />
</Project>

Просмотреть файл

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<EnableUnmanagedDebugging>true</EnableUnmanagedDebugging>
</PropertyGroup>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<EnableUnmanagedDebugging>true</EnableUnmanagedDebugging>
</PropertyGroup>
</Project>

Просмотреть файл

@ -1,27 +1,27 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace HttpOverStream.Server.Owin.Tests
{
[TestClass]
public class OnceTests
{
[TestMethod]
public void TestOnceCallsOnlyOnce()
{
int value = 0;
var once = new Once<int>(() => Interlocked.Increment(ref value));
Parallel.For(0, 1000, _ =>
{
once.EnsureDone();
});
Assert.AreEqual(1, value);
}
}
}
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace HttpOverStream.Server.Owin.Tests
{
[TestClass]
public class OnceTests
{
[TestMethod]
public void TestOnceCallsOnlyOnce()
{
int value = 0;
var once = new Once<int>(() => Interlocked.Increment(ref value));
Parallel.For(0, 1000, _ =>
{
once.EnsureDone();
});
Assert.AreEqual(1, value);
}
}
}

Просмотреть файл

@ -1,20 +1,20 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("HttpOverStream.WebApiTest")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("HttpOverStream.WebApiTest")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("96388ce9-b97a-4754-a3b3-c898cd195969")]
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("HttpOverStream.WebApiTest")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("HttpOverStream.WebApiTest")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("96388ce9-b97a-4754-a3b3-c898cd195969")]
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Просмотреть файл

@ -1,31 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="11.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.4.1" newVersion="4.0.4.1" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.7.0" newVersion="5.2.7.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="11.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.4.1" newVersion="4.0.4.1" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.7.0" newVersion="5.2.7.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

Просмотреть файл

@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.7" targetFramework="net461" />
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.6" targetFramework="net461" />
<package id="Microsoft.AspNet.WebApi.Owin" version="5.2.6" targetFramework="net461" />
<package id="Microsoft.Owin" version="4.0.1" targetFramework="net461" />
<package id="MSTest.TestAdapter" version="1.4.0" targetFramework="net461" />
<package id="MSTest.TestFramework" version="1.4.0" targetFramework="net461" />
<package id="Newtonsoft.Json" version="11.0.2" targetFramework="net461" />
<package id="Owin" version="1.0" targetFramework="net461" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net461" />
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net461" />
<package id="System.Threading.Tasks.Extensions" version="4.5.1" targetFramework="net461" />
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.7" targetFramework="net461" />
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.6" targetFramework="net461" />
<package id="Microsoft.AspNet.WebApi.Owin" version="5.2.6" targetFramework="net461" />
<package id="Microsoft.Owin" version="4.0.1" targetFramework="net461" />
<package id="MSTest.TestAdapter" version="1.4.0" targetFramework="net461" />
<package id="MSTest.TestFramework" version="1.4.0" targetFramework="net461" />
<package id="Newtonsoft.Json" version="11.0.2" targetFramework="net461" />
<package id="Owin" version="1.0" targetFramework="net461" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net461" />
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net461" />
<package id="System.Threading.Tasks.Extensions" version="4.5.1" targetFramework="net461" />
</packages>

Просмотреть файл

@ -1,21 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net461</TargetFramework>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Owin" Version="4.0.1" />
<PackageReference Include="Microsoft.Owin.Hosting" Version="4.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\HttpOverStream\HttpOverStream.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net461</TargetFramework>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Owin" Version="4.0.1" />
<PackageReference Include="Microsoft.Owin.Hosting" Version="4.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\HttpOverStream\HttpOverStream.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
</Project>

Просмотреть файл

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectView>ProjectFiles</ProjectView>
</PropertyGroup>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectView>ProjectFiles</ProjectView>
</PropertyGroup>
</Project>

Просмотреть файл

@ -1,19 +1,19 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>HttpOverStream.Server.Owin</id>
<version>1.0.0</version>
<title>HttpOverStream.Server.Owin</title>
<authors>HttpOverStream.Server.Owin</authors>
<owners>HttpOverStream.Server.Owin</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Package Description</description>
<dependencies>
<dependency id="HttpOverStream" version="1.0.0" exclude="Build,Analyzers" />
<dependency id="Owin" version="1.0.0" />
<dependency id="Microsoft.Owin" version="4.0.0" />
<dependency id="Microsoft.Owin.Hosting" version="4.0.0" />
<dependency id="System.Threading.Tasks.Extensions" version="4.5.1" />
</dependencies>
</metadata>
<?xml version="1.0"?>
<package >
<metadata>
<id>HttpOverStream.Server.Owin</id>
<version>1.0.0</version>
<title>HttpOverStream.Server.Owin</title>
<authors>HttpOverStream.Server.Owin</authors>
<owners>HttpOverStream.Server.Owin</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Package Description</description>
<dependencies>
<dependency id="HttpOverStream" version="1.0.0" exclude="Build,Analyzers" />
<dependency id="Owin" version="1.0.0" />
<dependency id="Microsoft.Owin" version="4.0.0" />
<dependency id="Microsoft.Owin.Hosting" version="4.0.0" />
<dependency id="System.Threading.Tasks.Extensions" version="4.5.1" />
</dependencies>
</metadata>
</package>

Просмотреть файл

@ -1,25 +1,25 @@
using System;
using System.Threading;
namespace HttpOverStream.Server.Owin
{
public class Once<T>
{
private T _result;
private Func<T> _todo;
public Once(Func<T> todo)
{
_todo = todo;
}
public T EnsureDone()
{
var todo = Interlocked.Exchange(ref _todo, null);
if (todo != null)
{
_result = todo();
}
return _result;
}
}
}
using System;
using System.Threading;
namespace HttpOverStream.Server.Owin
{
public class Once<T>
{
private T _result;
private Func<T> _todo;
public Once(Func<T> todo)
{
_todo = todo;
}
public T EnsureDone()
{
var todo = Interlocked.Exchange(ref _todo, null);
if (todo != null)
{
_result = todo();
}
return _result;
}
}
}

Просмотреть файл

@ -1,19 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.4.1" newVersion="4.0.4.1" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.4.1" newVersion="4.0.4.1" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

Просмотреть файл

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Owin" version="4.0.0" targetFramework="net461" />
<package id="Microsoft.Owin.Hosting" version="4.0.0" targetFramework="net461" />
<package id="Owin" version="1.0" targetFramework="net461" />
<package id="System.Buffers" version="4.5.0" targetFramework="net461" />
<package id="System.Memory" version="4.5.1" targetFramework="net461" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net461" />
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net461" />
<package id="System.Threading.Tasks.Extensions" version="4.5.1" targetFramework="net461" />
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Owin" version="4.0.0" targetFramework="net461" />
<package id="Microsoft.Owin.Hosting" version="4.0.0" targetFramework="net461" />
<package id="Owin" version="1.0" targetFramework="net461" />
<package id="System.Buffers" version="4.5.0" targetFramework="net461" />
<package id="System.Memory" version="4.5.1" targetFramework="net461" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net461" />
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net461" />
<package id="System.Threading.Tasks.Extensions" version="4.5.1" targetFramework="net461" />
</packages>

Просмотреть файл

@ -1,35 +1,35 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Xunit;
namespace HttpOverStream.Tests
{
public class BodyStreamTests
{
class TestStream : MemoryStream
{
public bool Disposed { get; private set; }
public TestStream(byte[] data) : base(data) { }
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
Disposed = true;
}
}
[Fact]
public async Task TestBodyStreamCloseOnReadEnd()
{
byte[] payload = new byte[10];
var ms = new TestStream(payload);
var bodyStream = new BodyStream(ms, 10, closeOnReachEnd: true);
var result = new byte[10];
var read = await bodyStream.ReadAsync(result, 0, 10);
Assert.Equal(10, read);
Assert.True(ms.Disposed);
}
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Xunit;
namespace HttpOverStream.Tests
{
public class BodyStreamTests
{
class TestStream : MemoryStream
{
public bool Disposed { get; private set; }
public TestStream(byte[] data) : base(data) { }
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
Disposed = true;
}
}
[Fact]
public async Task TestBodyStreamCloseOnReadEnd()
{
byte[] payload = new byte[10];
var ms = new TestStream(payload);
var bodyStream = new BodyStream(ms, 10, closeOnReachEnd: true);
var result = new byte[10];
var read = await bodyStream.ReadAsync(result, 0, 10);
Assert.Equal(10, read);
Assert.True(ms.Disposed);
}
}
}

Просмотреть файл

@ -1,50 +1,50 @@
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace HttpOverStream.Tests
{
public class ByLineReaderTests
{
[Fact]
public async Task TestWithCrLf()
{
var ms = new MemoryStream();
ms.Write(Encoding.UTF8.GetBytes("first line\r\nsecond longer line\r\nthird line\r\nhello\r\n\r\n"));
ms.Flush();
ms.Position = 0;
Assert.Equal("first line", await ms.ReadLineAsync(CancellationToken.None));
Assert.Equal("second longer line", await ms.ReadLineAsync(CancellationToken.None));
Assert.Equal("third line", await ms.ReadLineAsync(CancellationToken.None));
Assert.Equal("hello", await ms.ReadLineAsync(CancellationToken.None));
Assert.Equal("", await ms.ReadLineAsync(CancellationToken.None));
}
[Fact]
public async Task TestWithLf()
{
var ms = new MemoryStream();
ms.Write(Encoding.UTF8.GetBytes("first line\nsecond longer line\nthird line\nhello\n\n"));
ms.Flush();
ms.Position = 0;
Assert.Equal("first line", await ms.ReadLineAsync(CancellationToken.None));
Assert.Equal("second longer line", await ms.ReadLineAsync(CancellationToken.None));
Assert.Equal("third line", await ms.ReadLineAsync(CancellationToken.None));
Assert.Equal("hello", await ms.ReadLineAsync(CancellationToken.None));
Assert.Equal("", await ms.ReadLineAsync(CancellationToken.None));
}
[Fact]
public async Task TestMalformedHeaders()
{
var ms = new MemoryStream();
ms.Write(Encoding.UTF8.GetBytes("aaa\nsecond longer line\n"));
ms.Flush();
ms.Position = 0;
Assert.Equal("aaa", await ms.ReadLineAsync(CancellationToken.None));
Assert.Equal("second longer line", await ms.ReadLineAsync(CancellationToken.None));
await Assert.ThrowsAsync<EndOfStreamException>(async ()=> await ms.ReadLineAsync(CancellationToken.None));
}
}
}
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace HttpOverStream.Tests
{
public class ByLineReaderTests
{
[Fact]
public async Task TestWithCrLf()
{
var ms = new MemoryStream();
ms.Write(Encoding.UTF8.GetBytes("first line\r\nsecond longer line\r\nthird line\r\nhello\r\n\r\n"));
ms.Flush();
ms.Position = 0;
Assert.Equal("first line", await ms.ReadLineAsync(CancellationToken.None));
Assert.Equal("second longer line", await ms.ReadLineAsync(CancellationToken.None));
Assert.Equal("third line", await ms.ReadLineAsync(CancellationToken.None));
Assert.Equal("hello", await ms.ReadLineAsync(CancellationToken.None));
Assert.Equal("", await ms.ReadLineAsync(CancellationToken.None));
}
[Fact]
public async Task TestWithLf()
{
var ms = new MemoryStream();
ms.Write(Encoding.UTF8.GetBytes("first line\nsecond longer line\nthird line\nhello\n\n"));
ms.Flush();
ms.Position = 0;
Assert.Equal("first line", await ms.ReadLineAsync(CancellationToken.None));
Assert.Equal("second longer line", await ms.ReadLineAsync(CancellationToken.None));
Assert.Equal("third line", await ms.ReadLineAsync(CancellationToken.None));
Assert.Equal("hello", await ms.ReadLineAsync(CancellationToken.None));
Assert.Equal("", await ms.ReadLineAsync(CancellationToken.None));
}
[Fact]
public async Task TestMalformedHeaders()
{
var ms = new MemoryStream();
ms.Write(Encoding.UTF8.GetBytes("aaa\nsecond longer line\n"));
ms.Flush();
ms.Position = 0;
Assert.Equal("aaa", await ms.ReadLineAsync(CancellationToken.None));
Assert.Equal("second longer line", await ms.ReadLineAsync(CancellationToken.None));
await Assert.ThrowsAsync<EndOfStreamException>(async ()=> await ms.ReadLineAsync(CancellationToken.None));
}
}
}

Просмотреть файл

@ -1,21 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.8.0" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\HttpOverStream\HttpOverStream.csproj" />
<ProjectReference Include="..\HttpOverStream.Client\HttpOverStream.Client.csproj" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.8.0" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\HttpOverStream\HttpOverStream.csproj" />
<ProjectReference Include="..\HttpOverStream.Client\HttpOverStream.Client.csproj" />
</ItemGroup>
</Project>

Просмотреть файл

@ -1,67 +1,67 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28307.329
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HttpOverStream", "HttpOverStream\HttpOverStream.csproj", "{8E94720F-04F5-4734-AC2D-E14D208AF59E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HttpOverStream.Tests", "HttpOverStream.Tests\HttpOverStream.Tests.csproj", "{E4DF4D76-1729-427C-A362-EF4E122C7F2E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HttpOverStream.Client", "HttpOverStream.Client\HttpOverStream.Client.csproj", "{FD513277-F032-4106-ABCD-9719ADA8F3DB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HttpOverStream.Server.AspnetCore", "HttpOverStream.Server.AspnetCore\HttpOverStream.Server.AspnetCore.csproj", "{8FC5D101-1708-4B66-A8F1-3CFB50C32146}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpOverStream.Server.Owin", "HttpOverStream.Server.Owin\HttpOverStream.Server.Owin.csproj", "{008EDF79-F050-49C8-BF5F-25842466369B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpOverStream.Server.Owin.Tests", "HttpOverStream.Server.Owin.Tests\HttpOverStream.Server.Owin.Tests.csproj", "{96388CE9-B97A-4754-A3B3-C898CD195969}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HttpOverStream.Server.AspnetCore.Tests", "HttpOverStream.Server.AspnetCore.Tests\HttpOverStream.Server.AspnetCore.Tests.csproj", "{1E08ABEF-6BDF-4B01-87D4-2188227ACD63}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpOverStream.NamedPipe", "HttpOverStream.NamedPipe\HttpOverStream.NamedPipe.csproj", "{03090A81-4647-47BC-93BE-49D36484C94C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8E94720F-04F5-4734-AC2D-E14D208AF59E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8E94720F-04F5-4734-AC2D-E14D208AF59E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8E94720F-04F5-4734-AC2D-E14D208AF59E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8E94720F-04F5-4734-AC2D-E14D208AF59E}.Release|Any CPU.Build.0 = Release|Any CPU
{E4DF4D76-1729-427C-A362-EF4E122C7F2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E4DF4D76-1729-427C-A362-EF4E122C7F2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E4DF4D76-1729-427C-A362-EF4E122C7F2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E4DF4D76-1729-427C-A362-EF4E122C7F2E}.Release|Any CPU.Build.0 = Release|Any CPU
{FD513277-F032-4106-ABCD-9719ADA8F3DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FD513277-F032-4106-ABCD-9719ADA8F3DB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FD513277-F032-4106-ABCD-9719ADA8F3DB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FD513277-F032-4106-ABCD-9719ADA8F3DB}.Release|Any CPU.Build.0 = Release|Any CPU
{8FC5D101-1708-4B66-A8F1-3CFB50C32146}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8FC5D101-1708-4B66-A8F1-3CFB50C32146}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8FC5D101-1708-4B66-A8F1-3CFB50C32146}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8FC5D101-1708-4B66-A8F1-3CFB50C32146}.Release|Any CPU.Build.0 = Release|Any CPU
{008EDF79-F050-49C8-BF5F-25842466369B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{008EDF79-F050-49C8-BF5F-25842466369B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{008EDF79-F050-49C8-BF5F-25842466369B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{008EDF79-F050-49C8-BF5F-25842466369B}.Release|Any CPU.Build.0 = Release|Any CPU
{96388CE9-B97A-4754-A3B3-C898CD195969}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{96388CE9-B97A-4754-A3B3-C898CD195969}.Debug|Any CPU.Build.0 = Debug|Any CPU
{96388CE9-B97A-4754-A3B3-C898CD195969}.Release|Any CPU.ActiveCfg = Release|Any CPU
{96388CE9-B97A-4754-A3B3-C898CD195969}.Release|Any CPU.Build.0 = Release|Any CPU
{1E08ABEF-6BDF-4B01-87D4-2188227ACD63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1E08ABEF-6BDF-4B01-87D4-2188227ACD63}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1E08ABEF-6BDF-4B01-87D4-2188227ACD63}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1E08ABEF-6BDF-4B01-87D4-2188227ACD63}.Release|Any CPU.Build.0 = Release|Any CPU
{03090A81-4647-47BC-93BE-49D36484C94C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{03090A81-4647-47BC-93BE-49D36484C94C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{03090A81-4647-47BC-93BE-49D36484C94C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{03090A81-4647-47BC-93BE-49D36484C94C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {21FDAFB7-9661-403C-A19D-36403118786F}
EndGlobalSection
EndGlobal

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28307.329
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HttpOverStream", "HttpOverStream\HttpOverStream.csproj", "{8E94720F-04F5-4734-AC2D-E14D208AF59E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HttpOverStream.Tests", "HttpOverStream.Tests\HttpOverStream.Tests.csproj", "{E4DF4D76-1729-427C-A362-EF4E122C7F2E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HttpOverStream.Client", "HttpOverStream.Client\HttpOverStream.Client.csproj", "{FD513277-F032-4106-ABCD-9719ADA8F3DB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HttpOverStream.Server.AspnetCore", "HttpOverStream.Server.AspnetCore\HttpOverStream.Server.AspnetCore.csproj", "{8FC5D101-1708-4B66-A8F1-3CFB50C32146}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpOverStream.Server.Owin", "HttpOverStream.Server.Owin\HttpOverStream.Server.Owin.csproj", "{008EDF79-F050-49C8-BF5F-25842466369B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpOverStream.Server.Owin.Tests", "HttpOverStream.Server.Owin.Tests\HttpOverStream.Server.Owin.Tests.csproj", "{96388CE9-B97A-4754-A3B3-C898CD195969}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HttpOverStream.Server.AspnetCore.Tests", "HttpOverStream.Server.AspnetCore.Tests\HttpOverStream.Server.AspnetCore.Tests.csproj", "{1E08ABEF-6BDF-4B01-87D4-2188227ACD63}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpOverStream.NamedPipe", "HttpOverStream.NamedPipe\HttpOverStream.NamedPipe.csproj", "{03090A81-4647-47BC-93BE-49D36484C94C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8E94720F-04F5-4734-AC2D-E14D208AF59E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8E94720F-04F5-4734-AC2D-E14D208AF59E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8E94720F-04F5-4734-AC2D-E14D208AF59E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8E94720F-04F5-4734-AC2D-E14D208AF59E}.Release|Any CPU.Build.0 = Release|Any CPU
{E4DF4D76-1729-427C-A362-EF4E122C7F2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E4DF4D76-1729-427C-A362-EF4E122C7F2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E4DF4D76-1729-427C-A362-EF4E122C7F2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E4DF4D76-1729-427C-A362-EF4E122C7F2E}.Release|Any CPU.Build.0 = Release|Any CPU
{FD513277-F032-4106-ABCD-9719ADA8F3DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FD513277-F032-4106-ABCD-9719ADA8F3DB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FD513277-F032-4106-ABCD-9719ADA8F3DB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FD513277-F032-4106-ABCD-9719ADA8F3DB}.Release|Any CPU.Build.0 = Release|Any CPU
{8FC5D101-1708-4B66-A8F1-3CFB50C32146}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8FC5D101-1708-4B66-A8F1-3CFB50C32146}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8FC5D101-1708-4B66-A8F1-3CFB50C32146}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8FC5D101-1708-4B66-A8F1-3CFB50C32146}.Release|Any CPU.Build.0 = Release|Any CPU
{008EDF79-F050-49C8-BF5F-25842466369B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{008EDF79-F050-49C8-BF5F-25842466369B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{008EDF79-F050-49C8-BF5F-25842466369B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{008EDF79-F050-49C8-BF5F-25842466369B}.Release|Any CPU.Build.0 = Release|Any CPU
{96388CE9-B97A-4754-A3B3-C898CD195969}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{96388CE9-B97A-4754-A3B3-C898CD195969}.Debug|Any CPU.Build.0 = Debug|Any CPU
{96388CE9-B97A-4754-A3B3-C898CD195969}.Release|Any CPU.ActiveCfg = Release|Any CPU
{96388CE9-B97A-4754-A3B3-C898CD195969}.Release|Any CPU.Build.0 = Release|Any CPU
{1E08ABEF-6BDF-4B01-87D4-2188227ACD63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1E08ABEF-6BDF-4B01-87D4-2188227ACD63}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1E08ABEF-6BDF-4B01-87D4-2188227ACD63}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1E08ABEF-6BDF-4B01-87D4-2188227ACD63}.Release|Any CPU.Build.0 = Release|Any CPU
{03090A81-4647-47BC-93BE-49D36484C94C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{03090A81-4647-47BC-93BE-49D36484C94C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{03090A81-4647-47BC-93BE-49D36484C94C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{03090A81-4647-47BC-93BE-49D36484C94C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {21FDAFB7-9661-403C-A19D-36403118786F}
EndGlobalSection
EndGlobal

Просмотреть файл

@ -1,103 +1,103 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace HttpOverStream
{
public class BodyStream : Stream
{
long? _length;
long _read;
bool _closeOnReachEnd;
public Stream Underlying { get; private set; }
public BodyStream(Stream underlying, long? length, bool closeOnReachEnd = false)
{
Underlying = underlying;
_length = length;
_closeOnReachEnd = closeOnReachEnd;
}
private void CloseIfReachedEnd()
{
if (!_closeOnReachEnd || !_length.HasValue)
{
return;
}
if (_read >= _length.Value)
{
Close();
}
}
private int BoundedCount(int count)
{
if (!_length.HasValue)
{
return count;
}
return (int)Math.Min((long)count, _length.Value - _read);
}
public override void Flush() => throw new NotSupportedException();
public override int Read(byte[] buffer, int offset, int count)
{
count = BoundedCount(count);
if (count == 0)
{
return 0;
}
var read = Underlying.Read(buffer, offset, count);
_read += read;
CloseIfReachedEnd();
return read;
}
public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
public override void SetLength(long value) => throw new NotSupportedException();
public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
public override bool CanRead => true;
public override bool CanSeek => false;
public override bool CanWrite => false;
public override long Length
{
get
{
if (!_length.HasValue)
{
return Underlying.Length;
}
return _length.Value;
}
}
public override long Position
{
get => throw new InvalidOperationException("Cannot seek");
set => throw new InvalidOperationException("Cannot seek");
}
public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
count = BoundedCount(count);
if (count == 0)
{
return 0;
}
var read = await Underlying.ReadAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false);
_read += read;
CloseIfReachedEnd();
return read;
}
public override void Close() => Underlying.Close();
protected override void Dispose(bool disposing) {
base.Dispose(disposing);
if (disposing)
{
Underlying.Dispose();
}
}
}
}
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace HttpOverStream
{
public class BodyStream : Stream
{
long? _length;
long _read;
bool _closeOnReachEnd;
public Stream Underlying { get; private set; }
public BodyStream(Stream underlying, long? length, bool closeOnReachEnd = false)
{
Underlying = underlying;
_length = length;
_closeOnReachEnd = closeOnReachEnd;
}
private void CloseIfReachedEnd()
{
if (!_closeOnReachEnd || !_length.HasValue)
{
return;
}
if (_read >= _length.Value)
{
Close();
}
}
private int BoundedCount(int count)
{
if (!_length.HasValue)
{
return count;
}
return (int)Math.Min((long)count, _length.Value - _read);
}
public override void Flush() => throw new NotSupportedException();
public override int Read(byte[] buffer, int offset, int count)
{
count = BoundedCount(count);
if (count == 0)
{
return 0;
}
var read = Underlying.Read(buffer, offset, count);
_read += read;
CloseIfReachedEnd();
return read;
}
public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
public override void SetLength(long value) => throw new NotSupportedException();
public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
public override bool CanRead => true;
public override bool CanSeek => false;
public override bool CanWrite => false;
public override long Length
{
get
{
if (!_length.HasValue)
{
return Underlying.Length;
}
return _length.Value;
}
}
public override long Position
{
get => throw new InvalidOperationException("Cannot seek");
set => throw new InvalidOperationException("Cannot seek");
}
public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
count = BoundedCount(count);
if (count == 0)
{
return 0;
}
var read = await Underlying.ReadAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false);
_read += read;
CloseIfReachedEnd();
return read;
}
public override void Close() => Underlying.Close();
protected override void Dispose(bool disposing) {
base.Dispose(disposing);
if (disposing)
{
Underlying.Dispose();
}
}
}
}

Просмотреть файл

@ -1,44 +1,44 @@
using System.Collections.Generic;
using System.IO;
using System.IO.Pipes;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace HttpOverStream
{
public static class ByLineReader
{
public static async ValueTask<string> ReadLineAsync(this Stream stream, CancellationToken cancellationToken)
{
var bytes = new List<byte>();
var buffer = new byte[1];
const byte lineSeparator = (byte)'\n';
while(true)
{
var read = await stream.ReadAsync(buffer, 0, 1, cancellationToken).ConfigureAwait(false);
if (read == 0)
{
if (cancellationToken.IsCancellationRequested)
{
throw new TaskCanceledException("Cancellation token triggered before we finished reading from the stream.");
}
// EOF -> throw
throw new EndOfStreamException("Reached end of stream before finding a line seperator");
}
if (buffer[0] == lineSeparator)
{
break;
}
bytes.Add(buffer[0]);
}
// handle \r\n eol markers
const byte carriageReturn = (byte)'\r';
if (bytes.Count > 0 && bytes[bytes.Count - 1] == carriageReturn)
{
bytes.RemoveAt(bytes.Count - 1);
}
return Encoding.ASCII.GetString(bytes.ToArray());
}
}
}
using System.Collections.Generic;
using System.IO;
using System.IO.Pipes;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace HttpOverStream
{
public static class ByLineReader
{
public static async ValueTask<string> ReadLineAsync(this Stream stream, CancellationToken cancellationToken)
{
var bytes = new List<byte>();
var buffer = new byte[1];
const byte lineSeparator = (byte)'\n';
while(true)
{
var read = await stream.ReadAsync(buffer, 0, 1, cancellationToken).ConfigureAwait(false);
if (read == 0)
{
if (cancellationToken.IsCancellationRequested)
{
throw new TaskCanceledException("Cancellation token triggered before we finished reading from the stream.");
}
// EOF -> throw
throw new EndOfStreamException("Reached end of stream before finding a line seperator");
}
if (buffer[0] == lineSeparator)
{
break;
}
bytes.Add(buffer[0]);
}
// handle \r\n eol markers
const byte carriageReturn = (byte)'\r';
if (bytes.Count > 0 && bytes[bytes.Count - 1] == carriageReturn)
{
bytes.RemoveAt(bytes.Count - 1);
}
return Encoding.ASCII.GetString(bytes.ToArray());
}
}
}

Просмотреть файл

@ -1,20 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.1" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.1" />
</ItemGroup>
</Project>

Просмотреть файл

@ -1,24 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace HttpOverStream
{
public static class HttpParser
{
public static (string name, List<string> values) ParseHeaderNameValues(string line)
{
var pos = line.IndexOf(':');
if(pos == -1)
{
throw new FormatException("Invalid header format");
}
var name = line.Substring(0, pos).Trim();
var values = line.Substring(pos + 1)
.Split(',')
.Select(v => v.Trim())
.ToList();
return (name, values);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
namespace HttpOverStream
{
public static class HttpParser
{
public static (string name, List<string> values) ParseHeaderNameValues(string line)
{
var pos = line.IndexOf(':');
if(pos == -1)
{
throw new FormatException("Invalid header format");
}
var name = line.Substring(0, pos).Trim();
var values = line.Substring(pos + 1)
.Split(',')
.Select(v => v.Trim())
.ToList();
return (name, values);
}
}
}

Просмотреть файл

@ -1,74 +1,74 @@
var target = Argument("target", "Build");
var configuration = Argument("configuration", "Release");
var msbuildVerbosity = Argument("msbuild-verbosity", "Minimal");
var coverage = Argument("coverage", "false");
void SetMSBuildConfiguration(MSBuildSettings settings){
settings.Configuration = configuration;
settings.Verbosity = (Verbosity)Enum.Parse(typeof(Verbosity), msbuildVerbosity);
}
Task("Nuget-Restore")
.Does(() =>
{
NuGetRestore(".");
DotNetCoreRestore();
});
Task("Build")
.IsDependentOn("Nuget-Restore")
.Does(() =>
{
MSBuild(".", SetMSBuildConfiguration);
});
Task("Test")
.IsDependentOn("Nuget-Restore")
.Does(() =>
{
var settings = new DotNetCoreTestSettings
{
Configuration = configuration,
NoRestore = true,
};
var projectFiles = GetFiles("./**/*Test*.csproj");
foreach (var file in projectFiles)
{
DotNetCoreTest(file.FullPath, settings);
}
});
Task("Nuget-pack")
.IsDependentOn("Nuget-Restore")
.Does(()=>{
var version = "0.1.0";
if(BuildSystem.AppVeyor.Environment.Repository.Tag.IsTag){
version = BuildSystem.AppVeyor.Environment.Repository.Tag.Name;
}
var settings = new DotNetCorePackSettings
{
Configuration = "Release",
OutputDirectory = "./nupkgs/",
MSBuildSettings = new DotNetCoreMSBuildSettings().WithProperty("PackageVersion", version),
};
DotNetCorePack("./", settings);
});
Task("Nuget-push")
.IsDependentOn("Nuget-pack")
.Does(()=>{
if(!BuildSystem.AppVeyor.Environment.Repository.Tag.IsTag){
return;
}
// Get the paths to the packages.
var packages = GetFiles("./nupkgs/*.nupkg");
// Push the package.
NuGetPush(packages, new NuGetPushSettings {
Source = "https://api.nuget.org/v3/index.json",
ApiKey = EnvironmentVariable("NugetAPIKey")
});
});
var target = Argument("target", "Build");
var configuration = Argument("configuration", "Release");
var msbuildVerbosity = Argument("msbuild-verbosity", "Minimal");
var coverage = Argument("coverage", "false");
void SetMSBuildConfiguration(MSBuildSettings settings){
settings.Configuration = configuration;
settings.Verbosity = (Verbosity)Enum.Parse(typeof(Verbosity), msbuildVerbosity);
}
Task("Nuget-Restore")
.Does(() =>
{
NuGetRestore(".");
DotNetCoreRestore();
});
Task("Build")
.IsDependentOn("Nuget-Restore")
.Does(() =>
{
MSBuild(".", SetMSBuildConfiguration);
});
Task("Test")
.IsDependentOn("Nuget-Restore")
.Does(() =>
{
var settings = new DotNetCoreTestSettings
{
Configuration = configuration,
NoRestore = true,
};
var projectFiles = GetFiles("./**/*Test*.csproj");
foreach (var file in projectFiles)
{
DotNetCoreTest(file.FullPath, settings);
}
});
Task("Nuget-pack")
.IsDependentOn("Nuget-Restore")
.Does(()=>{
var version = "0.1.0";
if(BuildSystem.AppVeyor.Environment.Repository.Tag.IsTag){
version = BuildSystem.AppVeyor.Environment.Repository.Tag.Name;
}
var settings = new DotNetCorePackSettings
{
Configuration = "Release",
OutputDirectory = "./nupkgs/",
MSBuildSettings = new DotNetCoreMSBuildSettings().WithProperty("PackageVersion", version),
};
DotNetCorePack("./", settings);
});
Task("Nuget-push")
.IsDependentOn("Nuget-pack")
.Does(()=>{
if(!BuildSystem.AppVeyor.Environment.Repository.Tag.IsTag){
return;
}
// Get the paths to the packages.
var packages = GetFiles("./nupkgs/*.nupkg");
// Push the package.
NuGetPush(packages, new NuGetPushSettings {
Source = "https://api.nuget.org/v3/index.json",
ApiKey = EnvironmentVariable("NugetAPIKey")
});
});
RunTarget(target);