emqx_postgresql_SUITE.erl 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. % %%--------------------------------------------------------------------
  2. % %% Copyright (c) 2020-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
  3. % %%
  4. % %% Licensed under the Apache License, Version 2.0 (the "License");
  5. % %% you may not use this file except in compliance with the License.
  6. % %% You may obtain a copy of the License at
  7. % %% http://www.apache.org/licenses/LICENSE-2.0
  8. % %%
  9. % %% Unless required by applicable law or agreed to in writing, software
  10. % %% distributed under the License is distributed on an "AS IS" BASIS,
  11. % %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. % %% See the License for the specific language governing permissions and
  13. % %% limitations under the License.
  14. % %%--------------------------------------------------------------------
  15. -module(emqx_postgresql_SUITE).
  16. -compile(nowarn_export_all).
  17. -compile(export_all).
  18. -include("emqx_connector/include/emqx_connector.hrl").
  19. -include_lib("emqx_postgresql/include/emqx_postgresql.hrl").
  20. -include_lib("eunit/include/eunit.hrl").
  21. -include_lib("emqx/include/emqx.hrl").
  22. -include_lib("stdlib/include/assert.hrl").
  23. -define(PGSQL_HOST, "pgsql").
  24. -define(PGSQL_RESOURCE_MOD, emqx_postgresql).
  25. all() ->
  26. emqx_common_test_helpers:all(?MODULE).
  27. groups() ->
  28. [].
  29. init_per_suite(Config) ->
  30. case emqx_common_test_helpers:is_tcp_server_available(?PGSQL_HOST, ?PGSQL_DEFAULT_PORT) of
  31. true ->
  32. ok = emqx_common_test_helpers:start_apps([emqx_conf]),
  33. ok = emqx_connector_test_helpers:start_apps([emqx_resource]),
  34. {ok, _} = application:ensure_all_started(emqx_connector),
  35. Config;
  36. false ->
  37. {skip, no_pgsql}
  38. end.
  39. end_per_suite(_Config) ->
  40. ok = emqx_common_test_helpers:stop_apps([emqx_conf]),
  41. ok = emqx_connector_test_helpers:stop_apps([emqx_resource]),
  42. _ = application:stop(emqx_connector).
  43. init_per_testcase(_, Config) ->
  44. Config.
  45. end_per_testcase(_, _Config) ->
  46. ok.
  47. % %%------------------------------------------------------------------------------
  48. % %% Testcases
  49. % %%------------------------------------------------------------------------------
  50. t_lifecycle(_Config) ->
  51. perform_lifecycle_check(
  52. <<"emqx_postgresql_SUITE">>,
  53. pgsql_config()
  54. ).
  55. perform_lifecycle_check(ResourceId, InitialConfig) ->
  56. {ok, #{config := CheckedConfig}} =
  57. emqx_resource:check_config(?PGSQL_RESOURCE_MOD, InitialConfig),
  58. {ok, #{
  59. state := #{pool_name := PoolName} = State,
  60. status := InitialStatus
  61. }} =
  62. emqx_resource:create_local(
  63. ResourceId,
  64. ?CONNECTOR_RESOURCE_GROUP,
  65. ?PGSQL_RESOURCE_MOD,
  66. CheckedConfig,
  67. #{}
  68. ),
  69. ?assertEqual(InitialStatus, connected),
  70. % Instance should match the state and status of the just started resource
  71. {ok, ?CONNECTOR_RESOURCE_GROUP, #{
  72. state := State,
  73. status := InitialStatus
  74. }} =
  75. emqx_resource:get_instance(ResourceId),
  76. ?assertEqual({ok, connected}, emqx_resource:health_check(ResourceId)),
  77. % % Perform query as further check that the resource is working as expected
  78. ?assertMatch({ok, _, [{1}]}, emqx_resource:query(ResourceId, test_query_no_params())),
  79. ?assertMatch({ok, _, [{1}]}, emqx_resource:query(ResourceId, test_query_with_params())),
  80. ?assertEqual(ok, emqx_resource:stop(ResourceId)),
  81. % Resource will be listed still, but state will be changed and healthcheck will fail
  82. % as the worker no longer exists.
  83. {ok, ?CONNECTOR_RESOURCE_GROUP, #{
  84. state := State,
  85. status := StoppedStatus
  86. }} =
  87. emqx_resource:get_instance(ResourceId),
  88. ?assertEqual(stopped, StoppedStatus),
  89. ?assertEqual({error, resource_is_stopped}, emqx_resource:health_check(ResourceId)),
  90. % Resource healthcheck shortcuts things by checking ets. Go deeper by checking pool itself.
  91. ?assertEqual({error, not_found}, ecpool:stop_sup_pool(PoolName)),
  92. % Can call stop/1 again on an already stopped instance
  93. ?assertEqual(ok, emqx_resource:stop(ResourceId)),
  94. % Make sure it can be restarted and the healthchecks and queries work properly
  95. ?assertEqual(ok, emqx_resource:restart(ResourceId)),
  96. % async restart, need to wait resource
  97. timer:sleep(500),
  98. {ok, ?CONNECTOR_RESOURCE_GROUP, #{status := InitialStatus}} =
  99. emqx_resource:get_instance(ResourceId),
  100. ?assertEqual({ok, connected}, emqx_resource:health_check(ResourceId)),
  101. ?assertMatch({ok, _, [{1}]}, emqx_resource:query(ResourceId, test_query_no_params())),
  102. ?assertMatch({ok, _, [{1}]}, emqx_resource:query(ResourceId, test_query_with_params())),
  103. % Stop and remove the resource in one go.
  104. ?assertEqual(ok, emqx_resource:remove_local(ResourceId)),
  105. ?assertEqual({error, not_found}, ecpool:stop_sup_pool(PoolName)),
  106. % Should not even be able to get the resource data out of ets now unlike just stopping.
  107. ?assertEqual({error, not_found}, emqx_resource:get_instance(ResourceId)).
  108. % %%------------------------------------------------------------------------------
  109. % %% Helpers
  110. % %%------------------------------------------------------------------------------
  111. pgsql_config() ->
  112. RawConfig = list_to_binary(
  113. io_lib:format(
  114. ""
  115. "\n"
  116. " auto_reconnect = true\n"
  117. " database = mqtt\n"
  118. " username= root\n"
  119. " password = public\n"
  120. " pool_size = 8\n"
  121. " server = \"~s:~b\"\n"
  122. " "
  123. "",
  124. [?PGSQL_HOST, ?PGSQL_DEFAULT_PORT]
  125. )
  126. ),
  127. {ok, Config} = hocon:binary(RawConfig),
  128. #{<<"config">> => Config}.
  129. test_query_no_params() ->
  130. {query, <<"SELECT 1">>}.
  131. test_query_with_params() ->
  132. {query, <<"SELECT $1::integer">>, [1]}.