Explorar el Código

Merge pull request #6958 from mononym/EMQX-3143-postgre-sql

feat: create tests for connector pgsql module and refactoring
Chris Hicks hace 4 años
padre
commit
ddbb78557a

+ 19 - 0
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.

+ 1 - 1
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]),

+ 1 - 1
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]),

+ 1 - 1
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]),

+ 1 - 1
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]),

+ 1 - 1
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]),

+ 1 - 1
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]),

+ 1 - 1
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]),

+ 1 - 1
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]),

+ 0 - 11
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"]),

+ 1 - 1
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],

+ 1 - 1
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],

+ 1 - 1
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],

+ 1 - 1
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],

+ 0 - 9
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}) ->

+ 1 - 0
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

+ 143 - 0
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">>.