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
This commit is contained in:
parent
124ba7a071
commit
f697028b70
|
@ -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),
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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) ->
|
||||
|
|
|
@ -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})},
|
||||
|
|
|
@ -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([
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Reference in New Issue