在 Common Test 未通过的情况下杀死 gen_server

Killing a gen_server without failing the Common Test

我实现了一个故意崩溃的模块(以测试另一个正在监视它的模块的功能)。问题是,当这个 gen_server 崩溃时,它也会导致对它的通用测试失败。我试过使用 try/catch 并设置 process_flag(trap_exit, true) 但似乎没有任何效果。

这里是一些相关的代码:

-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;

% ...

和普通测试:

% ...

-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).

% ...

以及 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.

关于如何在不通过通用测试的情况下获得此功能的任何想法?

问题是我的 try/catch 尝试没有与实际错误进行模式匹配。这是修复:

-module(mod_bad_process).

% ...

kill() ->
    try gen_server:call(?MODULE, {update_behavior, kill}) of 
        _ -> error(failed_to_kill)
    catch
        exit:{killed, _} -> ok
    end.
% ...