React to Testing#280.

This commit is contained in:
Cesar Blum Silveira 2017-06-23 16:47:50 -07:00 committed by GitHub
parent c83f606b22
commit 3084227314
4 changed files with 4 additions and 276 deletions

View File

@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26510.0
VisualStudioVersion = 15.0.26621.2
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7972A5D6-3385-4127-9277-428506DD44FF}"
ProjectSection(SolutionItems) = preProject
@ -20,7 +20,6 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shared", "shared", "{0EF2ACDF-012F-4472-A13A-4272419E2903}"
ProjectSection(SolutionItems) = preProject
test\shared\DummyApplication.cs = test\shared\DummyApplication.cs
test\shared\HttpClientSlim.cs = test\shared\HttpClientSlim.cs
test\shared\HttpParsingData.cs = test\shared\HttpParsingData.cs
test\shared\KestrelTestLoggerProvider.cs = test\shared\KestrelTestLoggerProvider.cs
test\shared\LifetimeNotImplemented.cs = test\shared\LifetimeNotImplemented.cs
@ -270,4 +269,7 @@ Global
{D95A7EC3-48AC-4D03-B2E2-0DA3E13BD3A4} = {D3273454-EA07-41D2-BF0B-FCC3675C2483}
{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC} = {D3273454-EA07-41D2-BF0B-FCC3675C2483}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {2D10D020-6770-47CA-BB8D-2C23FE3AE071}
EndGlobalSection
EndGlobal

View File

@ -1,109 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Testing;
using Xunit;
namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
{
public class HttpClientSlimTests
{
[Fact]
public async Task GetStringAsyncHttp()
{
using (var host = StartHost())
{
Assert.Equal("test", await HttpClientSlim.GetStringAsync(host.GetUri()));
}
}
[Fact]
public async Task GetStringAsyncHttps()
{
using (var host = StartHost(protocol: "https"))
{
Assert.Equal("test", await HttpClientSlim.GetStringAsync(host.GetUri(isHttps: true), validateCertificate: false));
}
}
[Fact]
public async Task GetStringAsyncThrowsForErrorResponse()
{
using (var host = StartHost(statusCode: StatusCodes.Status500InternalServerError))
{
await Assert.ThrowsAnyAsync<HttpRequestException>(() => HttpClientSlim.GetStringAsync(host.GetUri()));
}
}
[Fact]
public async Task PostAsyncHttp()
{
using (var host = StartHost(handler: (context) => context.Request.Body.CopyToAsync(context.Response.Body)))
{
Assert.Equal("test post", await HttpClientSlim.PostAsync(host.GetUri(), new StringContent("test post")));
}
}
[Fact]
public async Task PostAsyncHttps()
{
using (var host = StartHost(protocol: "https",
handler: (context) => context.Request.Body.CopyToAsync(context.Response.Body)))
{
Assert.Equal("test post", await HttpClientSlim.PostAsync(host.GetUri(isHttps: true),
new StringContent("test post"), validateCertificate: false));
}
}
[Fact]
public async Task PostAsyncThrowsForErrorResponse()
{
using (var host = StartHost(statusCode: StatusCodes.Status500InternalServerError))
{
await Assert.ThrowsAnyAsync<HttpRequestException>(
() => HttpClientSlim.PostAsync(host.GetUri(), new StringContent("")));
}
}
private IWebHost StartHost(string protocol = "http", int statusCode = StatusCodes.Status200OK, Func<HttpContext, Task> handler = null)
{
var host = new WebHostBuilder()
.UseKestrel(options =>
{
options.Listen(new IPEndPoint(IPAddress.Loopback, 0), listenOptions =>
{
if (protocol == "https")
{
listenOptions.UseHttps(TestResources.TestCertificatePath, "testPassword");
}
});
})
.Configure((app) =>
{
app.Run(context =>
{
context.Response.StatusCode = statusCode;
if (handler == null)
{
return context.Response.WriteAsync("test");
}
else
{
return handler(context);
}
});
})
.Build();
host.Start();
return host;
}
}
}

View File

@ -10,24 +10,11 @@ namespace Microsoft.AspNetCore.Hosting
{
public static class IWebHostPortExtensions
{
public static string GetHost(this IWebHost host, bool isHttps = false)
{
return host.GetUri(isHttps).Host;
}
public static int GetPort(this IWebHost host)
{
return host.GetPorts().First();
}
public static int GetPort(this IWebHost host, string scheme)
{
return host.GetUris()
.Where(u => u.Scheme.Equals(scheme, StringComparison.OrdinalIgnoreCase))
.Select(u => u.Port)
.First();
}
public static IEnumerable<int> GetPorts(this IWebHost host)
{
return host.GetUris()
@ -39,27 +26,5 @@ namespace Microsoft.AspNetCore.Hosting
return host.ServerFeatures.Get<IServerAddressesFeature>().Addresses
.Select(a => new Uri(a));
}
public static Uri GetUri(this IWebHost host, bool isHttps = false)
{
var uri = host.GetUris().First();
if (isHttps && uri.Scheme == "http")
{
var uriBuilder = new UriBuilder(uri)
{
Scheme = "https",
};
if (uri.Port == 80)
{
uriBuilder.Port = 443;
}
return uriBuilder.Uri;
}
return uri;
}
}
}

View File

@ -1,130 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.AspNetCore.Testing
{
// Lightweight version of HttpClient implemented using Socket and SslStream
public static class HttpClientSlim
{
public static async Task<string> GetStringAsync(string requestUri, bool validateCertificate = true)
=> await GetStringAsync(new Uri(requestUri), validateCertificate).ConfigureAwait(false);
public static async Task<string> GetStringAsync(Uri requestUri, bool validateCertificate = true)
{
using (var stream = await GetStream(requestUri, validateCertificate).ConfigureAwait(false))
{
using (var writer = new StreamWriter(stream, Encoding.ASCII, bufferSize: 1024, leaveOpen: true))
{
await writer.WriteAsync($"GET {requestUri.PathAndQuery} HTTP/1.0\r\n").ConfigureAwait(false);
await writer.WriteAsync($"Host: {requestUri.Authority}\r\n").ConfigureAwait(false);
await writer.WriteAsync("\r\n").ConfigureAwait(false);
}
return await ReadResponse(stream).ConfigureAwait(false);
}
}
public static async Task<string> PostAsync(string requestUri, HttpContent content, bool validateCertificate = true)
=> await PostAsync(new Uri(requestUri), content, validateCertificate).ConfigureAwait(false);
public static async Task<string> PostAsync(Uri requestUri, HttpContent content, bool validateCertificate = true)
{
using (var stream = await GetStream(requestUri, validateCertificate))
{
using (var writer = new StreamWriter(stream, Encoding.ASCII, bufferSize: 1024, leaveOpen: true))
{
await writer.WriteAsync($"POST {requestUri.PathAndQuery} HTTP/1.0\r\n").ConfigureAwait(false);
await writer.WriteAsync($"Host: {requestUri.Authority}\r\n").ConfigureAwait(false);
await writer.WriteAsync($"Content-Type: {content.Headers.ContentType}\r\n").ConfigureAwait(false);
await writer.WriteAsync($"Content-Length: {content.Headers.ContentLength}\r\n").ConfigureAwait(false);
await writer.WriteAsync("\r\n").ConfigureAwait(false);
}
await content.CopyToAsync(stream).ConfigureAwait(false);
return await ReadResponse(stream).ConfigureAwait(false);
}
}
private static async Task<string> ReadResponse(Stream stream)
{
using (var reader = new StreamReader(stream, Encoding.ASCII, detectEncodingFromByteOrderMarks: true,
bufferSize: 1024, leaveOpen: true))
{
var response = await reader.ReadToEndAsync().ConfigureAwait(false);
var status = GetStatus(response);
new HttpResponseMessage(status).EnsureSuccessStatusCode();
var body = response.Substring(response.IndexOf("\r\n\r\n") + 4);
return body;
}
}
private static HttpStatusCode GetStatus(string response)
{
var statusStart = response.IndexOf(' ') + 1;
var statusEnd = response.IndexOf(' ', statusStart) - 1;
var statusLength = statusEnd - statusStart + 1;
return (HttpStatusCode)int.Parse(response.Substring(statusStart, statusLength));
}
private static async Task<Stream> GetStream(Uri requestUri, bool validateCertificate)
{
var socket = await GetSocket(requestUri);
var stream = new NetworkStream(socket, ownsSocket: true);
if (requestUri.Scheme.Equals("https", StringComparison.OrdinalIgnoreCase))
{
var sslStream = new SslStream(stream, leaveInnerStreamOpen: false, userCertificateValidationCallback:
validateCertificate ? null : (RemoteCertificateValidationCallback)((a, b, c, d) => true));
await sslStream.AuthenticateAsClientAsync(requestUri.Host, clientCertificates: null,
enabledSslProtocols: SslProtocols.Tls11 | SslProtocols.Tls12,
checkCertificateRevocation: validateCertificate).ConfigureAwait(false);
return sslStream;
}
else
{
return stream;
}
}
public static async Task<Socket> GetSocket(Uri requestUri)
{
var tcs = new TaskCompletionSource<Socket>();
var socketArgs = new SocketAsyncEventArgs();
socketArgs.RemoteEndPoint = new DnsEndPoint(requestUri.DnsSafeHost, requestUri.Port);
socketArgs.Completed += (s, e) => tcs.TrySetResult(e.ConnectSocket);
// Must use static ConnectAsync(), since instance Connect() does not support DNS names on OSX/Linux.
if (Socket.ConnectAsync(SocketType.Stream, ProtocolType.Tcp, socketArgs))
{
await tcs.Task.ConfigureAwait(false);
}
var socket = socketArgs.ConnectSocket;
if (socket == null)
{
throw new SocketException((int)socketArgs.SocketError);
}
else
{
return socket;
}
}
}
}