From db80307bf04e5f221322008810d1cb8b4946ef01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chrz=C4=85szcz?= Date: Thu, 4 Nov 2021 08:47:56 +0100 Subject: [PATCH 1/6] Remove redundant validation and conversion of the config schema It is already validated in the config parser --- src/muc_light/mod_muc_light.erl | 4 +- src/muc_light/mod_muc_light_room_config.erl | 42 ++++----------------- 2 files changed, 9 insertions(+), 37 deletions(-) diff --git a/src/muc_light/mod_muc_light.erl b/src/muc_light/mod_muc_light.erl index 1c0627bf4c..eb695de8a5 100644 --- a/src/muc_light/mod_muc_light.erl +++ b/src/muc_light/mod_muc_light.erl @@ -269,7 +269,7 @@ config_spec() -> config_schema_spec() -> #section{ - items = #{<<"field">> => #option{type = string, + items = #{<<"field">> => #option{type = binary, validate = non_empty}, <<"string_value">> => #option{type = binary}, <<"integer_value">> => #option{type = integer}, @@ -285,7 +285,7 @@ process_config_schema(KVs) -> {[[{field, FieldName}], InternalKeyOpts], ValueOpts} = proplists:split(KVs, [field, internal_key]), {Value, Type} = process_config_schema_value(ValueOpts), - InternalKey = proplists:get_value(internal_key, InternalKeyOpts, list_to_atom(FieldName)), + InternalKey = proplists:get_value(internal_key, InternalKeyOpts, binary_to_atom(FieldName)), {FieldName, Value, InternalKey, Type}. process_config_schema_value([{string_value, Val}]) -> {Val, binary}; diff --git a/src/muc_light/mod_muc_light_room_config.erl b/src/muc_light/mod_muc_light_room_config.erl index f4cce522de..67fbd62d27 100644 --- a/src/muc_light/mod_muc_light_room_config.erl +++ b/src/muc_light/mod_muc_light_room_config.erl @@ -65,9 +65,8 @@ -type binary_kv() :: [{Key :: binary(), Value :: binary()}]. %% User definition processing --type user_defined_schema_item() :: {FieldName :: string(), DefaultValue :: string()} - | {FieldName :: string(), DefaultValue :: value() | string(), - key(), value_type()}. +-type user_defined_schema_item() :: {FieldName :: binary(), DefaultValue :: value(), + key(), value_type()}. -type user_defined_schema() :: [user_defined_schema_item()]. %%==================================================================== @@ -127,36 +126,13 @@ schema_reverse_index(#schema{ reverse_index = RevIndex }) -> RevIndex. -spec add_config_schema_field(UserDefinedSchemaItem :: user_defined_schema_item(), SchemaAcc :: schema()) -> schema(). -add_config_schema_field({FieldName, DefaultValue}, SchemaAcc) -> - add_config_schema_field({FieldName, DefaultValue, list_to_atom(FieldName), binary}, SchemaAcc); -add_config_schema_field({FieldName, DefaultValue, Key, ValueType} = Definition, SchemaAcc) -> - case validate_schema_definition(Definition) of - true -> - #schema{ fields = Fields0, reverse_index = RevIndex0 } = SchemaAcc, - - FieldNameBin = unicode:characters_to_binary(FieldName), - NormalizedValue = normalize_value(DefaultValue, ValueType), - - NFields = Fields0#{ FieldNameBin => { NormalizedValue, Key, ValueType } }, - NRevIndex = RevIndex0#{ Key => FieldNameBin }, - - SchemaAcc#schema{ fields = NFields, reverse_index = NRevIndex }; - false -> - error({invalid_schema_definition, Definition}) - end. +add_config_schema_field({FieldName, DefaultValue, Key, ValueType}, SchemaAcc) -> + #schema{ fields = Fields0, reverse_index = RevIndex0 } = SchemaAcc, --spec validate_schema_definition(user_defined_schema_item()) -> boolean(). -validate_schema_definition({FieldName, DefaultValue, Key, ValueType}) - when is_list(FieldName), is_atom(Key) -> - validate_schema_default_and_type(DefaultValue, ValueType); -validate_schema_definition(_Definition) -> - false. + NFields = Fields0#{ FieldName => { DefaultValue, Key, ValueType } }, + NRevIndex = RevIndex0#{ Key => FieldName }, --spec validate_schema_default_and_type(value(), value_type()) -> boolean(). -validate_schema_default_and_type(Val, binary) -> is_binary(Val) orelse is_list(Val); -validate_schema_default_and_type(Val, integer) -> is_integer(Val); -validate_schema_default_and_type(Val, float) -> is_float(Val); -validate_schema_default_and_type(_Val, _Type) -> false. + SchemaAcc#schema{ fields = NFields, reverse_index = NRevIndex }. -spec from_kv_tuple(KeyBin :: binary(), ValBin :: binary(), ConfigSchema :: schema()) -> {ok, Key :: atom(), Val :: any()} | validation_error(). @@ -166,10 +142,6 @@ from_kv_tuple(KeyBin, ValBin, ConfigSchema) -> _ -> {error, {KeyBin, unknown}} end. --spec normalize_value(Value :: value() | string(), value_type()) -> value(). -normalize_value(Val, binary) when is_list(Val) -> unicode:characters_to_binary(Val); -normalize_value(Val, _) -> Val. - -spec b2value(ValBin :: binary(), Type :: value_type()) -> Converted :: value(). b2value(ValBin, binary) -> ValBin; b2value(ValBin, integer) -> binary_to_integer(ValBin); From b1033779b9575f34435e9b5cf7adab5574c330c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chrz=C4=85szcz?= Date: Fri, 5 Nov 2021 15:13:15 +0100 Subject: [PATCH 2/6] Do not convert the config schema to the internal structure with maps Reason: clarity, simplicity and little to no real performance benefit, as the computational cost was dominated by lists:keystore anyway. Also: separate functions for conversion of the initial config and the diff, which eliminates the need for storing the default config and using lists:keystore. The config schema needs to be sorted now. --- src/muc_light/mod_muc_light_room_config.erl | 124 +++++++------------- 1 file changed, 41 insertions(+), 83 deletions(-) diff --git a/src/muc_light/mod_muc_light_room_config.erl b/src/muc_light/mod_muc_light_room_config.erl index 67fbd62d27..5f664e8ee6 100644 --- a/src/muc_light/mod_muc_light_room_config.erl +++ b/src/muc_light/mod_muc_light_room_config.erl @@ -21,43 +21,20 @@ %%%---------------------------------------------------------------------- -module(mod_muc_light_room_config). --author('piotr.nosek@erlang-solutions.com'). %% API --export([schema_from_definition/1, default_from_schema/1]). --export([schema_reverse_find/2]). --export([apply_binary_kv/3, to_binary_kv/2]). - -%% Test helpers --export([schema_fields/1, schema_reverse_index/1]). - --ignore_xref([schema_fields/1, schema_reverse_find/2, schema_reverse_index/1]). +-export([from_binary_kv_diff/2, from_binary_kv/2, to_binary_kv/2]). -include("jlib.hrl"). -include("mongoose.hrl"). -include("mod_muc_light.hrl"). --export_type([schema/0, binary_kv/0, kv/0, user_defined_schema/0]). +-export_type([binary_kv/0, kv/0, schema/0]). %% Config primitives -type key() :: atom(). -type value() :: binary() | integer() | float(). -type value_type() :: binary | integer | float. --type form_field_name() :: binary(). - -%% Schema --record(schema, { - fields = #{}, - reverse_index = #{} - }). - --type schema_item() :: {Default :: value(), key(), value_type()}. --type schema_fields_map() :: #{ form_field_name() => schema_item() }. --type schema_reverse_index() :: #{ key() => form_field_name() }. --type schema() :: #schema{ - fields :: schema_fields_map(), - reverse_index :: schema_reverse_index() - }. %% Actual config -type item() :: {key(), value()}. @@ -65,83 +42,64 @@ -type binary_kv() :: [{Key :: binary(), Value :: binary()}]. %% User definition processing --type user_defined_schema_item() :: {FieldName :: binary(), DefaultValue :: value(), +-type schema_item() :: {FieldName :: binary(), DefaultValue :: value(), key(), value_type()}. --type user_defined_schema() :: [user_defined_schema_item()]. +-type schema() :: [schema_item()]. % has to be sorted %%==================================================================== %% API %%==================================================================== --spec schema_from_definition(UserDefinedSchema :: user_defined_schema()) -> schema(). -schema_from_definition(UserDefinedSchema) when is_list(UserDefinedSchema) -> - lists:foldl(fun add_config_schema_field/2, #schema{}, UserDefinedSchema). - --spec default_from_schema(ConfigSchema :: schema()) -> kv(). -default_from_schema(ConfigSchema) -> - lists:foldl(fun({DefaultValue, Key, _}, Acc) -> [{Key, DefaultValue} | Acc]; - (_, Acc) -> Acc - end, [], maps:values(ConfigSchema#schema.fields)). - --spec schema_reverse_find(Key :: key(), ConfigSchema :: schema()) -> - {ok, form_field_name()} | error. -schema_reverse_find(Key, ConfigSchema) -> - maps:find(Key, ConfigSchema#schema.reverse_index). - %% Guarantees that config will have unique fields --spec apply_binary_kv(RawConfig :: binary_kv(), Config :: kv(), ConfigSchema :: schema()) -> +-spec from_binary_kv_diff(RawConfig :: binary_kv(), ConfigSchema :: schema()) -> {ok, kv()} | validation_error(). -apply_binary_kv([], Config, _ConfigSchema) -> +from_binary_kv_diff(RawConfig, ConfigSchema) -> + from_binary_kv_diff(lists:ukeysort(1, RawConfig), ConfigSchema, []). + +from_binary_kv_diff([], [], Config) -> {ok, Config}; -apply_binary_kv([{KeyBin, ValBin} | RRawConfig], Config, ConfigSchema) -> - case from_kv_tuple(KeyBin, ValBin, ConfigSchema) of - {ok, Key, Val} -> - apply_binary_kv(RRawConfig, lists:keystore(Key, 1, Config, {Key, Val}), ConfigSchema); - Error -> - Error +from_binary_kv_diff(RawConfig, ConfigSchema, Config) -> + case take_next_kv(RawConfig, ConfigSchema) of + {error, Reason} -> + {error, Reason}; + {value, RRawConfig, RConfigSchema, KV} -> + from_binary_kv(RRawConfig, RConfigSchema, [KV | Config]); + {default, _, _, _} -> + % do not populate the diff with default values + from_binary_kv(RawConfig, ConfigSchema, Config) end. --spec to_binary_kv(Config :: kv(), ConfigSchema :: schema()) -> binary_kv(). -to_binary_kv([], _ConfigSchema) -> - []; -to_binary_kv([{Key, Val} | RConfig], ConfigSchema) -> - {ok, KeyBin} = schema_reverse_find(Key, ConfigSchema), - {_Def, _Key, ValType} = maps:get(KeyBin, ConfigSchema#schema.fields), - [{KeyBin, value2b(Val, ValType)} | to_binary_kv(RConfig, ConfigSchema)]. +-spec from_binary_kv(RawConfig :: binary_kv(), ConfigSchema :: schema()) -> + {ok, kv()} | validation_error(). +from_binary_kv(RawConfig, ConfigSchema) -> + from_binary_kv(lists:ukeysort(1, RawConfig), ConfigSchema, []). -%%==================================================================== -%% API for unit tests -%%==================================================================== +from_binary_kv([], [], Config) -> + {ok, Config}; +from_binary_kv(RawConfig, ConfigSchema, Config) -> + case take_next_kv(RawConfig, ConfigSchema) of + {error, Reason} -> + {error, Reason}; + {_, RRawConfig, RConfigSchema, KV} -> + from_binary_kv(RRawConfig, RConfigSchema, [KV | Config]) + end. --spec schema_fields(schema()) -> schema_fields_map(). -schema_fields(#schema{ fields = Fields }) -> Fields. +take_next_kv([{KeyBin, ValBin} | RRawConfig], [{KeyBin, _Default, Key, Type} | RSchema]) -> + {value, RRawConfig, RSchema, {Key, b2value(ValBin, Type)}}; +take_next_kv(RawConfig, [{_KeyBin, Default, Key, _Type} | RSchema]) -> + {default, RawConfig, RSchema, {Key, Default}}; +take_next_kv([{KeyBin, _} | _], _) -> + {error, {KeyBin, not_found}}. --spec schema_reverse_index(schema()) -> schema_reverse_index(). -schema_reverse_index(#schema{ reverse_index = RevIndex }) -> RevIndex. +-spec to_binary_kv(Config :: kv(), ConfigSchema :: schema()) -> binary_kv(). +to_binary_kv(Config, ConfigSchema) -> + ConfigWithSchema = lists:zip(lists:sort(Config), lists:keysort(3, ConfigSchema)), + [{KeyBin, value2b(Val, Type)} || {{Key, Val}, {KeyBin, _Default, Key, Type}} <- ConfigWithSchema]. %%==================================================================== %% Internal functions %%==================================================================== --spec add_config_schema_field(UserDefinedSchemaItem :: user_defined_schema_item(), - SchemaAcc :: schema()) -> - schema(). -add_config_schema_field({FieldName, DefaultValue, Key, ValueType}, SchemaAcc) -> - #schema{ fields = Fields0, reverse_index = RevIndex0 } = SchemaAcc, - - NFields = Fields0#{ FieldName => { DefaultValue, Key, ValueType } }, - NRevIndex = RevIndex0#{ Key => FieldName }, - - SchemaAcc#schema{ fields = NFields, reverse_index = NRevIndex }. - --spec from_kv_tuple(KeyBin :: binary(), ValBin :: binary(), ConfigSchema :: schema()) -> - {ok, Key :: atom(), Val :: any()} | validation_error(). -from_kv_tuple(KeyBin, ValBin, ConfigSchema) -> - case maps:find(KeyBin, ConfigSchema#schema.fields) of - {ok, {_Def, Key, Type}} -> {ok, Key, b2value(ValBin, Type)}; - _ -> {error, {KeyBin, unknown}} - end. - -spec b2value(ValBin :: binary(), Type :: value_type()) -> Converted :: value(). b2value(ValBin, binary) -> ValBin; b2value(ValBin, integer) -> binary_to_integer(ValBin); From 25c819225a6debb687547f73926d784fb9e582bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chrz=C4=85szcz?= Date: Fri, 5 Nov 2021 15:21:40 +0100 Subject: [PATCH 3/6] Use the new config processing API and drop the dynamic opts --- src/muc_light/mod_muc_light.erl | 57 +++++++++--------------- src/muc_light/mod_muc_light_db_rdbms.erl | 8 ++-- src/muc_light/mod_muc_light_room.erl | 4 +- 3 files changed, 26 insertions(+), 43 deletions(-) diff --git a/src/muc_light/mod_muc_light.erl b/src/muc_light/mod_muc_light.erl index eb695de8a5..58125ad0ec 100644 --- a/src/muc_light/mod_muc_light.erl +++ b/src/muc_light/mod_muc_light.erl @@ -24,9 +24,9 @@ -behaviour(mongoose_module_metrics). %% API --export([default_schema_definition/0, default_host/0]). +-export([default_host/0]). -export([server_host_to_muc_host/2]). --export([config_schema/1, default_config/1]). +-export([config_schema/1]). %% For Administration API -export([try_to_create_room/3, @@ -63,7 +63,8 @@ -export([subdomain_pattern/1]). %% For tests --export([set_module_opt_from_ct/3, +-export([default_schema/0, + set_module_opt_from_ct/3, force_clear_from_ct/0]). -define(MOD_MUC_LIGHT_DB_BACKEND_BACKEN, mod_muc_light_db_backend). @@ -82,7 +83,7 @@ {?MOD_MUC_LIGHT_DB_BACKEND_BACKEN, create_room, 4}, {?MOD_MUC_LIGHT_CODEC_BACKEND_BACKEN, decode, 4}, add_rooms_to_roster/2, apply_rsm/3, can_access_identity/4, can_access_room/4, - default_config/1, default_schema_definition/0, disco_local_items/1, + default_schema/0, disco_local_items/1, force_clear_from_ct/0, is_muc_room_owner/4, prevent_service_unavailable/4, process_iq_get/5, process_iq_set/4, remove_domain/3, remove_user/3, set_module_opt_from_ct/3, server_host_to_muc_host/2 @@ -99,38 +100,29 @@ supported_features() -> [dynamic_domains]. --spec default_schema_definition() -> mod_muc_light_room_config:user_defined_schema(). -default_schema_definition() -> - [{"roomname", "Untitled"}, - {"subject", ""}]. +-spec default_schema() -> mod_muc_light_room_config:schema(). +default_schema() -> + % This list needs to be sorted + [{<<"roomname">>, <<"Untitled">>, roomname, binary}, + {<<"subject">>, <<>>, subject, binary}]. -spec default_host() -> mongoose_subdomain_utils:subdomain_pattern(). default_host() -> mongoose_subdomain_utils:make_subdomain_pattern(<<"muclight.@HOST@">>). --spec default_config(MUCServer :: muc_server()) -> mod_muc_light_room_config:kv(). -default_config(MUCServer) -> - HostType = mod_muc_light_utils:muc_host_to_host_type(MUCServer), - default_config_for_host_type(HostType). - -spec config_schema(MUCServer :: muc_server()) -> mod_muc_light_room_config:schema(). config_schema(MUCServer) -> HostType = mod_muc_light_utils:muc_host_to_host_type(MUCServer), config_schema_for_host_type(HostType). %% Internals --spec default_config_for_host_type(host_type()) -> mod_muc_light_room_config:kv(). -default_config_for_host_type(HostType) -> - gen_mod:get_module_opt(HostType, ?MODULE, computed_default_config, []). -spec config_schema_for_host_type(host_type()) -> mod_muc_light_room_config:schema(). config_schema_for_host_type(HostType) -> - gen_mod:get_module_opt(HostType, ?MODULE, computed_config_schema, undefined). + gen_mod:get_module_opt(HostType, ?MODULE, config_schema, default_schema()). set_module_opt_from_ct(HostType, K, V) -> - gen_mod:set_module_opt(HostType, ?MODULE, K, V), - Opts = gen_mod:get_module_opts(HostType, ?MODULE), - set_dynamic_opts(HostType, Opts). + gen_mod:set_module_opt(HostType, ?MODULE, K, V). force_clear_from_ct() -> mod_muc_light_db_backend:force_clear(). @@ -191,7 +183,6 @@ delete_room(RoomUS) -> -spec start(HostType :: host_type(), Opts :: list()) -> ok. start(HostType, Opts) -> - set_dynamic_opts(HostType, Opts), Codec = host_type_to_codec(HostType), gen_mod:start_backend_module(mod_muc_light_db, Opts, tracked_db_funs()), gen_mod:start_backend_module(mod_muc_light_codec, [{backend, Codec}], []), @@ -232,16 +223,6 @@ tracked_db_funs() -> get_config, set_config, get_blocking, set_blocking, get_aff_users, modify_aff_users]. -set_dynamic_opts(HostType, Opts) -> - %% Prepare config schema - Def = gen_mod:get_opt(config_schema, Opts, default_schema_definition()), - ConfigSchema = mod_muc_light_room_config:schema_from_definition(Def), - %% XXX That is a bad style - gen_mod:set_module_opt(HostType, ?MODULE, computed_config_schema, ConfigSchema), - %% Prepare default config - DefaultConfig = mod_muc_light_room_config:default_from_schema(ConfigSchema), - gen_mod:set_module_opt(HostType, ?MODULE, computed_default_config, DefaultConfig). - %% Config callbacks -spec config_spec() -> mongoose_config_spec:config_section(). config_spec() -> @@ -263,7 +244,8 @@ config_spec() -> <<"rooms_per_page">> => #option{type = int_or_infinity, validate = positive}, <<"rooms_in_rosters">> => #option{type = boolean}, - <<"config_schema">> => #list{items = config_schema_spec()} + <<"config_schema">> => #list{items = config_schema_spec(), + process = fun ?MODULE:process_config_schema/1} } }. @@ -277,11 +259,13 @@ config_schema_spec() -> <<"internal_key">> => #option{type = atom, validate = non_empty} }, - required = [<<"field">>], - process = fun ?MODULE:process_config_schema/1 + required = [<<"field">>] }. -process_config_schema(KVs) -> +process_config_schema(Items) -> + lists:ukeysort(1, lists:map(fun process_config_schema_item/1, Items)). + +process_config_schema_item(KVs) -> {[[{field, FieldName}], InternalKeyOpts], ValueOpts} = proplists:split(KVs, [field, internal_key]), {Value, Type} = process_config_schema_value(ValueOpts), @@ -558,9 +542,8 @@ can_access_identity(_Acc, _HostType, _Room, _User) -> %%==================================================================== prepare_config(HostType, RawConfig) -> - DefConfig = default_config_for_host_type(HostType), Schema = config_schema_for_host_type(HostType), - mod_muc_light_room_config:apply_binary_kv(RawConfig, DefConfig, Schema). + mod_muc_light_room_config:from_binary_kv(RawConfig, Schema). prepare_affs(HostType, CreatorJid, RoomUS, #create{aff_users = AffUsers}) -> CreatorUS = jid:to_lus(CreatorJid), diff --git a/src/muc_light/mod_muc_light_db_rdbms.erl b/src/muc_light/mod_muc_light_db_rdbms.erl index cc1ad50fab..80af07310a 100644 --- a/src/muc_light/mod_muc_light_db_rdbms.erl +++ b/src/muc_light/mod_muc_light_db_rdbms.erl @@ -495,8 +495,8 @@ get_config({RoomU, RoomS} = RoomUS) -> {ok, [], Version}; [{Version, _, _} | _] -> RawConfig = [{Key, Val} || {_, Key, Val} <- Result], - {ok, Config} = mod_muc_light_room_config:apply_binary_kv( - RawConfig, [], mod_muc_light:config_schema(RoomS)), + {ok, Config} = mod_muc_light_room_config:from_binary_kv( + RawConfig, mod_muc_light:config_schema(RoomS)), {ok, Config, Version} end. @@ -596,8 +596,8 @@ get_info({RoomU, RoomS} = RoomUS) -> {selected, AffUsersDB} = select_affs_by_room_id(HostType, RoomID), AffUsers = decode_affs(AffUsersDB), {selected, ConfigDB} = select_config_by_room_id(HostType, RoomID), - {ok, Config} = mod_muc_light_room_config:apply_binary_kv( - ConfigDB, [], mod_muc_light:config_schema(RoomS)), + {ok, Config} = mod_muc_light_room_config:from_binary_kv( + ConfigDB, mod_muc_light:config_schema(RoomS)), {ok, Config, AffUsers, Version}; {selected, []} -> diff --git a/src/muc_light/mod_muc_light_room.erl b/src/muc_light/mod_muc_light_room.erl index e7828ec8da..0b4ca102e3 100644 --- a/src/muc_light/mod_muc_light_room.erl +++ b/src/muc_light/mod_muc_light_room.erl @@ -185,8 +185,8 @@ process_config_set(#config{ raw_config = [{<<"subject">>, _}] } = ConfigReq, Roo process_config_set(_ConfigReq, _RoomUS, member, _AffUsers, false) -> {error, not_allowed}; process_config_set(ConfigReq, {_, RoomS} = RoomUS, _UserAff, AffUsers, _AllCanConfigure) -> - case mod_muc_light_room_config:apply_binary_kv( - ConfigReq#config.raw_config, [], mod_muc_light:config_schema(RoomS)) of + case mod_muc_light_room_config:from_binary_kv_diff( + ConfigReq#config.raw_config, mod_muc_light:config_schema(RoomS)) of {ok, Config} -> NewVersion = mongoose_bin:gen_from_timestamp(), {ok, PrevVersion} = mod_muc_light_db_backend:set_config(RoomUS, Config, NewVersion), From f39790db25df0985d537060cf1dea9acdd1af02b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chrz=C4=85szcz?= Date: Fri, 5 Nov 2021 15:23:25 +0100 Subject: [PATCH 4/6] Update config tests for the config schema --- test/config_parser_SUITE.erl | 16 ++++++++++++---- test/config_parser_SUITE_data/modules.options | 8 ++++---- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/test/config_parser_SUITE.erl b/test/config_parser_SUITE.erl index de16b17f99..ab8687ba04 100644 --- a/test/config_parser_SUITE.erl +++ b/test/config_parser_SUITE.erl @@ -2410,15 +2410,23 @@ mod_muc_light_config_schema(_Config) -> M = fun(Cfg) -> modopts(mod_muc_light, [{config_schema, Cfg}]) end, Field = #{<<"field">> => <<"my_field">>}, ?eqf(M([]), T([])), - ?eqf(M([{"my_field", <<"My Room">>, my_field, binary}]), + ?eqf(M([{<<"my_field">>, <<"My Room">>, my_field, binary}]), T([Field#{<<"string_value">> => <<"My Room">>}])), - ?eqf(M([{"my_field", 1, my_field, integer}]), + ?eqf(M([{<<"my_field">>, 1, my_field, integer}]), T([Field#{<<"integer_value">> => 1}])), - ?eqf(M([{"my_field", 0.5, my_field, float}]), + ?eqf(M([{<<"my_field">>, 0.5, my_field, float}]), T([Field#{<<"float_value">> => 0.5}])), - ?eqf(M([{"my_field", 0, your_field, integer}]), + ?eqf(M([{<<"my_field">>, 0, your_field, integer}]), T([Field#{<<"integer_value">> => 0, <<"internal_key">> => <<"your_field">>}])), + ?eqf(M([{<<"żółć"/utf8>>, <<"Рентгеноэлектрокардиографический"/utf8>>, 'żółć', binary}]), + T([#{<<"field">> => <<"żółć"/utf8>>, + <<"string_value">> => <<"Рентгеноэлектрокардиографический"/utf8>>}])), + ?eqf(M([{<<"first">>, 1, first, integer}, % the config is u-key-sorted + {<<"second">>, <<"two">>, second, binary}]), + T([#{<<"field">> => <<"second">>, <<"string_value">> => <<"two">>}, + #{<<"field">> => <<"second">>, <<"float_value">> => 2.0}, + #{<<"field">> => <<"first">>, <<"integer_value">> => 1}])), ?errf(T([#{<<"string_value">> => <<"My Room">>}])), ?errf(T([#{<<"field">> => <<>>, <<"string_value">> => <<"My Room">>}])), diff --git a/test/config_parser_SUITE_data/modules.options b/test/config_parser_SUITE_data/modules.options index 9765d976f3..335e6005c5 100644 --- a/test/config_parser_SUITE_data/modules.options +++ b/test/config_parser_SUITE_data/modules.options @@ -197,8 +197,8 @@ {host,{fqdn,<<"muclight.example.com">>}}, {equal_occupants,true}, {config_schema, - [{"roomname",<<"The Room">>,roomname,binary}, - {"display-lines",30,display_lines,integer}]}, + [{<<"roomname">>,<<"The Room">>,roomname,binary}, + {<<"display-lines">>,30,display_lines,integer}]}, {blocking,false}, {all_can_invite,true}, {all_can_configure,true}]}, @@ -461,8 +461,8 @@ {host,{fqdn,<<"muclight.example.com">>}}, {equal_occupants,true}, {config_schema, - [{"roomname",<<"The Room">>,roomname,binary}, - {"display-lines",30,display_lines,integer}]}, + [{<<"roomname">>,<<"The Room">>,roomname,binary}, + {<<"display-lines">>,30,display_lines,integer}]}, {blocking,false}, {all_can_invite,true}, {all_can_configure,true}]}, From 90e83c80939b160e36f9068771825a760188d08a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chrz=C4=85szcz?= Date: Fri, 5 Nov 2021 15:24:14 +0100 Subject: [PATCH 5/6] Remove the schema processing tests from muc_light_SUITE The schema is now fully tested in config_parser_SUITE --- test/muc_light_SUITE.erl | 99 +--------------------------------------- 1 file changed, 2 insertions(+), 97 deletions(-) diff --git a/test/muc_light_SUITE.erl b/test/muc_light_SUITE.erl index 05b5fb01c8..7dc9ee2cad 100644 --- a/test/muc_light_SUITE.erl +++ b/test/muc_light_SUITE.erl @@ -19,8 +19,7 @@ all() -> [ {group, aff_changes}, {group, rsm_disco}, - {group, codec}, - {group, configuration} + {group, codec} ]. groups() -> @@ -33,15 +32,7 @@ groups() -> rsm_disco_success, rsm_disco_item_not_found ]}, - {codec, [sequence], [codec_calls]}, - {configuration, [parallel], [ - simple_config_items_are_parsed, - full_config_items_are_parsed, - invalid_binary_default_value_is_rejected, - invalid_integer_default_value_is_rejected, - invalid_float_default_value_is_rejected, - unicode_config_fields_are_supported - ]} + {codec, [sequence], [codec_calls]} ]. init_per_suite(Config) -> @@ -157,92 +148,6 @@ codec_calls(_Config) -> filter_room_packet_handler(Acc, _Params, _Extra) -> count_call(hook), {ok, Acc}. -%% ----------------- Room config schema ---------------------- - -simple_config_items_are_parsed(_Config) -> - Definition = [ - {"roomname", "TARDIS"}, - {"subject", "Time Travel"}, - {"incarnation", "13"}, - {"spoilers", "false"} - ], - Schema = mod_muc_light_room_config:schema_from_definition(Definition), - - ExpectedFields = #{ - <<"roomname">> => {<<"TARDIS">>, roomname, binary}, - <<"subject">> => {<<"Time Travel">>, subject, binary}, - <<"incarnation">> => {<<"13">>, incarnation, binary}, - <<"spoilers">> => {<<"false">>, spoilers, binary} - }, - ?assertEqual(ExpectedFields, mod_muc_light_room_config:schema_fields(Schema)), - - ExpectedRevIndex = #{ - roomname => <<"roomname">>, - subject => <<"subject">>, - incarnation => <<"incarnation">>, - spoilers => <<"spoilers">> - }, - ?assertEqual(ExpectedRevIndex, mod_muc_light_room_config:schema_reverse_index(Schema)). - - -full_config_items_are_parsed(_Config) -> - Definition = [ - {"roomname", "TARDIS", roomname, binary}, - {"subject", "Time Travel", subject, binary}, - {"incarnation", 13, incarnation, integer}, - {"height", 1.67, height, float} - ], - Schema = mod_muc_light_room_config:schema_from_definition(Definition), - - ExpectedFields = #{ - <<"roomname">> => {<<"TARDIS">>, roomname, binary}, - <<"subject">> => {<<"Time Travel">>, subject, binary}, - <<"incarnation">> => {13, incarnation, integer}, - <<"height">> => {1.67, height, float} - }, - ?assertEqual(ExpectedFields, mod_muc_light_room_config:schema_fields(Schema)), - - ExpectedRevIndex = #{ - roomname => <<"roomname">>, - subject => <<"subject">>, - incarnation => <<"incarnation">>, - height => <<"height">> - }, - ?assertEqual(ExpectedRevIndex, mod_muc_light_room_config:schema_reverse_index(Schema)). - - -invalid_binary_default_value_is_rejected(_Config) -> - ?assertError(_, mod_muc_light_room_config:schema_from_definition([{"roomname", 12345}])), - ?assertError(_, mod_muc_light_room_config:schema_from_definition([{"roomname", 12345, - roomname, binary}])). - -invalid_integer_default_value_is_rejected(_Config) -> - ?assertError(_, mod_muc_light_room_config:schema_from_definition([{"incarnation", 123.45, - incarnation, integer}])). - -invalid_float_default_value_is_rejected(_Config) -> - ?assertError(_, mod_muc_light_room_config:schema_from_definition([{"height", 12345, - height, float}])). - -unicode_config_fields_are_supported(_Config) -> - Definition = [{"zażółćgęśląjaźń", "gżegżółka"}, - {"Рентгеноэлектрокардиографический", 42, - 'Рентгеноэлектрокардиографический', integer}], - Schema = mod_muc_light_room_config:schema_from_definition(Definition), - - ExpectedFields = #{ - <<"zażółćgęśląjaźń"/utf8>> => {<<"gżegżółka"/utf8>>, 'zażółćgęśląjaźń', binary}, - <<"Рентгеноэлектрокардиографический"/utf8>> => - {42, 'Рентгеноэлектрокардиографический', integer} - }, - ?assertEqual(ExpectedFields, mod_muc_light_room_config:schema_fields(Schema)), - - ExpectedRevIndex = #{ - 'zażółćgęśląjaźń' => <<"zażółćgęśląjaźń"/utf8>>, - 'Рентгеноэлектрокардиографический' => <<"Рентгеноэлектрокардиографический"/utf8>> - }, - ?assertEqual(ExpectedRevIndex, mod_muc_light_room_config:schema_reverse_index(Schema)). - %% ------------------------------------------------------------------ %% Properties and validators From fb042ee6b41b4a6db3c27386e708cdc1dfb6bd13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chrz=C4=85szcz?= Date: Fri, 5 Nov 2021 15:26:08 +0100 Subject: [PATCH 6/6] Update MUC Light tests with the simplified config schema format Whenever possible, call deafult_config(Schema) to verify against the specific expected schema instead of the one from MIM. Use default_config() only in room creation helpers. --- big_tests/tests/muc_light_SUITE.erl | 66 +++++++++------------- big_tests/tests/muc_light_helper.erl | 30 ++++++++-- big_tests/tests/muc_light_legacy_SUITE.erl | 29 ++++------ 3 files changed, 60 insertions(+), 65 deletions(-) diff --git a/big_tests/tests/muc_light_SUITE.erl b/big_tests/tests/muc_light_SUITE.erl index 33a8e52d62..a1498d1c1d 100644 --- a/big_tests/tests/muc_light_SUITE.erl +++ b/big_tests/tests/muc_light_SUITE.erl @@ -90,10 +90,11 @@ stanza_create_room/3, create_room/6, stanza_aff_set/2, - default_config/0, user_leave/3, set_mod_config/3, - stanza_blocking_set/1 + stanza_blocking_set/1, + default_config/1, + default_schema/0 ]). -include("muc_light.hrl"). @@ -103,9 +104,6 @@ -define(MUCHOST, (muc_light_helper:muc_host())). --define(CHECK_FUN, fun mod_muc_light_room:participant_limit_check/2). --define(BACKEND, mod_muc_light_db_backend). - -type ct_aff_user() :: {EscalusClient :: escalus:client(), Aff :: atom()}. -type ct_aff_users() :: [ct_aff_user()]. -type ct_block_item() :: muc_light_helper:ct_block_item(). @@ -252,7 +250,7 @@ init_per_testcase(disco_rooms_rsm, Config) -> init_per_testcase(CaseName, Config) -> set_default_mod_config(), case lists:member(CaseName, ?CUSTOM_CONFIG_CASES) of - true -> set_custom_config(common_custom_config()); + true -> set_config_schema(custom_schema()); _ -> ok end, case lists:member(CaseName, ?ROOM_LESS_CASES) of @@ -268,7 +266,7 @@ end_per_testcase(CaseName, Config) when CaseName =:= disco_features_with_mam; escalus:end_per_testcase(CaseName, Config); end_per_testcase(CaseName, Config) -> case lists:member(CaseName, ?CUSTOM_CONFIG_CASES) of - true -> set_custom_config(default_schema_definition()); + true -> set_config_schema(default_schema()); _ -> ok end, muc_light_helper:clear_db(), @@ -437,7 +435,7 @@ rooms_in_rosters(Config) -> RosterResult, [{element, <<"query">>}, {element, <<"item">>}]), ProperJID = room_bin_jid(?ROOM), ProperJID = exml_query:attr(Item, <<"jid">>), - ProperName = proplists:get_value(roomname, default_config()), + ProperName = proplists:get_value(<<"roomname">>, default_config(default_schema())), ProperName = exml_query:attr(Item, <<"name">>), ProperVer = ver(1), ProperVer = exml_query:path(Item, [{element, <<"version">>}, cdata]) @@ -535,7 +533,7 @@ set_config_deny(Config) -> get_room_config(Config) -> escalus:story(Config, [{alice, 1}, {bob, 1}, {kate, 1}], fun(Alice, Bob, Kate) -> Stanza = stanza_config_get(?ROOM, <<"oldver">>), - ConfigKV = [{"version", binary_to_list(ver(1))} | standard_default_config()], + ConfigKV = [{<<"version">>, ver(1)} | default_config(default_schema())], foreach_occupant([Alice, Bob, Kate], Stanza, config_iq_verify_fun(ConfigKV)), %% Empty result when user has most recent version @@ -548,7 +546,7 @@ get_room_config(Config) -> custom_default_config_works(Config) -> escalus:story(Config, [{alice, 1}, {bob, 1}, {kate, 1}], fun(Alice, Bob, Kate) -> Stanza = stanza_config_get(?ROOM, <<"oldver">>), - ConfigKV = [{"version", binary_to_list(ver(1))} | common_custom_config()], + ConfigKV = [{<<"version">>, ver(1)} | default_config(custom_schema())], foreach_occupant([Alice, Bob, Kate], Stanza, config_iq_verify_fun(ConfigKV)) end). @@ -568,10 +566,9 @@ get_room_occupants(Config) -> get_room_info(Config) -> escalus:story(Config, [{alice, 1}, {bob, 1}, {kate, 1}], fun(Alice, Bob, Kate) -> Stanza = stanza_info_get(?ROOM, <<"oldver">>), - ConfigKV = default_config(), - ConfigKVBin = [{list_to_binary(atom_to_list(Key)), Val} || {Key, Val} <- ConfigKV], + ConfigKV = default_config(default_schema()), foreach_occupant([Alice, Bob, Kate], Stanza, - info_iq_verify_fun(?DEFAULT_AFF_USERS, ver(1), ConfigKVBin)), + info_iq_verify_fun(?DEFAULT_AFF_USERS, ver(1), ConfigKV)), escalus:send(Bob, stanza_aff_get(?ROOM, ver(1))), IQRes = escalus:wait_for_stanza(Bob), @@ -966,7 +963,7 @@ stanza_aff_get(Room, Ver) -> stanza_destroy_room(Room) -> escalus_stanza:to(escalus_stanza:iq_set(?NS_MUC_LIGHT_DESTROY, []), room_bin_jid(Room)). --spec stanza_config_set(Room :: binary(), ConfigChanges :: [{binary(), binary()}]) -> xmlel(). +-spec stanza_config_set(Room :: binary(), ConfigChanges :: [muc_light_helper:config_item()]) -> xmlel(). stanza_config_set(Room, ConfigChanges) -> Items = [ kv_el(Key, Value) || {Key, Value} <- ConfigChanges], escalus_stanza:to( @@ -1008,7 +1005,7 @@ verify_no_stanzas(Users) -> {false, _} = {escalus_client:has_stanzas(User), User} end, Users). --spec verify_config(ConfigRoot :: xmlel(), Config :: [{binary(), binary()}]) -> ok. +-spec verify_config(ConfigRoot :: xmlel(), Config :: [muc_light_helper:config_item()]) -> ok. verify_config(ConfigRoot, Config) -> lists:foreach( fun({Key, Val}) -> @@ -1019,7 +1016,7 @@ verify_config(ConfigRoot, Config) -> %% Verification funs generators %%-------------------------------------------------------------------- --spec config_msg_verify_fun(RoomConfig :: [{binary(), binary()}]) -> verify_fun(). +-spec config_msg_verify_fun(RoomConfig :: [muc_light_helper:config_item()]) -> verify_fun(). config_msg_verify_fun(RoomConfig) -> fun(Incoming) -> escalus:assert(is_groupchat_message, Incoming), @@ -1036,14 +1033,12 @@ config_msg_verify_fun(RoomConfig) -> end, RoomConfig) end. --spec config_iq_verify_fun(RoomConfig :: [{string(), string()}]) -> verify_fun(). +-spec config_iq_verify_fun(RoomConfig :: [muc_light_helper:config_item()]) -> verify_fun(). config_iq_verify_fun(RoomConfig) -> fun(Incoming) -> [Query] = exml_query:subelements(Incoming, <<"query">>), ?NS_MUC_LIGHT_CONFIGURATION = exml_query:attr(Query, <<"xmlns">>), - BinaryRoomConfig = [{list_to_binary(K), list_to_binary(V)} - || {K, V} <- RoomConfig], - verify_config(Query, BinaryRoomConfig) + verify_config(Query, RoomConfig) end. -spec aff_iq_verify_fun(AffUsers :: ct_aff_users(), Version :: binary()) -> verify_fun(). @@ -1058,8 +1053,8 @@ aff_iq_verify_fun(AffUsers, Version) -> end. -spec info_iq_verify_fun(AffUsers :: ct_aff_users(), Version :: binary(), - ConfigKVBin :: [{binary(), binary()}]) -> verify_fun(). -info_iq_verify_fun(AffUsers, Version, ConfigKVBin) -> + ConfigKV :: [muc_light_helper:config_item()]) -> verify_fun(). +info_iq_verify_fun(AffUsers, Version, ConfigKV) -> BinAffUsers = bin_aff_users(AffUsers), fun(Incoming) -> [Query] = exml_query:subelements(Incoming, <<"query">>), @@ -1069,7 +1064,7 @@ info_iq_verify_fun(AffUsers, Version, ConfigKVBin) -> {element, <<"user">>}]), verify_aff_users(UsersItems, BinAffUsers), ConfigurationEl = exml_query:subelement(Query, <<"configuration">>), - verify_config(ConfigurationEl, ConfigKVBin) + verify_config(ConfigurationEl, ConfigKV) end. -spec verify_user_has_one_room(User :: escalus:client()) -> any(). @@ -1106,20 +1101,11 @@ assert_process_memory_not_growing(Pid, OldMemory, Counter) -> end, assert_process_memory_not_growing(Pid, Memory, NewCounter). --spec common_custom_config() -> list(). -common_custom_config() -> [{"background", "builtin:hell"}, {"music", "builtin:screams"}]. - --spec default_schema_definition() -> list(). -default_schema_definition() -> - rpc(mod_muc_light, default_schema_definition, []). - --spec standard_default_config() -> list(). -standard_default_config() -> - % Default schema definition is actually a proplist with the option name as a key - % and the default as a value, but we verify it to avoid strange errors. - DefaultConfig = default_schema_definition(), - lists:foreach(fun({K, V}) when is_list(K), is_list(V) -> ok end, DefaultConfig), - DefaultConfig. +-spec custom_schema() -> [muc_light_helper:schema_item()]. +custom_schema() -> + % This list needs to be sorted + [{<<"background">>, <<"builtin:hell">>, background, binary}, + {<<"music">>, <<"builtin:screams">>, music, binary}]. -spec set_default_mod_config() -> ok. set_default_mod_config() -> @@ -1135,6 +1121,6 @@ set_default_mod_config() -> {rooms_per_page, infinity} ]). --spec set_custom_config(UserDefSchema :: list()) -> any(). -set_custom_config(UserDefSchema) when is_list(UserDefSchema) -> - set_mod_config(config_schema, UserDefSchema, ?MUCHOST). +-spec set_config_schema(Schema :: list()) -> any(). +set_config_schema(Schema) when is_list(Schema) -> + set_mod_config(config_schema, Schema, ?MUCHOST). diff --git a/big_tests/tests/muc_light_helper.erl b/big_tests/tests/muc_light_helper.erl index 948b59bc71..c1cae03f90 100644 --- a/big_tests/tests/muc_light_helper.erl +++ b/big_tests/tests/muc_light_helper.erl @@ -15,7 +15,12 @@ -type ct_aff_users() :: [ct_aff_user()]. -type ct_block_item() :: {What :: atom(), Action :: atom(), Who :: binary()}. --export_type([ct_block_item/0]). +%% The tests use only binary config fields +-type schema_item() :: {binary(), binary(), atom(), binary}. +-type config_item() :: {binary(), binary()}. +-type internal_config_item() :: {atom(), binary()}. + +-export_type([ct_block_item/0, schema_item/0, config_item/0, internal_config_item/0]). -spec room_bin_jid(Room :: binary()) -> binary(). room_bin_jid(Room) -> @@ -28,7 +33,7 @@ muc_host_pattern() -> ct:get_config({hosts, mim, muc_light_service_pattern}). create_room(RoomU, MUCHost, Owner, Members, Config, Version) -> - DefaultConfig = default_config(), + DefaultConfig = default_internal_config(MUCHost), RoomUS = {RoomU, MUCHost}, AffUsers = [{to_lus(Owner, Config), owner} | [ {to_lus(Member, Config), member} || Member <- Members ]], @@ -37,10 +42,23 @@ create_room(RoomU, MUCHost, Owner, Members, Config, Version) -> {ok, _RoomUS} = rpc(mim(), mod_muc_light_db_backend, create_room, [RoomUS, DefaultConfig, AffUsersSort, Version]). --spec default_config() -> list(). -default_config() -> assert_list(rpc(mim(), mod_muc_light, default_config, [muc_host()])). +-spec default_internal_config(jid:lserver()) -> [internal_config_item()]. +default_internal_config(MUCHost) -> + Schema = rpc(mim(), mod_muc_light, config_schema, [MUCHost]), + {ok, Config} = rpc(mim(), mod_muc_light_room_config, from_binary_kv, [[], Schema]), + Config. + +-spec default_schema() -> [schema_item()]. +default_schema() -> + rpc(mim(), mod_muc_light, default_schema, []). + +-spec default_config([schema_item()]) -> [config_item()]. +default_config(Schema) -> + [config_item(SchemaItem) || SchemaItem <- Schema]. -assert_list(X) when is_list(X) -> X. +-spec config_item(schema_item()) -> config_item(). +config_item({BinKey, BinValue, _Key, binary}) when is_binary(BinKey), is_binary(BinValue) -> + {BinKey, BinValue}. -spec ns_muc_light_affiliations() -> binary(). ns_muc_light_affiliations() -> @@ -207,7 +225,7 @@ verify_aff_users(Items, BinAffUsers) -> Aff :: binary(), AffAcc :: list()) -> list(). verify_keytake({value, {_, Aff}, NewAffAcc}, _JID, Aff, _AffAcc) -> NewAffAcc. --spec stanza_create_room(RoomNode :: binary() | undefined, InitConfig :: [{binary(), binary()}], +-spec stanza_create_room(RoomNode :: binary() | undefined, InitConfig :: [config_item()], InitOccupants :: ct_aff_users()) -> exml:element(). stanza_create_room(RoomNode, InitConfig, InitOccupants) -> Host = muc_host(), diff --git a/big_tests/tests/muc_light_legacy_SUITE.erl b/big_tests/tests/muc_light_legacy_SUITE.erl index 61c4c84a5c..d820f25a45 100644 --- a/big_tests/tests/muc_light_legacy_SUITE.erl +++ b/big_tests/tests/muc_light_legacy_SUITE.erl @@ -57,7 +57,10 @@ bin_aff_users/1, to_lus/2, lbin/1, - set_mod_config/3 + create_room/6, + set_mod_config/3, + default_config/1, + default_schema/0 ]). -define(ROOM, <<"testroom">>). @@ -68,9 +71,6 @@ -define(MUCHOST, (muc_helper:muc_host())). --define(CHECK_FUN, fun mod_muc_light_room:participant_limit_check/2). --define(BACKEND, mod_muc_light_db_backend). - -type ct_aff_user() :: {EscalusClient :: escalus:client(), Aff :: atom()}. -type ct_aff_users() :: [ct_aff_user()]. -type ct_block_item() :: {What :: atom(), Action :: atom(), Who :: binary()}. @@ -198,11 +198,7 @@ end_per_testcase(CaseName, Config) -> %% ---------------------- Helpers ---------------------- create_room(RoomU, MUCHost, Owner, Members, Config) -> - DefaultConfig = default_config(), - RoomUS = {RoomU, MUCHost}, - AffUsers = [{to_lus(Owner, Config), owner} - | [ {to_lus(Member, Config), member} || Member <- Members ]], - {ok, _RoomUS} = rpc(?BACKEND, create_room, [RoomUS, DefaultConfig, AffUsers, <<"-">>]). + create_room(RoomU, MUCHost, Owner, Members, Config, <<"-">>). clear_db() -> muc_light_helper:clear_db(). @@ -336,9 +332,8 @@ set_config_deny(Config) -> get_room_config(Config) -> escalus:story(Config, [{alice, 1}, {bob, 1}, {kate, 1}], fun(Alice, Bob, Kate) -> Stanza = stanza_config_get(?ROOM), - ConfigKV = default_config(), - ConfigKVBin = [{list_to_binary(atom_to_list(Key)), Val} || {Key, Val} <- ConfigKV], - foreach_occupant([Alice, Bob, Kate], Stanza, config_iq_verify_fun(ConfigKVBin)) + ConfigKV = default_config(default_schema()), + foreach_occupant([Alice, Bob, Kate], Stanza, config_iq_verify_fun(ConfigKV)) end). get_room_occupants(Config) -> @@ -629,7 +624,7 @@ stanza_destroy_room(Room) -> escalus_stanza:to(escalus_stanza:iq_set(?NS_MUC_OWNER, [#xmlel{ name = <<"destroy">> }]), room_bin_jid(Room)). --spec stanza_config_set(Room :: binary(), ConfigChanges :: [{binary(), binary()}]) -> xmlel(). +-spec stanza_config_set(Room :: binary(), ConfigChanges :: [muc_light_helper:config_item()]) -> xmlel(). stanza_config_set(Room, ConfigChanges) -> IQ = escalus_stanza:iq_set(?NS_MUC_OWNER, [form_x_el(ConfigChanges)]), escalus_stanza:to(IQ, room_bin_jid(Room)). @@ -726,7 +721,7 @@ verify_no_stanzas(Users) -> {false, _} = {escalus_client:has_stanzas(User), User} end, Users). --spec verify_config(ConfigFields :: [xmlel()], Config :: [{binary(), binary()}]) -> ok. +-spec verify_config(ConfigFields :: [xmlel()], Config :: [muc_light_helper:config_item()]) -> ok. verify_config(ConfigFields, Config) -> [] = lists:foldl( fun(Field, ConfigAcc) -> @@ -787,7 +782,7 @@ config_msg_verify_fun() -> <<"104">> = exml_query:path(X, [{element, <<"status">>}, {attr, <<"code">>}]) end. --spec config_iq_verify_fun(RoomConfig :: [{binary(), binary()}]) -> verify_fun(). +-spec config_iq_verify_fun(RoomConfig :: [muc_light_helper:config_item()]) -> verify_fun(). config_iq_verify_fun(RoomConfig) -> fun(Incoming) -> Fields = exml_query:paths(Incoming, [{element, <<"query">>}, {element, <<"x">>}, @@ -859,10 +854,6 @@ presence_verify(User, UserAff, #xmlel{ name = <<"presence">> } = Incoming) -> %% Other helpers %%-------------------------------------------------------------------- --spec default_config() -> list(). -default_config() -> - rpc(mod_muc_light, default_config, [?MUCHOST]). - -spec set_default_mod_config() -> ok. set_default_mod_config() -> lists:foreach(