diff --git a/apps/emqx/test/emqx_common_test_helpers.erl b/apps/emqx/test/emqx_common_test_helpers.erl index 0fd7ea94b..ac4d1ba03 100644 --- a/apps/emqx/test/emqx_common_test_helpers.erl +++ b/apps/emqx/test/emqx_common_test_helpers.erl @@ -49,6 +49,8 @@ , render_config_file/2 , read_schema_configs/2 , load_config/2 + , is_tcp_server_available/2 + , is_tcp_server_available/3 ]). -define( CERTS_PATH(CertName), filename:join( [ "etc", "certs", CertName ]) ). @@ -111,6 +113,7 @@ ] } ]). +-define(DEFAULT_TCP_SERVER_CHECK_AVAIL_TIMEOUT, 1000). %%------------------------------------------------------------------------------ %% APIs @@ -433,3 +436,19 @@ copy_certs(_, _) -> ok. load_config(SchemaModule, Config) -> ok = emqx_config:delete_override_conf_files(), ok = emqx_config:init_load(SchemaModule, Config). + +-spec is_tcp_server_available(Host :: inet:socket_address() | inet:hostname(), + Port :: inet:port_number()) -> boolean. +is_tcp_server_available(Host, Port) -> + is_tcp_server_available(Host, Port, ?DEFAULT_TCP_SERVER_CHECK_AVAIL_TIMEOUT). + +-spec is_tcp_server_available(Host :: inet:socket_address() | inet:hostname(), + Port :: inet:port_number(), Timeout :: integer()) -> boolean. +is_tcp_server_available(Host, Port, Timeout) -> + case gen_tcp:connect(Host, Port, [], Timeout) of + {ok, Socket} -> + gen_tcp:close(Socket), + true; + {error, _} -> + false + end. diff --git a/apps/emqx_authn/test/emqx_authn_mongo_SUITE.erl b/apps/emqx_authn/test/emqx_authn_mongo_SUITE.erl index cb97e3d48..4e69c6fcc 100644 --- a/apps/emqx_authn/test/emqx_authn_mongo_SUITE.erl +++ b/apps/emqx_authn/test/emqx_authn_mongo_SUITE.erl @@ -47,7 +47,7 @@ end_per_testcase(_TestCase, _Config) -> init_per_suite(Config) -> _ = application:load(emqx_conf), - case emqx_authn_test_lib:is_tcp_server_available(?MONGO_HOST, ?MONGO_PORT) of + case emqx_common_test_helpers:is_tcp_server_available(?MONGO_HOST, ?MONGO_PORT) of true -> ok = emqx_common_test_helpers:start_apps([emqx_authn]), ok = start_apps([emqx_resource, emqx_connector]), diff --git a/apps/emqx_authn/test/emqx_authn_mongo_tls_SUITE.erl b/apps/emqx_authn/test/emqx_authn_mongo_tls_SUITE.erl index 73cdd6a53..0531ce249 100644 --- a/apps/emqx_authn/test/emqx_authn_mongo_tls_SUITE.erl +++ b/apps/emqx_authn/test/emqx_authn_mongo_tls_SUITE.erl @@ -43,7 +43,7 @@ init_per_testcase(_TestCase, Config) -> init_per_suite(Config) -> _ = application:load(emqx_conf), - case emqx_authn_test_lib:is_tcp_server_available(?MONGO_HOST, ?MONGO_PORT) of + case emqx_common_test_helpers:is_tcp_server_available(?MONGO_HOST, ?MONGO_PORT) of true -> ok = emqx_common_test_helpers:start_apps([emqx_authn]), ok = start_apps([emqx_resource, emqx_connector]), diff --git a/apps/emqx_authn/test/emqx_authn_mysql_SUITE.erl b/apps/emqx_authn/test/emqx_authn_mysql_SUITE.erl index bd5ab3126..489a602c0 100644 --- a/apps/emqx_authn/test/emqx_authn_mysql_SUITE.erl +++ b/apps/emqx_authn/test/emqx_authn_mysql_SUITE.erl @@ -53,7 +53,7 @@ end_per_group(require_seeds, Config) -> init_per_suite(Config) -> _ = application:load(emqx_conf), - case emqx_authn_test_lib:is_tcp_server_available(?MYSQL_HOST, ?MYSQL_PORT) of + case emqx_common_test_helpers:is_tcp_server_available(?MYSQL_HOST, ?MYSQL_PORT) of true -> ok = emqx_common_test_helpers:start_apps([emqx_authn]), ok = start_apps([emqx_resource, emqx_connector]), diff --git a/apps/emqx_authn/test/emqx_authn_mysql_tls_SUITE.erl b/apps/emqx_authn/test/emqx_authn_mysql_tls_SUITE.erl index bc38b8910..d20b7b50d 100644 --- a/apps/emqx_authn/test/emqx_authn_mysql_tls_SUITE.erl +++ b/apps/emqx_authn/test/emqx_authn_mysql_tls_SUITE.erl @@ -44,7 +44,7 @@ init_per_testcase(_, Config) -> init_per_suite(Config) -> _ = application:load(emqx_conf), - case emqx_authn_test_lib:is_tcp_server_available(?MYSQL_HOST, ?MYSQL_PORT) of + case emqx_common_test_helpers:is_tcp_server_available(?MYSQL_HOST, ?MYSQL_PORT) of true -> ok = emqx_common_test_helpers:start_apps([emqx_authn]), ok = start_apps([emqx_resource, emqx_connector]), diff --git a/apps/emqx_authn/test/emqx_authn_pgsql_SUITE.erl b/apps/emqx_authn/test/emqx_authn_pgsql_SUITE.erl index 714c9715e..6a5e07939 100644 --- a/apps/emqx_authn/test/emqx_authn_pgsql_SUITE.erl +++ b/apps/emqx_authn/test/emqx_authn_pgsql_SUITE.erl @@ -54,7 +54,7 @@ end_per_group(require_seeds, Config) -> init_per_suite(Config) -> _ = application:load(emqx_conf), - case emqx_authn_test_lib:is_tcp_server_available(?PGSQL_HOST, ?PGSQL_PORT) of + case emqx_common_test_helpers:is_tcp_server_available(?PGSQL_HOST, ?PGSQL_PORT) of true -> ok = emqx_common_test_helpers:start_apps([emqx_authn]), ok = start_apps([emqx_resource, emqx_connector]), diff --git a/apps/emqx_authn/test/emqx_authn_pgsql_tls_SUITE.erl b/apps/emqx_authn/test/emqx_authn_pgsql_tls_SUITE.erl index 0225ed06f..b2ec46fd5 100644 --- a/apps/emqx_authn/test/emqx_authn_pgsql_tls_SUITE.erl +++ b/apps/emqx_authn/test/emqx_authn_pgsql_tls_SUITE.erl @@ -44,7 +44,7 @@ init_per_testcase(_, Config) -> init_per_suite(Config) -> _ = application:load(emqx_conf), - case emqx_authn_test_lib:is_tcp_server_available(?PGSQL_HOST, ?PGSQL_PORT) of + case emqx_common_test_helpers:is_tcp_server_available(?PGSQL_HOST, ?PGSQL_PORT) of true -> ok = emqx_common_test_helpers:start_apps([emqx_authn]), ok = start_apps([emqx_resource, emqx_connector]), diff --git a/apps/emqx_authn/test/emqx_authn_redis_SUITE.erl b/apps/emqx_authn/test/emqx_authn_redis_SUITE.erl index 5a376b9c7..64805ecb7 100644 --- a/apps/emqx_authn/test/emqx_authn_redis_SUITE.erl +++ b/apps/emqx_authn/test/emqx_authn_redis_SUITE.erl @@ -53,7 +53,7 @@ end_per_group(require_seeds, Config) -> init_per_suite(Config) -> _ = application:load(emqx_conf), - case emqx_authn_test_lib:is_tcp_server_available(?REDIS_HOST, ?REDIS_PORT) of + case emqx_common_test_helpers:is_tcp_server_available(?REDIS_HOST, ?REDIS_PORT) of true -> ok = emqx_common_test_helpers:start_apps([emqx_authn]), ok = start_apps([emqx_resource, emqx_connector]), diff --git a/apps/emqx_authn/test/emqx_authn_redis_tls_SUITE.erl b/apps/emqx_authn/test/emqx_authn_redis_tls_SUITE.erl index ba7f87272..84f67937b 100644 --- a/apps/emqx_authn/test/emqx_authn_redis_tls_SUITE.erl +++ b/apps/emqx_authn/test/emqx_authn_redis_tls_SUITE.erl @@ -44,7 +44,7 @@ init_per_testcase(_, Config) -> init_per_suite(Config) -> _ = application:load(emqx_conf), - case emqx_authn_test_lib:is_tcp_server_available(?REDIS_HOST, ?REDIS_PORT) of + case emqx_common_test_helpers:is_tcp_server_available(?REDIS_HOST, ?REDIS_PORT) of true -> ok = emqx_common_test_helpers:start_apps([emqx_authn]), ok = start_apps([emqx_resource, emqx_connector]), diff --git a/apps/emqx_authn/test/emqx_authn_test_lib.erl b/apps/emqx_authn/test/emqx_authn_test_lib.erl index 2c3437281..357d8b05b 100644 --- a/apps/emqx_authn/test/emqx_authn_test_lib.erl +++ b/apps/emqx_authn/test/emqx_authn_test_lib.erl @@ -21,8 +21,6 @@ -compile(nowarn_export_all). -compile(export_all). --define(DEFAULT_CHECK_AVAIL_TIMEOUT, 1000). - authenticator_example(Id) -> #{Id := #{value := Example}} = emqx_authn_api:authenticator_examples(), Example. @@ -57,15 +55,6 @@ delete_config(ID) -> {delete_authenticator, ?GLOBAL, ID}, #{rawconf_with_defaults => false}). -is_tcp_server_available(Host, Port) -> - case gen_tcp:connect(Host, Port, [], ?DEFAULT_CHECK_AVAIL_TIMEOUT) of - {ok, Socket} -> - gen_tcp:close(Socket), - true; - {error, _} -> - false - end. - client_ssl_cert_opts() -> Dir = code:lib_dir(emqx_authn, test), #{keyfile => filename:join([Dir, "data/certs", "client.key"]), diff --git a/apps/emqx_authz/test/emqx_authz_mongodb_SUITE.erl b/apps/emqx_authz/test/emqx_authz_mongodb_SUITE.erl index 62f9f932e..4b990f125 100644 --- a/apps/emqx_authz/test/emqx_authz_mongodb_SUITE.erl +++ b/apps/emqx_authz/test/emqx_authz_mongodb_SUITE.erl @@ -34,7 +34,7 @@ groups() -> []. init_per_suite(Config) -> - case emqx_authz_test_lib:is_tcp_server_available(?MONGO_HOST, ?MONGO_PORT) of + case emqx_common_test_helpers:is_tcp_server_available(?MONGO_HOST, ?MONGO_PORT) of true -> ok = emqx_common_test_helpers:start_apps( [emqx_conf, emqx_authz], diff --git a/apps/emqx_authz/test/emqx_authz_mysql_SUITE.erl b/apps/emqx_authz/test/emqx_authz_mysql_SUITE.erl index d1b8d0934..0cccd748e 100644 --- a/apps/emqx_authz/test/emqx_authz_mysql_SUITE.erl +++ b/apps/emqx_authz/test/emqx_authz_mysql_SUITE.erl @@ -34,7 +34,7 @@ groups() -> []. init_per_suite(Config) -> - case emqx_authn_test_lib:is_tcp_server_available(?MYSQL_HOST, ?MYSQL_PORT) of + case emqx_common_test_helpers:is_tcp_server_available(?MYSQL_HOST, ?MYSQL_PORT) of true -> ok = emqx_common_test_helpers:start_apps( [emqx_conf, emqx_authz], diff --git a/apps/emqx_authz/test/emqx_authz_postgresql_SUITE.erl b/apps/emqx_authz/test/emqx_authz_postgresql_SUITE.erl index 45745326d..fbc2cc922 100644 --- a/apps/emqx_authz/test/emqx_authz_postgresql_SUITE.erl +++ b/apps/emqx_authz/test/emqx_authz_postgresql_SUITE.erl @@ -34,7 +34,7 @@ groups() -> []. init_per_suite(Config) -> - case emqx_authn_test_lib:is_tcp_server_available(?PGSQL_HOST, ?PGSQL_PORT) of + case emqx_common_test_helpers:is_tcp_server_available(?PGSQL_HOST, ?PGSQL_PORT) of true -> ok = emqx_common_test_helpers:start_apps( [emqx_conf, emqx_authz], diff --git a/apps/emqx_authz/test/emqx_authz_redis_SUITE.erl b/apps/emqx_authz/test/emqx_authz_redis_SUITE.erl index cf784b1ab..83699f51c 100644 --- a/apps/emqx_authz/test/emqx_authz_redis_SUITE.erl +++ b/apps/emqx_authz/test/emqx_authz_redis_SUITE.erl @@ -35,7 +35,7 @@ groups() -> []. init_per_suite(Config) -> - case emqx_authn_test_lib:is_tcp_server_available(?REDIS_HOST, ?REDIS_PORT) of + case emqx_common_test_helpers:is_tcp_server_available(?REDIS_HOST, ?REDIS_PORT) of true -> ok = emqx_common_test_helpers:start_apps( [emqx_conf, emqx_authz], diff --git a/apps/emqx_authz/test/emqx_authz_test_lib.erl b/apps/emqx_authz/test/emqx_authz_test_lib.erl index b7de5c3da..6225d3a83 100644 --- a/apps/emqx_authz/test/emqx_authz_test_lib.erl +++ b/apps/emqx_authz/test/emqx_authz_test_lib.erl @@ -45,15 +45,6 @@ setup_config(BaseConfig, SpecialParams) -> {error, Reason} -> {error, Reason} end. -is_tcp_server_available(Host, Port) -> - case gen_tcp:connect(Host, Port, [], ?DEFAULT_CHECK_AVAIL_TIMEOUT) of - {ok, Socket} -> - gen_tcp:close(Socket), - true; - {error, _} -> - false - end. - test_samples(ClientInfo, Samples) -> lists:foreach( fun({Expected, Action, Topic}) -> diff --git a/apps/emqx_connector/test/emqx_connector_api_SUITE.erl b/apps/emqx_connector/test/emqx_connector_api_SUITE.erl index 4e73384ec..9e5e44273 100644 --- a/apps/emqx_connector/test/emqx_connector_api_SUITE.erl +++ b/apps/emqx_connector/test/emqx_connector_api_SUITE.erl @@ -21,6 +21,7 @@ -include("emqx/include/emqx.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("common_test/include/ct.hrl"). +-include("emqx_dashboard/include/emqx_dashboard.hrl"). %% output functions -export([ inspect/3 diff --git a/apps/emqx_connector/test/emqx_connector_pgsql_SUITE.erl b/apps/emqx_connector/test/emqx_connector_pgsql_SUITE.erl new file mode 100644 index 000000000..8f04bd71a --- /dev/null +++ b/apps/emqx_connector/test/emqx_connector_pgsql_SUITE.erl @@ -0,0 +1,143 @@ +% %%-------------------------------------------------------------------- +% %% Copyright (c) 2020-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_connector_pgsql_SUITE). + +-compile(nowarn_export_all). +-compile(export_all). + +-include_lib("eunit/include/eunit.hrl"). +-include_lib("emqx/include/emqx.hrl"). +-include_lib("stdlib/include/assert.hrl"). + +-define(PGSQL_HOST, "pgsql"). +-define(PGSQL_PORT, 5432). + +all() -> + emqx_common_test_helpers:all(?MODULE). + +groups() -> + []. + +init_per_suite(Config) -> + case emqx_common_test_helpers:is_tcp_server_available(?PGSQL_HOST, ?PGSQL_PORT) of + true -> + Config; + false -> + {skip, no_pgsql} + end. + +end_per_suite(_Config) -> + ok. + +init_per_testcase(_, Config) -> + ?assertEqual( + {ok, #{poolname => emqx_connector_pgsql}}, + emqx_connector_pgsql:on_start(<<"emqx_connector_pgsql">>, pgsql_config()) + ), + Config. + +end_per_testcase(_, _Config) -> + ?assertEqual( + ok, + emqx_connector_pgsql:on_stop(<<"emqx_connector_pgsql">>, #{poolname => emqx_connector_pgsql}) + ). + +% %%------------------------------------------------------------------------------ +% %% Testcases +% %%------------------------------------------------------------------------------ + +% Simple test to make sure the proper reference to the module is returned. +t_roots(_Config) -> + ExpectedRoots = [{config, #{type => {ref, emqx_connector_pgsql, config}}}], + ActualRoots = emqx_connector_pgsql:roots(), + ?assertEqual(ExpectedRoots, ActualRoots). + +% Not sure if this level of testing is appropriate for this function. +% Checking the actual values/types of the returned term starts getting +% into checking the emqx_connector_schema_lib.erl returns and the shape +% of expected data elsewhere. +t_fields(_Config) -> + Fields = emqx_connector_pgsql:fields(config), + lists:foreach( + fun({FieldName, FieldValue}) -> + ?assert(is_atom(FieldName)), + if + is_map(FieldValue) -> + ?assert(maps:is_key(type, FieldValue) and maps:is_key(default, FieldValue)); + true -> + ?assert(is_function(FieldValue)) + end + end, + Fields + ). + +% Execute a minimal query to validate connection. +t_basic_query(_Config) -> + ?assertMatch( + {ok, _, [{1}]}, + emqx_connector_pgsql:on_query( + <<"emqx_connector_pgsql">>, {query, test_query()}, undefined, #{ + poolname => emqx_connector_pgsql + } + ) + ). + +% Perform health check. +t_do_healthcheck(_Config) -> + ?assertEqual( + {ok, #{poolname => emqx_connector_pgsql}}, + emqx_connector_pgsql:on_health_check(<<"emqx_connector_pgsql">>, #{ + poolname => emqx_connector_pgsql + }) + ). + +% Perform healthcheck on a connector that does not exist. +t_healthceck_when_connector_does_not_exist(_Config) -> + ?assertEqual( + {error, health_check_failed, #{poolname => emqx_connector_pgsql_does_not_exist}}, + emqx_connector_pgsql:on_health_check(<<"emqx_connector_pgsql_does_not_exist">>, #{ + poolname => emqx_connector_pgsql_does_not_exist + }) + ). + +% %%------------------------------------------------------------------------------ +% %% Helpers +% %%------------------------------------------------------------------------------ + +pgsql_config() -> + #{ + auto_reconnect => true, + database => <<"mqtt">>, + username => <<"root">>, + password => <<"public">>, + pool_size => 8, + server => {?PGSQL_HOST, ?PGSQL_PORT}, + ssl => #{enable => false} + }. + +pgsql_bad_config() -> + #{ + auto_reconnect => true, + database => <<"bad_mqtt">>, + username => <<"bad_root">>, + password => <<"bad_public">>, + pool_size => 8, + server => {?PGSQL_HOST, ?PGSQL_PORT}, + ssl => #{enable => false} + }. + +test_query() -> + <<"SELECT 1">>.