使用 Common Test 测试 gen_server 模块

Testing a gen_server module using Common Test

我有这个(非常简单)gen_server实现:

-module(rand_gen).

-behaviour(gen_server).

-define(BASE, 1000).

%% Module Functionality
-export([start/0]).
-export([stop/1]).
-export([uniform/1, uniform/2]).

%% Callback Functions
-export([code_change/3]).
-export([init/1]).
-export([handle_call/3]).
-export([handle_cast/2]).
-export([handle_info/2]).
-export([terminate/2]).

%%%=======================================================================
%%% Export
%%%=======================================================================

-spec start() -> {ok, pid()} | {error, Reason :: term()}.
start() ->
  gen_server:start(?MODULE, [], []).

-spec stop(Pid) -> ok when Pid :: pid().
stop(Pid) ->
  gen_server:stop(Pid).

-spec uniform(Pid, Max) -> number() when Pid :: pid(), Max :: non_neg_integer().
uniform(Pid, Max) ->
  gen_server:call(Pid, {uniform, #{max => Max}}).

-spec uniform(Pid) -> number() when Pid :: pid().
uniform(Pid) ->
  gen_server:call(Pid, uniform).

%%%=======================================================================
%%% Callback Functions
%%%=======================================================================

code_change(_OldVsn, State, _Extra) ->
  {ok, State}.

handle_call({uniform, Input = #{max := Max}}, _From, _State) ->
  {reply, rand:uniform(Max), Input};
handle_call(uniform, _From, State = #{max := Max}) ->
  {reply, rand:uniform(Max), State};
handle_call(Msg, From, State) ->
  io:format("Unexpected call [~p] from [~p]~n", [Msg, From]),
  {reply, {error, no_call, Msg}, State}.

handle_cast(Msg, State) ->
  io:format("Unexpected cast [~p]~n", [Msg]),
  {noreply, State}.

handle_info(Msg, State) ->
  io:format("Unexpected message ~p~n", [Msg]),
  {noreply, State}.

init([]) ->
  io:format("Crypto strong seed initialized! Using [~p] as base value.~n", [?BASE]),
  <<I1:32/unsigned-integer, I2:32/unsigned-integer, I3:32/unsigned-integer>> = crypto:strong_rand_bytes(?BASE),
  _ = rand:seed(exsplus, {I1, I2, I3}),
  {ok, #{max => ?BASE}}.

terminate(_Reason, _StateData) ->
  ok.

%%%=======================================================================
%%% Internal
%%%=======================================================================

现在我想写一个 Common Test 套件来测试它 ‒ 我刚开始学习这个。

-module(rand_gen_SUITE).

-include_lib("common_test/include/ct.hrl").

-compile(export_all).

%%%=======================================================================
%%% Setup
%%%=======================================================================

all() ->
  [
    {group, generate}
  ].

groups() ->
  [
    {generate,
      %%[parallel, {repeat, 3}],
      [uniform]
    }
  ].

init_per_suite(Config) ->
  {ok, Pid} = rand_gen:start(),
  [{pid, Pid} | Config].

end_per_suite(_Config) ->
  ok.

%%%=======================================================================
%%% Test Cases
%%%=======================================================================

uniform(Config) ->
  Pid = ?config(pid, Config),
  true = is_number(rand_gen:uniform(Pid)).

...但每次我 运行 (超小)suite/file 我都会收到一条奇怪的消息说:

===> Running Common Test suites...
%%% rand_gen_SUITE ==> init_per_suite: FAILED
%%% rand_gen_SUITE ==> {{badmatch,<<3,217,51,126,122,17,213,209,222,82,29,106,213,128,218,98,129,12,
             123,22,27,194,123,120,74,110,1,254,132,243,147,87,181,74,43,159,
             163,94,58,224,18,40,46,190,134,198,43,225,57,81,109,216,64,245,
             103,131,46,47,234,165,210,2,78,97,52,44,131,49,0,94,168,207,176,
             214,38,69,235,105,116,240,92,37,112,17,16,47,86,0,179,4,167,61,
             61,167,88,84,227,247,74,132,86,64,33,92,175,51,130,242,155,174,
             167,126,142,100,123,35,77,159,198,113,105,182,43,61,130,173,169,
             155,135,0,6,19,90,65,139,70,236,217,253,76,223,86,228,175,145,
             198,89,40,251,158,6,193,177,66,202,199,110,39,130,232,28,37,176,
             215,45,251,65,220,229,124,204,99,126,132,119,41,83,226,235,117,
             152,69,179,211,10,97,194,128,147,134,26,240,175,218,188,204,82,
             55,34,35,49,195,183,78,150,125,137,141,76,92,253,1,46,203,37,142,
             224,236,8,252,94,129,89,108,84,133,88,213,56,127,255,48,172,26,
             246,51,29,79,56,33,59,122,135,80,137,63,37,124,168,90,76,46,12,
             155,241,182,16,218,147,227,16,110,9,51,213,74,216,18,51,219,12,
             111,229,159,231,33,12,87,114,134,113,79,147,35,122,227,114,154,
             52,164,223,95,66,162,136,231,174,47,93,10,66,62,63,76,196,232,
             100,240,49,16,122,81,200,222,66,180,212,16,185,117,31,111,152,
             216,10,125,212,138,203,219,31,67,94,170,181,160,225,189,182,10,
             110,207,197,177,198,199,83,227,121,235,12,186,90,212,160,102,187,
             99,61,127,123,255,76,36,63,190,197,175,167,175,132,230,187,162,
             68,183,220,9,198,29,18,191,199,182,10,227,139,38,25,113,153,199,
             80,244,13,55,62,153,250,165,218,137,211,210,129,123,35,67,226,20,
             153,85,25,193,46,53,40,49,134,67,92,198,106,151,195,242,46,153,
             223,187,163,100,205,108,253,191,192,220,65,101,15,32,161,41,25,
             148,203,153,134,55,33,88,107,222,49,120,44,173,167,82,238,185,
             213,107,164,45,64,28,180,253,34,131,92,49,112,202,188,1,36,59,81,
             223,0,200,93,34,253,3,214,240,211,51,135,43,70,105,98,125,186,
             131,129,85,246,147,167,238,32,176,54,92,250,200,73,63,246,72,159,
             64,105,119,246,58,5,153,54,126,4,33,82,153,245,79,163,187,61,45,
             172,173,30,45,148,252,230,74,80,213,132,45,52,202,101,234,98,30,
             68,18,117,175,231,41,153,243,243,132,184,98,234,72,134,140,229,
             239,205,136,228,223,52,189,118,250,195,178,126,33,56,142,247,242,
             235,160,129,75,221,73,21,148,139,110,194,87,127,147,9,71,25,111,
             218,6,206,38,3,208,154,128,236,127,96,155,223,25,164,139,80,170,
             82,230,130,118,88,198,254,109,249,252,146,143,6,108,134,49,29,
             152,215,67,74,96,240,109,6,97,36,145,250,234,48,145,17,144,217,
             198,236,60,68,213,30,7,120,228,117,41,231,72,208,245,73,153,251,
             64,195,16,201,250,12,143,23,138,23,215,74,5,180,228,133,236,61,
             227,123,188,100,81,77,254,187,69,213,127,22,38,143,84,184,4,47,
             47,124,245,230,221,105,105,36,220,28,52,200,195,104,7,78,155,250,
             36,8,42,228,166,212,106,147,247,101,21,230,78,236,91,217,115,84,
             76,125,193,18,136,103,85,104,33,102,7,235,250,197,139,238,187,
             154,12,84,152,174,133,92,165,72,76,45,70,90,115,32,161,156,251,
             197,103,70,141,168,220,223,251,252,14,249,172,40,122,53,69,137,
             45,29,129,144,146,238,181,104,28,117,166,19,238,44,162,174,117,
             250,21,62,155,39,149,221,207,48,168,19,35,209,53,188,31,122,99,
             83,74,138,164,103,72,106,27,175,239,240,3,100,118,152,180,225,82,
             227,60,108,66,223,165,173,183,46,166,23,85,236,141,238,166,160,
             114,31,7,14,23,220,90,226,79,217,203,240,126,128,241,41,149,224,
             148,130,86,130,244,12,27,237,123,234,0,68,164,165,250,235,87,243,
             217,253,215,249,13,206,155,197,138,192,249,154,104,131,109,229,
             126,77,216,127,254,55,170,192,100,90,49,30,78,209,249,140,184,81,
             121,164,178,50,204,131,144,214,8,12,130,32,164,149,92,200,235,
             145,48,162,244,238,114,47,251,31,79,242,186,111,117,207,16,178,
             212,234,209,161,143,21,241,111,218,32,255,191,70,177,203,5,117,
             182,148,199,231,93,118,76,72>>},
 [{rand_gen,init,1,
            [{file,"/home/x80486/Workshop/erlang/erlang_basics/_build/test/lib/erlang_basics/src/rand_gen.erl"},
             {line,74}]},
  {rand_gen_SUITE,init_per_suite,1,
                  [{file,"/home/x80486/Workshop/erlang/erlang_basics/_build/test/lib/erlang_basics/test/rand_gen_SUITE.erl"},
                   {line,34}]},
  {test_server,ts_tc,3,[{file,"test_server.erl"},{line,1546}]},
  {test_server,run_test_case_eval1,6,[{file,"test_server.erl"},{line,1147}]},
  {test_server,run_test_case_eval,9,[{file,"test_server.erl"},{line,994}]}]}

有什么线索吗?提前致谢!

那是因为 crypto:strong_rand_bytes(?BASE) 的结果与 <<I1:32/unsigned-integer, I2:32/unsigned-integer, I3:32/unsigned-integer>> 不匹配,因为它(正如您在错误中看到的那样)比那个长。

您可以尝试将代码中的该行更改为: <<I1:32/unsigned-integer, I2:32/unsigned-integer, I3:32/unsigned-integer, _/bitstring>> = crypto:strong_rand_bytes(?BASE),