# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
"""Tests scenarios for Firecracker signal handling."""

import os
from signal import SIGBUS, SIGSEGV
from time import sleep

import pytest

import host_tools.logging as log_tools


@pytest.mark.parametrize(
    "signum",
    [SIGBUS, SIGSEGV]
)
def test_sigbus_sigsegv(test_microvm_with_api, signum):
    """Test signal handling for `SIGBUS` and `SIGSEGV`."""
    test_microvm = test_microvm_with_api
    test_microvm.spawn()

    # We don't need to monitor the memory for this test.
    test_microvm.memory_events_queue = None

    test_microvm.basic_config()

    # Configure logging.
    log_fifo_path = os.path.join(test_microvm.path, 'log_fifo')
    log_fifo = log_tools.Fifo(log_fifo_path)
    response = test_microvm.logger.put(
        log_fifo=test_microvm.create_jailed_resource(log_fifo_path),
        level='Error',
        show_level=False,
        show_log_origin=False
    )
    assert test_microvm.api_session.is_status_no_content(response.status_code)

    test_microvm.start()
    firecracker_pid = int(test_microvm.jailer_clone_pid)

    sleep(0.5)
    os.kill(firecracker_pid, signum)

    msg = 'Shutting down VM after intercepting signal {}'.format(signum)
    log_fifo.flags = log_fifo.flags & ~os.O_NONBLOCK
    lines = log_fifo.sequential_reader(5)

    msg_found = False
    for line in lines:
        if msg in line:
            msg_found = True
            break
    assert msg_found

@@ -193,24 +193,34 @@
 port SIGBUS,
+ SIGRTMIN,
  SIGSEGV%0Afro
@@ -216,16 +216,16 @@
 SIGSEGV%0A
-
 from tim
@@ -294,16 +294,55 @@
 g_tools%0A
+import host_tools.network as net_tools%0A
 %0A%0A@pytes
@@ -1545,16 +1545,16 @@
   break%0A
-
     asse
@@ -1566,8 +1566,1161 @@
 g_found%0A
+%0A%0Adef test_handled_signals(test_microvm_with_ssh, network_config):%0A    %22%22%22Test that handled signals don't kill the microVM.%22%22%22%0A    microvm = test_microvm_with_ssh%0A    microvm.spawn()%0A%0A    # We don't need to monitor the memory for this test.%0A    microvm.memory_events_queue = None%0A%0A    microvm.basic_config(vcpu_count=2)%0A%0A    # Configure a network interface.%0A    _tap, _, _ = microvm.ssh_network_config(network_config, '1')%0A%0A    microvm.start()%0A    firecracker_pid = int(microvm.jailer_clone_pid)%0A%0A    # Open a SSH connection to validate the microVM stays alive.%0A    ssh_connection = net_tools.SSHConnection(microvm.ssh_config)%0A    # Just validate a simple command: %60nproc%60%0A    cmd = %22nproc%22%0A    _, stdout, stderr = ssh_connection.execute_command(cmd)%0A    assert stderr.read().decode(%22utf-8%22) == %22%22%0A    assert int(stdout.read().decode(%22utf-8%22)) == 2%0A%0A    # We have a handler installed for this signal.%0A    os.kill(firecracker_pid, SIGRTMIN+1)%0A%0A    # Validate the microVM is still up and running.%0A    _, stdout, stderr = ssh_connection.execute_command(cmd)%0A    assert stderr.read().decode(%22utf-8%22) == %22%22%0A    assert int(stdout.read().decode(%22utf-8%22)) == 2%0A

add integration test for graceful signal handling