-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #247 from martincostello/Support-Custom-Server
Support custom IServer with LambdaTestServer
- Loading branch information
Showing
24 changed files
with
787 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
// Copyright (c) Martin Costello, 2019. All rights reserved. | ||
// Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information. | ||
|
||
using System.Net.Sockets; | ||
using System.Reflection; | ||
using System.Text.Json; | ||
using Amazon.Lambda.APIGatewayEvents; | ||
using MartinCostello.Testing.AwsLambdaTestServer; | ||
using Microsoft.AspNetCore.Http; | ||
|
||
namespace MinimalApi; | ||
|
||
public class ApiTests : IAsyncLifetime | ||
{ | ||
private readonly HttpLambdaTestServer _server; | ||
|
||
public ApiTests(ITestOutputHelper outputHelper) | ||
{ | ||
_server = new() { OutputHelper = outputHelper }; | ||
} | ||
|
||
public async Task DisposeAsync() | ||
=> await _server.DisposeAsync(); | ||
|
||
public async Task InitializeAsync() | ||
=> await _server.InitializeAsync(); | ||
|
||
[Fact(Timeout = 5_000)] | ||
public async Task Can_Hash_String() | ||
{ | ||
// Arrange | ||
var options = new JsonSerializerOptions(JsonSerializerDefaults.Web); | ||
|
||
var body = new | ||
{ | ||
algorithm = "sha256", | ||
format = "base64", | ||
plaintext = "ASP.NET Core", | ||
}; | ||
|
||
var request = new APIGatewayProxyRequest() | ||
{ | ||
Body = JsonSerializer.Serialize(body), | ||
Headers = new Dictionary<string, string>() | ||
{ | ||
["content-type"] = "application/json", | ||
}, | ||
HttpMethod = HttpMethods.Post, | ||
Path = "/hash", | ||
}; | ||
|
||
// Arrange | ||
string json = JsonSerializer.Serialize(request, options); | ||
|
||
LambdaTestContext context = await _server.EnqueueAsync(json); | ||
|
||
using var cts = GetCancellationTokenSourceForResponseAvailable(context); | ||
|
||
// Act | ||
_ = Task.Run( | ||
() => | ||
{ | ||
try | ||
{ | ||
typeof(HashRequest).Assembly.EntryPoint!.Invoke(null, new[] { Array.Empty<string>() }); | ||
} | ||
catch (Exception ex) when (LambdaServerWasShutDown(ex)) | ||
{ | ||
// The Lambda runtime server was shut down | ||
} | ||
}, | ||
cts.Token); | ||
|
||
// Assert | ||
await context.Response.WaitToReadAsync(cts.IsCancellationRequested ? default : cts.Token); | ||
|
||
context.Response.TryRead(out LambdaTestResponse? response).ShouldBeTrue(); | ||
response.IsSuccessful.ShouldBeTrue($"Failed to process request: {await response.ReadAsStringAsync()}"); | ||
response.Duration.ShouldBeInRange(TimeSpan.Zero, TimeSpan.FromSeconds(2)); | ||
response.Content.ShouldNotBeEmpty(); | ||
|
||
// Assert | ||
var actual = JsonSerializer.Deserialize<APIGatewayProxyResponse>(response.Content, options); | ||
|
||
actual.ShouldNotBeNull(); | ||
|
||
actual.ShouldNotBeNull(); | ||
actual.StatusCode.ShouldBe(StatusCodes.Status200OK); | ||
actual.MultiValueHeaders.ShouldContainKey("Content-Type"); | ||
actual.MultiValueHeaders["Content-Type"].ShouldBe(new[] { "application/json; charset=utf-8" }); | ||
|
||
var hash = JsonSerializer.Deserialize<HashResponse>(actual.Body, options); | ||
|
||
hash.ShouldNotBeNull(); | ||
hash.Hash.ShouldBe("XXE/IcKhlw/yjLTH7cCWPSr7JfOw5LuYXeBuE5skNfA="); | ||
} | ||
|
||
private static CancellationTokenSource GetCancellationTokenSourceForResponseAvailable( | ||
LambdaTestContext context, | ||
TimeSpan? timeout = null) | ||
{ | ||
if (timeout == null) | ||
{ | ||
timeout = System.Diagnostics.Debugger.IsAttached ? Timeout.InfiniteTimeSpan : TimeSpan.FromSeconds(3); | ||
} | ||
|
||
var cts = new CancellationTokenSource(timeout.Value); | ||
|
||
// Queue a task to stop the test server from listening as soon as the response is available | ||
_ = Task.Run( | ||
async () => | ||
{ | ||
await context.Response.WaitToReadAsync(cts.Token); | ||
|
||
if (!cts.IsCancellationRequested) | ||
{ | ||
cts.Cancel(); | ||
} | ||
}, | ||
cts.Token); | ||
|
||
return cts; | ||
} | ||
|
||
private static bool LambdaServerWasShutDown(Exception exception) | ||
{ | ||
if (exception is not TargetInvocationException targetException || | ||
targetException.InnerException is not HttpRequestException httpException || | ||
httpException.InnerException is not SocketException socketException) | ||
{ | ||
return false; | ||
} | ||
|
||
return socketException.SocketErrorCode == SocketError.ConnectionRefused; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// Copyright (c) Martin Costello, 2019. All rights reserved. | ||
// Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information. | ||
|
||
using MartinCostello.Logging.XUnit; | ||
using MartinCostello.Testing.AwsLambdaTestServer; | ||
using Microsoft.AspNetCore.Hosting; | ||
using Microsoft.AspNetCore.Hosting.Server; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.Extensions.Logging; | ||
|
||
namespace MinimalApi; | ||
|
||
internal sealed class HttpLambdaTestServer : LambdaTestServer, IAsyncLifetime, ITestOutputHelperAccessor | ||
{ | ||
private readonly CancellationTokenSource _cts = new(); | ||
private bool _disposed; | ||
private IWebHost? _webHost; | ||
|
||
public HttpLambdaTestServer() | ||
: base() | ||
{ | ||
} | ||
|
||
public ITestOutputHelper? OutputHelper { get; set; } | ||
|
||
public async Task DisposeAsync() | ||
{ | ||
if (_webHost is not null) | ||
{ | ||
await _webHost.StopAsync(); | ||
} | ||
|
||
Dispose(); | ||
} | ||
|
||
public async Task InitializeAsync() | ||
=> await StartAsync(_cts.Token); | ||
|
||
protected override IServer CreateServer(WebHostBuilder builder) | ||
{ | ||
_webHost = builder | ||
.UseKestrel() | ||
.ConfigureServices((services) => services.AddLogging((builder) => builder.AddXUnit(this))) | ||
.UseUrls("http://127.0.0.1:0") | ||
.Build(); | ||
|
||
_webHost.Start(); | ||
|
||
return _webHost.Services.GetRequiredService<IServer>(); | ||
} | ||
|
||
protected override void Dispose(bool disposing) | ||
{ | ||
if (!_disposed) | ||
{ | ||
if (disposing) | ||
{ | ||
_webHost?.Dispose(); | ||
|
||
_cts.Cancel(); | ||
_cts.Dispose(); | ||
} | ||
|
||
_disposed = true; | ||
} | ||
|
||
base.Dispose(disposing); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<PropertyGroup> | ||
<IsPackable>false</IsPackable> | ||
<NoWarn>$(NoWarn);CA1062;CA1707;CA2007;CA2234;SA1600</NoWarn> | ||
<RootNamespace>MinimalApi</RootNamespace> | ||
<TargetFramework>net6.0</TargetFramework> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<Content Include="xunit.runner.json" CopyToOutputDirectory="PreserveNewest" /> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<PackageReference Include="MartinCostello.Logging.XUnit" /> | ||
<PackageReference Include="Microsoft.NET.Test.Sdk" /> | ||
<PackageReference Include="Shouldly" /> | ||
<PackageReference Include="xunit" /> | ||
<PackageReference Include="xunit.runner.visualstudio" /> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<ProjectReference Include="..\MinimalApi\MinimalApi.csproj" /> | ||
<ProjectReference Include="..\..\src\AwsLambdaTestServer\MartinCostello.Testing.AwsLambdaTestServer.csproj" /> | ||
</ItemGroup> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"methodDisplay": "method" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// Copyright (c) Martin Costello, 2019. All rights reserved. | ||
// Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information. | ||
|
||
namespace MinimalApi; | ||
|
||
public class HashRequest | ||
{ | ||
public string Algorithm { get; set; } = string.Empty; | ||
|
||
public string Format { get; set; } = string.Empty; | ||
|
||
public string Plaintext { get; set; } = string.Empty; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
// Copyright (c) Martin Costello, 2019. All rights reserved. | ||
// Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information. | ||
|
||
namespace MinimalApi; | ||
|
||
public class HashResponse | ||
{ | ||
public string Hash { get; set; } = string.Empty; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<Project Sdk="Microsoft.NET.Sdk.Web"> | ||
<PropertyGroup> | ||
<NoWarn>$(NoWarn);CA1050;CA1812;CA2007;CA5350;CA5351;SA1600</NoWarn> | ||
<RootNamespace>MinimalApi</RootNamespace> | ||
<TargetFramework>net6.0</TargetFramework> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<PackageReference Include="Amazon.Lambda.AspNetCoreServer.Hosting" /> | ||
</ItemGroup> | ||
</Project> |
Oops, something went wrong.