diff --git a/apps/emqx_gateway/src/emqx_gateway.erl b/apps/emqx_gateway/src/emqx_gateway.erl index 9421229f7..74a8244d4 100644 --- a/apps/emqx_gateway/src/emqx_gateway.erl +++ b/apps/emqx_gateway/src/emqx_gateway.erl @@ -41,6 +41,7 @@ registered_gateway() -> %%-------------------------------------------------------------------- %% Gateway APIs +%% @doc List the load gateways -spec list() -> [gateway()]. list() -> emqx_gateway_sup:list_gateway_insta(). @@ -65,6 +66,8 @@ lookup(Name) -> -spec update(gateway_name(), emqx_config:config()) -> ok | {error, any()}. %% @doc This function only supports full configuration updates +%% +%% Note: If the `enable` option is missing, it will be set to true by default update(Name, Config) -> emqx_gateway_sup:update_gateway(Name, Config). diff --git a/apps/emqx_gateway/src/emqx_gateway_gw_sup.erl b/apps/emqx_gateway/src/emqx_gateway_gw_sup.erl index fa55ceb8d..9ca806213 100644 --- a/apps/emqx_gateway/src/emqx_gateway_gw_sup.erl +++ b/apps/emqx_gateway/src/emqx_gateway_gw_sup.erl @@ -51,7 +51,6 @@ create_insta(Sup, Gateway = #{name := Name}, GwDscrptr) -> {ok, _GwInstaPid} -> {error, alredy_existed}; false -> Ctx = ctx(Sup, Name), - %% ChildSpec = emqx_gateway_utils:childspec( Name, worker, diff --git a/apps/emqx_gateway/src/emqx_gateway_insta_sup.erl b/apps/emqx_gateway/src/emqx_gateway_insta_sup.erl index 30cebb3cc..096ab1f81 100644 --- a/apps/emqx_gateway/src/emqx_gateway_insta_sup.erl +++ b/apps/emqx_gateway/src/emqx_gateway_insta_sup.erl @@ -308,8 +308,7 @@ do_update_one_by_one(NCfg, State = #state{ name = GwName, config = OCfg, status = Status}) -> - OEnable = maps:get(enable, OCfg, true), - NEnable = maps:get(enable, NCfg, OEnable), + NEnable = maps:get(enable, NCfg, true), OAuths = authns(GwName, OCfg), NAuths = authns(GwName, NCfg), diff --git a/apps/emqx_gateway/src/emqx_gateway_sup.erl b/apps/emqx_gateway/src/emqx_gateway_sup.erl index 9a969a5ce..499132d35 100644 --- a/apps/emqx_gateway/src/emqx_gateway_sup.erl +++ b/apps/emqx_gateway/src/emqx_gateway_sup.erl @@ -59,7 +59,8 @@ load_gateway(Gateway = #{name := GwName}) -> unload_gateway(GwName) -> case lists:keyfind(GwName, 1, supervisor:which_children(?MODULE)) of false -> {error, not_found}; - _ -> + {_Id, Pid, _Type, _Mods} -> + _ = emqx_gateway_gw_sup:remove_insta(Pid, GwName), _ = supervisor:terminate_child(?MODULE, GwName), _ = supervisor:delete_child(?MODULE, GwName), ok diff --git a/apps/emqx_gateway/test/emqx_gateway_SUITE.erl b/apps/emqx_gateway/test/emqx_gateway_SUITE.erl new file mode 100644 index 000000000..dc6ab3a9c --- /dev/null +++ b/apps/emqx_gateway/test/emqx_gateway_SUITE.erl @@ -0,0 +1,100 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2022 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_gateway_SUITE). + +-include_lib("eunit/include/eunit.hrl"). + +-compile(export_all). +-compile(nowarn_export_all). + +-define(GWNAME, mqttsn). +-define(CONF_DEFAULT, <<"gateway {}">>). + +%%-------------------------------------------------------------------- +%% setups +%%-------------------------------------------------------------------- + +all() -> emqx_common_test_helpers:all(?MODULE). + +init_per_suite(Conf) -> + emqx_config:erase(gateway), + emqx_config:init_load(emqx_gateway_schema, ?CONF_DEFAULT), + emqx_common_test_helpers:start_apps([emqx_gateway]), + Conf. + +end_per_suite(_Conf) -> + emqx_common_test_helpers:stop_apps([emqx_gateway]). + +%%-------------------------------------------------------------------- +%% cases +%%-------------------------------------------------------------------- + +t_registered_gateway(_) -> + [{coap, #{cbkmod := emqx_coap_impl}}, + {exproto, #{cbkmod := emqx_exproto_impl}}, + {lwm2m, #{cbkmod := emqx_lwm2m_impl}}, + {mqttsn, #{cbkmod := emqx_sn_impl}}, + {stomp, #{cbkmod := emqx_stomp_impl}}] = emqx_gateway:registered_gateway(). + +t_load_unload_list_lookup(_) -> + {ok, _} = emqx_gateway:load(?GWNAME, #{idle_timeout => 1000}), + ?assertEqual( + {error, alredy_existed}, + emqx_gateway:load(?GWNAME, #{})), + ?assertEqual( + {error, {unknown_gateway_name, bad_gw_name}}, + emqx_gateway:load(bad_gw_name, #{})), + + ?assertEqual(1, length(emqx_gateway:list())), + ?assertEqual( + emqx_gateway:lookup(?GWNAME), + lists:nth(1, emqx_gateway:list())), + + ?assertEqual(ok, emqx_gateway:unload(?GWNAME)), + ?assertEqual({error, not_found}, emqx_gateway:unload(?GWNAME)). + +t_start_stop_update(_) -> + {ok, _} = emqx_gateway:load(?GWNAME, #{idle_timeout => 1000}), + + #{status := running} = emqx_gateway:lookup(?GWNAME), + + ok = emqx_gateway:stop(?GWNAME), + {error, already_stopped} = emqx_gateway:stop(?GWNAME), + + #{status := stopped} = emqx_gateway:lookup(?GWNAME), + + ok = emqx_gateway:update( + ?GWNAME, #{enable => false, idle_timeout => 2000}), + #{status := stopped, + config := #{idle_timeout := 2000}} = emqx_gateway:lookup(?GWNAME), + + ok = emqx_gateway:update( + ?GWNAME, #{enable => true, idle_timeout => 3000}), + #{status := running, + config := #{idle_timeout := 3000}} = emqx_gateway:lookup(?GWNAME), + + ok = emqx_gateway:update( + ?GWNAME, #{enable => false, idle_timeout => 4000}), + #{status := stopped, + config := #{idle_timeout := 4000}} = emqx_gateway:lookup(?GWNAME), + + ok = emqx_gateway:start(?GWNAME), + #{status := running, + config := #{idle_timeout := 4000}} = emqx_gateway:lookup(?GWNAME), + + {error, already_started} = emqx_gateway:start(?GWNAME), + ok. diff --git a/apps/emqx_gateway/test/emqx_gateway_cm_registry_SUITE.erl b/apps/emqx_gateway/test/emqx_gateway_cm_registry_SUITE.erl index 1541ed281..3cca034a6 100644 --- a/apps/emqx_gateway/test/emqx_gateway_cm_registry_SUITE.erl +++ b/apps/emqx_gateway/test/emqx_gateway_cm_registry_SUITE.erl @@ -90,7 +90,7 @@ t_cleanup_channels(Conf) -> [], emqx_gateway_cm_registry:lookup_channels(?GWNAME, ?CLIENTID)). -t_unexpected_msg_handling(Conf) -> +t_handle_unexpected_msg(Conf) -> Pid = proplists:get_value(registry, Conf), _ = Pid ! unexpected_info, ok = gen_server:cast(Pid, unexpected_cast), diff --git a/apps/emqx_gateway/test/emqx_gateway_registry_SUITE.erl b/apps/emqx_gateway/test/emqx_gateway_registry_SUITE.erl index 993da10bb..63378f875 100644 --- a/apps/emqx_gateway/test/emqx_gateway_registry_SUITE.erl +++ b/apps/emqx_gateway/test/emqx_gateway_registry_SUITE.erl @@ -57,7 +57,13 @@ t_load_unload(_) -> {error, already_existed} = emqx_gateway_registry:reg(test, [{cbkmod, ?MODULE}]), + ok = emqx_gateway_registry:unreg(test), ok = emqx_gateway_registry:unreg(test), undefined = emqx_gateway_registry:lookup(test), OldCnt = length(emqx_gateway_registry:list()), ok. + +t_handle_unexpected_msg(_) -> + _ = emqx_gateway_registry ! unexpected_info, + ok = gen_server:cast(emqx_gateway_registry, unexpected_cast), + ok = gen_server:call(emqx_gateway_registry, unexpected_call).