1: -module(mongoose_deprecations_SUITE).
    2: 
    3: -include_lib("eunit/include/eunit.hrl").
    4: -include_lib("common_test/include/ct.hrl").
    5: 
    6: -compile([export_all, nowarn_export_all]).
    7: 
    8: -define(TEST_COOLDOWN, 50).    % ms
    9: -define(COOLDOWN_EPS, 3).      % ms, must be much smaller than TEST_COOLDOWN
   10: -define(LOG_MSG, #{what => cool_deprecated}).
   11: 
   12: all() ->
   13:     [
   14:         check_too_fast_pace,
   15:         check_ok_pace,
   16:         check_changing_pace,
   17:         different_tags_get_logged_always,
   18:         specified_lvl_logged_default_stays,
   19:         default_lvl_is_error
   20:     ].
   21: 
   22: init_per_suite(C) ->
   23:     C.
   24: 
   25: end_per_suite(C) ->
   26:     C.
   27: 
   28: init_per_testcase(_, C) ->
   29:     mock_log_with_lvl(self()),
   30:     mongoose_deprecations:start(),
   31:     C.
   32: 
   33: end_per_testcase(_, C) ->
   34:     mongoose_deprecations:stop(),
   35:     meck:unload(),
   36:     C.
   37: 
   38: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   39: %% Test cases
   40: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   41: 
   42: check_too_fast_pace(Config) ->
   43:     mongoose_deprecations:log(some_tag, ?LOG_MSG, [{cooldown, ?TEST_COOLDOWN}]),
   44:     mongoose_deprecations:log(some_tag, ?LOG_MSG, [{cooldown, ?TEST_COOLDOWN}]),
   45:     mongoose_deprecations:log(some_tag, ?LOG_MSG, [{cooldown, ?TEST_COOLDOWN}]),
   46:     {ok, _} = assert_n_logged(1),
   47:     ok.
   48: 
   49: check_ok_pace(_Config) ->
   50:     mongoose_deprecations:log(some_tag, ?LOG_MSG, [{cooldown, ?TEST_COOLDOWN}]),
   51:     timer:sleep(?TEST_COOLDOWN + ?COOLDOWN_EPS),
   52:     mongoose_deprecations:log(some_tag, ?LOG_MSG, [{cooldown, ?TEST_COOLDOWN}]),
   53:     timer:sleep(?TEST_COOLDOWN + ?COOLDOWN_EPS),
   54:     mongoose_deprecations:log(some_tag, ?LOG_MSG, [{cooldown, ?TEST_COOLDOWN}]),
   55:     {ok, _} = assert_n_logged(3),
   56:     ok.
   57: 
   58: check_changing_pace(_Config) ->
   59:     mongoose_deprecations:log(some_tag, ?LOG_MSG, [{cooldown, ?TEST_COOLDOWN}]),
   60:     timer:sleep(?TEST_COOLDOWN + ?COOLDOWN_EPS),
   61:     mongoose_deprecations:log(some_tag, ?LOG_MSG, [{cooldown, ?TEST_COOLDOWN}]),
   62:     mongoose_deprecations:log(some_tag, ?LOG_MSG, [{cooldown, ?TEST_COOLDOWN}]),
   63:     mongoose_deprecations:log(some_tag, ?LOG_MSG, [{cooldown, ?TEST_COOLDOWN}]),
   64:     timer:sleep(?TEST_COOLDOWN + ?COOLDOWN_EPS),
   65:     mongoose_deprecations:log(some_tag, ?LOG_MSG, [{cooldown, ?TEST_COOLDOWN}]),
   66:     {ok, _} = assert_n_logged(3),
   67:     ok.
   68: 
   69: %% Even the same message can be logged with any frequency when tags
   70: %% are different
   71: different_tags_get_logged_always(_Config) ->
   72:     mongoose_deprecations:log(some_tag, ?LOG_MSG, [{cooldown, ?TEST_COOLDOWN}]),
   73:     mongoose_deprecations:log(some_tag1, ?LOG_MSG, [{cooldown, ?TEST_COOLDOWN}]),
   74:     mongoose_deprecations:log(some_tag2, ?LOG_MSG, [{cooldown, ?TEST_COOLDOWN}]),
   75:     {ok, _} = assert_n_logged(3),
   76:     ok.
   77: 
   78: default_lvl_is_error(_Config) ->
   79:     mongoose_deprecations:log(some_tag, ?LOG_MSG, [{cooldown, ?TEST_COOLDOWN}]),
   80:     timer:sleep(?TEST_COOLDOWN + ?COOLDOWN_EPS),
   81:     mongoose_deprecations:log(some_tag, ?LOG_MSG, [{cooldown, ?TEST_COOLDOWN}]),
   82:     timer:sleep(?TEST_COOLDOWN + ?COOLDOWN_EPS),
   83:     mongoose_deprecations:log(some_tag, ?LOG_MSG, [{cooldown, ?TEST_COOLDOWN}]),
   84:     {ok, [error, error, error]} = assert_n_logged(3),
   85:     ok.
   86: 
   87: % One can specify the level error on warning. It does not affect the default
   88: % level.
   89: specified_lvl_logged_default_stays(_Config) ->
   90:     mongoose_deprecations:log(some_tag, ?LOG_MSG, 
   91:                               [{cooldown, ?TEST_COOLDOWN},
   92:                                {log_level, warning}]),
   93:     timer:sleep(?TEST_COOLDOWN + ?COOLDOWN_EPS),
   94:     mongoose_deprecations:log(some_tag, ?LOG_MSG, [{cooldown, ?TEST_COOLDOWN}]),
   95:     timer:sleep(?TEST_COOLDOWN + ?COOLDOWN_EPS),
   96:     mongoose_deprecations:log(some_tag, ?LOG_MSG, 
   97:                               [{cooldown, ?TEST_COOLDOWN},
   98:                                {log_level, warning}]),
   99:     timer:sleep(?TEST_COOLDOWN + ?COOLDOWN_EPS),
  100:     mongoose_deprecations:log(some_tag, ?LOG_MSG, [{cooldown, ?TEST_COOLDOWN}]),
  101:     {ok, [warning, error, warning, error]} = assert_n_logged(4),
  102:     ok.
  103: 
  104: 
  105: 
  106: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  107: %% Helpers
  108: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  109: 
  110: % Returns {ok, Lvls} where Lvls is the list
  111: % of log levels used for each message. In order
  112: % of appearing.
  113: assert_n_logged(N) ->
  114:     do_assert_n_logged(N, []).
  115: 
  116: do_assert_n_logged(0, LvlsAcc) ->
  117:     receive
  118:         {logged, {Msg, Lvl}} ->
  119:             ct:fail(too_many_logged)
  120:     after ?TEST_COOLDOWN * 2 ->
  121:               {ok, lists:reverse(LvlsAcc)}
  122:     end;
  123: do_assert_n_logged(N, LvlsAcc) ->
  124:     receive
  125:         {logged, {Msg, Lvl}} ->
  126:             do_assert_n_logged(N - 1, [Lvl | LvlsAcc])
  127:     after ?TEST_COOLDOWN * 2 ->
  128:               ct:fail(too_little_logged)
  129:     end.
  130: 
  131: mock_log_with_lvl(Pid) ->
  132:     meck:new(mongoose_deprecations, [passthrough]),
  133:     meck:expect(mongoose_deprecations, log_with_lvl, fun(Msg, Lvl) ->
  134:                                     Pid ! {logged, {Msg, Lvl}},
  135:                                     ok end).