Просмотр исходного кода

Rewrite the test cases for extended modules

Feng Lee 6 лет назад
Родитель
Сommit
3705f4f929

+ 17 - 16
src/emqx_mod_rewrite.erl

@@ -22,8 +22,9 @@
 -include_lib("emqx_mqtt.hrl").
 
 -ifdef(TEST).
--compile(export_all).
--compile(nowarn_export_all).
+-export([ compile/1
+        , match_and_rewrite/2
+        ]).
 -endif.
 
 %% APIs
@@ -48,13 +49,13 @@ load(RawRules) ->
     emqx_hooks:add('message.publish',    {?MODULE, rewrite_publish, [Rules]}).
 
 rewrite_subscribe(_ClientInfo, _Properties, TopicFilters, Rules) ->
-    {ok, [{match_rule(Topic, Rules), Opts} || {Topic, Opts} <- TopicFilters]}.
+    {ok, [{match_and_rewrite(Topic, Rules), Opts} || {Topic, Opts} <- TopicFilters]}.
 
 rewrite_unsubscribe(_ClientInfo, _Properties, TopicFilters, Rules) ->
-    {ok, [{match_rule(Topic, Rules), Opts} || {Topic, Opts} <- TopicFilters]}.
+    {ok, [{match_and_rewrite(Topic, Rules), Opts} || {Topic, Opts} <- TopicFilters]}.
 
 rewrite_publish(Message = #message{topic = Topic}, Rules) ->
-    {ok, Message#message{topic = match_rule(Topic, Rules)}}.
+    {ok, Message#message{topic = match_and_rewrite(Topic, Rules)}}.
 
 unload(_) ->
     emqx_hooks:del('client.subscribe',   {?MODULE, rewrite_subscribe}),
@@ -65,16 +66,22 @@ unload(_) ->
 %% Internal functions
 %%--------------------------------------------------------------------
 
-match_rule(Topic, []) ->
+compile(Rules) ->
+    lists:map(fun({rewrite, Topic, Re, Dest}) ->
+                  {ok, MP} = re:compile(Re),
+                  {rewrite, Topic, MP, Dest}
+              end, Rules).
+
+match_and_rewrite(Topic, []) ->
     Topic;
 
-match_rule(Topic, [{rewrite, Filter, MP, Dest} | Rules]) ->
+match_and_rewrite(Topic, [{rewrite, Filter, MP, Dest} | Rules]) ->
     case emqx_topic:match(Topic, Filter) of
-        true  -> match_regx(Topic, MP, Dest);
-        false -> match_rule(Topic, Rules)
+        true  -> rewrite(Topic, MP, Dest);
+        false -> match_and_rewrite(Topic, Rules)
     end.
 
-match_regx(Topic, MP, Dest) ->
+rewrite(Topic, MP, Dest) ->
     case re:run(Topic, MP, [{capture, all_but_first, list}]) of
         {match, Captured} ->
             Vars = lists:zip(["\\$" ++ integer_to_list(I)
@@ -86,9 +93,3 @@ match_regx(Topic, MP, Dest) ->
         nomatch -> Topic
     end.
 
-compile(Rules) ->
-    lists:map(fun({rewrite, Topic, Re, Dest}) ->
-                  {ok, MP} = re:compile(Re),
-                  {rewrite, Topic, MP, Dest}
-              end, Rules).
-

+ 0 - 50
test/emqx_mod_rewrite_SUITE.erl

@@ -1,50 +0,0 @@
-%%--------------------------------------------------------------------
-%% Copyright (c) 2019 EMQ Technologies Co., Ltd. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%%     http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%--------------------------------------------------------------------
-
--module(emqx_mod_rewrite_SUITE).
-
--compile(export_all).
--compile(nowarn_export_all).
-
--include("emqx_mqtt.hrl").
--include_lib("eunit/include/eunit.hrl").
-
--define(rules, [{rewrite,<<"x/#">>,<<"^x/y/(.+)$">>,<<"z/y/$1">>},
-                {rewrite,<<"y/+/z/#">>,<<"^y/(.+)/z/(.+)$">>,<<"y/z/$2">>}]).
-
-all() -> emqx_ct:all(?MODULE).
-
-t_rewrite_rule(_Config) ->
-    {ok, _} = emqx_hooks:start_link(),
-    ok = emqx_mod_rewrite:load(?rules),
-    RawTopicFilters = [{<<"x/y/2">>, opts},
-                       {<<"x/1/2">>, opts},
-                       {<<"y/a/z/b">>, opts},
-                       {<<"y/def">>, opts}],
-    SubTopicFilters = emqx_hooks:run_fold('client.subscribe', [client, properties], RawTopicFilters),
-    UnSubTopicFilters = emqx_hooks:run_fold('client.unsubscribe', [client, properties], RawTopicFilters),
-    Messages = [emqx_hooks:run_fold('message.publish', [], emqx_message:make(Topic, <<"payload">>))
-                || {Topic, _Opts} <- RawTopicFilters],
-    ExpectedTopicFilters = [{<<"z/y/2">>, opts},
-                            {<<"x/1/2">>, opts},
-                            {<<"y/z/b">>, opts},
-                            {<<"y/def">>, opts}],
-    ?assertEqual(ExpectedTopicFilters, SubTopicFilters),
-    ?assertEqual(ExpectedTopicFilters, UnSubTopicFilters),
-    [?assertEqual(ExpectedTopic, emqx_message:topic(Message))
-     || {{ExpectedTopic, _opts}, Message} <- lists:zip(ExpectedTopicFilters, Messages)],
-    ok = emqx_mod_rewrite:unload(?rules),
-    ok = emqx_hooks:stop().

+ 0 - 52
test/emqx_mod_subscription_SUITE.erl

@@ -1,52 +0,0 @@
-%%--------------------------------------------------------------------
-%% Copyright (c) 2019 EMQ Technologies Co., Ltd. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%%     http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%--------------------------------------------------------------------
-
--module(emqx_mod_subscription_SUITE).
-
--compile(export_all).
--compile(nowarn_export_all).
-
--include("emqx_mqtt.hrl").
--include("emqx.hrl").
-
--include_lib("eunit/include/eunit.hrl").
--include_lib("common_test/include/ct.hrl").
-
-all() -> emqx_ct:all(?MODULE).
-
-init_per_suite(Config) ->
-    emqx_ct_helpers:boot_modules(all),
-    emqx_ct_helpers:start_apps([emqx]),
-    Config.
-
-end_per_suite(_Config) ->
-    emqx_ct_helpers:stop_apps([emqx]).
-
-t_mod_subscription(_) ->
-    emqx_mod_subscription:load([{<<"connected/%c/%u">>, ?QOS_0}]),
-    {ok, C} = emqtt:start_link([{host, "localhost"}, {client_id, "myclient"}, {username, "admin"}]),
-    {ok, _} = emqtt:connect(C),
-    % ct:sleep(100),
-    emqtt:publish(C, <<"connected/myclient/admin">>, <<"Hello world">>, ?QOS_0),
-    receive
-        {publish, #{topic := Topic, payload := Payload}} ->
-            ?assertEqual(<<"connected/myclient/admin">>, Topic),
-            ?assertEqual(<<"Hello world">>, Payload)
-    after 100 ->
-        ct:fail("no_message")
-    end,
-    ok = emqtt:disconnect(C),
-    emqx_mod_subscription:unload([]).

+ 148 - 0
test/emqx_modules_SUITE.erl

@@ -0,0 +1,148 @@
+%%--------------------------------------------------------------------
+%% Copyright (c) 2019 EMQ Technologies Co., Ltd. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%%     http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%--------------------------------------------------------------------
+
+-module(emqx_modules_SUITE).
+
+%% API
+-compile(export_all).
+-compile(nowarn_export_all).
+
+-include("emqx.hrl").
+-include("emqx_mqtt.hrl").
+
+%%-include_lib("proper/include/proper.hrl").
+-include_lib("common_test/include/ct.hrl").
+-include_lib("eunit/include/eunit.hrl").
+
+%%-define(PROPTEST(M,F), true = proper:quickcheck(M:F())).
+
+-define(RULES, [{rewrite,<<"x/#">>,<<"^x/y/(.+)$">>,<<"z/y/$1">>},
+                {rewrite,<<"y/+/z/#">>,<<"^y/(.+)/z/(.+)$">>,<<"y/z/$2">>}
+               ]).
+
+all() -> emqx_ct:all(?MODULE).
+
+suite() ->
+    [{ct_hooks,[cth_surefire]}, {timetrap, {seconds, 30}}].
+
+init_per_suite(Config) ->
+    emqx_ct_helpers:boot_modules(all),
+    emqx_ct_helpers:start_apps([emqx]),
+    %% Ensure all the modules unloaded.
+    ok = emqx_modules:unload(),
+    Config.
+
+end_per_suite(_Config) ->
+    emqx_ct_helpers:stop_apps([emqx]).
+
+%%--------------------------------------------------------------------
+%% Test cases
+%%--------------------------------------------------------------------
+
+%% Test case for emqx_mod_presence
+t_mod_presence(_) ->
+    ok = emqx_mod_presence:load([{qos, ?QOS_1}]),
+    {ok, C1} = emqtt:start_link([{client_id, <<"monsys">>}]),
+    {ok, _} = emqtt:connect(C1),
+    {ok, _Props, [?QOS_1]} = emqtt:subscribe(C1, <<"$SYS/brokers/+/clients/#">>, qos1),
+    %% Connected Presence
+    {ok, C2} = emqtt:start_link([{client_id, <<"clientid">>},
+                                 {username, <<"username">>}]),
+    {ok, _} = emqtt:connect(C2),
+    ok = recv_and_check_presence(<<"clientid">>, <<"connected">>),
+    %% Disconnected Presence
+    ok = emqtt:disconnect(C2),
+    ok = recv_and_check_presence(<<"clientid">>, <<"disconnected">>),
+    ok = emqtt:disconnect(C1),
+    ok = emqx_mod_presence:unload([{qos, ?QOS_1}]).
+
+recv_and_check_presence(ClientId, Presence) ->
+    {ok, #{qos := ?QOS_1, topic := Topic, payload := Payload}} = receive_publish(100),
+    ?assertMatch([<<"$SYS">>, <<"brokers">>, _Node, <<"clients">>, ClientId, Presence],
+                 binary:split(Topic, <<"/">>, [global])),
+    case Presence of
+        <<"connected">> ->
+            ?assertMatch(#{clientid := <<"clientid">>,
+                           username := <<"username">>,
+                           ipaddress := <<"127.0.0.1">>,
+                           proto_name := <<"MQTT">>,
+                           proto_ver := ?MQTT_PROTO_V4,
+                           connack := ?RC_SUCCESS,
+                           clean_start := true}, emqx_json:decode(Payload, [{labels, atom}, return_maps]));
+        <<"disconnected">> ->
+            ?assertMatch(#{clientid := <<"clientid">>,
+                           username := <<"username">>,
+                           reason := <<"normal">>}, emqx_json:decode(Payload, [{labels, atom}, return_maps]))
+    end.
+
+%% Test case for emqx_mod_subscription
+t_mod_subscription(_) ->
+    emqx_mod_subscription:load([{<<"connected/%c/%u">>, ?QOS_0}]),
+    {ok, C} = emqtt:start_link([{host, "localhost"},
+                                {client_id, "myclient"},
+                                {username, "admin"}]),
+    {ok, _} = emqtt:connect(C),
+    emqtt:publish(C, <<"connected/myclient/admin">>, <<"Hello world">>, ?QOS_0),
+    {ok, #{topic := Topic, payload := Payload}} = receive_publish(100),
+    ?assertEqual(<<"connected/myclient/admin">>, Topic),
+    ?assertEqual(<<"Hello world">>, Payload),
+    ok = emqtt:disconnect(C),
+    emqx_mod_subscription:unload([]).
+
+%% Test case for emqx_mod_write
+t_mod_rewrite(_Config) ->
+    ok = emqx_mod_rewrite:load(?RULES),
+    {ok, C} = emqtt:start_link([{client_id, <<"rewrite_client">>}]),
+    {ok, _} = emqtt:connect(C),
+    OrigTopics = [<<"x/y/2">>, <<"x/1/2">>, <<"y/a/z/b">>, <<"y/def">>],
+    DestTopics = [<<"z/y/2">>, <<"x/1/2">>, <<"y/z/b">>, <<"y/def">>],
+    %% Subscribe
+    {ok, _Props, _} = emqtt:subscribe(C, [{Topic, ?QOS_1} || Topic <- OrigTopics]),
+    timer:sleep(100),
+    Subscriptions = emqx_broker:subscriptions(<<"rewrite_client">>),
+    ?assertEqual(DestTopics, [Topic || {Topic, _SubOpts} <- Subscriptions]),
+    %% Publish
+    RecvTopics = [begin
+                      ok = emqtt:publish(C, Topic, <<"payload">>),
+                      {ok, #{topic := RecvTopic}} = receive_publish(100),
+                      RecvTopic
+                  end || Topic <- OrigTopics],
+    ?assertEqual(DestTopics, RecvTopics),
+    %% Unsubscribe
+    {ok, _, _} = emqtt:unsubscribe(C, OrigTopics),
+    timer:sleep(100),
+    ?assertEqual([], emqx_broker:subscriptions(<<"rewrite_client">>)),
+    ok = emqtt:disconnect(C),
+    ok = emqx_mod_rewrite:unload(?RULES).
+
+t_rewrite_rule(_Config) ->
+    Rules = emqx_mod_rewrite:compile(?RULES),
+    ?assertEqual(<<"z/y/2">>, emqx_mod_rewrite:match_and_rewrite(<<"x/y/2">>, Rules)),
+    ?assertEqual(<<"x/1/2">>, emqx_mod_rewrite:match_and_rewrite(<<"x/1/2">>, Rules)),
+    ?assertEqual(<<"y/z/b">>, emqx_mod_rewrite:match_and_rewrite(<<"y/a/z/b">>, Rules)),
+    ?assertEqual(<<"y/def">>, emqx_mod_rewrite:match_and_rewrite(<<"y/def">>, Rules)).
+
+%%--------------------------------------------------------------------
+%% Internal functions
+%%--------------------------------------------------------------------
+
+receive_publish(Timeout) ->
+    receive
+        {publish, Publish} -> {ok, Publish}
+    after
+        Timeout -> {error, timeout}
+    end.
+