I implemented a module which is purposefully supposed to crash (to test the functionality of another module, which is monitoring it). The problem is, when this gen_server crashes it also causes the common test for it to fail. I've tried using try/catch and setting process_flag(trap_exit, true)
but nothing seems to work.
Here is some relevant code:
-module(mod_bad_process).
% ...
%% ct calls this function directly
kill() ->
gen_server:call(?MODULE, {update_behavior, kill}).
% ...
handle_cast({update_behavior, Behavior}, _From, State) ->
case Behavior of
kill -> {stop, killed, State};
_ -> {reply, ok, State#{state := Behavior}}
end;
% ...
And the common test:
% ...
-define(BAD_PROC, mod_bad_process).
% ...
remonitor_test(_Conf) ->
InitialPid = whereis(?BAD_PROC),
true = undefined =/= InitialPid,
true = is_monitored_gen_server(?BAD_PROC),
mod_bad_process:kill(), % gen_server crashes
timer:sleep(?REMONITOR_DELAY_MS),
FinalPid = whereis(?BAD_PROC),
true = InitialPid =/= FinalPid,
true = undefined =/= FinalPid,
true = is_monitored_gen_server(?BAD_PROC).
% ...
And the resulting error from ct:
*** CT Error Notification 2021-07-16 16:08:20.791 ***
gen_server:call failed on line 238
Reason: {killed,{gen_server,call,...}}
=== Ended at 2021-07-16 16:08:20
=== Location: [{gen_server,call,238},
{mod_bad_process,kill,48},
{monitor_tests,remonitor_test,62},
{test_server,ts_tc,1784},
{test_server,run_test_case_eval1,1293},
{test_server,run_test_case_eval,1225}]
=== === Reason: {killed,{gen_server,call,
[mod_bad_process_global,
{update_behavior,kill}]}}
===
*** monitor_remonitor_test failed.
Skipping all other cases in sequence.
Any ideas on how to get this functionality without failing the common test?
The problem was that my try/catch attempts were not pattern matching to the actual error. Here is the fix:
-module(mod_bad_process).
% ...
kill() ->
try gen_server:call(?MODULE, {update_behavior, kill}) of
_ -> error(failed_to_kill)
catch
exit:{killed, _} -> ok
end.
% ...