rabbitmq-server/deps/rabbit/test/signal_handling_SUITE.erl

161 lines
5.0 KiB
Erlang

%% This Source Code Form is subject to the terms of the Mozilla Public
%% License, v. 2.0. If a copy of the MPL was not distributed with this
%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
%%
%% Copyright (c) 2020-2021 VMware, Inc. or its affiliates. All rights reserved.
%%
-module(signal_handling_SUITE).
-include_lib("common_test/include/ct.hrl").
-include_lib("eunit/include/eunit.hrl").
-export([suite/0,
all/0,
groups/0,
init_per_suite/1,
end_per_suite/1,
init_per_group/2,
end_per_group/2,
init_per_testcase/2,
end_per_testcase/2,
send_sighup/1,
send_sigterm/1,
send_sigtstp/1
]).
suite() ->
[{timetrap, {minutes, 5}}].
all() ->
[
{group, signal_sent_to_pid_in_pidfile},
{group, signal_sent_to_pid_from_os_getpid}
].
groups() ->
Signals = [sighup,
sigterm,
sigtstp],
Tests = [list_to_existing_atom(rabbit_misc:format("send_~s", [Signal]))
|| Signal <- Signals],
[
{signal_sent_to_pid_in_pidfile, [], Tests},
{signal_sent_to_pid_from_os_getpid, [], Tests}
].
%% -------------------------------------------------------------------
%% Testsuite setup/teardown.
%% -------------------------------------------------------------------
init_per_suite(Config) ->
case os:type() of
{unix, _} ->
rabbit_ct_helpers:log_environment(),
rabbit_ct_helpers:run_setup_steps(Config);
_ ->
{skip, "This testsuite is only relevant on Unix"}
end.
end_per_suite(Config) ->
rabbit_ct_helpers:run_teardown_steps(Config).
init_per_group(_, Config) ->
Config.
end_per_group(_, Config) ->
Config.
init_per_testcase(Testcase, Config) ->
rabbit_ct_helpers:testcase_started(Config, Testcase),
ClusterSize = 1,
TestNumber = rabbit_ct_helpers:testcase_number(Config, ?MODULE, Testcase),
Config1 = rabbit_ct_helpers:set_config(
Config,
[
{rmq_nodename_suffix, Testcase},
{tcp_ports_base, {skip_n_nodes, TestNumber * ClusterSize}}
]),
rabbit_ct_helpers:run_steps(Config1,
rabbit_ct_broker_helpers:setup_steps() ++
rabbit_ct_client_helpers:setup_steps()).
end_per_testcase(Testcase, Config) ->
Config1 = rabbit_ct_helpers:run_steps(Config,
rabbit_ct_client_helpers:teardown_steps() ++
rabbit_ct_broker_helpers:teardown_steps()),
rabbit_ct_helpers:testcase_finished(Config1, Testcase).
%% -------------------------------------------------------------------
%% Testcases.
%% -------------------------------------------------------------------
send_sighup(Config) ->
{PidFile, Pid} = get_pidfile_and_pid(Config),
%% A SIGHUP signal should be ignored and the node should still be
%% running.
send_signal(Pid, "HUP"),
timer:sleep(10000),
A = rabbit_ct_broker_helpers:get_node_config(Config, 0, nodename),
?assert(rabbit_ct_broker_helpers:rpc(Config, A, rabbit, is_running, [])),
?assert(filelib:is_regular(PidFile)).
send_sigterm(Config) ->
{PidFile, Pid} = get_pidfile_and_pid(Config),
%% After sending a SIGTERM to the process, we expect the node to
%% exit.
send_signal(Pid, "TERM"),
wait_for_node_exit(Pid),
%% After a clean exit, the PID file should be removed.
?assertNot(filelib:is_regular(PidFile)).
send_sigtstp(Config) ->
{PidFile, Pid} = get_pidfile_and_pid(Config),
%% A SIGHUP signal should be ignored and the node should still be
%% running.
send_signal(Pid, "TSTP"),
timer:sleep(10000),
A = rabbit_ct_broker_helpers:get_node_config(Config, 0, nodename),
?assert(rabbit_ct_broker_helpers:rpc(Config, A, rabbit, is_running, [])),
?assert(filelib:is_regular(PidFile)).
get_pidfile_and_pid(Config) ->
PidFile = rabbit_ct_broker_helpers:get_node_config(Config, 0, pid_file),
?assert(filelib:is_regular(PidFile)),
%% We send the signal to either the process referenced in the
%% PID file or the Erlang VM process. Up-to 3.8.x, they can be
%% the different process because the PID file may reference the
%% rabbitmq-server(8) script wrapper.
[{name, Group} | _] = ?config(tc_group_properties, Config),
Pid = case Group of
signal_sent_to_pid_in_pidfile ->
{ok, P} = file:read_file(PidFile),
string:trim(P, trailing, [$\r,$\n]);
signal_sent_to_pid_from_os_getpid ->
A = rabbit_ct_broker_helpers:get_node_config(
Config, 0, nodename),
rabbit_ct_broker_helpers:rpc(Config, A, os, getpid, [])
end,
{PidFile, Pid}.
send_signal(Pid, Signal) ->
Cmd = ["kill",
"-" ++ Signal,
Pid],
?assertMatch({ok, _}, rabbit_ct_helpers:exec(Cmd)).
wait_for_node_exit(Pid) ->
case rabbit_misc:is_os_process_alive(Pid) of
true ->
timer:sleep(1000),
wait_for_node_exit(Pid);
false ->
ok
end.