Browse Source

Update all the test cases

Feng Lee 6 years ago
parent
commit
4afa02ee48
70 changed files with 944 additions and 3935 deletions
  1. 23 15
      src/emqx_tables.erl
  2. 8 4
      src/emqx_time.erl
  3. 10 9
      src/emqx_topic.erl
  4. 0 206
      test/emqx_SUITE.erl
  5. 0 29
      test/emqx_SUITE_data/acl.conf
  6. 0 0
      test/emqx_SUITE_data/loaded_plugins
  7. 116 85
      test/emqx_access_SUITE.erl
  8. 5 1
      test/emqx_acl_test_mod.erl
  9. 0 110
      test/emqx_alarm_handler_SUITE.erl
  10. 0 29
      test/emqx_auth_anonymous_test_mod.erl
  11. 0 30
      test/emqx_auth_dashboard.erl
  12. 52 24
      test/emqx_banned_SUITE.erl
  13. 11 6
      test/emqx_batch_SUITE.erl
  14. 61 73
      test/emqx_broker_SUITE.erl
  15. 0 74
      test/emqx_channel_SUITE.erl
  16. 0 209
      test/emqx_client_SUITE.erl
  17. 0 71
      test/emqx_cm_SUITE.erl
  18. 0 62
      test/emqx_flapping_SUITE.erl
  19. 71 70
      test/emqx_frame_SUITE.erl
  20. 1 2
      test/emqx_gc_SUITE.erl
  21. 5 5
      test/emqx_guid_SUITE.erl
  22. 11 8
      test/emqx_hooks_SUITE.erl
  23. 69 22
      test/emqx_inflight_SUITE.erl
  24. 12 7
      test/emqx_json_SUITE.erl
  25. 2 9
      test/emqx_keepalive_SUITE.erl
  26. 0 175
      test/emqx_lib_SUITE.erl
  27. 4 9
      test/emqx_listeners_SUITE.erl
  28. 13 13
      test/emqx_message_SUITE.erl
  29. 50 41
      test/emqx_metrics_SUITE.erl
  30. 30 11
      test/emqx_misc_tests.erl
  31. 0 101
      test/emqx_mock_client.erl
  32. 0 27
      test/emqx_mod_SUITE.erl
  33. 0 65
      test/emqx_mod_rewrite_tests.erl
  34. 0 45
      test/emqx_mod_sup_SUITE.erl
  35. 39 10
      test/emqx_mountpoint_SUITE.erl
  36. 0 133
      test/emqx_mqtt_caps_SUITE.erl
  37. 0 117
      test/emqx_mqtt_packet_SUITE.erl
  38. 14 2
      test/emqx_mqtt_props_SUITE.erl
  39. 9 7
      test/emqx_mqueue_SUITE.erl
  40. 2 3
      test/emqx_os_mon_SUITE.erl
  41. 22 27
      test/emqx_packet_SUITE.erl
  42. 2 2
      test/emqx_pd_SUITE.erl
  43. 1 2
      test/emqx_pmon_SUITE.erl
  44. 21 12
      test/emqx_pool_SUITE.erl
  45. 5 6
      test/emqx_pqueue_SUITE.erl
  46. 0 613
      test/emqx_protocol_SUITE.erl
  47. 0 30
      test/emqx_protocol_tests.erl
  48. 11 7
      test/emqx_reason_codes_tests.erl
  49. 0 97
      test/emqx_request_handler.erl
  50. 0 71
      test/emqx_request_response_SUITE.erl
  51. 0 77
      test/emqx_request_sender.erl
  52. 7 16
      test/emqx_router_SUITE.erl
  53. 0 38
      test/emqx_rpc_SUITE.erl
  54. 15 6
      test/emqx_sequence_SUITE.erl
  55. 39 4
      test/emqx_session_SUITE.erl
  56. 0 260
      test/emqx_shared_sub_SUITE.erl
  57. 0 115
      test/emqx_sm_SUITE.erl
  58. 18 13
      test/emqx_stats_tests.erl
  59. 21 14
      test/emqx_sys_mon_SUITE.erl
  60. 22 7
      test/emqx_tables_SUITE.erl
  61. 12 7
      test/emqx_time_SUITE.erl
  62. 75 73
      test/emqx_topic_SUITE.erl
  63. 2 3
      test/emqx_tracer_SUITE.erl
  64. 3 3
      test/emqx_trie_SUITE.erl
  65. 26 29
      test/emqx_vm_SUITE.erl
  66. 2 3
      test/emqx_vm_mon_SUITE.erl
  67. 0 144
      test/emqx_ws_channel_SUITE.erl
  68. 22 11
      test/emqx_zone_SUITE.erl
  69. 0 251
      test/rfc6455_client.erl
  70. 0 75
      test/ws_client.erl

+ 23 - 15
src/emqx_tables.erl

@@ -16,12 +16,21 @@
 
 -module(emqx_tables).
 
--export([new/2, delete/1]).
+-export([ new/1
+        , new/2
+        ]).
 
 -export([ lookup_value/2
         , lookup_value/3
         ]).
 
+-export([delete/1]).
+
+%% Create an ets table.
+-spec(new(atom()) -> ok).
+new(Tab) ->
+    new(Tab, []).
+
 %% Create a named_table ets.
 -spec(new(atom(), list()) -> ok).
 new(Tab, Opts) ->
@@ -32,26 +41,25 @@ new(Tab, Opts) ->
         Tab -> ok
     end.
 
--spec(delete(atom()) -> ok).
-delete(Tab) ->
-    case ets:info(Tab, name) of
-        undefined ->
-            ok;
-        Tab ->
-            ets:delete(Tab),
-            ok
-    end.
-
 %% KV lookup
--spec(lookup_value(atom(), term()) -> any()).
+-spec(lookup_value(ets:tab(), term()) -> any()).
 lookup_value(Tab, Key) ->
     lookup_value(Tab, Key, undefined).
 
--spec(lookup_value(atom(), term(), any()) -> any()).
+-spec(lookup_value(ets:tab(), term(), any()) -> any()).
 lookup_value(Tab, Key, Def) ->
-    try
-        ets:lookup_element(Tab, Key, 2)
+    try ets:lookup_element(Tab, Key, 2)
     catch
         error:badarg -> Def
     end.
 
+%% Delete the ets table.
+-spec(delete(ets:tab()) -> ok).
+delete(Tab) ->
+    case ets:info(Tab, name) of
+        undefined -> ok;
+        Tab ->
+            ets:delete(Tab),
+            ok
+    end.
+

+ 8 - 4
src/emqx_time.erl

@@ -21,9 +21,16 @@
         , now_secs/1
         , now_ms/0
         , now_ms/1
-        , ts_from_ms/1
         ]).
 
+-compile({inline,
+          [ seed/0
+          , now_secs/0
+          , now_secs/1
+          , now_ms/0
+          , now_ms/1
+          ]}).
+
 seed() ->
     rand:seed(exsplus, erlang:timestamp()).
 
@@ -39,6 +46,3 @@ now_ms() ->
 now_ms({MegaSecs, Secs, MicroSecs}) ->
     (MegaSecs * 1000000 + Secs) * 1000 + round(MicroSecs/1000).
 
-ts_from_ms(Ms) ->
-    {Ms div 1000000, Ms rem 1000000, 0}.
-

+ 10 - 9
src/emqx_topic.erl

@@ -16,8 +16,6 @@
 
 -module(emqx_topic).
 
--include("emqx_mqtt.hrl").
-
 %% APIs
 -export([ match/2
         , validate/1
@@ -66,7 +64,7 @@ wildcard(['+'|_]) ->
 wildcard([_H|T]) ->
     wildcard(T).
 
-%% @doc Match Topic name with filter
+%% @doc Match Topic name with filter.
 -spec(match(Name, Filter) -> boolean() when
       Name   :: topic() | words(),
       Filter :: topic() | words()).
@@ -74,7 +72,7 @@ match(<<$$, _/binary>>, <<$+, _/binary>>) ->
     false;
 match(<<$$, _/binary>>, <<$#, _/binary>>) ->
     false;
-match(Name, Filter) when is_binary(Name) and is_binary(Filter) ->
+match(Name, Filter) when is_binary(Name), is_binary(Filter) ->
     match(words(Name), words(Filter));
 match([], []) ->
     true;
@@ -101,13 +99,15 @@ validate({Type, Topic}) when Type =:= name; Type =:= filter ->
 -spec(validate(name | filter, topic()) -> true).
 validate(_, <<>>) ->
     error(empty_topic);
-validate(_, Topic) when is_binary(Topic) and (size(Topic) > ?MAX_TOPIC_LEN) ->
+validate(_, Topic) when is_binary(Topic) andalso (size(Topic) > ?MAX_TOPIC_LEN) ->
     error(topic_too_long);
 validate(filter, Topic) when is_binary(Topic) ->
     validate2(words(Topic));
 validate(name, Topic) when is_binary(Topic) ->
     Words = words(Topic),
-    validate2(Words) and (not wildcard(Words)).
+    validate2(Words)
+        andalso (not wildcard(Words))
+            orelse error(topic_name_error).
 
 validate2([]) ->
     true;
@@ -129,7 +129,7 @@ validate3(<<C/utf8, _Rest/binary>>) when C == $#; C == $+; C == 0 ->
 validate3(<<_/utf8, Rest/binary>>) ->
     validate3(Rest).
 
-%% @doc Topic to triples
+%% @doc Topic to triples.
 -spec(triples(topic()) -> list(triple())).
 triples(Topic) when is_binary(Topic) ->
     triples(words(Topic), root, []).
@@ -218,13 +218,14 @@ parse(TopicFilter) when is_binary(TopicFilter) ->
 parse({TopicFilter, Options}) when is_binary(TopicFilter) ->
     parse(TopicFilter, Options).
 
+-spec(parse(topic(), map()) -> {topic(), map()}).
 parse(TopicFilter = <<"$queue/", _/binary>>, #{share := _Group}) ->
     error({invalid_topic_filter, TopicFilter});
-parse(TopicFilter = <<?SHARE, "/", _/binary>>, #{share := _Group}) ->
+parse(TopicFilter = <<"$share/", _/binary>>, #{share := _Group}) ->
     error({invalid_topic_filter, TopicFilter});
 parse(<<"$queue/", TopicFilter/binary>>, Options) ->
     parse(TopicFilter, Options#{share => <<"$queue">>});
-parse(TopicFilter = <<?SHARE, "/", Rest/binary>>, Options) ->
+parse(TopicFilter = <<"$share/", Rest/binary>>, Options) ->
     case binary:split(Rest, <<"/">>) of
         [_Any] -> error({invalid_topic_filter, TopicFilter});
         [ShareName, Filter] ->

+ 0 - 206
test/emqx_SUITE.erl

@@ -1,206 +0,0 @@
-%% Copyright (c) 2013-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_SUITE).
-
--compile(export_all).
--compile(nowarn_export_all).
-
--define(APP, emqx).
-
--include_lib("eunit/include/eunit.hrl").
-
--include_lib("common_test/include/ct.hrl").
-
--include("emqx_mqtt.hrl").
-
--record(ssl_socket, {tcp, ssl}).
-
-
--define(CLIENT, ?CONNECT_PACKET(#mqtt_packet_connect{
-                                client_id = <<"mqtt_client">>,
-                                username  = <<"admin">>,
-                                password  = <<"public">>})).
-
--define(CLIENT2, ?CONNECT_PACKET(#mqtt_packet_connect{
-                                username  = <<"admin">>,
-                                clean_start = false,
-                                password  = <<"public">>})).
-
--define(CLIENT3, ?CONNECT_PACKET(#mqtt_packet_connect{
-                                username  = <<"admin">>,
-                                proto_ver = ?MQTT_PROTO_V5,
-                                clean_start = false,
-                                password  = <<"public">>,
-                                will_props = #{'Will-Delay-Interval' => 2}})).
-
--define(SUBCODE, [0]).
-
--define(PACKETID, 1).
-
--define(PUBQOS, 1).
-
--define(SUBPACKET, ?SUBSCRIBE_PACKET(?PACKETID, [{<<"sub/topic">>, ?DEFAULT_SUBOPTS}])).
-
--define(PUBPACKET, ?PUBLISH_PACKET(?PUBQOS, <<"sub/topic">>, ?PACKETID, <<"publish">>)).
-
--define(PAYLOAD, [{type,"dsmSimulationData"},
-                  {id, 9999},
-                  {status, "running"},
-                  {soc, 1536702170},
-                  {fracsec, 451000},
-                  {data, lists:seq(1, 20480)}]).
-
--define(BIG_PUBPACKET, ?PUBLISH_PACKET(?PUBQOS, <<"sub/topic">>, ?PACKETID, emqx_json:encode(?PAYLOAD))).
-
-all() ->
-    [{group, connect},
-     {group, publish}].
-
-groups() ->
-    [{connect, [non_parallel_tests],
-      [mqtt_connect,
-       mqtt_connect_with_tcp,
-       mqtt_connect_with_will_props,
-       mqtt_connect_with_ssl_oneway,
-       mqtt_connect_with_ssl_twoway,
-       mqtt_connect_with_ws]},
-     {publish, [non_parallel_tests],
-      [packet_size]}].
-
-init_per_suite(Config) ->
-    emqx_ct_helpers:start_apps([]),
-    Config.
-
-end_per_suite(_Config) ->
-    emqx_ct_helpers:stop_apps([]).
-
-%%--------------------------------------------------------------------
-%% Protocol Test
-%%--------------------------------------------------------------------
-mqtt_connect(_) ->
-    %% Issue #599
-    %% Empty clientId and clean_session = false
-    ?assertEqual(<<32,2,0,2>>, connect_broker_(<<16,12,0,4,77,81,84,84,4,0,0,90,0,0>>, 4)),
-    %% Empty clientId and clean_session = true
-    ?assertEqual(<<32,2,0,0>>, connect_broker_(<<16,12,0,4,77,81,84,84,4,2,0,90,0,0>>, 4)).
-
-connect_broker_(Packet, RecvSize) ->
-    {ok, Sock} = emqx_client_sock:connect({127,0,0,1}, 1883, [binary, {packet, raw}, {active, false}], 3000),
-    emqx_client_sock:send(Sock, Packet),
-    {ok, Data} = gen_tcp:recv(Sock, RecvSize, 3000),
-    emqx_client_sock:close(Sock),
-    Data.
-
-mqtt_connect_with_tcp(_) ->
-    %% Issue #599
-    %% Empty clientId and clean_session = false
-    {ok, Sock} = emqx_client_sock:connect({127,0,0,1}, 1883, [binary, {packet, raw}, {active, false}], 3000),
-    Packet = raw_send_serialize(?CLIENT2),
-    emqx_client_sock:send(Sock, Packet),
-    {ok, Data} = gen_tcp:recv(Sock, 0),
-    {ok, ?CONNACK_PACKET(?CONNACK_INVALID_ID), <<>>, _} = raw_recv_pase(Data),
-    emqx_client_sock:close(Sock).
-
-mqtt_connect_with_will_props(_) ->
-    %% Issue #599
-    %% Empty clientId and clean_session = false
-    {ok, Sock} = emqx_client_sock:connect({127,0,0,1}, 1883, [binary, {packet, raw}, {active, false}], 3000),
-    Packet = raw_send_serialize(?CLIENT3),
-    emqx_client_sock:send(Sock, Packet),
-    emqx_client_sock:close(Sock).
-
-mqtt_connect_with_ssl_oneway(_) ->
-    emqx:shutdown(),
-    emqx_ct_helpers:change_emqx_opts(ssl_oneway),
-    emqx:start(),
-    ClientSsl = emqx_ct_helpers:client_ssl(),
-    {ok, #ssl_socket{tcp = _Sock1, ssl = SslSock} = Sock}
-    = emqx_client_sock:connect("127.0.0.1", 8883, [{ssl_opts, ClientSsl}], 3000),
-    Packet = raw_send_serialize(?CLIENT),
-    emqx_client_sock:setopts(Sock, [{active, once}]),
-    emqx_client_sock:send(Sock, Packet),
-    ?assert(
-    receive {ssl, _, ConAck}->
-        {ok, ?CONNACK_PACKET(?CONNACK_ACCEPT), <<>>, _} = raw_recv_pase(ConAck), true
-    after 1000 ->
-        false
-    end),
-    ssl:close(SslSock).
-
-mqtt_connect_with_ssl_twoway(_Config) ->
-    emqx:shutdown(),
-    emqx_ct_helpers:change_emqx_opts(ssl_twoway),
-    emqx:start(),
-    ClientSsl = emqx_ct_helpers:client_ssl_twoway(),
-    {ok, #ssl_socket{tcp = _Sock1, ssl = SslSock} = Sock}
-        = emqx_client_sock:connect("127.0.0.1", 8883, [{ssl_opts, ClientSsl}], 3000),
-    Packet = raw_send_serialize(?CLIENT),
-    emqx_client_sock:setopts(Sock, [{active, once}]),
-    emqx_client_sock:send(Sock, Packet),
-    timer:sleep(500),
-    ?assert(
-    receive {ssl, _, Data}->
-        {ok, ?CONNACK_PACKET(?CONNACK_ACCEPT), <<>>, _} = raw_recv_pase(Data), true
-    after 1000 ->
-        false
-    end),
-    ssl:close(SslSock),
-    emqx_client_sock:close(Sock).
-
-mqtt_connect_with_ws(_Config) ->
-    WS = rfc6455_client:new("ws://127.0.0.1:8083" ++ "/mqtt", self()),
-    {ok, _} = rfc6455_client:open(WS),
-
-    %% Connect Packet
-    Packet = raw_send_serialize(?CLIENT),
-    ok = rfc6455_client:send_binary(WS, Packet),
-    {binary, CONACK} = rfc6455_client:recv(WS),
-    {ok, ?CONNACK_PACKET(?CONNACK_ACCEPT), <<>>, _} = raw_recv_pase(CONACK),
-
-    %% Sub Packet
-    SubPacket = raw_send_serialize(?SUBPACKET),
-    rfc6455_client:send_binary(WS, SubPacket),
-    {binary, SubAck} = rfc6455_client:recv(WS),
-    {ok, ?SUBACK_PACKET(?PACKETID, ?SUBCODE), <<>>, _} = raw_recv_pase(SubAck),
-
-    %% Pub Packet QoS 1
-    PubPacket = raw_send_serialize(?PUBPACKET),
-    rfc6455_client:send_binary(WS, PubPacket),
-    {binary, PubAck} = rfc6455_client:recv(WS),
-    {ok, ?PUBACK_PACKET(?PACKETID), <<>>, _} = raw_recv_pase(PubAck),
-    {close, _} = rfc6455_client:close(WS),
-    ok.
-
-%%issue 1811
-packet_size(_Config) ->
-    {ok, Sock} = emqx_client_sock:connect({127,0,0,1}, 1883, [binary, {packet, raw}, {active, false}], 3000),
-    Packet = raw_send_serialize(?CLIENT),
-    emqx_client_sock:send(Sock, Packet),
-    {ok, Data} = gen_tcp:recv(Sock, 0),
-    {ok, ?CONNACK_PACKET(?CONNACK_ACCEPT), <<>>, _} = raw_recv_pase(Data),
-
-    %% Pub Packet QoS 1
-    PubPacket = raw_send_serialize(?BIG_PUBPACKET),
-    emqx_client_sock:send(Sock, PubPacket),
-    {ok, Data1} = gen_tcp:recv(Sock, 0),
-    {ok, ?PUBACK_PACKET(?PACKETID), <<>>, _} = raw_recv_pase(Data1),
-    emqx_client_sock:close(Sock).
-
-raw_send_serialize(Packet) ->
-    emqx_frame:serialize(Packet).
-
-raw_recv_pase(Bin) ->
-    emqx_frame:parse(Bin).
-

+ 0 - 29
test/emqx_SUITE_data/acl.conf

@@ -1,29 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% [ACL](https://github.com/emqtt/emqttd/wiki/ACL)
-%%
-%% -type who() :: all | binary() |
-%%                {ipaddr, esockd_access:cidr()} |
-%%                {client, binary()} |
-%%                {user, binary()}.
-%%
-%% -type access() :: subscribe | publish | pubsub.
-%%
-%% -type topic() :: binary().
-%%
-%% -type rule() :: {allow, all} |
-%%                 {allow, who(), access(), list(topic())} |
-%%                 {deny, all} |
-%%                 {deny, who(), access(), list(topic())}.
-%%
-%%--------------------------------------------------------------------
-
-{allow, {user, "dashboard"}, subscribe, ["$SYS/#"]}.
-
-{allow, {ipaddr, "127.0.0.1"}, pubsub, ["$SYS/#", "#"]}.
-
-{deny, all, subscribe, ["$SYS/#", {eq, "#"}]}.
-
-{allow, all}.
-
-

+ 0 - 0
test/emqx_SUITE_data/loaded_plugins


+ 116 - 85
test/emqx_access_SUITE.erl

@@ -21,41 +21,46 @@
 
 -include("emqx.hrl").
 
--include_lib("common_test/include/ct.hrl").
 -include_lib("eunit/include/eunit.hrl").
+-include_lib("common_test/include/ct.hrl").
 
 -define(AC, emqx_access_control).
 -define(CACHE, emqx_acl_cache).
 
--import(emqx_access_rule, [compile/1, match/3]).
+-import(emqx_access_rule,
+        [ compile/1
+        , match/3
+        ]).
 
 all() ->
     [{group, access_control},
      {group, acl_cache},
      {group, access_control_cache_mode},
-     {group, access_rule}].
+     {group, access_rule}
+    ].
 
 groups() ->
     [{access_control, [sequence],
-      [reload_acl,
-       check_acl_1,
-       check_acl_2]},
-     {access_control_cache_mode, [],
-      [acl_cache_basic,
-       acl_cache_expiry,
-       acl_cache_cleanup,
-       acl_cache_full]},
-     {acl_cache, [],
-      [put_get_del_cache,
-       cache_update,
-       cache_expiry,
-       cache_replacement,
-       cache_cleanup,
-       cache_auto_emtpy,
-       cache_auto_cleanup]},
-     {access_rule, [],
-      [compile_rule,
-       match_rule]}].
+      [t_reload_acl,
+       t_check_acl_1,
+       t_check_acl_2]},
+     {access_control_cache_mode, [sequence],
+      [t_acl_cache_basic,
+       t_acl_cache_expiry,
+       t_acl_cache_cleanup,
+       t_acl_cache_full]},
+     {acl_cache, [sequence],
+      [t_put_get_del_cache,
+       t_cache_update,
+       t_cache_expiry,
+       t_cache_replacement,
+       t_cache_cleanup,
+       t_cache_auto_emtpy,
+       t_cache_auto_cleanup]},
+     {access_rule, [parallel],
+      [t_compile_rule,
+       t_match_rule]
+     }].
 
 init_per_suite(Config) ->
     emqx_ct_helpers:start_apps([]),
@@ -102,62 +107,76 @@ end_per_group(_Group, Config) ->
 %% emqx_access_control
 %%--------------------------------------------------------------------
 
-reload_acl(_) ->
+t_reload_acl(_) ->
     ok = ?AC:reload_acl().
 
-check_acl_1(_) ->
-    SelfUser = #{client_id => <<"client1">>, username => <<"testuser">>, zone => external},
-    allow = ?AC:check_acl(SelfUser, subscribe, <<"users/testuser/1">>),
-    allow = ?AC:check_acl(SelfUser, subscribe, <<"clients/client1">>),
-    deny  = ?AC:check_acl(SelfUser, subscribe, <<"clients/client1/x/y">>),
-    allow = ?AC:check_acl(SelfUser, publish, <<"users/testuser/1">>),
-    allow = ?AC:check_acl(SelfUser, subscribe, <<"a/b/c">>).
-check_acl_2(_) ->
-    SelfUser = #{client_id => <<"client2">>, username => <<"xyz">>, zone => external},
-    deny = ?AC:check_acl(SelfUser, subscribe, <<"a/b/c">>).
-
-acl_cache_basic(_) ->
-    SelfUser = #{client_id => <<"client1">>, username => <<"testuser">>, zone => external},
+t_check_acl_1(_) ->
+    Client = #{zone => external,
+               client_id => <<"client1">>,
+               username => <<"testuser">>
+              },
+    allow = ?AC:check_acl(Client, subscribe, <<"users/testuser/1">>),
+    allow = ?AC:check_acl(Client, subscribe, <<"clients/client1">>),
+    deny  = ?AC:check_acl(Client, subscribe, <<"clients/client1/x/y">>),
+    allow = ?AC:check_acl(Client, publish, <<"users/testuser/1">>),
+    allow = ?AC:check_acl(Client, subscribe, <<"a/b/c">>).
+
+t_check_acl_2(_) ->
+    Client = #{zone => external,
+               client_id => <<"client2">>,
+               username => <<"xyz">>
+              },
+    deny = ?AC:check_acl(Client, subscribe, <<"a/b/c">>).
+
+t_acl_cache_basic(_) ->
+    Client = #{zone => external,
+               client_id => <<"client1">>,
+               username => <<"testuser">>
+              },
     not_found = ?CACHE:get_acl_cache(subscribe, <<"users/testuser/1">>),
     not_found = ?CACHE:get_acl_cache(subscribe, <<"clients/client1">>),
 
-    allow = ?AC:check_acl(SelfUser, subscribe, <<"users/testuser/1">>),
-    allow = ?AC:check_acl(SelfUser, subscribe, <<"clients/client1">>),
+    allow = ?AC:check_acl(Client, subscribe, <<"users/testuser/1">>),
+    allow = ?AC:check_acl(Client, subscribe, <<"clients/client1">>),
 
     allow = ?CACHE:get_acl_cache(subscribe, <<"users/testuser/1">>),
-    allow = ?CACHE:get_acl_cache(subscribe, <<"clients/client1">>),
-    ok.
+    allow = ?CACHE:get_acl_cache(subscribe, <<"clients/client1">>).
 
-acl_cache_expiry(_) ->
+t_acl_cache_expiry(_) ->
     application:set_env(emqx, acl_cache_ttl, 100),
-    SelfUser = #{client_id => <<"client1">>, username => <<"testuser">>, zone => external},
-    allow = ?AC:check_acl(SelfUser, subscribe, <<"clients/client1">>),
+    Client = #{zone => external,
+               client_id => <<"client1">>,
+               username => <<"testuser">>
+              },
+    allow = ?AC:check_acl(Client, subscribe, <<"clients/client1">>),
     allow = ?CACHE:get_acl_cache(subscribe, <<"clients/client1">>),
     ct:sleep(150),
-    not_found = ?CACHE:get_acl_cache(subscribe, <<"clients/client1">>),
-    ok.
+    not_found = ?CACHE:get_acl_cache(subscribe, <<"clients/client1">>).
 
-acl_cache_full(_) ->
+t_acl_cache_full(_) ->
     application:set_env(emqx, acl_cache_max_size, 1),
-
-    SelfUser = #{client_id => <<"client1">>, username => <<"testuser">>, zone => external},
-    allow = ?AC:check_acl(SelfUser, subscribe, <<"users/testuser/1">>),
-    allow = ?AC:check_acl(SelfUser, subscribe, <<"clients/client1">>),
+    Client = #{zone => external,
+               client_id => <<"client1">>,
+               username => <<"testuser">>
+              },
+    allow = ?AC:check_acl(Client, subscribe, <<"users/testuser/1">>),
+    allow = ?AC:check_acl(Client, subscribe, <<"clients/client1">>),
 
     %% the older ones (the <<"users/testuser/1">>) will be evicted first
     not_found = ?CACHE:get_acl_cache(subscribe, <<"users/testuser/1">>),
-    allow = ?CACHE:get_acl_cache(subscribe, <<"clients/client1">>),
-    ok.
+    allow = ?CACHE:get_acl_cache(subscribe, <<"clients/client1">>).
 
-acl_cache_cleanup(_) ->
+t_acl_cache_cleanup(_) ->
     %% The acl cache will try to evict memory, if the size is full and the newest
     %%   cache entry is expired
     application:set_env(emqx, acl_cache_ttl, 100),
     application:set_env(emqx, acl_cache_max_size, 2),
-
-    SelfUser = #{client_id => <<"client1">>, username => <<"testuser">>, zone => external},
-    allow = ?AC:check_acl(SelfUser, subscribe, <<"users/testuser/1">>),
-    allow = ?AC:check_acl(SelfUser, subscribe, <<"clients/client1">>),
+    Client = #{zone => external,
+               client_id => <<"client1">>,
+               username => <<"testuser">>
+              },
+    allow = ?AC:check_acl(Client, subscribe, <<"users/testuser/1">>),
+    allow = ?AC:check_acl(Client, subscribe, <<"clients/client1">>),
 
     allow = ?CACHE:get_acl_cache(subscribe, <<"users/testuser/1">>),
     allow = ?CACHE:get_acl_cache(subscribe, <<"clients/client1">>),
@@ -166,14 +185,13 @@ acl_cache_cleanup(_) ->
     %% now the cache is full and the newest one - "clients/client1"
     %%  should be expired, so we'll empty the cache before putting
     %%  the next cache entry
-    deny = ?AC:check_acl(SelfUser, subscribe, <<"#">>),
+    deny = ?AC:check_acl(Client, subscribe, <<"#">>),
 
     not_found = ?CACHE:get_acl_cache(subscribe, <<"users/testuser/1">>),
     not_found = ?CACHE:get_acl_cache(subscribe, <<"clients/client1">>),
-    deny = ?CACHE:get_acl_cache(subscribe, <<"#">>),
-    ok.
+    deny = ?CACHE:get_acl_cache(subscribe, <<"#">>).
 
-put_get_del_cache(_) ->
+t_put_get_del_cache(_) ->
     application:set_env(emqx, acl_cache_ttl, 300000),
     application:set_env(emqx, acl_cache_max_size, 30),
 
@@ -188,7 +206,7 @@ put_get_del_cache(_) ->
     2 = ?CACHE:get_cache_size(),
     ?assertEqual(?CACHE:cache_k(subscribe, <<"b">>), ?CACHE:get_newest_key()).
 
-cache_expiry(_) ->
+t_cache_expiry(_) ->
     application:set_env(emqx, acl_cache_ttl, 100),
     application:set_env(emqx, acl_cache_max_size, 30),
     ok = ?CACHE:put_acl_cache(subscribe, <<"a">>, allow),
@@ -203,7 +221,7 @@ cache_expiry(_) ->
     ct:sleep(150),
     not_found = ?CACHE:get_acl_cache(subscribe, <<"a">>).
 
-cache_update(_) ->
+t_cache_update(_) ->
     application:set_env(emqx, acl_cache_ttl, 300000),
     application:set_env(emqx, acl_cache_max_size, 30),
     [] = ?CACHE:dump_acl_cache(),
@@ -222,7 +240,7 @@ cache_update(_) ->
     ?assertEqual(?CACHE:cache_k(publish, <<"b">>), ?CACHE:get_newest_key()),
     ?assertEqual(?CACHE:cache_k(subscribe, <<"a">>), ?CACHE:get_oldest_key()).
 
-cache_replacement(_) ->
+t_cache_replacement(_) ->
     application:set_env(emqx, acl_cache_ttl, 300000),
     application:set_env(emqx, acl_cache_max_size, 3),
     ok = ?CACHE:put_acl_cache(subscribe, <<"a">>, allow),
@@ -248,7 +266,7 @@ cache_replacement(_) ->
     not_found = ?CACHE:get_acl_cache(publish, <<"b">>),
     allow = ?CACHE:get_acl_cache(publish, <<"c">>).
 
-cache_cleanup(_) ->
+t_cache_cleanup(_) ->
     application:set_env(emqx, acl_cache_ttl, 100),
     application:set_env(emqx, acl_cache_max_size, 30),
     ok = ?CACHE:put_acl_cache(subscribe, <<"a">>, allow),
@@ -261,7 +279,7 @@ cache_cleanup(_) ->
     ?assertEqual(?CACHE:cache_k(publish, <<"c">>), ?CACHE:get_oldest_key()),
     1 = ?CACHE:get_cache_size().
 
-cache_auto_emtpy(_) ->
+t_cache_auto_emtpy(_) ->
     %% verify cache is emptied when cache full and even the newest
     %%   one is expired.
     application:set_env(emqx, acl_cache_ttl, 100),
@@ -275,7 +293,7 @@ cache_auto_emtpy(_) ->
     ok = ?CACHE:put_acl_cache(subscribe, <<"d">>, deny),
     1 = ?CACHE:get_cache_size().
 
-cache_auto_cleanup(_) ->
+t_cache_auto_cleanup(_) ->
     %% verify we'll cleanup expired entries when we got a exipired acl
     %%   from cache.
     application:set_env(emqx, acl_cache_ttl, 100),
@@ -299,7 +317,7 @@ cache_auto_cleanup(_) ->
 %% emqx_access_rule
 %%--------------------------------------------------------------------
 
-compile_rule(_) ->
+t_compile_rule(_) ->
     {allow, {'and', [{ipaddr, {{127,0,0,1}, {127,0,0,1}, 32}},
                      {user, <<"user">>}]}, subscribe, [ [<<"$SYS">>, '#'], ['#'] ]} =
         compile({allow, {'and', [{ipaddr, "127.0.0.1"}, {user, <<"user">>}]}, subscribe, ["$SYS/#", "#"]}),
@@ -324,23 +342,36 @@ compile_rule(_) ->
     {allow, all} = compile({allow, all}),
     {deny, all} = compile({deny, all}).
 
-match_rule(_) ->
-    User = #{client_id => <<"testClient">>, username => <<"TestUser">>, peername => {{127,0,0,1}, 2948}, zone => external},
-    User2 = #{client_id => <<"testClient">>, username => <<"TestUser">>, peername => {{192,168,0,10}, 3028}, zone => external},
-
-    {matched, allow} = match(User, <<"Test/Topic">>, {allow, all}),
-    {matched, deny} = match(User, <<"Test/Topic">>, {deny, all}),
-    {matched, allow} = match(User, <<"Test/Topic">>, compile({allow, {ipaddr, "127.0.0.1"}, subscribe, ["$SYS/#", "#"]})),
-    {matched, allow} = match(User2, <<"Test/Topic">>, compile({allow, {ipaddr, "192.168.0.1/24"}, subscribe, ["$SYS/#", "#"]})),
-    {matched, allow} = match(User, <<"d/e/f/x">>, compile({allow, {user, "TestUser"}, subscribe, ["a/b/c", "d/e/f/#"]})),
-    nomatch = match(User, <<"d/e/f/x">>, compile({allow, {user, "admin"}, pubsub, ["d/e/f/#"]})),
-    {matched, allow} = match(User, <<"testTopics/testClient">>, compile({allow, {client, "testClient"}, publish, ["testTopics/testClient"]})),
-    {matched, allow} = match(User, <<"clients/testClient">>, compile({allow, all, pubsub, ["clients/%c"]})),
-    {matched, allow} = match(#{username => <<"user2">>}, <<"users/user2/abc/def">>, compile({allow, all, subscribe, ["users/%u/#"]})),
-    {matched, deny} = match(User, <<"d/e/f">>, compile({deny, all, subscribe, ["$SYS/#", "#"]})),
+t_match_rule(_) ->
+    Client1 = #{zone => external,
+                client_id => <<"testClient">>,
+                username => <<"TestUser">>,
+                peername => {{127,0,0,1}, 2948}
+               },
+    Client2 = #{zone => external,
+                client_id => <<"testClient">>,
+                username => <<"TestUser">>,
+                peername => {{192,168,0,10}, 3028}
+               },
+    {matched, allow} = match(Client1, <<"Test/Topic">>, {allow, all}),
+    {matched, deny} = match(Client1, <<"Test/Topic">>, {deny, all}),
+    {matched, allow} = match(Client1, <<"Test/Topic">>,
+                             compile({allow, {ipaddr, "127.0.0.1"}, subscribe, ["$SYS/#", "#"]})),
+    {matched, allow} = match(Client2, <<"Test/Topic">>,
+                             compile({allow, {ipaddr, "192.168.0.1/24"}, subscribe, ["$SYS/#", "#"]})),
+    {matched, allow} = match(Client1, <<"d/e/f/x">>,
+                             compile({allow, {user, "TestUser"}, subscribe, ["a/b/c", "d/e/f/#"]})),
+    nomatch = match(Client1, <<"d/e/f/x">>, compile({allow, {user, "admin"}, pubsub, ["d/e/f/#"]})),
+    {matched, allow} = match(Client1, <<"testTopics/testClient">>,
+                             compile({allow, {client, "testClient"}, publish, ["testTopics/testClient"]})),
+    {matched, allow} = match(Client1, <<"clients/testClient">>, compile({allow, all, pubsub, ["clients/%c"]})),
+    {matched, allow} = match(#{username => <<"user2">>}, <<"users/user2/abc/def">>,
+                             compile({allow, all, subscribe, ["users/%u/#"]})),
+    {matched, deny} = match(Client1, <<"d/e/f">>, compile({deny, all, subscribe, ["$SYS/#", "#"]})),
     Rule = compile({allow, {'and', [{ipaddr, "127.0.0.1"}, {user, <<"WrongUser">>}]}, publish, <<"Topic">>}),
-    nomatch = match(User, <<"Topic">>, Rule),
+    nomatch = match(Client1, <<"Topic">>, Rule),
     AndRule = compile({allow, {'and', [{ipaddr, "127.0.0.1"}, {user, <<"TestUser">>}]}, publish, <<"Topic">>}),
-    {matched, allow} = match(User, <<"Topic">>, AndRule),
+    {matched, allow} = match(Client1, <<"Topic">>, AndRule),
     OrRule = compile({allow, {'or', [{ipaddr, "127.0.0.1"}, {user, <<"WrongUser">>}]}, publish, ["Topic"]}),
-    {matched, allow} = match(User, <<"Topic">>, OrRule).
+    {matched, allow} = match(Client1, <<"Topic">>, OrRule).
+

+ 5 - 1
test/emqx_acl_test_mod.erl

@@ -17,7 +17,11 @@
 -module(emqx_acl_test_mod).
 
 %% ACL callbacks
--export([init/1, check_acl/2, reload_acl/1, description/0]).
+-export([ init/1
+        , check_acl/2
+        , reload_acl/1
+        , description/0
+        ]).
 
 init(AclOpts) ->
     {ok, AclOpts}.

+ 0 - 110
test/emqx_alarm_handler_SUITE.erl

@@ -1,110 +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_alarm_handler_SUITE).
-
--compile(export_all).
--compile(nowarn_export_all).
-
--include_lib("eunit/include/eunit.hrl").
-
--include_lib("common_test/include/ct.hrl").
-
--include("emqx_mqtt.hrl").
--include("emqx.hrl").
-
-all() -> [t_alarm_handler].
-
-init_per_suite(Config) ->
-    emqx_ct_helpers:start_apps([], fun set_special_configs/1),
-    Config.
-
-end_per_suite(_Config) ->
-    emqx_ct_helpers:stop_apps([]).
-
-set_special_configs(emqx) ->
-    application:set_env(emqx, acl_file, emqx_ct_helpers:deps_path(emqx, "test/emqx_access_SUITE_data/acl_deny_action.conf"));
-set_special_configs(_App) ->
-    ok.
-
-with_connection(DoFun) ->
-    {ok, Sock} = emqx_client_sock:connect({127, 0, 0, 1}, 1883,
-                                          [binary, {packet, raw}, {active, false}],
-                                          3000),
-    try
-        DoFun(Sock)
-    after
-        emqx_client_sock:close(Sock)
-    end.
-
-t_alarm_handler(_) ->
-    with_connection(
-        fun(Sock) ->
-            emqx_client_sock:send(Sock,
-                                  raw_send_serialize(
-                                      ?CONNECT_PACKET(
-                                          #mqtt_packet_connect{
-                                          proto_ver  = ?MQTT_PROTO_V5}),
-                                      #{version => ?MQTT_PROTO_V5}
-                                  )),
-            {ok, Data} = gen_tcp:recv(Sock, 0),
-            {ok, ?CONNACK_PACKET(?RC_SUCCESS), <<>>, _} = raw_recv_parse(Data, ?MQTT_PROTO_V5),
-
-            Topic1 = emqx_topic:systop(<<"alarms/alert">>),
-            Topic2 = emqx_topic:systop(<<"alarms/clear">>),
-            SubOpts = #{rh => 1, qos => ?QOS_2, rap => 0, nl => 0, rc => 0},
-            emqx_client_sock:send(Sock,
-                                  raw_send_serialize(
-                                      ?SUBSCRIBE_PACKET(
-                                          1,
-                                          [{Topic1, SubOpts},
-                                           {Topic2, SubOpts}]),
-                                      #{version => ?MQTT_PROTO_V5})),
-
-            {ok, Data2} = gen_tcp:recv(Sock, 0),
-            {ok, ?SUBACK_PACKET(1, #{}, [2, 2]), <<>>, _} = raw_recv_parse(Data2, ?MQTT_PROTO_V5),
-
-            alarm_handler:set_alarm({alarm_for_test, #alarm{id = alarm_for_test,
-                                                            severity = error,
-                                                            title="alarm title",
-                                                            summary="alarm summary"}}),
-
-            {ok, Data3} = gen_tcp:recv(Sock, 0),
-
-            {ok, ?PUBLISH_PACKET(?QOS_0, Topic1, _, _), <<>>, _} = raw_recv_parse(Data3, ?MQTT_PROTO_V5),
-
-            ?assertEqual(true, lists:keymember(alarm_for_test, 1, emqx_alarm_handler:get_alarms())),
-
-            alarm_handler:clear_alarm(alarm_for_test),
-
-            {ok, Data4} = gen_tcp:recv(Sock, 0),
-
-            {ok, ?PUBLISH_PACKET(?QOS_0, Topic2, _, _), <<>>, _} = raw_recv_parse(Data4, ?MQTT_PROTO_V5),
-
-            ?assertEqual(false, lists:keymember(alarm_for_test, 1, emqx_alarm_handler:get_alarms()))
-
-        end).
-
-raw_send_serialize(Packet) ->
-    emqx_frame:serialize(Packet).
-
-raw_send_serialize(Packet, Opts) ->
-    emqx_frame:serialize(Packet, Opts).
-
-raw_recv_parse(Bin, ProtoVer) ->
-    emqx_frame:parse(Bin, {none, #{max_size => ?MAX_PACKET_SIZE,
-                                   version  => ProtoVer}}).
-

+ 0 - 29
test/emqx_auth_anonymous_test_mod.erl

@@ -1,29 +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_auth_anonymous_test_mod).
-
-%% ACL callbacks
--export([init/1, check/3, description/0]).
-
-init(AclOpts) ->
-    {ok, AclOpts}.
-
-check(_Client, _Password, _Opts) ->
-    allow.
-
-description() ->
-    "Test emqx_auth_anonymous Mod".

+ 0 - 30
test/emqx_auth_dashboard.erl

@@ -1,30 +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_auth_dashboard).
-
-%% Auth callbacks
--export([init/1, check/3, description/0]).
-
-init(Opts) ->
-    {ok, Opts}.
-
-check(_Client, _Password, _Opts) ->
-    allow.
-
-description() ->
-    "Test Auth Mod".
-

+ 52 - 24
test/emqx_banned_SUITE.erl

@@ -20,35 +20,63 @@
 -compile(nowarn_export_all).
 
 -include("emqx.hrl").
--include("emqx_mqtt.hrl").
 -include_lib("eunit/include/eunit.hrl").
 
-all() -> [t_banned_all].
+all() -> emqx_ct:all(?MODULE).
 
-t_banned_all(_) ->
-    emqx_ct_helpers:start_apps([]),
-    emqx_banned:start_link(),
-    TimeNow = erlang:system_time(second),
+init_per_suite(Config) ->
+    application:load(emqx),
+    ok = ekka:start(),
+    Config.
+
+end_per_suite(_Config) ->
+    ekka:stop(),
+    ekka_mnesia:ensure_stopped(),
+    ekka_mnesia:delete_schema().
+
+t_add_delete(_) ->
     Banned = #banned{who = {client_id, <<"TestClient">>},
                      reason = <<"test">>,
                      by = <<"banned suite">>,
                      desc = <<"test">>,
-                     until = TimeNow + 1},
-    ok = emqx_banned:add(Banned),
-    % here is not expire banned test because its check interval is greater than 5 mins, but its effect has been confirmed
-    ?assert(emqx_banned:check(#{client_id => <<"TestClient">>,
-                                username => undefined,
-                                peername => {undefined, undefined}})),
-    timer:sleep(2500),
-    ?assertNot(emqx_banned:check(#{client_id => <<"TestClient">>,
-                                   username => undefined,
-                                   peername => {undefined, undefined}})),
+                     until = erlang:system_time(second) + 1000
+                    },
     ok = emqx_banned:add(Banned),
-    ?assert(emqx_banned:check(#{client_id => <<"TestClient">>,
-                                username => undefined,
-                                peername => {undefined, undefined}})),
-    emqx_banned:delete({client_id, <<"TestClient">>}),
-    ?assertNot(emqx_banned:check(#{client_id => <<"TestClient">>,
-                                   username => undefined,
-                                   peername => {undefined, undefined}})),
-    emqx_ct_helpers:stop_apps([]).
+    ?assertEqual(1, emqx_banned:info(size)),
+    ok = emqx_banned:delete({client_id, <<"TestClient">>}),
+    ?assertEqual(0, emqx_banned:info(size)).
+
+t_check(_) ->
+    ok = emqx_banned:add(#banned{who = {client_id, <<"BannedClient">>}}),
+    ok = emqx_banned:add(#banned{who = {username, <<"BannedUser">>}}),
+    ok = emqx_banned:add(#banned{who = {ipaddr, {192,168,0,1}}}),
+    ?assertEqual(3, emqx_banned:info(size)),
+    Client1 = #{client_id => <<"BannedClient">>,
+                username => <<"user">>,
+                peername => {{127,0,0,1}, 5000}
+               },
+    Client2 = #{client_id => <<"client">>,
+                username => <<"BannedUser">>,
+                peername => {{127,0,0,1}, 5000}
+               },
+    Client3 = #{client_id => <<"client">>,
+                username => <<"user">>,
+                peername => {{192,168,0,1}, 5000}
+               },
+    Client4 = #{client_id => <<"client">>,
+                username => <<"user">>,
+                peername => {{127,0,0,1}, 5000}
+               },
+    ?assert(emqx_banned:check(Client1)),
+    ?assert(emqx_banned:check(Client2)),
+    ?assert(emqx_banned:check(Client3)),
+    ?assertNot(emqx_banned:check(Client4)),
+    ok = emqx_banned:delete({client_id, <<"BannedClient">>}),
+    ok = emqx_banned:delete({username, <<"BannedUser">>}),
+    ok = emqx_banned:delete({ipaddr, {192,168,0,1}}),
+    ?assertNot(emqx_banned:check(Client1)),
+    ?assertNot(emqx_banned:check(Client2)),
+    ?assertNot(emqx_banned:check(Client3)),
+    ?assertNot(emqx_banned:check(Client4)),
+    ?assertEqual(0, emqx_banned:info(size)).
+

+ 11 - 6
test/emqx_batch_SUITE.erl

@@ -21,11 +21,13 @@
 
 -include_lib("eunit/include/eunit.hrl").
 
-all() ->
-    [batch_full_commit, batch_linger_commit].
+all() -> emqx_ct:all(?MODULE).
 
-batch_full_commit(_) ->
-    B0 = emqx_batch:init(#{batch_size => 3, linger_ms => 2000, commit_fun => fun(_) -> ok end}),
+t_batch_full_commit(_) ->
+    B0 = emqx_batch:init(#{batch_size => 3,
+                           linger_ms => 2000,
+                           commit_fun => fun(_) -> ok end
+                          }),
     B3 = lists:foldl(fun(E, B) -> emqx_batch:push(E, B) end, B0, [a, b, c]),
     ?assertEqual(3, emqx_batch:size(B3)),
     ?assertEqual([a, b, c], emqx_batch:items(B3)),
@@ -34,9 +36,12 @@ batch_full_commit(_) ->
     ?assertEqual(0, emqx_batch:size(B4)),
     ?assertEqual([], emqx_batch:items(B4)).
 
-batch_linger_commit(_) ->
+t_batch_linger_commit(_) ->
     CommitFun = fun(Q) -> ?assertEqual(3, length(Q)) end,
-    B0 = emqx_batch:init(#{batch_size => 3, linger_ms => 500, commit_fun => CommitFun}),
+    B0 = emqx_batch:init(#{batch_size => 3,
+                           linger_ms => 500,
+                           commit_fun => CommitFun
+                          }),
     B3 = lists:foldl(fun(E, B) -> emqx_batch:push(E, B) end, B0, [a, b, c]),
     ?assertEqual(3, emqx_batch:size(B3)),
     ?assertEqual([a, b, c], emqx_batch:items(B3)),

+ 61 - 73
test/emqx_broker_SUITE.erl

@@ -29,19 +29,24 @@
 
 all() ->
     [{group, pubsub},
-     {group, session},
      {group, metrics},
      {group, stats}].
 
 groups() ->
-    [{pubsub, [sequence], [subscribe_unsubscribe,
-                           publish, pubsub,
-                           t_shared_subscribe,
-                           dispatch_with_no_sub,
-                           'pubsub#', 'pubsub+']},
-     {session, [sequence], [start_session]},
-     {metrics, [sequence], [inc_dec_metric]},
-     {stats, [sequence], [set_get_stat]}].
+    [{pubsub, [sequence],
+      [t_sub_unsub,
+       t_publish,
+       t_pubsub,
+       t_shared_subscribe,
+       t_dispatch_with_no_sub,
+       't_pubsub#',
+       't_pubsub+'
+      ]},
+     {metrics, [sequence],
+      [inc_dec_metric]},
+     {stats, [sequence],
+      [set_get_stat]
+     }].
 
 init_per_suite(Config) ->
     emqx_ct_helpers:start_apps([]),
@@ -54,47 +59,48 @@ end_per_suite(_Config) ->
 %% PubSub Test
 %%--------------------------------------------------------------------
 
-subscribe_unsubscribe(_) ->
-    ok = emqx:subscribe(<<"topic">>, <<"clientId">>),
-    ok = emqx:subscribe(<<"topic/1">>, <<"clientId">>, #{ qos => 1 }),
-    ok = emqx:subscribe(<<"topic/2">>, <<"clientId">>, #{ qos => 2 }),
-    true = emqx:subscribed(<<"clientId">>, <<"topic">>),
-    Topics = emqx:topics(),
+t_sub_unsub(_) ->
+    ok = emqx_broker:subscribe(<<"topic">>, <<"clientId">>),
+    ok = emqx_broker:subscribe(<<"topic/1">>, <<"clientId">>, #{qos => 1}),
+    ok = emqx_broker:subscribe(<<"topic/2">>, <<"clientId">>, #{qos => 2}),
+    true = emqx_broker:subscribed(<<"clientId">>, <<"topic">>),
+    Topics = emqx_broker:topics(),
     lists:foreach(fun(Topic) ->
                       ?assert(lists:member(Topic, Topics))
                   end, Topics),
-    ok = emqx:unsubscribe(<<"topic">>),
-    ok = emqx:unsubscribe(<<"topic/1">>),
-    ok = emqx:unsubscribe(<<"topic/2">>).
+    ok = emqx_broker:unsubscribe(<<"topic">>),
+    ok = emqx_broker:unsubscribe(<<"topic/1">>),
+    ok = emqx_broker:unsubscribe(<<"topic/2">>).
 
-publish(_) ->
+t_publish(_) ->
     Msg = emqx_message:make(ct, <<"test/pubsub">>, <<"hello">>),
-    ok = emqx:subscribe(<<"test/+">>),
+    ok = emqx_broker:subscribe(<<"test/+">>),
     timer:sleep(10),
-    emqx:publish(Msg),
-    ?assert(receive {dispatch, <<"test/+">>, #message{payload = <<"hello">>}} -> true after 100 -> false end).
+    emqx_broker:publish(Msg),
+    ?assert(receive {deliver, <<"test/+">>, #message{payload = <<"hello">>}} -> true after 100 -> false end).
 
-dispatch_with_no_sub(_) ->
+t_dispatch_with_no_sub(_) ->
     Msg = emqx_message:make(ct, <<"no_subscribers">>, <<"hello">>),
     Delivery = #delivery{sender = self(), message = Msg, results = []},
     ?assertEqual(Delivery, emqx_broker:route([{<<"no_subscribers">>, node()}], Delivery)).
 
-pubsub(_) ->
+t_pubsub(_) ->
     true = emqx:is_running(node()),
     Self = self(),
     Subscriber = <<"clientId">>,
-    ok = emqx:subscribe(<<"a/b/c">>, Subscriber, #{ qos => 1 }),
+    ok = emqx_broker:subscribe(<<"a/b/c">>, Subscriber, #{ qos => 1 }),
     #{qos := 1} = ets:lookup_element(emqx_suboption, {Self, <<"a/b/c">>}, 2),
     #{qos := 1} = emqx_broker:get_subopts(Subscriber, <<"a/b/c">>),
     true = emqx_broker:set_subopts(<<"a/b/c">>, #{qos => 0}),
     #{qos := 0} = emqx_broker:get_subopts(Subscriber, <<"a/b/c">>),
-    ok = emqx:subscribe(<<"a/b/c">>, Subscriber, #{ qos => 2 }),
+    ok = emqx_broker:subscribe(<<"a/b/c">>, Subscriber, #{ qos => 2 }),
     %% ct:log("Emq Sub: ~p.~n", [ets:lookup(emqx_suboption, {<<"a/b/c">>, Subscriber})]),
     timer:sleep(10),
     [Self] = emqx_broker:subscribers(<<"a/b/c">>),
-    emqx:publish(emqx_message:make(ct, <<"a/b/c">>, <<"hello">>)),
+    emqx_broker:publish(
+      emqx_message:make(ct, <<"a/b/c">>, <<"hello">>)),
     ?assert(
-        receive {dispatch, <<"a/b/c">>, _ } ->
+        receive {deliver, <<"a/b/c">>, _ } ->
                 true;
             P ->
                 ct:log("Receive Message: ~p~n",[P])
@@ -102,62 +108,43 @@ pubsub(_) ->
             false
         end),
     spawn(fun() ->
-            emqx:subscribe(<<"a/b/c">>),
-            emqx:subscribe(<<"c/d/e">>),
+            emqx_broker:subscribe(<<"a/b/c">>),
+            emqx_broker:subscribe(<<"c/d/e">>),
             timer:sleep(10),
-            emqx:unsubscribe(<<"a/b/c">>)
+            emqx_broker:unsubscribe(<<"a/b/c">>)
           end),
     timer:sleep(20),
-    emqx:unsubscribe(<<"a/b/c">>).
+    emqx_broker:unsubscribe(<<"a/b/c">>).
 
 t_shared_subscribe(_) ->
-    emqx:subscribe("$share/group2/topic2"),
-    emqx:subscribe("$queue/topic3"),
+    emqx_broker:subscribe(<<"$share/group2/topic2">>),
+    emqx_broker:subscribe(<<"$queue/topic3">>),
     timer:sleep(10),
-    ct:log("share subscriptions: ~p~n", [emqx:subscriptions(self())]),
-    ?assertEqual(2, length(emqx:subscriptions(self()))),
-    emqx:unsubscribe("$share/group2/topic2"),
-    emqx:unsubscribe("$queue/topic3"),
-    ?assertEqual(0, length(emqx:subscriptions(self()))).
-
-'pubsub#'(_) ->
-    emqx:subscribe(<<"a/#">>),
+    ct:pal("Share subscriptions: ~p",
+           [emqx_broker:subscriptions(self())]),
+    ?assertEqual(2, length(emqx_broker:subscriptions(self()))),
+    emqx_broker:unsubscribe(<<"$share/group2/topic2">>),
+    emqx_broker:unsubscribe(<<"$queue/topic3">>),
+    ?assertEqual(0, length(emqx_broker:subscriptions(self()))).
+
+'t_pubsub#'(_) ->
+    emqx_broker:subscribe(<<"a/#">>),
     timer:sleep(10),
-    emqx:publish(emqx_message:make(ct, <<"a/b/c">>, <<"hello">>)),
-    ?assert(receive {dispatch, <<"a/#">>, _} -> true after 100 -> false end),
-    emqx:unsubscribe(<<"a/#">>).
+    emqx_broker:publish(emqx_message:make(ct, <<"a/b/c">>, <<"hello">>)),
+    ?assert(receive {deliver, <<"a/#">>, _} -> true after 100 -> false end),
+    emqx_broker:unsubscribe(<<"a/#">>).
 
-'pubsub+'(_) ->
-    emqx:subscribe(<<"a/+/+">>),
-    timer:sleep(10),
-    emqx:publish(emqx_message:make(ct, <<"a/b/c">>, <<"hello">>)),
-    ?assert(receive {dispatch, <<"a/+/+">>, _} -> true after 100 -> false end),
-    emqx:unsubscribe(<<"a/+/+">>).
-
-%%--------------------------------------------------------------------
-%% Session Group
-%%--------------------------------------------------------------------
-start_session(_) ->
-    ClientId = <<"clientId">>,
-    {ok, ClientPid} = emqx_mock_client:start_link(ClientId),
-    {ok, SessPid} = emqx_mock_client:open_session(ClientPid, ClientId, internal),
-    Message1 = emqx_message:make(<<"clientId">>, 2, <<"topic">>, <<"hello">>),
-    emqx_session:publish(SessPid, 1, Message1),
-    emqx_session:pubrel(SessPid, 2, reasoncode),
-    emqx_session:subscribe(SessPid, [{<<"topic/session">>, #{qos => 2}}]),
-    Message2 = emqx_message:make(<<"clientId">>, 1, <<"topic/session">>, <<"test">>),
-    emqx_session:publish(SessPid, 3, Message2),
-    emqx_session:unsubscribe(SessPid, [{<<"topic/session">>, []}]),
-    %% emqx_mock_client:stop(ClientPid).
-    emqx_mock_client:close_session(ClientPid).
-
-%%--------------------------------------------------------------------
-%% Broker Group
-%%--------------------------------------------------------------------
+'t_pubsub+'(_) ->
+    emqx_broker:subscribe(<<"a/+/+">>),
+    timer:sleep(10), %% TODO: why sleep?
+    emqx_broker:publish(emqx_message:make(ct, <<"a/b/c">>, <<"hello">>)),
+    ?assert(receive {deliver, <<"a/+/+">>, _} -> true after 100 -> false end),
+    emqx_broker:unsubscribe(<<"a/+/+">>).
 
 %%--------------------------------------------------------------------
 %% Metric Group
 %%--------------------------------------------------------------------
+
 inc_dec_metric(_) ->
     emqx_metrics:inc('messages.retained', 10),
     emqx_metrics:dec('messages.retained', 10).
@@ -168,4 +155,5 @@ inc_dec_metric(_) ->
 
 set_get_stat(_) ->
     emqx_stats:setstat('retained.max', 99),
-    99 = emqx_stats:getstat('retained.max').
+    ?assertEqual(99, emqx_stats:getstat('retained.max')).
+

+ 0 - 74
test/emqx_channel_SUITE.erl

@@ -1,74 +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_channel_SUITE).
-
--compile(export_all).
--compile(nowarn_export_all).
-
--include("emqx_mqtt.hrl").
-
--include_lib("eunit/include/eunit.hrl").
-
--include_lib("common_test/include/ct.hrl").
-
-all() ->
-    [t_connect_api].
-
-init_per_suite(Config) ->
-    emqx_ct_helpers:start_apps([]),
-    Config.
-
-end_per_suite(_Config) ->
-    emqx_ct_helpers:stop_apps([]).
-
-t_connect_api(_Config) ->
-    {ok, T1} = emqx_client:start_link([{host, "localhost"},
-                                       {client_id, <<"client1">>},
-                                       {username, <<"testuser1">>},
-                                       {password, <<"pass1">>}]),
-    {ok, _} = emqx_client:connect(T1),
-    CPid = emqx_cm:lookup_conn_pid(<<"client1">>),
-    ConnStats = emqx_channel:stats(CPid),
-    ok = t_stats(ConnStats),
-    ConnAttrs = emqx_channel:attrs(CPid),
-    ok = t_attrs(ConnAttrs),
-    ConnInfo = emqx_channel:info(CPid),
-    ok = t_info(ConnInfo),
-    SessionPid = emqx_channel:session(CPid),
-    true = is_pid(SessionPid),
-    emqx_client:disconnect(T1).
-
-t_info(ConnInfo) ->
-    ?assertEqual(tcp, maps:get(socktype, ConnInfo)),
-    ?assertEqual(running, maps:get(conn_state, ConnInfo)),
-    ?assertEqual(<<"client1">>, maps:get(client_id, ConnInfo)),
-    ?assertEqual(<<"testuser1">>, maps:get(username, ConnInfo)),
-    ?assertEqual(<<"MQTT">>, maps:get(proto_name, ConnInfo)).
-
-t_attrs(AttrsData) ->
-    ?assertEqual(<<"client1">>, maps:get(client_id, AttrsData)),
-    ?assertEqual(emqx_channel, maps:get(conn_mod, AttrsData)),
-    ?assertEqual(<<"testuser1">>, maps:get(username, AttrsData)).
-
-t_stats(StatsData) ->
-    ?assertEqual(true, proplists:get_value(recv_oct, StatsData) >= 0),
-    ?assertEqual(true, proplists:get_value(mailbox_len, StatsData) >= 0),
-    ?assertEqual(true, proplists:get_value(heap_size, StatsData) >= 0),
-    ?assertEqual(true, proplists:get_value(reductions, StatsData) >=0),
-    ?assertEqual(true, proplists:get_value(recv_pkt, StatsData) =:=1),
-    ?assertEqual(true, proplists:get_value(recv_msg, StatsData) >=0),
-    ?assertEqual(true, proplists:get_value(send_pkt, StatsData) =:=1).

+ 0 - 209
test/emqx_client_SUITE.erl

@@ -1,209 +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_client_SUITE).
-
--compile(export_all).
--compile(nowarn_export_all).
-
--import(lists, [nth/2]).
-
--include("emqx_mqtt.hrl").
-
--include_lib("eunit/include/eunit.hrl").
-
--include_lib("common_test/include/ct.hrl").
-
--define(TOPICS, [<<"TopicA">>, <<"TopicA/B">>, <<"Topic/C">>, <<"TopicA/C">>,
-                 <<"/TopicA">>]).
-
--define(WILD_TOPICS, [<<"TopicA/+">>, <<"+/C">>, <<"#">>, <<"/#">>, <<"/+">>,
-                      <<"+/+">>, <<"TopicA/#">>]).
-
-all() ->
-    [{group, mqttv4}].
-
-groups() ->
-    [{mqttv4, [non_parallel_tests],
-      [basic_test,
-       will_message_test,
-       offline_message_queueing_test,
-       overlapping_subscriptions_test,
-       %% keepalive_test,
-       redelivery_on_reconnect_test,
-       %% subscribe_failure_test,
-       dollar_topics_test]}].
-
-init_per_suite(Config) ->
-    emqx_ct_helpers:start_apps([]),
-    Config.
-
-end_per_suite(_Config) ->
-    emqx_ct_helpers:stop_apps([]).
-
-receive_messages(Count) ->
-    receive_messages(Count, []).
-
-receive_messages(0, Msgs) ->
-    Msgs;
-receive_messages(Count, Msgs) ->
-    receive
-        {publish, Msg} ->
-            receive_messages(Count-1, [Msg|Msgs]);
-        _Other ->
-            receive_messages(Count, Msgs)
-    after 100 ->
-        Msgs
-    end.
-
-basic_test(_Config) ->
-    Topic = nth(1, ?TOPICS),
-    ct:print("Basic test starting"),
-    {ok, C} = emqx_client:start_link(),
-    {ok, _} = emqx_client:connect(C),
-    {ok, _, [1]} = emqx_client:subscribe(C, Topic, qos1),
-    {ok, _, [2]} = emqx_client:subscribe(C, Topic, qos2),
-    {ok, _} = emqx_client:publish(C, Topic, <<"qos 2">>, 2),
-    {ok, _} = emqx_client:publish(C, Topic, <<"qos 2">>, 2),
-    {ok, _} = emqx_client:publish(C, Topic, <<"qos 2">>, 2),
-    ?assertEqual(3, length(receive_messages(3))),
-    ok = emqx_client:disconnect(C).
-
-will_message_test(_Config) ->
-    {ok, C1} = emqx_client:start_link([{clean_start, true},
-                                          {will_topic, nth(3, ?TOPICS)},
-                                          {will_payload, <<"client disconnected">>},
-                                          {keepalive, 2}]),
-    {ok, _} = emqx_client:connect(C1),
-
-    {ok, C2} = emqx_client:start_link(),
-    {ok, _} = emqx_client:connect(C2),
-
-    {ok, _, [2]} = emqx_client:subscribe(C2, nth(3, ?TOPICS), 2),
-    timer:sleep(10),
-    ok = emqx_client:stop(C1),
-    timer:sleep(5),
-    ?assertEqual(1, length(receive_messages(1))),
-    ok = emqx_client:disconnect(C2),
-    ct:print("Will message test succeeded").
-
-offline_message_queueing_test(_) ->
-    {ok, C1} = emqx_client:start_link([{clean_start, false},
-                                       {client_id, <<"c1">>}]),
-    {ok, _} = emqx_client:connect(C1),
-
-    {ok, _, [2]} = emqx_client:subscribe(C1, nth(6, ?WILD_TOPICS), 2),
-    ok = emqx_client:disconnect(C1),
-    {ok, C2} = emqx_client:start_link([{clean_start, true},
-                                       {client_id, <<"c2">>}]),
-    {ok, _} = emqx_client:connect(C2),
-
-    ok = emqx_client:publish(C2, nth(2, ?TOPICS), <<"qos 0">>, 0),
-    {ok, _} = emqx_client:publish(C2, nth(3, ?TOPICS), <<"qos 1">>, 1),
-    {ok, _} = emqx_client:publish(C2, nth(4, ?TOPICS), <<"qos 2">>, 2),
-    timer:sleep(10),
-    emqx_client:disconnect(C2),
-    {ok, C3} = emqx_client:start_link([{clean_start, false},
-                                          {client_id, <<"c1">>}]),
-    {ok, _} = emqx_client:connect(C3),
-
-    timer:sleep(10),
-    emqx_client:disconnect(C3),
-    ?assertEqual(3, length(receive_messages(3))).
-
-overlapping_subscriptions_test(_) ->
-    {ok, C} = emqx_client:start_link([]),
-    {ok, _} = emqx_client:connect(C),
-
-    {ok, _, [2, 1]} = emqx_client:subscribe(C, [{nth(7, ?WILD_TOPICS), 2},
-                                                {nth(1, ?WILD_TOPICS), 1}]),
-    timer:sleep(10),
-    {ok, _} = emqx_client:publish(C, nth(4, ?TOPICS), <<"overlapping topic filters">>, 2),
-    timer:sleep(10),
-
-    Num = length(receive_messages(2)),
-    ?assert(lists:member(Num, [1, 2])),
-    if
-        Num == 1 ->
-            ct:print("This server is publishing one message for all
-                     matching overlapping subscriptions, not one for each.");
-        Num == 2 ->
-            ct:print("This server is publishing one message per each
-                     matching overlapping subscription.");
-        true -> ok
-    end,
-    emqx_client:disconnect(C).
-
-%% keepalive_test(_) ->
-%%     ct:print("Keepalive test starting"),
-%%     {ok, C1, _} = emqx_client:start_link([{clean_start, true},
-%%                                           {keepalive, 5},
-%%                                           {will_flag, true},
-%%                                           {will_topic, nth(5, ?TOPICS)},
-%%                                           %% {will_qos, 2},
-%%                                           {will_payload, <<"keepalive expiry">>}]),
-%%     ok = emqx_client:pause(C1),
-%%     {ok, C2, _} = emqx_client:start_link([{clean_start, true},
-%%                                           {keepalive, 0}]),
-%%     {ok, _, [2]} = emqx_client:subscribe(C2, nth(5, ?TOPICS), 2),
-%%     ok = emqx_client:disconnect(C2),
-%%     ?assertEqual(1, length(receive_messages(1))),
-%%     ct:print("Keepalive test succeeded").
-
-redelivery_on_reconnect_test(_) ->
-    ct:print("Redelivery on reconnect test starting"),
-    {ok, C1} = emqx_client:start_link([{clean_start, false},
-                                       {client_id, <<"c">>}]),
-    {ok, _} = emqx_client:connect(C1),
-
-    {ok, _, [2]} = emqx_client:subscribe(C1, nth(7, ?WILD_TOPICS), 2),
-    timer:sleep(10),
-    ok = emqx_client:pause(C1),
-    {ok, _} = emqx_client:publish(C1, nth(2, ?TOPICS), <<>>,
-                                  [{qos, 1}, {retain, false}]),
-    {ok, _} = emqx_client:publish(C1, nth(4, ?TOPICS), <<>>,
-                                  [{qos, 2}, {retain, false}]),
-    timer:sleep(10),
-    ok = emqx_client:disconnect(C1),
-    ?assertEqual(0, length(receive_messages(2))),
-    {ok, C2} = emqx_client:start_link([{clean_start, false},
-                                          {client_id, <<"c">>}]),
-    {ok, _} = emqx_client:connect(C2),
-
-    timer:sleep(10),
-    ok = emqx_client:disconnect(C2),
-    ?assertEqual(2, length(receive_messages(2))).
-
-%% subscribe_failure_test(_) ->
-%%     ct:print("Subscribe failure test starting"),
-%%     {ok, C, _} = emqx_client:start_link([]),
-%%     {ok, _, [2]} = emqx_client:subscribe(C, <<"$SYS/#">>, 2),
-%%     timer:sleep(10),
-%%     ct:print("Subscribe failure test succeeded").
-
-dollar_topics_test(_) ->
-    ct:print("$ topics test starting"),
-    {ok, C} = emqx_client:start_link([{clean_start, true},
-                                      {keepalive, 0}]),
-    {ok, _} = emqx_client:connect(C),
-
-    {ok, _, [1]} = emqx_client:subscribe(C, nth(6, ?WILD_TOPICS), 1),
-    {ok, _} = emqx_client:publish(C, << <<"$">>/binary, (nth(2, ?TOPICS))/binary>>,
-                                  <<"test">>, [{qos, 1}, {retain, false}]),
-    timer:sleep(10),
-    ?assertEqual(0, length(receive_messages(1))),
-    ok = emqx_client:disconnect(C),
-    ct:print("$ topics test succeeded").

+ 0 - 71
test/emqx_cm_SUITE.erl

@@ -1,71 +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_cm_SUITE).
-
--compile(export_all).
--compile(nowarn_export_all).
-
--include("emqx.hrl").
--include("emqx_mqtt.hrl").
--include_lib("eunit/include/eunit.hrl").
-
-all() -> [{group, cm}].
-
-groups() ->
-    [{cm, [non_parallel_tests],
-      [t_get_set_conn_attrs,
-       t_get_set_conn_stats,
-       t_lookup_conn_pid]}].
-
-init_per_suite(Config) ->
-    emqx_ct_helpers:start_apps([]),
-    Config.
-
-end_per_suite(_Config) ->
-    emqx_ct_helpers:stop_apps([]).
-
-init_per_testcase(_TestCase, Config) ->
-    register_connection(),
-    Config.
-
-end_per_testcase(_TestCase, _Config) ->
-    unregister_connection(),
-    ok.
-
-t_get_set_conn_attrs(_) ->
-    ?assert(emqx_cm:set_conn_attrs(<<"conn1">>, [{port, 8080}, {ip, "192.168.0.1"}])),
-    ?assert(emqx_cm:set_conn_attrs(<<"conn2">>, self(), [{port, 8080}, {ip, "192.168.0.2"}])),
-    ?assertEqual([{port, 8080}, {ip, "192.168.0.1"}], emqx_cm:get_conn_attrs(<<"conn1">>)),
-    ?assertEqual([{port, 8080}, {ip, "192.168.0.2"}], emqx_cm:get_conn_attrs(<<"conn2">>, self())).
-
-t_get_set_conn_stats(_) ->
-    ?assert(emqx_cm:set_conn_stats(<<"conn1">>, [{count, 1}, {max, 2}])),
-    ?assert(emqx_cm:set_conn_stats(<<"conn2">>, self(), [{count, 1}, {max, 2}])),
-    ?assertEqual([{count, 1}, {max, 2}], emqx_cm:get_conn_stats(<<"conn1">>)),
-    ?assertEqual([{count, 1}, {max, 2}], emqx_cm:get_conn_stats(<<"conn2">>, self())).
-
-t_lookup_conn_pid(_) ->
-    ?assertEqual(ok, emqx_cm:register_connection(<<"conn1">>, self())),
-    ?assertEqual(self(), emqx_cm:lookup_conn_pid(<<"conn1">>)).
-
-register_connection() ->
-    ?assertEqual(ok, emqx_cm:register_connection(<<"conn1">>)),
-    ?assertEqual(ok, emqx_cm:register_connection(<<"conn2">>, self())).
-
-unregister_connection() ->
-    ?assertEqual(ok, emqx_cm:unregister_connection(<<"conn1">>)),
-    ?assertEqual(ok, emqx_cm:unregister_connection(<<"conn2">>, self())).

+ 0 - 62
test/emqx_flapping_SUITE.erl

@@ -1,62 +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_flapping_SUITE).
-
--compile(export_all).
--compile(nowarn_export_all).
-
--include("emqx.hrl").
-
--include_lib("common_test/include/ct.hrl").
--include_lib("eunit/include/eunit.hrl").
-
-all() ->
-    [t_flapping].
-
-init_per_suite(Config) ->
-    emqx_ct_helpers:start_apps([]),
-    prepare_for_test(),
-    Config.
-
-end_per_suite(_Config) ->
-    emqx_ct_helpers:stop_apps([]).
-
-t_flapping(_Config) ->
-    process_flag(trap_exit, true),
-    flapping_connect(5),
-    {ok, C} = emqx_client:start_link([{client_id, <<"Client">>}]),
-    {error, _} = emqx_client:connect(C),
-    receive
-        {'EXIT', Client, _Reason} ->
-            ct:log("receive exit signal, Client: ~p", [Client])
-    after 1000 ->
-            ct:log("timeout")
-    end.
-
-
-flapping_connect(Times) ->
-    [flapping_connect() || _ <- lists:seq(1, Times)].
-
-flapping_connect() ->
-    {ok, C} = emqx_client:start_link([{client_id, <<"Client">>}]),
-    {ok, _} = emqx_client:connect(C),
-    ok = emqx_client:disconnect(C).
-
-prepare_for_test() ->
-    emqx_zone:set_env(external, enable_flapping_detect, true),
-    emqx_zone:set_env(external, flapping_threshold, {10, 60}),
-    emqx_zone:set_env(external, flapping_expiry_interval, 3600).

+ 71 - 70
test/emqx_frame_SUITE.erl

@@ -37,60 +37,60 @@ all() ->
 
 groups() ->
     [{connect, [parallel],
-      [serialize_parse_connect,
-       serialize_parse_v3_connect,
-       serialize_parse_v4_connect,
-       serialize_parse_v5_connect,
-       serialize_parse_connect_without_clientid,
-       serialize_parse_connect_with_will,
-       serialize_parse_bridge_connect
+      [t_serialize_parse_connect,
+       t_serialize_parse_v3_connect,
+       t_serialize_parse_v4_connect,
+       t_serialize_parse_v5_connect,
+       t_serialize_parse_connect_without_clientid,
+       t_serialize_parse_connect_with_will,
+       t_serialize_parse_bridge_connect
       ]},
      {connack, [parallel],
-      [serialize_parse_connack,
-       serialize_parse_connack_v5
+      [t_serialize_parse_connack,
+       t_serialize_parse_connack_v5
       ]},
      {publish, [parallel],
-      [serialize_parse_qos0_publish,
-       serialize_parse_qos1_publish,
-       serialize_parse_qos2_publish,
-       serialize_parse_publish_v5
+      [t_serialize_parse_qos0_publish,
+       t_serialize_parse_qos1_publish,
+       t_serialize_parse_qos2_publish,
+       t_serialize_parse_publish_v5
       ]},
      {puback, [parallel],
-      [serialize_parse_puback,
-       serialize_parse_puback_v5,
-       serialize_parse_pubrec,
-       serialize_parse_pubrec_v5,
-       serialize_parse_pubrel,
-       serialize_parse_pubrel_v5,
-       serialize_parse_pubcomp,
-       serialize_parse_pubcomp_v5
+      [t_serialize_parse_puback,
+       t_serialize_parse_puback_v5,
+       t_serialize_parse_pubrec,
+       t_serialize_parse_pubrec_v5,
+       t_serialize_parse_pubrel,
+       t_serialize_parse_pubrel_v5,
+       t_serialize_parse_pubcomp,
+       t_serialize_parse_pubcomp_v5
       ]},
      {subscribe, [parallel],
-      [serialize_parse_subscribe,
-       serialize_parse_subscribe_v5
+      [t_serialize_parse_subscribe,
+       t_serialize_parse_subscribe_v5
       ]},
      {suback, [parallel],
-      [serialize_parse_suback,
-       serialize_parse_suback_v5
+      [t_serialize_parse_suback,
+       t_serialize_parse_suback_v5
       ]},
      {unsubscribe, [parallel],
-      [serialize_parse_unsubscribe,
-       serialize_parse_unsubscribe_v5
+      [t_serialize_parse_unsubscribe,
+       t_serialize_parse_unsubscribe_v5
       ]},
      {unsuback, [parallel],
-      [serialize_parse_unsuback,
-       serialize_parse_unsuback_v5
+      [t_serialize_parse_unsuback,
+       t_serialize_parse_unsuback_v5
       ]},
      {ping, [parallel],
-      [serialize_parse_pingreq,
-       serialize_parse_pingresp
+      [t_serialize_parse_pingreq,
+       t_serialize_parse_pingresp
       ]},
      {disconnect, [parallel],
-      [serialize_parse_disconnect,
-       serialize_parse_disconnect_v5
+      [t_serialize_parse_disconnect,
+       t_serialize_parse_disconnect_v5
       ]},
      {auth, [parallel],
-      [serialize_parse_auth_v5]
+      [t_serialize_parse_auth_v5]
      }].
 
 init_per_suite(Config) ->
@@ -105,7 +105,7 @@ init_per_group(_Group, Config) ->
 end_per_group(_Group, _Config) ->
 	ok.
 
-serialize_parse_connect(_) ->
+t_serialize_parse_connect(_) ->
     Packet1 = ?CONNECT_PACKET(#mqtt_packet_connect{}),
     ?assertEqual(Packet1, parse_serialize(Packet1)),
     Packet2 = ?CONNECT_PACKET(#mqtt_packet_connect{
@@ -119,7 +119,7 @@ serialize_parse_connect(_) ->
                                 }),
     ?assertEqual(Packet2, parse_serialize(Packet2)).
 
-serialize_parse_v3_connect(_) ->
+t_serialize_parse_v3_connect(_) ->
     Bin = <<16,37,0,6,77,81,73,115,100,112,3,2,0,60,0,23,109,111,115,
             113,112,117, 98,47,49,48,52,53,49,45,105,77,97,99,46,108,
             111,99,97>>,
@@ -132,7 +132,7 @@ serialize_parse_v3_connect(_) ->
                                     }),
     ?assertMatch({ok, Packet, <<>>, _}, emqx_frame:parse(Bin)).
 
-serialize_parse_v4_connect(_) ->
+t_serialize_parse_v4_connect(_) ->
     Bin = <<16,35,0,4,77,81,84,84,4,2,0,60,0,23,109,111,115,113,112,117,
             98,47,49,48,52,53,49,45,105,77,97,99,46,108,111,99,97>>,
     Packet = ?CONNECT_PACKET(#mqtt_packet_connect{proto_ver   = 4,
@@ -143,7 +143,7 @@ serialize_parse_v4_connect(_) ->
     ?assertEqual(Bin, serialize_to_binary(Packet)),
     ?assertMatch({ok, Packet, <<>>, _}, emqx_frame:parse(Bin)).
 
-serialize_parse_v5_connect(_) ->
+t_serialize_parse_v5_connect(_) ->
     Props = #{'Session-Expiry-Interval'      => 60,
               'Receive-Maximum'              => 100,
               'Maximum-QoS'                  => ?QOS_2,
@@ -183,7 +183,7 @@ serialize_parse_v5_connect(_) ->
                                     }),
     ?assertEqual(Packet, parse_serialize(Packet)).
 
-serialize_parse_connect_without_clientid(_) ->
+t_serialize_parse_connect_without_clientid(_) ->
     Bin = <<16,12,0,4,77,81,84,84,4,2,0,60,0,0>>,
     Packet = ?CONNECT_PACKET(
                 #mqtt_packet_connect{proto_ver   = 4,
@@ -195,7 +195,7 @@ serialize_parse_connect_without_clientid(_) ->
     ?assertEqual(Bin, serialize_to_binary(Packet)),
     ?assertMatch({ok, Packet, <<>>, _}, emqx_frame:parse(Bin)).
 
-serialize_parse_connect_with_will(_) ->
+t_serialize_parse_connect_with_will(_) ->
     Bin = <<16,67,0,6,77,81,73,115,100,112,3,206,0,60,0,23,109,111,115,113,112,
             117,98,47,49,48,52,53,50,45,105,77,97,99,46,108,111,99,97,0,5,47,119,
             105,108,108,0,7,119,105,108,108,109,115,103,0,4,116,101,115,116,0,6,
@@ -217,7 +217,7 @@ serialize_parse_connect_with_will(_) ->
     ?assertEqual(Bin, serialize_to_binary(Packet)),
     ?assertMatch({ok, Packet, <<>>, _}, emqx_frame:parse(Bin)).
 
-serialize_parse_bridge_connect(_) ->
+t_serialize_parse_bridge_connect(_) ->
     Bin = <<16,86,0,6,77,81,73,115,100,112,131,44,0,60,0,19,67,95,48,48,58,48,67,
             58,50,57,58,50,66,58,55,55,58,53,50,0,48,36,83,89,83,47,98,114,111,107,
             101,114,47,99,111,110,110,101,99,116,105,111,110,47,67,95,48,48,58,48,
@@ -239,12 +239,12 @@ serialize_parse_bridge_connect(_) ->
     ?assertEqual(Bin, serialize_to_binary(Packet)),
     ?assertMatch({ok, Packet, <<>>, _}, emqx_frame:parse(Bin)).
 
-serialize_parse_connack(_) ->
+t_serialize_parse_connack(_) ->
     Packet = ?CONNACK_PACKET(?RC_SUCCESS),
     ?assertEqual(<<32,2,0,0>>, serialize_to_binary(Packet)),
     ?assertEqual(Packet, parse_serialize(Packet)).
 
-serialize_parse_connack_v5(_) ->
+t_serialize_parse_connack_v5(_) ->
     Props = #{'Session-Expiry-Interval'            => 60,
               'Receive-Maximum'                    => 100,
               'Maximum-QoS'                        => ?QOS_2,
@@ -265,7 +265,7 @@ serialize_parse_connack_v5(_) ->
     Packet = ?CONNACK_PACKET(?RC_SUCCESS, 0, Props),
     ?assertEqual(Packet, parse_serialize(Packet, #{version => ?MQTT_PROTO_V5})).
 
-serialize_parse_qos0_publish(_) ->
+t_serialize_parse_qos0_publish(_) ->
     Bin = <<48,14,0,7,120,120,120,47,121,121,121,104,101,108,108,111>>,
     Packet = #mqtt_packet{header   = #mqtt_packet_header{type   = ?PUBLISH,
                                                          dup    = false,
@@ -277,7 +277,7 @@ serialize_parse_qos0_publish(_) ->
     ?assertEqual(Bin, serialize_to_binary(Packet)),
     ?assertMatch({ok, Packet, <<>>, _}, emqx_frame:parse(Bin)).
 
-serialize_parse_qos1_publish(_) ->
+t_serialize_parse_qos1_publish(_) ->
     Bin = <<50,13,0,5,97,47,98,47,99,0,1,104,97,104,97>>,
     Packet = #mqtt_packet{header   = #mqtt_packet_header{type   = ?PUBLISH,
                                                          dup    = false,
@@ -289,11 +289,11 @@ serialize_parse_qos1_publish(_) ->
     ?assertEqual(Bin, serialize_to_binary(Packet)),
     ?assertMatch({ok, Packet, <<>>, _}, emqx_frame:parse(Bin)).
 
-serialize_parse_qos2_publish(_) ->
+t_serialize_parse_qos2_publish(_) ->
     Packet = ?PUBLISH_PACKET(?QOS_2, <<"Topic">>, 1, payload()),
     ?assertEqual(Packet, parse_serialize(Packet)).
 
-serialize_parse_publish_v5(_) ->
+t_serialize_parse_publish_v5(_) ->
     Props = #{'Payload-Format-Indicator' => 1,
               'Message-Expiry-Interval'  => 60,
               'Topic-Alias'              => 16#AB,
@@ -304,45 +304,45 @@ serialize_parse_publish_v5(_) ->
     Packet = ?PUBLISH_PACKET(?QOS_1, <<"$share/group/topic">>, 1, Props, <<"payload">>),
     ?assertEqual(Packet, parse_serialize(Packet, #{version => ?MQTT_PROTO_V5})).
 
-serialize_parse_puback(_) ->
+t_serialize_parse_puback(_) ->
     Packet = ?PUBACK_PACKET(1),
     ?assertEqual(<<64,2,0,1>>, serialize_to_binary(Packet)),
     ?assertEqual(Packet, parse_serialize(Packet)).
 
-serialize_parse_puback_v5(_) ->
+t_serialize_parse_puback_v5(_) ->
     Packet = ?PUBACK_PACKET(16, ?RC_SUCCESS, #{'Reason-String' => <<"success">>}),
     ?assertEqual(Packet, parse_serialize(Packet, #{version => ?MQTT_PROTO_V5})).
 
-serialize_parse_pubrec(_) ->
+t_serialize_parse_pubrec(_) ->
     Packet = ?PUBREC_PACKET(1),
     ?assertEqual(<<5:4,0:4,2,0,1>>, serialize_to_binary(Packet)),
     ?assertEqual(Packet, parse_serialize(Packet)).
 
-serialize_parse_pubrec_v5(_) ->
+t_serialize_parse_pubrec_v5(_) ->
     Packet = ?PUBREC_PACKET(16, ?RC_SUCCESS, #{'Reason-String' => <<"success">>}),
     ?assertEqual(Packet, parse_serialize(Packet, #{version => ?MQTT_PROTO_V5})).
 
-serialize_parse_pubrel(_) ->
+t_serialize_parse_pubrel(_) ->
     Packet = ?PUBREL_PACKET(1),
     Bin = serialize_to_binary(Packet),
     ?assertEqual(<<6:4,2:4,2,0,1>>, Bin),
     ?assertEqual(Packet, parse_serialize(Packet)).
 
-serialize_parse_pubrel_v5(_) ->
+t_serialize_parse_pubrel_v5(_) ->
     Packet = ?PUBREL_PACKET(16, ?RC_SUCCESS, #{'Reason-String' => <<"success">>}),
     ?assertEqual(Packet, parse_serialize(Packet, #{version => ?MQTT_PROTO_V5})).
 
-serialize_parse_pubcomp(_) ->
+t_serialize_parse_pubcomp(_) ->
     Packet = ?PUBCOMP_PACKET(1),
     Bin = serialize_to_binary(Packet),
     ?assertEqual(<<7:4,0:4,2,0,1>>, Bin),
     ?assertEqual(Packet, parse_serialize(Packet)).
 
-serialize_parse_pubcomp_v5(_) ->
+t_serialize_parse_pubcomp_v5(_) ->
     Packet = ?PUBCOMP_PACKET(16, ?RC_SUCCESS, #{'Reason-String' => <<"success">>}),
     ?assertEqual(Packet, parse_serialize(Packet, #{version => ?MQTT_PROTO_V5})).
 
-serialize_parse_subscribe(_) ->
+t_serialize_parse_subscribe(_) ->
     %% SUBSCRIBE(Q1, R0, D0, PacketId=2, TopicTable=[{<<"TopicA">>,2}])
     Bin = <<130,11,0,2,0,6,84,111,112,105,99,65,2>>,
     TopicOpts = #{nl => 0 , rap => 0, rc => 0, rh => 0, qos => 2},
@@ -352,61 +352,61 @@ serialize_parse_subscribe(_) ->
     %%ct:log("Bin: ~p, Packet: ~p ~n", [Packet, parse(Bin)]),
     ?assertMatch({ok, Packet, <<>>, _}, emqx_frame:parse(Bin)).
 
-serialize_parse_subscribe_v5(_) ->
+t_serialize_parse_subscribe_v5(_) ->
     TopicFilters = [{<<"TopicQos0">>, #{rh => 1, qos => ?QOS_2, rap => 0, nl => 0, rc => 0}},
                     {<<"TopicQos1">>, #{rh => 1, qos => ?QOS_2, rap => 0, nl => 0, rc => 0}}],
     Packet = ?SUBSCRIBE_PACKET(3, #{'Subscription-Identifier' => 16#FFFFFFF}, TopicFilters),
     ?assertEqual(Packet, parse_serialize(Packet, #{version => ?MQTT_PROTO_V5})).
 
-serialize_parse_suback(_) ->
+t_serialize_parse_suback(_) ->
     Packet = ?SUBACK_PACKET(10, [?QOS_0, ?QOS_1, 128]),
     ?assertEqual(Packet, parse_serialize(Packet)).
 
-serialize_parse_suback_v5(_) ->
+t_serialize_parse_suback_v5(_) ->
     Packet = ?SUBACK_PACKET(1, #{'Reason-String' => <<"success">>,
                                  'User-Property' => [{<<"key">>, <<"value">>}]},
                             [?QOS_0, ?QOS_1, 128]),
     ?assertEqual(Packet, parse_serialize(Packet, #{version => ?MQTT_PROTO_V5})).
 
-serialize_parse_unsubscribe(_) ->
+t_serialize_parse_unsubscribe(_) ->
     %% UNSUBSCRIBE(Q1, R0, D0, PacketId=2, TopicTable=[<<"TopicA">>])
     Packet = ?UNSUBSCRIBE_PACKET(2, [<<"TopicA">>]),
     Bin = <<162,10,0,2,0,6,84,111,112,105,99,65>>,
     ?assertEqual(Bin, serialize_to_binary(Packet)),
     ?assertMatch({ok, Packet, <<>>, _}, emqx_frame:parse(Bin)).
 
-serialize_parse_unsubscribe_v5(_) ->
+t_serialize_parse_unsubscribe_v5(_) ->
     Props = #{'User-Property' => [{<<"key">>, <<"val">>}]},
     Packet = ?UNSUBSCRIBE_PACKET(10, Props, [<<"Topic1">>, <<"Topic2">>]),
     ?assertEqual(Packet, parse_serialize(Packet, #{version => ?MQTT_PROTO_V5})).
 
-serialize_parse_unsuback(_) ->
+t_serialize_parse_unsuback(_) ->
     Packet = ?UNSUBACK_PACKET(10),
     ?assertEqual(Packet, parse_serialize(Packet)).
 
-serialize_parse_unsuback_v5(_) ->
+t_serialize_parse_unsuback_v5(_) ->
     Packet = ?UNSUBACK_PACKET(10, #{'Reason-String' => <<"Not authorized">>,
                                     'User-Property' => [{<<"key">>, <<"val">>}]},
                               [16#87, 16#87, 16#87]),
     ?assertEqual(Packet, parse_serialize(Packet, #{version => ?MQTT_PROTO_V5})).
 
-serialize_parse_pingreq(_) ->
+t_serialize_parse_pingreq(_) ->
     PingReq = ?PACKET(?PINGREQ),
     ?assertEqual(PingReq, parse_serialize(PingReq)).
 
-serialize_parse_pingresp(_) ->
+t_serialize_parse_pingresp(_) ->
     PingResp = ?PACKET(?PINGRESP),
     ?assertEqual(PingResp, parse_serialize(PingResp)).
 
-parse_disconnect(_) ->
+t_parse_disconnect(_) ->
     Packet = ?DISCONNECT_PACKET(?RC_SUCCESS),
     ?assertMatch({ok, Packet, <<>>, _}, emqx_frame:parse(<<224, 0>>)).
 
-serialize_parse_disconnect(_) ->
+t_serialize_parse_disconnect(_) ->
     Packet = ?DISCONNECT_PACKET(?RC_SUCCESS),
     ?assertEqual(Packet, parse_serialize(Packet)).
 
-serialize_parse_disconnect_v5(_) ->
+t_serialize_parse_disconnect_v5(_) ->
     Packet = ?DISCONNECT_PACKET(?RC_SUCCESS,
                                 #{'Session-Expiry-Interval' => 60,
                                   'Reason-String' => <<"server_moved">>,
@@ -414,7 +414,7 @@ serialize_parse_disconnect_v5(_) ->
                                  }),
     ?assertEqual(Packet, parse_serialize(Packet, #{version => ?MQTT_PROTO_V5})).
 
-serialize_parse_auth_v5(_) ->
+t_serialize_parse_auth_v5(_) ->
     Packet = ?AUTH_PACKET(?RC_SUCCESS,
                           #{'Authentication-Method' => <<"oauth2">>,
                             'Authentication-Data' => <<"3zekkd">>,
@@ -427,7 +427,8 @@ parse_serialize(Packet) ->
     parse_serialize(Packet, #{}).
 
 parse_serialize(Packet, Opts) when is_map(Opts) ->
-    Bin = iolist_to_binary(emqx_frame:serialize(Packet, Opts)),
+    Ver = maps:get(version, Opts, ?MQTT_PROTO_V4),
+    Bin = iolist_to_binary(emqx_frame:serialize(Packet, Ver)),
     ParseState = emqx_frame:initial_parse_state(Opts),
     {ok, NPacket, <<>>, _} = emqx_frame:parse(Bin, ParseState),
     NPacket.

+ 1 - 2
test/emqx_gc_SUITE.erl

@@ -21,8 +21,7 @@
 
 -include_lib("eunit/include/eunit.hrl").
 
-all() ->
-    [t_init, t_run, t_info, t_reset].
+all() -> emqx_ct:all(?MODULE).
 
 t_init(_) ->
     ?assertEqual(undefined, emqx_gc:init(false)),

+ 5 - 5
test/emqx_guid_SUITE.erl

@@ -16,21 +16,21 @@
 
 -module(emqx_guid_SUITE).
 
--include_lib("eunit/include/eunit.hrl").
-
 -compile(export_all).
 -compile(nowarn_export_all).
 
-all() -> [t_guid_gen, t_guid_hexstr, t_guid_base62].
+-include_lib("eunit/include/eunit.hrl").
+
+all() -> emqx_ct:all(?MODULE).
 
 t_guid_gen(_) ->
     Guid1 = emqx_guid:gen(),
     Guid2 = emqx_guid:gen(),
     <<_:128>> = Guid1,
-    true = (Guid2 >= Guid1),
+    ?assert((Guid2 >= Guid1)),
     {Ts1, _, 0} = emqx_guid:new(),
     Ts2 = emqx_guid:timestamp(emqx_guid:gen()),
-    true = Ts2 > Ts1.
+    ?assert(Ts2 > Ts1).
 
 t_guid_hexstr(_) ->
     Guid = emqx_guid:gen(),

+ 11 - 8
test/emqx_hooks_SUITE.erl

@@ -20,12 +20,10 @@
 -compile(nowarn_export_all).
 
 -include_lib("eunit/include/eunit.hrl").
--include_lib("common_test/include/ct.hrl").
 
-all() ->
-    [add_delete_hook, run_hook].
+all() -> emqx_ct:all(?MODULE).
 
-add_delete_hook(_) ->
+t_add_del_hook(_) ->
     {ok, _} = emqx_hooks:start_link(),
     ok = emqx:hook(test_hook, fun ?MODULE:hook_fun1/1, []),
     ok = emqx:hook(test_hook, fun ?MODULE:hook_fun2/1, []),
@@ -56,7 +54,7 @@ add_delete_hook(_) ->
     ?assertEqual([], emqx_hooks:lookup(emqx_hook)),
     ok = emqx_hooks:stop().
 
-run_hook(_) ->
+t_run_hooks(_) ->
     {ok, _} = emqx_hooks:start_link(),
     ok = emqx:hook(foldl_hook, fun ?MODULE:hook_fun3/4, [init]),
     ok = emqx:hook(foldl_hook, {?MODULE, hook_fun3, [init]}),
@@ -86,6 +84,10 @@ run_hook(_) ->
 
     ok = emqx_hooks:stop().
 
+%%--------------------------------------------------------------------
+%% Hook fun
+%%--------------------------------------------------------------------
+
 hook_fun1(arg) -> ok;
 hook_fun1(_) -> error.
 
@@ -104,7 +106,7 @@ hook_fun7(arg, initArg) -> ok.
 hook_fun8(arg, initArg) -> ok.
 
 hook_fun9(arg, Acc)  -> {stop, [r9 | Acc]}.
-hook_fun10(arg, Acc)  -> {stop, [r10 | Acc]}.
+hook_fun10(arg, Acc) -> {stop, [r10 | Acc]}.
 
 hook_filter1(arg) -> true;
 hook_filter1(_) -> false.
@@ -112,6 +114,7 @@ hook_filter1(_) -> false.
 hook_filter2(arg, _Acc, init_arg) -> true;
 hook_filter2(_, _Acc, _IntArg) -> false.
 
-hook_filter2_1(arg, _Acc, init_arg) -> true;
+hook_filter2_1(arg, _Acc, init_arg)  -> true;
 hook_filter2_1(arg1, _Acc, init_arg) -> true;
-hook_filter2_1(_, _Acc, _IntArg) -> false.
+hook_filter2_1(_, _Acc, _IntArg)     -> false.
+

+ 69 - 22
test/emqx_inflight_SUITE.erl

@@ -19,26 +19,73 @@
 -compile(export_all).
 -compile(nowarn_export_all).
 
-all() -> [t_inflight_all].
-
-t_inflight_all(_) ->
-    Empty = emqx_inflight:new(2),
-    true = emqx_inflight:is_empty(Empty),
-    2 = emqx_inflight:max_size(Empty),
-    false = emqx_inflight:contain(a, Empty),
-    none = emqx_inflight:lookup(a, Empty),
-    try emqx_inflight:update(a, 1, Empty) catch
-        error:Reason -> io:format("Reason: ~w~n", [Reason])
-    end,
-    0 = emqx_inflight:size(Empty),
-    Inflight1 = emqx_inflight:insert(a, 1, Empty),
-    Inflight2 = emqx_inflight:insert(b, 2, Inflight1),
-    2 = emqx_inflight:size(Inflight2),
-    true = emqx_inflight:is_full(Inflight2),
-    {value, 1} = emqx_inflight:lookup(a, Inflight1),
-    {value, 2} = emqx_inflight:lookup(a, emqx_inflight:update(a, 2, Inflight1)),
-    false = emqx_inflight:contain(a, emqx_inflight:delete(a, Inflight1)),
-    [1, 2] = emqx_inflight:values(Inflight2),
-    [{a, 1}, {b ,2}] = emqx_inflight:to_list(Inflight2),
-    [a, b] = emqx_inflight:window(Inflight2).
+-include_lib("eunit/include/eunit.hrl").
+-include_lib("emqx_ct_helpers/include/emqx_ct.hrl").
+
+all() -> emqx_ct:all(?MODULE).
+
+t_contain(_) ->
+    Inflight = emqx_inflight:insert(k, v, emqx_inflight:new()),
+    ?assert(emqx_inflight:contain(k, Inflight)),
+    ?assertNot(emqx_inflight:contain(badkey, Inflight)).
+
+t_lookup(_) ->
+    Inflight = emqx_inflight:insert(k, v, emqx_inflight:new()),
+    ?assertEqual({value, v}, emqx_inflight:lookup(k, Inflight)),
+    ?assertEqual(none, emqx_inflight:lookup(badkey, Inflight)).
+
+t_insert(_) ->
+    Inflight = emqx_inflight:insert(
+                 b, 2, emqx_inflight:insert(
+                         a, 1, emqx_inflight:new())),
+    ?assertEqual(2, emqx_inflight:size(Inflight)),
+    ?assertEqual({value, 1}, emqx_inflight:lookup(a, Inflight)),
+    ?assertEqual({value, 2}, emqx_inflight:lookup(b, Inflight)),
+    ?catch_error({key_exists, a}, emqx_inflight:insert(a, 1, Inflight)).
+
+t_update(_) ->
+    Inflight = emqx_inflight:insert(k, v, emqx_inflight:new()),
+    ?assertEqual(Inflight, emqx_inflight:update(k, v, Inflight)),
+    ?catch_error(function_clause, emqx_inflight:update(badkey, v, Inflight)).
+
+t_resize(_) ->
+    Inflight = emqx_inflight:insert(k, v, emqx_inflight:new(2)),
+    ?assertEqual(1, emqx_inflight:size(Inflight)),
+    ?assertEqual(2, emqx_inflight:max_size(Inflight)),
+    Inflight1 = emqx_inflight:resize(4, Inflight),
+    ?assertEqual(4, emqx_inflight:max_size(Inflight1)),
+    ?assertEqual(1, emqx_inflight:size(Inflight)).
+
+t_delete(_) ->
+    Inflight = emqx_inflight:insert(k, v, emqx_inflight:new(2)),
+    Inflight1 = emqx_inflight:delete(k, Inflight),
+    ?assert(emqx_inflight:is_empty(Inflight1)),
+    ?assertNot(emqx_inflight:contain(k, Inflight1)).
+
+t_values(_) ->
+    Inflight = emqx_inflight:insert(
+                 b, 2, emqx_inflight:insert(
+                         a, 1, emqx_inflight:new())),
+    ?assertEqual([1,2], emqx_inflight:values(Inflight)),
+    ?assertEqual([{a,1},{b,2}], emqx_inflight:to_list(Inflight)).
+
+t_is_full(_) ->
+    Inflight = emqx_inflight:insert(k, v, emqx_inflight:new()),
+    ?assertNot(emqx_inflight:is_full(Inflight)),
+    Inflight1 = emqx_inflight:insert(
+                  b, 2, emqx_inflight:insert(
+                          a, 1, emqx_inflight:new(2))),
+    ?assert(emqx_inflight:is_full(Inflight1)).
+
+t_is_empty(_) ->
+    Inflight = emqx_inflight:insert(a, 1, emqx_inflight:new(2)),
+    ?assertNot(emqx_inflight:is_empty(Inflight)),
+    Inflight1 = emqx_inflight:delete(a, Inflight),
+    ?assert(emqx_inflight:is_empty(Inflight1)).
+
+t_window(_) ->
+    Inflight = emqx_inflight:insert(
+                 b, 2, emqx_inflight:insert(
+                         a, 1, emqx_inflight:new(2))),
+    [a, b] = emqx_inflight:window(Inflight).
 

+ 12 - 7
test/emqx_json_SUITE.erl

@@ -19,21 +19,26 @@
 -compile(export_all).
 -compile(nowarn_export_all).
 
-all() -> [t_decode_encode, t_safe_decode_encode].
+-include_lib("eunit/include/eunit.hrl").
+
+-define(DEC_OPTS, [{labels, atom}, return_maps]).
+
+all() -> emqx_ct:all(?MODULE).
 
 t_decode_encode(_) ->
     JsonText = <<"{\"library\": \"jsx\", \"awesome\": true}">>,
     JsonTerm = emqx_json:decode(JsonText),
     JsonMaps = #{library => <<"jsx">>, awesome => true},
-    JsonMaps = emqx_json:decode(JsonText, [{labels, atom}, return_maps]),
-    JsonText = emqx_json:encode(JsonTerm, [{space, 1}]).
+    ?assertEqual(JsonText, emqx_json:encode(JsonTerm, [{space, 1}])),
+    ?assertEqual(JsonMaps, emqx_json:decode(JsonText, ?DEC_OPTS)).
 
 t_safe_decode_encode(_) ->
     JsonText = <<"{\"library\": \"jsx\", \"awesome\": true}">>,
     {ok, JsonTerm} = emqx_json:safe_decode(JsonText),
     JsonMaps = #{library => <<"jsx">>, awesome => true},
-    {ok, JsonMaps} = emqx_json:safe_decode(JsonText, [{labels, atom}, return_maps]),
-    {ok, JsonText} = emqx_json:safe_encode(JsonTerm, [{space, 1}]),
+    ?assertEqual({ok, JsonText}, emqx_json:safe_encode(JsonTerm, [{space, 1}])),
+    ?assertEqual({ok, JsonMaps}, emqx_json:safe_decode(JsonText, ?DEC_OPTS)),
     BadJsonText = <<"{\"library\", \"awesome\": true}">>,
-    {error, _} = emqx_json:safe_decode(BadJsonText),
-    {error, _} = emqx_json:safe_encode({a, {b ,1}}).
+    ?assertEqual({error, badarg}, emqx_json:safe_decode(BadJsonText)),
+    {error, badarg} = emqx_json:safe_encode({a, {b ,1}}).
+

+ 2 - 9
test/emqx_keepalive_SUITE.erl

@@ -19,13 +19,7 @@
 -compile(export_all).
 -compile(nowarn_export_all).
 
-all() -> [{group, keepalive}].
-
-groups() -> [{keepalive, [], [t_keepalive]}].
-
-%%--------------------------------------------------------------------
-%% Keepalive
-%%--------------------------------------------------------------------
+all() -> emqx_ct:all(?MODULE).
 
 t_keepalive(_) ->
     {ok, KA} = emqx_keepalive:start(fun() -> {ok, 1} end, 1, {keepalive, timeout}),
@@ -38,7 +32,6 @@ keepalive_recv(KA, Acc) ->
                 {ok, KA1} -> keepalive_recv(KA1, [resumed | Acc]);
                 {error, timeout} -> [timeout | Acc]
             end
-        after 4000 ->
-                Acc
+        after 4000 -> Acc
     end.
 

+ 0 - 175
test/emqx_lib_SUITE.erl

@@ -1,175 +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_lib_SUITE).
-
--include_lib("eunit/include/eunit.hrl").
-
--compile(export_all).
--compile(nowarn_export_all).
-
--define(SOCKOPTS, [
-	binary,
-	{packet,    raw},
-	{reuseaddr, true},
-	{backlog,   512},
-	{nodelay,   true}
-]).
-
--define(PQ, emqx_pqueue).
-
--define(BASE62, emqx_base62).
-
-all() -> [{group, guid}, {group, opts},
-          {group, ?PQ}, {group, time},
-          {group, node}, {group, base62}].
-
-groups() ->
-    [{guid, [], [guid_gen, guid_hexstr, guid_base62]},
-     {opts, [], [opts_merge]},
-     {?PQ,  [], [priority_queue_plen,
-                 priority_queue_out2]},
-     {time, [], [time_now_to_]},
-     {node, [], [node_is_aliving, node_parse_name]},
-     {base62, [], [base62_encode]}].
-
-%%--------------------------------------------------------------------
-%% emqx_guid
-%%--------------------------------------------------------------------
-
-guid_gen(_) ->
-    Guid1 = emqx_guid:gen(),
-    Guid2 = emqx_guid:gen(),
-    <<_:128>> = Guid1,
-    true = (Guid2 >= Guid1),
-    {Ts1, _, 0} = emqx_guid:new(),
-    Ts2 = emqx_guid:timestamp(emqx_guid:gen()),
-    true = Ts2 > Ts1.
-
-guid_hexstr(_) ->
-    Guid = emqx_guid:gen(),
-    ?assertEqual(Guid, emqx_guid:from_hexstr(emqx_guid:to_hexstr(Guid))).
-
-guid_base62(_) ->
-    Guid = emqx_guid:gen(),
-    ?assertEqual(Guid, emqx_guid:from_base62(emqx_guid:to_base62(Guid))).
-
-%%--------------------------------------------------------------------
-%% emqx_opts
-%%--------------------------------------------------------------------
-
-opts_merge(_) ->
-    Opts = emqx_misc:merge_opts(?SOCKOPTS, [raw,
-                                            binary,
-                                            {backlog, 1024},
-                                            {nodelay, false},
-                                            {max_clients, 1024},
-                                            {acceptors, 16}]),
-    1024 = proplists:get_value(backlog, Opts),
-    1024 = proplists:get_value(max_clients, Opts),
-    [binary, raw,
-     {acceptors, 16},
-     {backlog, 1024},
-     {max_clients, 1024},
-     {nodelay, false},
-     {packet, raw},
-     {reuseaddr, true}] = lists:sort(Opts).
-
-%%--------------------------------------------------------------------
-%% priority_queue
-%%--------------------------------------------------------------------
-
-priority_queue_plen(_) ->
-    Q = ?PQ:new(),
-    0 = ?PQ:plen(0, Q),
-    Q0 = ?PQ:in(z, Q),
-    1 = ?PQ:plen(0, Q0),
-    Q1 = ?PQ:in(x, 1, Q0),
-    1 = ?PQ:plen(1, Q1),
-    Q2 = ?PQ:in(y, 2, Q1),
-    1 = ?PQ:plen(2, Q2),
-    Q3 = ?PQ:in(z, 2, Q2),
-    2 = ?PQ:plen(2, Q3),
-    {_, Q4} = ?PQ:out(1, Q3),
-    0 = ?PQ:plen(1, Q4),
-    {_, Q5} = ?PQ:out(Q4),
-    1 = ?PQ:plen(2, Q5),
-    {_, Q6} = ?PQ:out(Q5),
-    0 = ?PQ:plen(2, Q6),
-    1 = ?PQ:len(Q6),
-    {_, Q7} = ?PQ:out(Q6),
-    0 = ?PQ:len(Q7).
-
-priority_queue_out2(_) ->
-    Els = [a, {b, 1}, {c, 1}, {d, 2}, {e, 2}, {f, 2}],
-    Q  = ?PQ:new(),
-    Q0 = lists:foldl(
-            fun({El, P}, Acc) ->
-                    ?PQ:in(El, P, Acc);
-                (El, Acc) ->
-                    ?PQ:in(El, Acc)
-            end, Q, Els),
-    {Val, Q1} = ?PQ:out(Q0),
-    {value, d} = Val,
-    {Val1, Q2} = ?PQ:out(2, Q1),
-    {value, e} = Val1,
-    {Val2, Q3} = ?PQ:out(1, Q2),
-    {value, b} = Val2,
-    {Val3, Q4} = ?PQ:out(Q3),
-    {value, f} = Val3,
-    {Val4, Q5} = ?PQ:out(Q4),
-    {value, c} = Val4,
-    {Val5, Q6} = ?PQ:out(Q5),
-    {value, a} = Val5,
-    {empty, _Q7} = ?PQ:out(Q6).
-
-%%--------------------------------------------------------------------
-%% emqx_time
-%%--------------------------------------------------------------------
-
-time_now_to_(_) ->
-    emqx_time:seed(),
-    emqx_time:now_secs(),
-    emqx_time:now_ms().
-
-%%--------------------------------------------------------------------
-%% emqx_node
-%%--------------------------------------------------------------------
-
-node_is_aliving(_) ->
-    io:format("Node: ~p~n", [node()]),
-    true = ekka_node:is_aliving(node()),
-    false = ekka_node:is_aliving('x@127.0.0.1').
-
-node_parse_name(_) ->
-    'a@127.0.0.1' = ekka_node:parse_name("a@127.0.0.1"),
-    'b@127.0.0.1' = ekka_node:parse_name("b").
-
-%%--------------------------------------------------------------------
-%% base62 encode decode
-%%--------------------------------------------------------------------
-
-base62_encode(_) ->
-    <<"10">> = ?BASE62:decode(?BASE62:encode(<<"10">>)),
-    <<"100">> = ?BASE62:decode(?BASE62:encode(<<"100">>)),
-    <<"9999">> = ?BASE62:decode(?BASE62:encode(<<"9999">>)),
-    <<"65535">> = ?BASE62:decode(?BASE62:encode(<<"65535">>)),
-    <<X:128/unsigned-big-integer>> = emqx_guid:gen(),
-    <<Y:128/unsigned-big-integer>> = emqx_guid:gen(),
-    X = ?BASE62:decode(?BASE62:encode(X), integer),
-    Y = ?BASE62:decode(?BASE62:encode(Y), integer),
-    <<"helloworld">> = ?BASE62:decode(?BASE62:encode("helloworld")),
-    "helloworld" = ?BASE62:decode(?BASE62:encode("helloworld", string), string).

+ 4 - 9
test/emqx_listeners_SUITE.erl

@@ -19,16 +19,10 @@
 -compile(export_all).
 -compile(nowarn_export_all).
 
--include_lib("eunit/include/eunit.hrl").
-
--include_lib("common_test/include/ct.hrl").
-
 -include("emqx.hrl").
 -include("emqx_mqtt.hrl").
 
-all() ->
-    [start_stop_listeners,
-     restart_listeners].
+all() -> emqx_ct:all(?MODULE).
 
 init_per_suite(Config) ->
     NewConfig = generate_config(),
@@ -41,11 +35,11 @@ end_per_suite(_Config) ->
     application:stop(esockd),
     application:stop(cowboy).
 
-start_stop_listeners(_) ->
+t_start_stop_listeners(_) ->
     ok = emqx_listeners:start(),
     ok = emqx_listeners:stop().
 
-restart_listeners(_) ->
+t_restart_listeners(_) ->
     ok = emqx_listeners:start(),
     ok = emqx_listeners:stop(),
     ok = emqx_listeners:restart(),
@@ -95,3 +89,4 @@ get_base_dir(Module) ->
 
 get_base_dir() ->
     get_base_dir(?MODULE).
+

+ 13 - 13
test/emqx_message_SUITE.erl

@@ -16,7 +16,9 @@
 
 -module(emqx_message_SUITE).
 
--include("emqx.hrl").
+-compile(export_all).
+-compile(nowarn_export_all).
+
 -include("emqx_mqtt.hrl").
 -include_lib("eunit/include/eunit.hrl").
 
@@ -32,17 +34,22 @@
         , suite/0
         ]).
 
+all() -> emqx_ct:all(?MODULE).
+
+suite() ->
+    [{ct_hooks, [cth_surefire]}, {timetrap, {seconds, 30}}].
+
 t_make(_) ->
     Msg = emqx_message:make(<<"topic">>, <<"payload">>),
-    ?assertEqual(0, emqx_message:qos(Msg)),
+    ?assertEqual(?QOS_0, emqx_message:qos(Msg)),
     ?assertEqual(undefined, emqx_message:from(Msg)),
     ?assertEqual(<<"payload">>, emqx_message:payload(Msg)),
     Msg1 = emqx_message:make(<<"clientid">>, <<"topic">>, <<"payload">>),
-    ?assertEqual(0, emqx_message:qos(Msg1)),
+    ?assertEqual(?QOS_0, emqx_message:qos(Msg1)),
     ?assertEqual(<<"topic">>, emqx_message:topic(Msg1)),
     Msg2 = emqx_message:make(<<"clientid">>, ?QOS_2, <<"topic">>, <<"payload">>),
     ?assert(is_binary(emqx_message:id(Msg2))),
-    ?assertEqual(2, emqx_message:qos(Msg2)),
+    ?assertEqual(?QOS_2, emqx_message:qos(Msg2)),
     ?assertEqual(<<"clientid">>, emqx_message:from(Msg2)),
     ?assertEqual(<<"topic">>, emqx_message:topic(Msg2)),
     ?assertEqual(<<"payload">>, emqx_message:payload(Msg2)).
@@ -86,21 +93,14 @@ t_expired(_) ->
 
 t_to_map(_) ->
     Msg = emqx_message:make(<<"clientid">>, ?QOS_1, <<"topic">>, <<"payload">>),
-    List = [{id, Msg#message.id},
+    List = [{id, emqx_message:id(Msg)},
             {qos, ?QOS_1},
             {from, <<"clientid">>},
             {flags, #{dup => false}},
             {headers, #{}},
             {topic, <<"topic">>},
             {payload, <<"payload">>},
-            {timestamp, Msg#message.timestamp}],
+            {timestamp, emqx_message:timestamp(Msg)}],
     ?assertEqual(List, emqx_message:to_list(Msg)),
     ?assertEqual(maps:from_list(List), emqx_message:to_map(Msg)).
 
-all() ->
-    IsTestCase = fun("t_" ++ _) -> true; (_) -> false end,
-    [F || {F, _A} <- module_info(exports), IsTestCase(atom_to_list(F))].
-
-suite() ->
-    [{ct_hooks, [cth_surefire]}, {timetrap, {seconds, 30}}].
-

+ 50 - 41
test/emqx_metrics_SUITE.erl

@@ -22,55 +22,64 @@
 -include("emqx_mqtt.hrl").
 -include_lib("eunit/include/eunit.hrl").
 
-all() -> [t_inc_dec, t_inc_recv, t_inc_sent, t_trans].
+all() -> emqx_ct:all(?MODULE).
 
 t_inc_dec(_) ->
-    {ok, _} = emqx_metrics:start_link(),
-    ?assertEqual(0, emqx_metrics:val('bytes.received')),
-    ?assertEqual(0, emqx_metrics:val('messages.retained')),
-    ok = emqx_metrics:inc('bytes.received'),
-    ok = emqx_metrics:inc('bytes.received', 2),
-    ok = emqx_metrics:inc('bytes.received', 2),
-    ?assertEqual(5, emqx_metrics:val('bytes.received')),
-    ok = emqx_metrics:inc('messages.retained', 2),
-    ok = emqx_metrics:inc('messages.retained', 2),
-    ?assertEqual(4, emqx_metrics:val('messages.retained')),
-    ok = emqx_metrics:dec('messages.retained'),
-    ok = emqx_metrics:dec('messages.retained', 1),
-    ?assertEqual(2, emqx_metrics:val('messages.retained')),
-    ok = emqx_metrics:set('messages.retained', 3),
-    ?assertEqual(3, emqx_metrics:val('messages.retained')),
-    ok = emqx_metrics:stop().
+    with_metrics_server(
+      fun() ->
+        ?assertEqual(0, emqx_metrics:val('bytes.received')),
+        ?assertEqual(0, emqx_metrics:val('messages.retained')),
+        ok = emqx_metrics:inc('bytes.received'),
+        ok = emqx_metrics:inc('bytes.received', 2),
+        ok = emqx_metrics:inc('bytes.received', 2),
+        ?assertEqual(5, emqx_metrics:val('bytes.received')),
+        ok = emqx_metrics:inc('messages.retained', 2),
+        ok = emqx_metrics:inc('messages.retained', 2),
+        ?assertEqual(4, emqx_metrics:val('messages.retained')),
+        ok = emqx_metrics:dec('messages.retained'),
+        ok = emqx_metrics:dec('messages.retained', 1),
+        ?assertEqual(2, emqx_metrics:val('messages.retained')),
+        ok = emqx_metrics:set('messages.retained', 3),
+        ?assertEqual(3, emqx_metrics:val('messages.retained'))
+      end).
 
 t_inc_recv(_) ->
-    {ok, _} = emqx_metrics:start_link(),
-    ok = emqx_metrics:inc_recv(?PACKET(?CONNECT)),
-    ?assertEqual(1, emqx_metrics:val('packets.received')),
-    ?assertEqual(1, emqx_metrics:val('packets.connect.received')),
-    ok = emqx_metrics:stop().
+    with_metrics_server(
+      fun() ->
+        ok = emqx_metrics:inc_recv(?PACKET(?CONNECT)),
+        ?assertEqual(1, emqx_metrics:val('packets.received')),
+        ?assertEqual(1, emqx_metrics:val('packets.connect.received'))
+      end).
 
 t_inc_sent(_) ->
-    {ok, _} = emqx_metrics:start_link(),
-    ok = emqx_metrics:inc_sent(?CONNACK_PACKET(0)),
-    ?assertEqual(1, emqx_metrics:val('packets.sent')),
-    ?assertEqual(1, emqx_metrics:val('packets.connack.sent')),
-    ok = emqx_metrics:stop().
+    with_metrics_server(
+      fun() ->
+        ok = emqx_metrics:inc_sent(?CONNACK_PACKET(0)),
+        ?assertEqual(1, emqx_metrics:val('packets.sent')),
+        ?assertEqual(1, emqx_metrics:val('packets.connack.sent'))
+      end).
 
 t_trans(_) ->
+    with_metrics_server(
+      fun() ->
+        ok = emqx_metrics:trans(inc, 'bytes.received'),
+        ok = emqx_metrics:trans(inc, 'bytes.received', 2),
+        ?assertEqual(0, emqx_metrics:val('bytes.received')),
+        ok = emqx_metrics:trans(inc, 'messages.retained', 2),
+        ok = emqx_metrics:trans(inc, 'messages.retained', 2),
+        ?assertEqual(0, emqx_metrics:val('messages.retained')),
+        ok = emqx_metrics:commit(),
+        ?assertEqual(3, emqx_metrics:val('bytes.received')),
+        ?assertEqual(4, emqx_metrics:val('messages.retained')),
+        ok = emqx_metrics:trans(dec, 'messages.retained'),
+        ok = emqx_metrics:trans(dec, 'messages.retained', 1),
+        ?assertEqual(4, emqx_metrics:val('messages.retained')),
+        ok = emqx_metrics:commit(),
+        ?assertEqual(2, emqx_metrics:val('messages.retained'))
+      end).
+
+with_metrics_server(Fun) ->
     {ok, _} = emqx_metrics:start_link(),
-    ok = emqx_metrics:trans(inc, 'bytes.received'),
-    ok = emqx_metrics:trans(inc, 'bytes.received', 2),
-    ?assertEqual(0, emqx_metrics:val('bytes.received')),
-    ok = emqx_metrics:trans(inc, 'messages.retained', 2),
-    ok = emqx_metrics:trans(inc, 'messages.retained', 2),
-    ?assertEqual(0, emqx_metrics:val('messages.retained')),
-    ok = emqx_metrics:commit(),
-    ?assertEqual(3, emqx_metrics:val('bytes.received')),
-    ?assertEqual(4, emqx_metrics:val('messages.retained')),
-    ok = emqx_metrics:trans(dec, 'messages.retained'),
-    ok = emqx_metrics:trans(dec, 'messages.retained', 1),
-    ?assertEqual(4, emqx_metrics:val('messages.retained')),
-    ok = emqx_metrics:commit(),
-    ?assertEqual(2, emqx_metrics:val('messages.retained')),
+    _ = Fun(),
     ok = emqx_metrics:stop().
 

+ 30 - 11
test/emqx_misc_tests.erl

@@ -14,7 +14,11 @@
 %% limitations under the License.
 %%--------------------------------------------------------------------
 
--module(emqx_misc_tests).
+-module(emqx_misc_SUITE).
+
+-compile(export_all).
+-compile(nowarn_export_all).
+
 -include_lib("eunit/include/eunit.hrl").
 
 -define(SOCKOPTS, [binary,
@@ -23,8 +27,9 @@
                    {backlog,   512},
                    {nodelay,   true}]).
 
+all() -> emqx_ct:all(?MODULE).
 
-t_merge_opts_test() ->
+t_merge_opts() ->
     Opts = emqx_misc:merge_opts(?SOCKOPTS, [raw,
                                             binary,
                                             {backlog, 1024},
@@ -41,33 +46,47 @@ t_merge_opts_test() ->
      {packet, raw},
      {reuseaddr, true}] = lists:sort(Opts).
 
-timer_cancel_flush_test() ->
+t_timer_cancel_flush() ->
     Timer = emqx_misc:start_timer(0, foo),
     ok = emqx_misc:cancel_timer(Timer),
-    receive {timeout, Timer, foo} -> error(unexpected)
+    receive
+        {timeout, Timer, foo} ->
+            error(unexpected)
     after 0 -> ok
     end.
 
-shutdown_disabled_test() ->
+t_shutdown_disabled() ->
     ok = drain(),
     self() ! foo,
-    ?assertEqual(continue, conn_proc_mng_policy(0)),
+    ?assertEqual(continue, emqx_misc:conn_proc_mng_policy(0)),
     receive foo -> ok end,
-    ?assertEqual(hibernate, conn_proc_mng_policy(0)).
+    ?assertEqual(hibernate, emqx_misc:conn_proc_mng_policy(0)).
 
-message_queue_too_long_test() ->
+t_message_queue_too_long() ->
     ok = drain(),
     self() ! foo,
     self() ! bar,
     ?assertEqual({shutdown, message_queue_too_long},
-                 conn_proc_mng_policy(1)),
+                 emqx_misc:conn_proc_mng_policy(1)),
     receive foo -> ok end,
-    ?assertEqual(continue, conn_proc_mng_policy(1)),
+    ?assertEqual(continue, emqx_misc:conn_proc_mng_policy(1)),
     receive bar -> ok end.
 
-conn_proc_mng_policy(L) ->
+t_conn_proc_mng_policy(L) ->
     emqx_misc:conn_proc_mng_policy(#{message_queue_len => L}).
 
+t_proc_name(_) ->
+    'TODO'.
+
+t_proc_stats(_) ->
+    'TODO'.
+
+t_drain_deliver(_) ->
+    'TODO'.
+
+t_drain_down(_) ->
+    'TODO'.
+
 %% drain self() msg queue for deterministic test behavior
 drain() ->
     _ = drain([]), % maybe log

+ 0 - 101
test/emqx_mock_client.erl

@@ -1,101 +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_mock_client).
-
--behaviour(gen_server).
-
--export([start_link/1, open_session/3, open_session/4,
-         close_session/1, stop/1, get_last_message/1]).
-
--export([init/1, handle_call/3, handle_cast/2, handle_info/2,
-         terminate/2, code_change/3]).
-
--record(state, {clean_start, client_id, client_pid, last_msg, session_pid}).
-
-start_link(ClientId) ->
-    gen_server:start_link(?MODULE, [ClientId], []).
-
-open_session(ClientPid, ClientId, Zone) ->
-    open_session(ClientPid, ClientId, Zone, _Attrs = #{}).
-
-open_session(ClientPid, ClientId, Zone, Attrs0) ->
-    Attrs1 = default_session_attributes(Zone, ClientId, ClientPid),
-    Attrs = maps:merge(Attrs1, Attrs0),
-    gen_server:call(ClientPid, {start_session, ClientPid, ClientId, Attrs}).
-
-%% close session and terminate the client itself
-close_session(ClientPid) ->
-    gen_server:call(ClientPid, stop_session, infinity).
-
-stop(CPid) ->
-    gen_server:call(CPid, stop, infinity).
-
-get_last_message(Pid) ->
-    gen_server:call(Pid, get_last_message, infinity).
-
-init([ClientId]) ->
-    erlang:process_flag(trap_exit, true),
-    {ok, #state{clean_start = true,
-                client_id = ClientId,
-                last_msg = undefined
-               }
-    }.
-
-handle_call({start_session, ClientPid, ClientId, Attrs}, _From, State) ->
-    {ok, SessPid} = emqx_sm:open_session(Attrs),
-    {reply, {ok, SessPid},
-     State#state{clean_start = true,
-                 client_id = ClientId,
-                 client_pid = ClientPid,
-                 session_pid = SessPid
-                }};
-handle_call(stop_session, _From, #state{session_pid = Pid} = State) ->
-    is_pid(Pid) andalso is_process_alive(Pid) andalso emqx_sm:close_session(Pid),
-    {stop, normal, ok, State#state{session_pid = undefined}};
-handle_call(get_last_message, _From, #state{last_msg = Msg} = State) ->
-    {reply, Msg, State};
-handle_call(stop, _From, State) ->
-    {stop, normal, ok, State};
-handle_call(_Request, _From, State) ->
-    {reply, ok, State}.
-
-handle_cast(_Msg, State) ->
-    {noreply, State}.
-
-handle_info({deliver, Msg}, State) ->
-    {noreply, State#state{last_msg = Msg}};
-handle_info(_Info, State) ->
-    {noreply, State}.
-
-terminate(_Reason, _State) ->
-    ok.
-
-code_change(_OldVsn, State, _Extra) ->
-    {ok, State}.
-
-default_session_attributes(Zone, ClientId, ClientPid) ->
-    #{zone                => Zone,
-      client_id           => ClientId,
-      conn_pid            => ClientPid,
-      clean_start         => true,
-      username            => undefined,
-      expiry_interval     => 0,
-      max_inflight        => 0,
-      topic_alias_maximum => 0,
-      will_msg            => undefined
-     }.
-

+ 0 - 27
test/emqx_mod_SUITE.erl

@@ -1,27 +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_SUITE).
-
--compile(export_all).
--compile(nowarn_export_all).
-
--include("emqx.hrl").
-
-all() -> [mod_subscription_rep].
-
-mod_subscription_rep(_) -> ok.
-

+ 0 - 65
test/emqx_mod_rewrite_tests.erl

@@ -1,65 +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_tests).
-
--include_lib("emqx.hrl").
--include_lib("eunit/include/eunit.hrl").
-
-
-rules() ->
-    Rawrules1 = "x/# ^x/y/(.+)$ z/y/$1",
-    Rawrules2 = "y/+/z/# ^y/(.+)/z/(.+)$ y/z/$2",
-    Rawrules = [Rawrules1, Rawrules2],
-    Rules = lists:map(fun(Rule) ->
-                              [Topic, Re, Dest] = string:tokens(Rule, " "),
-                              {rewrite,
-                               list_to_binary(Topic),
-                               list_to_binary(Re),
-                               list_to_binary(Dest)}
-                      end, Rawrules),
-    lists:map(fun({rewrite, Topic, Re, Dest}) ->
-                      {ok, MP} = re:compile(Re),
-                      {rewrite, Topic, MP, Dest}
-              end, Rules).
-
-rewrite_subscribe_test() ->
-    Rules = rules(),
-    io:format("Rules: ~p",[Rules]),
-    ?assertEqual({ok, [{<<"test">>, opts}]},
-                 emqx_mod_rewrite:rewrite_subscribe(credentials, [{<<"test">>, opts}], Rules)),
-    ?assertEqual({ok, [{<<"z/y/test">>, opts}]},
-                 emqx_mod_rewrite:rewrite_subscribe(credentials, [{<<"x/y/test">>, opts}], Rules)),
-    ?assertEqual({ok, [{<<"y/z/test_topic">>, opts}]},
-                 emqx_mod_rewrite:rewrite_subscribe(credentials, [{<<"y/test/z/test_topic">>, opts}], Rules)).
-
-rewrite_unsubscribe_test() ->
-    Rules = rules(),
-    ?assertEqual({ok, [{<<"test">>, opts}]},
-                 emqx_mod_rewrite:rewrite_subscribe(credentials, [{<<"test">>, opts}], Rules)),
-    ?assertEqual({ok, [{<<"z/y/test">>, opts}]},
-                 emqx_mod_rewrite:rewrite_subscribe(credentials, [{<<"x/y/test">>, opts}], Rules)),
-    ?assertEqual({ok, [{<<"y/z/test_topic">>, opts}]},
-                 emqx_mod_rewrite:rewrite_subscribe(credentials, [{<<"y/test/z/test_topic">>, opts}], Rules)).
-
-rewrite_publish_test() ->
-    Rules = rules(),
-    ?assertMatch({ok, #message{topic = <<"test">>}},
-                 emqx_mod_rewrite:rewrite_publish(#message{topic = <<"test">>}, Rules)),
-    ?assertMatch({ok, #message{topic = <<"z/y/test">>}},
-                 emqx_mod_rewrite:rewrite_publish(#message{topic = <<"x/y/test">>}, Rules)),
-    ?assertMatch({ok, #message{topic = <<"y/z/test_topic">>}},
-                 emqx_mod_rewrite:rewrite_publish(#message{topic = <<"y/test/z/test_topic">>}, Rules)).

+ 0 - 45
test/emqx_mod_sup_SUITE.erl

@@ -1,45 +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_sup_SUITE).
-
--compile(export_all).
--compile(nowarn_export_all).
-
--include("emqx.hrl").
-
-all() -> [t_child_all].
-
-start_link() ->
-    Pid = spawn_link(?MODULE, echo, [0]),
-    {ok, Pid}.
-
-echo(State) ->
-    receive
-        {From, Req} ->
-            ct:pal("======from:~p, req:~p", [From, Req]),
-            From ! Req,
-            echo(State)
-    end.
-
-t_child_all(_) ->
-    {ok, Pid} = emqx_mod_sup:start_link(),
-    {ok, Child} = emqx_mod_sup:start_child(?MODULE, worker),
-    timer:sleep(10),
-    Child ! {self(), hi},
-    receive hi -> ok after 100 -> ct:fail({timeout, wait_echo}) end,
-    ok = emqx_mod_sup:stop_child(?MODULE),
-    exit(Pid, normal).

+ 39 - 10
test/emqx_mountpoint_SUITE.erl

@@ -19,20 +19,49 @@
 -compile(export_all).
 -compile(nowarn_export_all).
 
--include("emqx.hrl").
--include("emqx_mqtt.hrl").
+-import(emqx_mountpoint,
+        [ mount/2
+        , unmount/2
+        , replvar/2
+        ]).
 
+-include("emqx.hrl").
 -include_lib("eunit/include/eunit.hrl").
 
-all() -> [t_mount_unmount, t_replvar].
+all() -> emqx_ct:all(?MODULE).
 
-t_mount_unmount(_) ->
+t_mount(_) ->
     Msg = emqx_message:make(<<"clientid">>, <<"topic">>, <<"payload">>),
-    Msg2 = emqx_mountpoint:mount(<<"mount">>, Msg),
-    ?assertEqual(<<"mounttopic">>, Msg2#message.topic),
-    TopicFilter = [{<<"mounttopic">>, #{qos => ?QOS_2}}],
-    TopicFilter = emqx_mountpoint:mount(<<"mount">>, [{<<"topic">>, #{qos => ?QOS_2}}]),
-    Msg = emqx_mountpoint:unmount(<<"mount">>, Msg2).
+    TopicFilters = [{<<"topic">>, #{qos => 2}}],
+    ?assertEqual(<<"topic">>, mount(undefined, <<"topic">>)),
+    ?assertEqual(Msg, mount(undefined, Msg)),
+    ?assertEqual(TopicFilters, mount(undefined, TopicFilters)),
+    ?assertEqual(<<"device/1/topic">>,
+                 mount(<<"device/1/">>, <<"topic">>)),
+    ?assertEqual(Msg#message{topic = <<"device/1/topic">>},
+                 mount(<<"device/1/">>, Msg)),
+    ?assertEqual([{<<"device/1/topic">>, #{qos => 2}}],
+                 mount(<<"device/1/">>, TopicFilters)).
+
+t_unmount(_) ->
+    Msg = emqx_message:make(<<"clientid">>, <<"device/1/topic">>, <<"payload">>),
+    ?assertEqual(<<"topic">>, unmount(undefined, <<"topic">>)),
+    ?assertEqual(Msg, unmount(undefined, Msg)),
+    ?assertEqual(<<"topic">>, unmount(<<"device/1/">>, <<"device/1/topic">>)),
+    ?assertEqual(Msg#message{topic = <<"topic">>}, unmount(<<"device/1/">>, Msg)),
+    ?assertEqual(<<"device/1/topic">>, unmount(<<"device/2/">>, <<"device/1/topic">>)),
+    ?assertEqual(Msg#message{topic = <<"device/1/topic">>}, unmount(<<"device/2/">>, Msg)).
 
 t_replvar(_) ->
-    <<"mount/test/clientid">> = emqx_mountpoint:replvar(<<"mount/%u/%c">>, #{client_id => <<"clientid">>, username => <<"test">>}).
+    ?assertEqual(undefined, replvar(undefined, #{})),
+    ?assertEqual(<<"mount/user/clientid/">>,
+                 replvar(<<"mount/%u/%c/">>,
+                         #{client_id => <<"clientid">>,
+                           username => <<"user">>
+                          })),
+    ?assertEqual(<<"mount/%u/clientid/">>,
+                 replvar(<<"mount/%u/%c/">>,
+                         #{client_id => <<"clientid">>,
+                           username => undefined
+                          })).
+

+ 0 - 133
test/emqx_mqtt_caps_SUITE.erl

@@ -1,133 +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_mqtt_caps_SUITE).
-
--include_lib("eunit/include/eunit.hrl").
-
--include("emqx.hrl").
--include("emqx_mqtt.hrl").
-
-%% CT
--compile(export_all).
--compile(nowarn_export_all).
-
-all() -> [t_get_set_caps, t_check_pub, t_check_sub].
-
-t_get_set_caps(_) ->
-    {ok, _} = emqx_zone:start_link(),
-    Caps = #{
-        max_packet_size => ?MAX_PACKET_SIZE,
-        max_clientid_len => ?MAX_CLIENTID_LEN,
-        max_topic_alias => 0,
-        max_topic_levels => 0,
-        max_qos_allowed => ?QOS_2,
-        mqtt_retain_available => true,
-        mqtt_shared_subscription => true,
-        mqtt_wildcard_subscription => true
-    },
-    Caps2 = Caps#{max_packet_size => 1048576},
-    case emqx_mqtt_caps:get_caps(zone) of
-        Caps -> ok;
-        Caps2 -> ok
-    end,
-    PubCaps = #{
-        max_qos_allowed => ?QOS_2,
-        mqtt_retain_available => true,
-        max_topic_alias => 0
-    },
-    PubCaps = emqx_mqtt_caps:get_caps(zone, publish),
-    NewPubCaps = PubCaps#{max_qos_allowed => ?QOS_1},
-    emqx_zone:set_env(zone, '$mqtt_pub_caps', NewPubCaps),
-    timer:sleep(100),
-    NewPubCaps = emqx_mqtt_caps:get_caps(zone, publish),
-    SubCaps = #{
-        max_topic_levels => 0,
-        max_qos_allowed => ?QOS_2,
-        mqtt_shared_subscription => true,
-        mqtt_wildcard_subscription => true
-    },
-    SubCaps = emqx_mqtt_caps:get_caps(zone, subscribe),
-    emqx_zone:stop().
-
-t_check_pub(_) ->
-    {ok, _} = emqx_zone:start_link(),
-    PubCaps = #{
-        max_qos_allowed => ?QOS_1,
-        mqtt_retain_available => false,
-        max_topic_alias => 4
-    },
-    emqx_zone:set_env(zone, '$mqtt_pub_caps', PubCaps),
-    timer:sleep(100),
-    ct:log("~p", [emqx_mqtt_caps:get_caps(zone, publish)]),
-    BadPubProps1 = #{
-        qos => ?QOS_2,
-        retain => false
-    },
-    {error, ?RC_QOS_NOT_SUPPORTED} = emqx_mqtt_caps:check_pub(zone, BadPubProps1),
-    BadPubProps2 = #{
-        qos => ?QOS_1,
-        retain => true
-    },
-    {error, ?RC_RETAIN_NOT_SUPPORTED} = emqx_mqtt_caps:check_pub(zone, BadPubProps2),
-    BadPubProps3 = #{
-        qos => ?QOS_1,
-        retain => false,
-        topic_alias => 5
-    },
-    {error, ?RC_TOPIC_ALIAS_INVALID} = emqx_mqtt_caps:check_pub(zone, BadPubProps3),
-    PubProps = #{
-        qos => ?QOS_1,
-        retain => false
-    },
-    ok = emqx_mqtt_caps:check_pub(zone, PubProps),
-    emqx_zone:stop().
-
-t_check_sub(_) ->
-    {ok, _} = emqx_zone:start_link(),
-
-    Opts = #{qos => ?QOS_2, share => true, rc => 0},
-    Caps = #{
-        max_topic_levels => 0,
-        max_qos_allowed => ?QOS_2,
-        mqtt_shared_subscription => true,
-        mqtt_wildcard_subscription => true
-    },
-
-    ok = do_check_sub([{<<"client/stat">>, Opts}], [{<<"client/stat">>, Opts}]),
-    ok = do_check_sub(Caps#{max_qos_allowed => ?QOS_1}, [{<<"client/stat">>, Opts}], [{<<"client/stat">>, Opts#{qos => ?QOS_1}}]),
-    ok = do_check_sub(Caps#{max_topic_levels => 1},
-                        [{<<"client/stat">>, Opts}],
-                        [{<<"client/stat">>, Opts#{rc => ?RC_TOPIC_FILTER_INVALID}}]),
-    ok = do_check_sub(Caps#{mqtt_shared_subscription => false},
-                        [{<<"client/stat">>, Opts}],
-                        [{<<"client/stat">>, Opts#{rc => ?RC_SHARED_SUBSCRIPTIONS_NOT_SUPPORTED}}]),
-
-    ok = do_check_sub(Caps#{mqtt_wildcard_subscription => false},
-                        [{<<"vlient/+/dsofi">>, Opts}],
-                        [{<<"vlient/+/dsofi">>, Opts#{rc => ?RC_WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED}}]),
-    emqx_zone:stop().
-
-
-
-do_check_sub(TopicFilters, Topics) ->
-    {ok, Topics} = emqx_mqtt_caps:check_sub(zone, TopicFilters),
-    ok.
-do_check_sub(Caps, TopicFilters, Topics) ->
-    emqx_zone:set_env(zone, '$mqtt_sub_caps', Caps),
-    timer:sleep(100),
-    {_, Topics} = emqx_mqtt_caps:check_sub(zone, TopicFilters),
-    ok.

+ 0 - 117
test/emqx_mqtt_packet_SUITE.erl

@@ -1,117 +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_mqtt_packet_SUITE).
-
--compile(export_all).
--compile(nowarn_export_all).
-
--import(emqx_frame, [serialize/1]).
-
--include("emqx_mqtt.hrl").
-
--include_lib("eunit/include/eunit.hrl").
-
--define(INVALID_RESERVED, 1).
-
--define(CONNECT_INVALID_PACKET(Var),
-    #mqtt_packet{header   = #mqtt_packet_header{type = ?INVALID_RESERVED},
-                 variable = Var}).
-
--define(CASE1_PROTOCOL_NAME, ?CONNECT_PACKET(#mqtt_packet_connect{
-                                proto_name = <<"MQTC">>,
-                                client_id = <<"mqtt_protocol_name">>,
-                                username  = <<"admin">>,
-                                password  = <<"public">>})).
-
--define(CASE2_PROTOCAL_VER, ?CONNECT_PACKET(#mqtt_packet_connect{
-                                client_id = <<"mqtt_client">>,
-                                proto_ver = 6,
-                                username  = <<"admin">>,
-                                password  = <<"public">>})).
-
--define(CASE3_PROTOCAL_INVALID_RESERVED, ?CONNECT_INVALID_PACKET(#mqtt_packet_connect{
-                                client_id = <<"mqtt_client">>,
-                                proto_ver = 5,
-                                username  = <<"admin">>,
-                                password  = <<"public">>})).
-
--define(PROTOCOL5, ?CONNECT_PACKET(#mqtt_packet_connect{
-                                proto_ver = 5,
-                                keepalive = 60,
-                                properties = #{'Message-Expiry-Interval' => 3600},
-                                client_id = <<"mqtt_client">>,
-                                will_topic = <<"will_tipic">>,
-                                will_payload = <<"will message">>,
-                                username  = <<"admin">>,
-                                password  = <<"public">>})).
-
-
-
-all() -> [{group, connect}].
-
-groups() -> [{connect, [sequence],
-              [case1_protocol_name,
-               case2_protocol_ver%,
-             %TOTO case3_invalid_reserved
-              ]}].
-
-init_per_suite(Config) ->
-    emqx_ct_helpers:start_apps([]),
-    Config.
-
-end_per_suite(_Config) ->
-    emqx_ct_helpers:stop_apps([]).
-
-init_per_group(_Group, Config) ->
-    Config.
-
-end_per_group(_Group, _Config) ->
-	ok.
-
-case1_protocol_name(_) ->
-    {ok, Sock} = emqx_client_sock:connect({127,0,0,1}, 1883, [binary, {packet, raw}, {active, false}], 3000),
-    MqttPacket = serialize(?CASE1_PROTOCOL_NAME),
-    emqx_client_sock:send(Sock, MqttPacket),
-    {ok, Data} = gen_tcp:recv(Sock, 0),
-    {ok, ?CONNACK_PACKET(?CONNACK_PROTO_VER), <<>>, _} = raw_recv_pase(Data),
-    Disconnect  = gen_tcp:recv(Sock, 0),
-    ?assertEqual({error, closed}, Disconnect).
-
-case2_protocol_ver(_) ->
-    {ok, Sock} = emqx_client_sock:connect({127,0,0,1}, 1883, [binary, {packet, raw}, {active, false}], 3000),
-    Packet = serialize(?CASE2_PROTOCAL_VER),
-    emqx_client_sock:send(Sock, Packet),
-    {ok, Data} = gen_tcp:recv(Sock, 0),
-    %% case1 Unacceptable protocol version
-    {ok, ?CONNACK_PACKET(?CONNACK_PROTO_VER), <<>>, _} = raw_recv_pase(Data),
-    Disconnect  = gen_tcp:recv(Sock, 0),
-    ?assertEqual({error, closed}, Disconnect).
-
-case3_invalid_reserved(_) ->
-    {ok, Sock} = emqx_client_sock:connect({127,0,0,1}, 1883, [binary, {packet, raw}, {active, false}], 3000),
-    Packet = serialize(?CASE3_PROTOCAL_INVALID_RESERVED),
-    emqx_client_sock:send(Sock, Packet),
-    {ok, Data} = gen_tcp:recv(Sock, 0),
-    %% case1 Unacceptable protocol version
-    ct:log("Data:~p~n", [raw_recv_pase(Data)]),
-    {ok, ?CONNACK_PACKET(?CONNACK_PROTO_VER), _} = raw_recv_pase(Data),
-    Disconnect  = gen_tcp:recv(Sock, 0),
-    ?assertEqual({error, closed}, Disconnect).
-
-raw_recv_pase(P) ->
-    emqx_frame:parse(P, {none, #{max_packet_size => ?MAX_PACKET_SIZE,
-                                 version         => ?MQTT_PROTO_V4} }).

+ 14 - 2
test/emqx_mqtt_props_SUITE.erl

@@ -21,9 +21,21 @@
 
 -include("emqx_mqtt.hrl").
 
-all() -> [t_mqtt_properties_all].
+all() -> emqx_ct:all(?MODULE).
 
-t_mqtt_properties_all(_) ->
+t_id(_) ->
+    'TODO'.
+
+t_name(_) ->
+    'TODO'.
+
+t_filter(_) ->
+    'TODO'.
+
+t_validate(_) ->
+    'TODO'.
+
+deprecated_mqtt_properties_all(_) ->
     Props = emqx_mqtt_props:filter(?CONNECT, #{'Session-Expiry-Interval' => 1, 'Maximum-Packet-Size' => 255}),
     ok = emqx_mqtt_props:validate(Props),
     #{} = emqx_mqtt_props:filter(?CONNECT, #{'Maximum-QoS' => ?QOS_2}).

+ 9 - 7
test/emqx_mqueue_SUITE.erl

@@ -26,8 +26,7 @@
 
 -define(Q, emqx_mqueue).
 
-all() -> [t_in, t_in_qos0, t_out, t_simple_mqueue, t_infinity_simple_mqueue,
-          t_priority_mqueue, t_infinity_priority_mqueue].
+all() -> emqx_ct:all(?MODULE).
 
 t_in(_) ->
     Opts = #{max_len => 5, store_qos0 => true},
@@ -130,15 +129,18 @@ t_infinity_priority_mqueue(_) ->
     ?assertEqual(510, ?Q:len(Qx)),
     ?assertEqual([{len, 510}, {max_len, 0}, {dropped, 0}], ?Q:stats(Qx)).
 
-t_priority_mqueue2(_) ->
-    Opts = #{max_length => 2, store_qos0 => false},
-    Q = ?Q:init("priority_queue2_test", Opts),
+%%TODO: fixme later
+t_length_priority_mqueue(_) ->
+    Opts = #{max_len => 2,
+             store_qos0 => false
+            },
+    Q = ?Q:init(Opts),
     2 = ?Q:max_len(Q),
     {_, Q1} = ?Q:in(#message{topic = <<"x">>, qos = 1, payload = <<1>>}, Q),
     {_, Q2} = ?Q:in(#message{topic = <<"x">>, qos = 1, payload = <<2>>}, Q1),
     {_, Q3} = ?Q:in(#message{topic = <<"y">>, qos = 1, payload = <<3>>}, Q2),
     {_, Q4} = ?Q:in(#message{topic = <<"y">>, qos = 1, payload = <<4>>}, Q3),
-    4 = ?Q:len(Q4),
+    ?assertEqual(2, ?Q:len(Q4)),
     {{value, _Val}, Q5} = ?Q:out(Q4),
-    3 = ?Q:len(Q5).
+    ?assertEqual(1, ?Q:len(Q5)).
 

+ 2 - 3
test/emqx_os_mon_SUITE.erl

@@ -21,9 +21,7 @@
 
 -include_lib("eunit/include/eunit.hrl").
 
--include_lib("common_test/include/ct.hrl").
-
-all() -> [t_api].
+all() -> emqx_ct:all(?MODULE).
 
 init_per_suite(Config) ->
     application:ensure_all_started(os_mon),
@@ -56,3 +54,4 @@ t_api(_) ->
     % timer:sleep(3000),
     % ?assertEqual(false, lists:keymember(cpu_high_watermark, 1, alarm_handler:get_alarms())),
     ok.
+

+ 22 - 27
test/emqx_packet_SUITE.erl

@@ -20,35 +20,28 @@
 -compile(nowarn_export_all).
 
 -include("emqx.hrl").
-
 -include("emqx_mqtt.hrl").
 
 -include_lib("eunit/include/eunit.hrl").
 
-all() ->
-    [
-        packet_proto_name,
-        packet_type_name,
-        packet_validate,
-        packet_message,
-        packet_format,
-        packet_will_msg
-    ].
+all() -> emqx_ct:all(?MODULE).
 
-packet_proto_name(_) ->
+t_proto_name(_) ->
     ?assertEqual(<<"MQIsdp">>, emqx_packet:protocol_name(3)),
     ?assertEqual(<<"MQTT">>, emqx_packet:protocol_name(4)),
     ?assertEqual(<<"MQTT">>, emqx_packet:protocol_name(5)).
 
-packet_type_name(_) ->
-    ?assertEqual('CONNECT',     emqx_packet:type_name(?CONNECT)),
+t_type_name(_) ->
+    ?assertEqual('CONNECT', emqx_packet:type_name(?CONNECT)),
     ?assertEqual('UNSUBSCRIBE', emqx_packet:type_name(?UNSUBSCRIBE)).
 
-packet_validate(_) ->
-    ?assert(emqx_packet:validate(?SUBSCRIBE_PACKET(15, #{'Subscription-Identifier' => 1}, [{<<"topic">>, #{qos => ?QOS_0}}]))),
+t_validate(_) ->
+    ?assert(emqx_packet:validate(?SUBSCRIBE_PACKET(15, #{'Subscription-Identifier' => 1},
+                                                   [{<<"topic">>, #{qos => ?QOS_0}}]))),
     ?assert(emqx_packet:validate(?UNSUBSCRIBE_PACKET(89, [<<"topic">>]))),
     ?assert(emqx_packet:validate(?CONNECT_PACKET(#mqtt_packet_connect{}))),
-    ?assert(emqx_packet:validate(?PUBLISH_PACKET(1, <<"topic">>, 1, #{'Response-Topic' => <<"responsetopic">>, 'Topic-Alias' => 1}, <<"payload">>))),
+    Props = #{'Response-Topic' => <<"responsetopic">>, 'Topic-Alias' => 1},
+    ?assert(emqx_packet:validate(?PUBLISH_PACKET(?QOS_1, <<"topic">>, 1, Props, <<"payload">>))),
     ?assert(emqx_packet:validate(?CONNECT_PACKET(#mqtt_packet_connect{properties = #{'Receive-Maximum' => 1}}))),
     ?assertError(subscription_identifier_invalid,
                  emqx_packet:validate(
@@ -89,7 +82,7 @@ packet_validate(_) ->
                                       properties =
                                           #{'Receive-Maximum' => 0}}))).
 
-packet_message(_) ->
+t_from_to_message(_) ->
     Pkt = #mqtt_packet{header = #mqtt_packet_header{type   = ?PUBLISH,
                                                     qos    = ?QOS_0,
                                                     retain = false,
@@ -111,7 +104,7 @@ packet_message(_) ->
     Msg5 = Msg4#message{timestamp = Msg3#message.timestamp, id = Msg3#message.id},
     Msg5 = Msg3.
 
-packet_format(_) ->
+t_packet_format(_) ->
     io:format("~s", [emqx_packet:format(?CONNECT_PACKET(#mqtt_packet_connect{}))]),
     io:format("~s", [emqx_packet:format(?CONNACK_PACKET(?CONNACK_SERVER))]),
     io:format("~s", [emqx_packet:format(?PUBLISH_PACKET(?QOS_1, 1))]),
@@ -123,15 +116,17 @@ packet_format(_) ->
     io:format("~s", [emqx_packet:format(?UNSUBSCRIBE_PACKET(89, [<<"t">>, <<"t2">>]))]),
     io:format("~s", [emqx_packet:format(?UNSUBACK_PACKET(90))]).
 
-packet_will_msg(_) ->
-    Pkt = #mqtt_packet_connect{ will_flag = true,
-                                client_id = <<"clientid">>,
-                                username = "test",
-                                will_retain = true,
-                                will_qos = ?QOS_2,
-                                will_topic = <<"topic">>,
-                                will_props = #{},
-                                will_payload = <<"payload">>},
+t_will_msg(_) ->
+    Pkt = #mqtt_packet_connect{will_flag = true,
+                               client_id = <<"clientid">>,
+                               username = "test",
+                               will_retain = true,
+                               will_qos = ?QOS_2,
+                               will_topic = <<"topic">>,
+                               will_props = #{},
+                               will_payload = <<"payload">>
+                              },
     Msg = emqx_packet:will_msg(Pkt),
     ?assertEqual(<<"clientid">>, Msg#message.from),
     ?assertEqual(<<"topic">>, Msg#message.topic).
+

+ 2 - 2
test/emqx_pd_SUITE.erl

@@ -21,9 +21,9 @@
 
 -include_lib("eunit/include/eunit.hrl").
 
-all() -> [update_counter].
+all() -> emqx_ct:all(?MODULE).
 
-update_counter(_) ->
+t_update_counter(_) ->
     ?assertEqual(undefined, emqx_pd:update_counter(bytes, 1)),
     ?assertEqual(1, emqx_pd:update_counter(bytes, 1)),
     ?assertEqual(2, emqx_pd:update_counter(bytes, 1)),

+ 1 - 2
test/emqx_pmon_SUITE.erl

@@ -21,8 +21,7 @@
 
 -include_lib("eunit/include/eunit.hrl").
 
-all() ->
-    [t_monitor, t_find, t_erase].
+all() -> emqx_ct:all(?MODULE).
 
 t_monitor(_) ->
     PMon = emqx_pmon:new(),

+ 21 - 12
test/emqx_pool_SUITE.erl

@@ -19,20 +19,23 @@
 -compile(export_all).
 -compile(nowarn_export_all).
 
--include("emqx_mqtt.hrl").
 -include_lib("eunit/include/eunit.hrl").
 
 all() ->
-    [
-     {group, submit_case},
-     {group, async_submit_case},
+    [{group, submit},
+     {group, async_submit},
      t_unexpected
     ].
 
 groups() ->
-    [
-     {submit_case, [sequence], [submit_mfa, submit_fa]},
-     {async_submit_case, [sequence], [async_submit_mfa, async_submit_crash]}
+    [{submit, [sequence],
+      [t_submit_mfa,
+       t_submit_fa
+      ]},
+     {async_submit, [sequence],
+      [t_async_submit_mfa,
+       t_async_submit_crash
+      ]}
     ].
 
 init_per_suite(Config) ->
@@ -48,22 +51,28 @@ init_per_testcase(_, Config) ->
 
 end_per_testcase(_, Config) ->
     Sup = proplists:get_value(pool_sup, Config),
+    %% ???
     exit(Sup, normal).
 
-submit_mfa(_Config) ->
+t_submit_mfa(_Config) ->
     Result = emqx_pool:submit({?MODULE, test_mfa, []}),
     ?assertEqual(15, Result).
 
-submit_fa(_Config) ->
-    Fun = fun(X) -> case X rem 2 of 0 -> {true, X div 2}; _ -> false end end,
+t_submit_fa(_Config) ->
+    Fun = fun(X) ->
+              case X rem 2 of
+                  0 -> {true, X div 2};
+                  _ -> false
+              end
+          end,
     Result = emqx_pool:submit(Fun, [2]),
     ?assertEqual({true, 1}, Result).
 
-async_submit_mfa(_Config) ->
+t_async_submit_mfa(_Config) ->
     emqx_pool:async_submit({?MODULE, test_mfa, []}),
     emqx_pool:async_submit(fun ?MODULE:test_mfa/0, []).
 
-async_submit_crash(_) ->
+t_async_submit_crash(_) ->
     emqx_pool:async_submit(fun() -> error(unexpected_error) end).
 
 t_unexpected(_) ->

+ 5 - 6
test/emqx_pqueue_SUITE.erl

@@ -16,15 +16,15 @@
 
 -module(emqx_pqueue_SUITE).
 
--include("emqx_mqtt.hrl").
--include_lib("eunit/include/eunit.hrl").
-
 -compile(export_all).
 -compile(nowarn_export_all).
 
+-include_lib("eunit/include/eunit.hrl").
+
 -define(PQ, emqx_pqueue).
+-define(SUITE, ?MODULE).
 
-all() -> [t_priority_queue_plen, t_priority_queue_out2, t_priority_queues].
+all() -> emqx_ct:all(?SUITE).
 
 t_priority_queue_plen(_) ->
     Q = ?PQ:new(),
@@ -87,7 +87,7 @@ t_priority_queues(_) ->
 
     [{1, c}, {1, d}, {0, a}, {0, b}] = ?PQ:to_list(PQueue4),
     PQueue4 = ?PQ:from_list([{1, c}, {1, d}, {0, a}, {0, b}]),
-    
+
     empty = ?PQ:highest(?PQ:new()),
     0 = ?PQ:highest(PQueue1),
     1 = ?PQ:highest(PQueue4),
@@ -122,4 +122,3 @@ t_priority_queues(_) ->
     {pqueue,[{-1,{queue,[f],[d,f,d],4}},
              {0,{queue,[b],[a,b,a],4}}]} = ?PQ:join(PQueue8, PQueue8).
 
-

+ 0 - 613
test/emqx_protocol_SUITE.erl

@@ -1,613 +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_protocol_SUITE).
-
--compile(export_all).
--compile(nowarn_export_all).
-
--include_lib("eunit/include/eunit.hrl").
-
--include_lib("common_test/include/ct.hrl").
-
--include("emqx_mqtt.hrl").
-
--define(TOPICS, [<<"TopicA">>, <<"TopicA/B">>, <<"Topic/C">>, <<"TopicA/C">>,
-                 <<"/TopicA">>]).
-
--define(CLIENT, ?CONNECT_PACKET(#mqtt_packet_connect{
-                                   client_id = <<"mqtt_client">>,
-                                   username  = <<"emqx">>,
-                                   password  = <<"public">>})).
-
-all() ->
-    [{group, mqtt_common},
-     {group, mqttv4},
-     {group, mqttv5},
-     {group, acl},
-     {group, frame_partial}].
-
-groups() ->
-    [{mqtt_common, [sequence],
-      [will_topic_check,
-       will_acl_check]},
-     {mqttv4, [sequence],
-      [connect_v4,
-       subscribe_v4]},
-     {mqttv5, [sequence],
-      [connect_v5,
-       subscribe_v5]},
-     {acl, [sequence],
-      [acl_deny_action_ct]},
-     {frame_partial, [sequence],
-      [handle_followed_packet]}].
-
-init_per_suite(Config) ->
-    emqx_ct_helpers:start_apps([], fun set_special_configs/1),
-    MqttCaps = maps:from_list(emqx_mqtt_caps:default_caps()),
-    emqx_zone:set_env(external, '$mqtt_caps', MqttCaps#{max_topic_alias => 20}),
-    Config.
-
-end_per_suite(_Config) ->
-    emqx_ct_helpers:stop_apps([]).
-
-batch_connect(NumberOfConnections) ->
-    batch_connect([], NumberOfConnections).
-
-batch_connect(Socks, 0) ->
-    Socks;
-batch_connect(Socks, NumberOfConnections) ->
-    {ok, Sock} = emqx_client_sock:connect({127, 0, 0, 1}, 1883,
-                                          [binary, {packet, raw}, {active, false}],
-                                          3000),
-    batch_connect([Sock | Socks], NumberOfConnections - 1).
-
-with_connection(DoFun, NumberOfConnections) ->
-    Socks = batch_connect(NumberOfConnections),
-    try
-        DoFun(Socks)
-    after
-        lists:foreach(fun(Sock) ->
-                         emqx_client_sock:close(Sock)
-                      end, Socks)
-    end.
-
-with_connection(DoFun) ->
-    with_connection(DoFun, 1).
-
-handle_followed_packet(_Config) ->
-    ConnPkt = <<16,12,0,4,77,81,84,84,4,2,0,60,0,0>>,
-    PartialPkt1 = <<50,182,1,0,4,116,101,115,116,0,1,48,48,48,48,48,48,48,48,48,48,48,48,48,
-                    48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
-                    48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
-                    48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
-                    48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48>>,
-    PartialPkt2 = <<48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
-                    48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
-                    48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48>>,
-
-    %% This is a PUBLISH message (Qos=1)
-    PubPkt = <<PartialPkt1/binary, PartialPkt2/binary>>,
-    ComplexPkt = <<PubPkt/binary, PubPkt/binary, PubPkt/binary, PartialPkt1/binary>>,
-
-    AssertConnAck = fun(R) -> ?assertEqual({ok, <<32,2,0,0>>}, R) end,
-    AssertPubAck  = fun(R) -> ?assertEqual({ok, <<64,2,0,1>>}, R) end,
-
-    {ok, Sock} = gen_tcp:connect("127.0.0.1", 1883, [{active, false}, binary]),
-
-    %% CONNECT
-    ok = gen_tcp:send(Sock, ConnPkt),
-    AssertConnAck(gen_tcp:recv(Sock, 4, 500)),
-
-    %% Once Publish
-    ok = gen_tcp:send(Sock, PubPkt),
-    AssertPubAck(gen_tcp:recv(Sock, 4, 500)),
-
-    %% Complex Packet
-    ok = gen_tcp:send(Sock, ComplexPkt),
-    AssertPubAck(gen_tcp:recv(Sock, 4, 500)),
-    AssertPubAck(gen_tcp:recv(Sock, 4, 500)),
-    AssertPubAck(gen_tcp:recv(Sock, 4, 500)),
-
-    ok = gen_tcp:send(Sock, PartialPkt2),
-    AssertPubAck(gen_tcp:recv(Sock, 4, 500)),
-    gen_tcp:close(Sock).
-
-connect_v4(_) ->
-    with_connection(fun([Sock]) ->
-                            emqx_client_sock:send(Sock, raw_send_serialize(?PACKET(?PUBLISH))),
-                            {error, closed} =gen_tcp:recv(Sock, 0)
-                    end),
-    with_connection(fun([Sock]) ->
-                            ConnectPacket = raw_send_serialize(?CONNECT_PACKET
-                                                                   (#mqtt_packet_connect{
-                                                                       client_id = <<"mqttv4_client">>,
-                                                                       username = <<"admin">>,
-                                                                       password = <<"public">>,
-                                                                       proto_ver = ?MQTT_PROTO_V4
-                                                                      })),
-                            emqx_client_sock:send(Sock, ConnectPacket),
-                            {ok, Data} = gen_tcp:recv(Sock, 0),
-                            {ok, ?CONNACK_PACKET(?CONNACK_ACCEPT), <<>>, _} = raw_recv_parse(Data, ?MQTT_PROTO_V4),
-
-                            emqx_client_sock:send(Sock, ConnectPacket),
-                            {error, closed} = gen_tcp:recv(Sock, 0)
-                    end),
-    ok.
-
-
-connect_v5(_) ->
-    with_connection(fun([Sock]) ->
-                            emqx_client_sock:send(Sock,
-                                                  raw_send_serialize(
-                                                    ?CONNECT_PACKET(#mqtt_packet_connect{
-                                                                       proto_ver  = ?MQTT_PROTO_V5,
-                                                                       properties =
-                                                                           #{'Request-Response-Information' => -1}}))),
-                            {ok, Data} = gen_tcp:recv(Sock, 0),
-                            {ok, ?DISCONNECT_PACKET(?RC_PROTOCOL_ERROR), <<>>, _} = raw_recv_parse(Data, ?MQTT_PROTO_V5)
-                    end),
-
-    with_connection(fun([Sock]) ->
-                            emqx_client_sock:send(Sock,
-                                                  raw_send_serialize(
-                                                    ?CONNECT_PACKET(
-                                                       #mqtt_packet_connect{
-                                                          proto_ver  = ?MQTT_PROTO_V5,
-                                                          properties =
-                                                               #{'Request-Problem-Information' => 2}}))),
-                            {ok, Data} = gen_tcp:recv(Sock, 0),
-                            {ok, ?DISCONNECT_PACKET(?RC_PROTOCOL_ERROR), <<>>, _} = raw_recv_parse(Data, ?MQTT_PROTO_V5)
-                    end),
-
-    with_connection(fun([Sock]) ->
-                            emqx_client_sock:send(Sock,
-                                                  raw_send_serialize(
-                                                    ?CONNECT_PACKET(
-                                                       #mqtt_packet_connect{
-                                                          proto_ver  = ?MQTT_PROTO_V5,
-                                                          properties =
-                                                              #{'Request-Response-Information' => 1}})
-                                                  )),
-                            {ok, Data} = gen_tcp:recv(Sock, 0),
-                            {ok, ?CONNACK_PACKET(?RC_SUCCESS, 0, Props), <<>>, _} =
-                                raw_recv_parse(Data, ?MQTT_PROTO_V5),
-                            ?assertNot(maps:is_key('Response-Information', Props))
-                    end),
-
-    % topic alias = 0
-    with_connection(fun([Sock]) ->
-
-                            %% ct:log("emqx_protocol: ~p~n", [emqx_zone:get_zone(external, max_topic_alias)]),
-                            emqx_client_sock:send(Sock,
-                                                  raw_send_serialize(
-                                                      ?CONNECT_PACKET(
-                                                          #mqtt_packet_connect{
-                                                              client_id  = "hello",
-                                                              proto_ver  = ?MQTT_PROTO_V5,
-                                                              properties =
-                                                                  #{'Topic-Alias-Maximum' => 10}}),
-                                                      #{version => ?MQTT_PROTO_V5}
-                                                  )),
-                            {ok, Data} = gen_tcp:recv(Sock, 0),
-                            {ok, ?CONNACK_PACKET(?RC_SUCCESS, 0,
-                                                 #{'Topic-Alias-Maximum' := 20}), <<>>, _} =
-                                raw_recv_parse(Data, ?MQTT_PROTO_V5),
-                            emqx_client_sock:send(Sock,
-                                                  raw_send_serialize(
-                                                      ?PUBLISH_PACKET(?QOS_1, <<"TopicA">>, 1, #{'Topic-Alias' => 0}, <<"hello">>),
-                                                      #{version => ?MQTT_PROTO_V5}
-                                                  )),
-
-                            {ok, Data2} = gen_tcp:recv(Sock, 0),
-                            {ok, ?DISCONNECT_PACKET(?RC_TOPIC_ALIAS_INVALID), <<>>, _} = raw_recv_parse(Data2, ?MQTT_PROTO_V5)
-                    end),
-
-    % topic alias maximum
-    with_connection(fun([Sock]) ->
-                            emqx_client_sock:send(Sock,
-                                                  raw_send_serialize(
-                                                      ?CONNECT_PACKET(
-                                                          #mqtt_packet_connect{
-                                                              proto_ver  = ?MQTT_PROTO_V5,
-                                                              properties =
-                                                                  #{'Topic-Alias-Maximum' => 10}}),
-                                                      #{version => ?MQTT_PROTO_V5}
-                                                  )),
-                            {ok, Data} = gen_tcp:recv(Sock, 0),
-                            {ok, ?CONNACK_PACKET(?RC_SUCCESS, 0,
-                                                 #{'Topic-Alias-Maximum' := 20}), <<>>, _} =
-                                raw_recv_parse(Data, ?MQTT_PROTO_V5),
-
-                            emqx_client_sock:send(Sock, raw_send_serialize(?SUBSCRIBE_PACKET(1, [{<<"TopicA">>, #{rh  => 1,
-                                             qos => ?QOS_2,
-                                             rap => 0,
-                                             nl  => 0,
-                                             rc  => 0}}]), #{version => ?MQTT_PROTO_V5})),
-
-                            {ok, Data2} = gen_tcp:recv(Sock, 0),
-                            {ok, ?SUBACK_PACKET(1, #{}, [2]), <<>>, _} = raw_recv_parse(Data2, ?MQTT_PROTO_V5),
-
-                            emqx_client_sock:send(Sock,
-                                                  raw_send_serialize(
-                                                      ?PUBLISH_PACKET(?QOS_1, <<"TopicA">>, 1, #{'Topic-Alias' => 15}, <<"hello">>),
-                                                      #{version => ?MQTT_PROTO_V5}
-                                                  )),
-
-                            {ok, Data3} = gen_tcp:recv(Sock, 6),
-
-                            {ok, ?PUBACK_PACKET(1, 0), <<>>, _} = raw_recv_parse(Data3, ?MQTT_PROTO_V5),
-
-                            {ok, Data4} = gen_tcp:recv(Sock, 0),
-
-                            {ok, ?PUBLISH_PACKET(?QOS_1, <<"TopicA">>, _, <<"hello">>), <<>>, _} = raw_recv_parse(Data4, ?MQTT_PROTO_V5),
-
-                            emqx_client_sock:send(Sock,
-                                                  raw_send_serialize(
-                                                      ?PUBLISH_PACKET(?QOS_1, <<"TopicA">>, 2, #{'Topic-Alias' => 21}, <<"hello">>),
-                                                      #{version => ?MQTT_PROTO_V5}
-                                                  )),
-
-                            {ok, Data5} = gen_tcp:recv(Sock, 0),
-                            {ok, ?DISCONNECT_PACKET(?RC_TOPIC_ALIAS_INVALID), <<>>, _} = raw_recv_parse(Data5, ?MQTT_PROTO_V5)
-                    end),
-
-    % test clean start
-    with_connection(fun([Sock]) ->
-                            emqx_client_sock:send(Sock,
-                                                    raw_send_serialize(
-                                                        ?CONNECT_PACKET(
-                                                            #mqtt_packet_connect{
-                                                                proto_ver   = ?MQTT_PROTO_V5,
-                                                                clean_start = true,
-                                                                client_id   = <<"myclient">>,
-                                                                properties  =
-                                                                    #{'Session-Expiry-Interval' => 10}})
-                                                  )),
-                            {ok, Data} = gen_tcp:recv(Sock, 0),
-                            {ok, ?CONNACK_PACKET(?RC_SUCCESS, 0), <<>>, _} = raw_recv_parse(Data, ?MQTT_PROTO_V5),
-                            emqx_client_sock:send(Sock, raw_send_serialize(
-                                                            ?DISCONNECT_PACKET(?RC_SUCCESS)
-                                                  ))
-                    end),
-
-    timer:sleep(1000),
-
-    with_connection(fun([Sock]) ->
-                            emqx_client_sock:send(Sock,
-                                                    raw_send_serialize(
-                                                        ?CONNECT_PACKET(
-                                                            #mqtt_packet_connect{
-                                                                proto_ver   = ?MQTT_PROTO_V5,
-                                                                clean_start = false,
-                                                                client_id   = <<"myclient">>,
-                                                                properties  =
-                                                                    #{'Session-Expiry-Interval' => 10}})
-                                                  )),
-                            {ok, Data} = gen_tcp:recv(Sock, 0),
-                            {ok, ?CONNACK_PACKET(?RC_SUCCESS, 1), <<>>, _} = raw_recv_parse(Data, ?MQTT_PROTO_V5)
-                    end),
-
-    % test will message publish and cancel
-    with_connection(fun([Sock]) ->
-                            emqx_client_sock:send(Sock,
-                                                    raw_send_serialize(
-                                                        ?CONNECT_PACKET(
-                                                            #mqtt_packet_connect{
-                                                                proto_ver    = ?MQTT_PROTO_V5,
-                                                                clean_start  = true,
-                                                                client_id    = <<"myclient">>,
-                                                                will_flag    = true,
-                                                                will_qos     = ?QOS_1,
-                                                                will_retain  = false,
-                                                                will_props   = #{'Will-Delay-Interval' => 5},
-                                                                will_topic   = <<"TopicA">>,
-                                                                will_payload = <<"will message">>,
-                                                                properties   = #{'Session-Expiry-Interval' => 0}
-                                                            }
-                                                        )
-                                                    )
-                            ),
-                            {ok, Data} = gen_tcp:recv(Sock, 0),
-                            {ok, ?CONNACK_PACKET(?RC_SUCCESS, 0), <<>>, _} = raw_recv_parse(Data, ?MQTT_PROTO_V5),
-
-                            {ok, Sock2} = emqx_client_sock:connect({127, 0, 0, 1}, 1883,
-                                                                   [binary, {packet, raw},
-                                                                    {active, false}], 3000),
-
-                            do_connect(Sock2, ?MQTT_PROTO_V5),
-
-                            emqx_client_sock:send(Sock2, raw_send_serialize(?SUBSCRIBE_PACKET(1, [{<<"TopicA">>, #{rh  => 1,
-                                             qos => ?QOS_2,
-                                             rap => 0,
-                                             nl  => 0,
-                                             rc  => 0}}]), #{version => ?MQTT_PROTO_V5})),
-
-                            {ok, SubData} = gen_tcp:recv(Sock2, 0),
-                            {ok, ?SUBACK_PACKET(1, #{}, [2]), <<>>, _} = raw_recv_parse(SubData, ?MQTT_PROTO_V5),
-
-                            emqx_client_sock:send(Sock, raw_send_serialize(
-                                                            ?DISCONNECT_PACKET(?RC_SUCCESS))),
-
-                            {error, timeout} = gen_tcp:recv(Sock2, 0, 2000),
-
-                            % session resumed
-                            {ok, Sock3} = emqx_client_sock:connect({127, 0, 0, 1}, 1883,
-                                                                   [binary, {packet, raw},
-                                                                    {active, false}], 3000),
-
-                            emqx_client_sock:send(Sock3,
-                                                    raw_send_serialize(
-                                                        ?CONNECT_PACKET(
-                                                            #mqtt_packet_connect{
-                                                                proto_ver    = ?MQTT_PROTO_V5,
-                                                                clean_start  = false,
-                                                                client_id    = <<"myclient">>,
-                                                                will_flag    = true,
-                                                                will_qos     = ?QOS_1,
-                                                                will_retain  = false,
-                                                                will_props   = #{'Will-Delay-Interval' => 5},
-                                                                will_topic   = <<"TopicA">>,
-                                                                will_payload = <<"will message 2">>,
-                                                                properties   = #{'Session-Expiry-Interval' => 3}
-                                                            }
-                                                        ),
-                                                        #{version => ?MQTT_PROTO_V5}
-                                                    )
-                            ),
-                            {ok, Data3} = gen_tcp:recv(Sock3, 0),
-                            {ok, ?CONNACK_PACKET(?RC_SUCCESS, 0), <<>>, _} = raw_recv_parse(Data3, ?MQTT_PROTO_V5),
-
-                            emqx_client_sock:send(Sock3, raw_send_serialize(
-                                                            ?DISCONNECT_PACKET(?RC_DISCONNECT_WITH_WILL_MESSAGE),
-                                                            #{version => ?MQTT_PROTO_V5}
-                                                        )
-                            ),
-
-                            {ok, WillData} = gen_tcp:recv(Sock2, 0, 5000),
-                            {ok, ?PUBLISH_PACKET(?QOS_1, <<"TopicA">>, _, <<"will message 2">>), <<>>, _}
-                                = raw_recv_parse(WillData, ?MQTT_PROTO_V5)
-                    end),
-
-    % duplicate client id
-    with_connection(fun([Sock, Sock1]) ->
-                            emqx_zone:set_env(external, use_username_as_clientid, true),
-                            emqx_client_sock:send(Sock,
-                                                    raw_send_serialize(
-                                                        ?CONNECT_PACKET(
-                                                            #mqtt_packet_connect{
-                                                                proto_ver   = ?MQTT_PROTO_V5,
-                                                                clean_start = true,
-                                                                client_id   = <<"myclient">>,
-                                                                properties  =
-                                                                    #{'Session-Expiry-Interval' => 10}})
-                                                  )),
-                            {ok, Data} = gen_tcp:recv(Sock, 0),
-                            {ok, ?CONNACK_PACKET(?RC_SUCCESS, 0), <<>>, _} = raw_recv_parse(Data, ?MQTT_PROTO_V5),
-
-                            emqx_client_sock:send(Sock1,
-                                                    raw_send_serialize(
-                                                        ?CONNECT_PACKET(
-                                                            #mqtt_packet_connect{
-                                                                proto_ver   = ?MQTT_PROTO_V5,
-                                                                clean_start = false,
-                                                                client_id   = <<"myclient">>,
-                                                                username    = <<"admin">>,
-                                                                password    = <<"public">>,
-                                                                properties  =
-                                                                    #{'Session-Expiry-Interval' => 10}})
-                                                  )),
-                            {ok, Data1} = gen_tcp:recv(Sock1, 0),
-                            {ok, ?CONNACK_PACKET(?RC_SUCCESS, 0), <<>>, _} = raw_recv_parse(Data1, ?MQTT_PROTO_V5),
-
-                            emqx_client_sock:send(Sock, raw_send_serialize(?SUBSCRIBE_PACKET(1, [{<<"TopicA">>, #{rh  => 1,
-                                                                                                                  qos => ?QOS_2,
-                                                                                                                  rap => 0,
-                                                                                                                  nl  => 0,
-                                                                                                                  rc  => 0}}]),
-                                                                            #{version => ?MQTT_PROTO_V5})),
-
-                            {ok, SubData} = gen_tcp:recv(Sock, 0),
-                            {ok, ?SUBACK_PACKET(1, #{}, [2]), <<>>, _} = raw_recv_parse(SubData, ?MQTT_PROTO_V5),
-
-                            emqx_client_sock:send(Sock1, raw_send_serialize(?SUBSCRIBE_PACKET(1, [{<<"TopicA">>, #{rh  => 1,
-                                                                                                                   qos => ?QOS_2,
-                                                                                                                   rap => 0,
-                                                                                                                   nl  => 0,
-                                                                                                                   rc  => 0}}]),
-                                                                            #{version => ?MQTT_PROTO_V5})),
-
-                            {ok, SubData1} = gen_tcp:recv(Sock1, 0),
-                            {ok, ?SUBACK_PACKET(1, #{}, [2]), <<>>, _} = raw_recv_parse(SubData1, ?MQTT_PROTO_V5)
-                    end, 2),
-
-    ok.
-
-do_connect(Sock, ProtoVer) ->
-    emqx_client_sock:send(Sock, raw_send_serialize(
-                                  ?CONNECT_PACKET(
-                                     #mqtt_packet_connect{
-                                        client_id  = <<"mqtt_client">>,
-                                        proto_ver  = ProtoVer
-                                       }))),
-    {ok, Data} = gen_tcp:recv(Sock, 0),
-    {ok, ?CONNACK_PACKET(?CONNACK_ACCEPT), <<>>, _} = raw_recv_parse(Data, ProtoVer).
-
-subscribe_v4(_) ->
-    with_connection(fun([Sock]) ->
-                            do_connect(Sock, ?MQTT_PROTO_V4),
-                            SubPacket = raw_send_serialize(
-                                          ?SUBSCRIBE_PACKET(15,
-                                                            [{<<"topic">>, #{rh => 1,
-                                                                             qos => ?QOS_2,
-                                                                             rap => 0,
-                                                                             nl => 0,
-                                                                             rc => 0}}])),
-                            emqx_client_sock:send(Sock, SubPacket),
-                            {ok, Data} = gen_tcp:recv(Sock, 0),
-                            {ok, ?SUBACK_PACKET(15, _), <<>>, _} = raw_recv_parse(Data, ?MQTT_PROTO_V4)
-                    end),
-    ok.
-
-subscribe_v5(_) ->
-    with_connection(fun([Sock]) ->
-                            do_connect(Sock, ?MQTT_PROTO_V5),
-                            SubPacket = raw_send_serialize(?SUBSCRIBE_PACKET(15, #{'Subscription-Identifier' => -1},[]),
-                                                            #{version => ?MQTT_PROTO_V5}),
-                            emqx_client_sock:send(Sock, SubPacket),
-                            {ok, DisConnData} = gen_tcp:recv(Sock, 0),
-                            {ok, ?DISCONNECT_PACKET(?RC_TOPIC_FILTER_INVALID), <<>>, _} =
-                                raw_recv_parse(DisConnData, ?MQTT_PROTO_V5)
-                    end),
-    with_connection(fun([Sock]) ->
-                            do_connect(Sock, ?MQTT_PROTO_V5),
-                            SubPacket = raw_send_serialize(
-                                          ?SUBSCRIBE_PACKET(0, #{}, [{<<"TopicQos0">>,
-                                                                      #{rh => 1, qos => ?QOS_2,
-                                                                        rap => 0, nl => 0,
-                                                                        rc => 0}}]),
-                                          #{version => ?MQTT_PROTO_V5}),
-                            emqx_client_sock:send(Sock, SubPacket),
-                            {ok, DisConnData} = gen_tcp:recv(Sock, 0),
-                            ?assertMatch(
-                               {ok, ?DISCONNECT_PACKET(?RC_MALFORMED_PACKET), <<>>, _},
-                               raw_recv_parse(DisConnData, ?MQTT_PROTO_V5))
-                    end),
-    with_connection(fun([Sock]) ->
-                            do_connect(Sock, ?MQTT_PROTO_V5),
-                            SubPacket = raw_send_serialize(
-                                          ?SUBSCRIBE_PACKET(1, #{'Subscription-Identifier' => 0},
-                                                            [{<<"TopicQos0">>,
-                                                              #{rh => 1, qos => ?QOS_2,
-                                                                rap => 0, nl => 0,
-                                                                rc => 0}}]),
-                                          #{version => ?MQTT_PROTO_V5}),
-                            emqx_client_sock:send(Sock, SubPacket),
-                            {ok, DisConnData} = gen_tcp:recv(Sock, 0),
-                            ?assertMatch(
-                               {ok, ?DISCONNECT_PACKET(?RC_SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED), <<>>, _},
-                               raw_recv_parse(DisConnData, ?MQTT_PROTO_V5))
-                    end),
-    with_connection(fun([Sock]) ->
-                            do_connect(Sock, ?MQTT_PROTO_V5),
-                            SubPacket = raw_send_serialize(
-                                          ?SUBSCRIBE_PACKET(1, #{'Subscription-Identifier' => 1},
-                                                            [{<<"TopicQos0">>,
-                                                              #{rh => 1, qos => ?QOS_2,
-                                                                rap => 0, nl => 0,
-                                                                rc => 0}}]),
-                                          #{version => ?MQTT_PROTO_V5}),
-                            emqx_client_sock:send(Sock, SubPacket),
-                            {ok, SubData} = gen_tcp:recv(Sock, 0),
-                            {ok, ?SUBACK_PACKET(1, #{}, [2]), <<>>, _}
-                                = raw_recv_parse(SubData, ?MQTT_PROTO_V5)
-                    end),
-    ok.
-
-publish_v4(_) ->
-    ok.
-
-publish_v5(_) ->
-    ok.
-
-raw_send_serialize(Packet) ->
-    emqx_frame:serialize(Packet).
-
-raw_send_serialize(Packet, Opts) ->
-    emqx_frame:serialize(Packet, Opts).
-
-raw_recv_parse(Bin, ProtoVer) ->
-    emqx_frame:parse(Bin, emqx_frame:initial_parse_state(#{version => ProtoVer})).
-
-acl_deny_action_ct(_) ->
-    emqx_zone:set_env(external, acl_deny_action, disconnect),
-    process_flag(trap_exit, true),
-    [acl_deny_do_disconnect(subscribe, QoS, <<"acl_deny_action">>) || QoS <- lists:seq(0, 2)],
-    [acl_deny_do_disconnect(publish, QoS, <<"acl_deny_action">>) || QoS <- lists:seq(0, 2)],
-    emqx_zone:set_env(external, acl_deny_action, ignore),
-    ok.
-
-will_topic_check(_) ->
-    {ok, Client} = emqx_client:start_link([{username, <<"emqx">>},
-                                           {will_flag, true},
-                                           {will_topic, <<"aaa">>},
-                                           {will_payload, <<"I have died">>},
-                                           {will_qos, 0}]),
-    {ok, _} = emqx_client:connect(Client),
-
-    {ok, T} = emqx_client:start_link([{client_id, <<"client">>}]),
-    emqx_client:connect(T),
-    emqx_client:subscribe(T, <<"aaa">>),
-    ct:sleep(200),
-
-    emqx_client:stop(Client),
-    ct:sleep(100),
-    false = is_process_alive(Client),
-    emqx_ct_helpers:wait_mqtt_payload(<<"I have died">>),
-    emqx_client:stop(T).
-
-will_acl_check(_) ->
-    %% The connection will be rejected if publishing of the will message is not allowed by
-    %% ACL rules
-    process_flag(trap_exit, true),
-    {ok, Client} = emqx_client:start_link([{username, <<"pub_deny">>},
-                                           {will_flag, true},
-                                           {will_topic, <<"pub_deny">>},
-                                           {will_payload, <<"I have died">>},
-                                           {will_qos, 0}]),
-    ?assertMatch({error,{_,_}}, emqx_client:connect(Client)).
-
-acl_deny_do_disconnect(publish, QoS, Topic) ->
-    process_flag(trap_exit, true),
-    {ok, Client} = emqx_client:start_link([{username, <<"emqx">>}]),
-    {ok, _} = emqx_client:connect(Client),
-    emqx_client:publish(Client, Topic, <<"test">>, QoS),
-    receive
-        {disconnected, shutdown, tcp_closed} ->
-            ct:pal(info, "[OK] after publish, client got disconnected: tcp_closed", []);
-        {'EXIT', Client, {shutdown,tcp_closed}} ->
-            ct:pal(info, "[OK] after publish, received exit: {shutdown,tcp_closed}"),
-            false = is_process_alive(Client);
-        {'EXIT', Client, Reason} ->
-            ct:pal(info, "[OK] after publish, client got disconnected: ~p", [Reason])
-    after 1000 -> ct:fail({timeout, wait_tcp_closed})
-    end;
-
-acl_deny_do_disconnect(subscribe, QoS, Topic) ->
-    process_flag(trap_exit, true),
-    {ok, Client} = emqx_client:start_link([{username, <<"emqx">>}]),
-    {ok, _} = emqx_client:connect(Client),
-    {ok, _, [128]} = emqx_client:subscribe(Client, Topic, QoS),
-    receive
-        {disconnected, shutdown, tcp_closed} ->
-            ct:pal(info, "[OK] after subscribe, client got disconnected: tcp_closed", []);
-        {'EXIT', Client, {shutdown,tcp_closed}} ->
-            ct:pal(info, "[OK] after subscribe, received exit: {shutdown,tcp_closed}"),
-            false = is_process_alive(Client);
-        {'EXIT', Client, Reason} ->
-            ct:pal(info, "[OK] after subscribe, client got disconnected: ~p", [Reason])
-    after 1000 -> ct:fail({timeout, wait_tcp_closed})
-    end.
-
-set_special_configs(emqx) ->
-    application:set_env(emqx, enable_acl_cache, false),
-    application:set_env(emqx, plugins_loaded_file,
-                        emqx_ct_helpers:deps_path(emqx, "test/emqx_SUITE_data/loaded_plugins")),
-    application:set_env(emqx, acl_deny_action, disconnect),
-    application:set_env(emqx, acl_file,
-                        emqx_ct_helpers:deps_path(emqx, "test/emqx_access_SUITE_data/acl_deny_action.conf"));
-set_special_configs(_App) ->
-    ok.

+ 0 - 30
test/emqx_protocol_tests.erl

@@ -1,30 +0,0 @@
-%% Copyright (c) 2013-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_protocol_tests).
-
--include_lib("eunit/include/eunit.hrl").
-
-set_property_test() ->
-    ?assertEqual(#{test => test_property}, emqx_protocol:set_property(test, test_property, undefined)),
-    TestMap = #{test => test_property},
-    ?assertEqual(#{test => test_property, test1 => test_property2},
-                 emqx_protocol:set_property(test1, test_property2, TestMap)),
-    ok.
-
-init_username_test() ->
-    ?assertEqual(<<"Peercert">>,
-                 emqx_protocol:init_username(<<"Peercert">>, [{peer_cert_as_username, crt}])),
-    ?assertEqual(undefined,
-                 emqx_protocol:init_username(undefined, [{peer_cert_as_username, undefined}])).

+ 11 - 7
test/emqx_reason_codes_tests.erl

@@ -14,12 +14,13 @@
 %% limitations under the License.
 %%--------------------------------------------------------------------
 
+-module(emqx_reason_codes_SUITE).
 
--module(emqx_reason_codes_tests).
-
--include_lib("eunit/include/eunit.hrl").
+-compile(export_all).
+-compile(nowarn_export_all).
 
 -include("emqx_mqtt.hrl").
+-include_lib("eunit/include/eunit.hrl").
 
 -import(lists, [seq/2, zip/2, foreach/2]).
 
@@ -89,25 +90,27 @@
                           ?CONNACK_AUTH,
                           ?CONNACK_SERVER, ?CONNACK_SERVER, ?CONNACK_SERVER, ?CONNACK_SERVER]).
 
-mqttv4_name_test() ->
+all() -> emqx_ct:all(?MODULE).
+
+t_mqttv4_name() ->
     (((codes_test(?MQTT_PROTO_V4))
         (seq(0,6)))
        (?MQTTV4_CODE_NAMES))
       (fun emqx_reason_codes:name/2).
 
-mqttv5_name_test() ->
+t_mqttv5_name() ->
     (((codes_test(?MQTT_PROTO_V5))
         (?MQTTV5_CODES))
        (?MQTTV5_CODE_NAMES))
       (fun emqx_reason_codes:name/2).
 
-text_test() ->
+t_text() ->
     (((codes_test(?MQTT_PROTO_V5))
         (?MQTTV5_CODES))
        (?MQTTV5_TXT))
       (fun emqx_reason_codes:text/1).
 
-compat_test() ->
+t_compat() ->
     (((codes_test(connack))
         (?COMPAT_CODES_V5))
        (?COMPAT_CODES_V4))
@@ -135,3 +138,4 @@ codes_test(AsistVar) ->
             end
         end
     end.
+

+ 0 - 97
test/emqx_request_handler.erl

@@ -1,97 +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.
-%%--------------------------------------------------------------------
-
-%% @doc This module implements a request handler based on emqx_client.
-%% A request handler is a MQTT client which subscribes to a request topic,
-%% processes the requests then send response to another topic which is
-%% subscribed by the request sender.
-%% This code is in test directory because request and response are pure
-%% client-side behaviours.
-
--module(emqx_request_handler).
-
--export([start_link/4, stop/1]).
-
--type qos() :: emqx_mqtt_types:qos_name() | emqx_mqtt_types:qos().
--type topic() :: emqx_topic:topic().
--type handler() :: fun((CorrData :: binary(), ReqPayload :: binary()) -> RspPayload :: binary()).
-
--spec start_link(topic(), qos(), handler(), emqx_client:options()) ->
-        {ok, pid()} | {error, any()}.
-start_link(RequestTopic, QoS, RequestHandler, Options0) ->
-    Parent = self(),
-    MsgHandler = make_msg_handler(RequestHandler, Parent),
-    Options = [{msg_handler, MsgHandler} | Options0],
-    case emqx_client:start_link(Options) of
-        {ok, Pid} ->
-            {ok, _} = emqx_client:connect(Pid),
-            try subscribe(Pid, RequestTopic, QoS) of
-                ok -> {ok, Pid};
-                {error, _} = Error -> Error
-            catch
-                C : E : S ->
-                    emqx_client:stop(Pid),
-                    {error, {C, E, S}}
-            end;
-        {error, _} = Error -> Error
-    end.
-
-stop(Pid) ->
-    emqx_client:disconnect(Pid).
-
-make_msg_handler(RequestHandler, Parent) ->
-    #{publish => fun(Msg) -> handle_msg(Msg, RequestHandler, Parent) end,
-      puback => fun(_Ack) -> ok end,
-      disconnected => fun(_Reason) -> ok end
-     }.
-
-handle_msg(ReqMsg, RequestHandler, Parent) ->
-    #{qos := QoS, properties := Props, payload := ReqPayload} = ReqMsg,
-    case maps:find('Response-Topic', Props) of
-        {ok, RspTopic} when RspTopic =/= <<>> ->
-            CorrData = maps:get('Correlation-Data', Props),
-            RspProps = maps:without(['Response-Topic'], Props),
-            RspPayload = RequestHandler(CorrData, ReqPayload),
-            emqx_logger:debug("~p sending response msg to topic ~s with~n"
-                              "corr-data=~p~npayload=~p",
-                              [?MODULE, RspTopic, CorrData, RspPayload]),
-            ok = send_response(RspTopic, RspProps, RspPayload, QoS);
-        _ ->
-            Parent ! {discarded, ReqPayload},
-            ok
-    end.
-
-send_response(Topic, Properties, Payload, QoS) ->
-    %% This function is evaluated by emqx_client itself.
-    %% hence delegate to another temp process for the loopback gen_statem call.
-    Client = self(),
-    _ = spawn_link(fun() ->
-                           case emqx_client:publish(Client, Topic, Properties, Payload, [{qos, QoS}]) of
-                               ok -> ok;
-                               {ok, _} -> ok;
-                               {error, Reason} -> exit({failed_to_publish_response, Reason})
-                           end
-                   end),
-    ok.
-
-subscribe(Client, Topic, QoS) ->
-    {ok, _Props, _QoS} =
-        emqx_client:subscribe(Client, [{Topic, [{rh, 2}, {rap, false},
-                                       {nl, true}, {qos, QoS}]}]),
-    ok.
-
-
-

+ 0 - 71
test/emqx_request_response_SUITE.erl

@@ -1,71 +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_request_response_SUITE).
-
--compile(export_all).
--compile(nowarn_export_all).
-
--include("emqx_mqtt.hrl").
--include_lib("eunit/include/eunit.hrl").
--include_lib("common_test/include/ct.hrl").
-
-init_per_suite(Config) ->
-    emqx_ct_helpers:start_apps([]),
-    Config.
-
-end_per_suite(_Config) ->
-    emqx_ct_helpers:stop_apps([]).
-
-all() ->
-    [request_response].
-
-request_response(_Config) ->
-    request_response_per_qos(?QOS_0),
-    request_response_per_qos(?QOS_1),
-    request_response_per_qos(?QOS_2).
-
-request_response_per_qos(QoS) ->
-    ReqTopic = <<"request_topic">>,
-    RspTopic = <<"response_topic">>,
-    {ok, Requester} = emqx_request_sender:start_link(RspTopic, QoS,
-                                                     [{proto_ver, v5},
-                                                      {client_id, <<"requester">>},
-                                                      {properties, #{ 'Request-Response-Information' => 1}}]),
-    %% This is a square service
-    Square = fun(_CorrData, ReqBin) ->
-                     I = b2i(ReqBin),
-                     i2b(I * I)
-              end,
-    {ok, Responser} = emqx_request_handler:start_link(ReqTopic, QoS, Square,
-                                                      [{proto_ver, v5},
-                                                       {client_id, <<"responser">>}
-                                                      ]),
-    ok = emqx_request_sender:send(Requester, ReqTopic, RspTopic, <<"corr-1">>, <<"2">>, QoS),
-    receive
-        {response, <<"corr-1">>, <<"4">>} ->
-            ok;
-        Other ->
-            erlang:error({unexpected, Other})
-    after
-        100 ->
-            erlang:error(timeout)
-    end,
-    ok = emqx_request_sender:stop(Requester),
-    ok = emqx_request_handler:stop(Responser).
-
-b2i(B) -> binary_to_integer(B).
-i2b(I) -> integer_to_binary(I).

+ 0 - 77
test/emqx_request_sender.erl

@@ -1,77 +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.
-%%--------------------------------------------------------------------
-
-%% @doc This module implements a request sender based on emqx_client.
-%% A request sender is a MQTT client which sends messages to a request
-%% topic, and subscribes to another topic for responses.
-%% This code is in test directory because request and response are pure
-%% client-side behaviours.
-
--module(emqx_request_sender).
-
--export([start_link/3, stop/1, send/6]).
-
-start_link(ResponseTopic, QoS, Options0) ->
-    Parent = self(),
-    MsgHandler = make_msg_handler(Parent),
-    Options = [{msg_handler, MsgHandler} | Options0],
-    case emqx_client:start_link(Options) of
-        {ok, Pid} ->
-            {ok, _} = emqx_client:connect(Pid),
-            try subscribe(Pid, ResponseTopic, QoS) of
-                ok -> {ok, Pid};
-                {error, _} = Error -> Error
-            catch
-                C : E : S ->
-                    emqx_client:stop(Pid),
-                    {error, {C, E, S}}
-            end;
-        {error, _} = Error -> Error
-    end.
-
-%% @doc Send a message to request topic with correlation-data `CorrData'.
-%% Response should be delivered as a `{response, CorrData, Payload}'
-send(Client, ReqTopic, RspTopic, CorrData, Payload, QoS) ->
-    Props = #{'Response-Topic' => RspTopic,
-              'Correlation-Data' => CorrData
-             },
-    case emqx_client:publish(Client, ReqTopic, Props, Payload, [{qos, QoS}]) of
-        ok -> ok; %% QoS = 0
-        {ok, _} -> ok;
-        {error, _} = E -> E
-    end.
-
-stop(Pid) ->
-    emqx_client:disconnect(Pid).
-
-subscribe(Client, Topic, QoS) ->
-    case emqx_client:subscribe(Client, Topic, QoS) of
-        {ok, _, _} -> ok;
-        {error, _} = Error -> Error
-    end.
-
-make_msg_handler(Parent) ->
-    #{publish => fun(Msg) -> handle_msg(Msg, Parent) end,
-      puback => fun(_Ack) -> ok end,
-      disconnected => fun(_Reason) -> ok end
-     }.
-
-handle_msg(Msg, Parent) ->
-    #{properties := Props, payload := Payload} = Msg,
-    CorrData = maps:get('Correlation-Data', Props),
-    Parent ! {response, CorrData, Payload},
-    ok.
-

+ 7 - 16
test/emqx_router_SUITE.erl

@@ -16,26 +16,15 @@
 
 -module(emqx_router_SUITE).
 
--include("emqx.hrl").
--include_lib("eunit/include/eunit.hrl").
-
 -compile(export_all).
 -compile(nowarn_export_all).
 
--define(R, emqx_router).
+-include("emqx.hrl").
+-include_lib("eunit/include/eunit.hrl").
 
-all() ->
-    [{group, route}].
+-define(R, emqx_router).
 
-groups() ->
-    [{route, [sequence],
-      [t_mnesia,
-       t_add_delete,
-       t_do_add_delete,
-       t_match_routes,
-       t_print_routes,
-       t_has_routes,
-       t_unexpected]}].
+all() -> emqx_ct:all(?MODULE).
 
 init_per_suite(Config) ->
     emqx_ct_helpers:start_apps([]),
@@ -107,4 +96,6 @@ t_unexpected(_) ->
     Router ! bad_info.
 
 clear_tables() ->
-    lists:foreach(fun mnesia:clear_table/1, [emqx_route, emqx_trie, emqx_trie_node]).
+    lists:foreach(fun mnesia:clear_table/1,
+                  [emqx_route, emqx_trie, emqx_trie_node]).
+

+ 0 - 38
test/emqx_rpc_SUITE.erl

@@ -1,38 +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_rpc_SUITE).
-
--include("emqx.hrl").
--include_lib("eunit/include/eunit.hrl").
-
--compile(export_all).
--compile(nowarn_export_all).
--define(MASTER, 'emqxct@127.0.0.1').
-
-all() -> [t_rpc].
-
-init_per_suite(Config) ->
-    emqx_ct_helpers:start_apps([]),
-    Config.
-
-end_per_suite(_Config) ->
-    emqx_ct_helpers:stop_apps([]).
-
-t_rpc(_) ->
-    60000 = emqx_rpc:call(?MASTER, timer, seconds, [60]),
-    {badrpc, _} = emqx_rpc:call(?MASTER, os, test, []),
-    {_, []} = emqx_rpc:multicall([?MASTER, ?MASTER], os, timestamp, []).

+ 15 - 6
test/emqx_sequence_SUITE.erl

@@ -21,20 +21,29 @@
 
 -include_lib("eunit/include/eunit.hrl").
 
--import(emqx_sequence, [nextval/2, reclaim/2]).
+-import(emqx_sequence,
+        [ nextval/2
+        , currval/2
+        , reclaim/2
+        ]).
 
-all() ->
-    [sequence_generate].
+all() -> emqx_ct:all(?MODULE).
 
-sequence_generate(_) ->
+t_generate(_) ->
     ok = emqx_sequence:create(seqtab),
+    ?assertEqual(0, currval(seqtab, key)),
     ?assertEqual(1, nextval(seqtab, key)),
+    ?assertEqual(1, currval(seqtab, key)),
     ?assertEqual(2, nextval(seqtab, key)),
+    ?assertEqual(2, currval(seqtab, key)),
     ?assertEqual(3, nextval(seqtab, key)),
     ?assertEqual(2, reclaim(seqtab, key)),
     ?assertEqual(1, reclaim(seqtab, key)),
     ?assertEqual(0, reclaim(seqtab, key)),
-    ?assertEqual(false, ets:member(seqtab, key)),
     ?assertEqual(1, nextval(seqtab, key)),
-    ?assert(emqx_sequence:delete(seqtab)).
+    ?assertEqual(0, reclaim(seqtab, key)),
+    ?assertEqual(0, reclaim(seqtab, key)),
+    ?assertEqual(false, ets:member(seqtab, key)),
+    ?assert(emqx_sequence:delete(seqtab)),
+    ?assertNot(emqx_sequence:delete(seqtab)).
 

+ 39 - 4
test/emqx_session_SUITE.erl

@@ -21,9 +21,7 @@
 
 -include_lib("eunit/include/eunit.hrl").
 
--include_lib("common_test/include/ct.hrl").
-
-all() -> [ignore_loop, t_session_all].
+all() -> emqx_ct:all(?MODULE).
 
 init_per_suite(Config) ->
     emqx_ct_helpers:start_apps([]),
@@ -32,6 +30,42 @@ init_per_suite(Config) ->
 end_per_suite(_Config) ->
     emqx_ct_helpers:stop_apps([]).
 
+t_info(_) ->
+    'TODO'.
+
+t_attrs(_) ->
+    'TODO'.
+
+t_stats(_) ->
+    'TODO'.
+
+t_subscribe(_) ->
+    'TODO'.
+
+t_unsubscribe(_) ->
+    'TODO'.
+
+t_publish(_) ->
+    'TODO'.
+
+t_puback(_) ->
+    'TODO'.
+
+t_pubrec(_) ->
+    'TODO'.
+
+t_pubrel(_) ->
+    'TODO'.
+
+t_pubcomp(_) ->
+    'TODO'.
+
+t_deliver(_) ->
+    'TODO'.
+
+t_timeout(_) ->
+    'TODO'.
+
 ignore_loop(_Config) ->
     emqx_zone:set_env(external, ignore_loop_deliver, true),
     {ok, Client} = emqx_client:start_link(),
@@ -45,7 +79,7 @@ ignore_loop(_Config) ->
     ok = emqx_client:disconnect(Client),
     emqx_zone:set_env(external, ignore_loop_deliver, false).
 
-t_session_all(_) ->
+session_all(_) ->
     emqx_zone:set_env(internal, idle_timeout, 1000),
     ClientId = <<"ClientId">>,
     {ok, ConnPid} = emqx_mock_client:start_link(ClientId),
@@ -68,3 +102,4 @@ t_session_all(_) ->
     timer:sleep(200),
     [] = emqx:subscriptions(SPid),
     emqx_mock_client:close_session(ConnPid).
+

+ 0 - 260
test/emqx_shared_sub_SUITE.erl

@@ -1,260 +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_shared_sub_SUITE).
-
--export([all/0, init_per_suite/1, end_per_suite/1]).
--export([t_random_basic/1,
-         t_random/1,
-         t_round_robin/1,
-         t_sticky/1,
-         t_hash/1,
-         t_not_so_sticky/1,
-         t_no_connection_nack/1
-        ]).
-
--include("emqx.hrl").
--include_lib("eunit/include/eunit.hrl").
--include_lib("common_test/include/ct.hrl").
-
--define(wait(For, Timeout), emqx_ct_helpers:wait_for(?FUNCTION_NAME, ?LINE, fun() -> For end, Timeout)).
-
-all() -> [t_random_basic,
-          t_random,
-          t_round_robin,
-          t_sticky,
-          t_hash,
-          t_not_so_sticky,
-          t_no_connection_nack].
-
-init_per_suite(Config) ->
-    emqx_ct_helpers:start_apps([]),
-    Config.
-
-end_per_suite(_Config) ->
-    emqx_ct_helpers:stop_apps([]).
-
-t_random_basic(_) ->
-    ok = ensure_config(random),
-    ClientId = <<"ClientId">>,
-    {ok, ConnPid} = emqx_mock_client:start_link(ClientId),
-    {ok, SPid} = emqx_mock_client:open_session(ConnPid, ClientId, internal),
-    Message1 = emqx_message:make(<<"ClientId">>, 2, <<"foo">>, <<"hello">>),
-    emqx_session:subscribe(SPid, [{<<"foo">>, #{qos => 2, share => <<"group1">>}}]),
-    %% wait for the subscription to show up
-    ?wait(subscribed(<<"group1">>, <<"foo">>, SPid), 1000),
-    PacketId = 1,
-    emqx_session:publish(SPid, PacketId, Message1),
-    ?wait(case emqx_mock_client:get_last_message(ConnPid) of
-              [{publish, 1, _}] -> true;
-              Other -> Other
-          end, 1000),
-    emqx_session:pubrec(SPid, PacketId, reasoncode),
-    emqx_session:pubcomp(SPid, PacketId, reasoncode),
-    emqx_mock_client:close_session(ConnPid),
-    ok.
-
-%% Start two subscribers share subscribe to "$share/g1/foo/bar"
-%% Set 'sticky' dispatch strategy, send 1st message to find
-%% out which member it picked, then close its connection
-%% send the second message, the message should be 'nack'ed
-%% by the sticky session and delivered to the 2nd session.
-%% After the connection for the 2nd session is also closed,
-%% i.e. when all clients are offline, the following message(s)
-%% should be delivered randomly.
-t_no_connection_nack(_) ->
-    ok = ensure_config(sticky),
-    Publisher = <<"publisher">>,
-    Subscriber1 = <<"Subscriber1">>,
-    Subscriber2 = <<"Subscriber2">>,
-    QoS = 1,
-    Group = <<"g1">>,
-    Topic = <<"foo/bar">>,
-    {ok, PubConnPid} = emqx_mock_client:start_link(Publisher),
-    {ok, SubConnPid1} = emqx_mock_client:start_link(Subscriber1),
-    {ok, SubConnPid2} = emqx_mock_client:start_link(Subscriber2),
-    %% allow session to persist after connection shutdown
-    Attrs = #{expiry_interval => timer:seconds(30)},
-    {ok, P_Pid} = emqx_mock_client:open_session(PubConnPid, Publisher, internal, Attrs),
-    {ok, SPid1} = emqx_mock_client:open_session(SubConnPid1, Subscriber1, internal, Attrs),
-    {ok, SPid2} = emqx_mock_client:open_session(SubConnPid2, Subscriber2, internal, Attrs),
-    emqx_session:subscribe(SPid1, [{Topic, #{qos => QoS, share => Group}}]),
-    emqx_session:subscribe(SPid2, [{Topic, #{qos => QoS, share => Group}}]),
-    %% wait for the subscriptions to show up
-    ?wait(subscribed(Group, Topic, SPid1), 1000),
-    ?wait(subscribed(Group, Topic, SPid2), 1000),
-    MkPayload = fun(PacketId) -> iolist_to_binary(["hello-", integer_to_list(PacketId)]) end,
-    SendF = fun(PacketId) -> emqx_session:publish(P_Pid, PacketId, emqx_message:make(Publisher, QoS, Topic, MkPayload(PacketId))) end,
-    SendF(1),
-    Ref = make_ref(),
-    CasePid = self(),
-    Received =
-        fun(PacketId, ConnPid) ->
-                Payload = MkPayload(PacketId),
-                case emqx_mock_client:get_last_message(ConnPid) of
-                    [{publish, _, #message{payload = Payload}}] ->
-                        CasePid ! {Ref, PacketId, ConnPid},
-                        true;
-                    _Other ->
-                        false
-                end
-        end,
-    ?wait(Received(1, SubConnPid1) orelse Received(1, SubConnPid2), 1000),
-    %% This is the connection which was picked by broker to dispatch (sticky) for 1st message
-    ConnPid = receive {Ref, 1, Pid} -> Pid after 1000 -> error(timeout) end,
-    %% Now kill the connection, expect all following messages to be delivered to the other subscriber.
-    emqx_mock_client:stop(ConnPid),
-    %% sleep then make synced calls to session processes to ensure that
-    %% the connection pid's 'EXIT' message is propagated to the session process
-    %% also to be sure sessions are still alive
-    timer:sleep(2),
-    _ = emqx_session:info(SPid1),
-    _ = emqx_session:info(SPid2),
-    %% Now we know what is the other still alive connection
-    [TheOtherConnPid] = [SubConnPid1, SubConnPid2] -- [ConnPid],
-    %% Send some more messages
-    PacketIdList = lists:seq(2, 10),
-    lists:foreach(fun(Id) ->
-                          SendF(Id),
-                          ?wait(Received(Id, TheOtherConnPid), 1000)
-                  end, PacketIdList),
-    %% Now close the 2nd (last connection)
-    emqx_mock_client:stop(TheOtherConnPid),
-    timer:sleep(2),
-    %% both sessions should have conn_pid = undefined
-    ?assertEqual({conn_pid, undefined}, lists:keyfind(conn_pid, 1, emqx_session:info(SPid1))),
-    ?assertEqual({conn_pid, undefined}, lists:keyfind(conn_pid, 1, emqx_session:info(SPid2))),
-    %% send more messages, but all should be queued in session state
-    lists:foreach(fun(Id) -> SendF(Id) end, PacketIdList),
-    {_, L1} = lists:keyfind(mqueue_len, 1, emqx_session:info(SPid1)),
-    {_, L2} = lists:keyfind(mqueue_len, 1, emqx_session:info(SPid2)),
-    ?assertEqual(length(PacketIdList), L1 + L2),
-    %% clean up
-    emqx_mock_client:close_session(PubConnPid),
-    emqx_sm:close_session(SPid1),
-    emqx_sm:close_session(SPid2),
-    ok.
-
-t_random(_) ->
-    test_two_messages(random).
-
-t_round_robin(_) ->
-    test_two_messages(round_robin).
-
-t_sticky(_) ->
-    test_two_messages(sticky).
-
-t_hash(_) ->
-    test_two_messages(hash, false).
-
-%% if the original subscriber dies, change to another one alive
-t_not_so_sticky(_) ->
-    ok = ensure_config(sticky),
-    ClientId1 = <<"ClientId1">>,
-    ClientId2 = <<"ClientId2">>,
-    {ok, ConnPid1} = emqx_mock_client:start_link(ClientId1),
-    {ok, ConnPid2} = emqx_mock_client:start_link(ClientId2),
-    {ok, SPid1} = emqx_mock_client:open_session(ConnPid1, ClientId1, internal),
-    {ok, SPid2} = emqx_mock_client:open_session(ConnPid2, ClientId2, internal),
-    Message1 = emqx_message:make(ClientId1, 0, <<"foo/bar">>, <<"hello1">>),
-    Message2 = emqx_message:make(ClientId1, 0, <<"foo/bar">>, <<"hello2">>),
-    emqx_session:subscribe(SPid1, [{<<"foo/bar">>, #{qos => 0, share => <<"group1">>}}]),
-    %% wait for the subscription to show up
-    ?wait(subscribed(<<"group1">>, <<"foo/bar">>, SPid1), 1000),
-    emqx_session:publish(SPid1, 1, Message1),
-    ?wait(case emqx_mock_client:get_last_message(ConnPid1) of
-              [{publish, _, #message{payload = <<"hello1">>}}] -> true;
-              Other -> Other
-          end, 1000),
-    emqx_mock_client:close_session(ConnPid1),
-    ?wait(not subscribed(<<"group1">>, <<"foo/bar">>, SPid1), 1000),
-    emqx_session:subscribe(SPid2, [{<<"foo/#">>, #{qos => 0, share => <<"group1">>}}]),
-    ?wait(subscribed(<<"group1">>, <<"foo/#">>, SPid2), 1000),
-    emqx_session:publish(SPid2, 2, Message2),
-    ?wait(case emqx_mock_client:get_last_message(ConnPid2) of
-              [{publish, _, #message{payload = <<"hello2">>}}] -> true;
-              Other -> Other
-          end, 1000),
-    emqx_mock_client:close_session(ConnPid2),
-    ?wait(not subscribed(<<"group1">>, <<"foo/#">>, SPid2), 1000),
-    ok.
-
-test_two_messages(Strategy) ->
-    test_two_messages(Strategy, _WithAck = true).
-
-test_two_messages(Strategy, WithAck) ->
-    ok = ensure_config(Strategy, WithAck),
-    Topic = <<"foo/bar">>,
-    ClientId1 = <<"ClientId1">>,
-    ClientId2 = <<"ClientId2">>,
-    {ok, ConnPid1} = emqx_mock_client:start_link(ClientId1),
-    {ok, ConnPid2} = emqx_mock_client:start_link(ClientId2),
-    {ok, SPid1} = emqx_mock_client:open_session(ConnPid1, ClientId1, internal),
-    {ok, SPid2} = emqx_mock_client:open_session(ConnPid2, ClientId2, internal),
-    Message1 = emqx_message:make(ClientId1, 0, Topic, <<"hello1">>),
-    Message2 = emqx_message:make(ClientId1, 0, Topic, <<"hello2">>),
-    emqx_session:subscribe(SPid1, [{Topic, #{qos => 0, share => <<"group1">>}}]),
-    emqx_session:subscribe(SPid2, [{Topic, #{qos => 0, share => <<"group1">>}}]),
-    %% wait for the subscription to show up
-    ?wait(subscribed(<<"group1">>, Topic, SPid1) andalso
-          subscribed(<<"group1">>, Topic, SPid2), 1000),
-    emqx_broker:publish(Message1),
-    Me = self(),
-    WaitF = fun(ExpectedPayload) ->
-                    case last_message(ExpectedPayload, [ConnPid1, ConnPid2]) of
-                        {true, Pid} ->
-                            Me ! {subscriber, Pid},
-                            true;
-                        Other ->
-                            Other
-                    end
-            end,
-    ?wait(WaitF(<<"hello1">>), 2000),
-    UsedSubPid1 = receive {subscriber, P1} -> P1 end,
-    emqx_broker:publish(Message2),
-    ?wait(WaitF(<<"hello2">>), 2000),
-    UsedSubPid2 = receive {subscriber, P2} -> P2 end,
-    case Strategy of
-        sticky -> ?assert(UsedSubPid1 =:= UsedSubPid2);
-        round_robin -> ?assert(UsedSubPid1 =/= UsedSubPid2);
-        hash -> ?assert(UsedSubPid1 =:= UsedSubPid2);
-        _ -> ok
-    end,
-    emqx_mock_client:close_session(ConnPid1),
-    emqx_mock_client:close_session(ConnPid2),
-    ok.
-
-last_message(_ExpectedPayload, []) -> <<"not yet?">>;
-last_message(ExpectedPayload, [Pid | Pids]) ->
-    case emqx_mock_client:get_last_message(Pid) of
-        [{publish, _, #message{payload = ExpectedPayload}}] -> {true, Pid};
-        _Other -> last_message(ExpectedPayload, Pids)
-    end.
-
-%%------------------------------------------------------------------------------
-%% help functions
-%%------------------------------------------------------------------------------
-
-ensure_config(Strategy) ->
-    ensure_config(Strategy, _AckEnabled = true).
-
-ensure_config(Strategy, AckEnabled) ->
-    application:set_env(emqx, shared_subscription_strategy, Strategy),
-    application:set_env(emqx, shared_dispatch_ack_enabled, AckEnabled),
-    ok.
-
-subscribed(Group, Topic, Pid) ->
-    lists:member(Pid, emqx_shared_sub:subscribers(Group, Topic)).

+ 0 - 115
test/emqx_sm_SUITE.erl

@@ -1,115 +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_sm_SUITE).
-
--include("emqx.hrl").
--include_lib("eunit/include/eunit.hrl").
--include_lib("common_test/include/ct.hrl").
-
--compile(export_all).
--compile(nowarn_export_all).
-
--define(ATTRS, #{clean_start         => true,
-                 client_id           => <<"client">>,
-                 zone                => internal,
-                 username            => <<"emqx">>,
-                 expiry_interval     => 0,
-                 max_inflight        => 0,
-                 topic_alias_maximum => 0,
-                 will_msg            => undefined}).
-
-all() -> [{group, registry}, {group, ets}].
-
-groups() ->
-    Cases =
-        [ t_resume_session,
-          t_discard_session,
-          t_register_unregister_session,
-          t_get_set_session_attrs,
-          t_get_set_session_stats,
-          t_lookup_session_pids],
-    [ {registry, [non_parallel_tests], Cases},
-      {ets, [non_parallel_tests], Cases}].
-
-init_per_suite(Config) ->
-    Config.
-
-end_per_suite(_Config) ->
-    ok.
-
-init_per_group(registry, Config) ->
-    emqx_ct_helpers:start_apps([], fun enable_session_registry/1),
-    Config;
-init_per_group(ets, Config) ->
-    emqx_ct_helpers:start_apps([], fun disable_session_registry/1),
-    Config.
-
-end_per_group(_, _Config) ->
-    emqx_ct_helpers:stop_apps([]).
-
-init_per_testcase(_All, Config) ->
-    {ok, SPid} = emqx_sm:open_session(?ATTRS#{conn_pid => self()}),
-    [{session_pid, SPid}|Config].
-
-end_per_testcase(_All, Config) ->
-    emqx_sm:close_session(?config(session_pid, Config)),
-    receive
-        {shutdown, normal} -> ok
-    after 500 -> ct:fail({timeout, wait_session_shutdown})
-    end.
-
-enable_session_registry(_) ->
-    application:set_env(emqx, enable_session_registry, true),
-    ok.
-
-disable_session_registry(_) ->
-    application:set_env(emqx, enable_session_registry, false),
-    ok.
-
-t_resume_session(Config) ->
-    ?assertEqual({ok, ?config(session_pid, Config)}, emqx_sm:resume_session(<<"client">>, ?ATTRS#{conn_pid => self()})).
-
-t_discard_session(_) ->
-    ?assertEqual(ok, emqx_sm:discard_session(<<"client1">>)).
-
-t_register_unregister_session(_) ->
-    Pid = self(),
-    ?assertEqual(ok, emqx_sm:register_session(<<"client">>)),
-    ?assertEqual(ok, emqx_sm:register_session(<<"client">>, Pid)),
-    ?assertEqual(ok, emqx_sm:unregister_session(<<"client">>)),
-    ?assertEqual(ok, emqx_sm:unregister_session(<<"client">>), Pid).
-
-t_get_set_session_attrs(Config) ->
-    SPid = ?config(session_pid, Config),
-    ClientPid0 = spawn(fun() -> receive _ -> ok end end),
-    ?assertEqual(true, emqx_sm:set_session_attrs(<<"client">>, [?ATTRS#{conn_pid => ClientPid0}])),
-    ?assertEqual(true, emqx_sm:set_session_attrs(<<"client">>, SPid, [?ATTRS#{conn_pid => ClientPid0}])),
-    [SAttr0] = emqx_sm:get_session_attrs(<<"client">>, SPid),
-    ?assertEqual(ClientPid0, maps:get(conn_pid, SAttr0)),
-    ?assertEqual(true, emqx_sm:set_session_attrs(<<"client">>, SPid, [?ATTRS#{conn_pid => self()}])),
-    [SAttr1] = emqx_sm:get_session_attrs(<<"client">>, SPid),
-    ?assertEqual(self(), maps:get(conn_pid, SAttr1)).
-
-t_get_set_session_stats(Config) ->
-    SPid = ?config(session_pid, Config),
-    ?assertEqual(true, emqx_sm:set_session_stats(<<"client">>, [{inflight, 10}])),
-    ?assertEqual(true, emqx_sm:set_session_stats(<<"client">>, SPid, [{inflight, 10}])),
-    ?assertEqual([{inflight, 10}], emqx_sm:get_session_stats(<<"client">>, SPid)).
-
-t_lookup_session_pids(Config) ->
-    SPid = ?config(session_pid, Config),
-    ?assertEqual([SPid], emqx_sm:lookup_session_pids(<<"client">>)).

+ 18 - 13
test/emqx_stats_tests.erl

@@ -14,36 +14,41 @@
 %% limitations under the License.
 %%--------------------------------------------------------------------
 
--module(emqx_stats_tests).
+-module(emqx_stats_SUITE).
+
+-compile(export_all).
+-compile(nowarn_export_all).
 
 -include_lib("eunit/include/eunit.hrl").
 
-get_state_test() ->
+all() -> emqx_ct:all(?MODULE).
+
+t_get_state() ->
     with_proc(fun() ->
         SetConnsCount = emqx_stats:statsfun('connections.count'),
         SetConnsCount(1),
-        1 = emqx_stats:getstat('connections.count'),
+        ?assertEqual(1, emqx_stats:getstat('connections.count')),
         emqx_stats:setstat('connections.count', 2),
-        2 = emqx_stats:getstat('connections.count'),
+        ?assertEqual(2, emqx_stats:getstat('connections.count')),
         emqx_stats:setstat('connections.count', 'connections.max', 3),
         timer:sleep(100),
-        3 = emqx_stats:getstat('connections.count'),
-        3 = emqx_stats:getstat('connections.max'),
+        ?assertEqual(3, emqx_stats:getstat('connections.count')),
+        ?assertEqual(3, emqx_stats:getstat('connections.max')),
         emqx_stats:setstat('connections.count', 'connections.max', 2),
         timer:sleep(100),
-        2 = emqx_stats:getstat('connections.count'),
-        3 = emqx_stats:getstat('connections.max'),
+        ?assertEqual(2, emqx_stats:getstat('connections.count')),
+        ?assertEqual(3, emqx_stats:getstat('connections.max')),
         SetConns = emqx_stats:statsfun('connections.count', 'connections.max'),
         SetConns(4),
         timer:sleep(100),
-        4 = emqx_stats:getstat('connections.count'),
-        4 = emqx_stats:getstat('connections.max'),
+        ?assertEqual(4, emqx_stats:getstat('connections.count')),
+        ?assertEqual(4, emqx_stats:getstat('connections.max')),
         Conns = emqx_stats:getstats(),
-        4 = proplists:get_value('connections.count', Conns),
-        4 = proplists:get_value('connections.max', Conns)
+        ?assertEqual(4, proplists:get_value('connections.count', Conns)),
+        ?assertEqual(4, proplists:get_value('connections.max', Conns))
     end).
 
-update_interval_test() ->
+t_update_interval() ->
     TickMs = 200,
     with_proc(fun() ->
         SleepMs = TickMs * 2 + TickMs div 2, %% sleep for 2.5 ticks

+ 21 - 14
test/emqx_sys_mon_SUITE.erl

@@ -19,21 +19,27 @@
 -compile(export_all).
 -compile(nowarn_export_all).
 
+-include("emqx_mqtt.hrl").
 -include_lib("eunit/include/eunit.hrl").
 
--include_lib("common_test/include/ct.hrl").
-
--include("emqx_mqtt.hrl").
+-define(SYSMON, emqx_sys_mon).
 
--define(SYSMONPID, emqx_sys_mon).
--define(INPUTINFO, [{self(), long_gc, concat_str("long_gc warning: pid = ~p, info: ~p", self(), "hello"), "hello"},
-                    {self(), long_schedule, concat_str("long_schedule warning: pid = ~p, info: ~p", self(), "hello"), "hello"},
-                    {self(), busy_port, concat_str("busy_port warning: suspid = ~p, port = ~p", self(), list_to_port("#Port<0.4>")), list_to_port("#Port<0.4>")},
-                    {self(), busy_dist_port, concat_str("busy_dist_port warning: suspid = ~p, port = ~p", self(), list_to_port("#Port<0.4>")),list_to_port("#Port<0.4>")},
-                    {list_to_port("#Port<0.4>"), long_schedule, concat_str("long_schedule warning: port = ~p, info: ~p", list_to_port("#Port<0.4>"), "hello"), "hello"}
+-define(INPUTINFO, [{self(), long_gc,
+                     concat_str("long_gc warning: pid = ~p, info: ~p", self(), "hello"), "hello"},
+                    {self(), long_schedule,
+                     concat_str("long_schedule warning: pid = ~p, info: ~p", self(), "hello"), "hello"},
+                    {self(), busy_port,
+                     concat_str("busy_port warning: suspid = ~p, port = ~p",
+                                self(), list_to_port("#Port<0.4>")), list_to_port("#Port<0.4>")},
+                    {self(), busy_dist_port,
+                     concat_str("busy_dist_port warning: suspid = ~p, port = ~p",
+                                self(), list_to_port("#Port<0.4>")),list_to_port("#Port<0.4>")},
+                    {list_to_port("#Port<0.4>"), long_schedule,
+                     concat_str("long_schedule warning: port = ~p, info: ~p",
+                                list_to_port("#Port<0.4>"), "hello"), "hello"}
                     ]).
 
-all() -> [t_sys_mon].
+all() -> emqx_ct:all(?MODULE).
 
 init_per_suite(Config) ->
     emqx_ct_helpers:start_apps([]),
@@ -43,16 +49,17 @@ end_per_suite(_Config) ->
     emqx_ct_helpers:stop_apps([]).
 
 t_sys_mon(_Config) ->
-    lists:foreach(fun({PidOrPort, SysMonName,ValidateInfo, InfoOrPort}) ->
-                      validate_sys_mon_info(PidOrPort, SysMonName,ValidateInfo, InfoOrPort)
-                  end, ?INPUTINFO).
+    lists:foreach(
+      fun({PidOrPort, SysMonName,ValidateInfo, InfoOrPort}) ->
+              validate_sys_mon_info(PidOrPort, SysMonName,ValidateInfo, InfoOrPort)
+      end, ?INPUTINFO).
 
 validate_sys_mon_info(PidOrPort, SysMonName,ValidateInfo, InfoOrPort) ->
     {ok, C} = emqx_client:start_link([{host, "localhost"}]),
     {ok, _} = emqx_client:connect(C),
     emqx_client:subscribe(C, emqx_topic:systop(lists:concat(['sysmon/', SysMonName])), qos1),
     timer:sleep(100),
-    ?SYSMONPID ! {monitor, PidOrPort, SysMonName, InfoOrPort},
+    ?SYSMON ! {monitor, PidOrPort, SysMonName, InfoOrPort},
     receive
         {publish,  #{payload := Info}} ->
             ?assertEqual(ValidateInfo, binary_to_list(Info)),

+ 22 - 7
test/emqx_tables_SUITE.erl

@@ -19,12 +19,27 @@
 -compile(export_all).
 -compile(nowarn_export_all).
 
-all() -> [t_new].
+-include_lib("eunit/include/eunit.hrl").
+
+-define(TAB, ?MODULE).
+
+all() -> emqx_ct:all(?MODULE).
 
 t_new(_) ->
-    ok = emqx_tables:new(test_table, [{read_concurrency, true}]),
-    ets:insert(test_table, {key, 100}),
-    ok = emqx_tables:new(test_table, [{read_concurrency, true}]),
-    100 = ets:lookup_element(test_table, key, 2),
-    ok = emqx_tables:delete(test_table),
-    ok = emqx_tables:delete(test_table).
+    ok = emqx_tables:new(?TAB),
+    ok = emqx_tables:new(?TAB, [{read_concurrency, true}]),
+    ?assertEqual(?TAB, ets:info(?TAB, name)).
+
+t_lookup_value(_) ->
+    ok = emqx_tables:new(?TAB, []),
+    true = ets:insert(?TAB, {key, val}),
+    ?assertEqual(val, emqx_tables:lookup_value(?TAB, key)),
+    ?assertEqual(undefined, emqx_tables:lookup_value(?TAB, badkey)).
+
+t_delete(_) ->
+    ok = emqx_tables:new(?TAB, []),
+    ?assertEqual(?TAB, ets:info(?TAB, name)),
+    ok = emqx_tables:delete(?TAB),
+    ok = emqx_tables:delete(?TAB),
+    ?assertEqual(undefined, ets:info(?TAB, name)).
+

+ 12 - 7
test/emqx_time_SUITE.erl

@@ -16,14 +16,19 @@
 
 -module(emqx_time_SUITE).
 
--include_lib("eunit/include/eunit.hrl").
-
 -compile(export_all).
 -compile(nowarn_export_all).
 
-all() -> [t_time_now_to].
+-include_lib("eunit/include/eunit.hrl").
+
+all() -> emqx_ct:all(?MODULE).
+
+t_seed(_) ->
+    ?assert(is_tuple(emqx_time:seed())).
+
+t_now_secs(_) ->
+    ?assert(emqx_time:now_secs() =< emqx_time:now_secs(os:timestamp())).
+
+t_now_ms(_) ->
+    ?assert(emqx_time:now_ms() =< emqx_time:now_ms(os:timestamp())).
 
-t_time_now_to(_) ->
-    emqx_time:seed(),
-    emqx_time:now_secs(),
-    emqx_time:now_ms().

+ 75 - 73
test/emqx_topic_SUITE.erl

@@ -16,44 +16,29 @@
 
 -module(emqx_topic_SUITE).
 
--include_lib("eunit/include/eunit.hrl").
-
-%% CT
 -compile(export_all).
 -compile(nowarn_export_all).
 
+-include_lib("eunit/include/eunit.hrl").
+-include_lib("emqx_ct_helpers/include/emqx_ct.hrl").
+
 -import(emqx_topic,
         [ wildcard/1
         , match/2
         , validate/1
         , triples/1
+        , prepend/2
         , join/1
         , words/1
         , systop/1
         , feed_var/3
         , parse/1
+        , parse/2
         ]).
 
--define(N, 10000).
-
-all() ->
-    [t_wildcard,
-     t_match, t_match2, t_match3,
-     t_validate,
-     t_triples,
-     t_join,
-     t_levels,
-     t_tokens,
-     t_words,
-     t_systop,
-     t_feed_var,
-     t_sys_match,
-     't_#_match',
-     t_sigle_level_validate,
-     t_sigle_level_match,
-     t_match_perf,
-     t_triples_perf,
-     t_parse].
+-define(N, 100000).
+
+all() -> emqx_ct:all(?MODULE).
 
 t_wildcard(_) ->
     true  = wildcard(<<"a/b/#">>),
@@ -61,7 +46,7 @@ t_wildcard(_) ->
     false = wildcard(<<"">>),
     false = wildcard(<<"a/b/c">>).
 
-t_match(_) ->
+t_match1(_) ->
     true  = match(<<"a/b/c">>, <<"a/b/+">>),
     true  = match(<<"a/b/c">>, <<"a/#">>),
     true  = match(<<"abcd/ef/g">>, <<"#">>),
@@ -132,74 +117,74 @@ t_match_perf(_) ->
     Name = <<"/abkc/19383/192939/akakdkkdkak/xxxyyuya/akakak">>,
     Filter = <<"/abkc/19383/+/akakdkkdkak/#">>,
     true = match(Name, Filter),
-    {Time, _} = timer:tc(fun() ->
-                [match(Name, Filter) || _I <- lists:seq(1, ?N)]
-        end),
-    io:format("Time for match: ~p(micro)", [Time/?N]).
+    ok = bench('match/2', fun emqx_topic:match/2, [Name, Filter]).
 
 t_validate(_) ->
-    true  = validate({name, <<"abc/de/f">>}),
-    true  = validate({filter, <<"abc/+/f">>}),
-    true  = validate({filter, <<"abc/#">>}),
-    true  = validate({filter, <<"x">>}),
-    true  = validate({name, <<"x//y">>}),
-	true  = validate({filter, <<"sport/tennis/#">>}),
-    catch validate({name, <<>>}),
-    catch validate({name, long_topic()}),
-    catch validate({name, <<"abc/#">>}),
-    catch validate({filter, <<"abc/#/1">>}),
-    catch validate({filter, <<"abc/#xzy/+">>}),
-    catch validate({filter, <<"abc/xzy/+9827">>}),
-	catch validate({filter, <<"sport/tennis#">>}),
-    catch validate({filter, <<"sport/tennis/#/ranking">>}),
-    ok.
+    true = validate(<<"a/+/#">>),
+    true = validate(<<"a/b/c/d">>),
+    true = validate({name, <<"abc/de/f">>}),
+    true = validate({filter, <<"abc/+/f">>}),
+    true = validate({filter, <<"abc/#">>}),
+    true = validate({filter, <<"x">>}),
+    true = validate({name, <<"x//y">>}),
+	true = validate({filter, <<"sport/tennis/#">>}),
+    ok = ?catch_error(empty_topic, validate({name, <<>>})),
+    ok = ?catch_error(topic_name_error, validate({name, <<"abc/#">>})),
+    ok = ?catch_error(topic_too_long, validate({name, long_topic()})),
+    ok = ?catch_error('topic_invalid_#', validate({filter, <<"abc/#/1">>})),
+    ok = ?catch_error(topic_invalid_char, validate({filter, <<"abc/#xzy/+">>})),
+    ok = ?catch_error(topic_invalid_char, validate({filter, <<"abc/xzy/+9827">>})),
+	ok = ?catch_error(topic_invalid_char, validate({filter, <<"sport/tennis#">>})),
+    ok = ?catch_error('topic_invalid_#', validate({filter, <<"sport/tennis/#/ranking">>})).
 
 t_sigle_level_validate(_) ->
-    true  = validate({filter, <<"+">>}),
-    true  = validate({filter, <<"+/tennis/#">>}),
-    true  = validate({filter, <<"sport/+/player1">>}),
-    catch validate({filter, <<"sport+">>}),
-    ok.
+    true = validate({filter, <<"+">>}),
+    true = validate({filter, <<"+/tennis/#">>}),
+    true = validate({filter, <<"sport/+/player1">>}),
+    ok = ?catch_error(topic_invalid_char, validate({filter, <<"sport+">>})).
 
 t_triples(_) ->
     Triples = [{root,<<"a">>,<<"a">>},
                {<<"a">>,<<"b">>,<<"a/b">>},
                {<<"a/b">>,<<"c">>,<<"a/b/c">>}],
-    Triples = triples(<<"a/b/c">>).
+    ?assertEqual(Triples, triples(<<"a/b/c">>)).
 
 t_triples_perf(_) ->
     Topic = <<"/abkc/19383/192939/akakdkkdkak/xxxyyuya/akakak">>,
-    {Time, _} = timer:tc(fun() ->
-                [triples(Topic) || _I <- lists:seq(1, ?N)]
-        end),
-    io:format("Time for triples: ~p(micro)", [Time/?N]).
+    ok = bench('triples/1', fun emqx_topic:triples/1, [Topic]).
+
+t_prepend(_) ->
+    ?assertEqual(<<"a/b/c">>, prepend(root, <<"a/b/c">>)),
+    ?assertEqual(<<"ab">>, prepend(undefined, <<"ab">>)),
+    ?assertEqual(<<"a/b">>, prepend(<<>>, <<"a/b">>)),
+    ?assertEqual(<<"x/a/b">>, prepend("x/", <<"a/b">>)),
+    ?assertEqual(<<"x/y/a/b">>, prepend(<<"x/y">>, <<"a/b">>)),
+    ?assertEqual(<<"+/a/b">>, prepend('+', <<"a/b">>)).
 
 t_levels(_) ->
+    ?assertEqual(3, emqx_topic:levels(<<"a/+/#">>)),
     ?assertEqual(4, emqx_topic:levels(<<"a/b/c/d">>)).
 
 t_tokens(_) ->
-    ?assertEqual([<<"a">>, <<"b">>, <<"+">>, <<"#">>], emqx_topic:tokens(<<"a/b/+/#">>)).
+    ?assertEqual([<<"a">>, <<"b">>, <<"+">>, <<"#">>],
+                 emqx_topic:tokens(<<"a/b/+/#">>)).
 
 t_words(_) ->
-    ['', <<"a">>, '+', '#'] = words(<<"/a/+/#">>),
-    ['', <<"abkc">>, <<"19383">>, '+', <<"akakdkkdkak">>, '#'] = words(<<"/abkc/19383/+/akakdkkdkak/#">>),
-    {Time, _} = timer:tc(fun() ->
-                [words(<<"/abkc/19383/+/akakdkkdkak/#">>) || _I <- lists:seq(1, ?N)]
-        end),
-    io:format("Time for words: ~p(micro)", [Time/?N]),
-    {Time2, _} = timer:tc(fun() ->
-                [binary:split(<<"/abkc/19383/+/akakdkkdkak/#">>, <<"/">>, [global]) || _I <- lists:seq(1, ?N)]
-        end),
-    io:format("Time for binary:split: ~p(micro)", [Time2/?N]).
+    Topic = <<"/abkc/19383/+/akakdkkdkak/#">>,
+    ?assertEqual(['', <<"a">>, '+', '#'], words(<<"/a/+/#">>)),
+    ?assertEqual(['', <<"abkc">>, <<"19383">>, '+', <<"akakdkkdkak">>, '#'], words(Topic)),
+    ok = bench('words/1', fun emqx_topic:words/1, [Topic]),
+    BSplit = fun(Bin) -> binary:split(Bin, <<"/">>, [global]) end,
+    ok = bench('binary:split/3', BSplit, [Topic]).
 
 t_join(_) ->
-    <<>>       = join([]),
-    <<"x">>    = join([<<"x">>]),
-    <<"#">>    = join(['#']),
-    <<"+//#">> = join(['+', '', '#']),
-    <<"x/y/z/+">> = join([<<"x">>, <<"y">>, <<"z">>, '+']),
-    <<"/ab/cd/ef/">> = join(words(<<"/ab/cd/ef/">>)),
-    <<"ab/+/#">> = join(words(<<"ab/+/#">>)).
+    ?assertEqual(<<>>, join([])),
+    ?assertEqual(<<"x">>, join([<<"x">>])),
+    ?assertEqual(<<"#">>, join(['#'])),
+    ?assertEqual(<<"+//#">>, join(['+', '', '#'])),
+    ?assertEqual(<<"x/y/z/+">>, join([<<"x">>, <<"y">>, <<"z">>, '+'])),
+    ?assertEqual(<<"/ab/cd/ef/">>, join(words(<<"/ab/cd/ef/">>))),
+    ?assertEqual(<<"ab/+/#">>, join(words(<<"ab/+/#">>))).
 
 t_systop(_) ->
     SysTop1 = iolist_to_binary(["$SYS/brokers/", atom_to_list(node()), "/xyz"]),
@@ -219,12 +204,29 @@ long_topic() ->
     iolist_to_binary([[integer_to_list(I), "/"] || I <- lists:seq(0, 10000)]).
 
 t_parse(_) ->
+    ok = ?catch_error({invalid_topic_filter, <<"$queue/t">>},
+                      parse(<<"$queue/t">>, #{share => <<"g">>})),
+    ok = ?catch_error({invalid_topic_filter, <<"$share/g/t">>},
+                      parse(<<"$share/g/t">>, #{share => <<"g">>})),
+    ok = ?catch_error({invalid_topic_filter, <<"$share/t">>},
+                      parse(<<"$share/t">>)),
+    ok = ?catch_error({invalid_topic_filter, <<"$share/+/t">>},
+                      parse(<<"$share/+/t">>)),
     ?assertEqual({<<"a/b/+/#">>, #{}}, parse(<<"a/b/+/#">>)),
     ?assertEqual({<<"a/b/+/#">>, #{qos => 1}}, parse({<<"a/b/+/#">>, #{qos => 1}})),
-    ?assertEqual({<<"topic">>, #{ share => <<"$queue">> }}, parse(<<"$queue/topic">>)),
-    ?assertEqual({<<"topic">>, #{ share => <<"group">>}}, parse(<<"$share/group/topic">>)),
+    ?assertEqual({<<"topic">>, #{share => <<"$queue">>}}, parse(<<"$queue/topic">>)),
+    ?assertEqual({<<"topic">>, #{share => <<"group">>}}, parse(<<"$share/group/topic">>)),
+    %% The '$local' and '$fastlane' topics have been deprecated.
     ?assertEqual({<<"$local/topic">>, #{}}, parse(<<"$local/topic">>)),
     ?assertEqual({<<"$local/$queue/topic">>, #{}}, parse(<<"$local/$queue/topic">>)),
     ?assertEqual({<<"$local/$share/group/a/b/c">>, #{}}, parse(<<"$local/$share/group/a/b/c">>)),
     ?assertEqual({<<"$fastlane/topic">>, #{}}, parse(<<"$fastlane/topic">>)).
 
+bench(Case, Fun, Args) ->
+    {Time, ok} = timer:tc(fun lists:foreach/2,
+                          [fun(_) -> apply(Fun, Args) end,
+                           lists:seq(1, ?N)
+                          ]),
+    ct:pal("Time consumed by ~s: ~.3f(us)~nCall ~s per second: ~w",
+           [Case, Time/?N, Case, (?N * 1000000) div Time]).
+

+ 2 - 3
test/emqx_tracer_SUITE.erl

@@ -20,10 +20,9 @@
 -compile(nowarn_export_all).
 
 -include_lib("eunit/include/eunit.hrl").
-
 -include_lib("common_test/include/ct.hrl").
 
-all() -> [start_traces].
+all() -> [t_start_traces].
 
 init_per_suite(Config) ->
     emqx_ct_helpers:start_apps([]),
@@ -32,7 +31,7 @@ init_per_suite(Config) ->
 end_per_suite(_Config) ->
     emqx_ct_helpers:stop_apps([]).
 
-start_traces(_Config) ->
+t_start_traces(_Config) ->
     {ok, T} = emqx_client:start_link([{host, "localhost"},
                                       {client_id, <<"client">>},
                                       {username, <<"testuser">>},

+ 3 - 3
test/emqx_trie_SUITE.erl

@@ -25,8 +25,7 @@
 -define(TRIE, emqx_trie).
 -define(TRIE_TABS, [emqx_trie, emqx_trie_node]).
 
-all() ->
-    [t_mnesia, t_insert, t_match, t_match2, t_match3, t_empty, t_delete, t_delete2, t_delete3].
+all() -> emqx_ct:all(?MODULE).
 
 init_per_suite(Config) ->
     application:load(emqx),
@@ -51,7 +50,8 @@ t_insert(_) ->
     TN = #trie_node{node_id = <<"sensor">>,
                     edge_count = 3,
                     topic = <<"sensor">>,
-                    flags = undefined},
+                    flags = undefined
+                   },
     Fun = fun() ->
               ?TRIE:insert(<<"sensor/1/metric/2">>),
               ?TRIE:insert(<<"sensor/+/#">>),

+ 26 - 29
test/emqx_vm_SUITE.erl

@@ -19,7 +19,7 @@
 -compile(export_all).
 -compile(nowarn_export_all).
 
--include_lib("common_test/include/ct.hrl").
+-include_lib("eunit/include/eunit.hrl").
 
 -define(SYSTEM_INFO, [allocated_areas,
                       allocator,
@@ -94,82 +94,79 @@
                      min_heap_size]).
                      %fullsweep_after]).
 
+all() -> emqx_ct:all(?MODULE).
 
+t_load(_Config) ->
+    ?assertMatch([{load1, _},
+                  {load5, _},
+                  {load15, _}
+                 ], emqx_vm:loads()).
 
-all() ->
-    [load, systeminfo, mem_info, process_list, process_info, process_gc,
-     get_ets_list, get_ets_info, get_ets_object, get_port_types, get_port_info,
-     scheduler_usage, get_memory, microsecs, schedulers, get_process_group_leader_info,
-     get_process_limit].
-
-load(_Config) ->
-    Loads = emqx_vm:loads(),
-    [{load1, _}, {load5, _}, {load15, _}] = Loads.
-
-systeminfo(_Config) ->
+t_systeminfo(_Config) ->
    Keys =  [Key || {Key, _} <- emqx_vm:get_system_info()],
    ?SYSTEM_INFO = Keys.
 
-mem_info(_Config) ->
+t_mem_info(_Config) ->
     application:ensure_all_started(os_mon),
     MemInfo = emqx_vm:mem_info(),
     [{total_memory, _},
      {used_memory, _}]= MemInfo,
     application:stop(os_mon).
 
-process_list(_Config) ->
+t_process_list(_Config) ->
     Pid = self(),
     ProcessInfo = emqx_vm:get_process_list(),
     true = lists:member({pid, Pid}, lists:concat(ProcessInfo)).
 
-process_info(_Config) ->
+t_process_info(_Config) ->
     ProcessInfos = emqx_vm:get_process_info(),
     ProcessInfo = lists:last(ProcessInfos),
     Keys = [K || {K, _V}<- ProcessInfo],
     ?PROCESS_INFO = Keys.
 
-process_gc(_Config) ->
+t_process_gc(_Config) ->
     ProcessGcs = emqx_vm:get_process_gc(),
     ProcessGc = lists:last(ProcessGcs),
     Keys = [K || {K, _V}<- ProcessGc],
     ?PROCESS_GC = Keys.
-   
-get_ets_list(_Config) ->
+
+t_get_ets_list(_Config) ->
     ets:new(test, [named_table]),
     Ets =  emqx_vm:get_ets_list(),
     true = lists:member(test, Ets).
 
-get_ets_info(_Config) ->
+t_get_ets_info(_Config) ->
     ets:new(test, [named_table]),
     [] = emqx_vm:get_ets_info(test1),
     EtsInfo = emqx_vm:get_ets_info(test),
     test = proplists:get_value(name, EtsInfo).
 
-get_ets_object(_Config) ->
+t_get_ets_object(_Config) ->
     ets:new(test, [named_table]),
     ets:insert(test, {k, v}),
     [{k, v}] = emqx_vm:get_ets_object(test).
 
-get_port_types(_Config) ->
+t_get_port_types(_Config) ->
     emqx_vm:get_port_types().
 
-get_port_info(_Config) ->
+t_get_port_info(_Config) ->
     emqx_vm:get_port_info().
 
-scheduler_usage(_Config) ->
+t_scheduler_usage(_Config) ->
     emqx_vm:scheduler_usage(5000).
 
-get_memory(_Config) ->
+t_get_memory(_Config) ->
     emqx_vm:get_memory().
-   
-microsecs(_Config) ->
+
+t_microsecs(_Config) ->
     emqx_vm:microsecs().
 
-schedulers(_Config) ->
+t_schedulers(_Config) ->
     emqx_vm:schedulers().
 
-get_process_group_leader_info(_Config) ->
+t_get_process_group_leader_info(_Config) ->
     emqx_vm:get_process_group_leader_info(self()).
 
-get_process_limit(_Config) ->
+t_get_process_limit(_Config) ->
     emqx_vm:get_process_limit().
+

+ 2 - 3
test/emqx_vm_mon_SUITE.erl

@@ -21,8 +21,6 @@
 
 -include_lib("eunit/include/eunit.hrl").
 
--include_lib("common_test/include/ct.hrl").
-
 -define(WAIT(PATTERN, TIMEOUT),
         receive
             PATTERN ->
@@ -32,7 +30,7 @@
                 error(timeout)
         end).
 
-all() -> [t_api].
+all() -> emqx_ct:all(?MODULE).
 
 init_per_suite(Config) ->
     application:ensure_all_started(sasl),
@@ -75,3 +73,4 @@ t_api(_) ->
     after
         meck:unload(alarm_handler)
     end.
+

+ 0 - 144
test/emqx_ws_channel_SUITE.erl

@@ -1,144 +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_ws_channel_SUITE).
-
--compile(export_all).
--compile(nowarn_export_all).
-
--include("emqx_mqtt.hrl").
--include_lib("eunit/include/eunit.hrl").
--include_lib("common_test/include/ct.hrl").
-
--define(CLIENT, ?CONNECT_PACKET(#mqtt_packet_connect{
-                                client_id = <<"mqtt_client">>,
-                                username  = <<"admin">>,
-                                password  = <<"public">>})).
-
--define(WILL_TOPIC, <<"test/websocket/will">>).
-
--define(WILL_CLIENT, ?CONNECT_PACKET(#mqtt_packet_connect{
-                                     client_id = <<"mqtt_client">>,
-                                     username  = <<"admin">>,
-                                     password  = <<"public">>,
-                                     will_flag = true,
-                                     will_qos = ?QOS_1,
-                                     will_topic = ?WILL_TOPIC,
-                                     will_payload = <<"payload">>
-                                   })).
-
-all() ->
-    [ t_ws_connect_api
-    , t_ws_auth_failure
-    , t_ws_other_type_frame
-    , t_ws_will
-    ].
-
-init_per_suite(Config) ->
-    emqx_ct_helpers:start_apps([]),
-    Config.
-
-end_per_suite(_Config) ->
-    emqx_ct_helpers:stop_apps([]).
-
-t_ws_will(_Config) ->
-    {ok, ClientPid} = emqx_client:start_link(),
-    {ok, _} = emqx_client:connect(ClientPid),
-    {ok, _, [1]} = emqx_client:subscribe(ClientPid, ?WILL_TOPIC, qos1),
-    WS = rfc6455_client:new("ws://127.0.0.1:8083" ++ "/mqtt", self()),
-    {ok, _} = rfc6455_client:open(WS),
-    Packet = raw_send_serialize(?WILL_CLIENT),
-    ok = rfc6455_client:send_binary(WS, Packet),
-    {binary, Bin} = rfc6455_client:recv(WS),
-    Connack = ?CONNACK_PACKET(?CONNACK_ACCEPT),
-    {ok, Connack, <<>>, _} = raw_recv_pase(Bin),
-    exit(WS, abnomal),
-    ?assertEqual(1, length(emqx_client_SUITE:receive_messages(1))),
-    ok = emqx_client:disconnect(ClientPid),
-    ok.
-
-t_ws_auth_failure(_Config) ->
-    application:set_env(emqx, allow_anonymous, false),
-    WS = rfc6455_client:new("ws://127.0.0.1:8083" ++ "/mqtt", self()),
-    {ok, _} = rfc6455_client:open(WS),
-    Connect = ?CONNECT_PACKET(
-                 #mqtt_packet_connect{
-                    client_id = <<"mqtt_client">>,
-                    username  = <<"admin">>,
-                    password  = <<"public">>
-                   }),
-    ok = rfc6455_client:send_binary(WS, raw_send_serialize(Connect)),
-    {binary, Bin} = rfc6455_client:recv(WS),
-    Connack = ?CONNACK_PACKET(?CONNACK_ACCEPT),
-    {ok, Connack, <<>>, _} = raw_recv_pase(Bin),
-    Pid = emqx_cm:lookup_conn_pid(<<"mqtt_client">>),
-    ConnInfo = emqx_ws_channel:info(Pid),
-    ok = t_info(ConnInfo),
-    ConnAttrs = emqx_ws_channel:attrs(Pid),
-    ok = t_attrs(ConnAttrs),
-    ConnStats = emqx_ws_channel:stats(Pid),
-    ok = t_stats(ConnStats),
-    SessionPid = emqx_ws_channel:session(Pid),
-    true = is_pid(SessionPid),
-    ok = emqx_ws_channel:kick(Pid),
-    {close, _} = rfc6455_client:close(WS),
-    ok.
-
-t_ws_other_type_frame(_Config) ->
-    WS = rfc6455_client:new("ws://127.0.0.1:8083" ++ "/mqtt", self()),
-    {ok, _} = rfc6455_client:open(WS),
-    Connect = ?CONNECT_PACKET(
-                 #mqtt_packet_connect{
-                    client_id = <<"mqtt_client">>,
-                    username  = <<"admin">>,
-                    password  = <<"public">>
-                   }),
-    ok = rfc6455_client:send_binary(WS, raw_send_serialize(Connect)),
-    {binary, Bin} = rfc6455_client:recv(WS),
-    Connack = ?CONNACK_PACKET(?CONNACK_ACCEPT),
-    {ok, Connack, <<>>, _} = raw_recv_pase(Bin),
-    rfc6455_client:send(WS, <<"testdata">>),
-    timer:sleep(1000),
-    ?assertEqual(undefined, erlang:process_info(WS)),
-    ok.
-
-raw_send_serialize(Packet) ->
-    emqx_frame:serialize(Packet).
-
-raw_recv_pase(Packet) ->
-    emqx_frame:parse(Packet).
-
-t_info(InfoData) ->
-    ?assertEqual(websocket, maps:get(socktype, InfoData)),
-    ?assertEqual(running, maps:get(conn_state, InfoData)),
-    ?assertEqual(<<"mqtt_client">>, maps:get(client_id, InfoData)),
-    ?assertEqual(<<"admin">>, maps:get(username, InfoData)),
-    ?assertEqual(<<"MQTT">>, maps:get(proto_name, InfoData)).
-
-t_attrs(AttrsData) ->
-    ?assertEqual(<<"mqtt_client">>, maps:get(client_id, AttrsData)),
-    ?assertEqual(emqx_ws_channel, maps:get(conn_mod, AttrsData)),
-    ?assertEqual(<<"admin">>, maps:get(username, AttrsData)).
-
-t_stats(StatsData) ->
-    ?assertEqual(true, proplists:get_value(recv_oct, StatsData) >= 0),
-    ?assertEqual(true, proplists:get_value(mailbox_len, StatsData) >= 0),
-    ?assertEqual(true, proplists:get_value(heap_size, StatsData) >= 0),
-    ?assertEqual(true, proplists:get_value(reductions, StatsData) >=0),
-    ?assertEqual(true, proplists:get_value(recv_pkt, StatsData) =:=1),
-    ?assertEqual(true, proplists:get_value(recv_msg, StatsData) >=0),
-    ?assertEqual(true, proplists:get_value(send_pkt, StatsData) =:=1).
-

+ 22 - 11
test/emqx_zone_SUITE.erl

@@ -19,20 +19,31 @@
 -compile(export_all).
 -compile(nowarn_export_all).
 
--include("emqx_mqtt.hrl").
 -include_lib("eunit/include/eunit.hrl").
 
-all() -> [t_set_get_env].
+-define(OPTS, [{enable_acl, true},
+               {enable_banned, false}
+              ]).
+
+all() -> emqx_ct:all(?MODULE).
 
 t_set_get_env(_) ->
-    application:set_env(emqx, zones, [{china, [{language, chinese}]}]),
+    _ = application:load(emqx),
+    application:set_env(emqx, zones, [{external, ?OPTS}]),
     {ok, _} = emqx_zone:start_link(),
-    chinese = emqx_zone:get_env(china, language),
-    cn470 = emqx_zone:get_env(china, ism_band, cn470),
-    undefined = emqx_zone:get_env(undefined, delay),
-    500 = emqx_zone:get_env(undefined, delay, 500),
-    application:set_env(emqx, zones, [{zone1, [{key, val}]}]),
-    ?assertEqual(undefined, emqx_zone:get_env(zone1, key)),
-    emqx_zone:force_reload(),
-    ?assertEqual(val, emqx_zone:get_env(zone1, key)),
+    ?assert(emqx_zone:get_env(external, enable_acl)),
+    ?assertNot(emqx_zone:get_env(external, enable_banned)),
+    ?assertEqual(defval, emqx_zone:get_env(extenal, key, defval)),
+    ?assertEqual(undefined, emqx_zone:get_env(external, key)),
+    ?assertEqual(undefined, emqx_zone:get_env(internal, key)),
+    ?assertEqual(def, emqx_zone:get_env(internal, key, def)),
     emqx_zone:stop().
+
+t_force_reload(_) ->
+    {ok, _} = emqx_zone:start_link(),
+    application:set_env(emqx, zones, [{zone, [{key, val}]}]),
+    ?assertEqual(undefined, emqx_zone:get_env(zone, key)),
+    ok = emqx_zone:force_reload(),
+    ?assertEqual(val, emqx_zone:get_env(zone, key)),
+    emqx_zone:stop().
+

+ 0 - 251
test/rfc6455_client.erl

@@ -1,251 +0,0 @@
-%% The contents of this file are subject to the Mozilla Public License
-%% Version 1.1 (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.mozilla.org/MPL/
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
-%% License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Original Code is RabbitMQ Management Console.
-%%
-%% The Initial Developer of the Original Code is GoPivotal, Inc.
-%% Copyright (c) 2012-2016 Pivotal Software, Inc.  All rights reserved.
-%%
-
--module(rfc6455_client).
-
--export([new/2, open/1, recv/1, send/2, send_binary/2, close/1, close/2]).
-
--record(state, {host, port, addr, path, ppid, socket, data, phase}).
-
-%% --------------------------------------------------------------------------
-
-new(WsUrl, PPid) ->
-    crypto:start(),
-    "ws://" ++ Rest = WsUrl,
-    [Addr, Path] = split("/", Rest, 1),
-    [Host, MaybePort] = split(":", Addr, 1, empty),
-    Port = case MaybePort of
-               empty -> 80;
-               V     -> {I, ""} = string:to_integer(V), I
-           end,
-    State = #state{host = Host,
-                   port = Port,
-                   addr = Addr,
-                   path = "/" ++ Path,
-                   ppid = PPid},
-    spawn(fun() ->
-                  start_conn(State)
-          end).
-
-open(WS) ->
-    receive
-        {rfc6455, open, WS, Opts} ->
-            {ok, Opts};
-        {rfc6455, close, WS, R} ->
-            {close, R}
-    end.
-
-recv(WS) ->
-    receive
-        {rfc6455, recv, WS, Payload} ->
-            {ok, Payload};
-        {rfc6455, recv_binary, WS, Payload} ->
-            {binary, Payload};
-        {rfc6455, close, WS, R} ->
-            {close, R}
-    end.
-
-send(WS, IoData) ->
-    WS ! {send, IoData},
-    ok.
-
-send_binary(WS, IoData) ->
-    WS ! {send_binary, IoData},
-    ok.
-
-close(WS) ->
-    close(WS, {1000, ""}).
-
-close(WS, WsReason) ->
-    WS ! {close, WsReason},
-    receive
-        {rfc6455, close, WS, R} ->
-            {close, R}
-    end.
-
-
-%% --------------------------------------------------------------------------
-
-start_conn(State) ->
-    {ok, Socket} = gen_tcp:connect(State#state.host, State#state.port,
-                                   [binary,
-                                    {packet, 0}]),
-    Key = base64:encode_to_string(crypto:strong_rand_bytes(16)),
-    gen_tcp:send(Socket,
-        "GET " ++ State#state.path ++ " HTTP/1.1\r\n" ++
-        "Host: " ++ State#state.addr ++ "\r\n" ++
-        "Upgrade: websocket\r\n" ++
-        "Connection: Upgrade\r\n" ++
-        "Sec-WebSocket-Key: " ++ Key ++ "\r\n" ++
-        "Origin: null\r\n" ++
-        "Sec-WebSocket-Protocol: mqtt\r\n" ++
-        "Sec-WebSocket-Version: 13\r\n\r\n"),
-
-    loop(State#state{socket = Socket,
-                     data   = <<>>,
-                     phase = opening}).
-
-do_recv(State = #state{phase = opening, ppid = PPid, data = Data}) ->
-    case split("\r\n\r\n", binary_to_list(Data), 1, empty) of
-        [_Http, empty] -> State;
-        [Http, Data1]   ->
-            %% TODO: don't ignore http response data, verify key
-            PPid ! {rfc6455, open, self(), [{http_response, Http}]},
-            State#state{phase = open,
-                        data = Data1}
-    end;
-do_recv(State = #state{phase = Phase, data = Data, socket = Socket, ppid = PPid})
-  when Phase =:= open orelse Phase =:= closing ->
-    R = case Data of
-            <<F:1, _:3, O:4, 0:1, L:7, Payload:L/binary, Rest/binary>>
-              when L < 126 ->
-                {F, O, Payload, Rest};
-
-            <<F:1, _:3, O:4, 0:1, 126:7, L2:16, Payload:L2/binary, Rest/binary>> ->
-                {F, O, Payload, Rest};
-
-            <<F:1, _:3, O:4, 0:1, 127:7, L2:64, Payload:L2/binary, Rest/binary>> ->
-                {F, O, Payload, Rest};
-
-            <<_:1, _:3, _:4, 1:1, _/binary>> ->
-                %% According o rfc6455 5.1 the server must not mask any frames.
-                die(Socket, PPid, {1006, "Protocol error"}, normal);
-            _ ->
-                moredata
-        end,
-    case R of
-        moredata ->
-            State;
-        _ -> do_recv2(State, R)
-    end.
-
-do_recv2(State = #state{phase = Phase, socket = Socket, ppid = PPid}, R) ->
-    case R of
-        {1, 1, Payload, Rest} ->
-            PPid ! {rfc6455, recv, self(), Payload},
-            State#state{data = Rest};
-        {1, 2, Payload, Rest} ->
-            PPid ! {rfc6455, recv_binary, self(), Payload},
-            State#state{data = Rest};
-        {1, 8, Payload, _Rest} ->
-            WsReason = case Payload of
-                           <<WC:16, WR/binary>> -> {WC, WR};
-                           <<>> -> {1005, "No status received"}
-                       end,
-            case Phase of
-                open -> %% echo
-                    do_close(State, WsReason),
-                    gen_tcp:close(Socket);
-                closing ->
-                    ok
-            end,
-            die(Socket, PPid, WsReason, normal);
-        {_, _, _, _Rest2} ->
-            io:format("Unknown frame type~n"),
-            die(Socket, PPid, {1006, "Unknown frame type"}, normal)
-    end.
-
-encode_frame(F, O, Payload) ->
-    Mask = crypto:strong_rand_bytes(4),
-    MaskedPayload = apply_mask(Mask, iolist_to_binary(Payload)),
-
-    L = byte_size(MaskedPayload),
-    IoData = case L of
-                 _ when L < 126 ->
-                     [<<F:1, 0:3, O:4, 1:1, L:7>>, Mask, MaskedPayload];
-                 _ when L < 65536 ->
-                     [<<F:1, 0:3, O:4, 1:1, 126:7, L:16>>, Mask, MaskedPayload];
-                 _ ->
-                     [<<F:1, 0:3, O:4, 1:1, 127:7, L:64>>, Mask, MaskedPayload]
-           end,
-    iolist_to_binary(IoData).
-
-do_send(State = #state{socket = Socket}, Payload) ->
-    gen_tcp:send(Socket, encode_frame(1, 1, Payload)),
-    State.
-
-do_send_binary(State = #state{socket = Socket}, Payload) ->
-    gen_tcp:send(Socket, encode_frame(1, 2, Payload)),
-    State.
-
-do_close(State = #state{socket = Socket}, {Code, Reason}) ->
-    Payload = iolist_to_binary([<<Code:16>>, Reason]),
-    gen_tcp:send(Socket, encode_frame(1, 8, Payload)),
-    State#state{phase = closing}.
-
-loop(State = #state{socket = Socket, ppid = PPid, data = Data,
-                    phase = Phase}) ->
-    receive
-        {tcp, Socket, Bin} ->
-            State1 = State#state{data = iolist_to_binary([Data, Bin])},
-            loop(do_recv(State1));
-        {send, Payload} when Phase == open ->
-            loop(do_send(State, Payload));
-        {send_binary, Payload} when Phase == open ->
-            loop(do_send_binary(State, Payload));
-        {tcp_closed, Socket} ->
-            die(Socket, PPid, {1006, "Connection closed abnormally"}, normal);
-        {close, WsReason} when Phase == open ->
-            loop(do_close(State, WsReason))
-    end.
-
-
-die(Socket, PPid, WsReason, Reason) ->
-    gen_tcp:shutdown(Socket, read_write),
-    PPid ! {rfc6455, close, self(), WsReason},
-    exit(Reason).
-
-
-%% --------------------------------------------------------------------------
-
-split(SubStr, Str, Limit) ->
-    split(SubStr, Str, Limit, "").
-
-split(SubStr, Str, Limit, Default) ->
-    Acc = split(SubStr, Str, Limit, [], Default),
-    lists:reverse(Acc).
-split(_SubStr, Str, 0, Acc, _Default) -> [Str | Acc];
-split(SubStr, Str, Limit, Acc, Default) ->
-    {L, R} = case string:str(Str, SubStr) of
-                 0 -> {Str, Default};
-                 I -> {string:substr(Str, 1, I-1),
-                       string:substr(Str, I+length(SubStr))}
-             end,
-    split(SubStr, R, Limit-1, [L | Acc], Default).
-
-
-apply_mask(Mask, Data) when is_number(Mask) ->
-    apply_mask(<<Mask:32>>, Data);
-
-apply_mask(<<0:32>>, Data) ->
-    Data;
-apply_mask(Mask, Data) ->
-    iolist_to_binary(lists:reverse(apply_mask2(Mask, Data, []))).
-
-apply_mask2(M = <<Mask:32>>, <<Data:32, Rest/binary>>, Acc) ->
-    T = Data bxor Mask,
-    apply_mask2(M, Rest, [<<T:32>> | Acc]);
-apply_mask2(<<Mask:24, _:8>>, <<Data:24>>, Acc) ->
-    T = Data bxor Mask,
-    [<<T:24>> | Acc];
-apply_mask2(<<Mask:16, _:16>>, <<Data:16>>, Acc) ->
-    T = Data bxor Mask,
-    [<<T:16>> | Acc];
-apply_mask2(<<Mask:8, _:24>>, <<Data:8>>, Acc) ->
-    T = Data bxor Mask,
-    [<<T:8>> | Acc];
-apply_mask2(_, <<>>, Acc) ->
-    Acc.

+ 0 - 75
test/ws_client.erl

@@ -1,75 +0,0 @@
--module(ws_client).
-
--export([
-         start_link/0,
-         start_link/1,
-         send_binary/2,
-         send_ping/2,
-         recv/2,
-         recv/1,
-         stop/1
-        ]).
-
--export([
-         init/2,
-         websocket_handle/3,
-         websocket_info/3,
-         websocket_terminate/3
-        ]).
-
--record(state, {
-          buffer = [] :: list(),
-          waiting = undefined :: undefined | pid()
-         }).
-
-start_link() ->
-    start_link("ws://localhost:8083/mqtt").
-
-start_link(Url) ->
-    websocket_client:start_link(Url, ?MODULE, [], [{extra_headers, [{"Sec-Websocket-Protocol", "mqtt"}]}]).
-
-stop(Pid) ->
-    Pid ! stop.
-
-send_binary(Pid, Msg) ->
-    websocket_client:cast(Pid, {binary, Msg}).
-
-send_ping(Pid, Msg) ->
-    websocket_client:cast(Pid, {ping, Msg}).
-
-recv(Pid) ->
-    recv(Pid, 5000).
-
-recv(Pid, Timeout) ->
-    Pid ! {recv, self()},
-    receive
-        M -> M
-    after
-        Timeout -> error
-    end.
-
-init(_, _WSReq) ->
-    {ok, #state{}}.
-
-websocket_handle(Frame, _, State = #state{waiting = undefined, buffer = Buffer}) ->
-    logger:info("Client received frame~p", [Frame]),
-    {ok, State#state{buffer = [Frame|Buffer]}};
-websocket_handle(Frame, _, State = #state{waiting = From}) ->
-    logger:info("Client received frame~p", [Frame]),
-    From ! Frame,
-    {ok, State#state{waiting = undefined}}.
-
-websocket_info({send_text, Text}, WSReq, State) ->
-    websocket_client:send({text, Text}, WSReq),
-    {ok, State};
-websocket_info({recv, From}, _, State = #state{buffer = []}) ->
-    {ok, State#state{waiting = From}};
-websocket_info({recv, From}, _, State = #state{buffer = [Top|Rest]}) ->
-    From ! Top,
-    {ok, State#state{buffer = Rest}};
-websocket_info(stop, _, State) ->
-    {close, <<>>, State}.
-
-websocket_terminate(Close, _, State) ->
-    io:format("Websocket closed with frame ~p and state ~p", [Close, State]),
-    ok.