# Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.

# Path to the temporary configuration file.
CFG_FILE=@abs_top_builddir@/src/bin/dhcp6/tests/test_config.json
# Path to the Kea log file.
LOG_FILE=@abs_top_builddir@/src/bin/dhcp6/tests/test.log
# Kea configuration to be stored in the configuration file.
CONFIG="{
    \"Dhcp6\":
    {
        \"interfaces\": [ ],
        \"preferred-lifetime\": 3000,
        \"valid-lifetime\": 4000,
        \"renew-timer\": 1000,
        \"rebind-timer\": 2000,
        \"lease-database\":
        {
            \"type\": \"memfile\",
            \"persist\": false
        },
        \"subnet6\": [
        {
            \"subnet\": \"2001:db8:1::/64\",
            \"pool\": [ \"2001:db8:1::10-2001:db8:1::100\" ]
        } ]
    }
}"
# Invalid configuration (negative preferred-lifetime) to check that Kea
# gracefully handles reconfiguration errors.
CONFIG_INVALID="{
    \"Dhcp6\":
    {
        \"interfaces\": [ ],
        \"preferred-lifetime\": -3,
        \"valid-lifetime\": 4000,
        \"renew-timer\": 1000,
        \"rebind-timer\": 2000,
        \"lease-database\":
        {
            \"type\": \"memfile\",
            \"persist\": false
        },
        \"subnet6\": [
        {
            \"subnet\": \"2001:db8:1::/64\",
            \"pool\": [ \"2001:db8:1::10-2001:db8:1::100\" ]
        } ]
    }
}"

# Set the location of the executable.
bin="kea-dhcp6"
bin_path=@abs_top_builddir@/src/bin/dhcp6

# Import common test library.
. @abs_top_builddir@/src/lib/testutils/dhcp_test_lib.sh

# This test verifies that DHCPv6 can be reconfigured with a SIGHUP signal.
dynamic_reconfiguration_test() {
    # Log the start of the test and print test name.
    test_start "dhcpv6_srv.dynamic_reconfiguration"
    # Remove dangling Kea instances and remove log files.
    cleanup
    # Create new configuration file.
    create_config "${CONFIG}"
    # Instruct Kea to log to the specific file.
    set_logger
    # Start Kea.
    start_kea ${bin_path}/${bin}
    # Wait up to 20s for Kea to start.
    wait_for_kea 20
    if [ ${_WAIT_FOR_KEA} -eq 0 ]; then
        printf "ERROR: timeout waiting for Kea to start.\n"
        clean_exit 1
    fi

    # Check if it is still running. It could have terminated (e.g. as a result
    # of configuration failure).
    get_pids ${bin}
    if [ ${_GET_PIDS_NUM} -ne 1 ]; then
        printf "ERROR: expected one Kea process to be started. Found %d processes\
 started.\n" ${_GET_PIDS_NUM}
        clean_exit 1
    fi

    # Check in the log file, how many times server has been configured. It should
    # be just once on startup.
    get_reconfigs
    if [ ${_GET_RECONFIGS} -ne 1 ]; then
        printf "ERROR: server hasn't been configured.\n"
        clean_exit 1
    else
        printf "Server successfully configured.\n"
    fi

    # Now use invalid configuration.
    create_config "${CONFIG_INVALID}"

    # Try to reconfigure by sending SIGHUP
    send_signal 1 ${bin}

    # The configuration should fail and the error message should be there.
    wait_for_message 10 "DHCP6_CONFIG_LOAD_FAIL" 1

    # After receiving SIGHUP the server should try to reconfigure itself.
    # The configuration provided is invalid so it should result in
    # reconfiguration failure but the server should still be running.
    get_reconfigs
    if [ ${_GET_RECONFIGS} -ne 1 ]; then
        printf "ERROR: server has been reconfigured despite bogus configuration.\n"
        clean_exit 1
    elif [ ${_GET_RECONFIG_ERRORS} -ne 1 ]; then
        printf "ERROR: server did not report reconfiguration error despite attempt\
 to configure it with invalid configuration.\n"
        clean_exit 1
    fi

    # Make sure the server is still operational.
    get_pids ${bin}
    if [ ${_GET_PIDS_NUM} -ne 1 ]; then
        printf "ERROR: Kea process was killed when attempting reconfiguration.\n"
        clean_exit 1
    fi

    # Restore the good configuration.
    create_config "${CONFIG}"

    # Reconfigure the server with SIGHUP.
    send_signal 1 ${bin}

    # There should be two occurrences of the DHCP6_CONFIG_COMPLETE messages.
    # Wait for it up to 10s.
    wait_for_message 10 "DHCP6_CONFIG_COMPLETE" 2

    # After receiving SIGHUP the server should get reconfigured and the
    # reconfiguration should be noted in the log file. We should now
    # have two configurations logged in the log file.
    if [ ${_WAIT_FOR_MESSAGE} -eq 0 ]; then
        printf "ERROR: server hasn't been reconfigured.\n"
        clean_exit 1
    else
        printf "Server successfully reconfigured.\n"
    fi

    # Make sure the server is still operational.
    get_pids ${bin}
    if [ ${_GET_PIDS_NUM} -ne 1 ]; then
        printf "ERROR: Kea process was killed when attempting reconfiguration.\n"
        clean_exit 1
    fi

    # All ok. Shut down Kea and exit.
    test_finish 0
}

# This test verifies that DHCPv6 server is shut down gracefully when it
# receives a SIGINT or SIGTERM signal.
shutdown_test() {
    test_name=${1}  # Test name
    signum=${2}      # Signal number

    # Log the start of the test and print test name.
    test_start ${test_name}
    # Remove dangling Kea instances and remove log files.
    cleanup
    # Create new configuration file.
    create_config "${CONFIG}"
    # Instruct Kea to log to the specific file.
    set_logger
    # Start Kea.
    start_kea ${bin_path}/${bin}
    # Wait up to 20s for Kea to start.
    wait_for_kea 20
    if [ ${_WAIT_FOR_KEA} -eq 0 ]; then
        printf "ERROR: timeout waiting for Kea to start.\n"
        clean_exit 1
    fi

    # Check if it is still running. It could have terminated (e.g. as a result
    # of configuration failure).
    get_pids ${bin}
    if [ ${_GET_PIDS_NUM} -ne 1 ]; then
        printf "ERROR: expected one Kea process to be started. Found %d processes\
 started.\n" ${_GET_PIDS_NUM}
        clean_exit 1
    fi

    # Check in the log file, how many times server has been configured. It should
    # be just once on startup.
    get_reconfigs
    if [ ${_GET_RECONFIGS} -ne 1 ]; then
        printf "ERROR: server hasn't been configured.\n"
        clean_exit 1
    else
        printf "Server successfully configured.\n"
    fi

    # Send signal to Kea (SIGTERM, SIGINT etc.)
    send_signal ${signum} ${bin}

    # Wait up to 10s for the server's graceful shutdown. The graceful shut down
    # should be recorded in the log file with the appropriate message.
    wait_for_message 10 "DHCP6_SHUTDOWN" 1
    if [ ${_WAIT_FOR_MESSAGE} -eq 0 ]; then
        printf "ERROR: Server did not record shutdown in the log.\n"
        clean_exit 1
    fi

    # Make sure the server is down.
    wait_for_server_down 5 ${bin}
    assert_eq 1 ${_WAIT_FOR_SERVER_DOWN} \
        "Expected wait_for_server_down return %d, returned %d"

    test_finish 0
}

dynamic_reconfiguration_test
shutdown_test "dhcpv4.sigterm_test" 15
shutdown_test "dhcpv4.sigint_test" 2
