Fix all line endings
Signed-off-by: Mike Parker <michael.parker@docker.com>
This commit is contained in:
Родитель
3730157307
Коммит
dd6b5d8271
|
@ -1 +1 @@
|
|||
* text=auto
|
||||
* text=auto
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
146
src/build.cake
146
src/build.cake
|
@ -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);
|
Загрузка…
Ссылка в новой задаче