Skip to content
Draft
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
3 changes: 2 additions & 1 deletion .github/workflows/aws-lambda-java-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ on:
- 'aws-lambda-java-tests/**'
- 'aws-lambda-java-events/**'
- 'aws-lambda-java-serialization/**'
- 'aws-lambda-java-runtime-interface-client/**'
pull_request:
branches: [ '*' ]
paths:
- 'aws-lambda-java-tests/**'
- 'aws-lambda-java-events/**'
- 'aws-lambda-java-serialization/**'
- 'aws-lambda-java-runtime-interface-client/**'
- '.github/workflows/aws-lambda-java-tests.yml'

permissions:
contents: read

Expand Down
9 changes: 6 additions & 3 deletions .github/workflows/runtime-interface-client_pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,16 @@ jobs:

smoke-test:
runs-on: ubuntu-latest
strategy:
matrix:
java-version: [8, 11, 17, 21, 25]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

- name: Set up JDK 1.8
- name: Set up JDK ${{ matrix.java-version }}
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
java-version: 8
java-version: ${{ matrix.java-version }}
distribution: corretto
cache: maven

Expand All @@ -43,7 +46,7 @@ jobs:
working-directory: ./aws-lambda-java-runtime-interface-client
run: make pr
env:
IS_JAVA_8: true
IS_JAVA_8: ${{ matrix.java-version == 8 }}

build:
runs-on: ubuntu-latest
Expand Down
13 changes: 13 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ dependency-reduced-pom.xml
.settings
.classpath
.project
.factorypath

# OSX
.DS_Store
Expand All @@ -38,4 +39,16 @@ experimental/aws-lambda-java-profiler/integration_tests/helloworld/bin
.vscode
.kiro
build

# Logs
*.log

# Maven flatten plugin
.flattened-pom.xml

# Vim swap files
*.swp
*.swo

# Tool version manager
mise.toml
3 changes: 2 additions & 1 deletion aws-lambda-java-events-sdk-transformer/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@
<maven.compiler.target>1.8</maven.compiler.target>
<sdk.v1.version>1.11.914</sdk.v1.version>
<sdk.v2.version>2.15.40</sdk.v2.version>
<junit-jupiter.version>5.12.2</junit-jupiter.version>
<junit-jupiter.version>5.14.3</junit-jupiter.version>
<maven-surefire-plugin.version>3.5.4</maven-surefire-plugin.version>

</properties>

<distributionManagement>
Expand Down
2 changes: 1 addition & 1 deletion aws-lambda-java-events/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<jackson.version>2.20.1</jackson.version>
<json.unit>2.40.1</json.unit>
<junit-jupiter.version>5.12.2</junit-jupiter.version>
<junit-jupiter.version>5.14.3</junit-jupiter.version>
</properties>

<distributionManagement>
Expand Down
40 changes: 24 additions & 16 deletions aws-lambda-java-runtime-interface-client/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,57 +15,63 @@ endif
# making it possible to publish resulting artifacts to a codeartifact maven repository
-include ric-dev-environment/codeartifact-repo.mk

.PHONY: target

target:
$(info ${HELP_MESSAGE})
@exit 0

.PHONY: test

test:
mvn test $(EXTRA_LOAD_ARG)

.PHONY: setup-codebuild-agent

setup-codebuild-agent:
docker build -t codebuild-agent \
--build-arg ARCHITECTURE=$(ARCHITECTURE_ALIAS) \
- < test/integration/codebuild-local/Dockerfile.agent

.PHONY: test-smoke

test-smoke: setup-codebuild-agent
CODEBUILD_IMAGE_TAG=codebuild-agent test/integration/codebuild-local/test_one.sh test/integration/codebuild/buildspec.os.alpine.yml alpine 3.15 corretto11 linux/amd64
CODEBUILD_IMAGE_TAG=codebuild-agent test/integration/codebuild-local/test_one.sh test/integration/codebuild/buildspec.os.alpine.yml alpine 3.15 corretto11 linux/arm64/v8
CODEBUILD_IMAGE_TAG=codebuild-agent test/integration/codebuild-local/test_one.sh test/integration/codebuild/buildspec.os.amazoncorretto.yml amazoncorretto amazoncorretto 11 linux/amd64
CODEBUILD_IMAGE_TAG=codebuild-agent test/integration/codebuild-local/test_one.sh test/integration/codebuild/buildspec.os.amazoncorretto.yml amazoncorretto amazoncorretto 11 linux/arm64/v8

.PHONY: test-integ

test-integ: setup-codebuild-agent
CODEBUILD_IMAGE_TAG=codebuild-agent test/integration/codebuild-local/test_all.sh test/integration/codebuild

# Command to run everytime you make changes to verify everything works
.PHONY: dev

dev: test

# Verifications to run before sending a pull request
.PHONY: pr

pr: test test-smoke

.PHONY: build

# The default `mvn clean install` builds all 4 native .so variants (x86_64/aarch64 × glibc/musl)
# and bundles them into a single jar (see build-jni-lib.sh), runs the tests for the host
# environment, and updates coverage data. This is sufficient for what we want to do here.
#
# Running profile-specific builds (e.g., `mvn install -P linux-aarch64`) does NOT test the
# cross-compiled .so — JniHelper.load() tries each .so in order and always loads the first
# one matching the host platform (linux-x86_64 on GitHub Actions runners), so the other
# variants are never exercised.
#
# Platform-specific tests are run through test-smoke via codebuild containers.

build:
mvn clean install $(EXTRA_LOAD_ARG)
mvn install -P linux-x86_64 $(EXTRA_LOAD_ARG)
mvn install -P linux_musl-x86_64 $(EXTRA_LOAD_ARG)
mvn install -P linux-aarch64 $(EXTRA_LOAD_ARG)
mvn install -P linux_musl-aarch64 $(EXTRA_LOAD_ARG)
mvn clean install $(EXTRA_LOAD_ARG)

.PHONY: publish
publish:
./ric-dev-environment/publish_snapshot.sh

.PHONY: publish

test-publish:
./ric-dev-environment/test-platform-specific-jar-snapshot.sh

.PHONY: test-rie

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

Expand All @@ -80,3 +86,5 @@ TARGETS
test Run the Unit tests.
test-rie Build and test RIC locally with Lambda Runtime Interface Emulator. (Requires building the project first)
endef

.PHONY: target test setup-codebuild-agent test-smoke test-integ dev pr build publish publish test-rie
2 changes: 1 addition & 1 deletion aws-lambda-java-runtime-interface-client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
<jacoco.maven.plugin.version>0.8.12</jacoco.maven.plugin.version>
<maven-install-plugin.version>2.4</maven-install-plugin.version>
<maven-deploy-plugin.version>3.1.1</maven-deploy-plugin.version>
<junit-jupiter.version>5.12.2</junit-jupiter.version>
<junit-jupiter.version>5.14.3</junit-jupiter.version>
<maven-checkstyle-plugin.version>3.4.0</maven-checkstyle-plugin.version>
<maven-surefire-plugin.version>3.5.4</maven-surefire-plugin.version>
<!--
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@

set -euo pipefail

# Check if Docker is available and running. This works regardless of how Docker
# is configured (Unix socket, TCP, Docker Desktop, Colima, Rancher, etc.)
if ! docker info >/dev/null 2>&1; then
echo "WARNING: Docker is not available. Skipping JNI native library build."
echo "The native .so libraries will not be included in the build artifacts."
echo "This is fine for local development and running unit tests."
echo "To build the native libraries, ensure Docker is installed and running."
exit 0
fi

SRC_DIR=$(dirname "$0")
DST_DIR=${1}
MULTI_ARCH=${2}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@
package com.amazonaws.services.lambda.runtime.api.client;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledForJreRange;
import org.junit.jupiter.api.condition.EnabledForJreRange;
import org.junit.jupiter.api.condition.JRE;
import org.junit.jupiter.api.io.TempDir;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Collections;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;

import static org.junit.jupiter.api.Assertions.*;
Expand All @@ -27,21 +27,38 @@ void testLoadAllClassesWithNoClasspath() throws IOException {
String originalClasspath = System.getProperty("java.class.path");
try {
System.clearProperty("java.class.path");
ClasspathLoader.main(new String[]{});
ClasspathLoader.main(new String[] {});
} finally {
if (originalClasspath != null) {
System.setProperty("java.class.path", originalClasspath);
}
}
}

// On JDK 8-24, new File("").exists() returns false → FileNotFoundException.
@Test
@DisabledForJreRange(min = JRE.JAVA_25)
void testLoadAllClassesWithEmptyClasspath() {
String originalClasspath = System.getProperty("java.class.path");
try {
System.setProperty("java.class.path", "");
assertThrows(FileNotFoundException.class, () ->
ClasspathLoader.main(new String[]{}));
assertThrows(FileNotFoundException.class, () -> ClasspathLoader.main(new String[] {}));
} finally {
if (originalClasspath != null) {
System.setProperty("java.class.path", originalClasspath);
}
}
}

// On JDK 25+, new File("") resolves to cwd (exists=true, isDirectory=true) →
// skipped with warning, no exception.
@Test
@EnabledForJreRange(min = JRE.JAVA_25)
void testLoadAllClassesWithEmptyClasspathJdk25Plus() throws IOException {
String originalClasspath = System.getProperty("java.class.path");
try {
System.setProperty("java.class.path", "");
ClasspathLoader.main(new String[] {});
} finally {
if (originalClasspath != null) {
System.setProperty("java.class.path", originalClasspath);
Expand All @@ -54,8 +71,7 @@ void testLoadAllClassesWithInvalidPath() {
String originalClasspath = System.getProperty("java.class.path");
try {
System.setProperty("java.class.path", "nonexistent/path");
assertThrows(FileNotFoundException.class, () ->
ClasspathLoader.main(new String[]{}));
assertThrows(FileNotFoundException.class, () -> ClasspathLoader.main(new String[] {}));
} finally {
if (originalClasspath != null) {
System.setProperty("java.class.path", originalClasspath);
Expand All @@ -69,7 +85,7 @@ void testLoadAllClassesWithValidJar(@TempDir Path tempDir) throws IOException {
String originalClasspath = System.getProperty("java.class.path");
try {
System.setProperty("java.class.path", jarFile.getAbsolutePath());
ClasspathLoader.main(new String[]{});
ClasspathLoader.main(new String[] {});
} finally {
if (originalClasspath != null) {
System.setProperty("java.class.path", originalClasspath);
Expand All @@ -82,7 +98,7 @@ void testLoadAllClassesWithDirectory(@TempDir Path tempDir) throws IOException {
String originalClasspath = System.getProperty("java.class.path");
try {
System.setProperty("java.class.path", tempDir.toString());
ClasspathLoader.main(new String[]{});
ClasspathLoader.main(new String[] {});
} finally {
if (originalClasspath != null) {
System.setProperty("java.class.path", originalClasspath);
Expand All @@ -94,14 +110,14 @@ void testLoadAllClassesWithDirectory(@TempDir Path tempDir) throws IOException {
void testLoadAllClassesWithMultipleEntries(@TempDir Path tempDir) throws IOException {
File jarFile1 = createSimpleJar(tempDir, "test1.jar", "TestClass1");
File jarFile2 = createSimpleJar(tempDir, "test2.jar", "TestClass2");

String originalClasspath = System.getProperty("java.class.path");
try {
String newClasspath = jarFile1.getAbsolutePath() +
File.pathSeparator +
jarFile2.getAbsolutePath();
String newClasspath = jarFile1.getAbsolutePath() +
File.pathSeparator +
jarFile2.getAbsolutePath();
System.setProperty("java.class.path", newClasspath);
ClasspathLoader.main(new String[]{});
ClasspathLoader.main(new String[] {});
} finally {
if (originalClasspath != null) {
System.setProperty("java.class.path", originalClasspath);
Expand All @@ -112,7 +128,7 @@ void testLoadAllClassesWithMultipleEntries(@TempDir Path tempDir) throws IOExcep
@Test
void testLoadAllClassesWithBlocklistedClass(@TempDir Path tempDir) throws IOException {
File jarFile = tempDir.resolve("blocklist-test.jar").toFile();

try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(jarFile))) {
JarEntry blockedEntry = new JarEntry("META-INF/versions/9/module-info.class");
jos.putNextEntry(blockedEntry);
Expand All @@ -128,8 +144,9 @@ void testLoadAllClassesWithBlocklistedClass(@TempDir Path tempDir) throws IOExce
String originalClasspath = System.getProperty("java.class.path");
try {
System.setProperty("java.class.path", jarFile.getAbsolutePath());
ClasspathLoader.main(new String[]{});
// The test passes if no exception is thrown and the blocklisted class is skipped
ClasspathLoader.main(new String[] {});
// The test passes if no exception is thrown and the blocklisted class is
// skipped
} finally {
if (originalClasspath != null) {
System.setProperty("java.class.path", originalClasspath);
Expand All @@ -139,15 +156,15 @@ void testLoadAllClassesWithBlocklistedClass(@TempDir Path tempDir) throws IOExce

private File createSimpleJar(Path tempDir, String jarName, String className) throws IOException {
File jarFile = tempDir.resolve(jarName).toFile();

try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(jarFile))) {
// Add a simple non-class file to make it a valid jar
JarEntry entry = new JarEntry("com/test/" + className + ".txt");
jos.putNextEntry(entry);
jos.write("test content".getBytes());
jos.closeEntry();
}

return jarFile;
}
}
Loading
Loading