Skip to content
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

test: Remote invoke integration tests for response stream configured lambda functions #5383

Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import json
import uuid

from tests.integration.remote.invoke.remote_invoke_integ_base import RemoteInvokeIntegBase
from tests.testing_utils import run_command

from pathlib import Path
import pytest


@pytest.mark.xdist_group(name="sam_remote_invoke_lambda_response_streaming")
class TestInvokeResponseStreamingLambdas(RemoteInvokeIntegBase):
template = Path("template-lambda-response-streaming-fns.yaml")

@classmethod
def setUpClass(cls):
super().setUpClass()
cls.stack_name = f"{TestInvokeResponseStreamingLambdas.__name__}-{uuid.uuid4().hex}"
cls.create_resources_and_boto_clients()

def test_invoke_empty_event_provided(self):
command_list = self.get_command_list(stack_name=self.stack_name, resource_id="NodeStreamingFunction")

expected_streamed_responses = "LambdaFunctionStreamingResponsesTestDone!"
remote_invoke_result = run_command(command_list)

self.assertEqual(0, remote_invoke_result.process.returncode)
remote_invoke_result_stdout = remote_invoke_result.stdout.strip().decode()
self.assertIn(expected_streamed_responses, remote_invoke_result_stdout)

def test_invoke_with_only_event_provided(self):
command_list = self.get_command_list(
stack_name=self.stack_name,
resource_id="NodeStreamingFunction",
event='{"key1": "Hello", "key2": "serverless", "key3": "world"}',
)

expected_streamed_responses = "LambdaFunctionStreamingResponsesTestDone!"
remote_invoke_result = run_command(command_list)

self.assertEqual(0, remote_invoke_result.process.returncode)
remote_invoke_result_stdout = remote_invoke_result.stdout.strip().decode()
self.assertIn(expected_streamed_responses, remote_invoke_result_stdout)

def test_invoke_with_only_event_file_provided(self):
event_file_path = str(self.events_folder_path.joinpath("default_event.json"))
command_list = self.get_command_list(
stack_name=self.stack_name, resource_id="NodeStreamingEventValuesFunction", event_file=event_file_path
)

expected_streamed_responses = "Helloserverlessworld"
remote_invoke_result = run_command(command_list)

self.assertEqual(0, remote_invoke_result.process.returncode)
remote_invoke_result_stdout = remote_invoke_result.stdout.strip().decode()

self.assertEqual(expected_streamed_responses, remote_invoke_result_stdout)

def test_invoke_json_output_option(self):
command_list = self.get_command_list(
stack_name=self.stack_name,
event='{"key1": "Hello", "key2": "serverless", "key3": "world"}',
resource_id="NodeStreamingEventValuesFunction",
output="json",
parameter_list=[("LogType", "None")],
)

remote_invoke_result = run_command(command_list)
expected_output_result = [
{"PayloadChunk": {"Payload": "Hello"}},
{"PayloadChunk": {"Payload": "serverless"}},
{"PayloadChunk": {"Payload": "world"}},
{"InvokeComplete": {}},
]

self.assertEqual(0, remote_invoke_result.process.returncode)
remote_invoke_result_stdout = json.loads(remote_invoke_result.stdout.strip().decode())

response_event_stream = remote_invoke_result_stdout["EventStream"]
self.assertEqual(response_event_stream, expected_output_result)

def test_invoke_different_boto_options(self):
command_list = self.get_command_list(
stack_name=self.stack_name,
event='{"key1": "Hello", "key2": "serverless", "key3": "world"}',
resource_id="NodeStreamingEventValuesFunction",
output="json",
parameter_list=[("LogType", "None"), ("InvocationType", "DryRun"), ("Qualifier", "$LATEST")],
)

remote_invoke_result = run_command(command_list)
expected_output_result = [
{"PayloadChunk": {"Payload": "Hello"}},
{"PayloadChunk": {"Payload": "serverless"}},
{"PayloadChunk": {"Payload": "world"}},
{"InvokeComplete": {}},
]

self.assertEqual(0, remote_invoke_result.process.returncode)
remote_invoke_result_stdout = json.loads(remote_invoke_result.stdout.strip().decode())

response_event_stream = remote_invoke_result_stdout["EventStream"]
self.assertEqual(response_event_stream, expected_output_result)
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
exports.handler = awslambda.streamifyResponse(
async (event, responseStream, context) => {
responseStream.write("Lambda");
responseStream.write("Function");

responseStream.write("Streaming");
await new Promise(r => setTimeout(r, 1000));
responseStream.write("Responses");
await new Promise(r => setTimeout(r, 1000));
responseStream.write("Test");
await new Promise(r => setTimeout(r, 1000));

responseStream.write("Done!");
responseStream.end();
}
);

exports.stream_event_values = awslambda.streamifyResponse(
async (event, responseStream, context) => {
for (let k in event) {
responseStream.write(event[k]);
await new Promise(r => setTimeout(r, 1000));
}
responseStream.end();
}
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Description: >
Testing application for lambda functions with response streaming

Resources:
NodeStreamingFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: ./lambda-fns/src/
Handler: index.handler
Runtime: nodejs18.x
Timeout: 10
FunctionUrlConfig:
AuthType: AWS_IAM
InvokeMode: RESPONSE_STREAM

NodeStreamingEventValuesFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: ./lambda-fns/src/
Handler: index.stream_event_values
Runtime: nodejs18.x
Timeout: 10
FunctionUrlConfig:
AuthType: AWS_IAM
InvokeMode: RESPONSE_STREAM