diff --git a/.ci/build_packages/tests.sh b/.ci/build_packages/tests.sh index 36cf801b0..98139dc99 100755 --- a/.ci/build_packages/tests.sh +++ b/.ci/build_packages/tests.sh @@ -179,7 +179,7 @@ relup_test(){ find . -maxdepth 1 -name "${EMQX_NAME}-*-${ARCH}.zip" | while read -r pkg; do packagename=$(basename "${pkg}") - unzip "$packagename" + unzip -q "$packagename" if ! ./emqx/bin/emqx start; then cat emqx/log/erlang.log.1 || true cat emqx/log/emqx.log.1 || true @@ -190,8 +190,14 @@ relup_test(){ cp "${PACKAGE_PATH}/${EMQX_NAME}-${TARGET_VERSION}"-*-"${ARCH}".zip ./emqx/releases ./emqx/bin/emqx install "${TARGET_VERSION}" [ "$(./emqx/bin/emqx versions |grep permanent | awk '{print $2}')" = "${TARGET_VERSION}" ] || exit 1 + export EMQX_WAIT_FOR_STOP=300 ./emqx/bin/emqx_ctl status - ./emqx/bin/emqx stop + if ! ./emqx/bin/emqx stop; then + cat emqx/log/erlang.log.1 || true + cat emqx/log/emqx.log.1 || true + echo "failed to stop emqx" + exit 1 + fi rm -rf emqx done fi diff --git a/.ci/docker-compose-file/http-service/Dockerfile b/.ci/docker-compose-file/http-service/Dockerfile index df1f7f98c..6601841ef 100644 --- a/.ci/docker-compose-file/http-service/Dockerfile +++ b/.ci/docker-compose-file/http-service/Dockerfile @@ -1,7 +1,7 @@ FROM tomcat:10.0.5 RUN wget https://downloads.apache.org/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip \ - && unzip apache-maven-3.6.3-bin.zip \ + && unzip -q apache-maven-3.6.3-bin.zip \ && mv apache-maven-3.6.3 /opt/apache-maven-3.6.3/ \ && ln -s /opt/apache-maven-3.6.3/ /opt/maven ENV M2_HOME=/opt/maven diff --git a/.github/workflows/build_packages.yaml b/.github/workflows/build_packages.yaml index 5357ff35f..39b387e1c 100644 --- a/.github/workflows/build_packages.yaml +++ b/.github/workflows/build_packages.yaml @@ -119,7 +119,7 @@ jobs: mkdir -p _packages/${{ matrix.profile }} Compress-Archive -Path _build/${{ matrix.profile }}/rel/emqx -DestinationPath _build/${{ matrix.profile }}/rel/$pkg_name mv _build/${{ matrix.profile }}/rel/$pkg_name _packages/${{ matrix.profile }} - Get-FileHash -Path "_packages/${{ matrix.profile }}/$pkg_name" | Format-List | grep 'Hash' | awk '{print $3}' > _packages/${{ matrix.profile }}/$pkg_name.sha256 + sha256sum "_packages/${{ matrix.profile }}/$pkg_name" | head -c 64 > "_packages/${{ matrix.profile }}/${pkg_name}.sha256" - name: run emqx timeout-minutes: 1 working-directory: source @@ -207,8 +207,14 @@ jobs: exit 1 fi ./emqx/bin/emqx_ctl status - ./emqx/bin/emqx stop + if ! ./emqx/bin/emqx stop; then + cat emqx/log/erlang.log.1 || true + cat emqx/log/emqx.log.1 || true + echo "failed to stop emqx" + exit 1 + fi rm -rf emqx + #sha256sum $pkg_name | head -c64 > $pkg_name.sha256 openssl dgst -sha256 $pkg_name | awk '{print $2}' > $pkg_name.sha256 - uses: actions/upload-artifact@v1 if: startsWith(github.ref, 'refs/tags/') @@ -381,7 +387,7 @@ jobs: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ${{ secrets.AWS_DEFAULT_REGION }} - - name: Docker login for aws ecr + - name: Docker login to aws ecr if: matrix.registry == 'public.ecr.aws' run: aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws - uses: docker/login-action@v1 diff --git a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.appup.src b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.appup.src index 46fbd1f06..acaf9403d 100644 --- a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.appup.src +++ b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.appup.src @@ -1,45 +1,38 @@ %% -*- mode: erlang -*- {VSN, - [ - {<<"4.3.[0-3]">>, [ - {add_module,emqx_acl_mnesia_db}, - {add_module,emqx_acl_mnesia_migrator, [emqx_acl_mnesia_db]}, - {update, emqx_auth_mnesia_sup, supervisor}, - {apply, {emqx_acl_mnesia_migrator, start_supervised, []}}, - {load_module,emqx_auth_mnesia_api, brutal_purge,soft_purge,[]}, - {load_module,emqx_acl_mnesia, brutal_purge,soft_purge,[]}, - {load_module,emqx_auth_mnesia_app, brutal_purge,soft_purge,[]}, - {load_module,emqx_acl_mnesia_api, brutal_purge,soft_purge,[]}, - {load_module,emqx_acl_mnesia_cli, brutal_purge,soft_purge,[]} - ]}, - {<<"4.3.4">>, [ - {load_module,emqx_auth_mnesia, brutal_purge,soft_purge,[]}, - {load_module,emqx_auth_mnesia_cli, brutal_purge,soft_purge,[]}, - {load_module,emqx_acl_mnesia, brutal_purge,soft_purge,[]}, - {load_module,emqx_auth_mnesia_app, brutal_purge,soft_purge,[]} - ]}, - {<<".*">>, [ - ]} - ], - [ - {<<"4.3.[0-3]">>, [ - {apply, {emqx_acl_mnesia_migrator, stop_supervised, []}}, - {update, emqx_auth_mnesia_sup, supervisor}, - {load_module,emqx_acl_mnesia_cli, brutal_purge,soft_purge,[]}, - {load_module,emqx_acl_mnesia_api, brutal_purge,soft_purge,[]}, - {load_module,emqx_auth_mnesia_api, brutal_purge,soft_purge,[]}, - {load_module,emqx_acl_mnesia, brutal_purge,soft_purge,[]}, - {load_module,emqx_auth_mnesia_app, brutal_purge,soft_purge,[]}, - {delete_module,emqx_acl_mnesia_migrator}, - {delete_module,emqx_acl_mnesia_db} - ]}, - {<<"4.3.4">>, [ - {load_module,emqx_auth_mnesia, brutal_purge,soft_purge,[]}, - {load_module,emqx_auth_mnesia_cli, brutal_purge,soft_purge,[]}, - {load_module,emqx_acl_mnesia, brutal_purge,soft_purge,[]}, - {load_module,emqx_auth_mnesia_app, brutal_purge,soft_purge,[]} - ]}, - {<<".*">>, [ - ]} - ] -}. + [{<<"4.3.[0-3]">>, + [{load_module,emqx_auth_mnesia_cli,brutal_purge,soft_purge,[]}, + {load_module,emqx_auth_mnesia,brutal_purge,soft_purge,[]}, + {add_module,emqx_acl_mnesia_db}, + {add_module,emqx_acl_mnesia_migrator,[emqx_acl_mnesia_db]}, + {update,emqx_auth_mnesia_sup,supervisor}, + {apply,{emqx_acl_mnesia_migrator,start_supervised,[]}}, + {load_module,emqx_auth_mnesia_api,brutal_purge,soft_purge,[]}, + {load_module,emqx_acl_mnesia,brutal_purge,soft_purge,[]}, + {load_module,emqx_auth_mnesia_app,brutal_purge,soft_purge,[]}, + {load_module,emqx_acl_mnesia_api,brutal_purge,soft_purge,[]}, + {load_module,emqx_acl_mnesia_cli,brutal_purge,soft_purge,[]}]}, + {<<"4.3.4">>, + [{load_module,emqx_auth_mnesia,brutal_purge,soft_purge,[]}, + {load_module,emqx_auth_mnesia_cli,brutal_purge,soft_purge,[]}, + {load_module,emqx_acl_mnesia,brutal_purge,soft_purge,[]}, + {load_module,emqx_auth_mnesia_app,brutal_purge,soft_purge,[]}]}, + {<<".*">>,[]}], + [{<<"4.3.[0-3]">>, + [{load_module,emqx_auth_mnesia_cli,brutal_purge,soft_purge,[]}, + {load_module,emqx_auth_mnesia,brutal_purge,soft_purge,[]}, + {apply,{emqx_acl_mnesia_migrator,stop_supervised,[]}}, + {update,emqx_auth_mnesia_sup,supervisor}, + {load_module,emqx_acl_mnesia_cli,brutal_purge,soft_purge,[]}, + {load_module,emqx_acl_mnesia_api,brutal_purge,soft_purge,[]}, + {load_module,emqx_auth_mnesia_api,brutal_purge,soft_purge,[]}, + {load_module,emqx_acl_mnesia,brutal_purge,soft_purge,[]}, + {load_module,emqx_auth_mnesia_app,brutal_purge,soft_purge,[]}, + {delete_module,emqx_acl_mnesia_migrator}, + {delete_module,emqx_acl_mnesia_db}]}, + {<<"4.3.4">>, + [{load_module,emqx_auth_mnesia,brutal_purge,soft_purge,[]}, + {load_module,emqx_auth_mnesia_cli,brutal_purge,soft_purge,[]}, + {load_module,emqx_acl_mnesia,brutal_purge,soft_purge,[]}, + {load_module,emqx_auth_mnesia_app,brutal_purge,soft_purge,[]}]}, + {<<".*">>,[]}]}. diff --git a/apps/emqx_auth_mnesia/test/emqx_acl_mnesia_SUITE.erl b/apps/emqx_auth_mnesia/test/emqx_acl_mnesia_SUITE.erl index eb1ea74f3..1878dec45 100644 --- a/apps/emqx_auth_mnesia/test/emqx_acl_mnesia_SUITE.erl +++ b/apps/emqx_auth_mnesia/test/emqx_acl_mnesia_SUITE.erl @@ -47,7 +47,9 @@ groups() -> ]}]. init_per_suite(Config) -> - emqx_ct_helpers:start_apps([emqx_modules, emqx_management, emqx_auth_mnesia], fun set_special_configs/1), + emqx_ct_helpers:start_apps( [emqx_modules, emqx_management, emqx_auth_mnesia] + , fun set_special_configs/1 + ), supervisor:terminate_child(emqx_auth_mnesia_sup, emqx_acl_mnesia_migrator), create_default_app(), Config. @@ -151,7 +153,9 @@ run_acl_tests() -> timer:sleep(100), deny = emqx_access_control:check_acl(User1, subscribe, <<"topic/mix">>), allow = emqx_access_control:check_acl(User1, publish, <<"topic/mix">>), - ok = emqx_acl_mnesia_db:add_acl({clientid, <<"test_clientid">>}, <<"topic/mix">>, pubsub, allow), + ok = emqx_acl_mnesia_db:add_acl( {clientid, <<"test_clientid">>} + , <<"topic/mix">>, pubsub, allow + ), timer:sleep(100), allow = emqx_access_control:check_acl(User1, subscribe, <<"topic/mix">>), allow = emqx_access_control:check_acl(User1, publish, <<"topic/mix">>), @@ -302,7 +306,7 @@ t_start_stop_supervised(_Config) -> t_acl_cli(_Config) -> meck:new(emqx_ctl, [non_strict, passthrough]), - meck:expect(emqx_ctl, print, fun(Arg) -> emqx_ctl:format(Arg) end), + meck:expect(emqx_ctl, print, fun(Arg) -> emqx_ctl:format(Arg, []) end), meck:expect(emqx_ctl, print, fun(Msg, Arg) -> emqx_ctl:format(Msg, Arg) end), meck:expect(emqx_ctl, usage, fun(Usages) -> emqx_ctl:format_usage(Usages) end), meck:expect(emqx_ctl, usage, fun(Cmd, Descr) -> emqx_ctl:format_usage(Cmd, Descr) end), @@ -411,8 +415,12 @@ t_rest_api(_Config) -> create_conflicting_records() -> Records = [ - #?ACL_TABLE{filter = {{clientid,<<"client6">>}, <<"t">>}, action = pubsub, access = deny, created_at = 0}, - #?ACL_TABLE{filter = {{clientid,<<"client5">>}, <<"t">>}, action = pubsub, access = deny, created_at = 1}, + #?ACL_TABLE{ filter = {{clientid,<<"client6">>}, <<"t">>} + , action = pubsub, access = deny, created_at = 0 + }, + #?ACL_TABLE{ filter = {{clientid,<<"client5">>}, <<"t">>} + , action = pubsub, access = deny, created_at = 1 + }, #?ACL_TABLE2{who = {clientid,<<"client5">>}, rules = [{allow, sub, <<"t">>, 2}]} ], mnesia:transaction(fun() -> lists:foreach(fun mnesia:write/1, Records) end). diff --git a/apps/emqx_management/test/emqx_mgmt_SUITE.erl b/apps/emqx_management/test/emqx_mgmt_SUITE.erl index f21a0f66c..d2fc8cb49 100644 --- a/apps/emqx_management/test/emqx_mgmt_SUITE.erl +++ b/apps/emqx_management/test/emqx_mgmt_SUITE.erl @@ -163,9 +163,9 @@ t_clients_cmd(_) -> timer:sleep(300), emqx_mgmt_cli:clients(["list"]), ?assertMatch({match, _}, re:run(emqx_mgmt_cli:clients(["show", "client12"]), "client12")), - ?assertEqual("ok~n", emqx_mgmt_cli:clients(["kick", "client12"])), + ?assertEqual("ok\n", emqx_mgmt_cli:clients(["kick", "client12"])), timer:sleep(500), - ?assertEqual("ok~n", emqx_mgmt_cli:clients(["kick", "client12"])), + ?assertEqual("ok\n", emqx_mgmt_cli:clients(["kick", "client12"])), receive {'EXIT', T, _} -> ok @@ -291,8 +291,9 @@ t_subscriptions_cmd(_) -> timer:sleep(300), [?assertMatch({match, _} , re:run(Result, "b/b/c")) || Result <- emqx_mgmt_cli:subscriptions(["show", <<"client">>])], - ?assertEqual(emqx_mgmt_cli:subscriptions(["add", "client", "b/b/c", "0"]), "ok~n"), - ?assertEqual(emqx_mgmt_cli:subscriptions(["del", "client", "b/b/c"]), "ok~n"). + ?assertEqual(emqx_mgmt_cli:subscriptions(["add", "client", "b/b/c", "0"]), "ok\n"), + ?assertEqual(emqx_mgmt_cli:subscriptions(["del", "client", "b/b/c"]), "ok\n"), + unmock_print(). t_listeners_cmd_old(_) -> ok = emqx_listeners:ensure_all_started(), @@ -319,9 +320,10 @@ t_listeners_cmd_new(_) -> ), ?assertEqual( emqx_mgmt_cli:listeners(["restart", "bad:listener:identifier"]), - "Failed to restart bad:listener:identifier listener: " - "{no_such_listener,\"bad:listener:identifier\"}\n" - ). + "Failed to restart bad:listener:identifier listener:" + " {no_such_listener,\"bad:listener:identifier\"}\n" + ), + unmock_print(). t_plugins_cmd(_) -> ?assertEqual(emqx_mgmt_cli:plugins(["list"]), ok), @@ -335,8 +337,9 @@ t_plugins_cmd(_) -> ), ?assertEqual( emqx_mgmt_cli:plugins(["unload", "emqx_management"]), - "Plugin emqx_management can not be unloaded.~n" - ). + "Plugin emqx_management can not be unloaded.\n" + ), + unmock_print(). t_cli(_) -> ?assertMatch({match, _}, re:run(emqx_mgmt_cli:status([""]), "status")), @@ -368,7 +371,7 @@ t_cli(_) -> mock_print() -> catch meck:unload(emqx_ctl), meck:new(emqx_ctl, [non_strict, passthrough]), - meck:expect(emqx_ctl, print, fun(Arg) -> emqx_ctl:format(Arg) end), + meck:expect(emqx_ctl, print, fun(Arg) -> emqx_ctl:format(Arg, []) end), meck:expect(emqx_ctl, print, fun(Msg, Arg) -> emqx_ctl:format(Msg, Arg) end), meck:expect(emqx_ctl, usage, fun(Usages) -> emqx_ctl:format_usage(Usages) end), meck:expect(emqx_ctl, usage, fun(Cmd, Descr) -> emqx_ctl:format_usage(Cmd, Descr) end). diff --git a/apps/emqx_recon/test/emqx_recon_SUITE.erl b/apps/emqx_recon/test/emqx_recon_SUITE.erl index 2abf8f709..22c83eca8 100644 --- a/apps/emqx_recon/test/emqx_recon_SUITE.erl +++ b/apps/emqx_recon/test/emqx_recon_SUITE.erl @@ -105,10 +105,9 @@ cli_usage(_) -> mock_print() -> catch meck:unload(emqx_ctl), meck:new(emqx_ctl, [non_strict, passthrough]), - meck:expect(emqx_ctl, print, fun(Arg) -> emqx_ctl:format(Arg) end), + meck:expect(emqx_ctl, print, fun(Arg) -> emqx_ctl:format(Arg, []) end), meck:expect(emqx_ctl, print, fun(Msg, Arg) -> emqx_ctl:format(Msg, Arg) end), meck:expect(emqx_ctl, usage, fun(Usages) -> emqx_ctl:format_usage(Usages) end). unmock_print() -> meck:unload(). - diff --git a/apps/emqx_rule_engine/test/emqx_rule_engine_SUITE.erl b/apps/emqx_rule_engine/test/emqx_rule_engine_SUITE.erl index f430c3d4e..02e0f607c 100644 --- a/apps/emqx_rule_engine/test/emqx_rule_engine_SUITE.erl +++ b/apps/emqx_rule_engine/test/emqx_rule_engine_SUITE.erl @@ -187,7 +187,8 @@ end_per_group(_Groupname, _Config) -> init_per_testcase(t_events, Config) -> ok = emqx_rule_engine:load_providers(), init_events_counters(), - ok = emqx_rule_registry:register_resource_types([make_simple_resource_type(simple_resource_type)]), + ok = emqx_rule_registry:register_resource_types( + [make_simple_resource_type(simple_resource_type)]), ok = emqx_rule_registry:add_action( #action{name = 'hook-metrics-action', app = ?APP, module = ?MODULE, on_create = hook_metrics_action, @@ -206,7 +207,10 @@ init_per_testcase(t_events, Config) -> #{id => <<"rule:t_events">>, rawsql => SQL, actions => [#{id => <<"action:inspect">>, name => 'inspect', args => #{}}, - #{id => <<"action:hook-metrics-action">>, name => 'hook-metrics-action', args => #{}}], + #{ id => <<"action:hook-metrics-action">> + , name => 'hook-metrics-action' + , args => #{} + }], description => <<"Debug rule">>}), ?assertMatch(#rule{id = <<"rule:t_events">>}, Rule), [{hook_points_rules, Rule} | Config]; @@ -439,7 +443,8 @@ t_list_actions_api(_Config) -> ok. t_show_action_api(_Config) -> - {ok, #{code := 0, data := Actions}} = emqx_rule_engine_api:show_action(#{name => 'inspect'}, []), + {ok, #{code := 0, data := Actions}} = + emqx_rule_engine_api:show_action(#{name => 'inspect'}, []), ?assertEqual('inspect', maps:get(name, Actions)), ok. @@ -503,7 +508,8 @@ t_list_resource_types_api(_Config) -> ok. t_show_resource_type_api(_Config) -> - {ok, #{code := 0, data := RShow}} = emqx_rule_engine_api:show_resource_type(#{name => 'built_in'}, []), + {ok, #{code := 0, data := RShow}} = + emqx_rule_engine_api:show_resource_type(#{name => 'built_in'}, []), %ct:pal("RShow : ~p", [RShow]), ?assertEqual(built_in, maps:get(name, RShow)), ok. @@ -521,7 +527,15 @@ t_rules_cli(_Config) -> %ct:pal("Result : ~p", [RCreate]), ?assertMatch({match, _}, re:run(RCreate, "created")), - RuleId = re:replace(re:replace(RCreate, "Rule\s", "", [{return, list}]), "\screated\n", "", [{return, list}]), + RuleId = re:replace( + re:replace( RCreate + , "Rule\s" + , "" + , [{return, list}] + ), + "\screated\n", + "", + [{return, list}]), RList = emqx_rule_engine_cli:rules(["list"]), ?assertMatch({match, _}, re:run(RList, RuleId)), @@ -538,7 +552,7 @@ t_rules_cli(_Config) -> ?assertMatch({match, _}, re:run(RUpdate, "updated")), RDelete = emqx_rule_engine_cli:rules(["delete", RuleId]), - ?assertEqual("ok~n", RDelete), + ?assertEqual("ok\n", RDelete), %ct:pal("RDelete : ~p", [RDelete]), %ct:pal("table action params after deleted: ~p", [ets:tab2list(emqx_action_instance_params)]), @@ -562,8 +576,17 @@ t_actions_cli(_Config) -> t_resources_cli(_Config) -> mock_print(), - RCreate = emqx_rule_engine_cli:resources(["create", "built_in", "{\"a\" : 1}", "-d", "test resource"]), - ResId = re:replace(re:replace(RCreate, "Resource\s", "", [{return, list}]), "\screated\n", "", [{return, list}]), + RCreate = emqx_rule_engine_cli:resources( + ["create", "built_in", "{\"a\" : 1}", "-d", "test resource"]), + ResId = re:replace( + re:replace( RCreate + , "Resource\s" + , "" + , [{return, list}] + ), + "\screated\n", + "", + [{return, list}]), RList = emqx_rule_engine_cli:resources(["list"]), ?assertMatch({match, _}, re:run(RList, "test resource")), @@ -578,7 +601,7 @@ t_resources_cli(_Config) -> %ct:pal("RShow : ~p", [RShow]), RDelete = emqx_rule_engine_cli:resources(["delete", ResId]), - ?assertEqual("ok~n", RDelete), + ?assertEqual("ok\n", RDelete), RShow2 = emqx_rule_engine_cli:resources(["show", ResId]), ?assertMatch({match, _}, re:run(RShow2, "Cannot found")), @@ -765,48 +788,121 @@ t_get_rules_ordered_by_ts(_Config) -> t_get_rules_for_2(_Config) -> Len0 = length(emqx_rule_registry:get_rules_for(<<"simple/1">>)), ok = emqx_rule_registry:add_rules( - [make_simple_rule(<<"rule-debug-1">>, <<"select * from \"simple/#\"">>, [<<"simple/#">>]), - make_simple_rule(<<"rule-debug-2">>, <<"select * from \"simple/+\"">>, [<<"simple/+">>]), - make_simple_rule(<<"rule-debug-3">>, <<"select * from \"simple/+/1\"">>, [<<"simple/+/1">>]), - make_simple_rule(<<"rule-debug-4">>, <<"select * from \"simple/1\"">>, [<<"simple/1">>]), - make_simple_rule(<<"rule-debug-5">>, <<"select * from \"simple/2,simple/+,simple/3\"">>, [<<"simple/2">>,<<"simple/+">>, <<"simple/3">>]), - make_simple_rule(<<"rule-debug-6">>, <<"select * from \"simple/2,simple/3,simple/4\"">>, [<<"simple/2">>,<<"simple/3">>, <<"simple/4">>]) + [make_simple_rule( + <<"rule-debug-1">>, + <<"select * from \"simple/#\"">>, + [<<"simple/#">>]), + make_simple_rule( + <<"rule-debug-2">>, + <<"select * from \"simple/+\"">>, + [<<"simple/+">>]), + make_simple_rule( + <<"rule-debug-3">>, + <<"select * from \"simple/+/1\"">>, + [<<"simple/+/1">>]), + make_simple_rule( + <<"rule-debug-4">>, + <<"select * from \"simple/1\"">>, + [<<"simple/1">>]), + make_simple_rule( + <<"rule-debug-5">>, + <<"select * from \"simple/2,simple/+,simple/3\"">>, + [<<"simple/2">>,<<"simple/+">>, <<"simple/3">>]), + make_simple_rule( + <<"rule-debug-6">>, + <<"select * from \"simple/2,simple/3,simple/4\"">>, + [<<"simple/2">>,<<"simple/3">>, <<"simple/4">>]) ]), ?assertEqual(Len0+4, length(emqx_rule_registry:get_rules_for(<<"simple/1">>))), - ok = emqx_rule_registry:remove_rules([<<"rule-debug-1">>, <<"rule-debug-2">>,<<"rule-debug-3">>, <<"rule-debug-4">>,<<"rule-debug-5">>, <<"rule-debug-6">>]), + ok = emqx_rule_registry:remove_rules( + [ <<"rule-debug-1">> + , <<"rule-debug-2">> + , <<"rule-debug-3">> + , <<"rule-debug-4">> + , <<"rule-debug-5">> + , <<"rule-debug-6">> + ]), ok. t_get_rules_with_same_event(_Config) -> PubT = <<"simple/1">>, PubN = length(emqx_rule_registry:get_rules_with_same_event(PubT)), ?assertEqual([], emqx_rule_registry:get_rules_with_same_event(<<"$events/client_connected">>)), - ?assertEqual([], emqx_rule_registry:get_rules_with_same_event(<<"$events/client_disconnected">>)), - ?assertEqual([], emqx_rule_registry:get_rules_with_same_event(<<"$events/session_subscribed">>)), - ?assertEqual([], emqx_rule_registry:get_rules_with_same_event(<<"$events/session_unsubscribed">>)), + ?assertEqual( + [], + emqx_rule_registry:get_rules_with_same_event(<<"$events/client_disconnected">>)), + ?assertEqual( + [], + emqx_rule_registry:get_rules_with_same_event(<<"$events/session_subscribed">>)), + ?assertEqual( + [], + emqx_rule_registry:get_rules_with_same_event(<<"$events/session_unsubscribed">>)), ?assertEqual([], emqx_rule_registry:get_rules_with_same_event(<<"$events/message_delivered">>)), ?assertEqual([], emqx_rule_registry:get_rules_with_same_event(<<"$events/message_acked">>)), ?assertEqual([], emqx_rule_registry:get_rules_with_same_event(<<"$events/message_dropped">>)), ok = emqx_rule_registry:add_rules( [make_simple_rule(<<"r1">>, <<"select * from \"simple/#\"">>, [<<"simple/#">>]), make_simple_rule(<<"r2">>, <<"select * from \"abc/+\"">>, [<<"abc/+">>]), - make_simple_rule(<<"r3">>, <<"select * from \"$events/client_connected\"">>, [<<"$events/client_connected">>]), - make_simple_rule(<<"r4">>, <<"select * from \"$events/client_disconnected\"">>, [<<"$events/client_disconnected">>]), - make_simple_rule(<<"r5">>, <<"select * from \"$events/session_subscribed\"">>, [<<"$events/session_subscribed">>]), - make_simple_rule(<<"r6">>, <<"select * from \"$events/session_unsubscribed\"">>, [<<"$events/session_unsubscribed">>]), - make_simple_rule(<<"r7">>, <<"select * from \"$events/message_delivered\"">>, [<<"$events/message_delivered">>]), - make_simple_rule(<<"r8">>, <<"select * from \"$events/message_acked\"">>, [<<"$events/message_acked">>]), - make_simple_rule(<<"r9">>, <<"select * from \"$events/message_dropped\"">>, [<<"$events/message_dropped">>]), - make_simple_rule(<<"r10">>, <<"select * from \"t/1, $events/session_subscribed, $events/client_connected\"">>, [<<"t/1">>, <<"$events/session_subscribed">>, <<"$events/client_connected">>]) + make_simple_rule( + <<"r3">>, + <<"select * from \"$events/client_connected\"">>, + [<<"$events/client_connected">>]), + make_simple_rule( + <<"r4">>, + <<"select * from \"$events/client_disconnected\"">>, + [<<"$events/client_disconnected">>]), + make_simple_rule( + <<"r5">>, + <<"select * from \"$events/session_subscribed\"">>, + [<<"$events/session_subscribed">>]), + make_simple_rule( + <<"r6">>, + <<"select * from \"$events/session_unsubscribed\"">>, + [<<"$events/session_unsubscribed">>]), + make_simple_rule( + <<"r7">>, + <<"select * from \"$events/message_delivered\"">>, + [<<"$events/message_delivered">>]), + make_simple_rule( + <<"r8">>, + <<"select * from \"$events/message_acked\"">>, + [<<"$events/message_acked">>]), + make_simple_rule( + <<"r9">>, + <<"select * from \"$events/message_dropped\"">>, + [<<"$events/message_dropped">>]), + make_simple_rule( + <<"r10">>, + <<"select * from \"t/1, $events/session_subscribed," + " $events/client_connected\"">>, + [<<"t/1">>, <<"$events/session_subscribed">>, <<"$events/client_connected">>]) ]), ?assertEqual(PubN + 3, length(emqx_rule_registry:get_rules_with_same_event(PubT))), - ?assertEqual(2, length(emqx_rule_registry:get_rules_with_same_event(<<"$events/client_connected">>))), - ?assertEqual(1, length(emqx_rule_registry:get_rules_with_same_event(<<"$events/client_disconnected">>))), - ?assertEqual(2, length(emqx_rule_registry:get_rules_with_same_event(<<"$events/session_subscribed">>))), - ?assertEqual(1, length(emqx_rule_registry:get_rules_with_same_event(<<"$events/session_unsubscribed">>))), - ?assertEqual(1, length(emqx_rule_registry:get_rules_with_same_event(<<"$events/message_delivered">>))), - ?assertEqual(1, length(emqx_rule_registry:get_rules_with_same_event(<<"$events/message_acked">>))), - ?assertEqual(1, length(emqx_rule_registry:get_rules_with_same_event(<<"$events/message_dropped">>))), - ok = emqx_rule_registry:remove_rules([<<"r1">>, <<"r2">>,<<"r3">>, <<"r4">>,<<"r5">>, <<"r6">>, <<"r7">>, <<"r8">>, <<"r9">>, <<"r10">>]), + ?assertEqual( + 2, + length(emqx_rule_registry:get_rules_with_same_event(<<"$events/client_connected">>))), + ?assertEqual( + 1, + length(emqx_rule_registry:get_rules_with_same_event(<<"$events/client_disconnected">>))), + ?assertEqual( + 2, + length(emqx_rule_registry:get_rules_with_same_event(<<"$events/session_subscribed">>))), + ?assertEqual( + 1, + length(emqx_rule_registry:get_rules_with_same_event(<<"$events/session_unsubscribed">>))), + ?assertEqual( + 1, + length(emqx_rule_registry:get_rules_with_same_event(<<"$events/message_delivered">>))), + ?assertEqual( + 1, + length(emqx_rule_registry:get_rules_with_same_event(<<"$events/message_acked">>))), + ?assertEqual( + 1, + length(emqx_rule_registry:get_rules_with_same_event(<<"$events/message_dropped">>))), + ok = emqx_rule_registry:remove_rules( + [<<"r1">>, <<"r2">>,<<"r3">>, + <<"r4">>,<<"r5">>, <<"r6">>, + <<"r7">>, <<"r8">>, <<"r9">>, <<"r10">>]), ok. t_add_get_remove_action(_Config) -> @@ -882,7 +978,11 @@ register_resource_types() -> emqx_rule_registry:register_resource_types([ResType1,ResType2]), ok. get_resource_type() -> - ?assertMatch({ok, #resource_type{name = <<"resource-type-debug-1">>}}, emqx_rule_registry:find_resource_type(<<"resource-type-debug-1">>)), + ?assertMatch( { ok + , #resource_type{name = <<"resource-type-debug-1">>} + } + , emqx_rule_registry:find_resource_type(<<"resource-type-debug-1">>) + ), ok. get_resource_types() -> ResTypes = emqx_rule_registry:get_resource_types(), @@ -947,11 +1047,18 @@ client_disconnected(Client, Client2) -> verify_event('client.disconnected'), ok. session_subscribed(Client2) -> - {ok, _, _} = emqtt:subscribe(Client2, #{'User-Property' => {<<"topic_name">>, <<"t1">>}}, <<"t1">>, 1), + {ok, _, _} = emqtt:subscribe( Client2 + , #{'User-Property' => {<<"topic_name">>, <<"t1">>}} + , <<"t1">> + , 1 + ), verify_event('session.subscribed'), ok. session_unsubscribed(Client2) -> - {ok, _, _} = emqtt:unsubscribe(Client2, #{'User-Property' => {<<"topic_name">>, <<"t1">>}}, <<"t1">>), + {ok, _, _} = emqtt:unsubscribe( Client2 + , #{'User-Property' => {<<"topic_name">>, <<"t1">>}} + , <<"t1">> + ), verify_event('session.unsubscribed'), ok. @@ -977,7 +1084,10 @@ t_mfa_action(_Config) -> {ok, #rule{id = Id}} = emqx_rule_engine:create_rule( #{id => <<"rule:t_mfa_action">>, rawsql => SQL, - actions => [#{id => <<"action:mfa-test">>, name => 'mfa-action', args => #{}}], + actions => [#{ id => <<"action:mfa-test">> + , name => 'mfa-action' + , args => #{} + }], description => <<"Debug rule">>}), {ok, Client} = emqtt:start_link([{username, <<"emqx">>}]), {ok, _} = emqtt:connect(Client), @@ -1387,7 +1497,7 @@ t_metrics1(_Config) -> ?assertEqual(0, emqx_rule_metrics:get_rules_passed(RuleId)), ?assertEqual(0, emqx_rule_metrics:get_rules_failed(RuleId)), ?assertEqual(0, emqx_rule_metrics:get_rules_exception(RuleId)), - ?assertEqual(0, emqx_rule_metrics:get_rules_no_result(RuleId)), + ?assertEqual(0, emqx_rule_metrics:get_rules_no_result(RuleId)), {ok, Client} = emqtt:start_link([{username, <<"emqx">>}]), {ok, _} = emqtt:connect(Client), ct:sleep(200), @@ -1676,12 +1786,18 @@ t_sqlparse_foreach_1(_Config) -> Sql3 = "foreach payload.sensors " "from \"t/#\" ", ?assertMatch({ok,[#{item := #{<<"cmd">> := <<"1">>}, clientid := <<"c_a">>}, - #{item := #{<<"cmd">> := <<"2">>, <<"name">> := <<"ct">>}, clientid := <<"c_a">>}]}, + #{item := #{ <<"cmd">> := <<"2">> + , <<"name">> := <<"ct">> + } + , clientid := <<"c_a">>}]}, emqx_rule_sqltester:test( #{<<"rawsql">> => Sql3, - <<"ctx">> => #{ - <<"payload">> => <<"{\"sensors\": [{\"cmd\":\"1\"}, {\"cmd\":\"2\",\"name\":\"ct\"}]}">>, <<"clientid">> => <<"c_a">>, - <<"topic">> => <<"t/a">>}})), + <<"ctx">> => + #{ <<"payload">> => <<"{\"sensors\": [{\"cmd\":\"1\"}, " + "{\"cmd\":\"2\",\"name\":\"ct\"}]}">> + , <<"clientid">> => <<"c_a">> + , <<"topic">> => <<"t/a">> + }})), Sql4 = "foreach payload.sensors " "from \"t/#\" ", {ok,[#{metadata := #{rule_id := TRuleId}}, @@ -1766,12 +1882,17 @@ t_sqlparse_foreach_4(_Config) -> #{<<"payload">> => <<"{\"sensors\": [{\"cmd\":\"1\"}, {\"cmd\":\"2\"}]}">>, <<"topic">> => <<"t/a">>}})), - ?assertMatch({ok,[#{<<"msg_type">> := <<"1">>, <<"name">> := <<"n1">>}, #{<<"msg_type">> := <<"2">>}]}, + ?assertMatch({ ok + , [ #{<<"msg_type">> := <<"1">>, <<"name">> := <<"n1">>} + , #{<<"msg_type">> := <<"2">>} + ] + }, emqx_rule_sqltester:test( #{<<"rawsql">> => Sql, <<"ctx">> => #{<<"payload">> => - <<"{\"sensors\": [{\"cmd\":\"1\", \"name\":\"n1\"}, {\"cmd\":\"2\"}, {\"name\":\"n3\"}]}">>, + <<"{\"sensors\": [{\"cmd\":\"1\", \"name\":\"n1\"}, " + "{\"cmd\":\"2\"}, {\"name\":\"n3\"}]}">>, <<"topic">> => <<"t/a">>}})), ?assertMatch({ok,[]}, emqx_rule_sqltester:test( @@ -1828,8 +1949,13 @@ t_sqlparse_foreach_7(_Config) -> "incase is_not_null(info.cmd) " "from \"t/#\" " "where s.page = '2' ", - Payload = <<"{\"sensors\": {\"page\": 2, \"collection\": {\"info\":[{\"name\":\"cmd1\", \"cmd\":\"1\"}, {\"cmd\":\"2\"}]} } }">>, - ?assertMatch({ok,[#{<<"name">> := <<"cmd1">>, <<"msg_type">> := <<"1">>}, #{<<"msg_type">> := <<"2">>}]}, + Payload = <<"{\"sensors\": {\"page\": 2, \"collection\": " + "{\"info\":[{\"name\":\"cmd1\", \"cmd\":\"1\"}, {\"cmd\":\"2\"}]} } }">>, + ?assertMatch({ ok + , [ #{<<"name">> := <<"cmd1">>, <<"msg_type">> := <<"1">>} + , #{<<"msg_type">> := <<"2">>} + ] + }, emqx_rule_sqltester:test( #{<<"rawsql">> => Sql, <<"ctx">> => @@ -1854,7 +1980,8 @@ t_sqlparse_foreach_8(_Config) -> "incase is_map(info) " "from \"t/#\" " "where s.page = '2' ", - Payload = <<"{\"sensors\": {\"page\": 2, \"collection\": {\"info\":[\"haha\", {\"name\":\"cmd1\", \"cmd\":\"1\"}]} } }">>, + Payload = <<"{\"sensors\": {\"page\": 2, \"collection\": " + "{\"info\":[\"haha\", {\"name\":\"cmd1\", \"cmd\":\"1\"}]} } }">>, ?assertMatch({ok,[#{<<"name">> := <<"cmd1">>, <<"msg_type">> := <<"1">>}]}, emqx_rule_sqltester:test( #{<<"rawsql">> => Sql, @@ -1862,10 +1989,11 @@ t_sqlparse_foreach_8(_Config) -> #{<<"payload">> => Payload, <<"topic">> => <<"t/a">>}})), - Sql3 = "foreach json_decode(payload) as p, p.sensors as s, s.collection as c, sublist(2,1,c.info) as info " - "do info.cmd as msg_type, info.name as name " - "from \"t/#\" " - "where s.page = '2' ", + Sql3 = "foreach json_decode(payload) as p, p.sensors as s," + " s.collection as c, sublist(2,1,c.info) as info " + "do info.cmd as msg_type, info.name as name " + "from \"t/#\" " + "where s.page = '2' ", [?assertMatch({ok,[#{<<"name">> := <<"cmd1">>, <<"msg_type">> := <<"1">>}]}, emqx_rule_sqltester:test( #{<<"rawsql">> => SqlN, @@ -1992,10 +2120,12 @@ t_sqlparse_array_index_1(_Config) -> Sql3 = "select " " payload.x[2].y " "from \"t/#\" ", - ?assertMatch({ok, #{<<"payload">> := #{<<"x">> := [#{<<"y">> := 3}]}}}, emqx_rule_sqltester:test( + ?assertMatch( {ok, #{<<"payload">> := #{<<"x">> := [#{<<"y">> := 3}]}}} + , emqx_rule_sqltester:test( #{<<"rawsql">> => Sql3, <<"ctx">> => #{<<"payload">> => #{<<"x">> => [1,#{y => 3},4]}, - <<"topic">> => <<"t/a">>}})), + <<"topic">> => <<"t/a">>}}) + ), %% index get with 'as' Sql4 = "select " @@ -2228,10 +2358,12 @@ t_sqlparse_new_map(_Config) -> t_sqlparse_payload_as(_Config) -> %% https://github.com/emqx/emqx/issues/3866 Sql00 = "SELECT " - " payload, map_get('engineWorkTime', payload.params, -1) as payload.params.engineWorkTime, " + " payload, map_get('engineWorkTime', payload.params, -1) " + "as payload.params.engineWorkTime, " " map_get('hydOilTem', payload.params, -1) as payload.params.hydOilTem " "FROM \"t/#\" ", - Payload1 = <<"{ \"msgId\": 1002, \"params\": { \"convertTemp\": 20, \"engineSpeed\": 42, \"hydOilTem\": 30 } }">>, + Payload1 = <<"{ \"msgId\": 1002, \"params\": " + "{ \"convertTemp\": 20, \"engineSpeed\": 42, \"hydOilTem\": 30 } }">>, {ok, Res01} = emqx_rule_sqltester:test( #{<<"rawsql">> => Sql00, <<"ctx">> => #{<<"payload">> => Payload1, @@ -2711,7 +2843,7 @@ set_special_configs(_App) -> mock_print() -> catch meck:unload(emqx_ctl), meck:new(emqx_ctl, [non_strict, passthrough]), - meck:expect(emqx_ctl, print, fun(Arg) -> emqx_ctl:format(Arg) end), + meck:expect(emqx_ctl, print, fun(Arg) -> emqx_ctl:format(Arg, []) end), meck:expect(emqx_ctl, print, fun(Msg, Arg) -> emqx_ctl:format(Msg, Arg) end), meck:expect(emqx_ctl, usage, fun(Usages) -> emqx_ctl:format_usage(Usages) end), meck:expect(emqx_ctl, usage, fun(Cmd, Descr) -> emqx_ctl:format_usage(Cmd, Descr) end). @@ -2763,4 +2895,3 @@ t_clear_resource(_) -> t_clear_action(_) -> error('TODO'). - diff --git a/lib-ce/emqx_modules/test/emqx_modules_SUITE.erl b/lib-ce/emqx_modules/test/emqx_modules_SUITE.erl index dc76e8eb7..175b24bba 100644 --- a/lib-ce/emqx_modules/test/emqx_modules_SUITE.erl +++ b/lib-ce/emqx_modules/test/emqx_modules_SUITE.erl @@ -143,7 +143,7 @@ t_join_cluster(_) -> mock_print() -> catch meck:unload(emqx_ctl), meck:new(emqx_ctl, [non_strict, passthrough]), - meck:expect(emqx_ctl, print, fun(Arg) -> emqx_ctl:format(Arg) end), + meck:expect(emqx_ctl, print, fun(Arg) -> emqx_ctl:format(Arg, []) end), meck:expect(emqx_ctl, print, fun(Msg, Arg) -> emqx_ctl:format(Msg, Arg) end), meck:expect(emqx_ctl, usage, fun(Usages) -> emqx_ctl:format_usage(Usages) end), meck:expect(emqx_ctl, usage, fun(Cmd, Descr) -> emqx_ctl:format_usage(Cmd, Descr) end). diff --git a/src/emqx.appup.src b/src/emqx.appup.src index 80ae46894..bbd216755 100644 --- a/src/emqx.appup.src +++ b/src/emqx.appup.src @@ -1,7 +1,9 @@ %% -*- mode: erlang -*- {VSN, [{"4.4.0", - [ {load_module,emqx_channel,brutal_purge,soft_purge,[]} + [ {load_module,emqx_vm_mon,brutal_purge,soft_purge,[]} + , {load_module,emqx_ctl,brutal_purge,soft_purge,[]} + , {load_module,emqx_channel,brutal_purge,soft_purge,[]} , {load_module,emqx_connection,brutal_purge,soft_purge,[]} , {load_module,emqx_ws_connection,brutal_purge,soft_purge,[]} , {load_module,emqx_metrics,brutal_purge,soft_purge,[]} @@ -18,7 +20,9 @@ {<<".*">>,[]} ], [{"4.4.0", - [ {load_module,emqx_channel,brutal_purge,soft_purge,[]} + [ {load_module,emqx_vm_mon,brutal_purge,soft_purge,[]} + , {load_module,emqx_ctl,brutal_purge,soft_purge,[]} + , {load_module,emqx_channel,brutal_purge,soft_purge,[]} , {load_module,emqx_connection,brutal_purge,soft_purge,[]} , {load_module,emqx_ws_connection,brutal_purge,soft_purge,[]} , {load_module,emqx_access_control,brutal_purge,soft_purge,[]} diff --git a/src/emqx_ctl.erl b/src/emqx_ctl.erl index 79616e631..7b73c50fe 100644 --- a/src/emqx_ctl.erl +++ b/src/emqx_ctl.erl @@ -43,8 +43,7 @@ ]). %% Exports mainly for test cases --export([ format/1 - , format/2 +-export([ format/2 , format_usage/1 , format_usage/2 ]). @@ -58,6 +57,8 @@ , code_change/3 ]). +-elvis([{elvis_style, invalid_dynamic_call, #{ignore => [emqx_ctl]}}]). + -record(state, {seq = 0}). -type(cmd() :: atom()). @@ -137,7 +138,7 @@ help() -> -spec(print(io:format()) -> ok). print(Msg) -> - io:format("~s", [format(Msg)]). + io:format("~s", [format(Msg, [])]). -spec(print(io:format(), [term()]) -> ok). print(Format, Args) -> @@ -151,10 +152,6 @@ usage(UsageList) -> usage(CmdParams, Desc) -> io:format(format_usage(CmdParams, Desc)). --spec(format(io:format()) -> string()). -format(Msg) -> - lists:flatten(io_lib:format("~s", [Msg])). - -spec(format(io:format(), [term()]) -> string()). format(Format, Args) -> lists:flatten(io_lib:format(Format, Args)). diff --git a/test/emqx_ctl_SUITE.erl b/test/emqx_ctl_SUITE.erl index 8466cf7b0..4832bacff 100644 --- a/test/emqx_ctl_SUITE.erl +++ b/test/emqx_ctl_SUITE.erl @@ -70,7 +70,7 @@ t_print(_) -> ok = emqx_ctl:print("~s", [<<"~!@#$%^&*()">>]), % - check the output of the usage mock_print(), - ?assertEqual("help~n", emqx_ctl:print("help~n")), + ?assertEqual("help\n", emqx_ctl:print("help~n")), ?assertEqual("help", emqx_ctl:print("~s", [help])), ?assertEqual("~!@#$%^&*()", emqx_ctl:print("~s", [<<"~!@#$%^&*()">>])), unmock_print(). @@ -110,7 +110,7 @@ mock_print() -> %% proxy usage/1,2 and print/1,2 to format_xx/1,2 funcs catch meck:unload(emqx_ctl), meck:new(emqx_ctl, [non_strict, passthrough]), - meck:expect(emqx_ctl, print, fun(Arg) -> emqx_ctl:format(Arg) end), + meck:expect(emqx_ctl, print, fun(Arg) -> emqx_ctl:format(Arg, []) end), meck:expect(emqx_ctl, print, fun(Msg, Arg) -> emqx_ctl:format(Msg, Arg) end), meck:expect(emqx_ctl, usage, fun(Usages) -> emqx_ctl:format_usage(Usages) end), meck:expect(emqx_ctl, usage, fun(CmdParams, CmdDescr) ->