public static async Task Function_Reverses_Numbers_With_Custom_Options() { // Arrange var options = new LambdaTestServerOptions() { FunctionMemorySize = 256, FunctionTimeout = TimeSpan.FromSeconds(30), FunctionVersion = 42, }; using var server = new LambdaTestServer(options); 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); var actual = JsonSerializer.Deserialize <int[]>(response.Content); Assert.NotNull(actual); Assert.Equal(new[] { 3, 2, 1 }, actual); }
public void Constructor_Validates_Parameters() { // Arrange LambdaTestServerOptions options = null !; // Act and Assert Assert.Throws <ArgumentNullException>("options", () => new LambdaTestServer(options)); }
public static void Constructor_Initializes_Defaults() { // Act var actual = new LambdaTestServerOptions(); // Assert actual.Configure.ShouldBeNull(); actual.FunctionArn.ShouldNotBeNullOrEmpty(); actual.FunctionHandler.ShouldBe(string.Empty); actual.FunctionMemorySize.ShouldBe(128); actual.FunctionTimeout.ShouldBe(TimeSpan.FromSeconds(3)); actual.FunctionVersion.ShouldBe(1); actual.LogGroupName.ShouldNotBeNullOrEmpty(); actual.LogStreamName.ShouldNotBeNullOrEmpty(); }
/// <summary> /// Initializes a new instance of the <see cref="RuntimeHandler"/> class. /// </summary> /// <param name="options">The test server's options.</param> /// <param name="cancellationToken">The cancellation token that is signalled when request listening should stop.</param> internal RuntimeHandler(LambdaTestServerOptions options, CancellationToken cancellationToken) { _cancellationToken = cancellationToken; _options = options; // Support multi-threaded access to the request queue, although the default // usage scenario would be a single reader and writer from a test method. var channelOptions = new UnboundedChannelOptions() { SingleReader = false, SingleWriter = false, }; _requests = Channel.CreateUnbounded <LambdaTestRequest>(channelOptions); _responses = new ConcurrentDictionary <string, ResponseContext>(StringComparer.Ordinal); }
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); }
/// <summary> /// Initializes a new instance of the <see cref="LambdaTestServer"/> class. /// </summary> /// <param name="options">The options to use to configure the test Lambda runtime server.</param> /// <exception cref="ArgumentNullException"> /// <paramref name="options"/> is <see langword="null"/>. /// </exception> public LambdaTestServer(LambdaTestServerOptions options) { Options = options ?? throw new ArgumentNullException(nameof(options)); _onDisposed = new CancellationTokenSource(); }