Skip to content

Commit 7f604e4

Browse files
authored
ci: Fix infrastructure deployment and assertions in end-to-end tests. (#1816)
* Fix CDK Stack creation in e2e tests. * Fix timezone problem in MetricsE2ET.java. * Fix tracing E2E tests. * Consistently use UTC time in MetricsE2ET. * Fix LargeMessageE2ET. Initialize ExtendedSQSClient with correct region and use Autoclosable.
1 parent 0358d64 commit 7f604e4

File tree

7 files changed

+186
-166
lines changed

7 files changed

+186
-166
lines changed

Diff for: powertools-e2e-tests/handlers/tracing/src/main/java/software/amazon/lambda/powertools/e2e/Function.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,4 @@ private String buildMessage(String message, String funcName) {
5252
}
5353
return String.format("%s (%s)", message, funcName);
5454
}
55-
}
55+
}

Diff for: powertools-e2e-tests/pom.xml

+3-3
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030
<properties>
3131
<maven.compiler.source>11</maven.compiler.source>
3232
<maven.compiler.target>11</maven.compiler.target>
33-
<constructs.version>10.3.0</constructs.version>
34-
<cdk.version>2.162.1</cdk.version>
33+
<constructs.version>10.4.2</constructs.version>
34+
<cdk.version>2.186.0</cdk.version>
3535
</properties>
3636

3737
<dependencies>
@@ -231,4 +231,4 @@
231231
</profile>
232232
</profiles>
233233

234-
</project>
234+
</project>

Diff for: powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LargeMessageE2ET.java

+51-48
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
import static org.assertj.core.api.Assertions.assertThat;
44
import static software.amazon.lambda.powertools.testutils.Infrastructure.FUNCTION_NAME_OUTPUT;
55

6-
import com.amazon.sqs.javamessaging.AmazonSQSExtendedClient;
7-
import com.amazon.sqs.javamessaging.ExtendedClientConfiguration;
86
import java.io.IOException;
97
import java.io.InputStream;
108
import java.nio.charset.StandardCharsets;
@@ -14,6 +12,7 @@
1412
import java.util.Map;
1513
import java.util.UUID;
1614
import java.util.concurrent.TimeUnit;
15+
1716
import org.apache.commons.io.IOUtils;
1817
import org.junit.jupiter.api.AfterAll;
1918
import org.junit.jupiter.api.AfterEach;
@@ -22,6 +21,10 @@
2221
import org.junit.jupiter.api.Timeout;
2322
import org.slf4j.Logger;
2423
import org.slf4j.LoggerFactory;
24+
25+
import com.amazon.sqs.javamessaging.AmazonSQSExtendedClient;
26+
import com.amazon.sqs.javamessaging.ExtendedClientConfiguration;
27+
2528
import software.amazon.awssdk.http.SdkHttpClient;
2629
import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
2730
import software.amazon.awssdk.regions.Region;
@@ -101,21 +104,20 @@ public void reset() {
101104
@Test
102105
public void bigSQSMessageOffloadedToS3_shouldLoadFromS3() throws IOException, InterruptedException {
103106
// given
104-
final ExtendedClientConfiguration extendedClientConfig =
105-
new ExtendedClientConfiguration()
106-
.withPayloadSupportEnabled(s3Client, bucketName);
107-
AmazonSQSExtendedClient client =
108-
new AmazonSQSExtendedClient(SqsClient.builder().httpClient(httpClient).build(), extendedClientConfig);
109-
InputStream inputStream = this.getClass().getResourceAsStream("/large_sqs_message.txt");
110-
String bigMessage = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
111-
112-
// when
113-
client.sendMessage(SendMessageRequest
114-
.builder()
115-
.queueUrl(queueUrl)
116-
.messageBody(bigMessage)
117-
.build());
118-
107+
final ExtendedClientConfiguration extendedClientConfig = new ExtendedClientConfiguration()
108+
.withPayloadSupportEnabled(s3Client, bucketName);
109+
try (AmazonSQSExtendedClient client = new AmazonSQSExtendedClient(
110+
SqsClient.builder().region(region).httpClient(httpClient).build(), extendedClientConfig)) {
111+
InputStream inputStream = this.getClass().getResourceAsStream("/large_sqs_message.txt");
112+
String bigMessage = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
113+
114+
// when
115+
client.sendMessage(SendMessageRequest
116+
.builder()
117+
.queueUrl(queueUrl)
118+
.messageBody(bigMessage)
119+
.build());
120+
}
119121
Thread.sleep(30000); // wait for function to be executed
120122

121123
// then
@@ -137,36 +139,37 @@ public void bigSQSMessageOffloadedToS3_shouldLoadFromS3() throws IOException, In
137139
@Test
138140
public void smallSQSMessage_shouldNotReadFromS3() throws IOException, InterruptedException {
139141
// given
140-
final ExtendedClientConfiguration extendedClientConfig =
141-
new ExtendedClientConfiguration()
142-
.withPayloadSupportEnabled(s3Client, bucketName);
143-
AmazonSQSExtendedClient client =
144-
new AmazonSQSExtendedClient(SqsClient.builder().httpClient(httpClient).build(), extendedClientConfig);
145-
String message = "Hello World";
146-
147-
// when
148-
client.sendMessage(SendMessageRequest
149-
.builder()
150-
.queueUrl(queueUrl)
151-
.messageBody(message)
152-
.build());
153-
154-
Thread.sleep(30000); // wait for function to be executed
155-
156-
// then
157-
QueryRequest request = QueryRequest
158-
.builder()
159-
.tableName(tableName)
160-
.keyConditionExpression("functionName = :func")
161-
.expressionAttributeValues(
162-
Collections.singletonMap(":func", AttributeValue.builder().s(functionName).build()))
163-
.build();
164-
QueryResponse response = dynamoDbClient.query(request);
165-
List<Map<String, AttributeValue>> items = response.items();
166-
assertThat(items).hasSize(1);
167-
messageId = items.get(0).get("id").s();
168-
assertThat(Integer.valueOf(items.get(0).get("bodySize").n())).isEqualTo(
169-
message.getBytes(StandardCharsets.UTF_8).length);
170-
assertThat(items.get(0).get("bodyMD5").s()).isEqualTo("b10a8db164e0754105b7a99be72e3fe5");
142+
final ExtendedClientConfiguration extendedClientConfig = new ExtendedClientConfiguration()
143+
.withPayloadSupportEnabled(s3Client, bucketName);
144+
try (AmazonSQSExtendedClient client = new AmazonSQSExtendedClient(
145+
SqsClient.builder().region(region).httpClient(httpClient).build(),
146+
extendedClientConfig)) {
147+
String message = "Hello World";
148+
149+
// when
150+
client.sendMessage(SendMessageRequest
151+
.builder()
152+
.queueUrl(queueUrl)
153+
.messageBody(message)
154+
.build());
155+
156+
Thread.sleep(30000); // wait for function to be executed
157+
158+
// then
159+
QueryRequest request = QueryRequest
160+
.builder()
161+
.tableName(tableName)
162+
.keyConditionExpression("functionName = :func")
163+
.expressionAttributeValues(
164+
Collections.singletonMap(":func", AttributeValue.builder().s(functionName).build()))
165+
.build();
166+
QueryResponse response = dynamoDbClient.query(request);
167+
List<Map<String, AttributeValue>> items = response.items();
168+
assertThat(items).hasSize(1);
169+
messageId = items.get(0).get("id").s();
170+
assertThat(Integer.valueOf(items.get(0).get("bodySize").n())).isEqualTo(
171+
message.getBytes(StandardCharsets.UTF_8).length);
172+
assertThat(items.get(0).get("bodyMD5").s()).isEqualTo("b10a8db164e0754105b7a99be72e3fe5");
173+
}
171174
}
172175
}

Diff for: powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/MetricsE2ET.java

+31-36
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,8 @@
1818
import static software.amazon.lambda.powertools.testutils.Infrastructure.FUNCTION_NAME_OUTPUT;
1919
import static software.amazon.lambda.powertools.testutils.lambda.LambdaInvoker.invokeFunction;
2020

21+
import java.time.Clock;
2122
import java.time.Instant;
22-
import java.time.LocalDateTime;
23-
import java.time.ZoneOffset;
2423
import java.time.temporal.ChronoUnit;
2524
import java.util.Collections;
2625
import java.util.List;
@@ -29,10 +28,12 @@
2928
import java.util.concurrent.TimeUnit;
3029
import java.util.stream.Collectors;
3130
import java.util.stream.Stream;
31+
3232
import org.junit.jupiter.api.AfterAll;
3333
import org.junit.jupiter.api.BeforeAll;
3434
import org.junit.jupiter.api.Test;
3535
import org.junit.jupiter.api.Timeout;
36+
3637
import software.amazon.lambda.powertools.testutils.Infrastructure;
3738
import software.amazon.lambda.powertools.testutils.lambda.InvocationResult;
3839
import software.amazon.lambda.powertools.testutils.metrics.MetricsFetcher;
@@ -51,9 +52,9 @@ public static void setup() {
5152
.pathToFunction("metrics")
5253
.environmentVariables(
5354
Stream.of(new String[][] {
54-
{"POWERTOOLS_METRICS_NAMESPACE", namespace},
55-
{"POWERTOOLS_SERVICE_NAME", service}
56-
})
55+
{ "POWERTOOLS_METRICS_NAMESPACE", namespace },
56+
{ "POWERTOOLS_SERVICE_NAME", service }
57+
})
5758
.collect(Collectors.toMap(data -> data[0], data -> data[1])))
5859
.build();
5960
Map<String, String> outputs = infrastructure.deploy();
@@ -71,60 +72,54 @@ public static void tearDown() {
7172
public void test_recordMetrics() {
7273
// GIVEN
7374

74-
Instant currentTimeTruncatedToMinutes =
75-
LocalDateTime.now().truncatedTo(ChronoUnit.MINUTES).toInstant(ZoneOffset.UTC);
75+
Instant currentTimeTruncatedToMinutes = Instant.now(Clock.systemUTC()).truncatedTo(ChronoUnit.MINUTES);
76+
String event1 = "{ \"metrics\": {\"orders\": 1, \"products\": 4}, \"dimensions\": { \"Environment\": \"test\"}, \"highResolution\": \"false\"}";
7677

77-
String event1 =
78-
"{ \"metrics\": {\"orders\": 1, \"products\": 4}, \"dimensions\": { \"Environment\": \"test\"}, \"highResolution\": \"false\"}";
79-
80-
String event2 =
81-
"{ \"metrics\": {\"orders\": 1, \"products\": 8}, \"dimensions\": { \"Environment\": \"test\"}, \"highResolution\": \"true\"}";
78+
String event2 = "{ \"metrics\": {\"orders\": 1, \"products\": 8}, \"dimensions\": { \"Environment\": \"test\"}, \"highResolution\": \"true\"}";
8279
// WHEN
8380
InvocationResult invocationResult = invokeFunction(functionName, event1);
8481

8582
invokeFunction(functionName, event2);
8683

8784
// THEN
8885
MetricsFetcher metricsFetcher = new MetricsFetcher();
89-
List<Double> coldStart =
90-
metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, namespace,
91-
"ColdStart", Stream.of(new String[][] {
92-
{"FunctionName", functionName},
93-
{"Service", service}}
94-
).collect(Collectors.toMap(data -> data[0], data -> data[1])));
86+
List<Double> coldStart = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60,
87+
namespace,
88+
"ColdStart", Stream.of(new String[][] {
89+
{ "FunctionName", functionName },
90+
{ "Service", service } }).collect(Collectors.toMap(data -> data[0], data -> data[1])));
9591
assertThat(coldStart.get(0)).isEqualTo(1);
96-
List<Double> orderMetrics =
97-
metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, namespace,
98-
"orders", Collections.singletonMap("Environment", "test"));
92+
List<Double> orderMetrics = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(),
93+
60, namespace,
94+
"orders", Collections.singletonMap("Environment", "test"));
9995
assertThat(orderMetrics.get(0)).isEqualTo(2);
100-
List<Double> productMetrics =
101-
metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, namespace,
102-
"products", Collections.singletonMap("Environment", "test"));
96+
List<Double> productMetrics = metricsFetcher.fetchMetrics(invocationResult.getStart(),
97+
invocationResult.getEnd(), 60, namespace,
98+
"products", Collections.singletonMap("Environment", "test"));
10399

104-
// When searching across a 1 minute time period with a period of 60 we find both metrics and the sum is 12
100+
// When searching across a 1 minute time period with a period of 60 we find both metrics and the sum is 12
105101

106102
assertThat(productMetrics.get(0)).isEqualTo(12);
107103

108-
orderMetrics =
109-
metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, namespace,
110-
"orders", Collections.singletonMap("Service", service));
104+
orderMetrics = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60,
105+
namespace,
106+
"orders", Collections.singletonMap("Service", service));
111107
assertThat(orderMetrics.get(0)).isEqualTo(2);
112-
productMetrics =
113-
metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, namespace,
114-
"products", Collections.singletonMap("Service", service));
108+
productMetrics = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60,
109+
namespace,
110+
"products", Collections.singletonMap("Service", service));
115111
assertThat(productMetrics.get(0)).isEqualTo(12);
116112

117113
Instant searchStartTime = currentTimeTruncatedToMinutes.plusSeconds(15);
118114
Instant searchEndTime = currentTimeTruncatedToMinutes.plusSeconds(45);
119115

120-
List<Double> productMetricDataResult =
121-
metricsFetcher.fetchMetrics(searchStartTime, searchEndTime, 1, namespace,
122-
"products", Collections.singletonMap("Environment", "test"));
116+
List<Double> productMetricDataResult = metricsFetcher.fetchMetrics(searchStartTime, searchEndTime, 1, namespace,
117+
"products", Collections.singletonMap("Environment", "test"));
123118

124-
// We are searching across the time period the metric was created but with a period of 1 second. Only the high resolution metric will be available at this point
119+
// We are searching across the time period the metric was created but with a period of 1 second. Only the high
120+
// resolution metric will be available at this point
125121

126122
assertThat(productMetricDataResult.get(0)).isEqualTo(8);
127123

128-
129124
}
130125
}

Diff for: powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/TracingE2ET.java

+41-25
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@
1818
import static software.amazon.lambda.powertools.testutils.Infrastructure.FUNCTION_NAME_OUTPUT;
1919
import static software.amazon.lambda.powertools.testutils.lambda.LambdaInvoker.invokeFunction;
2020

21-
import java.util.Collections;
2221
import java.util.Map;
2322
import java.util.UUID;
2423
import java.util.concurrent.TimeUnit;
24+
2525
import org.junit.jupiter.api.AfterAll;
2626
import org.junit.jupiter.api.BeforeAll;
2727
import org.junit.jupiter.api.Test;
2828
import org.junit.jupiter.api.Timeout;
29+
2930
import software.amazon.lambda.powertools.testutils.Infrastructure;
3031
import software.amazon.lambda.powertools.testutils.lambda.InvocationResult;
3132
import software.amazon.lambda.powertools.testutils.tracing.SegmentDocument.SubSegment;
@@ -45,7 +46,9 @@ public static void setup() {
4546
.testName(TracingE2ET.class.getSimpleName())
4647
.pathToFunction("tracing")
4748
.tracing(true)
48-
.environmentVariables(Collections.singletonMap("POWERTOOLS_SERVICE_NAME", service))
49+
.environmentVariables(
50+
Map.of("POWERTOOLS_SERVICE_NAME", service,
51+
"POWERTOOLS_TRACER_CAPTURE_RESPONSE", "true"))
4952
.build();
5053
Map<String, String> outputs = infrastructure.deploy();
5154
functionName = outputs.get(FUNCTION_NAME_OUTPUT);
@@ -61,45 +64,58 @@ public static void tearDown() {
6164
@Test
6265
public void test_tracing() {
6366
// GIVEN
64-
String message = "Hello World";
65-
String event = String.format("{\"message\":\"%s\"}", message);
66-
String result = String.format("%s (%s)", message, functionName);
67+
final String message = "Hello World";
68+
final String event = String.format("{\"message\":\"%s\"}", message);
69+
final String result = String.format("%s (%s)", message, functionName);
6770

6871
// WHEN
69-
InvocationResult invocationResult = invokeFunction(functionName, event);
72+
final InvocationResult invocationResult = invokeFunction(functionName, event);
7073

7174
// THEN
72-
Trace trace = TraceFetcher.builder()
75+
final Trace trace = TraceFetcher.builder()
7376
.start(invocationResult.getStart())
7477
.end(invocationResult.getEnd())
7578
.functionName(functionName)
7679
.build()
7780
.fetchTrace();
7881

79-
assertThat(trace.getSubsegments()).hasSize(1);
80-
SubSegment handleRequest = trace.getSubsegments().get(0);
81-
assertThat(handleRequest.getName()).isEqualTo("## handleRequest");
82-
assertThat(handleRequest.getAnnotations()).hasSize(2);
83-
assertThat(handleRequest.getAnnotations().get("ColdStart")).isEqualTo(true);
84-
assertThat(handleRequest.getAnnotations().get("Service")).isEqualTo(service);
85-
assertThat(handleRequest.getMetadata()).hasSize(1);
86-
Map<String, Object> metadata = (Map<String, Object>) handleRequest.getMetadata().get(service);
87-
assertThat(metadata.get("handleRequest response")).isEqualTo(result);
88-
assertThat(handleRequest.getSubsegments()).hasSize(2);
89-
90-
SubSegment sub = handleRequest.getSubsegments().get(0);
82+
assertThat(trace.getSubsegments()).hasSize(2);
83+
84+
// We need to filter segments based on name because they are not returned in-order from the X-Ray API
85+
// The Init segment is created by default for Lambda functions in X-Ray
86+
final SubSegment initSegment = trace.getSubsegments().stream()
87+
.filter(subSegment -> subSegment.getName().equals("Init"))
88+
.findFirst().orElse(null);
89+
assertThat(initSegment.getName()).isEqualTo("Init");
90+
assertThat(initSegment.getAnnotations()).isNull();
91+
92+
final SubSegment handleRequestSegment = trace.getSubsegments().stream()
93+
.filter(subSegment -> subSegment.getName().equals("## handleRequest"))
94+
.findFirst().orElse(null);
95+
assertThat(handleRequestSegment.getName()).isEqualTo("## handleRequest");
96+
assertThat(handleRequestSegment.getAnnotations()).hasSize(2);
97+
assertThat(handleRequestSegment.getAnnotations()).containsEntry("ColdStart", true);
98+
assertThat(handleRequestSegment.getAnnotations()).containsEntry("Service", service);
99+
assertThat(handleRequestSegment.getMetadata()).hasSize(1);
100+
final Map<String, Object> metadata = (Map<String, Object>) handleRequestSegment.getMetadata().get(service);
101+
assertThat(metadata).containsEntry("handleRequest response", result);
102+
assertThat(handleRequestSegment.getSubsegments()).hasSize(2);
103+
104+
SubSegment sub = handleRequestSegment.getSubsegments().get(0);
91105
assertThat(sub.getName()).isIn("## internal_stuff", "## buildMessage");
92106

93-
sub = handleRequest.getSubsegments().get(1);
107+
sub = handleRequestSegment.getSubsegments().get(1);
94108
assertThat(sub.getName()).isIn("## internal_stuff", "## buildMessage");
95109

96-
SubSegment buildMessage = handleRequest.getSubsegments().stream()
97-
.filter(subSegment -> subSegment.getName().equals("## buildMessage")).findFirst().orElse(null);
110+
SubSegment buildMessage = handleRequestSegment.getSubsegments().stream()
111+
.filter(subSegment -> subSegment.getName().equals("## buildMessage"))
112+
.findFirst().orElse(null);
98113
assertThat(buildMessage).isNotNull();
99114
assertThat(buildMessage.getAnnotations()).hasSize(1);
100-
assertThat(buildMessage.getAnnotations().get("message")).isEqualTo(message);
115+
assertThat(buildMessage.getAnnotations()).containsEntry("message", message);
101116
assertThat(buildMessage.getMetadata()).hasSize(1);
102-
metadata = (Map<String, Object>) buildMessage.getMetadata().get(service);
103-
assertThat(metadata.get("buildMessage response")).isEqualTo(result);
117+
final Map<String, Object> buildMessageSegmentMetadata = (Map<String, Object>) buildMessage.getMetadata()
118+
.get(service);
119+
assertThat(buildMessageSegmentMetadata).containsEntry("buildMessage response", result);
104120
}
105121
}

0 commit comments

Comments
 (0)