diff --git a/.github/workflows/dockerized-test.yml b/.github/workflows/dockerized-test.yml new file mode 100644 index 0000000..fe90b9d --- /dev/null +++ b/.github/workflows/dockerized-test.yml @@ -0,0 +1,38 @@ +name: dockerized-test + +on: + push: + branches: [ main ] + pull_request: + branches: [ '*' ] + workflow_dispatch: + + +jobs: + dockerized-test: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + ruby_version: ['3.3', '3.4'] + + steps: + - uses: actions/checkout@v3 + + - name: Set up ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby_version }} + + - name: Build the lib + run: make build + + - name: Build the image + run: docker build . -t local/test -f Dockerfile.test --build-arg BASE_IMAGE=public.ecr.aws/lambda/ruby:${{ matrix.ruby_version }} + + - name: Run tests + uses: aws/containerized-test-runner-for-aws-lambda@v1 + with: + suiteFileArray: '["./test/dockerized/suites/*.json"]' + dockerImageName: 'local/test' + taskFolder: './test/dockerized/tasks' diff --git a/.gitignore b/.gitignore index f6b393d..1e84ce6 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,5 @@ test/examples/hello-world-docker/pkg *.iml .DS_Store Gemfile.lock +# useful when using rbenv +.ruby-version diff --git a/Dockerfile.test b/Dockerfile.test new file mode 100644 index 0000000..b59aafb --- /dev/null +++ b/Dockerfile.test @@ -0,0 +1,7 @@ +ARG BASE_IMAGE +FROM $BASE_IMAGE +ENV GEM_HOME=/var/runtime +RUN gem uninstall aws_lambda_ric --executables +ADD pkg /tmp/pkg +RUN gem install /tmp/pkg/aws_lambda_ric-*.gem +RUN rm -rf /tmp/pkg \ No newline at end of file diff --git a/test/dockerized/suites/core.json b/test/dockerized/suites/core.json new file mode 100644 index 0000000..20e8149 --- /dev/null +++ b/test/dockerized/suites/core.json @@ -0,0 +1,78 @@ +{ + "tests": [ + { + "name": "test_echo", + "handler": "core.ping", + "request": { + "msg": "message" + }, + "assertions": [ + { + "response": { + "msg": "pong[message]" + } + } + ] + }, + { + "name": "test_string_payload", + "handler": "core.str_ping", + "request": "message", + "assertions": [ + { + "response": { + "msg": "pong[message]" + } + } + ] + }, + { + "name": "test_module_echo", + "handler": "core.HandlerClass.ping", + "request": { + "msg": "MyMessage" + }, + "assertions": [ + { + "response": "Module Message: 'MyMessage'" + } + ] + }, + { + "name": "test_deep_module_echo", + "handler": "core.DeepModule::Handler.ping", + "request": { + "msg": "MyMessage" + }, + "assertions": [ + { + "response": "Deep Module Message: 'MyMessage'" + } + ] + }, + { + "name": "test_error", + "handler": "core.broken", + "request": { + "msg": "message" + }, + "assertions": [ + { + "errorType": "Function" + } + ] + }, + { + "name": "test_string", + "handler": "core.string", + "request": { + "msg": "MyMessage" + }, + "assertions": [ + { + "response": "Message: 'MyMessage'" + } + ] + } + ] +} \ No newline at end of file diff --git a/test/dockerized/suites/ctx.json b/test/dockerized/suites/ctx.json new file mode 100644 index 0000000..86b9099 --- /dev/null +++ b/test/dockerized/suites/ctx.json @@ -0,0 +1,49 @@ +{ + "tests": [ + { + "name": "test_ctx_cognito_pool_id", + "handler": "ctx.get_cognito_pool_id", + "cognitoIdentity": { + "cognitoIdentityId": "4ab95ea510c14353a7f6da04489c43b8", + "cognitoIdentityPoolId": "35ab4794a79a4f23947d3e851d3d6578" + }, + "request": {}, + "assertions": [ + { + "response": { + "cognito_pool_id": "35ab4794a79a4f23947d3e851d3d6578" + } + } + ] + }, + { + "name": "test_ctx_cognito_identity_id", + "handler": "ctx.get_cognito_identity_id", + "cognitoIdentity": { + "cognitoIdentityId": "4ab95ea510c14353a7f6da04489c43b8", + "cognitoIdentityPoolId": "35ab4794a79a4f23947d3e851d3d6578" + }, + "request": {}, + "assertions": [ + { + "response": { + "cognito_identity_id": "4ab95ea510c14353a7f6da04489c43b8" + } + } + ] + }, + { + "name": "get_remaining_time_in_millis | elapsedTime", + "handler": "ctx.get_remaining_time_from_context", + "request": { + "sleepTimeSeconds": 0.1 + }, + "assertions": [ + { + "transform": ".elapsedTime >= 100", + "response": true + } + ] + } + ] +} \ No newline at end of file diff --git a/test/dockerized/tasks/core.rb b/test/dockerized/tasks/core.rb new file mode 100644 index 0000000..85e53e8 --- /dev/null +++ b/test/dockerized/tasks/core.rb @@ -0,0 +1,55 @@ +# Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +def ping(event:, context:) + resp = {} + if event.nil? + resp[:event_nil] = true + else + resp[:msg] = "pong[#{event["msg"]}]" + end + puts "Hello, loggers!" + resp + end + + def str_ping(event:, context:) + { msg: "pong[#{event}]" } + end + + def broken(_) + raise ArgumentError.new("My error message.") + end + + def string(event:, context:) + "Message: '#{event["msg"]}'" + end + + def curl(event:,context:) + resp = Net::HTTP.get(URI(event["url"])) + if resp.size > 0 + { success: true } + else + raise "Empty response!" + end + end + + def io(_) + StringIO.new("This is IO!") + end + + def execution_env(_) + { "AWS_EXECUTION_ENV" => ENV["AWS_EXECUTION_ENV"] } + end + + class HandlerClass + def self.ping(event:,context:) + "Module Message: '#{event["msg"]}'" + end + end + + module DeepModule + class Handler + def self.ping(event:,context:) + "Deep Module Message: '#{event["msg"]}'" + end + end + end \ No newline at end of file diff --git a/test/dockerized/tasks/cxt.rb b/test/dockerized/tasks/cxt.rb new file mode 100644 index 0000000..072a573 --- /dev/null +++ b/test/dockerized/tasks/cxt.rb @@ -0,0 +1,32 @@ +# Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +def get_context(event:,context:) + { + function_name: context.function_name, + deadline_ns: context.deadline_ns, + aws_request_id: context.aws_request_id, + invoked_function_arn: context.invoked_function_arn, + log_group_name: context.log_group_name, + log_stream_name: context.log_stream_name, + memory_limit_in_mb: context.memory_limit_in_mb, + function_version: context.function_version + } + end + + def get_cognito_pool_id(event:,context:) + { cognito_pool_id: context.identity["cognitoIdentityPoolId"]} + end + + def get_cognito_identity_id(event:,context:) + { cognito_identity_id: context.identity["cognitoIdentityId"] } + end + + def echo_context(event:,context:) + context.client_context + end + + def get_remaining_time_from_context(event:, context:) + before = context.get_remaining_time_in_millis() + sleep(event['sleepTimeSeconds']) + return { elapsedTime: before - context.get_remaining_time_in_millis() } + end \ No newline at end of file