Selaa lähdekoodia

chore: preparing to run common tests / eunit with mix

Thales Macedo Garitezi 1 vuosi sitten
vanhempi
commit
19f3b030f9
100 muutettua tiedostoa jossa 779 lisäystä ja 486 poistoa
  1. 4 2
      Makefile
  2. 37 0
      apps/emqx/lib/mix/tasks/compile.copy_srcs.ex
  3. 20 5
      apps/emqx/mix.exs
  4. 1 1
      apps/emqx/test/emqx_bpapi_SUITE.erl
  5. 1 0
      apps/emqx/test/emqx_common_test_helpers.erl
  6. 9 2
      apps/emqx/test/emqx_cth_cluster.erl
  7. 4 4
      apps/emqx/test/emqx_cth_suite.erl
  8. 1 1
      apps/emqx/test/emqx_persistent_session_ds_router_SUITE.erl
  9. 4 2
      apps/emqx_audit/mix.exs
  10. 26 12
      apps/emqx_audit/test/emqx_audit_api_SUITE.erl
  11. 17 5
      apps/emqx_auth/mix.exs
  12. 22 24
      apps/emqx_auth/test/emqx_authz/emqx_authz_api_cache_SUITE.erl
  13. 22 25
      apps/emqx_auth/test/emqx_authz/emqx_authz_api_settings_SUITE.erl
  14. 24 24
      apps/emqx_auth/test/emqx_authz/emqx_authz_rule_SUITE.erl
  15. 4 2
      apps/emqx_auth_ext/mix.exs
  16. 7 7
      apps/emqx_auth_http/mix.exs
  17. 5 6
      apps/emqx_auth_jwt/mix.exs
  18. 5 5
      apps/emqx_auth_ldap/mix.exs
  19. 13 11
      apps/emqx_auth_ldap/test/emqx_authz_ldap_SUITE.erl
  20. 5 9
      apps/emqx_auth_mnesia/mix.exs
  21. 1 0
      apps/emqx_auth_mnesia/test/emqx_authn_api_mnesia_SUITE.erl
  22. 1 1
      apps/emqx_auth_mnesia/test/emqx_authz_mnesia_SUITE.erl
  23. 5 5
      apps/emqx_auth_mongodb/mix.exs
  24. 1 1
      apps/emqx_auth_mongodb/test/emqx_authn_mongodb_SUITE.erl
  25. 1 1
      apps/emqx_auth_mongodb/test/emqx_authn_mongodb_tls_SUITE.erl
  26. 1 1
      apps/emqx_auth_mongodb/test/emqx_authz_mongodb_SUITE.erl
  27. 5 5
      apps/emqx_auth_mysql/mix.exs
  28. 1 1
      apps/emqx_auth_mysql/test/emqx_authn_mysql_SUITE.erl
  29. 1 1
      apps/emqx_auth_mysql/test/emqx_authn_mysql_tls_SUITE.erl
  30. 1 1
      apps/emqx_auth_mysql/test/emqx_authz_mysql_SUITE.erl
  31. 5 6
      apps/emqx_auth_postgresql/mix.exs
  32. 2 2
      apps/emqx_auth_postgresql/test/emqx_authn_postgresql_SUITE.erl
  33. 1 1
      apps/emqx_auth_postgresql/test/emqx_authn_postgresql_tls_SUITE.erl
  34. 1 1
      apps/emqx_auth_postgresql/test/emqx_authz_postgresql_SUITE.erl
  35. 5 5
      apps/emqx_auth_redis/mix.exs
  36. 1 1
      apps/emqx_auth_redis/test/emqx_authn_redis_SUITE.erl
  37. 1 1
      apps/emqx_auth_redis/test/emqx_authz_redis_SUITE.erl
  38. 4 2
      apps/emqx_auto_subscribe/mix.exs
  39. 43 47
      apps/emqx_auto_subscribe/test/emqx_auto_subscribe_SUITE.erl
  40. 17 5
      apps/emqx_bridge/mix.exs
  41. 9 11
      apps/emqx_bridge/test/emqx_bridge_v2_testlib.erl
  42. 7 2
      apps/emqx_bridge_azure_blob_storage/mix.exs
  43. 5 3
      apps/emqx_bridge_azure_event_hub/mix.exs
  44. 4 2
      apps/emqx_bridge_cassandra/mix.exs
  45. 1 4
      apps/emqx_bridge_cassandra/test/emqx_bridge_cassandra_SUITE.erl
  46. 19 10
      apps/emqx_bridge_cassandra/test/emqx_bridge_cassandra_connector_SUITE.erl
  47. 4 2
      apps/emqx_bridge_clickhouse/mix.exs
  48. 18 8
      apps/emqx_bridge_clickhouse/test/emqx_bridge_clickhouse_SUITE.erl
  49. 19 7
      apps/emqx_bridge_clickhouse/test/emqx_bridge_clickhouse_connector_SUITE.erl
  50. 5 3
      apps/emqx_bridge_confluent/mix.exs
  51. 4 2
      apps/emqx_bridge_dynamo/mix.exs
  52. 16 7
      apps/emqx_bridge_dynamo/test/emqx_bridge_dynamo_SUITE.erl
  53. 4 2
      apps/emqx_bridge_es/mix.exs
  54. 4 2
      apps/emqx_bridge_gcp_pubsub/mix.exs
  55. 4 2
      apps/emqx_bridge_greptimedb/mix.exs
  56. 13 9
      apps/emqx_bridge_greptimedb/test/emqx_bridge_greptimedb_connector_SUITE.erl
  57. 5 3
      apps/emqx_bridge_hstreamdb/mix.exs
  58. 13 5
      apps/emqx_bridge_hstreamdb/test/emqx_bridge_hstreamdb_SUITE.erl
  59. 5 4
      apps/emqx_bridge_http/mix.exs
  60. 4 2
      apps/emqx_bridge_influxdb/mix.exs
  61. 26 23
      apps/emqx_bridge_influxdb/test/emqx_bridge_influxdb_SUITE.erl
  62. 13 7
      apps/emqx_bridge_influxdb/test/emqx_bridge_influxdb_connector_SUITE.erl
  63. 4 2
      apps/emqx_bridge_iotdb/mix.exs
  64. 13 2
      apps/emqx_bridge_iotdb/test/emqx_bridge_iotdb_impl_SUITE.erl
  65. 5 3
      apps/emqx_bridge_kafka/mix.exs
  66. 1 1
      apps/emqx_bridge_kafka/test/emqx_bridge_v2_kafka_producer_SUITE.erl
  67. 4 2
      apps/emqx_bridge_kinesis/mix.exs
  68. 17 9
      apps/emqx_bridge_kinesis/test/emqx_bridge_kinesis_impl_producer_SUITE.erl
  69. 4 2
      apps/emqx_bridge_matrix/mix.exs
  70. 4 2
      apps/emqx_bridge_mongodb/mix.exs
  71. 5 4
      apps/emqx_bridge_mqtt/mix.exs
  72. 4 3
      apps/emqx_bridge_mqtt/test/emqx_bridge_mqtt_SUITE.erl
  73. 4 2
      apps/emqx_bridge_mysql/mix.exs
  74. 22 5
      apps/emqx_bridge_mysql/test/emqx_bridge_mysql_SUITE.erl
  75. 4 2
      apps/emqx_bridge_opents/mix.exs
  76. 10 2
      apps/emqx_bridge_opents/test/emqx_bridge_opents_SUITE.erl
  77. 4 2
      apps/emqx_bridge_oracle/mix.exs
  78. 17 12
      apps/emqx_bridge_oracle/test/emqx_bridge_oracle_SUITE.erl
  79. 4 2
      apps/emqx_bridge_pgsql/mix.exs
  80. 1 1
      apps/emqx_bridge_pgsql/test/emqx_bridge_pgsql_SUITE.erl
  81. 1 3
      apps/emqx_bridge_pgsql/test/emqx_bridge_v2_pgsql_SUITE.erl
  82. 5 3
      apps/emqx_bridge_pulsar/mix.exs
  83. 9 6
      apps/emqx_bridge_rabbitmq/mix.exs
  84. 1 1
      apps/emqx_bridge_rabbitmq/test/emqx_bridge_rabbitmq_connector_SUITE.erl
  85. 30 19
      apps/emqx_bridge_rabbitmq/test/emqx_bridge_rabbitmq_test_utils.erl
  86. 4 2
      apps/emqx_bridge_redis/mix.exs
  87. 4 2
      apps/emqx_bridge_rocketmq/mix.exs
  88. 0 2
      apps/emqx_bridge_rocketmq/test/emqx_bridge_rocketmq_SUITE.erl
  89. 5 3
      apps/emqx_bridge_s3/mix.exs
  90. 4 2
      apps/emqx_bridge_sqlserver/mix.exs
  91. 14 7
      apps/emqx_bridge_sqlserver/test/emqx_bridge_sqlserver_SUITE.erl
  92. 4 2
      apps/emqx_bridge_syskeeper/mix.exs
  93. 4 2
      apps/emqx_bridge_tdengine/mix.exs
  94. 17 5
      apps/emqx_bridge_tdengine/test/emqx_bridge_tdengine_SUITE.erl
  95. 4 2
      apps/emqx_bridge_timescale/mix.exs
  96. 10 3
      apps/emqx_cluster_link/mix.exs
  97. 5 6
      apps/emqx_conf/mix.exs
  98. 0 2
      apps/emqx_conf/src/emqx_conf_schema.erl
  99. 0 1
      apps/emqx_conf/test/emqx_conf_app_SUITE.erl
  100. 0 0
      apps/emqx_conf/test/emqx_conf_cli_SUITE.erl

+ 4 - 2
Makefile

@@ -63,8 +63,10 @@ mix-deps-get: $(ELIXIR_COMMON_DEPS)
 	@mix deps.get
 
 .PHONY: eunit
-eunit: $(REBAR) merge-config
-	@$(REBAR) eunit --name eunit@127.0.0.1 -c -v --cover_export_name $(CT_COVER_EXPORT_PREFIX)-eunit
+eunit: $(REBAR) ${ELIXIR_COMMON_DEPS} merge-config
+	# @$(REBAR) eunit --name eunit@127.0.0.1 -c -v --cover_export_name $(CT_COVER_EXPORT_PREFIX)-eunit
+	# TODO: cover compile
+	mix eunit
 
 .PHONY: proper
 proper: $(REBAR)

+ 37 - 0
apps/emqx/lib/mix/tasks/compile.copy_srcs.ex

@@ -0,0 +1,37 @@
+defmodule Mix.Tasks.Compile.CopySrcs do
+  use Mix.Task.Compiler
+
+  @recursive true
+
+  @impl true
+  def run(_args) do
+    Mix.Project.get!()
+    config = Mix.Project.config()
+    extra_dirs = config[:extra_dirs]
+
+    unless extra_dirs && is_list(extra_dirs) do
+      Mix.raise("application option :extra_dirs in #{Mix.Project.project_file()} must be a list of directories under the application")
+    end
+
+    app_root = File.cwd!()
+    app_build_path = Mix.Project.app_path(config)
+
+    for extra_dir <- extra_dirs do
+      src = Path.join([app_root, extra_dir])
+      dest = Path.join([app_build_path, extra_dir])
+      File.rm(dest)
+      case File.ln_s(src, dest) do
+        :ok ->
+          :ok
+
+        {:error, :eexist} ->
+          Mix.shell().info(IO.ANSI.format([:yellow, "#{dest} still exists after attempted removal"]))
+          :ok
+
+        {:error, error} ->
+          Mix.raise("error trying to link #{src} to #{dest}: #{error}")
+      end
+    end
+    {:noop, []}
+  end
+end

+ 20 - 5
apps/emqx/mix.exs

@@ -1,15 +1,21 @@
 defmodule EMQX.MixProject do
   use Mix.Project
 
+  alias EMQXUmbrella.MixProject, as: UMP
+
   def project do
     [
       app: :emqx,
       version: "0.1.0",
       build_path: "../../_build",
+      erlc_paths: UMP.erlc_paths(),
       erlc_options: [
         {:i, "src"}
-        | EMQXUmbrella.MixProject.erlc_options()
+        | UMP.erlc_options()
       ],
+      compilers: Mix.compilers() ++ [:copy_srcs],
+      # used by our `Mix.Tasks.Compile.CopySrcs` compiler
+      extra_dirs: extra_dirs(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -21,14 +27,17 @@ defmodule EMQX.MixProject do
   # Run "mix help compile.app" to learn about applications
   def application do
     [
-      extra_applications: [:public_key, :ssl],
+      ## FIXME!!! go though emqx.app.src and add missing stuff...
+      extra_applications: [:public_key, :ssl, :os_mon, :logger, :mnesia] ++ UMP.extra_applications(),
       mod: {:emqx_app, []}
     ]
   end
 
   def deps() do
+    ## FIXME!!! go though emqx.app.src and add missing stuff...
     [
       {:emqx_utils, in_umbrella: true},
+      {:emqx_ds_backends, in_umbrella: true},
 
       {:ekka, github: "emqx/ekka", tag: "0.19.3", override: true},
       {:esockd, github: "emqx/esockd", tag: "5.11.2"},
@@ -36,9 +45,15 @@ defmodule EMQX.MixProject do
       {:hocon, github: "emqx/hocon", tag: "0.42.2", override: true},
       {:lc, github: "emqx/lc", tag: "0.3.2", override: true},
       {:ranch, github: "emqx/ranch", tag: "1.8.1-emqx", override: true},
-      {:snabbkaffe, github: "kafka4beam/snabbkaffe", tag: "1.0.10", override: true},
-    ] ++ quicer_dep()
+    ] ++ UMP.quicer_dep()
   end
 
-  defp quicer_dep(), do: EMQXUmbrella.MixProject.quicer_dep()
+  defp extra_dirs() do
+    dirs = ["src", "etc"]
+    if UMP.test_env?() do
+      ["test", "integration_test" | dirs]
+    else
+      dirs
+    end
+  end
 end

+ 1 - 1
apps/emqx/test/emqx_bpapi_SUITE.erl

@@ -21,7 +21,7 @@
 
 -include_lib("common_test/include/ct.hrl").
 -include_lib("stdlib/include/assert.hrl").
--include_lib("emqx/src/bpapi/emqx_bpapi.hrl").
+-include("../src/bpapi/emqx_bpapi.hrl").
 
 all() -> emqx_common_test_helpers:all(?MODULE).
 

+ 1 - 0
apps/emqx/test/emqx_common_test_helpers.erl

@@ -248,6 +248,7 @@ render_and_load_app_config(App, Opts) ->
             %% turn throw into error
             error({Conf, E, St})
     end.
+
 do_render_app_config(App, Schema, ConfigFile, Opts) ->
     %% copy acl_conf must run before read_schema_configs
     copy_acl_conf(),

+ 9 - 2
apps/emqx/test/emqx_cth_cluster.erl

@@ -391,7 +391,14 @@ node_init(#{name := Node, work_dir := WorkDir}) ->
     _ = share_load_module(Node, cthr),
     %% Enable snabbkaffe trace forwarding
     ok = snabbkaffe:forward_trace(Node),
-    when_cover_enabled(fun() -> {ok, _} = cover:start([Node]) end),
+    when_cover_enabled(fun() ->
+        case cover:start([Node]) of
+            {ok, _} ->
+                ok;
+            {error, {already_started, _}} ->
+                ok
+        end
+    end),
     ok.
 
 %% Returns 'true' if this node should appear in running nodes list.
@@ -456,7 +463,7 @@ stop(Nodes) ->
 
 stop_node(Name) ->
     Node = node_name(Name),
-    when_cover_enabled(fun() -> cover:flush([Node]) end),
+    when_cover_enabled(fun() -> ok = cover:flush([Node]) end),
     ok = emqx_cth_peer:stop(Node).
 
 %% Ports

+ 4 - 4
apps/emqx/test/emqx_cth_suite.erl

@@ -71,6 +71,7 @@
 -export([start_app/3]).
 -export([stop_apps/1]).
 
+-export([default_config/2]).
 -export([merge_appspec/2]).
 -export([merge_config/2]).
 
@@ -243,6 +244,7 @@ log_appspec(App, #{}) ->
 
 spec_fmt(fc, config) -> "~n~ts";
 spec_fmt(fc, _) -> "~p";
+spec_fmt(ffun, {config, false}) -> "false (don't inhibit config loader)";
 spec_fmt(ffun, {config, C}) -> render_config(C);
 spec_fmt(ffun, {_, X}) -> X.
 
@@ -349,6 +351,7 @@ default_appspec(emqx_conf, SuiteOpts) ->
             data_dir => unicode:characters_to_binary(maps:get(work_dir, SuiteOpts, "data"))
         }
     },
+    SharedApps = maps:get(emqx_conf_shared_apps, SuiteOpts, [emqx, emqx_auth]),
     % NOTE
     % Since `emqx_conf_schema` manages config for a lot of applications, it's good to include
     % their defaults as well.
@@ -357,10 +360,7 @@ default_appspec(emqx_conf, SuiteOpts) ->
             emqx_utils_maps:deep_merge(Acc, default_config(App, SuiteOpts))
         end,
         Config,
-        [
-            emqx,
-            emqx_auth
-        ]
+        SharedApps
     ),
     #{
         config => SharedConfig,

+ 1 - 1
apps/emqx/test/emqx_persistent_session_ds_router_SUITE.erl

@@ -19,7 +19,7 @@
 -compile(export_all).
 -compile(nowarn_export_all).
 
--include_lib("emqx/src/emqx_persistent_session_ds/emqx_ps_ds_int.hrl").
+-include("../src/emqx_persistent_session_ds/emqx_ps_ds_int.hrl").
 -include_lib("eunit/include/eunit.hrl").
 -include_lib("common_test/include/ct.hrl").
 

+ 4 - 2
apps/emqx_audit/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXAudit.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_audit,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,7 +18,7 @@ defmodule EMQXAudit.MixProject do
   end
 
   def application do
-    [extra_applications: [], mod: {:emqx_audit_app, []}]
+    [extra_applications: UMP.extra_applications(), mod: {:emqx_audit_app, []}]
   end
 
   def deps() do

+ 26 - 12
apps/emqx_audit/test/emqx_audit_api_SUITE.erl

@@ -18,6 +18,7 @@
 -compile(nowarn_export_all).
 
 -include_lib("eunit/include/eunit.hrl").
+-include_lib("common_test/include/ct.hrl").
 
 all() ->
     [
@@ -54,18 +55,27 @@ common_tests() ->
 }).
 
 init_per_suite(Config) ->
-    _ = application:load(emqx_conf),
-    emqx_config:erase_all(),
-    emqx_mgmt_api_test_util:init_suite([emqx_ctl, emqx_conf, emqx_audit]),
-    ok = emqx_common_test_helpers:load_config(emqx_enterprise_schema, ?CONF_DEFAULT),
-    emqx_config:save_schema_mod_and_names(emqx_enterprise_schema),
-    ok = emqx_config_logger:refresh_config(),
-    application:set_env(emqx, boot_modules, []),
-    emqx_conf_cli:load(),
-    Config.
+    Apps = emqx_cth_suite:start(
+        [
+            emqx_ctl,
+            emqx,
+            {emqx_conf, #{
+                config => ?CONF_DEFAULT,
+                schema_mod => emqx_enterprise_schema
+            }},
+            emqx_modules,
+            emqx_audit,
+            emqx_management,
+            emqx_mgmt_api_test_util:emqx_dashboard()
+        ],
+        #{work_dir => emqx_cth_suite:work_dir(Config)}
+    ),
+    [{apps, Apps} | Config].
 
-end_per_suite(_) ->
-    emqx_mgmt_api_test_util:end_suite([emqx_audit, emqx_conf, emqx_ctl]).
+end_per_suite(Config) ->
+    Apps = ?config(apps, Config),
+    ok = emqx_cth_suite:stop(Apps),
+    ok.
 
 t_http_api(_) ->
     process_flag(trap_exit, true),
@@ -164,6 +174,7 @@ t_cli(_Config) ->
         ],
         Data
     ),
+    [ShowLogEntry] = Data,
     %% check create at is valid
     [#{<<"created_at">> := CreateAtRaw}] = Data,
     CreateAt = calendar:rfc3339_to_system_time(binary_to_list(CreateAtRaw), [{unit, microsecond}]),
@@ -172,7 +183,10 @@ t_cli(_Config) ->
     %% check cli filter
     {ok, Res1} = emqx_mgmt_api_test_util:request_api(get, AuditPath, "from=cli", AuthHeader),
     #{<<"data">> := Data1} = emqx_utils_json:decode(Res1, [return_maps]),
-    ?assertEqual(Data, Data1),
+    ?assertMatch(
+        [ShowLogEntry, #{<<"operation_type">> := <<"emqx">>, <<"args">> := [<<"start">>]}],
+        Data1
+    ),
     {ok, Res2} = emqx_mgmt_api_test_util:request_api(
         get, AuditPath, "from=erlang_console", AuthHeader
     ),

+ 17 - 5
apps/emqx_auth/mix.exs

@@ -1,13 +1,18 @@
 defmodule EMQXAuth.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_auth,
       version: "0.1.0",
       build_path: "../../_build",
+      compilers: Mix.compilers() ++ [:copy_srcs],
+      # used by our `Mix.Tasks.Compile.CopySrcs` compiler
+      extra_dirs: extra_dirs(),
       # config_path: "../../config/config.exs",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -18,15 +23,22 @@ defmodule EMQXAuth.MixProject do
 
   # Run "mix help compile.app" to learn about applications
   def application do
-    [
-      extra_applications: [],
-      mod: {:emqx_auth_app, []}
-    ]
+    [extra_applications: UMP.extra_applications(), mod: {:emqx_auth_app, []}]
   end
 
   def deps() do
     [
       {:emqx, in_umbrella: true},
+      {:emqx_utils, in_umbrella: true}
     ]
   end
+
+  defp extra_dirs() do
+    dirs = ["etc"]
+    if UMP.test_env?() do
+      ["test" | dirs]
+    else
+      dirs
+    end
+  end
 end

+ 22 - 24
apps/emqx_auth/test/emqx_authz/emqx_authz_api_cache_SUITE.erl

@@ -32,32 +32,30 @@ groups() ->
     [].
 
 init_per_suite(Config) ->
-    ok = emqx_mgmt_api_test_util:init_suite(
-        [emqx_conf, emqx_auth],
-        fun set_special_configs/1
+    Apps = emqx_cth_suite:start(
+        [
+            emqx_conf,
+            {emqx_auth, #{
+                config =>
+                    #{
+                        authorization =>
+                            #{
+                                cache => #{enabled => true},
+                                no_match => deny,
+                                sources => []
+                            }
+                    }
+            }},
+            emqx_management,
+            emqx_mgmt_api_test_util:emqx_dashboard()
+        ],
+        #{work_dir => emqx_cth_suite:work_dir(Config)}
     ),
-    Config.
+    [{apps, Apps} | Config].
 
-end_per_suite(_Config) ->
-    {ok, _} = emqx:update_config(
-        [authorization],
-        #{
-            <<"no_match">> => <<"allow">>,
-            <<"cache">> => #{<<"enable">> => <<"true">>},
-            <<"sources">> => []
-        }
-    ),
-    emqx_mgmt_api_test_util:end_suite([emqx_auth, emqx_conf]),
-    ok.
-
-set_special_configs(emqx_dashboard) ->
-    emqx_dashboard_api_test_helpers:set_default_config();
-set_special_configs(emqx_auth) ->
-    {ok, _} = emqx:update_config([authorization, cache, enable], true),
-    {ok, _} = emqx:update_config([authorization, no_match], deny),
-    {ok, _} = emqx:update_config([authorization, sources], []),
-    ok;
-set_special_configs(_App) ->
+end_per_suite(Config) ->
+    Apps = ?config(apps, Config),
+    emqx_cth_suite:stop(Apps),
     ok.
 
 t_clean_cache(_) ->

+ 22 - 25
apps/emqx_auth/test/emqx_authz/emqx_authz_api_settings_SUITE.erl

@@ -30,33 +30,30 @@ groups() ->
     [].
 
 init_per_suite(Config) ->
-    ok = emqx_mgmt_api_test_util:init_suite(
-        [emqx_conf, emqx_auth, emqx_dashboard],
-        fun set_special_configs/1
+    Apps = emqx_cth_suite:start(
+        [
+            emqx_conf,
+            {emqx_auth, #{
+                config =>
+                    #{
+                        authorization =>
+                            #{
+                                cache => #{enabled => true},
+                                no_match => allow,
+                                sources => []
+                            }
+                    }
+            }},
+            emqx_management,
+            emqx_mgmt_api_test_util:emqx_dashboard()
+        ],
+        #{work_dir => emqx_cth_suite:work_dir(Config)}
     ),
-    Config.
+    [{apps, Apps} | Config].
 
-end_per_suite(_Config) ->
-    {ok, _} = emqx:update_config(
-        [authorization],
-        #{
-            <<"no_match">> => <<"allow">>,
-            <<"cache">> => #{<<"enable">> => <<"true">>},
-            <<"sources">> => []
-        }
-    ),
-    ok = stop_apps([emqx_resource]),
-    emqx_mgmt_api_test_util:end_suite([emqx_auth, emqx_conf]),
-    ok.
-
-set_special_configs(emqx_dashboard) ->
-    emqx_dashboard_api_test_helpers:set_default_config();
-set_special_configs(emqx_auth) ->
-    {ok, _} = emqx:update_config([authorization, cache, enable], false),
-    {ok, _} = emqx:update_config([authorization, no_match], deny),
-    {ok, _} = emqx:update_config([authorization, sources], []),
-    ok;
-set_special_configs(_App) ->
+end_per_suite(Config) ->
+    Apps = ?config(apps, Config),
+    emqx_cth_suite:stop(Apps),
     ok.
 
 %%------------------------------------------------------------------------------

+ 24 - 24
apps/emqx_auth/test/emqx_authz/emqx_authz_rule_SUITE.erl

@@ -34,22 +34,30 @@ all() ->
     emqx_common_test_helpers:all(?MODULE).
 
 init_per_suite(Config) ->
-    ok = emqx_common_test_helpers:start_apps(
-        [emqx_conf, emqx_auth],
-        fun set_special_configs/1
-    ),
-    Config.
-
-end_per_suite(_Config) ->
-    {ok, _} = emqx:update_config(
-        [authorization],
-        #{
-            <<"no_match">> => <<"allow">>,
-            <<"cache">> => #{<<"enable">> => <<"true">>},
-            <<"sources">> => []
-        }
-    ),
-    emqx_common_test_helpers:stop_apps([emqx_auth, emqx_conf]),
+    Apps = emqx_cth_suite:start(
+        [
+            emqx_conf,
+            {emqx_auth, #{
+                config =>
+                    #{
+                        authorization =>
+                            #{
+                                cache => #{enabled => false},
+                                no_match => deny,
+                                sources => []
+                            }
+                    }
+            }},
+            emqx_management,
+            emqx_mgmt_api_test_util:emqx_dashboard()
+        ],
+        #{work_dir => emqx_cth_suite:work_dir(Config)}
+    ),
+    [{apps, Apps} | Config].
+
+end_per_suite(Config) ->
+    Apps = ?config(apps, Config),
+    emqx_cth_suite:stop(Apps),
     ok.
 
 init_per_testcase(_TestCase, Config) ->
@@ -58,14 +66,6 @@ end_per_testcase(_TestCase, _Config) ->
     _ = emqx_authz:set_feature_available(rich_actions, true),
     ok.
 
-set_special_configs(emqx_auth) ->
-    {ok, _} = emqx:update_config([authorization, cache, enable], false),
-    {ok, _} = emqx:update_config([authorization, no_match], deny),
-    {ok, _} = emqx:update_config([authorization, sources], []),
-    ok;
-set_special_configs(_App) ->
-    ok.
-
 t_compile(_) ->
     % NOTE
     % Some of the following testcase are relying on the internal representation of

+ 4 - 2
apps/emqx_auth_ext/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXAuthExt.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_auth_ext,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,7 +18,7 @@ defmodule EMQXAuthExt.MixProject do
   end
 
   def application do
-    [extra_applications: []]
+    [extra_applications: UMP.extra_applications()]
   end
 
   def deps() do

+ 7 - 7
apps/emqx_auth_http/mix.exs

@@ -1,5 +1,6 @@
 defmodule EMQXAuthHTTP.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
@@ -7,7 +8,8 @@ defmodule EMQXAuthHTTP.MixProject do
       version: "0.1.0",
       build_path: "../../_build",
       # config_path: "../../config/config.exs",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -18,18 +20,16 @@ defmodule EMQXAuthHTTP.MixProject do
 
   # Run "mix help compile.app" to learn about applications
   def application do
-    [
-      extra_applications: [],
-      mod: {:emqx_auth_http_app, []}
-    ]
+    [extra_applications: UMP.extra_applications(), mod: {:emqx_auth_http_app, []}]
   end
 
   def deps() do
     [
       {:emqx, in_umbrella: true},
       {:emqx_auth, in_umbrella: true},
-      {:hocon, github: "emqx/hocon", tag: "0.42.2", override: true},
-      {:snabbkaffe, github: "kafka4beam/snabbkaffe", tag: "1.0.10", override: true},
+      {:emqx_resource, in_umbrella: true},
+      {:emqx_connector, in_umbrella: true},
+      {:hocon, github: "emqx/hocon", tag: "0.42.2", override: true}
     ]
   end
 end

+ 5 - 6
apps/emqx_auth_jwt/mix.exs

@@ -1,5 +1,6 @@
 defmodule EMQXAuthJWT.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
@@ -7,7 +8,8 @@ defmodule EMQXAuthJWT.MixProject do
       version: "0.1.0",
       build_path: "../../_build",
       # config_path: "../../config/config.exs",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -18,10 +20,7 @@ defmodule EMQXAuthJWT.MixProject do
 
   # Run "mix help compile.app" to learn about applications
   def application do
-    [
-      extra_applications: [],
-      mod: {:emqx_auth_jwt_app, []}
-    ]
+    [extra_applications: UMP.extra_applications(), mod: {:emqx_auth_jwt_app, []}]
   end
 
   def deps() do
@@ -29,7 +28,7 @@ defmodule EMQXAuthJWT.MixProject do
       {:emqx, in_umbrella: true},
       {:emqx_auth, in_umbrella: true},
       {:emqx_resource, in_umbrella: true},
-      {:jose, github: "potatosalad/erlang-jose", tag: "1.11.2"},
+      {:jose, github: "potatosalad/erlang-jose", tag: "1.11.2"}
     ]
   end
 end

+ 5 - 5
apps/emqx_auth_ldap/mix.exs

@@ -1,5 +1,6 @@
 defmodule EMQXAuthLDAP.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
@@ -7,7 +8,8 @@ defmodule EMQXAuthLDAP.MixProject do
       version: "0.1.0",
       build_path: "../../_build",
       # config_path: "../../config/config.exs",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -18,16 +20,14 @@ defmodule EMQXAuthLDAP.MixProject do
 
   # Run "mix help compile.app" to learn about applications
   def application do
-    [
-      extra_applications: [:eldap],
-      mod: {:emqx_auth_ldap_app, []}
-    ]
+    [extra_applications: [:eldap], mod: {:emqx_auth_ldap_app, []}]
   end
 
   def deps() do
     [
       {:emqx, in_umbrella: true},
       {:emqx_auth, in_umbrella: true},
+      {:emqx_ldap, in_umbrella: true},
     ]
   end
 end

+ 13 - 11
apps/emqx_auth_ldap/test/emqx_authz_ldap_SUITE.erl

@@ -33,25 +33,27 @@ groups() ->
     emqx_authz_test_lib:table_groups(t_run_case, cases()).
 
 init_per_suite(Config) ->
-    ok = stop_apps([emqx_resource]),
     case emqx_common_test_helpers:is_tcp_server_available(?LDAP_HOST, ?LDAP_DEFAULT_PORT) of
         true ->
-            ok = emqx_common_test_helpers:start_apps(
-                [emqx_conf, emqx_auth, emqx_auth_ldap],
-                fun set_special_configs/1
+            Apps = emqx_cth_suite:start(
+                [
+                    emqx,
+                    emqx_conf,
+                    emqx_auth,
+                    emqx_auth_ldap
+                ],
+                #{work_dir => emqx_cth_suite:work_dir(Config)}
             ),
-            ok = start_apps([emqx_resource]),
             ok = create_ldap_resource(),
-            Config;
+            [{apps, Apps} | Config];
         false ->
             {skip, no_ldap}
     end.
 
-end_per_suite(_Config) ->
-    ok = emqx_authz_test_lib:restore_authorizers(),
-    ok = emqx_resource:remove_local(?LDAP_RESOURCE),
-    ok = stop_apps([emqx_resource]),
-    ok = emqx_common_test_helpers:stop_apps([emqx_conf, emqx_auth, emqx_auth_ldap]).
+end_per_suite(Config) ->
+    Apps = ?config(apps, Config),
+    emqx_cth_suite:stop(Apps),
+    ok.
 
 init_per_group(Group, Config) ->
     [{test_case, emqx_authz_test_lib:get_case(Group, cases())} | Config].

+ 5 - 9
apps/emqx_auth_mnesia/mix.exs

@@ -1,5 +1,6 @@
 defmodule EMQXAuthMnesia.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
@@ -7,7 +8,8 @@ defmodule EMQXAuthMnesia.MixProject do
       version: "0.1.0",
       build_path: "../../_build",
       # config_path: "../../config/config.exs",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -18,16 +20,10 @@ defmodule EMQXAuthMnesia.MixProject do
 
   # Run "mix help compile.app" to learn about applications
   def application do
-    [
-      extra_applications: [],
-      mod: {:emqx_auth_mnesia_app, []}
-    ]
+    [extra_applications: UMP.extra_applications(), mod: {:emqx_auth_mnesia_app, []}]
   end
 
   def deps() do
-    [
-      {:emqx, in_umbrella: true},
-      {:emqx_auth, in_umbrella: true},
-    ]
+    [{:emqx, in_umbrella: true}, {:emqx_auth, in_umbrella: true}]
   end
 end

+ 1 - 0
apps/emqx_auth_mnesia/test/emqx_authn_api_mnesia_SUITE.erl

@@ -51,6 +51,7 @@ end_per_testcase(_, Config) ->
 init_per_suite(Config) ->
     Apps = emqx_cth_suite:start(
         [
+            emqx_ctl,
             emqx,
             emqx_conf,
             emqx_auth,

+ 1 - 1
apps/emqx_auth_mnesia/test/emqx_authz_mnesia_SUITE.erl

@@ -18,7 +18,7 @@
 -compile(nowarn_export_all).
 -compile(export_all).
 
--include_lib("emqx_authz.hrl").
+-include_lib("emqx_auth/include/emqx_authz.hrl").
 
 -include_lib("eunit/include/eunit.hrl").
 -include_lib("common_test/include/ct.hrl").

+ 5 - 5
apps/emqx_auth_mongodb/mix.exs

@@ -1,5 +1,6 @@
 defmodule EMQXAuthMongoDB.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
@@ -7,7 +8,8 @@ defmodule EMQXAuthMongoDB.MixProject do
       version: "0.1.0",
       build_path: "../../_build",
       # config_path: "../../config/config.exs",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -18,16 +20,14 @@ defmodule EMQXAuthMongoDB.MixProject do
 
   # Run "mix help compile.app" to learn about applications
   def application do
-    [
-      extra_applications: [],
-      mod: {:emqx_auth_mongodb_app, []}
-    ]
+    [extra_applications: UMP.extra_applications(), mod: {:emqx_auth_mongodb_app, []}]
   end
 
   def deps() do
     [
       {:emqx, in_umbrella: true},
       {:emqx_auth, in_umbrella: true},
+      {:emqx_mongodb, in_umbrella: true},
     ]
   end
 end

+ 1 - 1
apps/emqx_auth_mongodb/test/emqx_authn_mongodb_SUITE.erl

@@ -19,7 +19,7 @@
 -compile(nowarn_export_all).
 -compile(export_all).
 
--include_lib("emqx_connector/include/emqx_connector.hrl").
+-include("../../emqx_connector/include/emqx_connector.hrl").
 -include_lib("emqx_auth/include/emqx_authn.hrl").
 -include_lib("eunit/include/eunit.hrl").
 -include_lib("common_test/include/ct.hrl").

+ 1 - 1
apps/emqx_auth_mongodb/test/emqx_authn_mongodb_tls_SUITE.erl

@@ -19,7 +19,7 @@
 -compile(nowarn_export_all).
 -compile(export_all).
 
--include_lib("emqx_connector/include/emqx_connector.hrl").
+-include("../../emqx_connector/include/emqx_connector.hrl").
 -include_lib("emqx_auth/include/emqx_authn.hrl").
 -include_lib("eunit/include/eunit.hrl").
 -include_lib("common_test/include/ct.hrl").

+ 1 - 1
apps/emqx_auth_mongodb/test/emqx_authz_mongodb_SUITE.erl

@@ -19,7 +19,7 @@
 -compile(export_all).
 
 -include_lib("emqx_auth/include/emqx_authz.hrl").
--include_lib("emqx_connector/include/emqx_connector.hrl").
+-include("../../emqx_connector/include/emqx_connector.hrl").
 -include_lib("eunit/include/eunit.hrl").
 -include_lib("common_test/include/ct.hrl").
 -include_lib("emqx/include/emqx_placeholder.hrl").

+ 5 - 5
apps/emqx_auth_mysql/mix.exs

@@ -1,5 +1,6 @@
 defmodule EMQXAuthMySQL.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
@@ -7,7 +8,8 @@ defmodule EMQXAuthMySQL.MixProject do
       version: "0.1.0",
       build_path: "../../_build",
       # config_path: "../../config/config.exs",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -18,16 +20,14 @@ defmodule EMQXAuthMySQL.MixProject do
 
   # Run "mix help compile.app" to learn about applications
   def application do
-    [
-      extra_applications: [],
-      mod: {:emqx_auth_mysql_app, []}
-    ]
+    [extra_applications: UMP.extra_applications(), mod: {:emqx_auth_mysql_app, []}]
   end
 
   def deps() do
     [
       {:emqx, in_umbrella: true},
       {:emqx_auth, in_umbrella: true},
+      {:emqx_mysql, in_umbrella: true}
     ]
   end
 end

+ 1 - 1
apps/emqx_auth_mysql/test/emqx_authn_mysql_SUITE.erl

@@ -19,7 +19,7 @@
 -compile(nowarn_export_all).
 -compile(export_all).
 
--include_lib("emqx_connector/include/emqx_connector.hrl").
+-include("../../emqx_connector/include/emqx_connector.hrl").
 -include_lib("emqx_auth/include/emqx_authn.hrl").
 -include_lib("eunit/include/eunit.hrl").
 -include_lib("common_test/include/ct.hrl").

+ 1 - 1
apps/emqx_auth_mysql/test/emqx_authn_mysql_tls_SUITE.erl

@@ -19,7 +19,7 @@
 -compile(nowarn_export_all).
 -compile(export_all).
 
--include_lib("emqx_connector/include/emqx_connector.hrl").
+-include("../../emqx_connector/include/emqx_connector.hrl").
 -include_lib("emqx_auth/include/emqx_authn.hrl").
 -include_lib("eunit/include/eunit.hrl").
 -include_lib("common_test/include/ct.hrl").

+ 1 - 1
apps/emqx_auth_mysql/test/emqx_authz_mysql_SUITE.erl

@@ -18,7 +18,7 @@
 -compile(nowarn_export_all).
 -compile(export_all).
 
--include("emqx_connector.hrl").
+-include("../../emqx_connector/include/emqx_connector.hrl").
 -include_lib("emqx_auth/include/emqx_authz.hrl").
 -include_lib("eunit/include/eunit.hrl").
 -include_lib("common_test/include/ct.hrl").

+ 5 - 6
apps/emqx_auth_postgresql/mix.exs

@@ -1,5 +1,6 @@
 defmodule EMQXAuthPostgreSQL.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
@@ -7,7 +8,8 @@ defmodule EMQXAuthPostgreSQL.MixProject do
       version: "0.1.0",
       build_path: "../../_build",
       # config_path: "../../config/config.exs",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -18,17 +20,14 @@ defmodule EMQXAuthPostgreSQL.MixProject do
 
   # Run "mix help compile.app" to learn about applications
   def application do
-    [
-      extra_applications: [],
-      mod: {:emqx_auth_postgresql_app, []}
-    ]
+    [extra_applications: UMP.extra_applications(), mod: {:emqx_auth_postgresql_app, []}]
   end
 
   def deps() do
     [
       {:emqx, in_umbrella: true},
       {:emqx_auth, in_umbrella: true},
-      {:epgsql, github: "emqx/epgsql", tag: "4.7.1.2", override: true},
+      {:emqx_postgresql, in_umbrella: true},
     ]
   end
 end

+ 2 - 2
apps/emqx_auth_postgresql/test/emqx_authn_postgresql_SUITE.erl

@@ -19,7 +19,7 @@
 -compile(nowarn_export_all).
 -compile(export_all).
 
--include_lib("emqx_postgresql/include/emqx_postgresql.hrl").
+-include_lib("../../emqx_postgresql/include/emqx_postgresql.hrl").
 -include_lib("emqx_auth/include/emqx_authn.hrl").
 -include_lib("eunit/include/eunit.hrl").
 -include_lib("common_test/include/ct.hrl").
@@ -196,7 +196,7 @@ test_user_auth(#{
         ?GLOBAL
     ).
 
-t_authenticate_disabled_prepared_statements(Config) ->
+t_authenticate_disabled_prepared_statements(_Config) ->
     ResConfig = maps:merge(pgsql_config(), #{disable_prepared_statements => true}),
     {ok, _} = emqx_resource:recreate_local(?PGSQL_RESOURCE, emqx_postgresql, ResConfig),
     on_exit(fun() ->

+ 1 - 1
apps/emqx_auth_postgresql/test/emqx_authn_postgresql_tls_SUITE.erl

@@ -19,7 +19,7 @@
 -compile(nowarn_export_all).
 -compile(export_all).
 
--include_lib("emqx_postgresql/include/emqx_postgresql.hrl").
+-include_lib("../../emqx_postgresql/include/emqx_postgresql.hrl").
 -include_lib("emqx_auth/include/emqx_authn.hrl").
 -include_lib("eunit/include/eunit.hrl").
 -include_lib("common_test/include/ct.hrl").

+ 1 - 1
apps/emqx_auth_postgresql/test/emqx_authz_postgresql_SUITE.erl

@@ -18,7 +18,7 @@
 -compile(nowarn_export_all).
 -compile(export_all).
 
--include_lib("emqx_postgresql/include/emqx_postgresql.hrl").
+-include_lib("../../emqx_postgresql/include/emqx_postgresql.hrl").
 -include_lib("emqx_auth/include/emqx_authz.hrl").
 -include_lib("eunit/include/eunit.hrl").
 -include_lib("common_test/include/ct.hrl").

+ 5 - 5
apps/emqx_auth_redis/mix.exs

@@ -1,5 +1,6 @@
 defmodule EMQXAuthRedis.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
@@ -7,7 +8,8 @@ defmodule EMQXAuthRedis.MixProject do
       version: "0.1.0",
       build_path: "../../_build",
       # config_path: "../../config/config.exs",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -18,16 +20,14 @@ defmodule EMQXAuthRedis.MixProject do
 
   # Run "mix help compile.app" to learn about applications
   def application do
-    [
-      extra_applications: [],
-      mod: {:emqx_auth_redis_app, []}
-    ]
+    [extra_applications: UMP.extra_applications(), mod: {:emqx_auth_redis_app, []}]
   end
 
   def deps() do
     [
       {:emqx, in_umbrella: true},
       {:emqx_auth, in_umbrella: true},
+      {:emqx_redis, in_umbrella: true}
     ]
   end
 end

+ 1 - 1
apps/emqx_auth_redis/test/emqx_authn_redis_SUITE.erl

@@ -19,7 +19,7 @@
 -compile(nowarn_export_all).
 -compile(export_all).
 
--include_lib("emqx_connector/include/emqx_connector.hrl").
+-include("../../emqx_connector/include/emqx_connector.hrl").
 -include_lib("emqx_auth/include/emqx_authn.hrl").
 -include_lib("eunit/include/eunit.hrl").
 -include_lib("common_test/include/ct.hrl").

+ 1 - 1
apps/emqx_auth_redis/test/emqx_authz_redis_SUITE.erl

@@ -19,7 +19,7 @@
 -compile(nowarn_export_all).
 -compile(export_all).
 
--include("emqx_connector.hrl").
+-include("../../emqx_connector/include/emqx_connector.hrl").
 -include_lib("emqx_auth/include/emqx_authz.hrl").
 -include_lib("eunit/include/eunit.hrl").
 -include_lib("common_test/include/ct.hrl").

+ 4 - 2
apps/emqx_auto_subscribe/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXAutoSubscribe.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_auto_subscribe,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,7 +18,7 @@ defmodule EMQXAutoSubscribe.MixProject do
   end
 
   def application do
-    [extra_applications: [], mod: {:emqx_auto_subscribe_app, []}]
+    [extra_applications: UMP.extra_applications(), mod: {:emqx_auto_subscribe_app, []}]
   end
 
   def deps() do

+ 43 - 47
apps/emqx_auto_subscribe/test/emqx_auto_subscribe_SUITE.erl

@@ -19,8 +19,7 @@
 -compile(nowarn_export_all).
 
 -include_lib("eunit/include/eunit.hrl").
-
--define(APP, emqx_auto_subscribe).
+-include_lib("common_test/include/ct.hrl").
 
 -define(TOPIC_C, <<"/c/${clientid}">>).
 -define(TOPIC_U, <<"/u/${username}">>).
@@ -44,8 +43,6 @@ all() ->
     emqx_common_test_helpers:all(?MODULE).
 
 init_per_suite(Config) ->
-    mria:start(),
-    application:stop(?APP),
     meck:new(emqx_schema, [non_strict, passthrough, no_history, no_link]),
     meck:expect(emqx_schema, fields, fun
         ("auto_subscribe") ->
@@ -60,43 +57,45 @@ init_per_suite(Config) ->
     meck:expect(emqx_resource, update, fun(_, _, _, _) -> {ok, meck_data} end),
     meck:expect(emqx_resource, remove, fun(_) -> ok end),
 
-    application:load(emqx_dashboard),
-    application:load(?APP),
-    ok = emqx_common_test_helpers:load_config(
-        emqx_auto_subscribe_schema,
-        <<
-            "auto_subscribe {\n"
-            "            topics = [\n"
-            "                {\n"
-            "                    topic = \"/c/${clientid}\"\n"
-            "                },\n"
-            "                {\n"
-            "                    topic = \"/u/${username}\"\n"
-            "                },\n"
-            "                {\n"
-            "                    topic = \"/h/${host}\"\n"
-            "                },\n"
-            "                {\n"
-            "                    topic = \"/p/${port}\"\n"
-            "                },\n"
-            "                {\n"
-            "                    topic = \"/client/${clientid}/username/${username}/host/${host}/port/${port}\"\n"
-            "                },\n"
-            "                {\n"
-            "                    topic = \"/topic/simple\"\n"
-            "                    qos   = 1\n"
-            "                    rh    = 0\n"
-            "                    rap   = 0\n"
-            "                    nl    = 0\n"
-            "                }\n"
-            "            ]\n"
-            "        }"
-        >>
-    ),
-    emqx_mgmt_api_test_util:init_suite(
-        [emqx_conf, ?APP]
+    ASCfg = <<
+        "auto_subscribe {\n"
+        "            topics = [\n"
+        "                {\n"
+        "                    topic = \"/c/${clientid}\"\n"
+        "                },\n"
+        "                {\n"
+        "                    topic = \"/u/${username}\"\n"
+        "                },\n"
+        "                {\n"
+        "                    topic = \"/h/${host}\"\n"
+        "                },\n"
+        "                {\n"
+        "                    topic = \"/p/${port}\"\n"
+        "                },\n"
+        "                {\n"
+        "                    topic = \"/client/${clientid}/username/${username}/host/${host}/port/${port}\"\n"
+        "                },\n"
+        "                {\n"
+        "                    topic = \"/topic/simple\"\n"
+        "                    qos   = 1\n"
+        "                    rh    = 0\n"
+        "                    rap   = 0\n"
+        "                    nl    = 0\n"
+        "                }\n"
+        "            ]\n"
+        "        }"
+    >>,
+    Apps = emqx_cth_suite:start(
+        [
+            emqx,
+            emqx_conf,
+            {emqx_auto_subscribe, ASCfg},
+            emqx_management,
+            emqx_mgmt_api_test_util:emqx_dashboard()
+        ],
+        #{work_dir => emqx_cth_suite:work_dir(Config)}
     ),
-    Config.
+    [{apps, Apps} | Config].
 
 init_per_testcase(t_get_basic_usage_info, Config) ->
     {ok, _} = emqx_auto_subscribe:update([]),
@@ -119,13 +118,10 @@ topic_config(T) ->
         nl => 0
     }.
 
-end_per_suite(_) ->
-    application:unload(emqx_management),
-    application:unload(emqx_conf),
-    application:unload(?APP),
-    meck:unload(emqx_resource),
-    meck:unload(emqx_schema),
-    emqx_mgmt_api_test_util:end_suite([emqx_conf, ?APP]).
+end_per_suite(Config) ->
+    Apps = ?config(apps, Config),
+    emqx_cth_suite:stop(Apps),
+    ok.
 
 t_auto_subscribe(_) ->
     emqx_auto_subscribe:update([#{<<"topic">> => Topic} || Topic <- ?TOPICS]),

+ 17 - 5
apps/emqx_bridge/mix.exs

@@ -1,13 +1,18 @@
 defmodule EMQXBridge.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge,
       version: "0.1.0",
       build_path: "../../_build",
+      compilers: Mix.compilers() ++ [:copy_srcs],
+      # used by our `Mix.Tasks.Compile.CopySrcs` compiler
+      extra_dirs: extra_dirs(),
       # config_path: "../../config/config.exs",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -18,16 +23,23 @@ defmodule EMQXBridge.MixProject do
 
   # Run "mix help compile.app" to learn about applications
   def application do
-    [
-      extra_applications: [],
-      mod: {:emqx_bridge_app, []}
-    ]
+    [extra_applications: UMP.extra_applications(), mod: {:emqx_bridge_app, []}]
   end
 
   def deps() do
     [
       {:emqx, in_umbrella: true},
       {:emqx_resource, in_umbrella: true},
+      {:emqx_connector, in_umbrella: true},
     ]
   end
+
+  defp extra_dirs() do
+    dirs = []
+    if UMP.test_env?() do
+      ["test" | dirs]
+    else
+      dirs
+    end
+  end
 end

+ 9 - 11
apps/emqx_bridge/test/emqx_bridge_v2_testlib.erl

@@ -22,25 +22,22 @@ init_per_suite(Config, Apps) ->
     [{start_apps, Apps} | Config].
 
 end_per_suite(Config) ->
-    delete_all_bridges_and_connectors(),
-    emqx_mgmt_api_test_util:end_suite(),
-    ok = emqx_common_test_helpers:stop_apps([emqx_conf]),
-    ok = emqx_connector_test_helpers:stop_apps(lists:reverse(?config(start_apps, Config))),
-    _ = application:stop(emqx_connector),
+    Apps = ?config(apps, Config),
+    emqx_cth_suite:stop(Apps),
     ok.
 
 init_per_group(TestGroup, BridgeType, Config) ->
     ProxyHost = os:getenv("PROXY_HOST", "toxiproxy"),
     ProxyPort = list_to_integer(os:getenv("PROXY_PORT", "8474")),
     emqx_common_test_helpers:reset_proxy(ProxyHost, ProxyPort),
-    application:load(emqx_bridge),
-    ok = emqx_common_test_helpers:start_apps([emqx_conf]),
-    ok = emqx_connector_test_helpers:start_apps(?config(start_apps, Config)),
-    {ok, _} = application:ensure_all_started(emqx_connector),
-    emqx_mgmt_api_test_util:init_suite(),
+    Apps = emqx_cth_suite:start(
+        ?config(start_apps, Config),
+        #{work_dir => emqx_cth_suite:work_dir(Config)}
+    ),
     UniqueNum = integer_to_binary(erlang:unique_integer([positive])),
     MQTTTopic = <<"mqtt/topic/abc", UniqueNum/binary>>,
     [
+        {apps, Apps},
         {proxy_host, ProxyHost},
         {proxy_port, ProxyPort},
         {mqtt_topic, MQTTTopic},
@@ -50,10 +47,11 @@ init_per_group(TestGroup, BridgeType, Config) ->
     ].
 
 end_per_group(Config) ->
+    Apps = ?config(apps, Config),
     ProxyHost = ?config(proxy_host, Config),
     ProxyPort = ?config(proxy_port, Config),
     emqx_common_test_helpers:reset_proxy(ProxyHost, ProxyPort),
-    %    delete_all_bridges(),
+    emqx_cth_suite:stop(Apps),
     ok.
 
 init_per_testcase(TestCase, Config0, BridgeConfigCb) ->

+ 7 - 2
apps/emqx_bridge_azure_blob_storage/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgeAzureBlobStorage.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_azure_blob_storage,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,7 +18,10 @@ defmodule EMQXBridgeAzureBlobStorage.MixProject do
   end
 
   def application do
-    [extra_applications: [], mod: {:emqx_bridge_azure_blob_storage_app, []}]
+    [
+      extra_applications: UMP.extra_applications(),
+      mod: {:emqx_bridge_azure_blob_storage_app, []}
+    ]
   end
 
   def deps() do

+ 5 - 3
apps/emqx_bridge_azure_event_hub/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgeAzureEventHub.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_azure_event_hub,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,16 +18,16 @@ defmodule EMQXBridgeAzureEventHub.MixProject do
   end
 
   def application do
-    [extra_applications: []]
+    [extra_applications: UMP.extra_applications()]
   end
 
   def deps() do
     [
       {:wolff, github: "kafka4beam/wolff", tag: "1.10.4"},
-      ## TODO: remove `mix.exs` from `wolff` and remove this override
       {:kafka_protocol, github: "kafka4beam/kafka_protocol", tag: "4.1.5", override: true},
       {:brod_gssapi, github: "kafka4beam/brod_gssapi", tag: "v0.1.1"},
       {:brod, github: "kafka4beam/brod", tag: "3.18.0"},
+      ## TODO: remove `mix.exs` from `wolff` and remove this override
       ## TODO: remove `mix.exs` from `pulsar` and remove this override
       {:snappyer, "1.2.9", override: true},
       {:emqx_connector, in_umbrella: true, runtime: false},

+ 4 - 2
apps/emqx_bridge_cassandra/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgeCassandra.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_cassandra,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,7 +18,7 @@ defmodule EMQXBridgeCassandra.MixProject do
   end
 
   def application do
-    [extra_applications: []]
+    [extra_applications: UMP.extra_applications()]
   end
 
   def deps() do

+ 1 - 4
apps/emqx_bridge_cassandra/test/emqx_bridge_cassandra_SUITE.erl

@@ -148,8 +148,6 @@ init_per_suite(Config) ->
     Config.
 
 end_per_suite(_Config) ->
-    emqx_mgmt_api_test_util:end_suite(),
-    ok = emqx_common_test_helpers:stop_apps([emqx_bridge, emqx_conf]),
     ok.
 
 init_per_testcase(_Testcase, Config) ->
@@ -191,11 +189,10 @@ common_init(Config0) ->
                     emqx_bridge,
                     emqx_rule_engine,
                     emqx_management,
-                    {emqx_dashboard, "dashboard.listeners.http { enable = true, bind = 18083 }"}
+                    emqx_mgmt_api_test_util:emqx_dashboard()
                 ],
                 #{work_dir => emqx_cth_suite:work_dir(Config0)}
             ),
-            {ok, _Api} = emqx_common_test_http:create_default_app(),
             % Connect to cassnadra directly and create the table
             catch connect_and_drop_table(Config0),
             connect_and_create_table(Config0),

+ 19 - 10
apps/emqx_bridge_cassandra/test/emqx_bridge_cassandra_connector_SUITE.erl

@@ -9,7 +9,7 @@
 
 -include_lib("common_test/include/ct.hrl").
 -include("emqx_bridge_cassandra.hrl").
--include("emqx_connector/include/emqx_connector.hrl").
+-include("../../emqx_connector/include/emqx_connector.hrl").
 -include_lib("eunit/include/eunit.hrl").
 -include_lib("emqx/include/emqx.hrl").
 -include_lib("stdlib/include/assert.hrl").
@@ -53,10 +53,24 @@ cassandra_servers(CassandraHost, CassandraPort) ->
     ).
 
 init_per_suite(Config) ->
-    ok = emqx_common_test_helpers:start_apps([emqx_conf]),
-    ok = emqx_connector_test_helpers:start_apps([emqx_resource]),
-    {ok, _} = application:ensure_all_started(emqx_connector),
-    Config.
+    Apps = emqx_cth_suite:start(
+        [
+            emqx,
+            emqx_conf,
+            emqx_bridge_cassandra,
+            emqx_bridge,
+            emqx_rule_engine,
+            emqx_management,
+            emqx_mgmt_api_test_util:emqx_dashboard()
+        ],
+        #{work_dir => emqx_cth_suite:work_dir(Config)}
+    ),
+    [{apps, Apps} | Config].
+
+end_per_suite(Config) ->
+    Apps = ?config(apps, Config),
+    emqx_cth_suite:stop(Apps),
+    ok.
 
 init_per_group(Group, Config) ->
     {CassandraHost, CassandraPort, AuthOpts} =
@@ -98,11 +112,6 @@ init_per_group(Group, Config) ->
 end_per_group(_Group, _Config) ->
     ok.
 
-end_per_suite(_Config) ->
-    ok = emqx_common_test_helpers:stop_apps([emqx_conf]),
-    ok = emqx_connector_test_helpers:stop_apps([emqx_resource]),
-    _ = application:stop(emqx_connector).
-
 init_per_testcase(_, Config) ->
     Config.
 

+ 4 - 2
apps/emqx_bridge_clickhouse/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgeClickhouse.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_clickhouse,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,7 +18,7 @@ defmodule EMQXBridgeClickhouse.MixProject do
   end
 
   def application do
-    [extra_applications: []]
+    [extra_applications: UMP.extra_applications()]
   end
 
   def deps() do

+ 18 - 8
apps/emqx_bridge_clickhouse/test/emqx_bridge_clickhouse_SUITE.erl

@@ -7,9 +7,9 @@
 -compile(nowarn_export_all).
 -compile(export_all).
 
--define(APP, emqx_bridge_clickhouse).
 -define(CLICKHOUSE_HOST, "clickhouse").
 -define(CLICKHOUSE_PORT, "8123").
+-include_lib("common_test/include/ct.hrl").
 -include_lib("emqx_connector/include/emqx_connector.hrl").
 
 %% See comment in
@@ -25,17 +25,26 @@ init_per_suite(Config) ->
     Port = list_to_integer(clickhouse_port()),
     case emqx_common_test_helpers:is_tcp_server_available(Host, Port) of
         true ->
-            emqx_common_test_helpers:render_and_load_app_config(emqx_conf),
-            ok = emqx_common_test_helpers:start_apps([emqx_conf, emqx_bridge]),
-            ok = emqx_connector_test_helpers:start_apps([emqx_resource, ?APP]),
-            snabbkaffe:fix_ct_logging(),
+            Apps = emqx_cth_suite:start(
+                [
+                    emqx,
+                    emqx_conf,
+                    emqx_bridge_clickhouse,
+                    emqx_connector,
+                    emqx_bridge,
+                    emqx_rule_engine,
+                    emqx_management,
+                    emqx_mgmt_api_test_util:emqx_dashboard()
+                ],
+                #{work_dir => emqx_cth_suite:work_dir(Config)}
+            ),
             %% Create the db table
             Conn = start_clickhouse_connection(),
             % erlang:monitor,sb
             {ok, _, _} = clickhouse:query(Conn, sql_create_database(), #{}),
             {ok, _, _} = clickhouse:query(Conn, sql_create_table(), []),
             clickhouse:query(Conn, sql_find_key(42), []),
-            [{clickhouse_connection, Conn} | Config];
+            [{apps, Apps}, {clickhouse_connection, Conn} | Config];
         false ->
             case os:getenv("IS_CI") of
                 "yes" ->
@@ -74,8 +83,9 @@ start_clickhouse_connection() ->
 end_per_suite(Config) ->
     ClickhouseConnection = proplists:get_value(clickhouse_connection, Config),
     clickhouse:stop(ClickhouseConnection),
-    ok = emqx_connector_test_helpers:stop_apps([?APP, emqx_resource]),
-    ok = emqx_common_test_helpers:stop_apps([emqx_bridge, emqx_conf]).
+    Apps = ?config(apps, Config),
+    emqx_cth_suite:stop(Apps),
+    ok.
 
 init_per_testcase(_, Config) ->
     reset_table(Config),

+ 19 - 7
apps/emqx_bridge_clickhouse/test/emqx_bridge_clickhouse_connector_SUITE.erl

@@ -7,7 +7,7 @@
 -compile(nowarn_export_all).
 -compile(export_all).
 
--include("emqx_connector.hrl").
+-include("../../emqx_connector/include/emqx_connector.hrl").
 -include_lib("eunit/include/eunit.hrl").
 -include_lib("stdlib/include/assert.hrl").
 -include_lib("common_test/include/ct.hrl").
@@ -43,8 +43,19 @@ init_per_suite(Config) ->
     Port = list_to_integer(emqx_bridge_clickhouse_SUITE:clickhouse_port()),
     case emqx_common_test_helpers:is_tcp_server_available(Host, Port) of
         true ->
-            ok = emqx_common_test_helpers:start_apps([emqx_conf]),
-            ok = emqx_connector_test_helpers:start_apps([emqx_resource, ?APP]),
+            Apps = emqx_cth_suite:start(
+                [
+                    emqx,
+                    emqx_conf,
+                    emqx_bridge_clickhouse,
+                    emqx_connector,
+                    emqx_bridge,
+                    emqx_rule_engine,
+                    emqx_management,
+                    emqx_mgmt_api_test_util:emqx_dashboard()
+                ],
+                #{work_dir => emqx_cth_suite:work_dir(Config)}
+            ),
             %% Create the db table
             {ok, Conn} =
                 clickhouse:start_link([
@@ -55,7 +66,7 @@ init_per_suite(Config) ->
                 ]),
             {ok, _, _} = clickhouse:query(Conn, <<"CREATE DATABASE IF NOT EXISTS mqtt">>, #{}),
             clickhouse:stop(Conn),
-            Config;
+            [{apps, Apps} | Config];
         false ->
             case os:getenv("IS_CI") of
                 "yes" ->
@@ -65,9 +76,10 @@ init_per_suite(Config) ->
             end
     end.
 
-end_per_suite(_Config) ->
-    ok = emqx_common_test_helpers:stop_apps([emqx_conf]),
-    ok = emqx_connector_test_helpers:stop_apps([?APP, emqx_resource]).
+end_per_suite(Config) ->
+    Apps = ?config(apps, Config),
+    emqx_cth_suite:stop(Apps),
+    ok.
 
 init_per_testcase(_, Config) ->
     Config.

+ 5 - 3
apps/emqx_bridge_confluent/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgeConfluent.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_confluent,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,16 +18,16 @@ defmodule EMQXBridgeConfluent.MixProject do
   end
 
   def application do
-    [extra_applications: []]
+    [extra_applications: UMP.extra_applications()]
   end
 
   def deps() do
     [
       {:wolff, github: "kafka4beam/wolff", tag: "1.10.4"},
-      ## TODO: remove `mix.exs` from `wolff` and remove this override
       {:kafka_protocol, github: "kafka4beam/kafka_protocol", tag: "4.1.5", override: true},
       {:brod_gssapi, github: "kafka4beam/brod_gssapi", tag: "v0.1.1"},
       {:brod, github: "kafka4beam/brod", tag: "3.18.0"},
+      ## TODO: remove `mix.exs` from `wolff` and remove this override
       ## TODO: remove `mix.exs` from `pulsar` and remove this override
       {:snappyer, "1.2.9", override: true},
       {:emqx_connector, in_umbrella: true, runtime: false},

+ 4 - 2
apps/emqx_bridge_dynamo/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgeDynamo.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_dynamo,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,7 +18,7 @@ defmodule EMQXBridgeDynamo.MixProject do
   end
 
   def application do
-    [extra_applications: []]
+    [extra_applications: UMP.extra_applications()]
   end
 
   def deps() do

+ 16 - 7
apps/emqx_bridge_dynamo/test/emqx_bridge_dynamo_SUITE.erl

@@ -69,14 +69,18 @@ init_per_group(_Group, Config) ->
     Config.
 
 end_per_group(Group, Config) when Group =:= with_batch; Group =:= without_batch ->
+    Apps = ?config(apps, Config),
     ProxyHost = ?config(proxy_host, Config),
     ProxyPort = ?config(proxy_port, Config),
     emqx_common_test_helpers:reset_proxy(ProxyHost, ProxyPort),
+    emqx_cth_suite:stop(Apps),
     ok;
 end_per_group(Group, Config) when Group =:= flaky ->
+    Apps = ?config(apps, Config),
     ProxyHost = ?config(proxy_host, Config),
     ProxyPort = ?config(proxy_port, Config),
     emqx_common_test_helpers:reset_proxy(ProxyHost, ProxyPort),
+    emqx_cth_suite:stop(Apps),
     timer:sleep(1000),
     ok;
 end_per_group(_Group, _Config) ->
@@ -135,18 +139,23 @@ common_init(ConfigT) ->
             ProxyHost = os:getenv("PROXY_HOST", "toxiproxy"),
             ProxyPort = list_to_integer(os:getenv("PROXY_PORT", "8474")),
             emqx_common_test_helpers:reset_proxy(ProxyHost, ProxyPort),
-            % Ensure enterprise bridge module is loaded
-            ok = emqx_common_test_helpers:start_apps([
-                emqx_conf, emqx_resource, emqx_bridge, emqx_rule_engine
-            ]),
-            _ = application:ensure_all_started(erlcloud),
-            _ = emqx_bridge_enterprise:module_info(),
-            emqx_mgmt_api_test_util:init_suite(),
+            Apps = emqx_cth_suite:start(
+                [
+                    emqx_conf,
+                    emqx_bridge_dynamo,
+                    emqx_bridge,
+                    emqx_rule_engine,
+                    emqx_management,
+                    emqx_mgmt_api_test_util:emqx_dashboard()
+                ],
+                #{work_dir => emqx_cth_suite:work_dir(Config0)}
+            ),
             % setup dynamo
             setup_dynamo(Config0),
             {Name, TDConf} = dynamo_config(BridgeType, Config0),
             Config =
                 [
+                    {apps, Apps},
                     {dynamo_config, TDConf},
                     {dynamo_bridge_type, BridgeType},
                     {dynamo_name, Name},

+ 4 - 2
apps/emqx_bridge_es/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgeEs.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_es,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,7 +18,7 @@ defmodule EMQXBridgeEs.MixProject do
   end
 
   def application do
-    [extra_applications: []]
+    [extra_applications: UMP.extra_applications()]
   end
 
   def deps() do

+ 4 - 2
apps/emqx_bridge_gcp_pubsub/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgeGcpPubsub.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_gcp_pubsub,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,7 +18,7 @@ defmodule EMQXBridgeGcpPubsub.MixProject do
   end
 
   def application do
-    [extra_applications: []]
+    [extra_applications: UMP.extra_applications()]
   end
 
   def deps() do

+ 4 - 2
apps/emqx_bridge_greptimedb/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgeGreptimedb.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_greptimedb,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,7 +18,7 @@ defmodule EMQXBridgeGreptimedb.MixProject do
   end
 
   def application do
-    [extra_applications: []]
+    [extra_applications: UMP.extra_applications()]
   end
 
   def deps() do

+ 13 - 9
apps/emqx_bridge_greptimedb/test/emqx_bridge_greptimedb_connector_SUITE.erl

@@ -25,11 +25,17 @@ init_per_suite(Config) ->
     Servers = [{GreptimedbTCPHost, GreptimedbTCPPort}],
     case emqx_common_test_helpers:is_all_tcp_servers_available(Servers) of
         true ->
-            ok = emqx_common_test_helpers:start_apps([emqx_conf]),
-            ok = emqx_connector_test_helpers:start_apps([emqx_resource]),
-            {ok, _} = application:ensure_all_started(emqx_connector),
-            {ok, _} = application:ensure_all_started(greptimedb),
+            Apps = emqx_cth_suite:start(
+                [
+                    emqx,
+                    emqx_conf,
+                    emqx_bridge_greptimedb,
+                    emqx_bridge
+                ],
+                #{work_dir => emqx_cth_suite:work_dir(Config)}
+            ),
             [
+                {apps, Apps},
                 {greptimedb_tcp_host, GreptimedbTCPHost},
                 {greptimedb_tcp_port, GreptimedbTCPPort}
                 | Config
@@ -43,11 +49,9 @@ init_per_suite(Config) ->
             end
     end.
 
-end_per_suite(_Config) ->
-    ok = emqx_common_test_helpers:stop_apps([emqx_conf]),
-    ok = emqx_connector_test_helpers:stop_apps([emqx_resource]),
-    _ = application:stop(emqx_connector),
-    _ = application:stop(greptimedb),
+end_per_suite(Config) ->
+    Apps = ?config(apps, Config),
+    emqx_cth_suite:stop(Apps),
     ok.
 
 init_per_testcase(_, Config) ->

+ 5 - 3
apps/emqx_bridge_hstreamdb/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgeHstreamdb.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_hstreamdb,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,7 +18,7 @@ defmodule EMQXBridgeHstreamdb.MixProject do
   end
 
   def application do
-    [extra_applications: []]
+    [extra_applications: UMP.extra_applications()]
   end
 
   def deps() do
@@ -26,7 +28,7 @@ defmodule EMQXBridgeHstreamdb.MixProject do
       {:emqx, in_umbrella: true},
       {:emqx_utils, in_umbrella: true},
       {:emqx_connector, in_umbrella: true, runtime: false},
-      {:emqx_resource, in_umbrella: true},
+      {:emqx_resource, in_umbrella: true}
     ]
   end
 end

+ 13 - 5
apps/emqx_bridge_hstreamdb/test/emqx_bridge_hstreamdb_SUITE.erl

@@ -100,10 +100,12 @@ init_per_group(_Group, Config) ->
     Config.
 
 end_per_group(Group, Config) when Group =:= with_batch; Group =:= without_batch ->
+    Apps = ?config(apps, Config),
     connect_and_delete_stream(Config),
     ProxyHost = ?config(proxy_host, Config),
     ProxyPort = ?config(proxy_port, Config),
     emqx_common_test_helpers:reset_proxy(ProxyHost, ProxyPort),
+    emqx_cth_suite:stop(Apps),
     ok;
 end_per_group(_Group, _Config) ->
     ok.
@@ -408,11 +410,16 @@ common_init(ConfigT) ->
             ProxyHost = os:getenv("PROXY_HOST", "toxiproxy"),
             ProxyPort = list_to_integer(os:getenv("PROXY_PORT", "8474")),
             emqx_common_test_helpers:reset_proxy(ProxyHost, ProxyPort),
-            % Ensure EE bridge module is loaded
-            ok = emqx_common_test_helpers:start_apps([emqx_conf, emqx_resource, emqx_bridge]),
-            _ = application:ensure_all_started(hstreamdb_erl),
-            _ = emqx_bridge_enterprise:module_info(),
-            emqx_mgmt_api_test_util:init_suite(),
+            Apps = emqx_cth_suite:start(
+                [
+                    emqx_conf,
+                    emqx_bridge_hstreamdb,
+                    emqx_bridge,
+                    emqx_management,
+                    emqx_mgmt_api_test_util:emqx_dashboard()
+                ],
+                #{work_dir => emqx_cth_suite:work_dir(Config0)}
+            ),
             % Connect to hstreamdb directly
             % drop old stream and then create new one
             connect_and_delete_stream(Config0),
@@ -420,6 +427,7 @@ common_init(ConfigT) ->
             {Name, HStreamDBConf} = hstreamdb_config(BridgeType, Config0),
             Config =
                 [
+                    {apps, Apps},
                     {hstreamdb_config, HStreamDBConf},
                     {hstreamdb_bridge_type, BridgeType},
                     {hstreamdb_name, Name},

+ 5 - 4
apps/emqx_bridge_http/mix.exs

@@ -1,5 +1,6 @@
 defmodule EMQXBridgeHTTP.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
@@ -7,7 +8,8 @@ defmodule EMQXBridgeHTTP.MixProject do
       version: "0.1.0",
       build_path: "../../_build",
       # config_path: "../../config/config.exs",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -18,15 +20,14 @@ defmodule EMQXBridgeHTTP.MixProject do
 
   # Run "mix help compile.app" to learn about applications
   def application do
-    [
-      extra_applications: []
-    ]
+    [extra_applications: UMP.extra_applications()]
   end
 
   def deps() do
     [
       {:emqx, in_umbrella: true},
       {:emqx_resource, in_umbrella: true},
+      {:ehttpc, github: "emqx/ehttpc", tag: "0.4.13"}
     ]
   end
 end

+ 4 - 2
apps/emqx_bridge_influxdb/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgeInfluxdb.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_influxdb,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,7 +18,7 @@ defmodule EMQXBridgeInfluxdb.MixProject do
   end
 
   def application do
-    [extra_applications: []]
+    [extra_applications: UMP.extra_applications()]
   end
 
   def deps() do

+ 26 - 23
apps/emqx_bridge_influxdb/test/emqx_bridge_influxdb_SUITE.erl

@@ -53,12 +53,6 @@ init_per_suite(Config) ->
     Config.
 
 end_per_suite(_Config) ->
-    delete_all_bridges(),
-    emqx_mgmt_api_test_util:end_suite(),
-    ok = emqx_connector_test_helpers:stop_apps([
-        emqx_conf, emqx_bridge, emqx_resource, emqx_rule_engine
-    ]),
-    _ = application:stop(emqx_connector),
     ok.
 
 init_per_group(InfluxDBType, Config0) when
@@ -92,10 +86,18 @@ init_per_group(InfluxDBType, Config0) when
             ProxyHost = os:getenv("PROXY_HOST", "toxiproxy"),
             ProxyPort = list_to_integer(os:getenv("PROXY_PORT", "8474")),
             emqx_common_test_helpers:reset_proxy(ProxyHost, ProxyPort),
-            ok = start_apps(),
-            {ok, _} = application:ensure_all_started(emqx_connector),
-            emqx_mgmt_api_test_util:init_suite(),
-            Config = [{use_tls, UseTLS} | Config0],
+            Apps = emqx_cth_suite:start(
+                [
+                    emqx_conf,
+                    emqx_bridge_influxdb,
+                    emqx_bridge,
+                    emqx_rule_engine,
+                    emqx_management,
+                    emqx_mgmt_api_test_util:emqx_dashboard()
+                ],
+                #{work_dir => emqx_cth_suite:work_dir(Config0)}
+            ),
+            Config = [{apps, Apps}, {use_tls, UseTLS} | Config0],
             {Name, ConfigString, InfluxDBConfig} = influxdb_config(
                 apiv1, InfluxDBHost, InfluxDBPort, Config
             ),
@@ -164,10 +166,18 @@ init_per_group(InfluxDBType, Config0) when
             ProxyHost = os:getenv("PROXY_HOST", "toxiproxy"),
             ProxyPort = list_to_integer(os:getenv("PROXY_PORT", "8474")),
             emqx_common_test_helpers:reset_proxy(ProxyHost, ProxyPort),
-            ok = start_apps(),
-            {ok, _} = application:ensure_all_started(emqx_connector),
-            emqx_mgmt_api_test_util:init_suite(),
-            Config = [{use_tls, UseTLS} | Config0],
+            Apps = emqx_cth_suite:start(
+                [
+                    emqx_conf,
+                    emqx_bridge_influxdb,
+                    emqx_bridge,
+                    emqx_rule_engine,
+                    emqx_management,
+                    emqx_mgmt_api_test_util:emqx_dashboard()
+                ],
+                #{work_dir => emqx_cth_suite:work_dir(Config0)}
+            ),
+            Config = [{apps, Apps}, {use_tls, UseTLS} | Config0],
             {Name, ConfigString, InfluxDBConfig} = influxdb_config(
                 apiv2, InfluxDBHost, InfluxDBPort, Config
             ),
@@ -222,12 +232,13 @@ end_per_group(Group, Config) when
     Group =:= apiv2_tcp;
     Group =:= apiv2_tls
 ->
+    Apps = ?config(apps, Config),
     ProxyHost = ?config(proxy_host, Config),
     ProxyPort = ?config(proxy_port, Config),
     EHttpcPoolName = ?config(ehttpc_pool_name, Config),
     emqx_common_test_helpers:reset_proxy(ProxyHost, ProxyPort),
     ehttpc_sup:stop_pool(EHttpcPoolName),
-    delete_bridge(Config),
+    emqx_cth_suite:stop(Apps),
     ok;
 end_per_group(_Group, _Config) ->
     ok.
@@ -250,14 +261,6 @@ end_per_testcase(_Testcase, Config) ->
 %% Helper fns
 %%------------------------------------------------------------------------------
 
-start_apps() ->
-    %% some configs in emqx_conf app are mandatory
-    %% we want to make sure they are loaded before
-    %% ekka start in emqx_common_test_helpers:start_apps/1
-    emqx_common_test_helpers:render_and_load_app_config(emqx_conf),
-    ok = emqx_common_test_helpers:start_apps([emqx_conf]),
-    ok = emqx_connector_test_helpers:start_apps([emqx_resource, emqx_bridge, emqx_rule_engine]).
-
 example_write_syntax() ->
     %% N.B.: this single space character is relevant
     <<"${topic},clientid=${clientid}", " ", "payload=${payload},",

+ 13 - 7
apps/emqx_bridge_influxdb/test/emqx_bridge_influxdb_connector_SUITE.erl

@@ -27,10 +27,16 @@ init_per_suite(Config) ->
     Servers = [{InfluxDBTCPHost, InfluxDBTCPPort}, {InfluxDBTLSHost, InfluxDBTLSPort}],
     case emqx_common_test_helpers:is_all_tcp_servers_available(Servers) of
         true ->
-            ok = emqx_common_test_helpers:start_apps([emqx_conf]),
-            ok = emqx_connector_test_helpers:start_apps([emqx_resource]),
-            {ok, _} = application:ensure_all_started(emqx_connector),
+            Apps = emqx_cth_suite:start(
+                [
+                    emqx_conf,
+                    emqx_bridge_influxdb,
+                    emqx_bridge
+                ],
+                #{work_dir => emqx_cth_suite:work_dir(Config)}
+            ),
             [
+                {apps, Apps},
                 {influxdb_tcp_host, InfluxDBTCPHost},
                 {influxdb_tcp_port, InfluxDBTCPPort},
                 {influxdb_tls_host, InfluxDBTLSHost},
@@ -46,10 +52,10 @@ init_per_suite(Config) ->
             end
     end.
 
-end_per_suite(_Config) ->
-    ok = emqx_common_test_helpers:stop_apps([emqx_conf]),
-    ok = emqx_connector_test_helpers:stop_apps([emqx_resource]),
-    _ = application:stop(emqx_connector).
+end_per_suite(Config) ->
+    Apps = ?config(apps, Config),
+    emqx_cth_suite:stop(Apps),
+    ok.
 
 init_per_testcase(_, Config) ->
     Config.

+ 4 - 2
apps/emqx_bridge_iotdb/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgeIotdb.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_iotdb,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,7 +18,7 @@ defmodule EMQXBridgeIotdb.MixProject do
   end
 
   def application do
-    [extra_applications: []]
+    [extra_applications: UMP.extra_applications()]
   end
 
   def deps() do

+ 13 - 2
apps/emqx_bridge_iotdb/test/emqx_bridge_iotdb_impl_SUITE.erl

@@ -12,7 +12,6 @@
 -include_lib("snabbkaffe/include/snabbkaffe.hrl").
 
 -define(BRIDGE_TYPE_BIN, <<"iotdb">>).
--define(APPS, [emqx_bridge, emqx_resource, emqx_rule_engine, emqx_bridge_iotdb]).
 
 %%------------------------------------------------------------------------------
 %% CT boilerplate
@@ -34,7 +33,19 @@ groups() ->
     ].
 
 init_per_suite(Config) ->
-    emqx_bridge_v2_testlib:init_per_suite(Config, ?APPS).
+    emqx_bridge_v2_testlib:init_per_suite(
+        Config,
+        [
+            emqx,
+            emqx_conf,
+            emqx_bridge_iotdb,
+            emqx_connector,
+            emqx_bridge,
+            emqx_rule_engine,
+            emqx_management,
+            emqx_mgmt_api_test_util:emqx_dashboard()
+        ]
+    ).
 
 end_per_suite(Config) ->
     emqx_bridge_v2_testlib:end_per_suite(Config).

+ 5 - 3
apps/emqx_bridge_kafka/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgeKafka.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_kafka,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,16 +18,16 @@ defmodule EMQXBridgeKafka.MixProject do
   end
 
   def application do
-    [extra_applications: []]
+    [extra_applications: UMP.extra_applications()]
   end
 
   def deps() do
     [
       {:wolff, github: "kafka4beam/wolff", tag: "1.10.4"},
-      ## TODO: remove `mix.exs` from `wolff` and remove this override
       {:kafka_protocol, github: "kafka4beam/kafka_protocol", tag: "4.1.5", override: true},
       {:brod_gssapi, github: "kafka4beam/brod_gssapi", tag: "v0.1.1"},
       {:brod, github: "kafka4beam/brod", tag: "3.18.0"},
+      ## TODO: remove `mix.exs` from `wolff` and remove this override
       ## TODO: remove `mix.exs` from `pulsar` and remove this override
       {:snappyer, "1.2.9", override: true},
       {:emqx_connector, in_umbrella: true, runtime: false},

+ 1 - 1
apps/emqx_bridge_kafka/test/emqx_bridge_v2_kafka_producer_SUITE.erl

@@ -94,7 +94,7 @@ end_per_testcase(TestCase, Config) when
     TestCase =:= t_ancient_v1_config_migration_without_local_topic
 ->
     Cluster = ?config(cluster, Config),
-    emqx_cth_cluster:stop(Cluster),
+    ok = emqx_cth_cluster:stop(Cluster),
     ok;
 end_per_testcase(_TestCase, Config) ->
     ProxyHost = ?config(proxy_host, Config),

+ 4 - 2
apps/emqx_bridge_kinesis/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgeKinesis.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_kinesis,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,7 +18,7 @@ defmodule EMQXBridgeKinesis.MixProject do
   end
 
   def application do
-    [extra_applications: []]
+    [extra_applications: UMP.extra_applications()]
   end
 
   def deps() do

+ 17 - 9
apps/emqx_bridge_kinesis/test/emqx_bridge_kinesis_impl_producer_SUITE.erl

@@ -42,11 +42,21 @@ init_per_suite(Config) ->
     ProxyName = "kinesis",
     SecretFile = filename:join(?config(priv_dir, Config), "secret"),
     ok = file:write_file(SecretFile, <<?KINESIS_SECRET_KEY>>),
-    ok = emqx_common_test_helpers:start_apps([emqx_conf]),
-    ok = emqx_connector_test_helpers:start_apps([emqx_resource, emqx_bridge, emqx_rule_engine]),
-    {ok, _} = application:ensure_all_started(emqx_connector),
-    emqx_mgmt_api_test_util:init_suite(),
+    Apps = emqx_cth_suite:start(
+        [
+            emqx,
+            emqx_conf,
+            emqx_bridge_kinesis,
+            emqx_connector,
+            emqx_bridge,
+            emqx_rule_engine,
+            emqx_management,
+            emqx_mgmt_api_test_util:emqx_dashboard()
+        ],
+        #{work_dir => emqx_cth_suite:work_dir(Config)}
+    ),
     [
+        {apps, Apps},
         {proxy_host, ProxyHost},
         {proxy_port, ProxyPort},
         {kinesis_port, list_to_integer(os:getenv("KINESIS_PORT", integer_to_list(?KINESIS_PORT)))},
@@ -55,11 +65,9 @@ init_per_suite(Config) ->
         | Config
     ].
 
-end_per_suite(_Config) ->
-    emqx_mgmt_api_test_util:end_suite(),
-    ok = emqx_common_test_helpers:stop_apps([emqx_conf]),
-    ok = emqx_connector_test_helpers:stop_apps([emqx_bridge, emqx_resource, emqx_rule_engine]),
-    _ = application:stop(emqx_connector),
+end_per_suite(Config) ->
+    Apps = ?config(apps, Config),
+    emqx_cth_suite:stop(Apps),
     ok.
 
 init_per_group(with_batch, Config) ->

+ 4 - 2
apps/emqx_bridge_matrix/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgeMatrix.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_matrix,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,7 +18,7 @@ defmodule EMQXBridgeMatrix.MixProject do
   end
 
   def application do
-    [extra_applications: []]
+    [extra_applications: UMP.extra_applications()]
   end
 
   def deps() do

+ 4 - 2
apps/emqx_bridge_mongodb/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgeMongodb.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_mongodb,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,7 +18,7 @@ defmodule EMQXBridgeMongodb.MixProject do
   end
 
   def application do
-    [extra_applications: []]
+    [extra_applications: UMP.extra_applications()]
   end
 
   def deps() do

+ 5 - 4
apps/emqx_bridge_mqtt/mix.exs

@@ -1,5 +1,6 @@
 defmodule EMQXBridgeMQTT.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
@@ -7,7 +8,8 @@ defmodule EMQXBridgeMQTT.MixProject do
       version: "0.1.0",
       build_path: "../../_build",
       # config_path: "../../config/config.exs",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -18,15 +20,14 @@ defmodule EMQXBridgeMQTT.MixProject do
 
   # Run "mix help compile.app" to learn about applications
   def application do
-    [
-      extra_applications: []
-    ]
+    [extra_applications: UMP.extra_applications()]
   end
 
   def deps() do
     [
       {:emqx, in_umbrella: true},
       {:emqx_resource, in_umbrella: true},
+      {:emqtt, github: "emqx/emqtt", tag: "1.10.1", system_env: UMP.maybe_no_quic_env()}
     ]
   end
 end

+ 4 - 3
apps/emqx_bridge_mqtt/test/emqx_bridge_mqtt_SUITE.erl

@@ -20,9 +20,9 @@
 
 -import(emqx_dashboard_api_test_helpers, [request/4, uri/1]).
 
--include("emqx/include/emqx.hrl").
--include("emqx/include/emqx_hooks.hrl").
--include("emqx/include/asserts.hrl").
+-include_lib("emqx/include/emqx.hrl").
+-include_lib("emqx/include/emqx_hooks.hrl").
+-include_lib("emqx/include/asserts.hrl").
 -include_lib("eunit/include/eunit.hrl").
 -include_lib("common_test/include/ct.hrl").
 -include_lib("snabbkaffe/include/snabbkaffe.hrl").
@@ -214,6 +214,7 @@ t_conf_bridge_authn_password(_) ->
     ).
 
 t_conf_bridge_authn_passfile(Config) ->
+    %% test_server_ctrl:run_test_cases_loop
     DataDir = ?config(data_dir, Config),
     Username2 = <<"user2">>,
     PasswordFilename = filename:join(DataDir, "password"),

+ 4 - 2
apps/emqx_bridge_mysql/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgeMysql.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_mysql,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,7 +18,7 @@ defmodule EMQXBridgeMysql.MixProject do
   end
 
   def application do
-    [extra_applications: []]
+    [extra_applications: UMP.extra_applications()]
   end
 
   def deps() do

+ 22 - 5
apps/emqx_bridge_mysql/test/emqx_bridge_mysql_SUITE.erl

@@ -105,10 +105,12 @@ init_per_group(_Group, Config) ->
     Config.
 
 end_per_group(Group, Config) when Group =:= with_batch; Group =:= without_batch ->
+    Apps = ?config(apps, Config),
     connect_and_drop_table(Config),
     ProxyHost = ?config(proxy_host, Config),
     ProxyPort = ?config(proxy_port, Config),
     emqx_common_test_helpers:reset_proxy(ProxyHost, ProxyPort),
+    emqx_cth_suite:stop(Apps),
     ok;
 end_per_group(_Group, _Config) ->
     ok.
@@ -150,15 +152,25 @@ common_init(Config0) ->
             ProxyHost = os:getenv("PROXY_HOST", "toxiproxy"),
             ProxyPort = list_to_integer(os:getenv("PROXY_PORT", "8474")),
             emqx_common_test_helpers:reset_proxy(ProxyHost, ProxyPort),
-            % Ensure enterprise bridge module is loaded
-            ok = emqx_common_test_helpers:start_apps([emqx_conf, emqx_bridge, emqx_rule_engine]),
-            _ = emqx_bridge_enterprise:module_info(),
-            emqx_mgmt_api_test_util:init_suite(),
+            Apps = emqx_cth_suite:start(
+                [
+                    emqx,
+                    emqx_conf,
+                    emqx_connector,
+                    emqx_bridge,
+                    emqx_bridge_mysql,
+                    emqx_rule_engine,
+                    emqx_management,
+                    emqx_mgmt_api_test_util:emqx_dashboard()
+                ],
+                #{work_dir => emqx_cth_suite:work_dir(Config0)}
+            ),
             % Connect to mysql directly and create the table
             connect_and_create_table(Config0),
             {Name, MysqlConfig} = mysql_config(BridgeType, Config0),
             Config =
                 [
+                    {apps, Apps},
                     {mysql_config, MysqlConfig},
                     {mysql_bridge_type, BridgeType},
                     {mysql_name, Name},
@@ -171,7 +183,12 @@ common_init(Config0) ->
                 ],
             Config;
         false ->
-            {skip, no_mysql}
+            case os:getenv("IS_CI") of
+                "yes" ->
+                    throw(no_mysql);
+                _ ->
+                    {skip, no_mysql}
+            end
     end.
 
 mysql_config(BridgeType, Config) ->

+ 4 - 2
apps/emqx_bridge_opents/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgeOpents.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_opents,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,7 +18,7 @@ defmodule EMQXBridgeOpents.MixProject do
   end
 
   def application do
-    [extra_applications: []]
+    [extra_applications: UMP.extra_applications()]
   end
 
   def deps() do

+ 10 - 2
apps/emqx_bridge_opents/test/emqx_bridge_opents_SUITE.erl

@@ -13,7 +13,6 @@
 
 % DB defaults
 -define(BRIDGE_TYPE_BIN, <<"opents">>).
--define(APPS, [opentsdb, emqx_bridge, emqx_resource, emqx_rule_engine, emqx_bridge_opents_SUITE]).
 
 %%------------------------------------------------------------------------------
 %% CT boilerplate
@@ -31,7 +30,16 @@ groups() ->
     ].
 
 init_per_suite(Config) ->
-    emqx_bridge_v2_testlib:init_per_suite(Config, ?APPS).
+    emqx_bridge_v2_testlib:init_per_suite(Config, [
+        emqx,
+        emqx_conf,
+        emqx_bridge_opents,
+        emqx_connector,
+        emqx_bridge,
+        emqx_rule_engine,
+        emqx_management,
+        emqx_mgmt_api_test_util:emqx_dashboard()
+    ]).
 
 end_per_suite(Config) ->
     emqx_bridge_v2_testlib:end_per_suite(Config).

+ 4 - 2
apps/emqx_bridge_oracle/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgeOracle.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_oracle,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,7 +18,7 @@ defmodule EMQXBridgeOracle.MixProject do
   end
 
   def application do
-    [extra_applications: []]
+    [extra_applications: UMP.extra_applications()]
   end
 
   def deps() do

+ 17 - 12
apps/emqx_bridge_oracle/test/emqx_bridge_oracle_SUITE.erl

@@ -13,7 +13,6 @@
 -import(emqx_common_test_helpers, [on_exit/1]).
 
 -define(BRIDGE_TYPE_BIN, <<"oracle">>).
--define(APPS, [emqx_bridge, emqx_resource, emqx_rule_engine, emqx_oracle, emqx_bridge_oracle]).
 -define(SID, "XE").
 -define(RULE_TOPIC, "mqtt/rule").
 
@@ -36,10 +35,6 @@ init_per_suite(Config) ->
     Config.
 
 end_per_suite(_Config) ->
-    emqx_mgmt_api_test_util:end_suite(),
-    ok = emqx_common_test_helpers:stop_apps([emqx_conf]),
-    ok = emqx_connector_test_helpers:stop_apps(lists:reverse(?APPS)),
-    _ = application:stop(emqx_connector),
     ok.
 
 init_per_group(plain = Type, Config) ->
@@ -48,7 +43,7 @@ init_per_group(plain = Type, Config) ->
     ProxyName = "oracle",
     case emqx_common_test_helpers:is_tcp_server_available(OracleHost, OraclePort) of
         true ->
-            Config1 = common_init_per_group(),
+            Config1 = common_init_per_group(Config),
             [
                 {proxy_name, ProxyName},
                 {oracle_host, OracleHost},
@@ -71,23 +66,33 @@ end_per_group(Group, Config) when
     Group =:= plain
 ->
     common_end_per_group(Config),
+    Apps = ?config(apps, Config),
+    emqx_cth_suite:stop(Apps),
     ok;
 end_per_group(_Group, _Config) ->
     ok.
 
-common_init_per_group() ->
+common_init_per_group(Config) ->
     ProxyHost = os:getenv("PROXY_HOST", "toxiproxy"),
     ProxyPort = list_to_integer(os:getenv("PROXY_PORT", "8474")),
     emqx_common_test_helpers:reset_proxy(ProxyHost, ProxyPort),
     %% Ensure enterprise bridge module is loaded
-    ok = emqx_common_test_helpers:start_apps([emqx_conf, emqx_bridge]),
-    _ = emqx_bridge_enterprise:module_info(),
-    ok = emqx_connector_test_helpers:start_apps(?APPS),
-    {ok, _} = application:ensure_all_started(emqx_connector),
-    emqx_mgmt_api_test_util:init_suite(),
+    Apps = emqx_cth_suite:start(
+        [
+            emqx_conf,
+            emqx_oracle,
+            emqx_bridge_oracle,
+            emqx_bridge,
+            emqx_rule_engine,
+            emqx_management,
+            emqx_mgmt_api_test_util:emqx_dashboard()
+        ],
+        #{work_dir => emqx_cth_suite:work_dir(Config)}
+    ),
     UniqueNum = integer_to_binary(erlang:unique_integer()),
     MQTTTopic = <<"mqtt/topic/", UniqueNum/binary>>,
     [
+        {apps, Apps},
         {proxy_host, ProxyHost},
         {proxy_port, ProxyPort},
         {mqtt_topic, MQTTTopic}

+ 4 - 2
apps/emqx_bridge_pgsql/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgePgsql.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_pgsql,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,7 +18,7 @@ defmodule EMQXBridgePgsql.MixProject do
   end
 
   def application do
-    [extra_applications: []]
+    [extra_applications: UMP.extra_applications()]
   end
 
   def deps() do

+ 1 - 1
apps/emqx_bridge_pgsql/test/emqx_bridge_pgsql_SUITE.erl

@@ -10,7 +10,7 @@
 -include_lib("eunit/include/eunit.hrl").
 -include_lib("common_test/include/ct.hrl").
 -include_lib("snabbkaffe/include/snabbkaffe.hrl").
--include("emqx_resource_errors.hrl").
+-include("../../emqx_resource/include/emqx_resource_errors.hrl").
 
 % SQL definitions
 -define(SQL_BRIDGE,

+ 1 - 3
apps/emqx_bridge_pgsql/test/emqx_bridge_v2_pgsql_SUITE.erl

@@ -61,14 +61,12 @@ init_per_suite(Config) ->
                     emqx_bridge_pgsql,
                     emqx_rule_engine,
                     emqx_management,
-                    {emqx_dashboard, "dashboard.listeners.http { enable = true, bind = 18083 }"}
+                    emqx_mgmt_api_test_util:emqx_dashboard()
                 ],
                 #{work_dir => emqx_cth_suite:work_dir(Config)}
             ),
-            {ok, Api} = emqx_common_test_http:create_default_app(),
             NConfig = [
                 {apps, Apps},
-                {api, Api},
                 {pgsql_host, PostgresHost},
                 {pgsql_port, PostgresPort},
                 {enable_tls, false},

+ 5 - 3
apps/emqx_bridge_pulsar/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgePulsar.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_pulsar,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,14 +18,14 @@ defmodule EMQXBridgePulsar.MixProject do
   end
 
   def application do
-    [extra_applications: []]
+    [extra_applications: UMP.extra_applications()]
   end
 
   def deps() do
     [
-      ## TODO: remove `mix.exs` from `pulsar` and remove this override
       {:crc32cer, git: "https://github.com/zmstone/crc32cer", tag: "0.1.8", override: true},
       ## TODO: remove `mix.exs` from `pulsar` and remove this override
+      ## TODO: remove `mix.exs` from `pulsar` and remove this override
       {:snappyer, "1.2.9", override: true},
       {:pulsar, github: "emqx/pulsar-client-erl", tag: "0.8.3"},
       {:emqx_connector, in_umbrella: true, runtime: false},

+ 9 - 6
apps/emqx_bridge_rabbitmq/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgeRabbitmq.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_rabbitmq,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,18 +18,19 @@ defmodule EMQXBridgeRabbitmq.MixProject do
   end
 
   def application do
-    [extra_applications: [], mod: {:emqx_bridge_rabbitmq_app, []}]
+    [extra_applications: UMP.extra_applications(), mod: {:emqx_bridge_rabbitmq_app, []}]
   end
 
   def deps() do
     [
       {:thoas, github: "emqx/thoas", tag: "v1.0.0", override: true},
-      {:credentials_obfuscation, github: "emqx/credentials-obfuscation", tag: "v3.2.0", override: true},
+      {:credentials_obfuscation,
+       github: "emqx/credentials-obfuscation", tag: "v3.2.0", override: true},
       {:rabbit_common,
-       github: "emqx/rabbitmq-server", tag: "v3.11.13.2",
+       github: "emqx/rabbitmq-server",
+       tag: "v3.11.13.2",
        sparse: "deps/rabbit_common",
-       override: true
-      },
+       override: true},
       {:amqp_client,
        github: "emqx/rabbitmq-server", tag: "v3.11.13.2", sparse: "deps/amqp_client"},
       {:emqx_connector, in_umbrella: true, runtime: false},

+ 1 - 1
apps/emqx_bridge_rabbitmq/test/emqx_bridge_rabbitmq_connector_SUITE.erl

@@ -7,7 +7,7 @@
 -compile(nowarn_export_all).
 -compile(export_all).
 
--include("emqx_connector.hrl").
+-include("../../emqx_connector/include/emqx_connector.hrl").
 -include_lib("eunit/include/eunit.hrl").
 -include_lib("stdlib/include/assert.hrl").
 -include_lib("common_test/include/ct.hrl").

+ 30 - 19
apps/emqx_bridge_rabbitmq/test/emqx_bridge_rabbitmq_test_utils.erl

@@ -9,16 +9,21 @@
 
 -include_lib("emqx_connector/include/emqx_connector.hrl").
 -include_lib("eunit/include/eunit.hrl").
+-include_lib("common_test/include/ct.hrl").
 -include_lib("stdlib/include/assert.hrl").
 -include_lib("amqp_client/include/amqp_client.hrl").
 
-init_per_group(tcp, Config) ->
+init_per_group(tcp = Group, Config) ->
     RabbitMQHost = os:getenv("RABBITMQ_PLAIN_HOST", "rabbitmq"),
     RabbitMQPort = list_to_integer(os:getenv("RABBITMQ_PLAIN_PORT", "5672")),
     case emqx_common_test_helpers:is_tcp_server_available(RabbitMQHost, RabbitMQPort) of
         true ->
             Config1 = common_init_per_group(#{
-                host => RabbitMQHost, port => RabbitMQPort, tls => false
+                group => Group,
+                tc_config => Config,
+                host => RabbitMQHost,
+                port => RabbitMQPort,
+                tls => false
             }),
             Config1 ++ Config;
         false ->
@@ -29,13 +34,17 @@ init_per_group(tcp, Config) ->
                     {skip, no_rabbitmq}
             end
     end;
-init_per_group(tls, Config) ->
+init_per_group(tls = Group, Config) ->
     RabbitMQHost = os:getenv("RABBITMQ_TLS_HOST", "rabbitmq"),
     RabbitMQPort = list_to_integer(os:getenv("RABBITMQ_TLS_PORT", "5671")),
     case emqx_common_test_helpers:is_tcp_server_available(RabbitMQHost, RabbitMQPort) of
         true ->
             Config1 = common_init_per_group(#{
-                host => RabbitMQHost, port => RabbitMQPort, tls => true
+                group => Group,
+                tc_config => Config,
+                host => RabbitMQHost,
+                port => RabbitMQPort,
+                tls => true
             }),
             Config1 ++ Config;
         false ->
@@ -50,17 +59,24 @@ init_per_group(_Group, Config) ->
     Config.
 
 common_init_per_group(Opts) ->
-    emqx_common_test_helpers:render_and_load_app_config(emqx_conf),
-    ok = emqx_common_test_helpers:start_apps([
-        emqx_conf, emqx_bridge, emqx_bridge_rabbitmq, emqx_rule_engine, emqx_modules
-    ]),
-    ok = emqx_connector_test_helpers:start_apps([emqx_resource]),
-    {ok, _} = application:ensure_all_started(emqx_connector),
-    {ok, _} = application:ensure_all_started(amqp_client),
-    emqx_mgmt_api_test_util:init_suite(),
+    #{group := Group, tc_config := Config} = Opts,
+    Apps = emqx_cth_suite:start(
+        [
+            emqx,
+            emqx_conf,
+            emqx_connector,
+            emqx_bridge_rabbitmq,
+            emqx_bridge,
+            emqx_rule_engine,
+            emqx_management,
+            emqx_mgmt_api_test_util:emqx_dashboard()
+        ],
+        #{work_dir => emqx_cth_suite:work_dir(Group, Config)}
+    ),
     #{host := Host, port := Port, tls := UseTLS} = Opts,
     ChannelConnection = setup_rabbit_mq_exchange_and_queue(Host, Port, UseTLS),
     [
+        {apps, Apps},
         {channel_connection, ChannelConnection},
         {rabbitmq, #{server => Host, port => Port, tls => UseTLS}}
     ].
@@ -115,13 +131,8 @@ end_per_group(_Group, Config) ->
         channel := Channel
     } = get_channel_connection(Config),
     amqp_channel:call(Channel, #'queue.purge'{queue = rabbit_mq_queue()}),
-    emqx_mgmt_api_test_util:end_suite(),
-    ok = emqx_common_test_helpers:stop_apps([
-        emqx_conf, emqx_bridge_rabbitmq, emqx_rule_engine, emqx_modules
-    ]),
-    ok = emqx_connector_test_helpers:stop_apps([emqx_resource]),
-    _ = application:stop(emqx_connector),
-    _ = application:stop(emqx_bridge),
+    Apps = ?config(apps, Config),
+    emqx_cth_suite:stop(Apps),
     %% Close the channel
     ok = amqp_channel:close(Channel),
     %% Close the connection

+ 4 - 2
apps/emqx_bridge_redis/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgeRedis.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_redis,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,7 +18,7 @@ defmodule EMQXBridgeRedis.MixProject do
   end
 
   def application do
-    [extra_applications: []]
+    [extra_applications: UMP.extra_applications()]
   end
 
   def deps() do

+ 4 - 2
apps/emqx_bridge_rocketmq/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgeRocketmq.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_rocketmq,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,7 +18,7 @@ defmodule EMQXBridgeRocketmq.MixProject do
   end
 
   def application do
-    [extra_applications: []]
+    [extra_applications: UMP.extra_applications()]
   end
 
   def deps() do

+ 0 - 2
apps/emqx_bridge_rocketmq/test/emqx_bridge_rocketmq_SUITE.erl

@@ -73,8 +73,6 @@ init_per_suite(Config) ->
     Config.
 
 end_per_suite(_Config) ->
-    emqx_mgmt_api_test_util:end_suite(),
-    ok = emqx_common_test_helpers:stop_apps([emqx_bridge, emqx_conf]),
     ok.
 
 init_per_testcase(_Testcase, Config) ->

+ 5 - 3
apps/emqx_bridge_s3/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgeS3.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_s3,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,14 +18,14 @@ defmodule EMQXBridgeS3.MixProject do
   end
 
   def application do
-    [extra_applications: [], mod: {:emqx_bridge_s3_app, []}]
+    [extra_applications: UMP.extra_applications(), mod: {:emqx_bridge_s3_app, []}]
   end
 
   def deps() do
     [
       {:emqx_resource, in_umbrella: true},
       {:emqx_connector_aggregator, in_umbrella: true},
-      {:emqx_s3, in_umbrella: true},
+      {:emqx_s3, in_umbrella: true}
     ]
   end
 end

+ 4 - 2
apps/emqx_bridge_sqlserver/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgeSqlserver.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_sqlserver,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,7 +18,7 @@ defmodule EMQXBridgeSqlserver.MixProject do
   end
 
   def application do
-    [extra_applications: []]
+    [extra_applications: [:odbc] ++ UMP.extra_applications()]
   end
 
   def deps() do

+ 14 - 7
apps/emqx_bridge_sqlserver/test/emqx_bridge_sqlserver_SUITE.erl

@@ -7,7 +7,7 @@
 -compile(nowarn_export_all).
 -compile(export_all).
 
--include("emqx_bridge_sqlserver/include/emqx_bridge_sqlserver.hrl").
+-include("../include/emqx_bridge_sqlserver.hrl").
 -include_lib("eunit/include/eunit.hrl").
 -include_lib("common_test/include/ct.hrl").
 -include_lib("snabbkaffe/include/snabbkaffe.hrl").
@@ -122,9 +122,11 @@ init_per_group(_Group, Config) ->
 end_per_group(Group, Config) when Group =:= with_batch; Group =:= without_batch ->
     connect_and_drop_table(Config),
     connect_and_drop_db(Config),
+    Apps = ?config(apps, Config),
     ProxyHost = ?config(proxy_host, Config),
     ProxyPort = ?config(proxy_port, Config),
     emqx_common_test_helpers:reset_proxy(ProxyHost, ProxyPort),
+    emqx_cth_suite:stop(Apps),
     ok;
 end_per_group(_Group, _Config) ->
     ok.
@@ -135,8 +137,6 @@ init_per_suite(Config) ->
     [{sqlserver_passfile, Passfile} | Config].
 
 end_per_suite(_Config) ->
-    emqx_mgmt_api_test_util:end_suite(),
-    ok = emqx_common_test_helpers:stop_apps([emqx_bridge, emqx_conf]),
     ok.
 
 init_per_testcase(_Testcase, Config) ->
@@ -422,16 +422,23 @@ common_init(ConfigT) ->
             ProxyHost = os:getenv("PROXY_HOST", "toxiproxy"),
             ProxyPort = list_to_integer(os:getenv("PROXY_PORT", "8474")),
             emqx_common_test_helpers:reset_proxy(ProxyHost, ProxyPort),
-            % Ensure enterprise bridge module is loaded
-            ok = emqx_common_test_helpers:start_apps([emqx_conf, emqx_bridge, odbc]),
-            _ = emqx_bridge_enterprise:module_info(),
-            emqx_mgmt_api_test_util:init_suite(),
+            Apps = emqx_cth_suite:start(
+                [
+                    emqx_conf,
+                    emqx_bridge_sqlserver,
+                    emqx_bridge,
+                    emqx_management,
+                    emqx_mgmt_api_test_util:emqx_dashboard()
+                ],
+                #{work_dir => emqx_cth_suite:work_dir(Config0)}
+            ),
             % Connect to sqlserver directly
             % drop old db and table, and then create new ones
             connect_and_create_db_and_table(Config0),
             {Name, SQLServerConf} = sqlserver_config(BridgeType, Config0),
             Config =
                 [
+                    {apps, Apps},
                     {sqlserver_config, SQLServerConf},
                     {sqlserver_bridge_type, BridgeType},
                     {sqlserver_name, Name},

+ 4 - 2
apps/emqx_bridge_syskeeper/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgeSyskeeper.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_syskeeper,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,7 +18,7 @@ defmodule EMQXBridgeSyskeeper.MixProject do
   end
 
   def application do
-    [extra_applications: []]
+    [extra_applications: UMP.extra_applications()]
   end
 
   def deps() do

+ 4 - 2
apps/emqx_bridge_tdengine/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgeTdengine.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_tdengine,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,7 +18,7 @@ defmodule EMQXBridgeTdengine.MixProject do
   end
 
   def application do
-    [extra_applications: []]
+    [extra_applications: UMP.extra_applications()]
   end
 
   def deps() do

+ 17 - 5
apps/emqx_bridge_tdengine/test/emqx_bridge_tdengine_SUITE.erl

@@ -55,9 +55,6 @@
 ).
 
 -define(BRIDGE_TYPE_BIN, <<"tdengine">>).
--define(APPS, [
-    hackney, tdengine, emqx_bridge, emqx_resource, emqx_rule_engine, emqx_bridge_tdengine
-]).
 
 %%------------------------------------------------------------------------------
 %% CT boilerplate
@@ -81,7 +78,19 @@ groups() ->
     ].
 
 init_per_suite(Config) ->
-    emqx_bridge_v2_testlib:init_per_suite(Config, ?APPS).
+    emqx_bridge_v2_testlib:init_per_suite(
+        Config,
+        [
+            emqx,
+            emqx_conf,
+            emqx_bridge_tdengine,
+            emqx_connector,
+            emqx_bridge,
+            emqx_rule_engine,
+            emqx_management,
+            emqx_mgmt_api_test_util:emqx_dashboard()
+        ]
+    ).
 
 end_per_suite(Config) ->
     emqx_bridge_v2_testlib:end_per_suite(Config).
@@ -99,7 +108,10 @@ init_per_group(without_batch, Config0) ->
 init_per_group(_Group, Config) ->
     Config.
 
-end_per_group(default, Config) ->
+end_per_group(Group, Config) when
+    Group =:= with_batch;
+    Group =:= without_batch
+->
     emqx_bridge_v2_testlib:end_per_group(Config),
     ok;
 end_per_group(_Group, _Config) ->

+ 4 - 2
apps/emqx_bridge_timescale/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXBridgeTimescale.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_bridge_timescale,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,7 +18,7 @@ defmodule EMQXBridgeTimescale.MixProject do
   end
 
   def application do
-    [extra_applications: []]
+    [extra_applications: UMP.extra_applications()]
   end
 
   def deps() do

+ 10 - 3
apps/emqx_cluster_link/mix.exs

@@ -1,12 +1,14 @@
 defmodule EMQXClusterLink.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
       app: :emqx_cluster_link,
       version: "0.1.0",
       build_path: "../../_build",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -16,10 +18,15 @@ defmodule EMQXClusterLink.MixProject do
   end
 
   def application do
-    [extra_applications: [], mod: {:emqx_cluster_link_app, []}]
+    [extra_applications: UMP.extra_applications(), mod: {:emqx_cluster_link_app, []}]
   end
 
   def deps() do
-    [{:emqx, in_umbrella: true}, {:emqx_resource, in_umbrella: true}]
+    [
+      {:emqx, in_umbrella: true},
+      {:emqx_resource, in_umbrella: true},
+      {:emqtt,
+       github: "emqx/emqtt", tag: "1.10.1", override: true, system_env: UMP.maybe_no_quic_env()}
+    ]
   end
 end

+ 5 - 6
apps/emqx_conf/mix.exs

@@ -1,5 +1,6 @@
 defmodule EMQXConf.MixProject do
   use Mix.Project
+  alias EMQXUmbrella.MixProject, as: UMP
 
   def project do
     [
@@ -7,7 +8,8 @@ defmodule EMQXConf.MixProject do
       version: "0.1.0",
       build_path: "../../_build",
       # config_path: "../../config/config.exs",
-      erlc_options: EMQXUmbrella.MixProject.erlc_options(),
+      erlc_options: UMP.erlc_options(),
+      erlc_paths: UMP.erlc_paths(),
       deps_path: "../../deps",
       lockfile: "../../mix.lock",
       elixir: "~> 1.14",
@@ -18,16 +20,13 @@ defmodule EMQXConf.MixProject do
 
   # Run "mix help compile.app" to learn about applications
   def application do
-    [
-      extra_applications: [],
-      mod: {:emqx_conf_app, []}
-    ]
+    [extra_applications: UMP.extra_applications(), mod: {:emqx_conf_app, []}]
   end
 
   def deps() do
     [
       {:emqx, in_umbrella: true, runtime: false},
-      {:emqx_auth, in_umbrella: true, runtime: false},
+      {:emqx_auth, in_umbrella: true, runtime: false}
     ]
   end
 end

+ 0 - 2
apps/emqx_conf/src/emqx_conf_schema.erl

@@ -1428,8 +1428,6 @@ to_atom(Bin) when is_binary(Bin) ->
     binary_to_atom(Bin, utf8).
 
 roots(Module) ->
-    %% io:format(user, "\n\n>>>>>>>>>>>>>>>\n  ~p\n\n", [#{e => emqx_release:edition(), m => Module}]),
-    %% error({Module, emqx_release:edition()}),
     lists:map(fun({_BinName, Root}) -> Root end, hocon_schema:roots(Module)).
 
 %% Like authentication schema, authorization schema is incomplete in emqx_schema

+ 0 - 1
apps/emqx_conf/test/emqx_conf_app_SUITE.erl

@@ -57,7 +57,6 @@ t_copy_conf_override_on_restarts(Config) ->
 
 t_copy_new_data_dir(Config) ->
     ct:timetrap({seconds, 120}),
-    snabbkaffe:fix_ct_logging(),
     Cluster = cluster(
         ?FUNCTION_NAME,
         [cluster_spec({core, 4}), cluster_spec({core, 5}), cluster_spec({core, 6})],

+ 0 - 0
apps/emqx_conf/test/emqx_conf_cli_SUITE.erl


Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä