Skip to content

Commit 7824a93

Browse files
committed
IT test
1 parent d1c1ccf commit 7824a93

7 files changed

Lines changed: 157 additions & 5 deletions

File tree

Libraries/test/IntegrationTests.Helpers/S3Helper.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Threading.Tasks;
33
using Amazon.S3;
44
using Amazon.S3.Model;
5+
using Amazon.S3.Util;
56

67
namespace IntegrationTests.Helpers
78
{
@@ -33,5 +34,13 @@ public async Task<bool> BucketExistsAsync(string bucketName)
3334
var response = await _s3Client.ListBucketsAsync(new ListBucketsRequest());
3435
return response.Buckets.Any(x => x.BucketName.Equals(bucketName));
3536
}
37+
38+
public async Task<GetBucketNotificationResponse> GetBucketNotificationAsync(string bucketName)
39+
{
40+
return await _s3Client.GetBucketNotificationAsync(new GetBucketNotificationRequest
41+
{
42+
BucketName = bucketName
43+
});
44+
}
3645
}
3746
}

Libraries/test/TestServerlessApp.IntegrationTests/DeploymentScript.ps1

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,15 @@ try
6868
Write-Host "Added TestQueue resource to serverless.template"
6969
}
7070

71+
# Add TestS3Bucket resource to serverless.template for S3 event integration testing
72+
# The source generator creates a Ref to TestS3Bucket but doesn't define the resource itself
73+
$template = Get-Content $templatePath | Out-String | ConvertFrom-Json
74+
if (-not $template.Resources.PSObject.Properties['TestS3Bucket']) {
75+
$template.Resources | Add-Member -NotePropertyName "TestS3Bucket" -NotePropertyValue @{ Type = "AWS::S3::Bucket" } -Force
76+
$template | ConvertTo-Json -Depth 100 | Set-Content $templatePath
77+
Write-Host "Added TestS3Bucket resource to serverless.template"
78+
}
79+
7180
dotnet restore
7281
Write-Host "Creating CloudFormation Stack $identifier, Architecture $arch, Runtime $runtime"
7382
dotnet lambda deploy-serverless --template-parameters "ArchitectureTypeParameter=$arch"

Libraries/test/TestServerlessApp.IntegrationTests/IntegrationTestContextFixture.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,20 @@ public class IntegrationTestContextFixture : IAsyncLifetime
2525

2626
public readonly LambdaHelper LambdaHelper;
2727
public readonly CloudWatchHelper CloudWatchHelper;
28+
public readonly S3Helper S3HelperInstance;
2829
public readonly HttpClient HttpClient;
2930

3031
public string RestApiUrlPrefix;
3132
public string HttpApiUrlPrefix;
3233
public string TestQueueARN;
34+
public string TestS3BucketName;
3335
public List<LambdaFunction> LambdaFunctions;
3436

3537
public IntegrationTestContextFixture()
3638
{
3739
_cloudFormationHelper = new CloudFormationHelper(new AmazonCloudFormationClient(Amazon.RegionEndpoint.USWest2));
3840
_s3Helper = new S3Helper(new AmazonS3Client(Amazon.RegionEndpoint.USWest2));
41+
S3HelperInstance = _s3Helper;
3942
LambdaHelper = new LambdaHelper(new AmazonLambdaClient(Amazon.RegionEndpoint.USWest2));
4043
CloudWatchHelper = new CloudWatchHelper(new AmazonCloudWatchLogsClient(Amazon.RegionEndpoint.USWest2));
4144
HttpClient = new HttpClient();
@@ -77,11 +80,17 @@ public async Task InitializeAsync()
7780
Console.WriteLine($"[IntegrationTest] TestQueue URL: {queueUrl}");
7881
Assert.False(string.IsNullOrEmpty(queueUrl), $"CloudFormation resource 'TestQueue' was not found in stack '{_stackName}'.");
7982
TestQueueARN = ConvertSqsUrlToArn(queueUrl);
83+
84+
// Get the S3 bucket name from the physical resource ID
85+
TestS3BucketName = await _cloudFormationHelper.GetResourcePhysicalIdAsync(_stackName, "TestS3Bucket");
86+
Console.WriteLine($"[IntegrationTest] TestS3Bucket: {TestS3BucketName}");
87+
Assert.False(string.IsNullOrEmpty(TestS3BucketName), $"CloudFormation resource 'TestS3Bucket' was not found in stack '{_stackName}'.");
88+
8089
LambdaFunctions = await LambdaHelper.FilterByCloudFormationStackAsync(_stackName);
8190
Console.WriteLine($"[IntegrationTest] Found {LambdaFunctions.Count} Lambda functions: {string.Join(", ", LambdaFunctions.Select(f => f.Name ?? "(null)"))}");
8291

8392
Assert.True(await _s3Helper.BucketExistsAsync(_bucketName), $"S3 bucket {_bucketName} should exist");
84-
Assert.Equal(36, LambdaFunctions.Count);
93+
Assert.Equal(37, LambdaFunctions.Count);
8594
Assert.False(string.IsNullOrEmpty(RestApiUrlPrefix), "RestApiUrlPrefix should not be empty");
8695
Assert.False(string.IsNullOrEmpty(HttpApiUrlPrefix), "HttpApiUrlPrefix should not be empty");
8796

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using System.Linq;
2+
using System.Threading.Tasks;
3+
using Amazon.S3;
4+
using Xunit;
5+
6+
namespace TestServerlessApp.IntegrationTests
7+
{
8+
[Collection("Integration Tests")]
9+
public class S3EventNotification
10+
{
11+
private readonly IntegrationTestContextFixture _fixture;
12+
13+
public S3EventNotification(IntegrationTestContextFixture fixture)
14+
{
15+
_fixture = fixture;
16+
}
17+
18+
[Fact]
19+
public async Task VerifyS3EventNotificationConfiguration()
20+
{
21+
// Verify the Lambda function exists in the stack
22+
var lambdaFunction = _fixture.LambdaFunctions
23+
.FirstOrDefault(x => string.Equals(x.LogicalId, "S3EventHandler"));
24+
Assert.NotNull(lambdaFunction);
25+
Assert.NotNull(lambdaFunction.Name);
26+
27+
// Verify S3 bucket notification is configured correctly
28+
var notificationConfig = await _fixture.S3HelperInstance
29+
.GetBucketNotificationAsync(_fixture.TestS3BucketName);
30+
31+
var lambdaConfigs = notificationConfig.LambdaFunctionConfigurations;
32+
Assert.Single(lambdaConfigs);
33+
34+
var config = lambdaConfigs.First();
35+
36+
// Verify the notification points to the correct Lambda function ARN
37+
Assert.Contains(lambdaFunction.Name, config.FunctionArn);
38+
39+
// Verify the event type is s3:ObjectCreated:*
40+
Assert.Single(config.Events);
41+
Assert.Equal(EventType.ObjectCreatedAll, config.Events.First());
42+
43+
// Verify the suffix filter is .json
44+
var filterRules = config.Filter.S3KeyFilter.FilterRules;
45+
Assert.Single(filterRules);
46+
var suffixRule = filterRules.First(r => string.Equals(r.Name, "suffix", System.StringComparison.OrdinalIgnoreCase));
47+
Assert.Equal(".json", suffixRule.Value);
48+
}
49+
}
50+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using Amazon.Lambda.Annotations;
2+
using Amazon.Lambda.Annotations.S3;
3+
using Amazon.Lambda.Core;
4+
using Amazon.Lambda.S3Events;
5+
using System;
6+
7+
namespace TestServerlessApp.S3EventExamples
8+
{
9+
public class S3EventProcessing
10+
{
11+
[LambdaFunction(ResourceName = "S3EventHandler", Policies = "AWSLambdaBasicExecutionRole,AmazonS3ReadOnlyAccess", PackageType = LambdaPackageType.Image)]
12+
[S3Event("@TestS3Bucket", Events = "s3:ObjectCreated:*", FilterSuffix = ".json")]
13+
public void ProcessS3Event(S3Event evnt)
14+
{
15+
Console.WriteLine($"Received S3 event with {evnt.Records.Count} records");
16+
}
17+
}
18+
}

Libraries/test/TestServerlessApp/aws-lambda-tools-defaults.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"template": "serverless.template",
1414
"template-parameters": "",
1515
"docker-host-build-output-dir": "./bin/Release/lambda-publish",
16-
"s3-bucket": "test-serverless-app",
17-
"stack-name": "test-serverless-app",
18-
"function-architecture": "x86_64"
19-
}
16+
"s3-bucket" : "test-serverless-app-843e7392",
17+
"stack-name" : "test-serverless-app-843e7392",
18+
"function-architecture" : "x86_64"
19+
}

Libraries/test/TestServerlessApp/serverless.template

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,6 +1339,63 @@
13391339
]
13401340
}
13411341
}
1342+
},
1343+
"S3EventHandler": {
1344+
"Type": "AWS::Serverless::Function",
1345+
"Metadata": {
1346+
"Tool": "Amazon.Lambda.Annotations",
1347+
"SyncedEvents": [
1348+
"TestS3Bucket"
1349+
],
1350+
"SyncedEventProperties": {
1351+
"TestS3Bucket": [
1352+
"Bucket.Ref",
1353+
"Events",
1354+
"Filter.S3Key.Rules"
1355+
]
1356+
}
1357+
},
1358+
"Properties": {
1359+
"MemorySize": 512,
1360+
"Timeout": 30,
1361+
"Policies": [
1362+
"AWSLambdaBasicExecutionRole",
1363+
"AmazonS3ReadOnlyAccess"
1364+
],
1365+
"PackageType": "Image",
1366+
"ImageUri": ".",
1367+
"ImageConfig": {
1368+
"Command": [
1369+
"TestServerlessApp::TestServerlessApp.S3EventExamples.S3EventProcessing_ProcessS3Event_Generated::ProcessS3Event"
1370+
]
1371+
},
1372+
"Events": {
1373+
"TestS3Bucket": {
1374+
"Type": "S3",
1375+
"Properties": {
1376+
"Events": [
1377+
"s3:ObjectCreated:*"
1378+
],
1379+
"Filter": {
1380+
"S3Key": {
1381+
"Rules": [
1382+
{
1383+
"Name": "suffix",
1384+
"Value": ".json"
1385+
}
1386+
]
1387+
}
1388+
},
1389+
"Bucket": {
1390+
"Ref": "TestS3Bucket"
1391+
}
1392+
}
1393+
}
1394+
}
1395+
}
1396+
},
1397+
"TestS3Bucket": {
1398+
"Type": "AWS::S3::Bucket"
13421399
}
13431400
}
13441401
}

0 commit comments

Comments
 (0)