public static async Task Function_Reverses_Numbers_With_Mobile_Sdk() { // Arrange using var server = new LambdaTestServer(); using var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(1)); await server.StartAsync(cancellationTokenSource.Token); int[] value = new[] { 1, 2, 3 }; byte[] content = JsonSerializer.SerializeToUtf8Bytes(value); var request = new LambdaTestRequest(content) { ClientContext = JsonSerializer.Serialize(new { client = new { app_title = "my-app" } }), CognitoIdentity = JsonSerializer.Serialize(new { identityId = "my-identity" }), }; LambdaTestContext context = await server.EnqueueAsync(content); using var httpClient = server.CreateClient(); // Act await ReverseFunction.RunAsync(httpClient, cancellationTokenSource.Token); // Assert Assert.True(context.Response.TryRead(out LambdaTestResponse? response)); Assert.NotNull(response); Assert.True(response !.IsSuccessful); var actual = JsonSerializer.Deserialize <int[]>(response.Content); Assert.NotNull(actual); Assert.Equal(new[] { 3, 2, 1 }, actual); }
public static async Task Function_Computes_Results(double left, string op, double right, double expected) { // Arrange using var server = new LambdaTestServer(); using var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(1)); await server.StartAsync(cancellationTokenSource.Token); var value = new MathsRequest() { Left = left, Operator = op, Right = right }; string json = JsonSerializer.Serialize(value); var context = await server.EnqueueAsync(json); using var httpClient = server.CreateClient(); // Act await MathsFunction.RunAsync(httpClient, cancellationTokenSource.Token); // Assert Assert.True(context.Response.TryRead(out var response)); Assert.NotNull(response); Assert.True(response !.IsSuccessful); json = await response.ReadAsStringAsync(); var actual = JsonSerializer.Deserialize <MathsResponse>(json); Assert.NotNull(actual); Assert.Equal(expected, actual !.Result); }
public static async Task Function_Reverses_Numbers() { // Arrange using var server = new LambdaTestServer(); using var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(1)); await server.StartAsync(cancellationTokenSource.Token); int[] value = new[] { 1, 2, 3 }; byte[] json = JsonSerializer.SerializeToUtf8Bytes(value); LambdaTestContext context = await server.EnqueueAsync(json); using var httpClient = server.CreateClient(); // Act await ReverseFunction.RunAsync(httpClient, cancellationTokenSource.Token); // Assert Assert.True(context.Response.TryRead(out LambdaTestResponse? response)); Assert.True(response !.IsSuccessful); Assert.NotNull(response.Content); var actual = JsonSerializer.Deserialize <int[]>(response.Content); Assert.NotNull(actual); Assert.Equal(new[] { 3, 2, 1 }, actual); }
public async Task Function_Can_Handle_Failed_Initialization() { // Arrange void Configure(IServiceCollection services) { services.AddLogging((builder) => builder.AddXUnit(this)); } using var server = new LambdaTestServer(Configure); using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(2)); await server.StartAsync(cts.Token); var context = await server.EnqueueAsync(@"{""Values"": null}"); _ = Task.Run(async() => { await context.Response.WaitToReadAsync(cts.Token); if (!cts.IsCancellationRequested) { cts.Cancel(); } }); using var httpClient = server.CreateClient(); // Act await Assert.ThrowsAsync <InvalidOperationException>( () => FunctionRunner.RunAsync <MyFailedInitializationHandler>(httpClient, cts.Token)); }
public static async Task Function_Can_Process_Multiple_Requests_On_Different_Threads() { // Arrange int messageCount = 1_000; int expected = Enumerable.Range(0, messageCount).Sum(); using var server = new LambdaTestServer(); using var cts = new CancellationTokenSource(); await server.StartAsync(cts.Token); using var httpClient = server.CreateClient(); // Enqueue the requests to process in the background var completedAdding = EnqueueInParallel(messageCount, server); // Start a task to consume the responses in the background var completedProcessing = Assert(completedAdding, messageCount, cts); // Act - Start the function processing await ReverseFunction.RunAsync(httpClient, cts.Token); // Assert int actual = await completedProcessing.Task; actual.ShouldBe(expected); }
public void CreateClient_Throws_If_Not_Started() { // Arrange using var target = new LambdaTestServer(); // Act Assert.Throws <InvalidOperationException>(() => target.CreateClient()); }
public async Task Function_Can_Process_Multiple_Requests() { // Arrange void Configure(IServiceCollection services) { services.AddLogging((builder) => builder.AddXUnit(this)); } using var server = new LambdaTestServer(Configure); using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(2)); await server.StartAsync(cts.Token); var channels = new List <(int Expected, LambdaTestContext Context)>(); for (int i = 0; i < 10; i++) { var request = new MyRequest() { Values = Enumerable.Range(1, i + 1).ToArray(), }; channels.Add((request.Values.Sum(), await server.EnqueueAsync(request))); } _ = Task.Run(async() => { foreach ((var _, var context) in channels) { await context.Response.WaitToReadAsync(cts.Token); } if (!cts.IsCancellationRequested) { cts.Cancel(); } }); using var httpClient = server.CreateClient(); // Act await MyFunctionEntrypoint.RunAsync(httpClient, cts.Token); // Assert foreach ((int expected, var context) in channels) { context.Response.TryRead(out var response).ShouldBeTrue(); response.ShouldNotBeNull(); response !.IsSuccessful.ShouldBeTrue(); response.Content.ShouldNotBeNull(); var deserialized = response.ReadAs <MyResponse>(); deserialized.Sum.ShouldBe(expected); } }
public void CreateClient_Throws_If_Disposed() { // Arrange var target = new LambdaTestServer(); target.Dispose(); // Act Assert.Throws <ObjectDisposedException>(() => target.CreateClient()); }
public static async Task Function_Can_Process_Request() { // Arrange - Create a test server for the Lambda runtime to use using var server = new LambdaTestServer(); // Create a cancellation token that stops the server listening for new requests. // Auto-cancel the server after 2 seconds in case something goes wrong and the request is not handled. using var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(2)); // Start the test server so it is ready to listen for requests from the Lambda runtime await server.StartAsync(cancellationTokenSource.Token); // Create a test request for the Lambda function being tested var value = new MyRequest() { Values = new[] { 1, 2, 3 }, // The function returns the sum of the specified numbers }; string requestJson = JsonSerializer.Serialize(value); // Queue the request with the server to invoke the Lambda function and // store the ChannelReader into a variable to use to read the response. LambdaTestContext context = await server.EnqueueAsync(requestJson); // Queue a task to stop the test server from listening as soon as the response is available _ = Task.Run(async() => { await context.Response.WaitToReadAsync(cancellationTokenSource.Token); if (!cancellationTokenSource.IsCancellationRequested) { cancellationTokenSource.Cancel(); } }); // Create an HttpClient for the Lambda to use with LambdaBootstrap using var httpClient = server.CreateClient(); // Act - Start the Lambda runtime and run until the cancellation token is signalled await MyFunctionEntrypoint.RunAsync(httpClient, cancellationTokenSource.Token); // Assert - The channel reader should have the response available context.Response.TryRead(out LambdaTestResponse? response).ShouldBeTrue("No Lambda response is available."); response !.IsSuccessful.ShouldBeTrue("The Lambda function failed to handle the request."); response.Content.ShouldNotBeEmpty("The Lambda function did not return any content."); string responseJson = await response.ReadAsStringAsync(); var actual = JsonSerializer.Deserialize <MyResponse>(responseJson); actual.ShouldNotBeNull(); actual.Sum.ShouldBe(6, "The Lambda function returned an incorrect response."); }
public async Task Function_Can_Process_Request_With_Mobile_Sdk_Headers() { // Arrange void Configure(IServiceCollection services) { services.AddLogging((builder) => builder.AddXUnit(this)); } using var server = new LambdaTestServer(Configure); using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(2)); await server.StartAsync(cts.Token); byte[] content = Encoding.UTF8.GetBytes(@"{""Values"": [ 1, 2, 3 ]}"); var request = new LambdaTestRequest(content) { ClientContext = "{}", CognitoIdentity = "{}", }; var context = await server.EnqueueAsync(request); _ = Task.Run(async() => { await context.Response.WaitToReadAsync(cts.Token); if (!cts.IsCancellationRequested) { cts.Cancel(); } }); using var httpClient = server.CreateClient(); // Act await MyFunctionEntrypoint.RunAsync(httpClient, cts.Token); // Assert context.Response.TryRead(out var response).ShouldBeTrue(); response.ShouldNotBeNull(); response !.IsSuccessful.ShouldBeTrue(); }
public async Task Function_Returns_If_No_Requests_Within_Timeout() { // Arrange void Configure(IServiceCollection services) { services.AddLogging((builder) => builder.AddXUnit(this)); } using var server = new LambdaTestServer(Configure); using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(2)); await server.StartAsync(cts.Token); using var httpClient = server.CreateClient(); // Act await MyFunctionEntrypoint.RunAsync(httpClient, cts.Token); // Assert cts.IsCancellationRequested.ShouldBeTrue(); }
public async Task Function_Can_Process_Request() { // Arrange void Configure(IServiceCollection services) { services.AddLogging((builder) => builder.AddXUnit(this)); } using var server = new LambdaTestServer(Configure); using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(2)); await server.StartAsync(cts.Token); var context = await server.EnqueueAsync(@"{""Values"": [ 1, 2, 3 ]}"); _ = Task.Run(async() => { await context.Response.WaitToReadAsync(cts.Token); if (!cts.IsCancellationRequested) { cts.Cancel(); } }); using var httpClient = server.CreateClient(); // Act await MyFunctionEntrypoint.RunAsync(httpClient, cts.Token); // Assert context.Response.TryRead(out var response).ShouldBeTrue(); response.ShouldNotBeNull(); response !.IsSuccessful.ShouldBeTrue(); response.Content.ShouldNotBeNull(); response.Duration.ShouldBeGreaterThan(TimeSpan.Zero); Encoding.UTF8.GetString(response.Content).ShouldBe(@"{""Sum"":6}"); }
public async Task Can_Use_Custom_Function_Variables() { // Arrange LambdaTestServer.ClearLambdaEnvironmentVariables(); var options = new LambdaTestServerOptions() { FunctionArn = "my-custom-arn", FunctionHandler = "my-custom-handler", FunctionMemorySize = 1024, FunctionName = "my-function-name", FunctionTimeout = TimeSpan.FromSeconds(119), FunctionVersion = 42, LogGroupName = "my-log-group", LogStreamName = "my-log-stream", }; using var server = new LambdaTestServer(options); using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(2)); await server.StartAsync(cts.Token); var request = new LambdaTestRequest(Array.Empty <byte>(), "my-request-id") { ClientContext = @"{""client"":{""app_title"":""my-app""}}", CognitoIdentity = @"{""cognitoIdentityId"":""my-identity""}", }; var context = await server.EnqueueAsync(request); _ = Task.Run(async() => { await context.Response.WaitToReadAsync(cts.Token); if (!cts.IsCancellationRequested) { cts.Cancel(); } }); using var httpClient = server.CreateClient(); // Act await CustomFunction.RunAsync(httpClient, cts.Token); // Assert context.Response.TryRead(out var response).ShouldBeTrue(); response.ShouldNotBeNull(); response !.IsSuccessful.ShouldBeTrue(); response.Content.ShouldNotBeNull(); var lambdaContext = response.ReadAs <IDictionary <string, string> >(); lambdaContext.ShouldContainKeyAndValue("AwsRequestId", request.AwsRequestId); lambdaContext.ShouldContainKeyAndValue("ClientContext", "my-app"); lambdaContext.ShouldContainKeyAndValue("FunctionName", options.FunctionName); lambdaContext.ShouldContainKeyAndValue("FunctionVersion", "42"); lambdaContext.ShouldContainKeyAndValue("IdentityId", "my-identity"); lambdaContext.ShouldContainKeyAndValue("InvokedFunctionArn", options.FunctionArn); lambdaContext.ShouldContainKeyAndValue("LogGroupName", options.LogGroupName); lambdaContext.ShouldContainKeyAndValue("LogStreamName", options.LogStreamName); lambdaContext.ShouldContainKeyAndValue("MemoryLimitInMB", "1024"); lambdaContext.ShouldContainKey("RemainingTime"); string remainingTimeString = lambdaContext["RemainingTime"]; TimeSpan.TryParse(remainingTimeString, out var remainingTime).ShouldBeTrue(); remainingTime.Minutes.ShouldBe(options.FunctionTimeout.Minutes); }
public async Task Alexa_Function_Can_Process_Request() { // Arrange SkillRequest request = CreateRequest <LaunchRequest>(); request.Request.Type = "LaunchRequest"; string json = JsonConvert.SerializeObject(request); void Configure(IServiceCollection services) { services.AddLogging((builder) => builder.AddXUnit(this)); } using var server = new LambdaTestServer(Configure); using var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(2)); await server.StartAsync(cancellationTokenSource.Token); LambdaTestContext context = await server.EnqueueAsync(json); // Queue a task to stop the Lambda function as soon as the response is processed _ = Task.Run(async() => { await context.Response.WaitToReadAsync(cancellationTokenSource.Token); if (!cancellationTokenSource.IsCancellationRequested) { cancellationTokenSource.Cancel(); } }); using var httpClient = server.CreateClient(); // Act await FunctionEntrypoint.RunAsync(httpClient, cancellationTokenSource.Token); // Assert context.Response.TryRead(out LambdaTestResponse result).ShouldBeTrue(); result.ShouldNotBeNull(); result.IsSuccessful.ShouldBeTrue(); result.Duration.ShouldBeInRange(TimeSpan.FromTicks(1), TimeSpan.FromSeconds(1)); result.Content.ShouldNotBeEmpty(); json = await result.ReadAsStringAsync(); var actual = JsonConvert.DeserializeObject <SkillResponse>(json); actual.ShouldNotBeNull(); ResponseBody response = AssertResponse(actual, shouldEndSession: false); response.Card.ShouldBeNull(); response.Reprompt.ShouldBeNull(); response.OutputSpeech.ShouldNotBeNull(); response.OutputSpeech.Type.ShouldBe("SSML"); var ssml = response.OutputSpeech.ShouldBeOfType <SsmlOutputSpeech>(); ssml.Ssml.ShouldBe("<speak>Welcome to London Travel. You can ask me about disruption or for the status of any tube line, London Overground, the D.L.R. or T.F.L. Rail.</speak>"); }