1: -module(amp_SUITE).
    2: -compile([export_all, nowarn_export_all]).
    3: 
    4: %% @doc Tests for XEP-0079 <rule> -related functions
    5: -include("amp.hrl").
    6: -include_lib("exml/include/exml.hrl").
    7: 
    8: -include_lib("common_test/include/ct.hrl").
    9: -include_lib("proper/include/proper.hrl").
   10: -include_lib("eunit/include/eunit.hrl").
   11: 
   12: -import(prop_helper, [prop/2, readable_bitstring/0]).
   13: 
   14: -define(ae(Expected, Actual), ?assertEqual(Expected, Actual)).
   15: 
   16: all() ->
   17:     [{group, conversion},
   18:      {group, mutating},
   19:      {group, classification}
   20:     ].
   21: 
   22: groups() ->
   23:     [{conversion, [parallel],
   24:       [amp_binaries_to_rule_test,
   25:        valid_rules_property,
   26:        invalid_rules_property]},
   27:      {mutating, [parallel],
   28:       [strip_amp_el_test,
   29:        strip_amp_el_noop_test]},
   30:      {classification, [parallel],
   31:       [extract_non_amp_test,
   32:        extract_simple_request_test,
   33:        extract_complex_request_test,
   34:        extract_amp_response_test,
   35:        extract_amp_error_response_test,
   36:        extract_not_acceptable_rules_test,
   37:        extract_incomplete_amp_test]}
   38:     ].
   39: 
   40: amp_binaries_to_rule_test(_) ->
   41:     ?ae(#amp_rule{condition = 'deliver', value = 'none', action = 'notify'},
   42:         amp:binaries_to_rule(<<"deliver">>, <<"none">>, <<"notify">>)),
   43:     ?ae(#amp_rule{condition = 'match-resource', value = 'any', action = 'notify'},
   44:         amp:binaries_to_rule(<<"match-resource">>, <<"any">>, <<"notify">>)),
   45:     ?ae(#amp_rule{condition = 'expire-at', value = <<"2014-04-04T12:12:12Z">>, action = 'notify'},
   46:         amp:binaries_to_rule(<<"expire-at">>, <<"2014-04-04T12:12:12Z">>, <<"notify">>)),
   47:     ?ae(#amp_invalid_rule{condition = <<"Zeus">>, value = <<"Hades">>, action = <<"Poseidon">>},
   48:         amp:binaries_to_rule(<<"Zeus">>, <<"Hades">>, <<"Poseidon">>)).
   49: 
   50: valid_rules_property(_) ->
   51:     prop(valid_rules_property,
   52:              ?FORALL({C,V,A}, amp_gen:valid_cva_binaries(),
   53:                      is_valid_rule(amp:binaries_to_rule(C,V,A)))).
   54: 
   55: invalid_rules_property(_) ->
   56:     prop(invalid_rules_property,
   57:              ?FORALL({C,V,A}, amp_gen:invalid_cva_binaries(),
   58:                      not is_valid_rule(amp:binaries_to_rule(C,V,A)))).
   59: 
   60: extract_non_amp_test(_) ->
   61:     {ok, M} = exml:parse(<<"
   62: <message
   63:     from='bernardo@shakespeare.lit/pda'
   64:     to='francisco@shakespeare.lit'
   65:     type='chat'>
   66:   <body>Who's there?</body>
   67: </message>">>),
   68:     ?assertEqual(none,
   69:                  amp:extract_requested_rules(M)).
   70: 
   71: extract_simple_request_test(_) ->
   72:     {ok, M} = exml:parse(<<"
   73: <message
   74:     from='northumberland@shakespeare.lit'
   75:     id='richard2-4.1.247'
   76:     to='kingrichard@royalty.england.lit'>
   77:   <body>My lord, dispatch; read o'er these articles.</body>
   78:   <amp xmlns='http://jabber.org/protocol/amp'>
   79:     <rule condition='deliver' action='notify' value='direct'/>
   80:   </amp>
   81: </message> ">>),
   82:     ?assertEqual({rules, [#amp_rule{condition = 'deliver',
   83:                                     value     = 'direct',
   84:                                     action    = 'notify'}]},
   85:                   amp:extract_requested_rules(M)).
   86: 
   87: extract_complex_request_test(_) ->
   88:     {ok, M} = exml:parse(<<"
   89: <message to='francisco@hamlet.lit/pda'
   90:          from='bernardo@hamlet.lit/elsinore'
   91:          id='ibb1'>
   92:   <body>Hello, fellow human</body>
   93:   <amp xmlns='http://jabber.org/protocol/amp' per-hop='true'>
   94:     <rule action='notify' condition='deliver' value='direct'/>
   95:     <rule action='error' condition='deliver' value='none'/>
   96:     <rule action='notify' condition='deliver' value='forward'/>
   97:   </amp>
   98: </message>">>),
   99:     ?assertEqual({rules, [#amp_rule{condition = 'deliver',
  100:                                     value     = 'direct',
  101:                                     action    = 'notify'},
  102:                           #amp_rule{condition = 'deliver',
  103:                                     value     = 'none',
  104:                                     action    = 'error'},
  105:                           #amp_rule{condition = 'deliver',
  106:                                     value     = 'forward',
  107:                                     action    = 'notify'}
  108:                          ]},
  109:        amp:extract_requested_rules(M)).
  110: 
  111: extract_amp_response_test(_) ->
  112:     {ok, M} = exml:parse(<<"
  113:   <message from='hamlet.lit'
  114:            to='bernardo@hamlet.lit/elsinore'
  115:            id='chatty2'>
  116:     <amp xmlns='http://jabber.org/protocol/amp'
  117:          status='notify'
  118:          to='bernardo@hamlet.lit/elsinore'
  119:          from='francisco@hamlet.lit'>
  120:       <rule action='notify' condition='deliver' value='stored'/>
  121:     </amp>
  122:   </message>">>),
  123:     ?assertEqual(none,
  124:                  amp:extract_requested_rules(M)).
  125: 
  126: extract_amp_error_response_test(_) ->
  127:     {ok, M} = exml:parse(<<"
  128: <message
  129:     from='shakespeare.lit'
  130:     id='richard2-4.1.247'
  131:     to='northumberland@shakespeare.lit'
  132:     type='error'>
  133:   <amp xmlns='http://jabber.org/protocol/amp'>
  134:     <rule action='drop' condition='expire-at' value='2004-01-01T00:00:00Z'/>
  135:   </amp>
  136:   <error type='modify' code='400'>
  137:     <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  138:     <unsupported-actions xmlns='http://jabber.org/protocol/amp'>
  139:       <rule condition='expire-at'
  140:             action='drop'
  141:             value='2004-01-01T00:00:00Z'/>
  142:     </unsupported-actions>
  143:   </error>
  144: </message>">>),
  145:     ?assertEqual(none,
  146:                  amp:extract_requested_rules(M)).
  147: 
  148: 
  149: extract_not_acceptable_rules_test(_) ->
  150:     {ok, M} = exml:parse(<<"
  151: <message
  152:     from='northumberland@shakespeare.lit'
  153:     id='richard2-4.1.247'
  154:     to='kingrichard@royalty.england.lit'>
  155:   <body>My lord, dispatch; read o'er these articles.</body>
  156:   <amp xmlns='http://jabber.org/protocol/amp'>
  157:     <rule condition='hello' action='mike' value='!'/>
  158:   </amp>
  159: </message> ">>),
  160:     ?assertEqual({errors, [
  161:                            {'not-acceptable',
  162:                             #amp_invalid_rule{action = <<"mike">>,
  163:                                               condition = <<"hello">>,
  164:                                               value = <<"!">>}}]},
  165:                 amp:extract_requested_rules(M)).
  166: 
  167: extract_incomplete_amp_test(_) ->
  168:     {ok, M} = exml:parse(<<"
  169: <message
  170:     from='northumberland@shakespeare.lit'
  171:     id='richard2-4.1.247'
  172:     to='kingrichard@royalty.england.lit'>
  173:   <body>My lord, dispatch; read o'er these articles.</body>
  174:   <amp xmlns='http://jabber.org/protocol/amp'>
  175:     <incompatible-rule condition='hello' action='mike' value='!'/>
  176:   </amp>
  177: </message> ">>),
  178:     ?assertEqual(none,
  179:                  amp:extract_requested_rules(M)).
  180: 
  181: strip_amp_el_test(_) ->
  182:     AmpEl = #xmlel{name = <<"amp">>,
  183:                    attrs = [{<<"xmlns">>,<<"http://jabber.org/protocol/amp">>},
  184:                            {<<"status">>,<<"notify">>},
  185:                            {<<"to">>,<<"bernardo@hamlet.lit/elsinore">>},
  186:                            {<<"from">>,<<"francisco@hamlet.lit">>}],
  187:                    children = [
  188:                                #xmlel{name = <<"rule">>,
  189:                                        attrs = [{<<"action">>,<<"notify">>},
  190:                                                {<<"condition">>,<<"deliver">>},
  191:                                                {<<"value">>,<<"stored">>}]}]},
  192:     BodyEl = #xmlel{name = <<"body">>,
  193:                     attrs = [],
  194:                     children = [#xmlcdata{content = <<"Hello there!">>}]},
  195:     M = #xmlel{name = <<"message">>,
  196:                attrs =
  197:                    [{<<"from">>,<<"hamlet.lit">>},
  198:                     {<<"to">>,<<"bernardo@hamlet.lit/elsinore">>},
  199:                     {<<"id">>,<<"chatty2">>}],
  200:                children = [AmpEl,BodyEl]},
  201:     ?assertEqual(
  202:        #xmlel{name = <<"message">>,
  203:               attrs = [{<<"from">>, <<"hamlet.lit">>},
  204:                       {<<"to">>, <<"bernardo@hamlet.lit/elsinore">>},
  205:                       {<<"id">>, <<"chatty2">>}],
  206:               children = [BodyEl]
  207:              },
  208:        amp:strip_amp_el(M)).
  209: 
  210: strip_amp_el_noop_test(_) ->
  211:     BodyEl = #xmlel{name = <<"body">>,
  212:                     attrs = [],
  213:                     children = [#xmlcdata{content = <<"Hello there!">>}]},
  214:     M = #xmlel{name = <<"message">>,
  215:                attrs =
  216:                    [{<<"from">>,<<"hamlet.lit">>},
  217:                     {<<"to">>,<<"bernardo@hamlet.lit/elsinore">>},
  218:                     {<<"id">>,<<"chatty2">>}],
  219:                children = [BodyEl]},
  220:     ?assertEqual(M, amp:strip_amp_el(M)).
  221: 
  222: 
  223: is_valid_rule(#amp_rule{}) -> true;
  224: is_valid_rule(#amp_invalid_rule{}) -> false.
  225: 
  226: