fix(test): fix test case

This commit is contained in:
zhouzb 2021-09-07 10:29:45 +08:00
parent e998770f2e
commit 627de1d58c
12 changed files with 268 additions and 24 deletions

View File

@ -0,0 +1,238 @@
%%--------------------------------------------------------------------
%% Copyright (c) 2020-2021 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_authentication_SUITE).
-behaviour(hocon_schema).
-behaviour(emqx_authentication).
-compile(export_all).
-compile(nowarn_export_all).
-include_lib("common_test/include/ct.hrl").
-include_lib("eunit/include/eunit.hrl").
-include_lib("typerefl/include/types.hrl").
-export([ fields/1 ]).
-export([ refs/0
, create/1
, update/2
, authenticate/2
, destroy/1
]).
-define(AUTHN, emqx_authentication).
%%------------------------------------------------------------------------------
%% Hocon Schema
%%------------------------------------------------------------------------------
fields(type1) ->
[ {mechanism, {enum, ['password-based']}}
, {backend, {enum, ['built-in-database']}}
, {enable, fun enable/1}
];
fields(type2) ->
[ {mechanism, {enum, ['password-based']}}
, {backend, {enum, ['mysql']}}
, {enable, fun enable/1}
].
enable(type) -> boolean();
enable(default) -> true;
enable(_) -> undefined.
%%------------------------------------------------------------------------------
%% Callbacks
%%------------------------------------------------------------------------------
refs() ->
[ hoconsc:ref(?MODULE, type1)
, hoconsc:ref(?MODULE, type2)
].
create(_Config) ->
{ok, #{mark => 1}}.
update(_Config, _State) ->
{ok, #{mark => 2}}.
authenticate(#{username := <<"good">>}, _State) ->
{ok, #{superuser => true}};
authenticate(#{username := _}, _State) ->
{error, bad_username_or_password}.
destroy(_State) ->
ok.
all() ->
emqx_ct:all(?MODULE).
init_per_suite(Config) ->
application:set_env(ekka, strict_mode, true),
emqx_ct_helpers:start_apps([]),
Config.
end_per_suite(_) ->
emqx_ct_helpers:stop_apps([]),
ok.
t_chain(_) ->
% CRUD of authentication chain
ChainName = <<"test">>,
?assertMatch({ok, []}, ?AUTHN:list_chains()),
?assertMatch({ok, #{name := ChainName, authenticators := []}}, ?AUTHN:create_chain(ChainName)),
?assertEqual({error, {already_exists, {chain, ChainName}}}, ?AUTHN:create_chain(ChainName)),
?assertMatch({ok, #{name := ChainName, authenticators := []}}, ?AUTHN:lookup_chain(ChainName)),
?assertMatch({ok, [#{name := ChainName}]}, ?AUTHN:list_chains()),
?assertEqual(ok, ?AUTHN:delete_chain(ChainName)),
?assertMatch({error, {not_found, {chain, ChainName}}}, ?AUTHN:lookup_chain(ChainName)),
ok.
t_authenticator(_) ->
ChainName = <<"test">>,
AuthenticatorConfig1 = #{mechanism => 'password-based',
backend => 'built-in-database',
enable => true},
% Create an authenticator when the authentication chain does not exist
?assertEqual({error, {not_found, {chain, ChainName}}}, ?AUTHN:create_authenticator(ChainName, AuthenticatorConfig1)),
?AUTHN:create_chain(ChainName),
% Create an authenticator when the provider does not exist
?assertEqual({error, no_available_provider}, ?AUTHN:create_authenticator(ChainName, AuthenticatorConfig1)),
AuthNType1 = {'password-based', 'built-in-database'},
?AUTHN:add_provider(AuthNType1, ?MODULE),
ID1 = <<"password-based:built-in-database">>,
% CRUD of authencaticator
?assertMatch({ok, #{id := ID1, state := #{mark := 1}}}, ?AUTHN:create_authenticator(ChainName, AuthenticatorConfig1)),
?assertMatch({ok, #{id := ID1}}, ?AUTHN:lookup_authenticator(ChainName, ID1)),
?assertMatch({ok, [#{id := ID1}]}, ?AUTHN:list_authenticators(ChainName)),
?assertEqual({error, {already_exists, {authenticator, ID1}}}, ?AUTHN:create_authenticator(ChainName, AuthenticatorConfig1)),
?assertMatch({ok, #{id := ID1, state := #{mark := 2}}}, ?AUTHN:update_authenticator(ChainName, ID1, AuthenticatorConfig1)),
?assertEqual(ok, ?AUTHN:delete_authenticator(ChainName, ID1)),
?assertEqual({error, {not_found, {authenticator, ID1}}}, ?AUTHN:update_authenticator(ChainName, ID1, AuthenticatorConfig1)),
?assertMatch({ok, []}, ?AUTHN:list_authenticators(ChainName)),
% Multiple authenticators exist at the same time
AuthNType2 = {'password-based', mysql},
?AUTHN:add_provider(AuthNType2, ?MODULE),
ID2 = <<"password-based:mysql">>,
AuthenticatorConfig2 = #{mechanism => 'password-based',
backend => mysql,
enable => true},
?assertMatch({ok, #{id := ID1}}, ?AUTHN:create_authenticator(ChainName, AuthenticatorConfig1)),
?assertMatch({ok, #{id := ID2}}, ?AUTHN:create_authenticator(ChainName, AuthenticatorConfig2)),
% Move authenticator
?assertMatch({ok, [#{id := ID1}, #{id := ID2}]}, ?AUTHN:list_authenticators(ChainName)),
?assertEqual(ok, ?AUTHN:move_authenticator(ChainName, ID2, top)),
?assertMatch({ok, [#{id := ID2}, #{id := ID1}]}, ?AUTHN:list_authenticators(ChainName)),
?assertEqual(ok, ?AUTHN:move_authenticator(ChainName, ID2, bottom)),
?assertMatch({ok, [#{id := ID1}, #{id := ID2}]}, ?AUTHN:list_authenticators(ChainName)),
?assertEqual(ok, ?AUTHN:move_authenticator(ChainName, ID2, {before, ID1})),
?assertMatch({ok, [#{id := ID2}, #{id := ID1}]}, ?AUTHN:list_authenticators(ChainName)),
?AUTHN:delete_chain(ChainName),
?AUTHN:remove_provider(AuthNType1),
?AUTHN:remove_provider(AuthNType2),
ok.
t_authenticate(_) ->
ListenerID = <<"tcp:default">>,
ClientInfo = #{zone => default,
listener => ListenerID,
protocol => mqtt,
username => <<"good">>,
password => <<"any">>},
?assertEqual({ok, #{superuser => false}}, emqx_access_control:authenticate(ClientInfo)),
AuthNType = {'password-based', 'built-in-database'},
?AUTHN:add_provider(AuthNType, ?MODULE),
AuthenticatorConfig = #{mechanism => 'password-based',
backend => 'built-in-database',
enable => true},
?AUTHN:create_chain(ListenerID),
?assertMatch({ok, _}, ?AUTHN:create_authenticator(ListenerID, AuthenticatorConfig)),
?assertEqual({ok, #{superuser => true}}, emqx_access_control:authenticate(ClientInfo)),
?assertEqual({error, bad_username_or_password}, emqx_access_control:authenticate(ClientInfo#{username => <<"bad">>})),
?AUTHN:delete_chain(ListenerID),
?AUTHN:remove_provider(AuthNType),
ok.
t_update_config(_) ->
emqx_config_handler:add_handler([authentication], emqx_authentication),
AuthNType1 = {'password-based', 'built-in-database'},
AuthNType2 = {'password-based', mysql},
?AUTHN:add_provider(AuthNType1, ?MODULE),
?AUTHN:add_provider(AuthNType2, ?MODULE),
Global = <<"mqtt:global">>,
AuthenticatorConfig1 = #{mechanism => 'password-based',
backend => 'built-in-database',
enable => true},
AuthenticatorConfig2 = #{mechanism => 'password-based',
backend => mysql,
enable => true},
ID1 = <<"password-based:built-in-database">>,
ID2 = <<"password-based:mysql">>,
?assertMatch({ok, []}, ?AUTHN:list_chains()),
?assertMatch({ok, _}, update_config([authentication], {create_authenticator, Global, AuthenticatorConfig1})),
?assertMatch({ok, #{id := ID1, state := #{mark := 1}}}, ?AUTHN:lookup_authenticator(Global, ID1)),
?assertMatch({ok, _}, update_config([authentication], {create_authenticator, Global, AuthenticatorConfig2})),
?assertMatch({ok, #{id := ID2, state := #{mark := 1}}}, ?AUTHN:lookup_authenticator(Global, ID2)),
?assertMatch({ok, _}, update_config([authentication], {update_authenticator, Global, ID1, #{}})),
?assertMatch({ok, #{id := ID1, state := #{mark := 2}}}, ?AUTHN:lookup_authenticator(Global, ID1)),
?assertMatch({ok, _}, update_config([authentication], {move_authenticator, Global, ID2, <<"top">>})),
?assertMatch({ok, [#{id := ID2}, #{id := ID1}]}, ?AUTHN:list_authenticators(Global)),
?assertMatch({ok, _}, update_config([authentication], {delete_authenticator, Global, ID1})),
?assertEqual({error, {not_found, {authenticator, ID1}}}, ?AUTHN:lookup_authenticator(Global, ID1)),
ListenerID = <<"tcp:default">>,
ConfKeyPath = [listeners, tcp, default, authentication],
?assertMatch({ok, _}, update_config(ConfKeyPath, {create_authenticator, ListenerID, AuthenticatorConfig1})),
?assertMatch({ok, #{id := ID1, state := #{mark := 1}}}, ?AUTHN:lookup_authenticator(ListenerID, ID1)),
?assertMatch({ok, _}, update_config(ConfKeyPath, {create_authenticator, ListenerID, AuthenticatorConfig2})),
?assertMatch({ok, #{id := ID2, state := #{mark := 1}}}, ?AUTHN:lookup_authenticator(ListenerID, ID2)),
?assertMatch({ok, _}, update_config(ConfKeyPath, {update_authenticator, ListenerID, ID1, #{}})),
?assertMatch({ok, #{id := ID1, state := #{mark := 2}}}, ?AUTHN:lookup_authenticator(ListenerID, ID1)),
?assertMatch({ok, _}, update_config(ConfKeyPath, {move_authenticator, ListenerID, ID2, <<"top">>})),
?assertMatch({ok, [#{id := ID2}, #{id := ID1}]}, ?AUTHN:list_authenticators(ListenerID)),
?assertMatch({ok, _}, update_config(ConfKeyPath, {delete_authenticator, ListenerID, ID1})),
?assertEqual({error, {not_found, {authenticator, ID1}}}, ?AUTHN:lookup_authenticator(ListenerID, ID1)),
?AUTHN:delete_chain(Global),
?AUTHN:remove_provider(AuthNType1),
?AUTHN:remove_provider(AuthNType2),
ok.
update_config(Path, ConfigRequest) ->
emqx:update_config(Path, ConfigRequest, #{rawconf_with_defaults => true}).

View File

@ -251,8 +251,8 @@ generate_request(Credential, #{method := Method,
post -> post ->
NPath = append_query(Path, BaseQuery), NPath = append_query(Path, BaseQuery),
ContentType = proplists:get_value(<<"content-type">>, Headers), ContentType = proplists:get_value(<<"content-type">>, Headers),
Body = serialize_body(ContentType, Body), NBody = serialize_body(ContentType, Body),
{NPath, Headers, Body} {NPath, Headers, NBody}
end. end.
replace_placeholders(KVs, Credential) -> replace_placeholders(KVs, Credential) ->

View File

@ -15,3 +15,8 @@
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
-module(emqx_authn_SUITE). -module(emqx_authn_SUITE).
-compile(export_all).
-compile(nowarn_export_all).
all() -> emqx_ct:all(?MODULE).

View File

@ -16,8 +16,8 @@
-module(emqx_authn_jwt_SUITE). -module(emqx_authn_jwt_SUITE).
% -compile(export_all). -compile(export_all).
% -compile(nowarn_export_all). -compile(nowarn_export_all).
% -include_lib("common_test/include/ct.hrl"). % -include_lib("common_test/include/ct.hrl").
% -include_lib("eunit/include/eunit.hrl"). % -include_lib("eunit/include/eunit.hrl").
@ -26,8 +26,8 @@
% -define(AUTH, emqx_authn). % -define(AUTH, emqx_authn).
% all() -> all() ->
% emqx_ct:all(?MODULE). emqx_ct:all(?MODULE).
% init_per_suite(Config) -> % init_per_suite(Config) ->
% emqx_ct_helpers:start_apps([emqx_authn]), % emqx_ct_helpers:start_apps([emqx_authn]),

View File

@ -16,8 +16,8 @@
-module(emqx_authn_mnesia_SUITE). -module(emqx_authn_mnesia_SUITE).
% -compile(export_all). -compile(export_all).
% -compile(nowarn_export_all). -compile(nowarn_export_all).
% -include_lib("common_test/include/ct.hrl"). % -include_lib("common_test/include/ct.hrl").
% -include_lib("eunit/include/eunit.hrl"). % -include_lib("eunit/include/eunit.hrl").
@ -26,8 +26,8 @@
% -define(AUTH, emqx_authn). % -define(AUTH, emqx_authn).
% all() -> all() ->
% emqx_ct:all(?MODULE). emqx_ct:all(?MODULE).
% init_per_suite(Config) -> % init_per_suite(Config) ->
% emqx_ct_helpers:start_apps([emqx_authn]), % emqx_ct_helpers:start_apps([emqx_authn]),

View File

@ -142,7 +142,9 @@ to_ip_port(Str) ->
_ -> {error, Str} _ -> {error, Str}
end. end.
ip_port_to_string({Ip, Port}) -> ip_port_to_string({Ip, Port}) when is_list(Ip) ->
iolist_to_binary([Ip, ":", integer_to_list(Port)]);
ip_port_to_string({Ip, Port}) when is_tuple(Ip) ->
iolist_to_binary([inet:ntoa(Ip), ":", integer_to_list(Port)]). iolist_to_binary([inet:ntoa(Ip), ":", integer_to_list(Port)]).
to_servers(Str) -> to_servers(Str) ->

View File

@ -3,7 +3,7 @@
{vsn, "0.1.0"}, {vsn, "0.1.0"},
{registered, []}, {registered, []},
{mod, {emqx_gateway_app, []}}, {mod, {emqx_gateway_app, []}},
{applications, [kernel, stdlib, grpc, lwm2m_coap, emqx, emqx_authn]}, {applications, [kernel, stdlib, grpc, lwm2m_coap, emqx]},
{env, []}, {env, []},
{modules, []}, {modules, []},
{licenses, ["Apache 2.0"]}, {licenses, ["Apache 2.0"]},

View File

@ -55,20 +55,19 @@ metrics() ->
init_per_group(GrpName, Cfg) -> init_per_group(GrpName, Cfg) ->
put(grpname, GrpName), put(grpname, GrpName),
Svrs = emqx_exproto_echo_svr:start(), Svrs = emqx_exproto_echo_svr:start(),
emqx_ct_helpers:start_apps([emqx_authn, emqx_gateway], fun set_special_cfg/1), emqx_ct_helpers:start_apps([emqx_gateway], fun set_special_cfg/1),
emqx_logger:set_log_level(debug), emqx_logger:set_log_level(debug),
[{servers, Svrs}, {listener_type, GrpName} | Cfg]. [{servers, Svrs}, {listener_type, GrpName} | Cfg].
end_per_group(_, Cfg) -> end_per_group(_, Cfg) ->
emqx_ct_helpers:stop_apps([emqx_gateway, emqx_authn]), emqx_ct_helpers:stop_apps([emqx_gateway]),
emqx_exproto_echo_svr:stop(proplists:get_value(servers, Cfg)). emqx_exproto_echo_svr:stop(proplists:get_value(servers, Cfg)).
set_special_cfg(emqx_gateway) -> set_special_cfg(emqx_gateway) ->
LisType = get(grpname), LisType = get(grpname),
emqx_config:put( emqx_config:put(
[gateway, exproto], [gateway, exproto],
#{authentication => #{enable => false}, #{server => #{bind => 9100},
server => #{bind => 9100},
handler => #{address => "http://127.0.0.1:9001"}, handler => #{address => "http://127.0.0.1:9001"},
listeners => listener_confs(LisType) listeners => listener_confs(LisType)
}); });

View File

@ -35,11 +35,11 @@ all() -> emqx_ct:all(?MODULE).
init_per_suite(Cfg) -> init_per_suite(Cfg) ->
ok = emqx_config:init_load(emqx_gateway_schema, ?CONF_DEFAULT), ok = emqx_config:init_load(emqx_gateway_schema, ?CONF_DEFAULT),
emqx_ct_helpers:start_apps([emqx_authn, emqx_gateway]), emqx_ct_helpers:start_apps([emqx_gateway]),
Cfg. Cfg.
end_per_suite(_Cfg) -> end_per_suite(_Cfg) ->
emqx_ct_helpers:stop_apps([emqx_authn, emqx_gateway]), emqx_ct_helpers:stop_apps([emqx_gateway]),
ok. ok.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------

View File

@ -148,12 +148,12 @@ groups() ->
]. ].
init_per_suite(Config) -> init_per_suite(Config) ->
emqx_ct_helpers:start_apps([emqx_authn]), emqx_ct_helpers:start_apps([]),
Config. Config.
end_per_suite(Config) -> end_per_suite(Config) ->
timer:sleep(300), timer:sleep(300),
emqx_ct_helpers:stop_apps([emqx_authn]), emqx_ct_helpers:stop_apps([]),
Config. Config.
init_per_testcase(_AllTestCase, Config) -> init_per_testcase(_AllTestCase, Config) ->

View File

@ -83,11 +83,11 @@ all() ->
init_per_suite(Config) -> init_per_suite(Config) ->
ok = emqx_config:init_load(emqx_gateway_schema, ?CONF_DEFAULT), ok = emqx_config:init_load(emqx_gateway_schema, ?CONF_DEFAULT),
emqx_ct_helpers:start_apps([emqx_authn, emqx_gateway]), emqx_ct_helpers:start_apps([emqx_gateway]),
Config. Config.
end_per_suite(_) -> end_per_suite(_) ->
emqx_ct_helpers:stop_apps([emqx_gateway, emqx_authn]). emqx_ct_helpers:stop_apps([emqx_gateway]).
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Test cases %% Test cases

View File

@ -43,11 +43,11 @@ all() -> emqx_ct:all(?MODULE).
init_per_suite(Cfg) -> init_per_suite(Cfg) ->
ok = emqx_config:init_load(emqx_gateway_schema, ?CONF_DEFAULT), ok = emqx_config:init_load(emqx_gateway_schema, ?CONF_DEFAULT),
emqx_ct_helpers:start_apps([emqx_authn, emqx_gateway]), emqx_ct_helpers:start_apps([emqx_gateway]),
Cfg. Cfg.
end_per_suite(_Cfg) -> end_per_suite(_Cfg) ->
emqx_ct_helpers:stop_apps([emqx_gateway, emqx_authn]), emqx_ct_helpers:stop_apps([emqx_gateway]),
ok. ok.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------