Skip to content

Commit d805b3b

Browse files
committed
get base test setup working
1 parent f9c7c1c commit d805b3b

File tree

12 files changed

+1021
-0
lines changed

12 files changed

+1021
-0
lines changed

pom.xml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
<maven.compiler.source>17</maven.compiler.source>
2323
<maven.compiler.target>17</maven.compiler.target>
2424
<maven-checkstyle-plugin.version>3.2.0</maven-checkstyle-plugin.version>
25+
<testcontainers.version>1.19.7</testcontainers.version>
2526

2627
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
2728
</properties>
@@ -69,16 +70,57 @@
6970
<artifactId>spring-boot-starter-test</artifactId>
7071
<scope>test</scope>
7172
</dependency>
73+
<dependency>
74+
<groupId>org.testcontainers</groupId>
75+
<artifactId>testcontainers</artifactId>
76+
<version>${testcontainers.version}</version>
77+
<scope>test</scope>
78+
</dependency>
7279
<dependency>
7380
<groupId>org.json</groupId>
7481
<artifactId>json</artifactId>
7582
<version>20231013</version>
7683
</dependency>
7784

85+
<!-- LocalStack TestContainers -->
86+
<dependency>
87+
<groupId>org.testcontainers</groupId>
88+
<artifactId>localstack</artifactId>
89+
<version>${testcontainers.version}</version>
90+
<scope>test</scope>
91+
</dependency>
92+
<dependency>
93+
<groupId>org.testcontainers</groupId>
94+
<artifactId>junit-jupiter</artifactId>
95+
<version>${testcontainers.version}</version>
96+
<scope>test</scope>
97+
</dependency>
98+
99+
<!-- AWS SDK v2 Dependencies -->
100+
<dependency>
101+
<groupId>software.amazon.awssdk</groupId>
102+
<artifactId>lambda</artifactId>
103+
</dependency>
104+
<dependency>
105+
<groupId>software.amazon.awssdk</groupId>
106+
<artifactId>iam</artifactId>
107+
</dependency>
108+
<dependency>
109+
<groupId>software.amazon.awssdk</groupId>
110+
<artifactId>sns</artifactId>
111+
</dependency>
112+
78113
</dependencies>
79114

80115
<dependencyManagement>
81116
<dependencies>
117+
<dependency>
118+
<groupId>org.testcontainers</groupId>
119+
<artifactId>testcontainers-bom</artifactId>
120+
<version>${testcontainers.version}</version>
121+
<type>pom</type>
122+
<scope>import</scope>
123+
</dependency>
82124
<dependency>
83125
<groupId>software.amazon.awssdk</groupId>
84126
<artifactId>bom</artifactId>

src/.DS_Store

6 KB
Binary file not shown.

src/test/.DS_Store

6 KB
Binary file not shown.

src/test/java/.DS_Store

6 KB
Binary file not shown.
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
package dev.ancaghenade.shipmentlistdemo.integrationtests;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertNotEquals;
5+
import static org.junit.jupiter.api.Assertions.assertTrue;
6+
7+
import java.io.IOException;
8+
import java.nio.file.Files;
9+
import java.nio.file.Path;
10+
import java.security.MessageDigest;
11+
import java.security.NoSuchAlgorithmException;
12+
import java.util.Map;
13+
import org.junit.jupiter.api.BeforeAll;
14+
import org.junit.jupiter.api.MethodOrderer;
15+
import org.junit.jupiter.api.Order;
16+
import org.junit.jupiter.api.Test;
17+
import org.junit.jupiter.api.TestMethodOrder;
18+
import org.springframework.core.io.ByteArrayResource;
19+
import org.springframework.http.HttpEntity;
20+
import org.springframework.http.HttpHeaders;
21+
import org.springframework.http.HttpMethod;
22+
import org.springframework.http.HttpStatus;
23+
import org.springframework.http.MediaType;
24+
import org.springframework.http.ResponseEntity;
25+
import org.springframework.test.context.ActiveProfiles;
26+
import org.springframework.util.LinkedMultiValueMap;
27+
import org.springframework.util.MultiValueMap;
28+
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
29+
import software.amazon.awssdk.services.dynamodb.model.GetItemRequest;
30+
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
31+
import software.amazon.awssdk.services.s3.model.NoSuchKeyException;
32+
33+
34+
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
35+
public class LambdaIntegrationTest extends LocalStackSetupConfigurations {
36+
37+
@BeforeAll
38+
public static void setup() throws IOException, InterruptedException, org.json.JSONException {
39+
LocalStackSetupConfigurations.setupConfig();
40+
localStack.followOutput(logConsumer);
41+
42+
createClients();
43+
44+
createS3Bucket();
45+
createDynamoDBResources();
46+
createIAMRole();
47+
createLambdaResources();
48+
createBucketNotificationConfiguration();
49+
createSNS();
50+
createSQS();
51+
createSNSSubscription();
52+
53+
lambdaClient.close();
54+
snsClient.close();
55+
sqsClient.close();
56+
iamClient.close();
57+
58+
}
59+
60+
@Test
61+
@Order(1)
62+
void testFileAddWatermarkInLambda() {
63+
64+
// prepare the file to upload
65+
var imageData = new byte[0];
66+
try {
67+
imageData = Files.readAllBytes(Path.of("src/test/java/resources/cat.jpg"));
68+
} catch (IOException e) {
69+
e.printStackTrace();
70+
}
71+
var resource = new ByteArrayResource(imageData) {
72+
@Override
73+
public String getFilename() {
74+
return "cat.jpg";
75+
}
76+
};
77+
78+
var originalHash = applyHash(imageData);
79+
80+
var shipmentId = "3317ac4f-1f9b-4bab-a974-4aa9876d5547";
81+
// build the URL with the id as a path variable
82+
var postUrl = "/api/shipment/" + shipmentId + "/image/upload";
83+
var getUrl = "/api/shipment/" + shipmentId + "/image/download";
84+
85+
// set the request headers
86+
var headers = new HttpHeaders();
87+
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
88+
// request body with the file resource and headers
89+
MultiValueMap<String, Object> requestBody = new LinkedMultiValueMap<>();
90+
requestBody.add("file", resource);
91+
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(requestBody,
92+
headers);
93+
94+
ResponseEntity<String> postResponse = restTemplate.exchange(BASE_URL + postUrl,
95+
HttpMethod.POST, requestEntity, String.class);
96+
97+
assertEquals(HttpStatus.OK, postResponse.getStatusCode());
98+
99+
// give the Lambda time to start up and process the image
100+
try {
101+
Thread.sleep(15000);
102+
103+
} catch (InterruptedException e) {
104+
e.printStackTrace();
105+
}
106+
107+
ResponseEntity<byte[]> responseEntity = restTemplate.exchange(BASE_URL + getUrl,
108+
HttpMethod.GET, null, byte[].class);
109+
110+
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
111+
112+
var watermarkHash = applyHash(responseEntity.getBody());
113+
114+
assertNotEquals(originalHash, watermarkHash);
115+
116+
}
117+
118+
@Test
119+
@Order(2)
120+
void testFileProcessedInLambdaHasMetadata() {
121+
var getItemRequest = GetItemRequest.builder()
122+
.tableName("shipment")
123+
.key(Map.of(
124+
"shipmentId",
125+
AttributeValue.builder().s("3317ac4f-1f9b-4bab-a974-4aa9876d5547").build())).build();
126+
127+
var getItemResponse = dynamoDbClient.getItem(getItemRequest);
128+
129+
dynamoDbClient.getItem(getItemRequest);
130+
GetObjectRequest getObjectRequest = GetObjectRequest.builder()
131+
.bucket(BUCKET_NAME)
132+
.key(getItemResponse.item().get("imageLink").s())
133+
.build();
134+
try {
135+
// already processed objects have a metadata field added, not be processed again
136+
var s3ObjectResponse = s3Client.getObject(getObjectRequest);
137+
assertTrue(s3ObjectResponse.response().metadata().entrySet().stream().anyMatch(
138+
entry -> entry.getKey().equals("exclude-lambda") && entry.getValue().equals("true")));
139+
} catch (NoSuchKeyException noSuchKeyException) {
140+
noSuchKeyException.printStackTrace();
141+
}
142+
dynamoDbClient.close();
143+
s3Client.close();
144+
145+
146+
}
147+
148+
private String applyHash(byte[] data) {
149+
String hashValue = null;
150+
try {
151+
var digest = MessageDigest.getInstance("SHA-256");
152+
153+
// get the hash of the byte array
154+
var hash = digest.digest(data);
155+
156+
// convert the hash bytes to a hexadecimal representation
157+
var hexString = new StringBuilder();
158+
for (byte b : hash) {
159+
var hex = Integer.toHexString(0xff & b);
160+
if (hex.length() == 1) {
161+
hexString.append('0');
162+
}
163+
hexString.append(hex);
164+
}
165+
hashValue = hexString.toString();
166+
System.out.println("Hash value: " + hashValue);
167+
} catch (NoSuchAlgorithmException e) {
168+
e.printStackTrace();
169+
}
170+
return hashValue;
171+
}
172+
}

0 commit comments

Comments
 (0)