1: -module(amp_resolver_SUITE).
    2: %% @doc Tests for resoloving server-side amp_strategy()
    3: %%      with amp_condition()/valu() pairs.
    4: %% @reference <a href="http://xmpp.org/extensions/xep-0079.html">XEP-0079</a>
    5: %% @author <mongooseim@erlang-solutions.com>
    6: %% @copyright 2014 Erlang Solutions, Ltd.
    7: %% This work was sponsored by Grindr LLC
    8: 
    9: -compile([export_all, nowarn_export_all]).
   10: 
   11: -include("amp.hrl").
   12: -include_lib("exml/include/exml.hrl").
   13: -include_lib("common_test/include/ct.hrl").
   14: -include_lib("eunit/include/eunit.hrl").
   15: 
   16: -define(ae(Expected, Actual), ?assertEqual(Expected, Actual)).
   17: 
   18: all() ->
   19:     [{group, resolver}].
   20: 
   21: groups() ->
   22:     [{resolver, [parallel],
   23:       [deliver_notify_match_test,
   24:        deliver_notify_undecided_test,
   25:        deliver_notify_no_match_test,
   26:        deliver_error_drop_match_test,
   27:        deliver_error_drop_no_match_test,
   28:        match_resource_match_test,
   29:        match_resource_no_match_test,
   30:        fold_on_match_test]
   31:      }].
   32: 
   33: %% Test cases
   34: 
   35: deliver_notify_match_test(_) ->
   36:     [?ae(match, check_cond(#amp_strategy{deliver = [D]},
   37:                            #amp_rule{condition = deliver, value = D, action = notify})) ||
   38:         D <- rule_deliver_values()],
   39:     ok.
   40: 
   41: deliver_notify_undecided_test(_) ->
   42:     [?ae(undecided, check_cond(#amp_strategy{deliver = Ds},
   43:                                #amp_rule{condition = deliver, value = Dr, action = notify})) ||
   44:         Ds <- strategy_deliver_multiple_values(),
   45:         Dr <- Ds],
   46:     ok.
   47: 
   48: deliver_notify_no_match_test(_) ->
   49:     [?ae(no_match, check_cond(#amp_strategy{deliver = Ds},
   50:                               #amp_rule{condition = deliver, value = Dr, action = notify})) ||
   51:         Ds <- strategy_deliver_values(),
   52:         Dr <- rule_deliver_values(),
   53:         Ds == undefined orelse not lists:member(Dr, Ds)],
   54:     ok.
   55: 
   56: deliver_error_drop_match_test(_) ->
   57:     [?ae(match, check_cond(#amp_strategy{deliver = Ds},
   58:                            #amp_rule{condition = deliver, value = Dr, action = A})) ||
   59:         Ds <- strategy_deliver_values(),
   60:         Dr <- rule_deliver_values(),
   61:         hd(Ds) == Dr,
   62:         A <- [error, drop]],
   63:     ok.
   64: 
   65: deliver_error_drop_no_match_test(_) ->
   66:     [?ae(no_match, check_cond(#amp_strategy{deliver = Ds},
   67:                               #amp_rule{condition = deliver, value = Dr, action = A})) ||
   68:         Ds <- strategy_deliver_values(),
   69:         Dr <- rule_deliver_values(),
   70:         hd(Ds) /= Dr,
   71:         Ds == undefined orelse Dr == none orelse not lists:member(Dr, Ds),
   72:         A <- [error, drop]],
   73:     ok.
   74: 
   75: match_resource_match_test(_) ->
   76:     [?ae(match, check_cond(#amp_strategy{'match-resource' = Ms},
   77:                            #amp_rule{condition = 'match-resource', value = Mr, action = A})) ||
   78:         Ms <- strategy_match_resource_values(),
   79:         Mr <- rule_match_resource_values(),
   80:         Ms /= undefined,
   81:         Mr == any orelse Mr == Ms,
   82:         A <- rule_actions()],
   83:     ok.
   84: 
   85: match_resource_no_match_test(_) ->
   86:     [?ae(no_match, check_cond(#amp_strategy{'match-resource' = Ms},
   87:                               #amp_rule{condition = 'match-resource', value = Mr, action = A})) ||
   88:         Ms <- strategy_match_resource_values(),
   89:         Mr <- rule_match_resource_values(),
   90:         Ms == undefined orelse (Mr /= any andalso Mr /= Ms),
   91:         A <- rule_actions()],
   92:     ok.
   93: 
   94: fold_on_match_test(_) ->
   95:     [?ae(Acc, check_cond(Acc,
   96:                         #amp_strategy{},
   97:                         #amp_rule{condition = 'match-resource', value = any, action = notify})) ||
   98:         Acc <- [match, undecided]],
   99:     ok.
  100: 
  101: %% Helpers
  102: 
  103: strategy_deliver_values() -> [undefined | strategy_deliver_single_values() ++
  104:                                   strategy_deliver_multiple_values()].
  105: strategy_deliver_single_values() -> [[none], [stored], [direct]].
  106: strategy_deliver_multiple_values() -> [[direct, stored], [direct, none]].
  107: strategy_match_resource_values() -> [undefined, other, exact].
  108: 
  109: rule_actions() -> [notify, error, drop].
  110: rule_deliver_values() -> [none, stored, direct].
  111: rule_match_resource_values() -> [exact, other, any].
  112: 
  113: check_cond(Strategy, Rule) ->
  114:     check_cond(no_match, Strategy, Rule).
  115: 
  116: check_cond(HookAcc, Strategy, Rule) ->
  117:     ct:log("check condition (acc: ~p)~nstrategy: ~p~nrule: ~p", [HookAcc, Strategy, Rule]),
  118:     {ok, Result} = amp_resolver:check_condition(HookAcc, #{strategy => Strategy, rule =>Rule}, #{}),
  119:     Result.