Skip to content

Enabling Local Testing with RIE and Improving Tests Coverability #560

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Aug 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions aws-lambda-java-runtime-interface-client/Dockerfile.rie
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FROM public.ecr.aws/lambda/java:21

COPY target/aws-lambda-java-runtime-interface-client-*.jar ${LAMBDA_TASK_ROOT}/
COPY target/aws-lambda-java-core-*.jar ${LAMBDA_TASK_ROOT}/
COPY target/aws-lambda-java-serialization-*.jar ${LAMBDA_TASK_ROOT}/
COPY test-handlers/EchoHandler.class ${LAMBDA_TASK_ROOT}/

CMD ["EchoHandler::handleRequest"]
6 changes: 5 additions & 1 deletion aws-lambda-java-runtime-interface-client/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ publish:
test-publish:
./ric-dev-environment/test-platform-specific-jar-snapshot.sh

.PHONY: test-rie
test-rie:
./scripts/test-rie.sh "EchoHandler::handleRequest"

define HELP_MESSAGE

Usage: $ make [TARGETS]
Expand All @@ -74,5 +78,5 @@ TARGETS
dev Run all development tests after a change.
pr Perform all checks before submitting a Pull Request.
test Run the Unit tests.

test-rie Build and test RIC locally with Lambda Runtime Interface Emulator. (Requires building the project first)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice!

endef
43 changes: 43 additions & 0 deletions aws-lambda-java-runtime-interface-client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,49 @@ This command invokes the function running in the container image and returns a r

*Alternately, you can also include RIE as a part of your base image. See the AWS documentation on how to [Build RIE into your base image](https://docs.aws.amazon.com/lambda/latest/dg/images-test.html#images-test-alternative).*

### Automated Local Testing

For developers working on this runtime interface client, we provide an automated testing script that handles RIE setup, dependency management, and Docker orchestration.

*Prerequisites:*
- Build the project first: `mvn clean install`
- Docker must be installed and running

*To run automated tests:*

```shell script
make test-rie
```

This single command will:
- Automatically download required dependencies (aws-lambda-java-core, aws-lambda-java-serialization)
- Build a Docker image with RIE pre-installed
- Compile and run a test Lambda function (EchoHandler)
- Execute the function and validate the response
- Clean up containers automatically

The test uses a simple EchoHandler that returns the input event, making it easy to verify the runtime interface client is working correctly.

## Test Coverage

This project uses JaCoCo for code coverage analysis. To exclude classes from JaCoCo coverage, add them to the `jacoco-maven-plugin` configuration:

```xml
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/*Exception.class</exclude>
<exclude>**/dto/*.class</exclude>
<exclude>**/YourClassName.class</exclude>
</excludes>
</configuration>
</plugin>
```

This project excludes by default: exceptions, interfaces, DTOs, constants, and runtime-only classes.

### Troubleshooting

While running integration tests, you might encounter the Docker Hub rate limit error with the following body:
Expand Down
18 changes: 18 additions & 0 deletions aws-lambda-java-runtime-interface-client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,24 @@
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.maven.plugin.version}</version>
<configuration>
<excludes>
<!-- Exclude simple exceptions (compiler enforced) -->
<exclude>**/*Exception.class</exclude>
<!-- Exclude interfaces (compiler enforced) -->
<exclude>**/Resource.class</exclude>
<!-- Exclude simple DTOs/POJOs (data containers) -->
<exclude>**/dto/*.class</exclude>
<!-- Exclude constants classes (build-time values) -->
<exclude>**/ReservedRuntimeEnvironmentVariables.class</exclude>
<exclude>**/RapidErrorType.class</exclude>
<!-- Exclude enum-like data holders -->
<exclude>**/FrameType.class</exclude>
<exclude>**/StructuredLogMessage.class</exclude>
<!-- Exclude main entry point (runtime-only) -->
<exclude>**/AWSLambda.class</exclude>
</excludes>
</configuration>
Comment on lines +217 to +234
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

<executions>
<execution>
<id>default-prepare-agent</id>
Expand Down
46 changes: 46 additions & 0 deletions aws-lambda-java-runtime-interface-client/scripts/test-rie.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/bin/bash
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
SERIALIZATION_ROOT="$(dirname "$PROJECT_ROOT")/aws-lambda-java-serialization"

if ! ls "$PROJECT_ROOT"/target/aws-lambda-java-runtime-interface-client-*.jar >/dev/null 2>&1; then
echo "RIC jar not found. Please build the project first with 'mvn package'."
exit 1
fi

IMAGE_TAG="java-ric-rie-test"

HANDLER="${1:-EchoHandler::handleRequest}"

echo "Starting RIE test setup for Java..."

# Build local dependencies if not present
CORE_ROOT="$(dirname "$PROJECT_ROOT")/aws-lambda-java-core"
if ! ls "$PROJECT_ROOT"/target/aws-lambda-java-core-*.jar >/dev/null 2>&1; then
echo "Building local aws-lambda-java-core..."
(cd "$CORE_ROOT" && mvn package -DskipTests)
cp "$CORE_ROOT"/target/aws-lambda-java-core-*.jar "$PROJECT_ROOT/target/"
fi

if ! ls "$PROJECT_ROOT"/target/aws-lambda-java-serialization-*.jar >/dev/null 2>&1; then
echo "Building local aws-lambda-java-serialization..."
(cd "$SERIALIZATION_ROOT" && mvn package -DskipTests)
cp "$SERIALIZATION_ROOT"/target/aws-lambda-java-serialization-*.jar "$PROJECT_ROOT/target/"
fi

echo "Compiling EchoHandler..."
javac -source 21 -target 21 -cp "$(ls "$PROJECT_ROOT"/target/aws-lambda-java-runtime-interface-client-*.jar):$(ls "$PROJECT_ROOT"/target/aws-lambda-java-core-*.jar):$(ls "$PROJECT_ROOT"/target/aws-lambda-java-serialization-*.jar)" \
-d "$PROJECT_ROOT/test-handlers/" "$PROJECT_ROOT/test-handlers/EchoHandler.java"

echo "Building test Docker image..."
docker build -t "$IMAGE_TAG" -f "$PROJECT_ROOT/Dockerfile.rie" "$PROJECT_ROOT"

echo "Starting test container on port 9000..."
echo ""
echo "In another terminal, invoke with:"
echo "curl -s -X POST -H 'Content-Type: application/json' \"http://localhost:9000/2015-03-31/functions/function/invocations\" -d '{\"message\":\"test\"}'"
echo ""

exec docker run -it -p 9000:8080 -e _HANDLER="$HANDLER" "$IMAGE_TAG"
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import java.util.Map;
import java.util.HashMap;

public class EchoHandler implements RequestHandler<Map<String, Object>, Map<String, Object>> {

@Override
public Map<String, Object> handleRequest(Map<String, Object> event, Context context) {
context.getLogger().log("Processing event: " + event);

Map<String, Object> response = new HashMap<>(event);
response.put("timestamp", System.currentTimeMillis());
response.put("requestId", context.getAwsRequestId());
response.put("functionName", context.getFunctionName());
response.put("remainingTimeInMillis", context.getRemainingTimeInMillis());

return response;
}
}