Skip to content

Commit

Permalink
aws-powertools#1298 added new E2E tests for ALB event, which should t…
Browse files Browse the repository at this point in the history
…rigger a validation exception
  • Loading branch information
Pascal Romanens committed Oct 30, 2023
1 parent 3f64d55 commit 46f7f4c
Show file tree
Hide file tree
Showing 15 changed files with 372 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<version>1.0.0</version>
</parent>

<artifactId>e2e-test-handler-validation</artifactId>
<artifactId>e2e-test-handler-validation-alb-event</artifactId>
<packaging>jar</packaging>
<name>A Lambda function using Powertools for AWS Lambda (Java) validation</name>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package software.amazon.lambda.powertools.e2e;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent;
import com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerResponseEvent;
import com.amazonaws.services.lambda.runtime.events.SQSBatchResponse;

import software.amazon.lambda.powertools.validation.Validation;
public class Function implements RequestHandler<ApplicationLoadBalancerRequestEvent, ApplicationLoadBalancerResponseEvent> {
// @Validation(inboundSchema = "classpath:/validation/inbound_schema.json", outboundSchema = "classpath:/validation/outbound_schema.json")
// public String handleRequest(SQSEvent input, Context context) {
// return "OK";
// }


@Validation(inboundSchema = "classpath:/validation/inbound_schema.json", outboundSchema = "classpath:/validation/outbound_schema.json")
// @Validation(inboundSchema = "classpath:/validation/inbound_schema.json")
public ApplicationLoadBalancerResponseEvent handleRequest(ApplicationLoadBalancerRequestEvent input, Context context) {
ApplicationLoadBalancerResponseEvent response = new ApplicationLoadBalancerResponseEvent();
response.setBody(input.getBody());
response.setStatusCode(200);
response.setIsBase64Encoded(false);
return response;
}
}
60 changes: 60 additions & 0 deletions powertools-e2e-tests/handlers/validation-apigw-event/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>software.amazon.lambda</groupId>
<artifactId>e2e-test-handlers-parent</artifactId>
<version>1.0.0</version>
</parent>

<artifactId>e2e-test-handler-validation-apigw-event</artifactId>
<packaging>jar</packaging>
<name>A Lambda function using Powertools for AWS Lambda (Java) validation</name>

<dependencies>
<dependency>
<groupId>software.amazon.lambda</groupId>
<artifactId>powertools-validation</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-events</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>dev.aspectj</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<complianceLevel>${maven.compiler.target}</complianceLevel>
<aspectLibraries>
<aspectLibrary>
<groupId>software.amazon.lambda</groupId>
<artifactId>powertools-validation</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<Console name="JsonAppender" target="SYSTEM_OUT">
<JsonTemplateLayout eventTemplateUri="classpath:LambdaJsonLayout.json" />
</Console>
</Appenders>
<Loggers>
<Root level="INFO">
<AppenderRef ref="JsonAppender"/>
</Root>
<Logger name="JsonLogger" level="INFO" additivity="false">
<AppenderRef ref="JsonAppender"/>
</Logger>
</Loggers>
</Configuration>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "http://example.com/product.json",
"type": "object",
"title": "Product schema",
"description": "JSON schema to validate Products",
"default": {},
"examples": [
{
"id": 43242,
"name": "FooBar XY",
"price": 258
}
],
"required": [
"price"
],
"properties": {
"price": {
"$id": "#/properties/price",
"type": "number",
"title": "Price of the product",
"description": "Positive price of the product",
"default": 0,
"exclusiveMinimum": 0,
"examples": [
258.99
]
}
},
"additionalProperties": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "http://example.com/product.json",
"type": "object",
"title": "Product schema",
"description": "JSON schema to validate Products",
"default": {},
"examples": [
{
"id": 43242,
"name": "FooBar XY",
"price": 258
}
],
"required": [
"price"
],
"properties": {
"price": {
"$id": "#/properties/price",
"type": "number",
"title": "Price of the product",
"description": "Positive price of the product",
"default": 0,
"exclusiveMaximum": 1000,
"examples": [
258.99
]
}
},
"additionalProperties": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package software.amazon.lambda.powertools;

import static org.assertj.core.api.Assertions.assertThat;
import static software.amazon.lambda.powertools.testutils.Infrastructure.FUNCTION_NAME_OUTPUT;
import static software.amazon.lambda.powertools.testutils.lambda.LambdaInvoker.invokeFunction;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import software.amazon.lambda.powertools.testutils.Infrastructure;
import software.amazon.lambda.powertools.testutils.lambda.InvocationResult;

class ValidationALBE2ET {

private static final ObjectMapper objectMapper = new ObjectMapper();

private static Infrastructure infrastructure;
private static String functionName;

@BeforeAll
@Timeout(value = 5, unit = TimeUnit.MINUTES)
public static void setup() {
infrastructure = Infrastructure.builder().testName(ValidationALBE2ET.class.getSimpleName())
.pathToFunction("validation-alb-event").build();
Map<String, String> outputs = infrastructure.deploy();
functionName = outputs.get(FUNCTION_NAME_OUTPUT);
}

@AfterAll
public static void tearDown() {
if (infrastructure != null) {
infrastructure.destroy();
}
}

@Test
void test_validInboundSQSEvent() throws IOException {
InputStream inputStream = this.getClass().getResourceAsStream("/validation/valid_alb_in_out_event.json");
String validEvent = IOUtils.toString(inputStream, StandardCharsets.UTF_8);

// WHEN
InvocationResult invocationResult = invokeFunction(functionName, validEvent);

// THEN
// invocation should pass validation and return 200
JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult());
assertThat(validJsonNode.get("statusCode").asInt()).isEqualTo(200);
assertThat(validJsonNode.get("body").asText()).isEqualTo("{\"price\": 150}");
}

@Test
void test_invalidInboundSQSEvent() throws IOException {
InputStream inputStream = this.getClass().getResourceAsStream("/validation/invalid_alb_in_event.json");
String invalidEvent = IOUtils.toString(inputStream, StandardCharsets.UTF_8);

// WHEN
InvocationResult invocationResult = invokeFunction(functionName, invalidEvent);

// THEN
// invocation should fail inbound validation and return an error message
JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult());
assertThat(validJsonNode.get("errorMessage").asText()).contains("$.price: is missing but it is required");
}

@Test
void test_invalidOutboundSQSEvent() throws IOException {
InputStream inputStream = this.getClass().getResourceAsStream("/validation/invalid_alb_out_event.json");
String invalidEvent = IOUtils.toString(inputStream, StandardCharsets.UTF_8);

// WHEN
InvocationResult invocationResult = invokeFunction(functionName, invalidEvent);

// THEN
// invocation should fail outbound validation and return 400
JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult());
assertThat(validJsonNode.get("errorMessage").asText()).contains("$.price: must have an exclusive maximum value of 1000");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
import software.amazon.lambda.powertools.testutils.Infrastructure;
import software.amazon.lambda.powertools.testutils.lambda.InvocationResult;

class ValidationE2ET {
class ValidationApiGWE2ET {

private static final ObjectMapper objectMapper = new ObjectMapper();

Expand All @@ -46,8 +46,8 @@ class ValidationE2ET {
@BeforeAll
@Timeout(value = 5, unit = TimeUnit.MINUTES)
public static void setup() {
infrastructure = Infrastructure.builder().testName(ValidationE2ET.class.getSimpleName())
.pathToFunction("validation").build();
infrastructure = Infrastructure.builder().testName(ValidationApiGWE2ET.class.getSimpleName())
.pathToFunction("validation-apigw-event").build();
Map<String, String> outputs = infrastructure.deploy();
functionName = outputs.get(FUNCTION_NAME_OUTPUT);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"requestContext": {
"elb": {
"targetGroupArn": "arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/lambda-279XGJDqGZ5rsrHC2Fjr/49e9d65c45c6791a"
}
},
"httpMethod": "POST",
"path": "/path/to/resource",
"queryStringParameters": {
"query": "1234ABCD"
},
"headers": {
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
"accept-encoding": "gzip",
"accept-language": "en-US,en;q=0.9",
"connection": "keep-alive",
"host": "lambda-alb-123578498.us-east-2.elb.amazonaws.com",
"upgrade-insecure-requests": "1",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36",
"x-amzn-trace-id": "Root=1-5c536348-3d683b8b04734faae651f476",
"x-forwarded-for": "72.12.164.125",
"x-forwarded-port": "80",
"x-forwarded-proto": "http",
"x-imforwards": "20"
},
"body": "{\"message\": \"Lambda rocks\"}",
"isBase64Encoded": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"requestContext": {
"elb": {
"targetGroupArn": "arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/lambda-279XGJDqGZ5rsrHC2Fjr/49e9d65c45c6791a"
}
},
"httpMethod": "POST",
"path": "/path/to/resource",
"queryStringParameters": {
"query": "1234ABCD"
},
"headers": {
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
"accept-encoding": "gzip",
"accept-language": "en-US,en;q=0.9",
"connection": "keep-alive",
"host": "lambda-alb-123578498.us-east-2.elb.amazonaws.com",
"upgrade-insecure-requests": "1",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36",
"x-amzn-trace-id": "Root=1-5c536348-3d683b8b04734faae651f476",
"x-forwarded-for": "72.12.164.125",
"x-forwarded-port": "80",
"x-forwarded-proto": "http",
"x-imforwards": "20"
},
"body": "{\"price\": 50000}",
"isBase64Encoded": true
}
Loading

0 comments on commit 46f7f4c

Please sign in to comment.