Skip to content

Commit 9eb5298

Browse files
committed
refactor and dynamodb tests
1 parent 2483ae7 commit 9eb5298

File tree

3 files changed

+116
-185
lines changed

3 files changed

+116
-185
lines changed

libraries/tests/e2e/functions/idempotency/Function/src/Function/Function.cs

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,39 @@
66
// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
77
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
88

9-
namespace Function;
10-
11-
public class Function
9+
namespace Function
1210
{
13-
public Function()
11+
public class Function
1412
{
15-
var tableName = Environment.GetEnvironmentVariable("IDEMPOTENCY_TABLE_NAME");
16-
Idempotency.Configure(builder => builder.UseDynamoDb(tableName));
17-
}
13+
public Function()
14+
{
15+
var tableName = Environment.GetEnvironmentVariable("IDEMPOTENCY_TABLE_NAME");
16+
Idempotency.Configure(builder => builder.UseDynamoDb(tableName));
17+
}
1818

19-
[Idempotent]
20-
public APIGatewayProxyResponse FunctionHandler(APIGatewayProxyRequest apigwProxyEvent, ILambdaContext context)
19+
[Idempotent]
20+
public APIGatewayProxyResponse FunctionHandler(APIGatewayProxyRequest apigwProxyEvent, ILambdaContext context)
21+
{
22+
return TestHelper.TestMethod(apigwProxyEvent);
23+
}
24+
}
25+
}
26+
27+
28+
namespace Function2
29+
{
30+
public class Function
2131
{
22-
return TestHelper.TestMethod(apigwProxyEvent);
32+
public Function()
33+
{
34+
// var tableName = Environment.GetEnvironmentVariable("IDEMPOTENCY_TABLE_NAME");
35+
// Idempotency.Configure(builder => builder.UseDynamoDb(tableName));
36+
}
37+
38+
// [Idempotent]
39+
public string FunctionHandler(APIGatewayProxyRequest apigwProxyEvent, ILambdaContext context)
40+
{
41+
return "Hello, World!";
42+
}
2343
}
24-
}
44+
}

libraries/tests/e2e/functions/idempotency/Function/test/Function.Tests/Function.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<PackageReference Include="Amazon.Lambda.APIGatewayEvents" Version="2.7.1" />
1111
<PackageReference Include="Amazon.Lambda.Core" Version="2.5.0" />
1212
<PackageReference Include="Amazon.Lambda.TestUtilities" Version="2.0.0" />
13+
<PackageReference Include="AWSSDK.DynamoDBv2" Version="3.7.405.11" />
1314
<PackageReference Include="AWSSDK.Lambda" Version="3.7.411.16" />
1415
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
1516
<PackageReference Include="xunit" Version="2.9.2" />
Lines changed: 84 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using System.Text.Json;
2+
using Amazon.DynamoDBv2;
3+
using Amazon.DynamoDBv2.Model;
24
using Amazon.Lambda;
35
using Amazon.Lambda.APIGatewayEvents;
46
using Xunit;
@@ -13,44 +15,52 @@ public class FunctionTests
1315
{
1416
private readonly ITestOutputHelper _testOutputHelper;
1517
private readonly AmazonLambdaClient _lambdaClient;
18+
private readonly AmazonDynamoDBClient _dynamoDbClient;
19+
private string _tableName = null!;
1620

1721
public FunctionTests(ITestOutputHelper testOutputHelper)
1822
{
1923
_testOutputHelper = testOutputHelper;
2024
_lambdaClient = new AmazonLambdaClient();
25+
_dynamoDbClient = new AmazonDynamoDBClient();
2126
}
2227

2328
[Trait("Category", "AOT")]
2429
[Theory]
25-
[InlineData("E2ETestLambda_X64_AOT_NET8_idempotency")]
26-
[InlineData("E2ETestLambda_ARM_AOT_NET8_idempotency")]
27-
public async Task AotFunctionTest(string functionName)
30+
[InlineData("E2ETestLambda_X64_AOT_NET8_idempotency", "IdempotencyTable-AOT-x86_64")]
31+
[InlineData("E2ETestLambda_ARM_AOT_NET8_idempotency", "IdempotencyTable-AOT-arm64")]
32+
public async Task IdempotencyHandlerAotTest(string functionName, string tableName)
2833
{
29-
await TestFunction(functionName);
34+
_tableName = tableName;
35+
await TestIdempotencyHandler(functionName);
3036
}
3137

3238
[Theory]
33-
[InlineData("E2ETestLambda_X64_NET6_idempotency")]
34-
[InlineData("E2ETestLambda_ARM_NET6_idempotency")]
35-
[InlineData("E2ETestLambda_X64_NET8_idempotency")]
36-
[InlineData("E2ETestLambda_ARM_NET8_idempotency")]
37-
public async Task FunctionTest(string functionName)
39+
[InlineData("E2ETestLambda_X64_NET6_idempotency", "IdempotencyTable")]
40+
[InlineData("E2ETestLambda_ARM_NET6_idempotency", "IdempotencyTable")]
41+
[InlineData("E2ETestLambda_X64_NET8_idempotency", "IdempotencyTable")]
42+
[InlineData("E2ETestLambda_ARM_NET8_idempotency", "IdempotencyTable")]
43+
public async Task IdempotencyHandlerTest(string functionName, string tableName)
3844
{
39-
await TestFunction(functionName);
45+
_tableName = tableName;
46+
await TestIdempotencyHandler(functionName);
4047
}
4148

42-
internal async Task TestFunction(string functionName)
49+
internal async Task TestIdempotencyHandler(string functionName)
4350
{
4451
var request = new InvokeRequest
4552
{
4653
FunctionName = functionName,
4754
InvocationType = InvocationType.RequestResponse,
4855
Payload = await File.ReadAllTextAsync("../../../../../../../payload.json"),
49-
LogType = LogType.Tail
56+
LogType = LogType.Tail,
5057
};
5158

52-
// run twice for cold and warm start
53-
for (int i = 0; i < 2; i++)
59+
var initialGuid = string.Empty;
60+
var initialRequestId = string.Empty;
61+
62+
// run three times to test idempotency
63+
for (int i = 0; i < 3; i++)
5464
{
5565
var response = await _lambdaClient.InvokeAsync(request);
5666

@@ -66,181 +76,81 @@ internal async Task TestFunction(string functionName)
6676
{
6777
Assert.Fail("Failed to parse payload.");
6878
}
69-
79+
7080
Assert.Equal(200, parsedPayload.StatusCode);
71-
Assert.Equal("HELLO WORLD", parsedPayload.Body);
81+
82+
var parsedResponse = JsonSerializer.Deserialize<Response>(parsedPayload.Body);
7283

73-
// Assert Output log from Lambda execution
74-
AssertOutputLog(functionName, response);
75-
}
76-
}
84+
if (parsedResponse == null)
85+
{
86+
Assert.Fail("Failed to parse response.");
87+
}
88+
89+
if(i == 0)
90+
{
91+
initialGuid = parsedResponse.MethodGuid;
92+
initialRequestId = parsedResponse.RequestId;
93+
}
7794

78-
private void AssertOutputLog(string functionName, InvokeResponse response)
79-
{
80-
// Extract and parse log
81-
var logResult = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(response.LogResult));
82-
_testOutputHelper.WriteLine(logResult);
83-
var output = OutputLogParser.ParseLogSegments(logResult, out var report);
84-
var isColdStart = report.initDuration != "N/A";
95+
Assert.Equal(initialGuid, parsedResponse.MethodGuid);
96+
Assert.Equal(initialRequestId, parsedResponse.RequestId);
97+
}
8598

86-
// Assert Logging utility
87-
// AssertEventLog(functionName, isColdStart, output[0]);
88-
// AssertInformationLog(functionName, isColdStart, output[1]);
89-
// AssertWarningLog(functionName, isColdStart, output[2]);
90-
// AssertExceptionLog(functionName, isColdStart, output[3]);
99+
// Query DynamoDB and assert results
100+
await AssertDynamoDbData(functionName, initialGuid, initialRequestId);
91101
}
92-
93-
private void AssertEventLog(string functionName, bool isColdStart, string output)
102+
103+
private async Task AssertDynamoDbData(string functionName, string initialGuid, string initialRequestId)
94104
{
95-
using JsonDocument doc = JsonDocument.Parse(output);
96-
JsonElement root = doc.RootElement;
105+
var id = $"{functionName}.FunctionHandler#35973cf447e6cc11008d603c791a232f";
106+
_testOutputHelper.WriteLine($"Querying DynamoDB with id: {id}");
97107

98-
AssertDefaultLoggingProperties.ArePresent(functionName, isColdStart, output);
99-
100-
if (!isColdStart)
108+
var queryRequest = new QueryRequest
101109
{
102-
Assert.True(root.TryGetProperty("LookupInfo", out JsonElement lookupInfoElement));
103-
Assert.True(lookupInfoElement.TryGetProperty("LookupId", out JsonElement lookupIdElement));
104-
Assert.Equal("c6af9ac6-7b61-11e6-9a41-93e8deadbeef", lookupIdElement.GetString());
105-
}
106-
107-
Assert.True(root.TryGetProperty("Level", out JsonElement levelElement));
108-
Assert.Equal("Information", levelElement.GetString());
109-
110-
Assert.True(root.TryGetProperty("Message", out JsonElement messageElement));
111-
Assert.True(messageElement.TryGetProperty("Resource", out JsonElement resourceElement));
112-
Assert.Equal("/{proxy+}", resourceElement.GetString());
113-
114-
Assert.True(messageElement.TryGetProperty("Path", out JsonElement pathElement));
115-
Assert.Equal("/path/to/resource", pathElement.GetString());
116-
117-
Assert.True(messageElement.TryGetProperty("HttpMethod", out JsonElement httpMethodElement));
118-
Assert.Equal("POST", httpMethodElement.GetString());
119-
120-
Assert.True(messageElement.TryGetProperty("Headers", out JsonElement headersElement));
121-
Assert.True(headersElement.TryGetProperty("Accept-Encoding", out JsonElement acceptEncodingElement));
122-
Assert.Equal("gzip, deflate, sdch", acceptEncodingElement.GetString());
123-
124-
Assert.True(headersElement.TryGetProperty("Accept-Language", out JsonElement acceptLanguageElement));
125-
Assert.Equal("en-US,en;q=0.8", acceptLanguageElement.GetString());
126-
127-
Assert.True(headersElement.TryGetProperty("Cache-Control", out JsonElement cacheControlElement));
128-
Assert.Equal("max-age=0", cacheControlElement.GetString());
129-
130-
Assert.True(
131-
messageElement.TryGetProperty("QueryStringParameters", out JsonElement queryStringParametersElement));
132-
Assert.True(queryStringParametersElement.TryGetProperty("Foo", out JsonElement fooElement));
133-
Assert.Equal("bar", fooElement.GetString());
134-
135-
Assert.True(messageElement.TryGetProperty("RequestContext", out JsonElement requestContextElement));
136-
Assert.True(requestContextElement.TryGetProperty("Path", out JsonElement requestContextPathElement));
137-
Assert.Equal("/prod/path/to/resource", requestContextPathElement.GetString());
138-
139-
Assert.True(requestContextElement.TryGetProperty("AccountId", out JsonElement accountIdElement));
140-
Assert.Equal("123456789012", accountIdElement.GetString());
141-
142-
Assert.True(requestContextElement.TryGetProperty("ResourceId", out JsonElement resourceIdElement));
143-
Assert.Equal("123456", resourceIdElement.GetString());
144-
145-
Assert.True(requestContextElement.TryGetProperty("Stage", out JsonElement stageElement));
146-
Assert.Equal("prod", stageElement.GetString());
147-
148-
Assert.True(requestContextElement.TryGetProperty("RequestId", out JsonElement requestIdElement));
149-
Assert.Equal("c6af9ac6-7b61-11e6-9a41-93e8deadbeef", requestIdElement.GetString());
150-
151-
Assert.True(requestContextElement.TryGetProperty("ResourcePath", out JsonElement resourcePathElement));
152-
Assert.Equal("/{proxy+}", resourcePathElement.GetString());
153-
154-
Assert.True(
155-
requestContextElement.TryGetProperty("HttpMethod", out JsonElement requestContextHttpMethodElement));
156-
Assert.Equal("POST", requestContextHttpMethodElement.GetString());
157-
158-
Assert.True(requestContextElement.TryGetProperty("ApiId", out JsonElement apiIdElement));
159-
Assert.Equal("1234567890", apiIdElement.GetString());
160-
161-
Assert.True(requestContextElement.TryGetProperty("RequestTime", out JsonElement requestTimeElement));
162-
Assert.Equal("09/Apr/2015:12:34:56 +0000", requestTimeElement.GetString());
163-
164-
Assert.True(requestContextElement.TryGetProperty("RequestTimeEpoch", out JsonElement requestTimeEpochElement));
165-
Assert.Equal(1428582896000, requestTimeEpochElement.GetInt64());
166-
167-
Assert.True(messageElement.TryGetProperty("Body", out JsonElement bodyElement));
168-
Assert.Equal("hello world", bodyElement.GetString());
169-
170-
Assert.True(messageElement.TryGetProperty("IsBase64Encoded", out JsonElement isBase64EncodedElement));
171-
Assert.False(isBase64EncodedElement.GetBoolean());
172-
}
173-
174-
private void AssertInformationLog(string functionName, bool isColdStart, string output)
175-
{
176-
using JsonDocument doc = JsonDocument.Parse(output);
177-
JsonElement root = doc.RootElement;
110+
TableName = _tableName,
111+
KeyConditionExpression = "id = :v_id",
112+
ExpressionAttributeValues = new Dictionary<string, AttributeValue>
113+
{
114+
{ ":v_id", new AttributeValue { S = id } }
115+
}
116+
};
117+
118+
_testOutputHelper.WriteLine($"QueryRequest: {JsonSerializer.Serialize(queryRequest)}");
178119

179-
AssertDefaultLoggingProperties.ArePresent(functionName, isColdStart, output);
120+
var queryResponse = await _dynamoDbClient.QueryAsync(queryRequest);
180121

181-
if (!isColdStart)
122+
_testOutputHelper.WriteLine($"QueryResponse: {JsonSerializer.Serialize(queryResponse)}");
123+
124+
if (queryResponse.Items.Count == 0)
182125
{
183-
Assert.True(root.TryGetProperty("LookupInfo", out JsonElement lookupInfoElement));
184-
Assert.True(lookupInfoElement.TryGetProperty("LookupId", out JsonElement lookupIdElement));
185-
Assert.Equal("c6af9ac6-7b61-11e6-9a41-93e8deadbeef", lookupIdElement.GetString());
126+
Assert.Fail("No items found in DynamoDB for the given id.");
186127
}
187128

188-
Assert.True(root.TryGetProperty("Level", out JsonElement levelElement));
189-
Assert.Equal("Information", levelElement.GetString());
190-
191-
Assert.True(root.TryGetProperty("Message", out JsonElement messageElement));
192-
Assert.Equal("Processing request started", messageElement.GetString());
193-
}
194-
195-
private static void AssertWarningLog(string functionName, bool isColdStart, string output)
196-
{
197-
using JsonDocument doc = JsonDocument.Parse(output);
198-
JsonElement root = doc.RootElement;
199-
200-
AssertDefaultLoggingProperties.ArePresent(functionName, isColdStart, output);
129+
foreach (var item in queryResponse.Items)
130+
{
131+
var data = item["data"].S;
132+
var status = item["status"].S;
201133

202-
Assert.True(root.TryGetProperty("LookupInfo", out JsonElement lookupInfoElement));
203-
Assert.True(lookupInfoElement.TryGetProperty("LookupId", out JsonElement lookupIdElement));
204-
Assert.Equal("c6af9ac6-7b61-11e6-9a41-93e8deadbeef", lookupIdElement.GetString());
134+
Assert.Equal("COMPLETED", status);
205135

206-
Assert.True(root.TryGetProperty("Level", out JsonElement levelElement));
207-
Assert.Equal("Warning", levelElement.GetString());
136+
var parsedData = JsonSerializer.Deserialize<APIGatewayProxyResponse>(data);
208137

209-
Assert.True(root.TryGetProperty("Test1", out JsonElement test1Element));
210-
Assert.Equal("value1", test1Element.GetString());
211-
212-
Assert.True(root.TryGetProperty("Test2", out JsonElement test2Element));
213-
Assert.Equal("value2", test2Element.GetString());
214-
215-
Assert.True(root.TryGetProperty("Message", out JsonElement messageElement));
216-
Assert.Equal("Warn with additional keys", messageElement.GetString());
138+
if (parsedData == null)
139+
{
140+
Assert.Fail("Failed to parse data field.");
141+
}
142+
143+
var parsedResponse = JsonSerializer.Deserialize<Response>(parsedData.Body);
144+
145+
if (parsedResponse == null)
146+
{
147+
Assert.Fail("Failed to parse response.");
148+
}
149+
150+
Assert.Equal(initialGuid, parsedResponse.MethodGuid);
151+
Assert.Equal(initialRequestId, parsedResponse.RequestId);
152+
}
217153
}
154+
}
218155

219-
private void AssertExceptionLog(string functionName, bool isColdStart, string output)
220-
{
221-
using JsonDocument doc = JsonDocument.Parse(output);
222-
JsonElement root = doc.RootElement;
223-
224-
AssertDefaultLoggingProperties.ArePresent(functionName, isColdStart, output);
225-
226-
Assert.True(root.TryGetProperty("LookupInfo", out JsonElement lookupInfoElement));
227-
Assert.True(lookupInfoElement.TryGetProperty("LookupId", out JsonElement lookupIdElement));
228-
Assert.Equal("c6af9ac6-7b61-11e6-9a41-93e8deadbeef", lookupIdElement.GetString());
229-
230-
Assert.True(root.TryGetProperty("Level", out JsonElement levelElement));
231-
Assert.Equal("Error", levelElement.GetString());
232-
233-
Assert.True(root.TryGetProperty("Message", out JsonElement messageElement));
234-
Assert.Equal("Oops something went wrong", messageElement.GetString());
235-
236-
Assert.True(root.TryGetProperty("Exception", out JsonElement exceptionElement));
237-
Assert.True(exceptionElement.TryGetProperty("Type", out JsonElement exceptionTypeElement));
238-
Assert.Equal("System.InvalidOperationException", exceptionTypeElement.GetString());
239-
240-
Assert.True(exceptionElement.TryGetProperty("Message", out JsonElement exceptionMessageElement));
241-
Assert.Equal("Parent exception message", exceptionMessageElement.GetString());
242-
243-
Assert.False(root.TryGetProperty("Test1", out JsonElement _));
244-
Assert.False(root.TryGetProperty("Test2", out JsonElement _));
245-
}
246-
}
156+
public record Response(string RequestId, string Greeting, string MethodGuid, string HandlerGuid);

0 commit comments

Comments
 (0)