def test_must_run_container_and_wait_for_logs(self, LambdaContainerMock): event = "event" code_dir = "some code dir" stdout = "stdout" stderr = "stderr" container = Mock() timer = Mock() debug_options = Mock() lambda_image_mock = Mock() self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock) # Using MagicMock to mock the context manager self.runtime._get_code_dir = MagicMock() self.runtime._get_code_dir( self.code_path).__enter__.return_value = code_dir # Configure interrupt handler self.runtime._configure_interrupt = Mock() self.runtime._configure_interrupt.return_value = timer LambdaContainerMock.return_value = container self.runtime.invoke(self.func_config, event, debug_context=debug_options, stdout=stdout, stderr=stderr) # Verify if Lambda Event data is set self.env_vars.add_lambda_event_body.assert_called_with(event) # Make sure env-vars get resolved self.env_vars.resolve.assert_called_with() # Make sure the context manager is called to return the code directory self.runtime._get_code_dir.assert_called_with(self.code_path) # Make sure the container is created with proper values LambdaContainerMock.assert_called_with( self.lang, self.handler, code_dir, self.layers, lambda_image_mock, memory_mb=self.DEFAULT_MEMORY, env_vars=self.env_var_value, debug_options=debug_options, ) # Run the container and get results self.manager_mock.run.assert_called_with(container) self.runtime._configure_interrupt.assert_called_with( self.name, self.DEFAULT_TIMEOUT, container, True) container.wait_for_logs.assert_called_with(stdout=stdout, stderr=stderr) # Finally block timer.cancel.assert_called_with() self.manager_mock.stop.assert_called_with(container)
def test_keyboard_interrupt_must_not_raise(self, LambdaContainerMock): event = "event" code_dir = "some code dir" stdout = "stdout" stderr = "stderr" container = Mock() layer_downloader = Mock() self.runtime = LambdaRuntime(self.manager_mock, layer_downloader) # Using MagicMock to mock the context manager self.runtime._get_code_dir = MagicMock() self.runtime._get_code_dir(self.code_path).__enter__.return_value = code_dir self.runtime._configure_interrupt = Mock() LambdaContainerMock.return_value = container self.manager_mock.run.side_effect = KeyboardInterrupt("some exception") self.runtime.invoke(self.func_config, event, stdout=stdout, stderr=stderr) # Run the container and get results self.manager_mock.run.assert_called_with(container) self.runtime._configure_interrupt.assert_not_called() # Finally block must be called self.manager_mock.stop.assert_called_with(container)
def test_exception_from_run_must_trigger_cleanup(self, LambdaContainerMock): event = "event" code_dir = "some code dir" stdout = "stdout" stderr = "stderr" container = Mock() timer = Mock() layer_downloader = Mock() self.runtime = LambdaRuntime(self.manager_mock, layer_downloader) # Using MagicMock to mock the context manager self.runtime._get_code_dir = MagicMock() self.runtime._get_code_dir.return_value = code_dir self.runtime._configure_interrupt = Mock() self.runtime._configure_interrupt.return_value = timer LambdaContainerMock.return_value = container container.is_running.return_value = False self.manager_mock.run.side_effect = ValueError("some exception") with self.assertRaises(ValueError): self.runtime.invoke(self.func_config, event, debug_context=None, stdout=stdout, stderr=stderr) # Run the container and get results self.manager_mock.run.assert_called_with(container) self.runtime._configure_interrupt.assert_not_called() # Finally block must be called # But timer was not yet created. It should not be called timer.cancel.assert_not_called() # In any case, stop the container self.manager_mock.stop.assert_called_with(container)
def setUp(self): self.name = "name" self.timeout = 123 self.container = Mock() self.manager_mock = Mock() self.runtime = LambdaRuntime(self.manager_mock)
def setUp(self): self.code_dir = { "echo": nodejs_lambda(ECHO_CODE), "sleep": nodejs_lambda(SLEEP_CODE), "envvar": nodejs_lambda(GET_ENV_VAR) } self.container_manager = ContainerManager() self.runtime = LambdaRuntime(self.container_manager)
def test_must_run_container_and_wait_for_result(self, LambdaContainerMock): event = "event" code_dir = "some code dir" stdout = "stdout" stderr = "stderr" container = Mock() timer = Mock() debug_options = Mock() lambda_image_mock = Mock() self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock) # Using MagicMock to mock the context manager self.runtime._get_code_dir = MagicMock() self.runtime._get_code_dir.return_value = code_dir self.runtime._clean_decompressed_paths = MagicMock() # Configure interrupt handler self.runtime._configure_interrupt = Mock() self.runtime._configure_interrupt.return_value = timer LambdaContainerMock.return_value = container container.is_running.return_value = False self.runtime.invoke(self.func_config, event, debug_context=debug_options, stdout=stdout, stderr=stderr) # Make sure env-vars get resolved self.env_vars.resolve.assert_called_with() # Make sure the context manager is called to return the code directory self.runtime._get_code_dir.assert_called_with(self.code_path) # Make sure the container is created with proper values LambdaContainerMock.assert_called_with( self.lang, self.imageuri, self.handler, self.packagetype, self.imageconfig, code_dir, self.layers, lambda_image_mock, debug_options=debug_options, env_vars=self.env_var_value, memory_mb=self.DEFAULT_MEMORY, ) # Run the container and get results self.manager_mock.run.assert_called_with(container) self.runtime._configure_interrupt.assert_called_with(self.name, self.DEFAULT_TIMEOUT, container, True) container.wait_for_result.assert_called_with(event=event, name=self.name, stdout=stdout, stderr=stderr) # Finally block timer.cancel.assert_called_with() self.manager_mock.stop.assert_called_with(container) self.runtime._clean_decompressed_paths.assert_called_with()
def test_must_skip_run_running_container(self): container = Mock() container.is_running.return_value = True debug_options = Mock() lambda_image_mock = Mock() self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock) self.runtime.run(container, self.func_config, debug_context=debug_options) self.manager_mock.run.assert_not_called()
def setUp(self): self.code_dir = { "echo": nodejs_lambda(ECHO_CODE), "sleep": nodejs_lambda(SLEEP_CODE), "envvar": nodejs_lambda(GET_ENV_VAR) } self.container_manager = ContainerManager() layer_downloader = LayerDownloader("./", "./") self.lambda_image = LambdaImage(layer_downloader, False, False) self.runtime = LambdaRuntime(self.container_manager, self.lambda_image)
def test_keyboard_interrupt_must_raise(self): container = Mock() container.is_running.return_value = False debug_options = Mock() lambda_image_mock = Mock() self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock) self.manager_mock.run.side_effect = KeyboardInterrupt("some exception") with self.assertRaises(KeyboardInterrupt): self.runtime.run(container, self.func_config, debug_context=debug_options)
class TestLambdaRuntime_get_code_dir(TestCase): def setUp(self): self.manager_mock = Mock() self.layer_downloader = Mock() self.runtime = LambdaRuntime(self.manager_mock, self.layer_downloader) @parameterized.expand([ (".zip"), (".ZIP"), (".JAR"), (".jar") ]) @patch("samcli.local.lambdafn.runtime.os") @patch("samcli.local.lambdafn.runtime.shutil") @patch("samcli.local.lambdafn.runtime._unzip_file") def test_must_uncompress_zip_files(self, extension, unzip_file_mock, shutil_mock, os_mock): code_path = "foo" + extension decompressed_dir = "decompressed-dir" unzip_file_mock.return_value = decompressed_dir os_mock.path.isfile.return_value = True with self.runtime._get_code_dir(code_path) as result: self.assertEquals(result, decompressed_dir) unzip_file_mock.assert_called_with(code_path) os_mock.path.isfile.assert_called_with(code_path) # Finally block must call this after the context manager exists shutil_mock.rmtree.assert_called_with(decompressed_dir) @patch("samcli.local.lambdafn.runtime.os") @patch("samcli.local.lambdafn.runtime.shutil") @patch("samcli.local.lambdafn.runtime._unzip_file") def test_must_return_a_valid_file(self, unzip_file_mock, shutil_mock, os_mock): """ Input is a file that exists, but is not a zip/jar file """ code_path = "foo.exe" os_mock.path.isfile.return_value = True with self.runtime._get_code_dir(code_path) as result: # code path must be returned. No decompression self.assertEquals(result, code_path) unzip_file_mock.assert_not_called() # Unzip must not be called os_mock.path.isfile.assert_called_with(code_path) # Because we never unzipped anything, we should never delete shutil_mock.rmtree.assert_not_called()
def test_must_create_container_first_if_passed_container_is_none(self): container = Mock() container.is_running.return_value = False debug_options = Mock() lambda_image_mock = Mock() self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock) create_mock = Mock() self.runtime.create = create_mock create_mock.return_value = container self.runtime.run(None, self.func_config, debug_context=debug_options) create_mock.assert_called_with(self.func_config, debug_options) self.manager_mock.run.assert_called_with(container)
def test_must_run_passed_container(self): event = "event" container = Mock() container.is_running.return_value = False debug_options = Mock() lambda_image_mock = Mock() self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock) self.runtime.run(container, self.func_config, debug_context=debug_options, event=event) self.manager_mock.run.assert_called_with(container)
def test_must_invoke(self): input_event = '"some data"' expected_env_vars = { "var1": "override_value1", "var2": "shell_env_value2" } manager = ContainerManager() local_runtime = LambdaRuntime(manager) runner = LocalLambdaRunner(local_runtime, self.mock_function_provider, self.cwd, self.env_var_overrides, debug_args=None, debug_port=None, aws_profile=None) # Append the real AWS credentials to the expected values. creds = runner.get_aws_creds() # default value for creds is not configured by the test. But coming from a downstream class expected_env_vars["AWS_SECRET_ACCESS_KEY"] = creds.get("secret", "defaultsecret") expected_env_vars["AWS_ACCESS_KEY_ID"] = creds.get("key", "defaultkey") expected_env_vars["AWS_REGION"] = creds.get("region", "us-east-1") stdout_stream = io.BytesIO() stderr_stream = io.BytesIO() runner.invoke(self.function_name, input_event, stdout=stdout_stream, stderr=stderr_stream) # stderr is where the Lambda container runtime logs are available. It usually contains requestId, start time # etc. So it is non-zero in size self.assertGreater(len(stderr_stream.getvalue().strip()), 0, "stderr stream must contain data") # This should contain all the environment variables passed to the function actual_output = json.loads(stdout_stream.getvalue().strip().decode('utf-8')) for key, value in expected_env_vars.items(): self.assertTrue(key in actual_output, "Key '{}' must be in function output".format(key)) self.assertEquals(actual_output.get(key), value)
def setUp(self): self.code_dir = nodejs_lambda(SLEEP_CODE) Input = namedtuple('Input', ["timeout", "sleep", "check_stdout"]) self.inputs = [ Input(sleep=1, timeout=10, check_stdout=True), Input(sleep=2, timeout=10, check_stdout=True), Input(sleep=3, timeout=10, check_stdout=True), Input(sleep=5, timeout=10, check_stdout=True), Input(sleep=8, timeout=10, check_stdout=True), Input(sleep=13, timeout=12, check_stdout=False), # Must timeout Input(sleep=21, timeout=20, check_stdout=False), # Must timeout. So stdout will be empty ] random.shuffle(self.inputs) container_manager = ContainerManager() self.runtime = LambdaRuntime(container_manager)
def setUp(self): self.name = "name" self.timeout = 123 self.container = Mock() self.manager_mock = Mock() self.layer_downloader = Mock() self.runtime = LambdaRuntime(self.manager_mock, self.layer_downloader)
def test_must_create_lambda_container(self, LambdaContainerMock): event = "event" code_dir = "some code dir" container = Mock() debug_options = Mock() lambda_image_mock = Mock() self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock) # Using MagicMock to mock the context manager self.runtime._get_code_dir = MagicMock() self.runtime._get_code_dir.return_value = code_dir LambdaContainerMock.return_value = container self.runtime.create(self.func_config, debug_context=debug_options, event=event) # Verify if Lambda Event data is set self.env_vars.add_lambda_event_body.assert_called_with(event) # Make sure env-vars get resolved self.env_vars.resolve.assert_called_with() # Make sure the context manager is called to return the code directory self.runtime._get_code_dir.assert_called_with(self.code_path) # Make sure the container is created with proper values LambdaContainerMock.assert_called_with( self.lang, self.imageuri, self.handler, self.packagetype, self.imageconfig, code_dir, self.layers, lambda_image_mock, debug_options=debug_options, env_vars=self.env_var_value, memory_mb=self.DEFAULT_MEMORY, ) # Run the container and get results self.manager_mock.create.assert_called_with(container)
def setUp(self): self.host = "127.0.0.1" self.port = random.randint(30000, 40000) # get a random port self.url = "http://{}:{}".format(self.host, self.port) self.code_abs_path = nodejs_lambda(API_GATEWAY_ECHO_EVENT) # Let's convert this absolute path to relative path. Let the parent be the CWD, and codeuri be the folder self.cwd = os.path.dirname(self.code_abs_path) self.code_uri = os.path.relpath(self.code_abs_path, self.cwd) # Get relative path with respect to CWD # Setup a static file in the directory self.static_dir = "mystaticdir" self.static_file_name = "myfile.txt" self.static_file_content = "This is a static file" self._setup_static_file( os.path.join(self.cwd, self.static_dir), # Create static directory with in cwd self.static_file_name, self.static_file_content, ) # Create one Lambda function self.function_name = "name" self.function = provider.Function( name=self.function_name, runtime="nodejs4.3", memory=256, timeout=5, handler="index.handler", codeuri=self.code_uri, environment={}, rolearn=None, layers=[], ) self.mock_function_provider = Mock() self.mock_function_provider.get.return_value = self.function # Setup two APIs pointing to the same function routes = [ Route(path="/get", methods=["GET"], function_name=self.function_name), Route(path="/post", methods=["POST"], function_name=self.function_name), ] api = Api(routes=routes) self.api_provider_mock = Mock() self.api_provider_mock.get_all.return_value = api # Now wire up the Lambda invoker and pass it through the context self.lambda_invoke_context_mock = Mock() manager = ContainerManager() layer_downloader = LayerDownloader("./", "./") lambda_image = LambdaImage(layer_downloader, False, False) local_runtime = LambdaRuntime(manager, lambda_image) lambda_runner = LocalLambdaRunner(local_runtime, self.mock_function_provider, self.cwd, debug_context=None) self.lambda_invoke_context_mock.local_lambda_runner = lambda_runner self.lambda_invoke_context_mock.get_cwd.return_value = self.cwd
def setUp(self): self.code_dir = nodejs_lambda(SLEEP_CODE) Input = namedtuple("Input", ["timeout", "sleep", "check_stdout"]) self.inputs = [ Input(sleep=1, timeout=10, check_stdout=True), Input(sleep=2, timeout=10, check_stdout=True), Input(sleep=3, timeout=10, check_stdout=True), Input(sleep=5, timeout=10, check_stdout=True), Input(sleep=8, timeout=10, check_stdout=True), Input(sleep=13, timeout=12, check_stdout=False), # Must timeout Input(sleep=21, timeout=20, check_stdout=False), # Must timeout. So stdout will be empty ] random.shuffle(self.inputs) container_manager = ContainerManager() layer_downloader = LayerDownloader("./", "./") self.lambda_image = LambdaImage(layer_downloader, False, False) self.runtime = LambdaRuntime(container_manager, self.lambda_image)
def test_keyboard_interrupt_must_raise(self, LambdaContainerMock): code_dir = "some code dir" container = Mock() debug_options = Mock() lambda_image_mock = Mock() self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock) # Using MagicMock to mock the context manager self.runtime._get_code_dir = MagicMock() self.runtime._get_code_dir.return_value = code_dir LambdaContainerMock.return_value = container self.manager_mock.create.side_effect = KeyboardInterrupt("some exception") with self.assertRaises(KeyboardInterrupt): self.runtime.create(self.func_config, debug_context=debug_options)
def test_exception_from_wait_for_logs_must_trigger_cleanup( self, LambdaContainerMock): event = "event" debug_port = 123 debug_arg = "abc" code_dir = "some code dir" stdout = "stdout" stderr = "stderr" container = Mock() timer = Mock() self.runtime = LambdaRuntime(self.manager_mock) # Using MagicMock to mock the context manager self.runtime._get_code_dir = MagicMock() self.runtime._get_code_dir( self.code_path).__enter__.return_value = code_dir self.runtime._configure_interrupt = Mock() self.runtime._configure_interrupt.return_value = timer LambdaContainerMock.return_value = container container.wait_for_logs.side_effect = ValueError("some exception") with self.assertRaises(ValueError): self.runtime.invoke(self.func_config, event, debug_port=debug_port, debug_args=debug_arg, stdout=stdout, stderr=stderr) # Run the container and get results self.manager_mock.run.assert_called_with(container) self.runtime._configure_interrupt.assert_called_with( self.name, self.DEFAULT_TIMEOUT, container, True) # Finally block must be called # Timer was created. So it must be cancelled timer.cancel.assert_called_with() # In any case, stop the container self.manager_mock.stop.assert_called_with(container)
def lambda_runtime(self) -> LambdaRuntime: if not self._lambda_runtimes: layer_downloader = LayerDownloader(self._layer_cache_basedir, self.get_cwd(), self._stacks) image_builder = LambdaImage(layer_downloader, self._skip_pull_image, self._force_image_build) self._lambda_runtimes = { ContainersMode.WARM: WarmLambdaRuntime(self._container_manager, image_builder), ContainersMode.COLD: LambdaRuntime(self._container_manager, image_builder), } return self._lambda_runtimes[self._containers_mode]
def make_service(function_provider, cwd): port = random_port() manager = ContainerManager() layer_downloader = LayerDownloader("./", "./") image_builder = LambdaImage(layer_downloader, False, False) local_runtime = LambdaRuntime(manager, image_builder) lambda_runner = LocalLambdaRunner(local_runtime=local_runtime, function_provider=function_provider, cwd=cwd) service = LocalLambdaInvokeService(lambda_runner, port=port, host="127.0.0.1") scheme = "http" url = "{}://127.0.0.1:{}".format(scheme, port) return service, port, url, scheme
def test_must_run_container_and_wait_for_logs(self, LambdaContainerMock): event = "event" code_dir = "some code dir" stdout = "stdout" stderr = "stderr" container = Mock() timer = Mock() debug_options = Mock() lambda_image_mock = Mock() self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock) # Using MagicMock to mock the context manager self.runtime._get_code_dir = MagicMock() self.runtime._get_code_dir(self.code_path).__enter__.return_value = code_dir # Configure interrupt handler self.runtime._configure_interrupt = Mock() self.runtime._configure_interrupt.return_value = timer LambdaContainerMock.return_value = container self.runtime.invoke(self.func_config, event, debug_context=debug_options, stdout=stdout, stderr=stderr) # Verify if Lambda Event data is set self.env_vars.add_lambda_event_body.assert_called_with(event) # Make sure env-vars get resolved self.env_vars.resolve.assert_called_with() # Make sure the context manager is called to return the code directory self.runtime._get_code_dir.assert_called_with(self.code_path) # Make sure the container is created with proper values LambdaContainerMock.assert_called_with(self.lang, self.handler, code_dir, self.layers, lambda_image_mock, memory_mb=self.DEFAULT_MEMORY, env_vars=self.env_var_value, debug_options=debug_options) # Run the container and get results self.manager_mock.run.assert_called_with(container) self.runtime._configure_interrupt.assert_called_with(self.name, self.DEFAULT_TIMEOUT, container, True) container.wait_for_logs.assert_called_with(stdout=stdout, stderr=stderr) # Finally block timer.cancel.assert_called_with() self.manager_mock.stop.assert_called_with(container)
def make_service(function_provider, cwd): port = random_port() manager = ContainerManager() local_runtime = LambdaRuntime(manager) lambda_runner = LocalLambdaRunner(local_runtime=local_runtime, function_provider=function_provider, cwd=cwd) service = LocalLambdaInvokeService(lambda_runner, port=port, host='127.0.0.1') scheme = "http" url = '{}://127.0.0.1:{}'.format(scheme, port) return service, port, url, scheme
def local_lambda_runner(self): """ Returns an instance of the runner capable of running Lambda functions locally :return samcli.commands.local.lib.local_lambda.LocalLambdaRunner: Runner configured to run Lambda functions locally """ container_manager = ContainerManager(docker_network_id=self._docker_network, skip_pull_image=self._skip_pull_image) lambda_runtime = LambdaRuntime(container_manager) return LocalLambdaRunner(local_runtime=lambda_runtime, function_provider=self._function_provider, cwd=self.get_cwd(), env_vars_values=self._env_vars_value, debug_context=self._debug_context, aws_profile=self._aws_profile, aws_region=self._aws_region)
def local_lambda_runner(self): """ Returns an instance of the runner capable of running Lambda functions locally :return samcli.commands.local.lib.local_lambda.LocalLambdaRunner: Runner configured to run Lambda functions locally """ layer_downloader = LayerDownloader(self._layer_cache_basedir, self.get_cwd()) image_builder = LambdaImage(layer_downloader, self._skip_pull_image, self._force_image_build) lambda_runtime = LambdaRuntime(self._container_manager, image_builder) return LocalLambdaRunner(local_runtime=lambda_runtime, function_provider=self._function_provider, cwd=self.get_cwd(), env_vars_values=self._env_vars_value, debug_context=self._debug_context)
def test_exception_from_wait_for_logs_must_trigger_cleanup(self, LambdaContainerMock): event = "event" code_dir = "some code dir" stdout = "stdout" stderr = "stderr" container = Mock() timer = Mock() debug_options = Mock() layer_downloader = Mock() self.runtime = LambdaRuntime(self.manager_mock, layer_downloader) # Using MagicMock to mock the context manager self.runtime._get_code_dir = MagicMock() self.runtime._get_code_dir(self.code_path).__enter__.return_value = code_dir self.runtime._configure_interrupt = Mock() self.runtime._configure_interrupt.return_value = timer LambdaContainerMock.return_value = container container.wait_for_logs.side_effect = ValueError("some exception") with self.assertRaises(ValueError): self.runtime.invoke(self.func_config, event, debug_context=debug_options, stdout=stdout, stderr=stderr) # Run the container and get results self.manager_mock.run.assert_called_with(container) self.runtime._configure_interrupt.assert_called_with(self.name, self.DEFAULT_TIMEOUT, container, True) # Finally block must be called # Timer was created. So it must be cancelled timer.cancel.assert_called_with() # In any case, stop the container self.manager_mock.stop.assert_called_with(container)
def test_exception_from_run_must_trigger_cleanup(self, LambdaContainerMock): event = "event" code_dir = "some code dir" stdout = "stdout" stderr = "stderr" container = Mock() timer = Mock() layer_downloader = Mock() self.runtime = LambdaRuntime(self.manager_mock, layer_downloader) # Using MagicMock to mock the context manager self.runtime._get_code_dir = MagicMock() self.runtime._get_code_dir(self.code_path).__enter__.return_value = code_dir self.runtime._configure_interrupt = Mock() self.runtime._configure_interrupt.return_value = timer LambdaContainerMock.return_value = container self.manager_mock.run.side_effect = ValueError("some exception") with self.assertRaises(ValueError): self.runtime.invoke(self.func_config, event, debug_context=None, stdout=stdout, stderr=stderr) # Run the container and get results self.manager_mock.run.assert_called_with(container) self.runtime._configure_interrupt.assert_not_called() # Finally block must be called # But timer was not yet created. It should not be called timer.cancel.assert_not_called() # In any case, stop the container self.manager_mock.stop.assert_called_with(container)
class LambdaRuntime_create(TestCase): DEFAULT_MEMORY = 128 DEFAULT_TIMEOUT = 3 def setUp(self): self.manager_mock = Mock() self.name = "name" self.lang = "runtime" self.handler = "handler" self.code_path = "code-path" self.layers = [] self.manager_mock = Mock() self.imageuri = None self.packagetype = ZIP self.imageconfig = None self.func_config = FunctionConfig( self.name, self.lang, self.handler, self.imageuri, self.imageconfig, self.packagetype, self.code_path, self.layers, ) self.env_vars = Mock() self.func_config.env_vars = self.env_vars self.env_var_value = {"a": "b"} self.env_vars.resolve.return_value = self.env_var_value @patch("samcli.local.lambdafn.runtime.LambdaContainer") def test_must_create_lambda_container(self, LambdaContainerMock): code_dir = "some code dir" container = Mock() debug_options = Mock() lambda_image_mock = Mock() self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock) # Using MagicMock to mock the context manager self.runtime._get_code_dir = MagicMock() self.runtime._get_code_dir.return_value = code_dir LambdaContainerMock.return_value = container self.runtime.create(self.func_config, debug_context=debug_options) # Make sure env-vars get resolved self.env_vars.resolve.assert_called_with() # Make sure the context manager is called to return the code directory self.runtime._get_code_dir.assert_called_with(self.code_path) # Make sure the container is created with proper values LambdaContainerMock.assert_called_with( self.lang, self.imageuri, self.handler, self.packagetype, self.imageconfig, code_dir, self.layers, lambda_image_mock, debug_options=debug_options, env_vars=self.env_var_value, memory_mb=self.DEFAULT_MEMORY, ) # Run the container and get results self.manager_mock.create.assert_called_with(container) @patch("samcli.local.lambdafn.runtime.LambdaContainer") def test_keyboard_interrupt_must_raise(self, LambdaContainerMock): code_dir = "some code dir" container = Mock() debug_options = Mock() lambda_image_mock = Mock() self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock) # Using MagicMock to mock the context manager self.runtime._get_code_dir = MagicMock() self.runtime._get_code_dir.return_value = code_dir LambdaContainerMock.return_value = container self.manager_mock.create.side_effect = KeyboardInterrupt("some exception") with self.assertRaises(KeyboardInterrupt): self.runtime.create(self.func_config, debug_context=debug_options)
def setUp(self): self.manager_mock = Mock() self.runtime = LambdaRuntime(self.manager_mock)
def setUp(self): self.manager_mock = Mock() self.layer_downloader = Mock() self.runtime = LambdaRuntime(self.manager_mock, self.layer_downloader)
class LambdaRuntime_run(TestCase): DEFAULT_MEMORY = 128 DEFAULT_TIMEOUT = 3 def setUp(self): self.manager_mock = Mock() self.name = "name" self.lang = "runtime" self.handler = "handler" self.code_path = "code-path" self.layers = [] self.imageuri = None self.packagetype = ZIP self.imageconfig = None self.func_config = FunctionConfig( self.name, self.lang, self.handler, self.imageuri, self.imageconfig, self.packagetype, self.code_path, self.layers, ) self.env_vars = Mock() self.func_config.env_vars = self.env_vars self.env_var_value = {"a": "b"} self.env_vars.resolve.return_value = self.env_var_value def test_must_run_passed_container(self): container = Mock() container.is_running.return_value = False debug_options = Mock() lambda_image_mock = Mock() self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock) self.runtime.run(container, self.func_config, debug_context=debug_options) self.manager_mock.run.assert_called_with(container) def test_must_create_container_first_if_passed_container_is_none(self): container = Mock() container.is_running.return_value = False debug_options = Mock() lambda_image_mock = Mock() self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock) create_mock = Mock() self.runtime.create = create_mock create_mock.return_value = container self.runtime.run(None, self.func_config, debug_context=debug_options) create_mock.assert_called_with(self.func_config, debug_options) self.manager_mock.run.assert_called_with(container) def test_must_skip_run_running_container(self): container = Mock() container.is_running.return_value = True debug_options = Mock() lambda_image_mock = Mock() self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock) self.runtime.run(container, self.func_config, debug_context=debug_options) self.manager_mock.run.assert_not_called() def test_keyboard_interrupt_must_raise(self): container = Mock() container.is_running.return_value = False debug_options = Mock() lambda_image_mock = Mock() self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock) self.manager_mock.run.side_effect = KeyboardInterrupt("some exception") with self.assertRaises(KeyboardInterrupt): self.runtime.run(container, self.func_config, debug_context=debug_options)
class LambdaRuntime_invoke(TestCase): DEFAULT_MEMORY = 128 DEFAULT_TIMEOUT = 3 def setUp(self): self.manager_mock = Mock() self.name = "name" self.lang = "runtime" self.handler = "handler" self.code_path = "code-path" self.layers = [] self.func_config = FunctionConfig(self.name, self.lang, self.handler, self.code_path, self.layers) self.env_vars = Mock() self.func_config.env_vars = self.env_vars self.env_var_value = {"a": "b"} self.env_vars.resolve.return_value = self.env_var_value @patch("samcli.local.lambdafn.runtime.LambdaContainer") def test_must_run_container_and_wait_for_logs(self, LambdaContainerMock): event = "event" code_dir = "some code dir" stdout = "stdout" stderr = "stderr" container = Mock() timer = Mock() debug_options = Mock() lambda_image_mock = Mock() self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock) # Using MagicMock to mock the context manager self.runtime._get_code_dir = MagicMock() self.runtime._get_code_dir(self.code_path).__enter__.return_value = code_dir # Configure interrupt handler self.runtime._configure_interrupt = Mock() self.runtime._configure_interrupt.return_value = timer LambdaContainerMock.return_value = container self.runtime.invoke(self.func_config, event, debug_context=debug_options, stdout=stdout, stderr=stderr) # Verify if Lambda Event data is set self.env_vars.add_lambda_event_body.assert_called_with(event) # Make sure env-vars get resolved self.env_vars.resolve.assert_called_with() # Make sure the context manager is called to return the code directory self.runtime._get_code_dir.assert_called_with(self.code_path) # Make sure the container is created with proper values LambdaContainerMock.assert_called_with(self.lang, self.handler, code_dir, self.layers, lambda_image_mock, memory_mb=self.DEFAULT_MEMORY, env_vars=self.env_var_value, debug_options=debug_options) # Run the container and get results self.manager_mock.run.assert_called_with(container) self.runtime._configure_interrupt.assert_called_with(self.name, self.DEFAULT_TIMEOUT, container, True) container.wait_for_logs.assert_called_with(stdout=stdout, stderr=stderr) # Finally block timer.cancel.assert_called_with() self.manager_mock.stop.assert_called_with(container) @patch("samcli.local.lambdafn.runtime.LambdaContainer") def test_exception_from_run_must_trigger_cleanup(self, LambdaContainerMock): event = "event" code_dir = "some code dir" stdout = "stdout" stderr = "stderr" container = Mock() timer = Mock() layer_downloader = Mock() self.runtime = LambdaRuntime(self.manager_mock, layer_downloader) # Using MagicMock to mock the context manager self.runtime._get_code_dir = MagicMock() self.runtime._get_code_dir(self.code_path).__enter__.return_value = code_dir self.runtime._configure_interrupt = Mock() self.runtime._configure_interrupt.return_value = timer LambdaContainerMock.return_value = container self.manager_mock.run.side_effect = ValueError("some exception") with self.assertRaises(ValueError): self.runtime.invoke(self.func_config, event, debug_context=None, stdout=stdout, stderr=stderr) # Run the container and get results self.manager_mock.run.assert_called_with(container) self.runtime._configure_interrupt.assert_not_called() # Finally block must be called # But timer was not yet created. It should not be called timer.cancel.assert_not_called() # In any case, stop the container self.manager_mock.stop.assert_called_with(container) @patch("samcli.local.lambdafn.runtime.LambdaContainer") def test_exception_from_wait_for_logs_must_trigger_cleanup(self, LambdaContainerMock): event = "event" code_dir = "some code dir" stdout = "stdout" stderr = "stderr" container = Mock() timer = Mock() debug_options = Mock() layer_downloader = Mock() self.runtime = LambdaRuntime(self.manager_mock, layer_downloader) # Using MagicMock to mock the context manager self.runtime._get_code_dir = MagicMock() self.runtime._get_code_dir(self.code_path).__enter__.return_value = code_dir self.runtime._configure_interrupt = Mock() self.runtime._configure_interrupt.return_value = timer LambdaContainerMock.return_value = container container.wait_for_logs.side_effect = ValueError("some exception") with self.assertRaises(ValueError): self.runtime.invoke(self.func_config, event, debug_context=debug_options, stdout=stdout, stderr=stderr) # Run the container and get results self.manager_mock.run.assert_called_with(container) self.runtime._configure_interrupt.assert_called_with(self.name, self.DEFAULT_TIMEOUT, container, True) # Finally block must be called # Timer was created. So it must be cancelled timer.cancel.assert_called_with() # In any case, stop the container self.manager_mock.stop.assert_called_with(container) @patch("samcli.local.lambdafn.runtime.LambdaContainer") def test_keyboard_interrupt_must_not_raise(self, LambdaContainerMock): event = "event" code_dir = "some code dir" stdout = "stdout" stderr = "stderr" container = Mock() layer_downloader = Mock() self.runtime = LambdaRuntime(self.manager_mock, layer_downloader) # Using MagicMock to mock the context manager self.runtime._get_code_dir = MagicMock() self.runtime._get_code_dir(self.code_path).__enter__.return_value = code_dir self.runtime._configure_interrupt = Mock() LambdaContainerMock.return_value = container self.manager_mock.run.side_effect = KeyboardInterrupt("some exception") self.runtime.invoke(self.func_config, event, stdout=stdout, stderr=stderr) # Run the container and get results self.manager_mock.run.assert_called_with(container) self.runtime._configure_interrupt.assert_not_called() # Finally block must be called self.manager_mock.stop.assert_called_with(container)
class TestLambdaRuntime_configure_interrupt(TestCase): def setUp(self): self.name = "name" self.timeout = 123 self.container = Mock() self.manager_mock = Mock() self.layer_downloader = Mock() self.runtime = LambdaRuntime(self.manager_mock, self.layer_downloader) @patch("samcli.local.lambdafn.runtime.threading") @patch("samcli.local.lambdafn.runtime.signal") def test_must_setup_timer(self, SignalMock, ThreadingMock): is_debugging = False # We are not debugging. So setup timer timer_obj = Mock() ThreadingMock.Timer.return_value = timer_obj result = self.runtime._configure_interrupt(self.name, self.timeout, self.container, is_debugging) self.assertEquals(result, timer_obj) ThreadingMock.Timer.assert_called_with(self.timeout, ANY, ()) timer_obj.start.assert_called_with() SignalMock.signal.assert_not_called() # must not setup signal handler @patch("samcli.local.lambdafn.runtime.threading") @patch("samcli.local.lambdafn.runtime.signal") def test_must_setup_signal_handler(self, SignalMock, ThreadingMock): is_debugging = True # We are debugging. So setup signal SignalMock.SIGTERM = sigterm = "sigterm" result = self.runtime._configure_interrupt(self.name, self.timeout, self.container, is_debugging) self.assertIsNone(result, "There are no return values when setting up signal handler") SignalMock.signal.assert_called_with(sigterm, ANY) ThreadingMock.Timer.signal.assert_not_called() # must not setup timer @patch("samcli.local.lambdafn.runtime.threading") @patch("samcli.local.lambdafn.runtime.signal") def test_verify_signal_handler(self, SignalMock, ThreadingMock): """ Verify the internal implementation of the Signal Handler """ is_debugging = True # We are debugging. So setup signal SignalMock.SIGTERM = "sigterm" # Fake the real method with a Lambda. Also run the handler immediately. SignalMock.signal = lambda term, handler: handler("a", "b") self.runtime._configure_interrupt(self.name, self.timeout, self.container, is_debugging) # This method should be called from within the Signal Handler self.manager_mock.stop.assert_called_with(self.container) @patch("samcli.local.lambdafn.runtime.threading") @patch("samcli.local.lambdafn.runtime.signal") def test_verify_timer_handler(self, SignalMock, ThreadingMock): """ Verify the internal implementation of the Signal Handler """ is_debugging = False def fake_timer(timeout, handler, args): handler() return Mock() # Fake the real method with a Lambda. Also run the handler immediately. ThreadingMock.Timer = fake_timer self.runtime._configure_interrupt(self.name, self.timeout, self.container, is_debugging) # This method should be called from within the Timer Handler self.manager_mock.stop.assert_called_with(self.container)