Pārlūkot izejas kodu

Fix ping not return pong (#6285)

* fix: ./bin/emqx ping return pong

* chore: waiting longer for logger flush log to disk

* fix: change swagger page's limit from 100 to 1000

* chore: type wrong

* fix: sync log to disk by logger_disk_log_h:filesync
zhongwencool 4 gadi atpakaļ
vecāks
revīzija
f697028b70

+ 6 - 5
apps/emqx/test/emqx_trace_SUITE.erl

@@ -22,7 +22,7 @@
 -include_lib("common_test/include/ct.hrl").
 -include_lib("eunit/include/eunit.hrl").
 -include_lib("emqx/include/emqx.hrl").
-
+-import(emqx_trace_handler_SUITE, [filesync/2]).
 -record(emqx_trace, {name, type, filter, enable = true, start_at, end_at}).
 
 %%--------------------------------------------------------------------
@@ -237,15 +237,16 @@ t_client_event(_Config) ->
     emqtt:ping(Client),
     ok = emqtt:publish(Client, <<"/test">>, #{}, <<"1">>, [{qos, 0}]),
     ok = emqtt:publish(Client, <<"/test">>, #{}, <<"2">>, [{qos, 0}]),
-    ct:sleep(200),
     ok = emqx_trace:create([{<<"name">>, <<"test_topic">>},
         {<<"type">>, <<"topic">>}, {<<"topic">>, <<"/test">>}, {<<"start_at">>, Start}]),
-    ct:sleep(200),
+    ok = filesync(Name, clientid),
+    ok = filesync(<<"test_topic">>, topic),
     {ok, Bin} = file:read_file(emqx_trace:log_file(Name, Now)),
     ok = emqtt:publish(Client, <<"/test">>, #{}, <<"3">>, [{qos, 0}]),
     ok = emqtt:publish(Client, <<"/test">>, #{}, <<"4">>, [{qos, 0}]),
     ok = emqtt:disconnect(Client),
-    ct:sleep(200),
+    ok = filesync(Name, clientid),
+    ok = filesync(<<"test_topic">>, topic),
     {ok, Bin2} = file:read_file(emqx_trace:log_file(Name, Now)),
     {ok, Bin3} = file:read_file(emqx_trace:log_file(<<"test_topic">>, Now)),
     ct:pal("Bin ~p Bin2 ~p Bin3 ~p", [byte_size(Bin), byte_size(Bin2), byte_size(Bin3)]),
@@ -301,7 +302,7 @@ t_download_log(_Config) ->
     {ok, Client} = emqtt:start_link([{clean_start, true}, {clientid, ClientId}]),
     {ok, _} = emqtt:connect(Client),
     [begin _ = emqtt:ping(Client) end ||_ <- lists:seq(1, 5)],
-    ct:sleep(100),
+    ok = filesync(Name, clientid),
     {ok, ZipFile} = emqx_trace_api:download_zip_log(#{name => Name}, []),
     ?assert(filelib:file_size(ZipFile) > 0),
     ok = emqtt:disconnect(Client),

+ 31 - 7
apps/emqx/test/emqx_trace_handler_SUITE.erl

@@ -62,7 +62,9 @@ t_trace_clientid(_Config) ->
         emqx_trace_handler:install(clientid, <<"client4">>, bad_level, "tmp/client4.log"),
     {error, {handler_not_added, {file_error, ".", eisdir}}} =
         emqx_trace_handler:install(clientid, <<"client5">>, debug, "."),
-    ct:sleep(100),
+    ok = filesync(<<"client">>, clientid),
+    ok = filesync(<<"client2">>, clientid),
+    ok = filesync(<<"client3">>, clientid),
 
     %% Verify the tracing file exits
     ?assert(filelib:is_regular("tmp/client.log")),
@@ -83,7 +85,10 @@ t_trace_clientid(_Config) ->
     emqtt:connect(T),
     emqtt:publish(T, <<"a/b/c">>, <<"hi">>),
     emqtt:ping(T),
-    ct:sleep(200),
+
+    ok = filesync(<<"client">>, clientid),
+    ok = filesync(<<"client2">>, clientid),
+    ok = filesync(<<"client3">>, clientid),
 
     %% Verify messages are logged to "tmp/client.log" but not "tmp/client2.log".
     {ok, Bin} = file:read_file("tmp/client.log"),
@@ -109,7 +114,8 @@ t_trace_topic(_Config) ->
     emqx_logger:set_log_level(debug),
     ok = emqx_trace_handler:install(topic, <<"x/#">>, all, "tmp/topic_trace_x.log"),
     ok = emqx_trace_handler:install(topic, <<"y/#">>, all, "tmp/topic_trace_y.log"),
-    ct:sleep(100),
+    ok = filesync(<<"x/#">>, topic),
+    ok = filesync(<<"y/#">>, topic),
 
     %% Verify the tracing file exits
     ?assert(filelib:is_regular("tmp/topic_trace_x.log")),
@@ -128,7 +134,8 @@ t_trace_topic(_Config) ->
     emqtt:publish(T, <<"x/y/z">>, <<"hi2">>),
     emqtt:subscribe(T, <<"x/y/z">>),
     emqtt:unsubscribe(T, <<"x/y/z">>),
-    ct:sleep(200),
+    ok = filesync(<<"x/#">>, topic),
+    ok = filesync(<<"y/#">>, topic),
 
     {ok, Bin} = file:read_file("tmp/topic_trace_x.log"),
     ?assertNotEqual(nomatch, binary:match(Bin, [<<"hi1">>])),
@@ -152,8 +159,8 @@ t_trace_ip_address(_Config) ->
     %% Start tracing
     ok = emqx_trace_handler:install(ip_address, "127.0.0.1", all, "tmp/ip_trace_x.log"),
     ok = emqx_trace_handler:install(ip_address, "192.168.1.1", all, "tmp/ip_trace_y.log"),
-    ct:sleep(100),
-
+    ok = filesync(<<"127.0.0.1">>, ip_address),
+    ok = filesync(<<"192.168.1.1">>, ip_address),
     %% Verify the tracing file exits
     ?assert(filelib:is_regular("tmp/ip_trace_x.log")),
     ?assert(filelib:is_regular("tmp/ip_trace_y.log")),
@@ -173,7 +180,8 @@ t_trace_ip_address(_Config) ->
     emqtt:publish(T, <<"x/y/z">>, <<"hi2">>),
     emqtt:subscribe(T, <<"x/y/z">>),
     emqtt:unsubscribe(T, <<"x/y/z">>),
-    ct:sleep(200),
+    ok = filesync(<<"127.0.0.1">>, ip_address),
+    ok = filesync(<<"192.168.1.1">>, ip_address),
 
     {ok, Bin} = file:read_file("tmp/ip_trace_x.log"),
     ?assertNotEqual(nomatch, binary:match(Bin, [<<"hi1">>])),
@@ -189,3 +197,19 @@ t_trace_ip_address(_Config) ->
     {error, _Reason} = emqx_trace_handler:uninstall(ip_address, <<"127.0.0.2">>),
     emqtt:disconnect(T),
     ?assertEqual([], emqx_trace_handler:running()).
+
+filesync(Name, Type) ->
+    filesync(Name, Type, 3).
+
+%% sometime the handler process is not started yet.
+filesync(_Name, _Type, 0) -> ok;
+filesync(Name, Type, Retry) ->
+    try
+        Handler = binary_to_atom(<<"trace_",
+            (atom_to_binary(Type))/binary, "_", Name/binary>>),
+        ok = logger_disk_log_h:filesync(Handler)
+    catch E:R ->
+        ct:pal("Filesync error:~p ~p~n", [{Name, Type, Retry}, {E, R}]),
+        ct:sleep(100),
+        filesync(Name, Type, Retry - 1)
+    end.

+ 4 - 3
apps/emqx_authn/src/emqx_authn_api.erl

@@ -21,6 +21,7 @@
 -include_lib("typerefl/include/types.hrl").
 -include("emqx_authn.hrl").
 -include_lib("emqx/include/emqx_placeholder.hrl").
+-include_lib("emqx/include/logger.hrl").
 
 -import(hoconsc, [mk/2, ref/1]).
 -import(emqx_dashboard_swagger, [error_codes/2]).
@@ -590,7 +591,7 @@ listener_authenticator(delete,
 authenticator_move(post,
                    #{bindings := #{id := AuthenticatorID},
                      body := #{<<"position">> := Position}}) ->
-    move_authenitcator([authentication], ?GLOBAL, AuthenticatorID, Position);
+    move_authenticator([authentication], ?GLOBAL, AuthenticatorID, Position);
 authenticator_move(post, #{bindings := #{id := _}, body := _}) ->
     serialize_error({missing_parameter, position}).
 
@@ -599,7 +600,7 @@ listener_authenticator_move(post,
                               body := #{<<"position">> := Position}}) ->
     with_listener(ListenerID,
                   fun(Type, Name, ChainName) ->
-                        move_authenitcator([listeners, Type, Name, authentication],
+                        move_authenticator([listeners, Type, Name, authentication],
                                            ChainName,
                                            AuthenticatorID,
                                            Position)
@@ -771,7 +772,7 @@ delete_authenticator(ConfKeyPath, ChainName, AuthenticatorID) ->
             serialize_error(Reason)
     end.
 
-move_authenitcator(ConfKeyPath, ChainName, AuthenticatorID, Position) ->
+move_authenticator(ConfKeyPath, ChainName, AuthenticatorID, Position) ->
     case parse_position(Position) of
         {ok, NPosition} ->
             case update_config(

+ 7 - 6
apps/emqx_dashboard/src/emqx_dashboard_swagger.erl

@@ -31,7 +31,8 @@
 -define(TO_COMPONENTS_PARAM(_M_, _F_), iolist_to_binary([<<"#/components/parameters/">>,
                                                          ?TO_REF(namespace(_M_), _F_)])).
 
--define(MAX_ROW_LIMIT, 100).
+-define(MAX_ROW_LIMIT, 1000).
+-define(DEFAULT_ROW, 100).
 
 -type(request() :: #{bindings => map(), query_string => map(), body => map()}).
 -type(request_meta() :: #{module => module(), path => string(), method => atom()}).
@@ -80,7 +81,7 @@ fields(page) ->
 fields(limit) ->
     Desc = iolist_to_binary([<<"Results per page(max ">>,
         integer_to_binary(?MAX_ROW_LIMIT), <<")">>]),
-    Meta = #{in => query, desc => Desc, default => ?MAX_ROW_LIMIT, example => 50},
+    Meta = #{in => query, desc => Desc, default => ?DEFAULT_ROW, example => 50},
     [{limit, hoconsc:mk(range(1, ?MAX_ROW_LIMIT), Meta)}].
 
 -spec(schema_with_example(hocon_schema:type(), term()) -> hocon_schema:field_schema_map()).
@@ -123,10 +124,10 @@ translate_req(Request, #{module := Module, path := Path, method := Method}, Chec
         {Bindings, QueryStr} = check_parameters(Request, Params, Module),
         NewBody = check_request_body(Request, Body, Module, CheckFun, hoconsc:is_schema(Body)),
         {ok, Request#{bindings => Bindings, query_string => QueryStr, body => NewBody}}
-    catch throw:Error ->
-        {_, [{validation_error, ValidErr}]} = Error,
-        #{path := Key, reason := Reason} = ValidErr,
-        {400, 'BAD_REQUEST', iolist_to_binary(io_lib:format("~ts : ~p", [Key, Reason]))}
+    catch throw:{_, ValidErrors} ->
+        Msg = [io_lib:format("~ts : ~p", [Key, Reason]) ||
+            {validation_error, #{path := Key, reason := Reason}} <- ValidErrors],
+        {400, 'BAD_REQUEST', iolist_to_binary(string:join(Msg, ","))}
     end.
 
 check_and_translate(Schema, Map, Opts) ->

+ 14 - 6
apps/emqx_dashboard/test/emqx_swagger_parameter_SUITE.erl

@@ -71,8 +71,10 @@ t_public_ref(_Config) ->
         {emqx_dashboard_swagger, page, parameter}
     ], Refs),
     ExpectRefs = [
-        #{<<"public.limit">> => #{description => <<"Results per page(max 100)">>, example => 50,in => query,name => limit,
-            schema => #{default => 100,example => 1,maximum => 100, minimum => 1,type => integer}}},
+        #{<<"public.limit">> => #{description => <<"Results per page(max 1000)">>,
+            example => 50,in => query,name => limit,
+            schema => #{default => 100,example => 1,maximum => 1000,
+                minimum => 1,type => integer}}},
         #{<<"public.page">> => #{description => <<"Page number of the results to fetch.">>,
             example => 1,in => query,name => page,
             schema => #{default => 1,example => 100,type => integer}}}],
@@ -176,7 +178,8 @@ t_in_mix_trans(_Config) ->
     Expect = {ok,
         #{body => #{},
             bindings => #{state => 720},
-            query_string => #{<<"filter">> => created,<<"is_admin">> => true, <<"per_page">> => 5,<<"timeout">> => 34}}},
+            query_string => #{<<"filter">> => created,<<"is_admin">> => true,
+                <<"per_page">> => 5,<<"timeout">> => 34}}},
     ?assertEqual(Expect, trans_parameters(Path, Bindings, Query)),
     ok.
 
@@ -268,7 +271,10 @@ schema("/test/in/:filter") ->
             parameters => [
                 {filter,
                     mk(hoconsc:enum([assigned, created, mentioned, all]),
-                        #{in => path, desc => <<"Indicates which sorts of issues to return">>, example => "all"})}
+                        #{in => path,
+                          desc => <<"Indicates which sorts of issues to return">>,
+                          example => "all"
+                        })}
             ],
             responses => #{200 => <<"ok">>}
         }
@@ -323,9 +329,11 @@ schema("/test/in/mix/:state") ->
             deprecated => true,
             parameters => [
                 {filter, hoconsc:mk(hoconsc:enum([assigned, created, mentioned, all]),
-                    #{in => query, desc => <<"Indicates which sorts of issues to return">>, example => "all"})},
+                    #{in => query, desc => <<"Indicates which sorts of issues to return">>,
+                        example => "all"})},
                 {state, mk(emqx_schema:duration_s(),
-                    #{in => path, required => true, example => "12m", desc => <<"Indicates the state of the issues to return.">>})},
+                    #{in => path, required => true, example => "12m",
+                        desc => <<"Indicates the state of the issues to return.">>})},
                 {per_page, mk(range(1, 50),
                     #{in => query, required => false, example => 10, default => 5})},
                 {is_admin, mk(boolean(), #{in => query})},

+ 56 - 25
apps/emqx_dashboard/test/emqx_swagger_requestBody_SUITE.erl

@@ -47,9 +47,14 @@ t_object(_Config) ->
             #{<<"schema">> =>
             #{required => [<<"timeout">>, <<"per_page">>],
                 <<"properties">> =>[
-                    {<<"per_page">>, #{description => <<"good per page desc">>, example => 1, maximum => 100, minimum => 1, type => integer}},
-                    {<<"timeout">>, #{default => 5, <<"oneOf">> => [#{example => <<"1h">>, type => string}, #{enum => [infinity], type => string}]}},
-                    {<<"inner_ref">>, #{<<"$ref">> => <<"#/components/schemas/emqx_swagger_requestBody_SUITE.good_ref">>}}],
+                    {<<"per_page">>, #{description => <<"good per page desc">>,
+                        example => 1, maximum => 100, minimum => 1, type => integer}},
+                    {<<"timeout">>, #{default => 5, <<"oneOf">> =>
+                    [#{example => <<"1h">>, type => string},
+                        #{enum => [infinity], type => string}]}},
+                    {<<"inner_ref">>,
+                        #{<<"$ref">> =>
+                        <<"#/components/schemas/emqx_swagger_requestBody_SUITE.good_ref">>}}],
                 <<"type">> => object}}}},
             responses => #{<<"200">> => #{description => <<"ok">>}}}},
     Refs = [{?MODULE, good_ref}],
@@ -63,14 +68,20 @@ t_nest_object(_Config) ->
             #{<<"schema">> =>
             #{required => [<<"timeout">>],
                 <<"properties">> =>
-                [{<<"per_page">>, #{description => <<"good per page desc">>, example => 1, maximum => 100, minimum => 1, type => integer}},
+                [{<<"per_page">>, #{description => <<"good per page desc">>,
+                    example => 1, maximum => 100, minimum => 1, type => integer}},
                     {<<"timeout">>, #{default => 5, <<"oneOf">> =>
-                    [#{example => <<"1h">>, type => string}, #{enum => [infinity], type => string}]}},
+                    [#{example => <<"1h">>, type => string},
+                        #{enum => [infinity], type => string}]}},
                     {<<"nest_object">>,
                         #{<<"properties">> =>
                         [{<<"good_nest_1">>, #{example => 100, type => integer}},
-                            {<<"good_nest_2">>, #{<<"$ref">> => <<"#/components/schemas/emqx_swagger_requestBody_SUITE.good_ref">>}}],<<"type">> => object}},
-                    {<<"inner_ref">>, #{<<"$ref">> => <<"#/components/schemas/emqx_swagger_requestBody_SUITE.good_ref">>}}],
+                            {<<"good_nest_2">>, #{<<"$ref">> =>
+                            <<"#/components/schemas/emqx_swagger_requestBody_SUITE.good_ref">>}}],
+                            <<"type">> => object}},
+                    {<<"inner_ref">>,
+                        #{<<"$ref">> =>
+                        <<"#/components/schemas/emqx_swagger_requestBody_SUITE.good_ref">>}}],
                 <<"type">> => object}}}},
             responses => #{<<"200">> => #{description => <<"ok">>}}}},
     Refs = [{?MODULE, good_ref}],
@@ -81,7 +92,8 @@ t_local_ref(_Config) ->
     Spec = #{
         post => #{parameters => [],
             requestBody => #{<<"content">> => #{<<"application/json">> =>
-            #{<<"schema">> => #{<<"$ref">> => <<"#/components/schemas/emqx_swagger_requestBody_SUITE.good_ref">>}}}},
+            #{<<"schema">> => #{<<"$ref">> =>
+            <<"#/components/schemas/emqx_swagger_requestBody_SUITE.good_ref">>}}}},
             responses => #{<<"200">> => #{description => <<"ok">>}}}},
     Refs = [{?MODULE, good_ref}],
     validate("/ref/local", Spec, Refs),
@@ -91,17 +103,22 @@ t_remote_ref(_Config) ->
     Spec = #{
         post => #{parameters => [],
             requestBody => #{<<"content">> => #{<<"application/json">> =>
-            #{<<"schema">> => #{<<"$ref">> => <<"#/components/schemas/emqx_swagger_remote_schema.ref2">>}}}},
+            #{<<"schema">> => #{<<"$ref">> =>
+            <<"#/components/schemas/emqx_swagger_remote_schema.ref2">>}}}},
             responses => #{<<"200">> => #{description => <<"ok">>}}}},
     Refs = [{emqx_swagger_remote_schema, "ref2"}],
     {_, Components} = validate("/ref/remote", Spec, Refs),
     ExpectComponents = [
         #{<<"emqx_swagger_remote_schema.ref2">> => #{<<"properties">> => [
-            {<<"page">>, #{description => <<"good page">>,example => 1, maximum => 100,minimum => 1,type => integer}},
-        {<<"another_ref">>, #{<<"$ref">> => <<"#/components/schemas/emqx_swagger_remote_schema.ref3">>}}], <<"type">> => object}},
+            {<<"page">>, #{description => <<"good page">>,example => 1,
+                maximum => 100,minimum => 1,type => integer}},
+        {<<"another_ref">>, #{<<"$ref">> =>
+        <<"#/components/schemas/emqx_swagger_remote_schema.ref3">>}}], <<"type">> => object}},
         #{<<"emqx_swagger_remote_schema.ref3">> => #{<<"properties">> => [
-            {<<"ip">>, #{description => <<"IP:Port">>, example => <<"127.0.0.1:80">>,type => string}},
-            {<<"version">>, #{description => <<"a good version">>, example => <<"1.0.0">>,type => string}}],
+            {<<"ip">>, #{description => <<"IP:Port">>,
+                example => <<"127.0.0.1:80">>,type => string}},
+            {<<"version">>, #{description => <<"a good version">>,
+                example => <<"1.0.0">>,type => string}}],
             <<"type">> => object}}],
     ?assertEqual(ExpectComponents, Components),
     ok.
@@ -110,18 +127,22 @@ t_nest_ref(_Config) ->
     Spec = #{
         post => #{parameters => [],
             requestBody => #{<<"content">> => #{<<"application/json">> =>
-            #{<<"schema">> => #{<<"$ref">> => <<"#/components/schemas/emqx_swagger_requestBody_SUITE.nest_ref">>}}}},
+            #{<<"schema">> => #{<<"$ref">> =>
+            <<"#/components/schemas/emqx_swagger_requestBody_SUITE.nest_ref">>}}}},
             responses => #{<<"200">> => #{description => <<"ok">>}}}},
     Refs = [{?MODULE, nest_ref}],
     ExpectComponents = lists:sort([
         #{<<"emqx_swagger_requestBody_SUITE.nest_ref">> => #{<<"properties">> => [
             {<<"env">>, #{enum => [test,dev,prod],type => string}},
-            {<<"another_ref">>, #{description => <<"nest ref">>, <<"$ref">> => <<"#/components/schemas/emqx_swagger_requestBody_SUITE.good_ref">>}}],
+            {<<"another_ref">>, #{description => <<"nest ref">>,
+                <<"$ref">> => <<"#/components/schemas/emqx_swagger_requestBody_SUITE.good_ref">>}}],
             <<"type">> => object}},
         #{<<"emqx_swagger_requestBody_SUITE.good_ref">> => #{<<"properties">> => [
-            {<<"webhook-host">>, #{default => <<"127.0.0.1:80">>, example => <<"127.0.0.1:80">>,type => string}},
+            {<<"webhook-host">>, #{default => <<"127.0.0.1:80">>,
+                example => <<"127.0.0.1:80">>,type => string}},
             {<<"log_dir">>, #{example => <<"var/log/emqx">>,type => string}},
-            {<<"tag">>, #{description => <<"tag">>, example => <<"binary-example">>,type => string}}],
+            {<<"tag">>, #{description => <<"tag">>,
+                example => <<"binary-example">>,type => string}}],
             <<"type">> => object}}]),
     {_, Components} = validate("/ref/nest/ref", Spec, Refs),
     ?assertEqual(ExpectComponents, Components),
@@ -153,9 +174,14 @@ t_ref_array_with_key(_Config) ->
             #{<<"schema">> => #{required => [<<"timeout">>],
                 <<"type">> => object, <<"properties">> =>
                 [
-                    {<<"per_page">>, #{description => <<"good per page desc">>, example => 1, maximum => 100, minimum => 1, type => integer}},
-                    {<<"timeout">>, #{default => 5, <<"oneOf">> => [#{example => <<"1h">>, type => string}, #{enum => [infinity], type => string}]}},
-                    {<<"array_refs">>, #{items => #{<<"$ref">> => <<"#/components/schemas/emqx_swagger_requestBody_SUITE.good_ref">>}, type => array}}
+                    {<<"per_page">>, #{description => <<"good per page desc">>,
+                        example => 1, maximum => 100, minimum => 1, type => integer}},
+                    {<<"timeout">>, #{default => 5, <<"oneOf">> =>
+                    [#{example => <<"1h">>, type => string},
+                        #{enum => [infinity], type => string}]}},
+                    {<<"array_refs">>, #{items => #{<<"$ref">> =>
+                    <<"#/components/schemas/emqx_swagger_requestBody_SUITE.good_ref">>},
+                        type => array}}
                 ]}}}},
             responses => #{<<"200">> => #{description => <<"ok">>}}}},
     Refs = [{?MODULE, good_ref}],
@@ -166,7 +192,8 @@ t_ref_array_without_key(_Config) ->
     Spec = #{
         post => #{parameters => [],
             requestBody => #{<<"content">> => #{<<"application/json">> => #{<<"schema">> =>
-            #{items => #{<<"$ref">> => <<"#/components/schemas/emqx_swagger_requestBody_SUITE.good_ref">>}, type => array}}}},
+            #{items => #{<<"$ref">> =>
+            <<"#/components/schemas/emqx_swagger_requestBody_SUITE.good_ref">>}, type => array}}}},
             responses => #{<<"200">> => #{description => <<"ok">>}}}},
     Refs = [{?MODULE, good_ref}],
     validate("/ref/array/without/key", Spec, Refs),
@@ -190,7 +217,8 @@ t_api_spec(_Config) ->
         {ok, #{body := #{<<"timeout">> := <<"infinity">>}}},
         trans_requestBody(Path, Body, Filter0)),
 
-    {Spec1, _} = emqx_dashboard_swagger:spec(?MODULE, #{check_schema => true, translate_body => true}),
+    {Spec1, _} = emqx_dashboard_swagger:spec(?MODULE,
+        #{check_schema => true, translate_body => true}),
     Filter1 = filter(Spec1, Path),
     ?assertMatch(
         {ok, #{body := #{<<"timeout">> := infinity}}},
@@ -237,7 +265,8 @@ t_object_notrans(_Config) ->
             <<"tag">> => <<"god_tag">>
         }
     },
-    {ok, #{body := ActualBody}} = trans_requestBody(Path, Body, fun emqx_dashboard_swagger:filter_check_request/2),
+    {ok, #{body := ActualBody}} = trans_requestBody(Path, Body,
+        fun emqx_dashboard_swagger:filter_check_request/2),
     ?assertEqual(Body, ActualBody),
     ok.
 
@@ -444,7 +473,8 @@ filter(ApiSpec, Path) ->
     Filter.
 
 trans_requestBody(Path, Body) ->
-    trans_requestBody(Path, Body, fun emqx_dashboard_swagger:filter_check_request_and_translate_body/2).
+    trans_requestBody(Path, Body,
+        fun emqx_dashboard_swagger:filter_check_request_and_translate_body/2).
 
 trans_requestBody(Path, Body, Filter) ->
     Meta = #{module => ?MODULE, method => post, path => Path},
@@ -453,7 +483,8 @@ trans_requestBody(Path, Body, Filter) ->
 
 api_spec() -> emqx_dashboard_swagger:spec(?MODULE).
 paths() ->
-    ["/object", "/nest/object", "/ref/local", "/ref/nest/ref", "/ref/array/with/key", "/ref/array/without/key"].
+    ["/object", "/nest/object", "/ref/local", "/ref/nest/ref",
+        "/ref/array/with/key", "/ref/array/without/key"].
 
 schema("/object") ->
     to_schema([

+ 46 - 23
apps/emqx_dashboard/test/emqx_swagger_response_SUITE.erl

@@ -40,9 +40,12 @@ t_object(_config) ->
         #{<<"content">> => #{<<"application/json">> =>
         #{<<"schema">> => #{required => [<<"timeout">>, <<"per_page">>],
             <<"properties">> => [
-                {<<"per_page">>, #{description => <<"good per page desc">>, example => 1, maximum => 100, minimum => 1, type => integer}},
-                {<<"timeout">>, #{default => 5, <<"oneOf">> => [#{example => <<"1h">>, type => string}, #{enum => [infinity], type => string}]}},
-                {<<"inner_ref">>, #{<<"$ref">> => <<"#/components/schemas/emqx_swagger_response_SUITE.good_ref">>}}],
+                {<<"per_page">>, #{description => <<"good per page desc">>,
+                    example => 1, maximum => 100, minimum => 1, type => integer}},
+                {<<"timeout">>, #{default => 5, <<"oneOf">> =>
+                [#{example => <<"1h">>, type => string}, #{enum => [infinity], type => string}]}},
+                {<<"inner_ref">>, #{<<"$ref">> =>
+                <<"#/components/schemas/emqx_swagger_response_SUITE.good_ref">>}}],
             <<"type">> => object}}}},
     ExpectRefs = [{?MODULE, good_ref}],
     validate(Path, Object, ExpectRefs),
@@ -80,14 +83,17 @@ t_nest_object(_Config) ->
     Object =
         #{<<"content">> => #{<<"application/json">> => #{<<"schema">> =>
         #{required => [<<"timeout">>], <<"type">> => object, <<"properties">> => [
-            {<<"per_page">>, #{description => <<"good per page desc">>, example => 1, maximum => 100, minimum => 1, type => integer}},
+            {<<"per_page">>, #{description => <<"good per page desc">>, example => 1,
+                maximum => 100, minimum => 1, type => integer}},
             {<<"timeout">>, #{default => 5, <<"oneOf">> =>
             [#{example => <<"1h">>, type => string}, #{enum => [infinity], type => string}]}},
             {<<"nest_object">>, #{<<"type">> => object, <<"properties">> => [
                 {<<"good_nest_1">>, #{example => 100, type => integer}},
-                {<<"good_nest_2">>, #{<<"$ref">> => <<"#/components/schemas/emqx_swagger_response_SUITE.good_ref">>}
+                {<<"good_nest_2">>, #{<<"$ref">> =>
+                <<"#/components/schemas/emqx_swagger_response_SUITE.good_ref">>}
                 }]}},
-            {<<"inner_ref">>, #{<<"$ref">> => <<"#/components/schemas/emqx_swagger_response_SUITE.good_ref">>}}]
+            {<<"inner_ref">>, #{<<"$ref">> =>
+            <<"#/components/schemas/emqx_swagger_response_SUITE.good_ref">>}}]
         }}}},
     ExpectRefs = [{?MODULE, good_ref}],
     validate(Path, Object, ExpectRefs),
@@ -138,7 +144,8 @@ t_bad_ref(_Config) ->
     Object = #{<<"content">> => #{<<"application/json">> => #{<<"schema">> =>
     #{<<"$ref">> => <<"#/components/schemas/emqx_swagger_response_SUITE.bad_ref">>}}}},
     ExpectRefs = [{?MODULE, bad_ref}],
-    ?assertThrow({error, #{module := ?MODULE, msg := <<"Object only supports not empty proplists">>}},
+    ?assertThrow({error, #{module := ?MODULE,
+        msg := <<"Object only supports not empty proplists">>}},
         validate(Path, Object, ExpectRefs)),
     ok.
 
@@ -158,7 +165,8 @@ t_nest_ref(_Config) ->
 
 t_complicated_type(_Config) ->
     Path = "/ref/complicated_type",
-    Object = #{<<"content">> => #{<<"application/json">> => #{<<"schema">> => #{<<"properties">> =>
+    Object = #{<<"content">> => #{<<"application/json">> =>
+    #{<<"schema">> => #{<<"properties">> =>
     [
         {<<"no_neg_integer">>, #{example => 100, minimum => 1, type => integer}},
         {<<"url">>, #{example => <<"http://127.0.0.1">>, type => string}},
@@ -176,7 +184,8 @@ t_complicated_type(_Config) ->
         {<<"comma_separated_list">>, #{example => <<"item1,item2">>, type => string}},
         {<<"comma_separated_atoms">>, #{example => <<"item1,item2">>, type => string}},
         {<<"log_level">>,
-            #{enum => [debug, info, notice, warning, error, critical, alert, emergency, all], type => string}},
+            #{enum => [debug, info, notice, warning, error, critical, alert, emergency, all],
+                type => string}},
         {<<"fix_integer">>, #{default => 100, enum => [100], example => 100,type => integer}}
     ],
         <<"type">> => object}}}},
@@ -192,15 +201,20 @@ t_ref_array_with_key(_Config) ->
     Path = "/ref/array/with/key",
     Object = #{<<"content">> => #{<<"application/json">> => #{<<"schema">> => #{
         required => [<<"timeout">>], <<"type">> => object, <<"properties">> => [
-            {<<"per_page">>, #{description => <<"good per page desc">>, example => 1, maximum => 100, minimum => 1, type => integer}},
+            {<<"per_page">>, #{description => <<"good per page desc">>,
+                example => 1, maximum => 100, minimum => 1, type => integer}},
             {<<"timeout">>, #{default => 5, <<"oneOf">> =>
             [#{example => <<"1h">>, type => string}, #{enum => [infinity], type => string}]}},
             {<<"assert">>, #{description => <<"money">>, example => 3.14159, type => number}},
-            {<<"number_ex">>, #{description => <<"number example">>, example => 42, type => number}},
-            {<<"percent_ex">>, #{description => <<"percent example">>, example => <<"12%">>, type => number}},
-            {<<"duration_ms_ex">>, #{description => <<"duration ms example">>, example => <<"32s">>, type => string}},
+            {<<"number_ex">>, #{description => <<"number example">>,
+                example => 42, type => number}},
+            {<<"percent_ex">>, #{description => <<"percent example">>,
+                example => <<"12%">>, type => number}},
+            {<<"duration_ms_ex">>, #{description => <<"duration ms example">>,
+                example => <<"32s">>, type => string}},
             {<<"atom_ex">>, #{description => <<"atom ex">>, example => atom, type => string}},
-            {<<"array_refs">>, #{items => #{<<"$ref">> => <<"#/components/schemas/emqx_swagger_response_SUITE.good_ref">>}, type => array}}
+            {<<"array_refs">>, #{items => #{<<"$ref">> =>
+            <<"#/components/schemas/emqx_swagger_response_SUITE.good_ref">>}, type => array}}
         ]}
     }}},
     ExpectRefs = [{?MODULE, good_ref}],
@@ -227,25 +241,34 @@ t_hocon_schema_function(_Config) ->
         }},
         #{<<"emqx_swagger_remote_schema.ref2">> => #{<<"type">> => object,
             <<"properties">> => [
-                {<<"page">>, #{description => <<"good page">>, example => 1, maximum => 100, minimum => 1, type => integer}},
-                {<<"another_ref">>, #{<<"$ref">> => <<"#/components/schemas/emqx_swagger_remote_schema.ref3">>}}
+                {<<"page">>, #{description => <<"good page">>,
+                    example => 1, maximum => 100, minimum => 1, type => integer}},
+                {<<"another_ref">>, #{<<"$ref">> =>
+                <<"#/components/schemas/emqx_swagger_remote_schema.ref3">>}}
             ]
         }},
         #{<<"emqx_swagger_remote_schema.ref3">> => #{<<"type">> => object,
             <<"properties">> => [
-                {<<"ip">>, #{description => <<"IP:Port">>, example => <<"127.0.0.1:80">>, type => string}},
-                {<<"version">>, #{description => <<"a good version">>, example => <<"1.0.0">>, type => string}}]
+                {<<"ip">>, #{description => <<"IP:Port">>,
+                    example => <<"127.0.0.1:80">>, type => string}},
+                {<<"version">>, #{description => <<"a good version">>,
+                    example => <<"1.0.0">>, type => string}}]
         }},
-        #{<<"emqx_swagger_remote_schema.root">> => #{required => [<<"default_password">>, <<"default_username">>],
+        #{<<"emqx_swagger_remote_schema.root">> =>
+        #{required => [<<"default_password">>, <<"default_username">>],
             <<"properties">> => [{<<"listeners">>, #{items =>
             #{<<"oneOf">> =>
             [#{<<"$ref">> => <<"#/components/schemas/emqx_swagger_remote_schema.ref2">>},
-                #{<<"$ref">> => <<"#/components/schemas/emqx_swagger_remote_schema.ref1">>}]}, type => array}},
+                #{<<"$ref">> => <<"#/components/schemas/emqx_swagger_remote_schema.ref1">>}]},
+                type => array}},
                 {<<"default_username">>,
                     #{default => <<"admin">>, example => <<"string-example">>, type => string}},
-                {<<"default_password">>, #{default => <<"public">>, example => <<"string-example">>, type => string}},
-                {<<"sample_interval">>, #{default => <<"10s">>, example => <<"1h">>, type => string}},
-                {<<"token_expired_time">>, #{default => <<"30m">>, example => <<"12m">>, type => string}}],
+                {<<"default_password">>,
+                    #{default => <<"public">>, example => <<"string-example">>, type => string}},
+                {<<"sample_interval">>,
+                    #{default => <<"10s">>, example => <<"1h">>, type => string}},
+                {<<"token_expired_time">>,
+                    #{default => <<"30m">>, example => <<"12m">>, type => string}}],
             <<"type">> => object}}],
     ExpectRefs = [{emqx_swagger_remote_schema, "root"}],
     {_, Components} = validate(Path, Object, ExpectRefs),

+ 1 - 0
bin/emqx

@@ -587,6 +587,7 @@ case "${COMMAND}" in
 
     ping)
         assert_node_alive
+        echo pong
         ;;
 
     escript)