From ac2c99f9964c43e5d50815a629e5596d9911ab2c Mon Sep 17 00:00:00 2001 From: Thales Macedo Garitezi Date: Fri, 1 Dec 2023 14:42:06 -0300 Subject: [PATCH] test(connector): add test to ensure connector schema has `resource_opts` https://emqx.atlassian.net/browse/EMQX-11509 --- apps/emqx_bridge/src/emqx_bridge_v2.erl | 5 +- .../emqx_bridge/test/emqx_bridge_v2_tests.erl | 75 ++++++++++++++++++- 2 files changed, 75 insertions(+), 5 deletions(-) diff --git a/apps/emqx_bridge/src/emqx_bridge_v2.erl b/apps/emqx_bridge/src/emqx_bridge_v2.erl index 97d0afb43..a9aeb0f8e 100644 --- a/apps/emqx_bridge/src/emqx_bridge_v2.erl +++ b/apps/emqx_bridge/src/emqx_bridge_v2.erl @@ -260,11 +260,10 @@ create(BridgeType, BridgeName, RawConf) -> #{override_to => cluster} ). -%% NOTE: This function can cause broken references from rules but it is only -%% called directly from test cases. - -spec remove(bridge_v2_type(), bridge_v2_name()) -> ok | {error, any()}. remove(BridgeType, BridgeName) -> + %% NOTE: This function can cause broken references from rules but it is only + %% called directly from test cases. ?SLOG(debug, #{ brige_action => remove, bridge_version => 2, diff --git a/apps/emqx_bridge/test/emqx_bridge_v2_tests.erl b/apps/emqx_bridge/test/emqx_bridge_v2_tests.erl index 4e28f3d88..600cd4210 100644 --- a/apps/emqx_bridge/test/emqx_bridge_v2_tests.erl +++ b/apps/emqx_bridge/test/emqx_bridge_v2_tests.erl @@ -16,6 +16,35 @@ -module(emqx_bridge_v2_tests). -include_lib("eunit/include/eunit.hrl"). +-include_lib("hocon/include/hoconsc.hrl"). + +%%------------------------------------------------------------------------------ +%% Helper fns +%%------------------------------------------------------------------------------ + +non_deprecated_fields(Fields) -> + [K || {K, Schema} <- Fields, not hocon_schema:is_deprecated(Schema)]. + +find_resource_opts_fields(SchemaMod, FieldName) -> + Fields = hocon_schema:fields(SchemaMod, FieldName), + case lists:keyfind(resource_opts, 1, Fields) of + false -> + undefined; + {resource_opts, ROSc} -> + get_resource_opts_subfields(ROSc) + end. + +get_resource_opts_subfields(ScFn) when is_function(ScFn, 1) -> + get_resource_opts_subfields(ScFn(type)); +get_resource_opts_subfields(#{type := T = ?R_REF(_SchemaModRO, _FieldNameRO)}) -> + get_resource_opts_subfields(T); +get_resource_opts_subfields(?R_REF(SchemaModRO, FieldNameRO)) -> + ROFields = non_deprecated_fields(hocon_schema:fields(SchemaModRO, FieldNameRO)), + proplists:get_keys(ROFields). + +%%------------------------------------------------------------------------------ +%% Testcases +%%------------------------------------------------------------------------------ resource_opts_union_connector_actions_test() -> %% The purpose of this test is to ensure we have split `resource_opts' fields @@ -37,5 +66,47 @@ resource_opts_union_connector_actions_test() -> ), ok. -non_deprecated_fields(Fields) -> - [K || {K, Schema} <- Fields, not hocon_schema:is_deprecated(Schema)]. +connector_resource_opts_test() -> + %% The purpose of this test is to ensure that all connectors have the `resource_opts' + %% field with at least some sub-fields that should always be present. + %% These are used by `emqx_resource_manager' itself to manage the resource lifecycle. + MinimumROFields = [ + health_check_interval, + query_mode, + start_after_created, + start_timeout + ], + ConnectorSchemasRefs = + lists:map( + fun({Type, #{type := ?MAP(_, ?R_REF(SchemaMod, FieldName))}}) -> + {Type, find_resource_opts_fields(SchemaMod, FieldName)} + end, + emqx_connector_schema:fields(connectors) + ), + ConnectorsMissingRO = [Type || {Type, undefined} <- ConnectorSchemasRefs], + ConnectorsMissingROSubfields = + lists:filtermap( + fun + ({_Type, undefined}) -> + false; + ({Type, Fs}) -> + case MinimumROFields -- Fs of + [] -> + false; + MissingFields -> + {true, {Type, MissingFields}} + end + end, + ConnectorSchemasRefs + ), + ?assertEqual( + #{ + missing_resource_opts_field => #{}, + missing_subfields => #{} + }, + #{ + missing_resource_opts_field => maps:from_keys(ConnectorsMissingRO, true), + missing_subfields => maps:from_list(ConnectorsMissingROSubfields) + } + ), + ok.