From 56904698963cb13a3df92bc734e391db707cb286 Mon Sep 17 00:00:00 2001 From: Zhongwen Deng Date: Tue, 30 May 2023 15:03:11 +0800 Subject: [PATCH] fix: flaky test when stopping dashboard listener --- apps/emqx/src/emqx_listeners.erl | 1 + apps/emqx_dashboard/src/emqx_dashboard.erl | 7 +- .../test/emqx_dashboard_SUITE.erl | 2 + .../test/emqx_dashboard_https_SUITE.erl | 83 ++++++++++++++++++- 4 files changed, 86 insertions(+), 7 deletions(-) diff --git a/apps/emqx/src/emqx_listeners.erl b/apps/emqx/src/emqx_listeners.erl index acdb9ff96..5fe9cf9ca 100644 --- a/apps/emqx/src/emqx_listeners.erl +++ b/apps/emqx/src/emqx_listeners.erl @@ -57,6 +57,7 @@ ]). -export([pre_config_update/3, post_config_update/5]). +-export([wait_listener_stopped/1]). -export([format_bind/1]). diff --git a/apps/emqx_dashboard/src/emqx_dashboard.erl b/apps/emqx_dashboard/src/emqx_dashboard.erl index 364853eec..77ec61687 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard.erl @@ -111,14 +111,15 @@ stop_listeners(Listeners) -> begin case minirest:stop(Name) of ok -> + _ = emqx_listeners:wait_listener_stopped(Bind), ?ULOG("Stop listener ~ts on ~ts successfully.~n", [ - Name, emqx_listeners:format_bind(Port) + Name, emqx_listeners:format_bind(Bind) ]); {error, not_found} -> - ?SLOG(warning, #{msg => "stop_listener_failed", name => Name, port => Port}) + ?SLOG(warning, #{msg => "stop_listener_failed", name => Name, bind => Bind}) end end - || {Name, _, Port, _, _} <- listeners(Listeners) + || {Name, _, Bind, _, _} <- listeners(Listeners) ], ok. diff --git a/apps/emqx_dashboard/test/emqx_dashboard_SUITE.erl b/apps/emqx_dashboard/test/emqx_dashboard_SUITE.erl index 0d446a7f2..1230316e0 100644 --- a/apps/emqx_dashboard/test/emqx_dashboard_SUITE.erl +++ b/apps/emqx_dashboard/test/emqx_dashboard_SUITE.erl @@ -234,6 +234,8 @@ do_request_dashboard(Method, Request) -> -> {ok, Return}; {ok, {Reason, _, _}} -> + {error, Reason}; + {error, Reason} -> {error, Reason} end. diff --git a/apps/emqx_dashboard/test/emqx_dashboard_https_SUITE.erl b/apps/emqx_dashboard/test/emqx_dashboard_https_SUITE.erl index fefaeb7f1..6c894d851 100644 --- a/apps/emqx_dashboard/test/emqx_dashboard_https_SUITE.erl +++ b/apps/emqx_dashboard/test/emqx_dashboard_https_SUITE.erl @@ -21,9 +21,11 @@ -include_lib("eunit/include/eunit.hrl"). -include("emqx_dashboard.hrl"). +-include_lib("snabbkaffe/include/snabbkaffe.hrl"). -define(NAME, 'https:dashboard'). --define(HOST, "https://127.0.0.1:18084"). +-define(HOST_HTTPS, "https://127.0.0.1:18084"). +-define(HOST_HTTP, "http://127.0.0.1:18083"). -define(BASE_PATH, "/api/v5"). -define(OVERVIEWS, [ "alarms", @@ -44,6 +46,76 @@ end_per_suite(_Config) -> emqx_mgmt_api_test_util:end_suite([emqx_management]). init_per_testcase(_TestCase, Config) -> Config. end_per_testcase(_TestCase, _Config) -> emqx_mgmt_api_test_util:end_suite([emqx_management]). +t_update_conf(_Config) -> + Conf = #{ + dashboard => #{ + listeners => #{ + https => #{bind => 18084, enable => true}, + http => #{bind => 18083, enable => true} + } + } + }, + emqx_common_test_helpers:load_config(emqx_dashboard_schema, Conf), + emqx_mgmt_api_test_util:init_suite([emqx_management], fun(X) -> X end), + Headers = emqx_dashboard_SUITE:auth_header_(), + {ok, Client1} = emqx_dashboard_SUITE:request_dashboard( + get, https_api_path(["clients"]), Headers + ), + {ok, Client2} = emqx_dashboard_SUITE:request_dashboard( + get, http_api_path(["clients"]), Headers + ), + Raw = emqx:get_raw_config([<<"dashboard">>]), + ?assertEqual(Client1, Client2), + ?check_trace( + begin + Raw1 = emqx_utils_maps:deep_put( + [<<"listeners">>, <<"https">>, <<"enable">>], Raw, false + ), + ?assertMatch({ok, _}, emqx:update_config([<<"dashboard">>], Raw1)), + ?assertEqual(Raw1, emqx:get_raw_config([<<"dashboard">>])), + {ok, _} = ?block_until(#{?snk_kind := regenerate_minirest_dispatch}, 10000), + ok + end, + fun(ok, Trace) -> + %% Don't start new listener, so is empty + ?assertMatch([#{listeners := []}], ?of_kind(regenerate_minirest_dispatch, Trace)) + end + ), + {ok, Client3} = emqx_dashboard_SUITE:request_dashboard( + get, http_api_path(["clients"]), Headers + ), + ?assertEqual(Client1, Client3), + ?assertMatch( + {error, + {failed_connect, [ + _, + {inet, [inet], econnrefused} + ]}}, + emqx_dashboard_SUITE:request_dashboard(get, https_api_path(["clients"]), Headers) + ), + %% reset + ?check_trace( + begin + ?assertMatch({ok, _}, emqx:update_config([<<"dashboard">>], Raw)), + ?assertEqual(Raw, emqx:get_raw_config([<<"dashboard">>])), + {ok, _} = ?block_until(#{?snk_kind := regenerate_minirest_dispatch}, 10000), + ok + end, + fun(ok, Trace) -> + %% start new listener('https:dashboard') + ?assertMatch( + [#{listeners := ['https:dashboard']}], ?of_kind(regenerate_minirest_dispatch, Trace) + ) + end + ), + {ok, Client1} = emqx_dashboard_SUITE:request_dashboard( + get, https_api_path(["clients"]), Headers + ), + {ok, Client2} = emqx_dashboard_SUITE:request_dashboard( + get, http_api_path(["clients"]), Headers + ), + emqx_mgmt_api_test_util:end_suite([emqx_management]). + t_default_ssl_cert(_Config) -> Conf = #{dashboard => #{listeners => #{https => #{bind => 18084, enable => true}}}}, validate_https(Conf, 512, default_ssl_cert(), verify_none), @@ -188,7 +260,7 @@ assert_https_request() -> Headers = emqx_dashboard_SUITE:auth_header_(), lists:foreach( fun(Path) -> - ApiPath = api_path([Path]), + ApiPath = https_api_path([Path]), ?assertMatch( {ok, _}, emqx_dashboard_SUITE:request_dashboard(get, ApiPath, Headers) @@ -197,8 +269,11 @@ assert_https_request() -> ?OVERVIEWS ). -api_path(Parts) -> - ?HOST ++ filename:join([?BASE_PATH | Parts]). +https_api_path(Parts) -> + ?HOST_HTTPS ++ filename:join([?BASE_PATH | Parts]). + +http_api_path(Parts) -> + ?HOST_HTTP ++ filename:join([?BASE_PATH | Parts]). naive_env_interpolation(Str0) -> Str1 = emqx_schema:naive_env_interpolation(Str0),