def test_binary_with_application_json(self): bootstrap.handle_event_request( lambda_runtime_client=self.lambda_runtime, request_handler=lambda event, ctx: event, invoke_id="invoke-id", event_body=b"\x89PNG\r\n\x1a\n\x00\x00\x00", content_type="application/json", client_context_json=None, cognito_identity_json=None, invoked_function_arn="invocation-arn", epoch_deadline_time_in_ms=1415836801003, log_sink=bootstrap.StandardLogSink(), ) self.lambda_runtime.post_invocation_result.assert_not_called() self.lambda_runtime.post_invocation_error.assert_called_once() ( invoke_id, error_result, xray_fault, ), _ = self.lambda_runtime.post_invocation_error.call_args error_dict = json.loads(error_result) self.assertEqual("invoke-id", invoke_id) self.assertEqual("Runtime.UnmarshalError", error_dict["errorType"])
def test_handle_event_request_no_module(self): def unable_to_import_module(json_input, lambda_context): import invalid_module # noqa: F401 expected_response = { "errorType": "ModuleNotFoundError", "errorMessage": "No module named 'invalid_module'", } bootstrap.handle_event_request( self.lambda_runtime, unable_to_import_module, "invoke_id", self.event_body, "application/json", {}, {}, "invoked_function_arn", 0, bootstrap.StandardLogSink(), ) args, _ = self.lambda_runtime.post_invocation_error.call_args error_response = json.loads(args[1]) self.assertEqual(args[0], "invoke_id") self.assertTrue( expected_response.items() <= error_response.items(), "Expected response is not a subset of the actual response\nExpected: {}\nActual: {}" .format(expected_response, error_response), )
def test_handle_event_request_custom_exception(self): def raise_exception_handler(json_input, lambda_context): class MyError(Exception): def __init__(self, message): self.message = message raise MyError("My error") expected_response = { "errorType": "MyError", "errorMessage": "My error" } bootstrap.handle_event_request( self.lambda_runtime, raise_exception_handler, "invoke_id", self.event_body, "application/json", {}, {}, "invoked_function_arn", 0, bootstrap.StandardLogSink(), ) args, _ = self.lambda_runtime.post_invocation_error.call_args error_response = json.loads(args[1]) self.assertEqual(args[0], "invoke_id") self.assertTrue( expected_response.items() <= error_response.items(), "Expected response is not a subset of the actual response\nExpected: {}\nActual: {}" .format(expected_response, error_response), ) xray_fault = json.loads(args[2]) self.assertEqual(xray_fault["working_directory"], self.working_directory) self.assertEqual(len(xray_fault["exceptions"]), 1) self.assertEqual(xray_fault["exceptions"][0]["message"], expected_response["errorMessage"]) self.assertEqual(xray_fault["exceptions"][0]["type"], expected_response["errorType"]) self.assertEqual(len(xray_fault["exceptions"][0]["stack"]), 1) self.assertEqual(xray_fault["exceptions"][0]["stack"][0]["label"], "raise_exception_handler") self.assertIsInstance(xray_fault["exceptions"][0]["stack"][0]["line"], int) self.assertTrue( xray_fault["exceptions"][0]["stack"][0]["path"].endswith( os.path.relpath(__file__))) self.assertEqual(len(xray_fault["paths"]), 1) self.assertTrue(xray_fault["paths"][0].endswith( os.path.relpath(__file__)))
def test_application_json(self): bootstrap.handle_event_request( lambda_runtime_client=self.lambda_runtime, request_handler=lambda event, ctx: {"response": event["msg"]}, invoke_id="invoke-id", event_body=b'{"msg":"foo"}', content_type="application/json", client_context_json=None, cognito_identity_json=None, invoked_function_arn="invocation-arn", epoch_deadline_time_in_ms=1415836801003, log_sink=bootstrap.StandardLogSink(), ) self.lambda_runtime.post_invocation_result.assert_called_once_with( "invoke-id", '{"response": "foo"}', "application/json")
def test_handle_event_request_fault_exception(self): def raise_exception_handler(json_input, lambda_context): try: import invalid_module # noqa: F401 except ImportError: raise FaultException( "FaultExceptionType", "Fault exception msg", ["trace_line1\ntrace_line2", "trace_line3\ntrace_line4"], ) expected_response = { "errorType": "FaultExceptionType", "errorMessage": "Fault exception msg", "requestId": "invoke_id", "stackTrace": ["trace_line1\ntrace_line2", "trace_line3\ntrace_line4"], } bootstrap.handle_event_request( self.lambda_runtime, raise_exception_handler, "invoke_id", self.event_body, "application/json", {}, {}, "invoked_function_arn", 0, bootstrap.StandardLogSink(), ) args, _ = self.lambda_runtime.post_invocation_error.call_args error_response = json.loads(args[1]) self.assertEqual(args[0], "invoke_id") self.assertEqual(error_response.items(), expected_response.items()) self.assertEqual( json.loads(args[2]), { "working_directory": self.working_directory, "exceptions": [{ "message": expected_response["errorMessage"], "type": "LambdaValidationError", "stack": [], }], "paths": [], }, )
def test_json_request_binary_response(self): binary_data = b"\x89PNG\r\n\x1a\n\x00\x00\x00" bootstrap.handle_event_request( lambda_runtime_client=self.lambda_runtime, request_handler=lambda event, ctx: binary_data, invoke_id="invoke-id", event_body=b'{"msg":"ignored"}', content_type="application/json", client_context_json=None, cognito_identity_json=None, invoked_function_arn="invocation-arn", epoch_deadline_time_in_ms=1415836801003, log_sink=bootstrap.StandardLogSink(), ) self.lambda_runtime.post_invocation_result.assert_called_once_with( "invoke-id", binary_data, "application/unknown")
def test_handle_event_request_happy_case(self): bootstrap.handle_event_request( self.lambda_runtime, self.dummy_handler, "invoke_id", self.event_body, "application/json", {}, {}, "invoked_function_arn", 0, bootstrap.StandardLogSink(), ) self.lambda_runtime.post_invocation_result.assert_called_once_with( "invoke_id", '{"input": "event_body", "aws_request_id": "invoke_id"}', "application/json", )
def test_handle_event_request_invalid_response(self): def invalid_json_response(json_input, lambda_context): return type("obj", (object, ), {"propertyName": "propertyValue"}) expected_response = { "errorType": "Runtime.MarshalError", "errorMessage": "Unable to marshal response: Object of type type is not JSON serializable", } bootstrap.handle_event_request( self.lambda_runtime, invalid_json_response, "invoke_id", self.event_body, "application/json", {}, {}, "invoked_function_arn", 0, bootstrap.StandardLogSink(), ) args, _ = self.lambda_runtime.post_invocation_error.call_args error_response = json.loads(args[1]) self.assertEqual(args[0], "invoke_id") self.assertTrue( expected_response.items() <= error_response.items(), "Expected response is not a subset of the actual response\nExpected: {}\nActual: {}" .format(expected_response, error_response), ) self.assertEqual( json.loads(args[2]), { "working_directory": self.working_directory, "exceptions": [{ "message": expected_response["errorMessage"], "type": "LambdaValidationError", "stack": [], }], "paths": [], }, )
def test_handle_event_request_invalid_event_body(self): expected_response = { "errorType": "Runtime.UnmarshalError", "errorMessage": "Unable to unmarshal input: Expecting value: line 1 column 1 (char 0)", } invalid_event_body = "not_valid_json" bootstrap.handle_event_request( self.lambda_runtime, self.dummy_handler, "invoke_id", invalid_event_body, "application/json", {}, {}, "invoked_function_arn", 0, bootstrap.StandardLogSink(), ) args, _ = self.lambda_runtime.post_invocation_error.call_args error_response = json.loads(args[1]) self.assertEqual(args[0], "invoke_id") self.assertTrue( expected_response.items() <= error_response.items(), "Response doesn't contain all the necessary fields\nExpected: {}\nActual: {}" .format(expected_response, error_response), ) self.assertEqual( json.loads(args[2]), { "working_directory": self.working_directory, "exceptions": [{ "message": expected_response["errorMessage"], "type": "LambdaValidationError", "stack": [], }], "paths": [], }, )
def test_handle_event_request_fault_exception_logging_notype_nomessage( self, mock_stdout ): def raise_exception_handler(json_input, lambda_context): try: import invalid_module except ImportError as e: raise bootstrap.FaultException( None, None, traceback.format_list( [ ("spam.py", 3, "<module>", "spam.eggs()"), ("eggs.py", 42, "eggs", 'return "bacon"'), ] ), ) bootstrap.handle_event_request( self.lambda_runtime, raise_exception_handler, "invoke_id", self.event_body, "application/json", {}, {}, "invoked_function_arn", 0, bootstrap.StandardLogSink(), ) error_logs = "[ERROR]\r" error_logs += "Traceback (most recent call last):\r" error_logs += ' File "spam.py", line 3, in <module>\r' error_logs += " spam.eggs()\r" error_logs += ' File "eggs.py", line 42, in eggs\r' error_logs += ' return "bacon"\n' self.assertEqual(mock_stdout.getvalue(), error_logs)
def test_handle_event_request_fault_exception_logging_syntax_error( self, mock_load_module, mock_find_module, mock_stdout ): try: eval("-") except SyntaxError as e: syntax_error = e mock_find_module.return_value = (None, None, ("", "", None)) mock_load_module.side_effect = syntax_error response_handler = bootstrap._get_handler("a.b") bootstrap.handle_event_request( self.lambda_runtime, response_handler, "invoke_id", self.event_body, "application/json", {}, {}, "invoked_function_arn", 0, bootstrap.StandardLogSink(), ) import sys sys.stderr.write(mock_stdout.getvalue()) error_logs = "[ERROR] Runtime.UserCodeSyntaxError: Syntax error in module 'a': unexpected EOF while parsing (<string>, line 1)\r" error_logs += "Traceback (most recent call last):\r" error_logs += ' File "<string>" Line 1\r' error_logs += " -\n" self.assertEqual(mock_stdout.getvalue(), error_logs)
def test_handle_event_request_fault_exception_logging_notype_notrace( self, mock_stdout): def raise_exception_handler(json_input, lambda_context): try: import invalid_module # noqa: F401 except ImportError: raise bootstrap.FaultException(None, "Fault exception msg", None) bootstrap.handle_event_request( self.lambda_runtime, raise_exception_handler, "invoke_id", self.event_body, "application/json", {}, {}, "invoked_function_arn", 0, bootstrap.StandardLogSink(), ) error_logs = "[ERROR] Fault exception msg\rTraceback (most recent call last):\n" self.assertEqual(mock_stdout.getvalue(), error_logs)
def test_handle_event_request_fault_exception_logging(self, mock_stdout): def raise_exception_handler(json_input, lambda_context): try: import invalid_module # noqa: F401 except ImportError: raise bootstrap.FaultException( "FaultExceptionType", "Fault exception msg", traceback.format_list([ ("spam.py", 3, "<module>", "spam.eggs()"), ("eggs.py", 42, "eggs", 'return "bacon"'), ]), ) bootstrap.handle_event_request( self.lambda_runtime, raise_exception_handler, "invoke_id", self.event_body, "application/json", {}, {}, "invoked_function_arn", 0, bootstrap.StandardLogSink(), ) # NOTE: Indentation characters are NO-BREAK SPACE (U+00A0) not SPACE (U+0020) error_logs = "[ERROR] FaultExceptionType: Fault exception msg\r" error_logs += "Traceback (most recent call last):\r" error_logs += ' File "spam.py", line 3, in <module>\r' error_logs += " spam.eggs()\r" error_logs += ' File "eggs.py", line 42, in eggs\r' error_logs += ' return "bacon"\n' self.assertEqual(mock_stdout.getvalue(), error_logs)
def test_handle_event_request_fault_exception_logging_nomessage_notrace( self, mock_stdout ): def raise_exception_handler(json_input, lambda_context): try: import invalid_module except ImportError as e: raise bootstrap.FaultException("FaultExceptionType", None, None) bootstrap.handle_event_request( self.lambda_runtime, raise_exception_handler, "invoke_id", self.event_body, "application/json", {}, {}, "invoked_function_arn", 0, bootstrap.StandardLogSink(), ) error_logs = "[ERROR] FaultExceptionType\n" self.assertEqual(mock_stdout.getvalue(), error_logs)