From 54a76ca3a5ef6120701733f1f583e4ff1266f70b Mon Sep 17 00:00:00 2001 From: Davide Melfi Date: Thu, 19 Feb 2026 16:46:33 +0000 Subject: [PATCH 01/13] refactor: :recycle: adding a new script that selectively builds specific examples --- Makefile | 7 +++++++ scripts/build-examples.sh | 23 +++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100755 scripts/build-examples.sh diff --git a/Makefile b/Makefile index d27d0e47..29bab781 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,10 @@ INTEG_EXTENSIONS := extension-fn extension-trait logs-trait # Using musl to run extensions on both AL1 and AL2 INTEG_ARCH := x86_64-unknown-linux-musl RIE_MAX_CONCURRENCY ?= 4 +OUTPUT_DIR ?= /tmp/var-task +EXAMPLES ?= + +.PHONY: pr-check integration-tests check-event-features fmt build-examples test-rie test-rie-lmi define uppercase $(shell sed -r 's/(^|-)(\w)/\U\2/g' <<< $(1)) @@ -112,6 +116,9 @@ check-event-features: fmt: cargo +nightly fmt --all +build-examples: + ./scripts/build-examples.sh + test-rie: ./scripts/test-rie.sh $(EXAMPLE) diff --git a/scripts/build-examples.sh b/scripts/build-examples.sh new file mode 100755 index 00000000..fb4e276b --- /dev/null +++ b/scripts/build-examples.sh @@ -0,0 +1,23 @@ +#!/bin/bash +set -e + +OUTPUT_DIR="${OUTPUT_DIR:-/tmp/var-task}" +EXAMPLES="${EXAMPLES:-}" + +mkdir -p "$OUTPUT_DIR" + +echo "Building examples: $(EXAMPLES)" + + +for example in ${EXAMPLES}; do + dir="examples/$example" + [ ! -f "$dir/Cargo.toml" ] && echo "✗ $example not found" && continue + + echo "Building $example..." + (cd "$dir" && cargo build --release) || continue + + [ -f "$dir/target/release/$example" ] && cp "$dir/target/release/$example" "$OUTPUT_DIR/" && echo "✓ $example" +done + +echo "" +ls -lh "$OUTPUT_DIR/" 2>/dev/null || echo "No binaries built" From 2cbcb4f844c677ce21d105c4bcb811fa1535e0de Mon Sep 17 00:00:00 2001 From: Davide Melfi Date: Thu, 19 Feb 2026 16:48:21 +0000 Subject: [PATCH 02/13] refactor: :recycle: add a custom lambda-entrypoint to select different binaries when called in the dockerfile. --- scripts/custom-lambda-entrypoint.sh | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 scripts/custom-lambda-entrypoint.sh diff --git a/scripts/custom-lambda-entrypoint.sh b/scripts/custom-lambda-entrypoint.sh new file mode 100644 index 00000000..fb02b26c --- /dev/null +++ b/scripts/custom-lambda-entrypoint.sh @@ -0,0 +1,15 @@ +#!/bin/sh +# custom entrypoint script to allow selection of multiple rust binaries for dockerized tests +set -e + +HANDLER=${1:-basic-lambda} + +if [ -f "/var/task/$HANDLER" ]; then + ln -sf "/var/task/$HANDLER" "${LAMBDA_RUNTIME_DIR}/bootstrap" + exec /usr/local/bin/aws-lambda-rie "${LAMBDA_RUNTIME_DIR}/bootstrap" +else + echo "Error: Handler '$HANDLER' not found in /var/task" + echo "Available handlers:" + ls -la /var/task + exit 1 +fi From 7aa7c0b2173cfcbeccb056be91e46c376afefb0e Mon Sep 17 00:00:00 2001 From: Davide Melfi Date: Thu, 19 Feb 2026 16:51:37 +0000 Subject: [PATCH 03/13] refactor: :recycle: modifying dockerfile to include both the build script and the custom entrypoint. Changing test-rie signature. --- Dockerfile.rie | 26 +++++++++++++++++--------- Makefile | 2 +- scripts/test-rie.sh | 13 +++++-------- 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/Dockerfile.rie b/Dockerfile.rie index 1a46b577..350fda67 100644 --- a/Dockerfile.rie +++ b/Dockerfile.rie @@ -1,25 +1,33 @@ FROM public.ecr.aws/lambda/provided:al2023 -RUN dnf install -y gcc +RUN dnf install -y gcc make RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y ENV PATH="/root/.cargo/bin:${PATH}" +ENV EXAMPLES="basic-lambda basic-lambda-concurrent" +ENV OUTPUT_DIR="/var/task" + ADD https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie /usr/local/bin/aws-lambda-rie RUN chmod +x /usr/local/bin/aws-lambda-rie -ARG EXAMPLE=basic-lambda - COPY Cargo.* /build/ COPY lambda-runtime /build/lambda-runtime COPY lambda-runtime-api-client /build/lambda-runtime-api-client COPY lambda-events /build/lambda-events COPY lambda-http /build/lambda-http COPY lambda-extension /build/lambda-extension -COPY examples/${EXAMPLE} /build/examples/${EXAMPLE} +COPY examples /build/examples +COPY scripts/custom-lambda-entrypoint.sh /usr/local/bin/lambda-entrypoint +COPY scripts/build-examples.sh /build/ + +WORKDIR /build + +RUN chmod +x /usr/local/bin/lambda-entrypoint +RUN chmod +x build-examples.sh + +# Build only basic-lambda example +RUN ./build-examples.sh -WORKDIR /build/examples/${EXAMPLE} -RUN cargo build --release -RUN cp target/release/${EXAMPLE} ${LAMBDA_RUNTIME_DIR}/bootstrap -ENTRYPOINT [] -CMD [ "/usr/local/bin/aws-lambda-rie", "/var/runtime/bootstrap" ] \ No newline at end of file +ENTRYPOINT ["/usr/local/bin/lambda-entrypoint"] +CMD ["basic-lambda"] \ No newline at end of file diff --git a/Makefile b/Makefile index 29bab781..95064ab8 100644 --- a/Makefile +++ b/Makefile @@ -120,7 +120,7 @@ build-examples: ./scripts/build-examples.sh test-rie: - ./scripts/test-rie.sh $(EXAMPLE) + ./scripts/test-rie.sh # Run RIE in Lambda Managed Instance (LMI) mode with concurrent polling. test-rie-lmi: diff --git a/scripts/test-rie.sh b/scripts/test-rie.sh index 3561a8ee..928d212e 100755 --- a/scripts/test-rie.sh +++ b/scripts/test-rie.sh @@ -1,12 +1,11 @@ #!/bin/bash set -euo pipefail -EXAMPLE=${1:-basic-lambda} # Optional: set RIE_MAX_CONCURRENCY to enable LMI mode (emulates AWS_LAMBDA_MAX_CONCURRENCY) RIE_MAX_CONCURRENCY=${RIE_MAX_CONCURRENCY:-} -echo "Building Docker image with RIE for example: $EXAMPLE..." -docker build -f Dockerfile.rie --build-arg EXAMPLE=$EXAMPLE -t rust-lambda-rie-test . +echo "Building Docker image with RIE" +docker build -f Dockerfile.rie -t rust-lambda-rie-test . echo "Starting RIE container on port 9000..." if [ -n "$RIE_MAX_CONCURRENCY" ]; then @@ -18,11 +17,9 @@ fi CONTAINER_PID=$! echo "Container started. Test with:" -if [ "$EXAMPLE" = "basic-lambda" ] || [ "$EXAMPLE" = "basic-lambda-concurrent" ]; then - echo "curl -XPOST 'http://localhost:9000/2015-03-31/functions/function/invocations' -d '{\"command\": \"test from RIE\"}' -H 'Content-Type: application/json'" -else - echo "For example '$EXAMPLE', check examples/$EXAMPLE/src/main.rs for the expected payload format." -fi +echo "curl -XPOST 'http://localhost:9000/2015-03-31/functions/function/invocations' -d '{\"command\": \"test from RIE\"}' -H 'Content-Type: application/json'" +echo "or for a specific example check under examples/ for the expected payload format." + echo "" echo "Press Ctrl+C to stop the container." From 9eb1b466609c9e06e9e68ac89a72c70e483df21c Mon Sep 17 00:00:00 2001 From: Davide Melfi Date: Thu, 19 Feb 2026 17:22:57 +0000 Subject: [PATCH 04/13] refactor: :recycle add nuke continaers to the makefile --- Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 95064ab8..428305d9 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ RIE_MAX_CONCURRENCY ?= 4 OUTPUT_DIR ?= /tmp/var-task EXAMPLES ?= -.PHONY: pr-check integration-tests check-event-features fmt build-examples test-rie test-rie-lmi +.PHONY: pr-check integration-tests check-event-features fmt build-examples test-rie test-rie-lmi nuke define uppercase $(shell sed -r 's/(^|-)(\w)/\U\2/g' <<< $(1)) @@ -122,6 +122,10 @@ build-examples: test-rie: ./scripts/test-rie.sh +nuke: + docker kill $$(docker ps -q) + + # Run RIE in Lambda Managed Instance (LMI) mode with concurrent polling. test-rie-lmi: RIE_MAX_CONCURRENCY=$(RIE_MAX_CONCURRENCY) ./scripts/test-rie.sh $(EXAMPLE) From 8ce868b684c58a5b46fbc086e9fc7fec4899d038 Mon Sep 17 00:00:00 2001 From: Davide Melfi Date: Fri, 20 Feb 2026 00:07:15 +0000 Subject: [PATCH 05/13] test: :sparkles: add harness testing capability --- .github/workflows/dockerized-test.yml | 24 ++++++++++++++ .gitignore | 1 + Dockerfile.rie | 24 +++++++------- Dockerfile.test-runner | 28 ++++++++++++++++ Makefile | 48 +++++++++++++++++++++++++-- test/dockerized/core.json | 19 +++++++++++ 6 files changed, 130 insertions(+), 14 deletions(-) create mode 100644 .github/workflows/dockerized-test.yml create mode 100644 Dockerfile.test-runner create mode 100644 test/dockerized/core.json diff --git a/.github/workflows/dockerized-test.yml b/.github/workflows/dockerized-test.yml new file mode 100644 index 00000000..cd0c8dde --- /dev/null +++ b/.github/workflows/dockerized-test.yml @@ -0,0 +1,24 @@ +name: dockerized-test + +on: + push: + branches: [ main ] + pull_request: + branches: [ '*' ] + workflow_dispatch: + +jobs: + dockerized-test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Build the image + run: docker build . -t local/test -f Dockerfile.rie + + - name: Run tests + uses: aws/containerized-test-runner-for-aws-lambda@v1 + with: + suiteFileArray: '["./tests/dockerized/*.json"]' + dockerImageName: 'local/test' \ No newline at end of file diff --git a/.gitignore b/.gitignore index d5e188a4..de557146 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ target lambda-runtime/libtest.rmeta lambda-integration-tests/target Cargo.lock +.test-runner # Built AWS Lambda zipfile lambda.zip diff --git a/Dockerfile.rie b/Dockerfile.rie index 350fda67..1dd2658a 100644 --- a/Dockerfile.rie +++ b/Dockerfile.rie @@ -1,15 +1,11 @@ -FROM public.ecr.aws/lambda/provided:al2023 +FROM public.ecr.aws/lambda/provided:al2023 AS builder RUN dnf install -y gcc make RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y ENV PATH="/root/.cargo/bin:${PATH}" -ENV EXAMPLES="basic-lambda basic-lambda-concurrent" +ENV EXAMPLES="basic-lambda" ENV OUTPUT_DIR="/var/task" - -ADD https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie /usr/local/bin/aws-lambda-rie -RUN chmod +x /usr/local/bin/aws-lambda-rie - COPY Cargo.* /build/ COPY lambda-runtime /build/lambda-runtime COPY lambda-runtime-api-client /build/lambda-runtime-api-client @@ -17,17 +13,21 @@ COPY lambda-events /build/lambda-events COPY lambda-http /build/lambda-http COPY lambda-extension /build/lambda-extension COPY examples /build/examples -COPY scripts/custom-lambda-entrypoint.sh /usr/local/bin/lambda-entrypoint COPY scripts/build-examples.sh /build/ WORKDIR /build +RUN chmod +x build-examples.sh && ./build-examples.sh -RUN chmod +x /usr/local/bin/lambda-entrypoint -RUN chmod +x build-examples.sh +# Final Image +FROM public.ecr.aws/lambda/provided:al2023 + +ADD https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie /usr/local/bin/aws-lambda-rie +RUN chmod +x /usr/local/bin/aws-lambda-rie -# Build only basic-lambda example -RUN ./build-examples.sh +COPY scripts/custom-lambda-entrypoint.sh /usr/local/bin/lambda-entrypoint +RUN chmod +x /usr/local/bin/lambda-entrypoint +COPY --from=builder /var/task /var/task ENTRYPOINT ["/usr/local/bin/lambda-entrypoint"] -CMD ["basic-lambda"] \ No newline at end of file +CMD ["basic-lambda"] diff --git a/Dockerfile.test-runner b/Dockerfile.test-runner new file mode 100644 index 00000000..b6f37716 --- /dev/null +++ b/Dockerfile.test-runner @@ -0,0 +1,28 @@ +FROM python:3.11-slim + +# Install build dependencies for pyjq and Docker CLI +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + gcc \ + g++ \ + make \ + autoconf \ + automake \ + libtool \ + ca-certificates \ + curl \ + && curl -fsSL https://get.docker.com -o get-docker.sh \ + && sh get-docker.sh \ + && rm get-docker.sh \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /app + +# Copy the test runner source +COPY .test-runner/ . + +# Install the test runner +RUN pip install --no-cache-dir . + +# Set the entrypoint +ENTRYPOINT ["python", "-m", "containerized_test_runner.cli"] diff --git a/Makefile b/Makefile index 428305d9..37e459f8 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,9 @@ RIE_MAX_CONCURRENCY ?= 4 OUTPUT_DIR ?= /tmp/var-task EXAMPLES ?= -.PHONY: pr-check integration-tests check-event-features fmt build-examples test-rie test-rie-lmi nuke +.PHONY: help pr-check integration-tests check-event-features fmt build-examples test-rie test-rie-lmi nuke test-dockerized + +.DEFAULT_GOAL := help define uppercase $(shell sed -r 's/(^|-)(\w)/\U\2/g' <<< $(1)) @@ -119,13 +121,55 @@ fmt: build-examples: ./scripts/build-examples.sh +test-dockerized: + @echo "Running dockerized tests locally..." + @echo "Building Docker image..." + docker build . -t local/test -f Dockerfile.rie + @echo "Setting up containerized test runner..." + @if [ ! -d ".test-runner" ]; then \ + echo "Cloning containerized-test-runner-for-aws-lambda..."; \ + git clone --quiet https://github.com/aws/containerized-test-runner-for-aws-lambda.git .test-runner; \ + fi + @echo "Building test runner Docker image..." + @docker build -t test-runner:local -f Dockerfile.test-runner . + @echo "Running tests in Docker..." + @echo "Running actual tests..." + @docker run --rm \ + -e DOCKER_API_VERSION=1.44 \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v "$(CURDIR)/tests/dockerized:/tests:ro" \ + test-runner:local \ + --test-image local/test \ + --debug \ + /tests/*.json + test-rie: ./scripts/test-rie.sh nuke: docker kill $$(docker ps -q) - # Run RIE in Lambda Managed Instance (LMI) mode with concurrent polling. test-rie-lmi: RIE_MAX_CONCURRENCY=$(RIE_MAX_CONCURRENCY) ./scripts/test-rie.sh $(EXAMPLE) + +help: ## Show this help message + @echo 'Usage: make [target]' + @echo '' + @echo 'Available targets:' + @echo ' pr-check Run pre-commit checks (fmt, clippy, tests)' + @echo ' integration-tests Build and run AWS integration tests' + @echo ' check-event-features Test individual event features' + @echo ' fmt Format code with cargo fmt' + @echo ' build-examples Build example Lambda functions' + @echo ' Usage: EXAMPLES="basic-lambda" make build-examples' + @echo ' test-rie Test Lambda with Runtime Interface Emulator' + @echo ' test-rie-lmi Test RIE in Lambda Managed Instance mode' + @echo ' Usage: RIE_MAX_CONCURRENCY=4 make test-rie-lmi' + @echo ' test-dockerized Run dockerized test harness' + @echo ' nuke Kill all running Docker containers' + @echo '' + @echo 'Environment variables:' + @echo ' EXAMPLES Space-separated list of examples to build' + @echo ' OUTPUT_DIR Directory for built binaries (default: /tmp/var-task)' + @echo ' RIE_MAX_CONCURRENCY Max concurrent Lambda invocations for LMI mode' diff --git a/test/dockerized/core.json b/test/dockerized/core.json new file mode 100644 index 00000000..5a21d066 --- /dev/null +++ b/test/dockerized/core.json @@ -0,0 +1,19 @@ +{ + "tests": [ + { + "name": "test_echo", + "handler": "basic-lambda", + "request": { + "command": "test" + }, + "assertions": [ + { + "response": { + "msg": "Command test executed." + }, + "transform": "{msg: .msg}" + } + ] + } + ] +} From 72f658ee832c624efb1282cc46097641368e0fdc Mon Sep 17 00:00:00 2001 From: Davide Melfi Date: Fri, 20 Feb 2026 01:15:03 +0000 Subject: [PATCH 06/13] refactor: :recycle: some small fixes --- Dockerfile.rie | 7 ++++--- Makefile | 29 +++++++++++++++++------------ README.md | 19 +++++-------------- scripts/build-examples.sh | 14 +++++++------- scripts/test-rie.sh | 14 ++++++++------ tests/dockerized/core.json | 19 +++++++++++++++++++ 6 files changed, 60 insertions(+), 42 deletions(-) create mode 100644 tests/dockerized/core.json diff --git a/Dockerfile.rie b/Dockerfile.rie index 1dd2658a..5d609ccf 100644 --- a/Dockerfile.rie +++ b/Dockerfile.rie @@ -3,8 +3,9 @@ FROM public.ecr.aws/lambda/provided:al2023 AS builder RUN dnf install -y gcc make RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y ENV PATH="/root/.cargo/bin:${PATH}" -ENV EXAMPLES="basic-lambda" -ENV OUTPUT_DIR="/var/task" + +ARG HANDLERS_TO_BUILD="basic-lambda" +ARG OUTPUT_DIR="/var/task" COPY Cargo.* /build/ COPY lambda-runtime /build/lambda-runtime @@ -16,7 +17,7 @@ COPY examples /build/examples COPY scripts/build-examples.sh /build/ WORKDIR /build -RUN chmod +x build-examples.sh && ./build-examples.sh +RUN chmod +x build-examples.sh && HANDLERS_TO_BUILD="$HANDLERS_TO_BUILD" OUTPUT_DIR="$OUTPUT_DIR" ./build-examples.sh # Final Image FROM public.ecr.aws/lambda/provided:al2023 diff --git a/Makefile b/Makefile index 37e459f8..b475709b 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,8 @@ INTEG_EXTENSIONS := extension-fn extension-trait logs-trait INTEG_ARCH := x86_64-unknown-linux-musl RIE_MAX_CONCURRENCY ?= 4 OUTPUT_DIR ?= /tmp/var-task -EXAMPLES ?= +HANDLERS_TO_BUILD ?= basic-lambda +HANDLER ?= basic-lambda .PHONY: help pr-check integration-tests check-event-features fmt build-examples test-rie test-rie-lmi nuke test-dockerized @@ -119,7 +120,10 @@ fmt: cargo +nightly fmt --all build-examples: - ./scripts/build-examples.sh + HANDLERS_TO_BUILD=${HANDLERS_TO_BUILD} ./scripts/build-examples.sh + +nuke: + docker kill $$(docker ps -q) test-dockerized: @echo "Running dockerized tests locally..." @@ -144,14 +148,11 @@ test-dockerized: /tests/*.json test-rie: - ./scripts/test-rie.sh - -nuke: - docker kill $$(docker ps -q) + HANDLER="$(HANDLER)" ./scripts/test-rie.sh # Run RIE in Lambda Managed Instance (LMI) mode with concurrent polling. test-rie-lmi: - RIE_MAX_CONCURRENCY=$(RIE_MAX_CONCURRENCY) ./scripts/test-rie.sh $(EXAMPLE) + RIE_MAX_CONCURRENCY=$(RIE_MAX_CONCURRENCY) HANDLER="$(HANDLER)" ./scripts/test-rie.sh $(EXAMPLE) help: ## Show this help message @echo 'Usage: make [target]' @@ -162,14 +163,18 @@ help: ## Show this help message @echo ' check-event-features Test individual event features' @echo ' fmt Format code with cargo fmt' @echo ' build-examples Build example Lambda functions' - @echo ' Usage: EXAMPLES="basic-lambda" make build-examples' + @echo ' Usage: EXAMPLES="basic-lambda" OUTPUT_DIR=/make build-examples' @echo ' test-rie Test Lambda with Runtime Interface Emulator' + @echo ' Usage: HANDLERS_TO_BUILD="basic-lambda basic-sqs" make test-rie' + @echo ' Usage: HANDLERS_TO_BUILD="basic-lambda" HANDLER="basic-lambda" make test-rie' @echo ' test-rie-lmi Test RIE in Lambda Managed Instance mode' - @echo ' Usage: RIE_MAX_CONCURRENCY=4 make test-rie-lmi' + @echo ' Usage: RIE_MAX_CONCURRENCY=4 HANDLERS_TO_BUILD="basic-lambda-concurrent" make test-rie-lmi' @echo ' test-dockerized Run dockerized test harness' @echo ' nuke Kill all running Docker containers' @echo '' @echo 'Environment variables:' - @echo ' EXAMPLES Space-separated list of examples to build' - @echo ' OUTPUT_DIR Directory for built binaries (default: /tmp/var-task)' - @echo ' RIE_MAX_CONCURRENCY Max concurrent Lambda invocations for LMI mode' + @echo ' EXAMPLES Space-separated list of examples to build (for build-examples)' + @echo ' HANDLERS_TO_BUILD Space-separated list of handlers to build for RIE (for test-rie)' + @echo ' HANDLER Specific handler to run (defaults to first in HANDLERS_TO_BUILD)' + @echo ' OUTPUT_DIR Directory for built binaries (default: /tmp/var-task for build-examples, /var/task for Docker)' + @echo ' RIE_MAX_CONCURRENCY Max concurrent Lambda invocations for LMI mode (for test-rie-lmi)' diff --git a/README.md b/README.md index 6ff25c9b..f1c7a546 100644 --- a/README.md +++ b/README.md @@ -392,35 +392,26 @@ You can read more about how [cargo lambda watch](https://www.cargo-lambda.info/c ### Local testing with Runtime Interface Emulator (RIE) -For testing with the official AWS Lambda Runtime Interface Emulator, use the provided RIE testing infrastructure: +For testing with the official AWS Lambda Runtime Interface Emulator: ```bash make test-rie ``` -By default, this uses the `basic-lambda` example. To test a different example: +By default, this builds and tests the `basic-lambda` example. To build and test a custom handler: ```bash -make test-rie EXAMPLE=basic-sqs -make test-rie EXAMPLE=http-basic-lambda +HANDLER="basic-tenant-id" make test-rie ``` -To test Lambda Managed Instances (concurrent polling), use: +To test Lambda Managed Instances (concurrent polling): ```bash -make test-rie-lmi EXAMPLE=basic-lambda-concurrent +RIE_MAX_CONCURRENCY=4 make test-rie ``` -This command will: -1. Build a Docker image with Rust toolchain and RIE -2. Compile the specified example inside the Linux container -3. Start the RIE container on port 9000 -4. Display the appropriate curl command for testing - Different examples expect different payload formats. Check the example's source code in `examples/EXAMPLE_NAME/src/main.rs` -This provides automated testing with Docker and RIE, ensuring your Lambda functions work in a Linux environment identical to AWS Lambda. - ### Lambda Debug Proxy Lambdas can be run and debugged locally using a special [Lambda debug proxy](https://github.com/rimutaka/lambda-debug-proxy) (a non-AWS repo maintained by @rimutaka), which is a Lambda function that forwards incoming requests to one AWS SQS queue and reads responses from another queue. A local proxy running on your development computer reads the queue, calls your Lambda locally and sends back the response. This approach allows debugging of Lambda functions locally while being part of your AWS workflow. The Lambda handler code does not need to be modified between the local and AWS versions. diff --git a/scripts/build-examples.sh b/scripts/build-examples.sh index fb4e276b..b479059d 100755 --- a/scripts/build-examples.sh +++ b/scripts/build-examples.sh @@ -2,21 +2,21 @@ set -e OUTPUT_DIR="${OUTPUT_DIR:-/tmp/var-task}" -EXAMPLES="${EXAMPLES:-}" +HANDLERS_TO_BUILD="${HANDLERS_TO_BUILD:-}" mkdir -p "$OUTPUT_DIR" -echo "Building examples: $(EXAMPLES)" +echo "Building handlers: ${HANDLERS_TO_BUILD}" -for example in ${EXAMPLES}; do - dir="examples/$example" - [ ! -f "$dir/Cargo.toml" ] && echo "✗ $example not found" && continue +for handler in ${HANDLERS_TO_BUILD}; do + dir="examples/$handler" + [ ! -f "$dir/Cargo.toml" ] && echo "✗ $handler not found" && continue - echo "Building $example..." + echo "Building $handler..." (cd "$dir" && cargo build --release) || continue - [ -f "$dir/target/release/$example" ] && cp "$dir/target/release/$example" "$OUTPUT_DIR/" && echo "✓ $example" + [ -f "$dir/target/release/$handler" ] && cp "$dir/target/release/$handler" "$OUTPUT_DIR/" && echo "✓ $handler" done echo "" diff --git a/scripts/test-rie.sh b/scripts/test-rie.sh index 928d212e..67f3595f 100755 --- a/scripts/test-rie.sh +++ b/scripts/test-rie.sh @@ -3,22 +3,24 @@ set -euo pipefail # Optional: set RIE_MAX_CONCURRENCY to enable LMI mode (emulates AWS_LAMBDA_MAX_CONCURRENCY) RIE_MAX_CONCURRENCY=${RIE_MAX_CONCURRENCY:-} +# Optional: specify which handler to run (defaults to first handler) +HANDLER=${HANDLER:-basic-lambda} -echo "Building Docker image with RIE" -docker build -f Dockerfile.rie -t rust-lambda-rie-test . +echo "Building Docker image with RIE (handlers: $HANDLER)" +docker build -f Dockerfile.rie --build-arg HANDLERS_TO_BUILD="$HANDLER" -t rust-lambda-rie-test . -echo "Starting RIE container on port 9000..." +echo "Starting RIE container on port 9000 with handler: $HANDLER" if [ -n "$RIE_MAX_CONCURRENCY" ]; then echo "Enabling LMI mode with AWS_LAMBDA_MAX_CONCURRENCY=$RIE_MAX_CONCURRENCY" - docker run -p 9000:8080 -e AWS_LAMBDA_MAX_CONCURRENCY="$RIE_MAX_CONCURRENCY" rust-lambda-rie-test & + docker run -p 9000:8080 -e AWS_LAMBDA_MAX_CONCURRENCY="$RIE_MAX_CONCURRENCY" rust-lambda-rie-test "$HANDLER" & else - docker run -p 9000:8080 rust-lambda-rie-test & + docker run -p 9000:8080 rust-lambda-rie-test "$HANDLER" & fi CONTAINER_PID=$! echo "Container started. Test with:" echo "curl -XPOST 'http://localhost:9000/2015-03-31/functions/function/invocations' -d '{\"command\": \"test from RIE\"}' -H 'Content-Type: application/json'" -echo "or for a specific example check under examples/ for the expected payload format." +echo "or for a specific example check under examples/ for the expected payload format." echo "" echo "Press Ctrl+C to stop the container." diff --git a/tests/dockerized/core.json b/tests/dockerized/core.json new file mode 100644 index 00000000..03cee2a7 --- /dev/null +++ b/tests/dockerized/core.json @@ -0,0 +1,19 @@ +{ + "tests": [ + { + "name": "test_echo", + "handler": "basic-lambda", + "request": { + "command": "test" + }, + "assertions": [ + { + "response": { + "msg": "Command test executed." + }, + "transform": "{msg: .msg}" + } + ] + } + ] +} \ No newline at end of file From 2b40b80d515b837f8b9aaffcc317c21c6459a8e0 Mon Sep 17 00:00:00 2001 From: Davide Melfi Date: Fri, 20 Feb 2026 01:34:15 +0000 Subject: [PATCH 07/13] chore: putting permission read --- .github/workflows/dockerized-test.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dockerized-test.yml b/.github/workflows/dockerized-test.yml index cd0c8dde..58214cc0 100644 --- a/.github/workflows/dockerized-test.yml +++ b/.github/workflows/dockerized-test.yml @@ -1,5 +1,8 @@ name: dockerized-test +permissions: + contents: read + on: push: branches: [ main ] @@ -7,12 +10,13 @@ on: branches: [ '*' ] workflow_dispatch: + jobs: dockerized-test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v6 - name: Build the image run: docker build . -t local/test -f Dockerfile.rie @@ -20,5 +24,5 @@ jobs: - name: Run tests uses: aws/containerized-test-runner-for-aws-lambda@v1 with: - suiteFileArray: '["./tests/dockerized/*.json"]' + suiteFileArray: '["./test/dockerized/*.json"]' dockerImageName: 'local/test' \ No newline at end of file From 707807436d527f8bed4e135ff45e134226f34c83 Mon Sep 17 00:00:00 2001 From: Davide Melfi Date: Fri, 20 Feb 2026 01:49:58 +0000 Subject: [PATCH 08/13] chore: add readme for test-dockerized --- README.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/README.md b/README.md index f1c7a546..6b7addf8 100644 --- a/README.md +++ b/README.md @@ -412,6 +412,41 @@ RIE_MAX_CONCURRENCY=4 make test-rie Different examples expect different payload formats. Check the example's source code in `examples/EXAMPLE_NAME/src/main.rs` +### Dockerized test harness + +For automated testing with AWS's containerized test runner: + +```bash +make test-dockerized +``` + +This runs test suites defined in `test/dockerized/*.json` files using the [containerized-test-runner-for-aws-lambda](https://github.com/aws/containerized-test-runner-for-aws-lambda). Test suites specify handlers to test (from examples), request payloads, and expected response assertions. + +Example test suite (`test/dockerized/core.json`): +```json +{ + "tests": [ + { + "name": "test_echo", + "handler": "basic-lambda", + "request": { + "command": "test" + }, + "assertions": [ + { + "response": { + "msg": "Command test executed." + }, + "transform": "{msg: .msg}" + } + ] + } + ] +} +``` + +The `transform` field uses jq syntax to extract specific fields from responses before comparison, useful when responses include dynamic fields like request IDs. + ### Lambda Debug Proxy Lambdas can be run and debugged locally using a special [Lambda debug proxy](https://github.com/rimutaka/lambda-debug-proxy) (a non-AWS repo maintained by @rimutaka), which is a Lambda function that forwards incoming requests to one AWS SQS queue and reads responses from another queue. A local proxy running on your development computer reads the queue, calls your Lambda locally and sends back the response. This approach allows debugging of Lambda functions locally while being part of your AWS workflow. The Lambda handler code does not need to be modified between the local and AWS versions. From eff6892dd2d5fe814cfccc0383852fb96147c8a2 Mon Sep 17 00:00:00 2001 From: Davide Melfi Date: Fri, 20 Feb 2026 02:15:21 +0000 Subject: [PATCH 09/13] chore: removing unused file --- tests/dockerized/core.json | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 tests/dockerized/core.json diff --git a/tests/dockerized/core.json b/tests/dockerized/core.json deleted file mode 100644 index 03cee2a7..00000000 --- a/tests/dockerized/core.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "tests": [ - { - "name": "test_echo", - "handler": "basic-lambda", - "request": { - "command": "test" - }, - "assertions": [ - { - "response": { - "msg": "Command test executed." - }, - "transform": "{msg: .msg}" - } - ] - } - ] -} \ No newline at end of file From 5f048207e0c905bc3887dc9d9c9fb847cbf00c3c Mon Sep 17 00:00:00 2001 From: Davide Melfi Date: Fri, 20 Feb 2026 02:16:12 +0000 Subject: [PATCH 10/13] chore: removed unused file --- Makefile | 2 +- PR_DESCRIPTION.md | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 PR_DESCRIPTION.md diff --git a/Makefile b/Makefile index b475709b..6fdcc762 100644 --- a/Makefile +++ b/Makefile @@ -141,7 +141,7 @@ test-dockerized: @docker run --rm \ -e DOCKER_API_VERSION=1.44 \ -v /var/run/docker.sock:/var/run/docker.sock \ - -v "$(CURDIR)/tests/dockerized:/tests:ro" \ + -v "$(CURDIR)/test/dockerized:/tests:ro" \ test-runner:local \ --test-image local/test \ --debug \ diff --git a/PR_DESCRIPTION.md b/PR_DESCRIPTION.md new file mode 100644 index 00000000..95bdf921 --- /dev/null +++ b/PR_DESCRIPTION.md @@ -0,0 +1,39 @@ +📬 *Issue #, if available:* + +N/A + +✍️ *Description of changes:* + +This PR adds Docker-based testing infrastructure using AWS's [containerized-test-runner-for-aws-lambda](https://github.com/aws/containerized-test-runner-for-aws-lambda), enabling automated testing of Lambda functions in a containerized environment that closely mirrors the AWS Lambda execution environment. + +The PR introduces a `test-dockerized` Makefile target that runs test suites defined in `test/dockerized/*.json` files. These test suites specify handlers to test (from the examples directory), request payloads, and expected response assertions with optional jq transforms for validation. + +The infrastructure reuses Lambda binaries from the `/examples` folder as test handlers, demonstrating the concept with an initial test case for `basic-lambda`. Additional tests and multi-concurrency scenarios can be added by creating new test suite JSON files. + +A GitHub Actions workflow provides CI/CD integration for automated testing on pull requests. + +## Testing + +Run dockerized tests locally: +```bash +make test-dockerized +``` + +Run RIE tests: +```bash +make test-rie +HANDLERS_TO_BUILD="basic-lambda basic-sqs" make test-rie +``` + +Build specific examples: +```bash +EXAMPLES="basic-lambda basic-lambda-concurrent" make build-examples +``` + +🔏 *By submitting this pull request* + +- [x] I confirm that I've ran `cargo +nightly fmt`. +- [x] I confirm that I've ran `cargo clippy --fix`. +- [x] I confirm that I've made a best effort attempt to update all relevant documentation. +- [x] I confirm that my contribution is made under the terms of the Apache 2.0 license.on. +- [x] I confirm that my contribution is made under the terms of the Apache 2.0 license. From d021b4862975c921302ecedf523c91af6c57f8f4 Mon Sep 17 00:00:00 2001 From: Davide Melfi Date: Fri, 20 Feb 2026 15:35:55 +0000 Subject: [PATCH 11/13] refactor: :recycle: moving the environmental variables in a dedicated file, fix --- .env | 16 ++++++++++++++++ Dockerfile.rie | 2 +- Makefile | 16 +++++++++++++--- 3 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 .env diff --git a/.env b/.env new file mode 100644 index 00000000..2623ad16 --- /dev/null +++ b/.env @@ -0,0 +1,16 @@ +# Test configuration for RIE and dockerized tests +# Customize these values as needed for testing both local and on github + +# Handlers to build +HANDLERS_TO_BUILD=basic-lambda + +HANDLER=basic-lambda + +# Output directory for built binaries +OUTPUT_DIR="/tmp/var-task" + +# Max concurrent Lambda invocations for LMI mode +RIE_MAX_CONCURRENCY=4 + +# Setting new version of docker buildkit +DOCKER_BUILDKIT=1 diff --git a/Dockerfile.rie b/Dockerfile.rie index 5d609ccf..180d6e3d 100644 --- a/Dockerfile.rie +++ b/Dockerfile.rie @@ -17,7 +17,7 @@ COPY examples /build/examples COPY scripts/build-examples.sh /build/ WORKDIR /build -RUN chmod +x build-examples.sh && HANDLERS_TO_BUILD="$HANDLERS_TO_BUILD" OUTPUT_DIR="$OUTPUT_DIR" ./build-examples.sh +RUN chmod +x build-examples.sh && HANDLERS_TO_BUILD=${HANDLERS_TO_BUILD} OUTPUT_DIR=${OUTPUT_DIR} ./build-examples.sh # Final Image FROM public.ecr.aws/lambda/provided:al2023 diff --git a/Makefile b/Makefile index 6fdcc762..b65ce5eb 100644 --- a/Makefile +++ b/Makefile @@ -7,8 +7,12 @@ INTEG_EXTENSIONS := extension-fn extension-trait logs-trait INTEG_ARCH := x86_64-unknown-linux-musl RIE_MAX_CONCURRENCY ?= 4 OUTPUT_DIR ?= /tmp/var-task -HANDLERS_TO_BUILD ?= basic-lambda -HANDLER ?= basic-lambda +HANDLERS_TO_BUILD ?= +HANDLER ?= + +# Load environment variables from .env file if it exists +-include .env +export .PHONY: help pr-check integration-tests check-event-features fmt build-examples test-rie test-rie-lmi nuke test-dockerized @@ -128,7 +132,13 @@ nuke: test-dockerized: @echo "Running dockerized tests locally..." @echo "Building Docker image..." - docker build . -t local/test -f Dockerfile.rie + DOCKER_BUILDKIT=1 docker build \ + -t local/test \ + -f Dockerfile.rie \ + --build-arg HANDLERS_TO_BUILD="${HANDLERS_TO_BUILD}" \ + --build-arg OUTPUT_DIR="${OUTPUT_DIR}" \ + . + @echo "Setting up containerized test runner..." @if [ ! -d ".test-runner" ]; then \ echo "Cloning containerized-test-runner-for-aws-lambda..."; \ From fbfa5e532b123c343edd7a90cf7bf9887bf4c0ad Mon Sep 17 00:00:00 2001 From: Davide Melfi Date: Fri, 20 Feb 2026 16:28:17 +0000 Subject: [PATCH 12/13] removing docker_buildkit --- .env | 3 --- Makefile | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/.env b/.env index 2623ad16..ffd8d09f 100644 --- a/.env +++ b/.env @@ -11,6 +11,3 @@ OUTPUT_DIR="/tmp/var-task" # Max concurrent Lambda invocations for LMI mode RIE_MAX_CONCURRENCY=4 - -# Setting new version of docker buildkit -DOCKER_BUILDKIT=1 diff --git a/Makefile b/Makefile index b65ce5eb..f353646c 100644 --- a/Makefile +++ b/Makefile @@ -132,7 +132,7 @@ nuke: test-dockerized: @echo "Running dockerized tests locally..." @echo "Building Docker image..." - DOCKER_BUILDKIT=1 docker build \ + docker build \ -t local/test \ -f Dockerfile.rie \ --build-arg HANDLERS_TO_BUILD="${HANDLERS_TO_BUILD}" \ From cf3320947473901b44847566c0d0099f60028ece Mon Sep 17 00:00:00 2001 From: Davide Melfi Date: Fri, 20 Feb 2026 17:29:43 +0000 Subject: [PATCH 13/13] chore: change the workflow version --- .github/workflows/dockerized-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dockerized-test.yml b/.github/workflows/dockerized-test.yml index 58214cc0..1d7097ce 100644 --- a/.github/workflows/dockerized-test.yml +++ b/.github/workflows/dockerized-test.yml @@ -22,7 +22,7 @@ jobs: run: docker build . -t local/test -f Dockerfile.rie - name: Run tests - uses: aws/containerized-test-runner-for-aws-lambda@v1 + uses: aws/containerized-test-runner-for-aws-lambda@main with: suiteFileArray: '["./test/dockerized/*.json"]' dockerImageName: 'local/test' \ No newline at end of file