1: -module(config_parser_SUITE). 2: -compile([export_all, nowarn_export_all]). 3: 4: -include_lib("eunit/include/eunit.hrl"). 5: 6: -define(HOST, <<"example.com">>). 7: 8: -define(eq(Expected, Actual), ?assertEqual(Expected, Actual)). 9: 10: %% Assertions 11: 12: %% global config options 13: -define(cfg(Key, Value, RawConfig), ?cfg([{Key, Value}], RawConfig)). 14: -define(cfg(ExpectedOpts, RawConfig), assert_options(ExpectedOpts, parse(RawConfig))). 15: 16: %% global config error 17: -define(err(RawConfig), ?err(_, RawConfig)). 18: -define(err(Pattern, RawConfig), ?assertError({config_error, _, Pattern}, parse(RawConfig))). 19: 20: %% host-or-global config options 21: -define(cfgh(KeyPrefix, Value, RawConfig), ?cfgh([{KeyPrefix, Value}], RawConfig)). 22: -define(cfgh(ExpectedOpts, RawConfig), 23: begin 24: ?cfg(host_opts(ExpectedOpts), RawConfig), 25: ?cfg(host_opts(ExpectedOpts), host_config(RawConfig)) 26: end). 27: 28: %% host-or-global config error 29: -define(errh(RawConfig), ?errh(_, RawConfig)). 30: -define(errh(Pattern, RawConfig), 31: begin 32: ?err(Pattern, RawConfig), 33: ?err(Pattern, host_config(RawConfig)) 34: end). 35: 36: -import(mongoose_config_parser_toml, [extract_errors/1]). 37: -import(config_parser_helper, [merge_with_default_pool_config/1, default_s2s/0, 38: mod_config/2, default_mod_config/1, 39: config/2, default_config/1]). 40: 41: -type key_prefix() :: top_level_key_prefix() | key_path_prefix(). 42: -type top_level_key_prefix() :: atom(). 43: -type key_path_prefix() :: [atom() | binary()]. 44: 45: all() -> 46: [{group, file}, 47: {group, dynamic_domains}, 48: {group, general}, 49: {group, listen}, 50: {group, auth}, 51: {group, pool}, 52: {group, shaper_acl_access}, 53: {group, s2s}, 54: {group, modules}, 55: {group, services}]. 56: 57: groups() -> 58: [{file, [parallel], [sample_pgsql, 59: miscellaneous, 60: s2s, 61: modules, 62: outgoing_pools, 63: host_types_file]}, 64: {dynamic_domains, [parallel], [supported_features, 65: unsupported_features]}, 66: {general, [parallel], [loglevel, 67: hosts, 68: host_types, 69: default_server_domain, 70: registration_timeout, 71: language, 72: all_metrics_are_global, 73: sm_backend, 74: max_fsm_queue, 75: http_server_name, 76: rdbms_server_type, 77: route_subdomains, 78: mongooseimctl_access_commands, 79: routing_modules, 80: replaced_wait_timeout, 81: hide_service_name, 82: domain_certfile]}, 83: {listen, [parallel], [listen_portip, 84: listen_proto, 85: listen_duplicate, 86: listen_ip_version, 87: listen_backlog, 88: listen_proxy_protocol, 89: listen_num_acceptors, 90: listen_access, 91: listen_shaper, 92: listen_xml_socket, 93: listen_zlib, 94: listen_hibernate_after, 95: listen_max_fsm_queue, 96: listen_max_stanza_size, 97: listen_tls_mode, 98: listen_tls_module, 99: listen_tls_verify, 100: listen_tls_verify_mode, 101: listen_tls_crl_files, 102: listen_tls_certfile, 103: listen_tls_cacertfile, 104: listen_tls_dhfile, 105: listen_tls_ciphers, 106: listen_tls_versions, 107: listen_tls_protocol_options, 108: listen_check_from, 109: listen_hidden_components, 110: listen_conflict_behaviour, 111: listen_password, 112: listen_http_num_acceptors, 113: listen_http_max_connections, 114: listen_http_compress, 115: listen_http_handlers, 116: listen_http_handlers_websockets, 117: listen_http_handlers_lasse, 118: listen_http_handlers_static, 119: listen_http_handlers_api, 120: listen_http_handlers_domain]}, 121: {auth, [parallel], [auth_methods, 122: auth_password, 123: auth_sasl_external, 124: auth_allow_multiple_connections, 125: auth_anonymous_protocol, 126: auth_sasl_mechanisms, 127: auth_ldap_pool, 128: auth_ldap_bind_pool, 129: auth_ldap_base, 130: auth_ldap_uids, 131: auth_ldap_filter, 132: auth_ldap_dn_filter, 133: auth_ldap_local_filter, 134: auth_ldap_deref, 135: auth_external, 136: auth_http_basic_auth, 137: auth_jwt, 138: auth_riak_bucket_type, 139: auth_rdbms_users_number_estimate, 140: auth_dummy]}, 141: {pool, [parallel], [pool_type, 142: pool_tag, 143: pool_scope, 144: pool_workers, 145: pool_strategy, 146: pool_call_timeout, 147: pool_rdbms_settings, 148: pool_rdbms_keepalive_interval, 149: pool_rdbms_server, 150: pool_rdbms_port, 151: pool_rdbms_tls, 152: pool_http_host, 153: pool_http_path_prefix, 154: pool_http_request_timeout, 155: pool_http_tls, 156: pool_redis_host, 157: pool_redis_port, 158: pool_redis_database, 159: pool_redis_password, 160: pool_riak_address, 161: pool_riak_port, 162: pool_riak_credentials, 163: pool_riak_cacertfile, 164: pool_riak_tls, 165: pool_cassandra_servers, 166: pool_cassandra_keyspace, 167: pool_cassandra_auth, 168: pool_cassandra_tls, 169: pool_ldap_port, 170: pool_ldap_servers, 171: pool_ldap_encrypt, 172: pool_ldap_rootdn, 173: pool_ldap_password, 174: pool_ldap_connect_interval, 175: pool_ldap_tls]}, 176: {shaper_acl_access, [parallel], [shaper, 177: acl, 178: acl_merge_host_and_global, 179: access, 180: access_merge_host_and_global]}, 181: {s2s, [parallel], [s2s_host_config, 182: s2s_dns_timeout, 183: s2s_dns_retries, 184: s2s_outgoing_port, 185: s2s_outgoing_ip_versions, 186: s2s_outgoing_timeout, 187: s2s_use_starttls, 188: s2s_certfile, 189: s2s_default_policy, 190: s2s_host_policy, 191: s2s_address, 192: s2s_ciphers, 193: s2s_shared, 194: s2s_max_retry_delay]}, 195: {modules, [parallel], [mod_adhoc, 196: mod_auth_token, 197: mod_bosh, 198: mod_caps, 199: mod_cache_users, 200: mod_carboncopy, 201: mod_csi, 202: mod_disco, 203: mod_inbox, 204: mod_global_distrib, 205: mod_global_distrib_connections, 206: mod_global_distrib_connections_endpoints, 207: mod_global_distrib_connections_advertised_endpoints, 208: mod_global_distrib_connections_tls, 209: mod_global_distrib_redis, 210: mod_global_distrib_cache, 211: mod_global_distrib_bounce, 212: mod_event_pusher_sns, 213: mod_event_pusher_push, 214: mod_event_pusher_http, 215: mod_event_pusher_rabbit, 216: mod_extdisco, 217: mod_http_upload, 218: mod_http_upload_s3, 219: mod_jingle_sip, 220: mod_keystore, 221: mod_keystore_keys, 222: mod_last, 223: mod_mam_meta, 224: mod_mam_meta_riak, 225: mod_mam_meta_pm, 226: mod_mam_meta_muc, 227: mod_muc, 228: mod_muc_default_room, 229: mod_muc_default_room_affiliations, 230: mod_muc_log, 231: mod_muc_log_top_link, 232: mod_muc_light, 233: mod_muc_light_config_schema, 234: mod_offline, 235: mod_ping, 236: mod_privacy, 237: mod_private, 238: mod_pubsub, 239: mod_pubsub_pep_mapping, 240: mod_pubsub_default_node_config, 241: mod_push_service_mongoosepush, 242: mod_register, 243: mod_roster, 244: mod_shared_roster_ldap, 245: mod_sic, 246: mod_stream_management, 247: mod_stream_management_stale_h, 248: mod_time, 249: mod_vcard, 250: mod_vcard_ldap_uids, 251: mod_vcard_ldap_vcard_map, 252: mod_vcard_ldap_search_fields, 253: mod_vcard_ldap_search_reported, 254: mod_version, 255: modules_without_config, 256: incorrect_module]}, 257: {services, [parallel], [service_admin_extra, 258: service_mongoose_system_metrics]} 259: ]. 260: 261: init_per_suite(Config) -> 262: {ok, _} = application:ensure_all_started(jid), 263: create_files(Config), 264: Config. 265: 266: end_per_suite(_Config) -> 267: ok. 268: 269: init_per_group(dynamic_domains, Config) -> 270: meck:new(ejabberd_auth_http, [passthrough, no_link]), 271: meck:new(mod_test, [non_strict, no_link]), 272: meck:expect(ejabberd_auth_http, supported_features, fun() -> [] end), 273: meck:expect(mod_test, supported_features, fun() -> [] end), 274: Config; 275: init_per_group(_, Config) -> 276: Config. 277: 278: end_per_group(dynamic_domains, _Config) -> 279: meck:unload(); 280: end_per_group(_, _Config) -> 281: ok. 282: 283: init_per_testcase(_, Config) -> 284: Config. 285: 286: end_per_testcase(_, _Config) -> 287: ok. 288: 289: sample_pgsql(Config) -> 290: test_config_file(Config, "mongooseim-pgsql"). 291: 292: miscellaneous(Config) -> 293: test_config_file(Config, "miscellaneous"). 294: 295: s2s(Config) -> 296: test_config_file(Config, "s2s_only"). 297: 298: modules(Config) -> 299: test_config_file(Config, "modules"). 300: 301: outgoing_pools(Config) -> 302: test_config_file(Config, "outgoing_pools"). 303: 304: host_types_file(Config) -> 305: test_config_file(Config, "host_types"). 306: 307: supported_features(_Config) -> 308: Gen = #{<<"general">> => #{<<"host_types">> => [<<"type1">>, <<"type2">>]}}, 309: Auth = #{<<"auth">> => #{<<"internal">> => #{}}}, 310: Mod = #{<<"modules">> => #{<<"mod_amp">> => #{}}}, 311: ?cfg([{auth, <<"type1">>}, methods], [internal], maps:merge(Gen, Auth)), 312: ?cfg([{auth, <<"type1">>}, methods], [internal], 313: Gen#{<<"host_config">> => [Auth#{<<"host_type">> => <<"type1">>}]}), 314: ?cfg([{modules, <<"type1">>}, mod_amp], [], maps:merge(Gen, Mod)), 315: ?cfg([{modules, <<"type1">>}, mod_amp], [], 316: Gen#{<<"host_config">> => [Mod#{<<"host_type">> => <<"type1">>}]}). 317: 318: unsupported_features(_Config) -> 319: % ejabberd_auth_http and mod_test are mocked and they don't support dynamic domains 320: Gen = #{<<"general">> => #{<<"host_types">> => [<<"type1">>, <<"type2">>]}}, 321: Auth = #{<<"auth">> => #{<<"http">> => #{}}}, 322: Mod = #{<<"modules">> => #{<<"mod_test">> => #{}}}, 323: ?err([#{reason := dynamic_domains_not_supported, 324: unsupported_auth_methods := [http], 325: unsupported_modules := []}], 326: maps:merge(Gen, Auth)), 327: ?err([#{reason := dynamic_domains_not_supported, 328: unsupported_auth_methods := [http], 329: unsupported_modules := []}], 330: Gen#{<<"host_config">> => [Auth#{<<"host_type">> => <<"type1">>}]}), 331: ?err([#{reason := dynamic_domains_not_supported, 332: unsupported_auth_methods := [], 333: unsupported_modules := [mod_test]}], 334: maps:merge(Gen, Mod)), 335: ?err([#{reason := dynamic_domains_not_supported, 336: unsupported_auth_methods := [], 337: unsupported_modules := [mod_test]}], 338: Gen#{<<"host_config">> => [Mod#{<<"host_type">> => <<"type1">>}]}). 339: 340: %% tests: general 341: loglevel(_Config) -> 342: ?cfg(loglevel, warning, #{}), % default 343: ?cfg(loglevel, debug, #{<<"general">> => #{<<"loglevel">> => <<"debug">>}}), 344: ?err(#{<<"general">> => #{<<"loglevel">> => <<"bebug">>}}), 345: %% make sure non-host options are not accepted in host_config 346: ?err(host_config(#{<<"general">> => #{<<"loglevel">> => <<"debug">>}})). 347: 348: hosts(_Config) -> 349: ?cfg(hosts, [], % default 350: #{<<"general">> => #{<<"host_types">> => [<<"type1">>]}, without => [<<"hosts">>]}), 351: ?cfg(hosts, [<<"host1">>], 352: #{<<"general">> => #{<<"hosts">> => [<<"host1">>]}}), 353: ?cfg(hosts, [<<"host1">>, <<"host2">>], 354: #{<<"general">> => #{<<"hosts">> => [<<"host1">>, <<"host2">>]}}), 355: ?err(#{<<"general">> => #{<<"hosts">> => [<<"what is this?">>]}}), 356: ?err(#{<<"general">> => #{<<"hosts">> => [<<>>]}}), 357: ?err(#{<<"general">> => #{<<"hosts">> => [<<"host1">>, <<"host1">>]}}), 358: %% at least one host or host_type must be provided 359: ?err(#{<<"general">> => #{}, without => [<<"hosts">>]}), 360: ?err(#{<<"general">> => #{<<"hosts">> => []}}), 361: ?err(#{<<"general">> => #{<<"host_types">> => []}, without => [<<"hosts">>]}), 362: ?err(#{<<"general">> => #{<<"hosts">> => [], <<"host_types">> => []}}). 363: 364: host_types(_Config) -> 365: ?cfg(host_types, [], #{}), % default 366: ?cfg([{host_types, [<<"type 1">>]}, 367: {hosts, []}], 368: #{<<"general">> => #{<<"host_types">> => [<<"type 1">>]}, without => [<<"hosts">>]}), 369: ?cfg([{host_types, [<<"type 1">>, <<"type 2">>]}, 370: {hosts, []}], 371: #{<<"general">> => #{<<"host_types">> => [<<"type 1">>, <<"type 2">>], 372: <<"hosts">> => []}}), 373: ?err(#{<<"general">> => #{<<"host_types">> => [<<>>]}}), 374: ?err(#{<<"general">> => #{<<"host_types">> => [<<"type1">>, <<"type1">>]}}), 375: %% either hosts and host_types cannot have the same values 376: ?err(#{<<"general">> => #{<<"host_types">> => [<<"type1">>], 377: <<"hosts">> => [<<"type1">>]}}). 378: 379: default_server_domain(_Config) -> 380: ?cfg(default_server_domain, <<"host1">>, 381: #{<<"general">> => #{<<"default_server_domain">> => <<"host1">>}}), 382: ?err(#{<<"general">> => #{<<"default_server_domain">> => <<"what is this?">>}}), 383: ?err(#{<<"general">> => #{<<"default_server_domain">> => <<>>}}), 384: %% default_server_domain must be provided 385: ?err(#{without => [<<"default_server_domain">>]}). 386: 387: registration_timeout(_Config) -> 388: ?cfg(registration_timeout, 600, #{}), % default 389: ?cfg(registration_timeout, infinity, 390: #{<<"general">> => #{<<"registration_timeout">> => <<"infinity">>}}), 391: ?cfg(registration_timeout, 300, 392: #{<<"general">> => #{<<"registration_timeout">> => 300}}), 393: ?err(#{<<"general">> => #{<<"registration_timeout">> => 0}}). 394: 395: language(_Config) -> 396: ?cfg(language, <<"en">>, #{}), % default 397: ?cfg(language, <<"pl">>, #{<<"general">> => #{<<"language">> => <<"pl">>}}), 398: ?err(#{<<"general">> => #{<<"language">> => <<>>}}). 399: 400: all_metrics_are_global(_Config) -> 401: ?cfg(all_metrics_are_global, false, #{}), % default 402: ?cfg(all_metrics_are_global, true, #{<<"general">> => #{<<"all_metrics_are_global">> => true}}), 403: ?err(#{<<"general">> => #{<<"all_metrics_are_global">> => <<"true">>}}). 404: 405: sm_backend(_Config) -> 406: ?cfg(sm_backend, {mnesia, []}, #{}), % default 407: ?cfg(sm_backend, {mnesia, []}, #{<<"general">> => #{<<"sm_backend">> => <<"mnesia">>}}), 408: ?cfg(sm_backend, {redis, []}, #{<<"general">> => #{<<"sm_backend">> => <<"redis">>}}), 409: ?err(#{<<"general">> => #{<<"sm_backend">> => <<"amnesia">>}}). 410: 411: max_fsm_queue(_Config) -> 412: ?cfg(max_fsm_queue, 100, #{<<"general">> => #{<<"max_fsm_queue">> => 100}}), 413: ?err(#{<<"general">> => #{<<"max_fsm_queue">> => -10}}). 414: 415: http_server_name(_Config) -> 416: ?cfg(cowboy_server_name, "my server", 417: #{<<"general">> => #{<<"http_server_name">> => <<"my server">>}}), 418: ?err(#{<<"general">> => #{<<"http_server_name">> => #{}}}). 419: 420: rdbms_server_type(_Config) -> 421: ?cfg(rdbms_server_type, generic, #{}), % default 422: ?cfg(rdbms_server_type, mssql, #{<<"general">> => #{<<"rdbms_server_type">> => <<"mssql">>}}), 423: ?cfg(rdbms_server_type, pgsql, #{<<"general">> => #{<<"rdbms_server_type">> => <<"pgsql">>}}), 424: ?err(#{<<"general">> => #{<<"rdbms_server_type">> => <<"nosql">>}}). 425: 426: route_subdomains(_Config) -> 427: ?cfgh(route_subdomains, s2s, #{<<"general">> => #{<<"route_subdomains">> => <<"s2s">>}}), 428: ?errh(#{<<"general">> => #{<<"route_subdomains">> => <<"c2s">>}}). 429: 430: mongooseimctl_access_commands(_Config) -> 431: ?cfg(mongooseimctl_access_commands, [], #{}), % default 432: AccessRule = #{<<"commands">> => [<<"join_cluster">>], 433: <<"argument_restrictions">> => #{<<"node">> => <<"mim1@host1">>}}, 434: ?cfg(mongooseimctl_access_commands, [{local, ["join_cluster"], [{node, "mim1@host1"}]}], 435: #{<<"general">> => #{<<"mongooseimctl_access_commands">> => 436: #{<<"local">> => AccessRule}}}), 437: ?cfg(mongooseimctl_access_commands, [{local, all, [{node, "mim1@host1"}]}], 438: #{<<"general">> => #{<<"mongooseimctl_access_commands">> => 439: #{<<"local">> => maps:remove(<<"commands">>, AccessRule)}}}), 440: ?cfg(mongooseimctl_access_commands, [{local, ["join_cluster"], []}], 441: #{<<"general">> => #{<<"mongooseimctl_access_commands">> => 442: #{<<"local">> => maps:remove(<<"argument_restrictions">>, 443: AccessRule)}}}), 444: ?cfg(mongooseimctl_access_commands, [{local, all, []}], 445: #{<<"general">> => #{<<"mongooseimctl_access_commands">> => #{<<"local">> => #{}}}}), 446: ?err(#{<<"general">> => #{<<"mongooseimctl_access_commands">> => 447: #{<<"local">> => #{<<"commands">> => <<"all">>}}}}), 448: ?err(#{<<"general">> => #{<<"mongooseimctl_access_commands">> => 449: #{<<"local">> => #{<<"argument_restrictions">> => 450: [<<"none">>]}}}}). 451: 452: routing_modules(_Config) -> 453: ?cfg(routing_modules, mongoose_router:default_routing_modules(), #{}), % default 454: ?cfg(routing_modules, [mongoose_router_global, mongoose_router_localdomain], 455: #{<<"general">> => #{<<"routing_modules">> => [<<"mongoose_router_global">>, 456: <<"mongoose_router_localdomain">>]}}), 457: ?err(#{<<"general">> => #{<<"routing_modules">> => [<<"moongoose_router_global">>]}}). 458: 459: replaced_wait_timeout(_Config) -> 460: ?cfg({replaced_wait_timeout, ?HOST}, 2000, #{}), % global default 461: ?cfgh(replaced_wait_timeout, 1000, #{<<"general">> => #{<<"replaced_wait_timeout">> => 1000}}), 462: ?errh(#{<<"general">> => #{<<"replaced_wait_timeout">> => 0}}). 463: 464: hide_service_name(_Config) -> 465: ?cfg(hide_service_name, false, #{}), % default 466: ?cfg(hide_service_name, true, #{<<"general">> => #{<<"hide_service_name">> => true}}), 467: ?err(#{<<"general">> => #{<<"hide_service_name">> => []}}). 468: 469: domain_certfile(_Config) -> 470: DomCert = #{<<"domain">> => <<"myxmpp.com">>, 471: <<"certfile">> => <<"priv/cert.pem">>}, 472: ?cfg(domain_certfile, #{<<"myxmpp.com">> => "priv/cert.pem"}, 473: #{<<"general">> => #{<<"domain_certfile">> => [DomCert]}}), 474: ?err([#{reason := invalid_filename}], 475: #{<<"general">> => #{<<"domain_certfile">> => 476: [DomCert#{<<"certfile">> => <<"missing.pem">>}]}}), 477: [?err(#{<<"general">> => #{<<"domain_certfile">> => [maps:without([K], DomCert)]}}) 478: || K <- maps:keys(DomCert)], 479: [?err(#{<<"general">> => #{<<"domain_certfile">> => [DomCert#{K := <<>>}]}}) 480: || K <- maps:keys(DomCert)], 481: ?err(#{<<"general">> => #{<<"domain_certfile">> => [DomCert, DomCert]}}). 482: 483: %% tests: listen 484: 485: listen_portip(_Config) -> 486: ?cfg(listen, [], #{}), 487: ?cfg(listener_config(ejabberd_c2s, #{}), listen_raw(<<"c2s">>, #{})), 488: ?cfg(listener_config(ejabberd_c2s, #{ip_address => "192.168.1.16", 489: ip_tuple => {192, 168, 1, 16}}), 490: listen_raw(<<"c2s">>, #{<<"ip_address">> => <<"192.168.1.16">>})), 491: ?cfg(listener_config(ejabberd_c2s, #{ip_address => "2001:db8:3:4:5:6:7:8", 492: ip_tuple => {8193, 3512, 3, 4, 5, 6, 7, 8}, 493: ip_version => 6}), 494: listen_raw(<<"c2s">>, #{<<"ip_address">> => <<"2001:db8:3:4:5:6:7:8">>})), 495: ?err(listen_raw(<<"c2s">>, #{<<"ip_address">> => <<"192.168.1.999">>})), 496: ?err(#{<<"listen">> => #{<<"c2s">> => [#{<<"ip_address">> => <<"192.168.1.16">>}]}}), 497: ?err(#{<<"listen">> => #{<<"c2s">> => [#{<<"port">> => <<"5222">>}]}}), 498: ?err(#{<<"listen">> => #{<<"c2s">> => [#{<<"port">> => 522222}]}}). 499: 500: listen_proto(_Config) -> 501: ?cfg(listener_config(ejabberd_c2s, #{}), 502: listen_raw(<<"c2s">>, #{<<"proto">> => <<"tcp">>})), 503: ?cfg(listener_config(ejabberd_c2s, #{proto => udp}), 504: listen_raw(<<"c2s">>, #{<<"proto">> => <<"udp">>})), 505: ?err(listen_raw(<<"c2s">>, #{<<"proto">> => <<"pigeon">>})). 506: 507: listen_duplicate(_Config) -> 508: ?cfg(listen, [listener(ejabberd_c2s, #{}), 509: listener(ejabberd_c2s, #{port => 5223})], 510: #{<<"listen">> => #{<<"c2s">> => [#{<<"port">> => 5222, 511: <<"ip_address">> => <<"0">>}, 512: #{<<"port">> => 5223}]}}), 513: ?err([#{reason := duplicate_listeners, 514: duplicates := [{5222, {0, 0, 0, 0}, tcp}]}], 515: #{<<"listen">> => #{<<"c2s">> => [#{<<"port">> => 5222, 516: <<"ip_address">> => <<"0">>}, 517: #{<<"port">> => 5222}]}}). 518: 519: listen_ip_version(_Config) -> 520: ?cfg(listener_config(ejabberd_c2s, #{}), 521: listen_raw(<<"c2s">>, #{<<"ip_version">> => 4})), 522: ?cfg(listener_config(ejabberd_c2s, #{ip_address => "::", 523: ip_tuple => {0, 0, 0, 0, 0, 0, 0, 0}, 524: ip_version => 6}), 525: listen_raw(<<"c2s">>, #{<<"ip_version">> => 6})), 526: ?err(listen_raw(<<"c2s">>, #{<<"ip_version">> => 7})). 527: 528: listen_backlog(_Config) -> 529: ?cfg(listener_config(ejabberd_c2s, #{backlog => 10}), 530: listen_raw(<<"c2s">>, #{<<"backlog">> => 10})), 531: ?err(listen_raw(<<"c2s">>, #{<<"backlog">> => -10})). 532: 533: listen_proxy_protocol(_Config) -> 534: ?cfg(listener_config(ejabberd_c2s, #{proxy_protocol => true}), 535: listen_raw(<<"c2s">>, #{<<"proxy_protocol">> => true})), 536: ?cfg(listener_config(ejabberd_s2s_in, #{proxy_protocol => true}), 537: listen_raw(<<"s2s">>, #{<<"proxy_protocol">> => true})), 538: ?cfg(listener_config(ejabberd_service, #{proxy_protocol => true}), 539: listen_raw(<<"service">>, #{<<"proxy_protocol">> => true})), 540: ?err(listen_raw(<<"c2s">>, #{<<"proxy_protocol">> => <<"awesome">>})). 541: 542: listen_num_acceptors(_Config) -> 543: ?cfg(listener_config(ejabberd_c2s, #{acceptors_num => 100}), 544: listen_raw(<<"c2s">>, #{<<"num_acceptors">> => 100})), 545: ?cfg(listener_config(ejabberd_s2s_in, #{acceptors_num => 100}), 546: listen_raw(<<"s2s">>, #{<<"num_acceptors">> => 100})), 547: ?cfg(listener_config(ejabberd_service, #{acceptors_num => 100}), 548: listen_raw(<<"service">>, #{<<"num_acceptors">> => 100})), 549: ?err(listen_raw(<<"c2s">>, #{<<"num_acceptors">> => 0})). 550: 551: listen_access(_Config) -> 552: ?cfg(listener_config(ejabberd_c2s, #{access => rule1}), 553: listen_raw(<<"c2s">>, #{<<"access">> => <<"rule1">>})), 554: ?cfg(listener_config(ejabberd_service, #{access => rule1}), 555: listen_raw(<<"service">>, #{<<"access">> => <<"rule1">>})), 556: ?err(listen_raw(<<"c2s">>, #{<<"access">> => <<>>})). 557: 558: listen_shaper(_Config) -> 559: ?cfg(listener_config(ejabberd_c2s, #{shaper => c2s_shaper}), 560: listen_raw(<<"c2s">>, #{<<"shaper">> => <<"c2s_shaper">>})), 561: ?cfg(listener_config(ejabberd_s2s_in, #{shaper => s2s_shaper}), 562: listen_raw(<<"s2s">>, #{<<"shaper">> => <<"s2s_shaper">>})), 563: ?cfg(listener_config(ejabberd_service, #{shaper_rule => fast}), 564: listen_raw(<<"service">>, #{<<"shaper_rule">> => <<"fast">>})), 565: ?err(listen_raw(<<"s2s">>, #{<<"shaper">> => <<>>})). 566: 567: listen_xml_socket(_Config) -> 568: ?cfg(listener_config(ejabberd_c2s, #{xml_socket => true}), 569: listen_raw(<<"c2s">>, #{<<"xml_socket">> => true})), 570: ?err(listen_raw(<<"c2s">>, #{<<"xml_socket">> => 10})). 571: 572: listen_zlib(_Config) -> 573: ?cfg(listener_config(ejabberd_c2s, #{zlib => 1024}), 574: listen_raw(<<"c2s">>, #{<<"zlib">> => 1024})), 575: ?err(listen_raw(<<"c2s">>, #{<<"zlib">> => 0})). 576: 577: listen_hibernate_after(_Config) -> 578: ?cfg(listener_config(ejabberd_c2s, #{hibernate_after => 10}), 579: listen_raw(<<"c2s">>, #{<<"hibernate_after">> => 10})), 580: ?cfg(listener_config(ejabberd_s2s_in, #{hibernate_after => 10}), 581: listen_raw(<<"s2s">>, #{<<"hibernate_after">> => 10})), 582: ?cfg(listener_config(ejabberd_service, #{hibernate_after => 10}), 583: listen_raw(<<"service">>, #{<<"hibernate_after">> => 10})), 584: ?err(listen_raw(<<"c2s">>, #{<<"hibernate_after">> => -10})). 585: 586: listen_max_stanza_size(_Config) -> 587: ?cfg(listener_config(ejabberd_c2s, #{max_stanza_size => 10000}), 588: listen_raw(<<"c2s">>, #{<<"max_stanza_size">> => 10000})), 589: ?cfg(listener_config(ejabberd_s2s_in, #{max_stanza_size => 10000}), 590: listen_raw(<<"s2s">>, #{<<"max_stanza_size">> => 10000})), 591: ?cfg(listener_config(ejabberd_service, #{max_stanza_size => 10000}), 592: listen_raw(<<"service">>, #{<<"max_stanza_size">> => 10000})), 593: ?err(listen_raw(<<"c2s">>, #{<<"max_stanza_size">> => <<"infinity">>})). 594: 595: listen_max_fsm_queue(_Config) -> 596: ?cfg(listener_config(ejabberd_c2s, #{max_fsm_queue => 1000}), 597: listen_raw(<<"c2s">>, #{<<"max_fsm_queue">> => 1000})), 598: ?cfg(listener_config(ejabberd_service, #{max_fsm_queue => 1000}), 599: listen_raw(<<"service">>, #{<<"max_fsm_queue">> => 1000})), 600: ?err(listen_raw(<<"s2s">>, #{<<"max_fsm_queue">> => 1000})), % only for c2s and service 601: ?err(listen_raw(<<"c2s">>, #{<<"max_fsm_queue">> => 0})). 602: 603: listen_tls_mode(_Config) -> 604: ?cfg(listener_config(ejabberd_c2s, #{tls => [starttls]}), 605: listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"mode">> => <<"starttls">>}})), 606: ?err(listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"mode">> => <<"stoptls">>}})). 607: 608: listen_tls_module(_Config) -> 609: ?cfg(listener_config(ejabberd_c2s, #{tls => [{tls_module, just_tls}]}), 610: listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"module">> => <<"just_tls">>}})), 611: ?cfg(listener_config(ejabberd_c2s, #{tls => []}), 612: listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"module">> => <<"fast_tls">>}})), 613: ?err(listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"module">> => <<"slow_tls">>}})). 614: 615: listen_tls_verify(_Config) -> 616: ?cfg(listener_config(ejabberd_c2s, #{tls => [verify_peer]}), 617: listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"verify_peer">> => true}})), 618: ?cfg(listener_config(ejabberd_c2s, #{tls => [verify_none]}), 619: listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"verify_peer">> => false}})), 620: ?cfg(listener_config(ejabberd_c2s, #{tls => [{tls_module, just_tls}, verify_peer]}), 621: listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"module">> => <<"just_tls">>, 622: <<"verify_peer">> => true}})), 623: ?cfg(listener_config(ejabberd_cowboy, #{ssl => [{verify, verify_peer}]}), 624: listen_raw(<<"http">>, #{<<"tls">> => #{<<"verify_peer">> => true}})), 625: ?cfg(listener_config(ejabberd_c2s, #{tls => [{tls_module, just_tls}, verify_none]}), 626: listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"module">> => <<"just_tls">>, 627: <<"verify_peer">> => false}})), 628: ?err(listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"verify_peer">> => <<"maybe">>}})). 629: 630: listen_tls_verify_mode(_Config) -> 631: ?cfg(listener_config(ejabberd_c2s, #{tls => [{tls_module, just_tls}, 632: {ssl_options, [{verify_fun, {peer, true}}]}]}), 633: listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"module">> => <<"just_tls">>, 634: <<"verify_mode">> => <<"peer">>}})), 635: ?cfg(listener_config(ejabberd_c2s, #{tls => [{tls_module, just_tls}, 636: {ssl_options, [{verify_fun, 637: {selfsigned_peer, false}}]}]}), 638: listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"module">> => <<"just_tls">>, 639: <<"verify_mode">> => <<"selfsigned_peer">>, 640: <<"disconnect_on_failure">> => false}})), 641: ?cfg(listener_config(ejabberd_cowboy, #{ssl => [{verify_mode, peer}]}), 642: listen_raw(<<"http">>, #{<<"tls">> => #{<<"verify_mode">> => <<"peer">>}})), 643: ?err(listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"module">> => <<"just_tls">>, 644: <<"verify_mode">> => <<"peer">>, 645: <<"disconnect_on_failure">> => <<"false">>}})), 646: ?err(listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"module">> => <<"just_tls">>, 647: <<"verify_mode">> => <<"whatever">>}})), 648: ?err(listen_raw(<<"http">>, #{<<"tls">> => #{<<"verify_mode">> => <<"whatever">>}})). 649: 650: listen_tls_crl_files(_Config) -> 651: ?cfg(listener_config(ejabberd_c2s, #{tls => [{tls_module, just_tls}, 652: {crlfiles, ["file1", "file2"]}]}), 653: listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"module">> => <<"just_tls">>, 654: <<"crl_files">> => [<<"file1">>, 655: <<"file2">>]}})), 656: ?err(listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"module">> => <<"just_tls">>, 657: <<"crl_files">> => [<<>>]}})), 658: %% only for just_tls 659: ?err(listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"crl_files">> => [<<"file1">>, 660: <<"file2">>]}})). 661: 662: listen_tls_certfile(_Config) -> 663: ?cfg(listener_config(ejabberd_c2s, #{tls => [{certfile, "priv/cert.pem"}]}), 664: listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"certfile">> => <<"priv/cert.pem">>}})), 665: ?cfg(listener_config(ejabberd_c2s, #{tls => [{tls_module, just_tls}, 666: {ssl_options, [{certfile, "priv/cert.pem"}]}]}), 667: listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"module">> => <<"just_tls">>, 668: <<"certfile">> => <<"priv/cert.pem">>}})), 669: ?cfg(listener_config(ejabberd_cowboy, #{ssl => [{certfile, "priv/cert.pem"}]}), 670: listen_raw(<<"http">>, #{<<"tls">> => #{<<"certfile">> => <<"priv/cert.pem">>}})), 671: ?err(listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"certfile">> => <<"no_such_file.pem">>}})). 672: 673: listen_tls_cacertfile(_Config) -> 674: ?cfg(listener_config(ejabberd_c2s, #{tls => [{cafile, "priv/ca.pem"}]}), 675: listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"cacertfile">> => <<"priv/ca.pem">>}})), 676: ?cfg(listener_config(ejabberd_s2s_in, #{tls => [{cafile, "priv/ca.pem"}]}), 677: listen_raw(<<"s2s">>, #{<<"tls">> => #{<<"cacertfile">> => <<"priv/ca.pem">>}})), 678: ?cfg(listener_config(ejabberd_c2s, #{tls => [{tls_module, just_tls}, 679: {ssl_options, [{cacertfile, "priv/ca.pem"}]}]}), 680: listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"module">> => <<"just_tls">>, 681: <<"cacertfile">> => <<"priv/ca.pem">>}})), 682: ?cfg(listener_config(ejabberd_cowboy, #{ssl => [{cacertfile, "priv/ca.pem"}]}), 683: listen_raw(<<"http">>, #{<<"tls">> => #{<<"cacertfile">> => <<"priv/ca.pem">>}})), 684: ?err(listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"cacertfile">> => <<"no_such_file.pem">>}})). 685: 686: listen_tls_dhfile(_Config) -> 687: ?cfg(listener_config(ejabberd_c2s, #{tls => [{dhfile, "priv/dh.pem"}]}), 688: listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"dhfile">> => <<"priv/dh.pem">>}})), 689: ?cfg(listener_config(ejabberd_s2s_in, #{tls => [{dhfile, "priv/dh.pem"}]}), 690: listen_raw(<<"s2s">>, #{<<"tls">> => #{<<"dhfile">> => <<"priv/dh.pem">>}})), 691: ?cfg(listener_config(ejabberd_c2s, #{tls => [{tls_module, just_tls}, 692: {ssl_options, [{dhfile, "priv/dh.pem"}]}]}), 693: listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"module">> => <<"just_tls">>, 694: <<"dhfile">> => <<"priv/dh.pem">>}})), 695: ?cfg(listener_config(ejabberd_cowboy, #{ssl => [{dhfile, "priv/dh.pem"}]}), 696: listen_raw(<<"http">>, #{<<"tls">> => #{<<"dhfile">> => <<"priv/dh.pem">>}})), 697: ?err(listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"dhfile">> => <<"no_such_file.pem">>}})). 698: 699: listen_tls_ciphers(_Config) -> 700: ?cfg(listener_config(ejabberd_c2s, #{tls => [{ciphers, "TLS_AES_256_GCM_SHA384"}]}), 701: listen_raw(<<"c2s">>, 702: #{<<"tls">> => #{<<"ciphers">> => <<"TLS_AES_256_GCM_SHA384">>}})), 703: ?cfg(listener_config(ejabberd_c2s, #{tls => [{tls_module, just_tls}, 704: {ssl_options, 705: [{ciphers, "TLS_AES_256_GCM_SHA384"}]}]}), 706: listen_raw(<<"c2s">>, 707: #{<<"tls">> => #{<<"module">> => <<"just_tls">>, 708: <<"ciphers">> => <<"TLS_AES_256_GCM_SHA384">>}})), 709: ?cfg(listener_config(ejabberd_s2s_in, #{tls => [{ciphers, "TLS_AES_256_GCM_SHA384"}]}), 710: listen_raw(<<"s2s">>, 711: #{<<"tls">> => #{<<"ciphers">> => <<"TLS_AES_256_GCM_SHA384">>}})), 712: ?cfg(listener_config(ejabberd_cowboy, #{ssl => [{ciphers, "TLS_AES_256_GCM_SHA384"}]}), 713: listen_raw(<<"http">>, 714: #{<<"tls">> => #{<<"ciphers">> => <<"TLS_AES_256_GCM_SHA384">>}})), 715: ?err(listen_raw(<<"c2s">>, 716: #{<<"tls">> => #{<<"ciphers">> => [<<"TLS_AES_256_GCM_SHA384">>]}})). 717: 718: listen_tls_versions(_Config) -> 719: ?cfg(listener_config(ejabberd_c2s, #{tls => [{tls_module, just_tls}, 720: {ssl_options, 721: [{versions, ['tlsv1.2', 'tlsv1.3']}]}]}), 722: listen_raw(<<"c2s">>, 723: #{<<"tls">> => #{<<"module">> => <<"just_tls">>, 724: <<"versions">> => [<<"tlsv1.2">>, <<"tlsv1.3">>]}})), 725: ?err(listen_raw(<<"c2s">>, 726: #{<<"tls">> => #{<<"module">> => <<"just_tls">>, 727: <<"versions">> => <<"tlsv1.2">>}})). 728: 729: listen_tls_protocol_options(_Config) -> 730: ?cfg(listener_config(ejabberd_c2s, #{tls => [{protocol_options, ["nosslv2"]}]}), 731: listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"protocol_options">> => [<<"nosslv2">>]}})), 732: ?cfg(listener_config(ejabberd_s2s_in, #{tls => [{protocol_options, ["nosslv2"]}]}), 733: listen_raw(<<"s2s">>, #{<<"tls">> => #{<<"protocol_options">> => [<<"nosslv2">>]}})), 734: ?err(listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"protocol_options">> => [<<>>]}})), 735: ?err(listen_raw(<<"s2s">>, #{<<"tls">> => #{<<"protocol_options">> => [<<>>]}})), 736: ?err(listen_raw(<<"c2s">>, #{<<"tls">> => #{<<"module">> => <<"just_tls">>, 737: <<"protocol_options">> => [<<"nosslv2">>]}})). 738: 739: listen_check_from(_Config) -> 740: ?cfg(listener_config(ejabberd_service, #{service_check_from => false}), 741: listen_raw(<<"service">>, #{<<"check_from">> => false})), 742: ?err(listen_raw(<<"service">>, #{<<"check_from">> => 1})). 743: 744: listen_hidden_components(_Config) -> 745: ?cfg(listener_config(ejabberd_service, #{hidden_components => true}), 746: listen_raw(<<"service">>, #{<<"hidden_components">> => true})), 747: ?err(listen_raw(<<"service">>, #{<<"hidden_components">> => <<"yes">>})). 748: 749: listen_conflict_behaviour(_Config) -> 750: ?cfg(listener_config(ejabberd_service, #{conflict_behaviour => kick_old}), 751: listen_raw(<<"service">>, #{<<"conflict_behaviour">> => <<"kick_old">>})), 752: ?err(listen_raw(<<"service">>, #{<<"conflict_behaviour">> => <<"kill_server">>})). 753: 754: listen_password(_Config) -> 755: ?cfg(listener_config(ejabberd_service, #{password => "secret"}), 756: listen_raw(<<"service">>, #{<<"password">> => <<"secret">>})), 757: ?err(listen_raw(<<"service">>, #{<<"password">> => <<>>})). 758: 759: listen_http_num_acceptors(_Config) -> 760: ?cfg(listener_config(ejabberd_cowboy, #{transport_options => [{num_acceptors, 10}]}), 761: listen_raw(<<"http">>, #{<<"transport">> => #{<<"num_acceptors">> => 10}})), 762: ?err(listen_raw(<<"http">>, #{<<"transport">> => #{<<"num_acceptors">> => 0}})). 763: 764: listen_http_max_connections(_Config) -> 765: ?cfg(listener_config(ejabberd_cowboy, #{transport_options => [{max_connections, 100}]}), 766: listen_raw(<<"http">>, #{<<"transport">> => #{<<"max_connections">> => 100}})), 767: ?cfg(listener_config(ejabberd_cowboy, #{transport_options => [{max_connections, infinity}]}), 768: listen_raw(<<"http">>, #{<<"transport">> => 769: #{<<"max_connections">> => <<"infinity">>}})), 770: ?err(listen_raw(<<"http">>, #{<<"transport">> => #{<<"max_connections">> => -1}})). 771: 772: listen_http_compress(_Config) -> 773: ?cfg(listener_config(ejabberd_cowboy, #{protocol_options => [{compress, true}]}), 774: listen_raw(<<"http">>, #{<<"protocol">> => #{<<"compress">> => true}})), 775: ?err(listen_raw(<<"http">>, #{<<"protocol">> => #{<<"compress">> => 0}})). 776: 777: listen_http_handlers(_Config) -> 778: ?cfg(listener_config(ejabberd_cowboy, #{modules => [{"_", "/http-bind", mod_bosh, []}]}), 779: listen_raw(<<"http">>, #{<<"handlers">> => 780: #{<<"mod_bosh">> => 781: [#{<<"host">> => <<"_">>, 782: <<"path">> => <<"/http-bind">>}]}})), 783: ?err(listen_raw(<<"http">>, #{<<"handlers">> => 784: #{<<"mod_bosch">> => 785: [#{<<"host">> => <<"dishwasher">>, 786: <<"path">> => <<"/cutlery">>}]}})), 787: ?err(listen_raw(<<"http">>, #{<<"handlers">> => 788: #{<<"mod_bosh">> => 789: [#{<<"host">> => <<"pathless">>}]}})), 790: ?err(listen_raw(<<"http">>, #{<<"handlers">> => 791: #{<<"mod_bosh">> => 792: [#{<<"host">> => <<>>, 793: <<"path">> => <<"/">>}]}})), 794: ?err(listen_raw(<<"http">>, #{<<"handlers">> => 795: #{<<"mod_bosh">> => 796: [#{<<"path">> => <<"hostless">>}]}})). 797: 798: listen_http_handlers_websockets(_Config) -> 799: ?cfg(listener_config(ejabberd_cowboy, #{modules => [{"localhost", "/api", mod_websockets, []}]}), 800: http_handler_raw(<<"mod_websockets">>, #{})), 801: ?cfg(listener_config(ejabberd_cowboy, #{modules => [{"localhost", "/api", mod_websockets, 802: [{ejabberd_service, [{access, all}]}] 803: }]}), 804: http_handler_raw(<<"mod_websockets">>, #{<<"service">> => #{<<"access">> => <<"all">>}})), 805: ?err(http_handler_raw(<<"mod_websockets">>, #{<<"service">> => <<"unbelievable">>})). 806: 807: listen_http_handlers_lasse(_Config) -> 808: ?cfg(listener_config(ejabberd_cowboy, #{modules => [{"localhost", "/api", lasse_handler, 809: [mongoose_client_api_sse] 810: }]}), 811: http_handler_raw(<<"lasse_handler">>, #{<<"module">> => <<"mongoose_client_api_sse">>})), 812: ?err(http_handler_raw(<<"lasse_handler">>, #{<<"module">> => <<"mooongooose_api_ssie">>})), 813: ?err(http_handler_raw(<<"lasse_handler">>, #{})). 814: 815: listen_http_handlers_static(_Config) -> 816: ?cfg(listener_config(ejabberd_cowboy, #{modules => [{"localhost", "/api", cowboy_static, 817: {priv_dir, cowboy_swagger, "swagger", 818: [{mimetypes, cow_mimetypes, all}]} 819: }]}), 820: http_handler_raw(<<"cowboy_static">>, #{<<"type">> => <<"priv_dir">>, 821: <<"app">> => <<"cowboy_swagger">>, 822: <<"content_path">> => <<"swagger">>})), 823: ?err(http_handler_raw(<<"cowboy_static">>, #{<<"type">> => <<"priv_dir">>, 824: <<"app">> => <<"cowboy_swagger">>})). 825: 826: listen_http_handlers_api(_Config) -> 827: ?cfg(listener_config(ejabberd_cowboy, #{modules => [{"localhost", "/api", mongoose_api, 828: [{handlers, [mongoose_api_metrics, 829: mongoose_api_users]}]} 830: ]}), 831: http_handler_raw(<<"mongoose_api">>, #{<<"handlers">> => [<<"mongoose_api_metrics">>, 832: <<"mongoose_api_users">>]})), 833: ?err(http_handler_raw(<<"mongoose_api">>, #{<<"handlers">> => [<<"not_an_api_module">>]})), 834: ?err(http_handler_raw(<<"mongoose_api">>, #{})). 835: 836: listen_http_handlers_domain(_Config) -> 837: ?cfg(listener_config(ejabberd_cowboy, 838: #{modules => [{"localhost", "/api", mongoose_domain_handler, 839: [{password, <<"cool">>}, {username, <<"admin">>}] 840: }]}), 841: http_handler_raw(<<"mongoose_domain_handler">>, 842: #{<<"username">> => <<"admin">>, <<"password">> => <<"cool">>})), 843: ?cfg(listener_config(ejabberd_cowboy, 844: #{modules => [{"localhost", "/api", mongoose_domain_handler, 845: [] }]}), 846: http_handler_raw(<<"mongoose_domain_handler">>, #{})), 847: %% Both username and password required. Or none. 848: ?err(http_handler_raw(<<"mongoose_domain_handler">>, #{<<"username">> => <<"admin">>})), 849: ?err(http_handler_raw(<<"mongoose_domain_handler">>, #{<<"password">> => <<"cool">>})). 850: 851: %% tests: auth 852: 853: auth_methods(_Config) -> 854: ?cfg([{auth, ?HOST}, methods], [], #{}), % global default 855: ?cfgh([auth, methods], [], #{<<"auth">> => #{}}), % default 856: ?cfgh([auth, methods], [internal, rdbms], % default alphabetical order 857: #{<<"auth">> => #{<<"internal">> => #{}, 858: <<"rdbms">> => #{}}}), 859: ?cfgh([auth, methods], [rdbms, internal], % specified order 860: #{<<"auth">> => #{<<"internal">> => #{}, 861: <<"rdbms">> => #{}, 862: <<"methods">> => [<<"rdbms">>, <<"internal">>]}}), 863: ?cfgh([auth, methods], [internal], % only one of the defined methods is enabled 864: #{<<"auth">> => #{<<"internal">> => #{}, 865: <<"rdbms">> => #{}, 866: <<"methods">> => [<<"internal">>]}}), 867: ?errh(#{<<"auth">> => #{<<"rdbms">> => <<"enabled">>}}), 868: ?errh(#{<<"auth">> => #{<<"supernatural">> => #{}}}), 869: ?errh(#{<<"auth">> => #{<<"methods">> => [<<"rdbms">>]}}). 870: 871: auth_password(_Config) -> 872: Defaults = #{format => scram, scram_iterations => 10000}, 873: ?cfg([{auth, ?HOST}, password], Defaults, #{}), % global default 874: ?cfgh([auth, password], Defaults, #{<<"auth">> => #{}}), % default 875: ?cfgh([auth, password], Defaults, #{<<"auth">> => #{<<"password">> => #{}}}), % default 876: ?cfgh([auth, password, format], plain, 877: #{<<"auth">> => #{<<"password">> => #{<<"format">> => <<"plain">>}}}), 878: ?errh(#{<<"auth">> => #{<<"password">> => #{<<"format">> => <<"plane">>}}}), 879: ?cfgh([auth, password, hash], [sha, sha256], 880: #{<<"auth">> => #{<<"password">> => #{<<"hash">> => [<<"sha">>, <<"sha256">>]}}}), 881: ?errh(#{<<"auth">> => #{<<"password">> => #{<<"hash">> => [<<"sha1234">>]}}}), 882: ?errh(#{<<"auth">> => #{<<"password">> => #{<<"harsh">> => [<<"sha">>]}}}), 883: ?cfgh([auth, password, scram_iterations], 1000, 884: #{<<"auth">> => #{<<"password">> => #{<<"scram_iterations">> => 1000}}}), 885: ?errh(#{<<"auth">> => #{<<"password">> => #{<<"scram_iterations">> => false}}}). 886: 887: auth_sasl_external(_Config) -> 888: ?cfg([{auth, ?HOST}, sasl_external], [standard], #{}), % global default 889: ?cfgh([auth, sasl_external], [standard], #{<<"auth">> => #{}}), % default 890: ?cfgh([auth, sasl_external], [standard, 891: common_name, 892: {mod, cyrsasl_external_verification}], 893: #{<<"auth">> => #{<<"sasl_external">> => 894: [<<"standard">>, 895: <<"common_name">>, 896: <<"cyrsasl_external_verification">>]}}), 897: ?errh(#{<<"auth">> => #{<<"sasl_external">> => [<<"unknown">>]}}). 898: 899: auth_sasl_mechanisms(_Config) -> 900: Default = cyrsasl:default_modules(), 901: ?cfg([{auth, ?HOST}, sasl_mechanisms], Default, #{}), % global default 902: ?cfg([{auth, ?HOST}, sasl_mechanisms], Default, #{<<"auth">> => #{}}), % default 903: ?cfgh([auth, sasl_mechanisms], [cyrsasl_external, cyrsasl_scram], 904: #{<<"auth">> => #{<<"sasl_mechanisms">> => [<<"external">>, <<"scram">>]}}), 905: ?errh(#{<<"auth">> => #{<<"sasl_mechanisms">> => [<<"none">>]}}). 906: 907: auth_allow_multiple_connections(_Config) -> 908: ?cfgh([auth, anonymous, allow_multiple_connections], true, 909: auth_raw(<<"anonymous">>, #{<<"allow_multiple_connections">> => true})), 910: ?errh(auth_raw(<<"anonymous">>, #{<<"allow_multiple_connections">> => <<"yes">>})). 911: 912: auth_anonymous_protocol(_Config) -> 913: ?cfgh([auth, anonymous, protocol], login_anon, 914: auth_raw(<<"anonymous">>, #{<<"protocol">> => <<"login_anon">>})), 915: ?errh(auth_raw(<<"anonymous">>, #{<<"protocol">> => <<"none">>})). 916: 917: auth_ldap_pool(_Config) -> 918: ?cfgh([auth, ldap, pool_tag], default, auth_ldap_raw(#{})), % default 919: ?cfgh([auth, ldap, pool_tag], ldap_pool, 920: auth_ldap_raw(#{<<"pool_tag">> => <<"ldap_pool">>})), 921: ?errh(auth_ldap_raw(#{<<"pool_tag">> => <<>>})). 922: 923: auth_ldap_bind_pool(_Config) -> 924: ?cfgh([auth, ldap, bind_pool_tag], bind, auth_ldap_raw(#{})), % default 925: ?cfgh([auth, ldap, bind_pool_tag], ldap_bind_pool, 926: auth_ldap_raw(#{<<"bind_pool_tag">> => <<"ldap_bind_pool">>})), 927: ?errh(auth_ldap_raw(#{<<"bind_pool_tag">> => true})). 928: 929: auth_ldap_base(_Config) -> 930: ?cfgh([auth, ldap, base], <<>>, auth_ldap_raw(#{})), % default 931: ?cfgh([auth, ldap, base], <<"ou=Users,dc=example,dc=com">>, 932: auth_ldap_raw(#{<<"base">> => <<"ou=Users,dc=example,dc=com">>})), 933: ?errh(auth_ldap_raw(#{<<"base">> => 10})). 934: 935: auth_ldap_uids(_Config) -> 936: ?cfgh([auth, ldap, uids], [{<<"uid">>, <<"%u">>}], auth_ldap_raw(#{})), % default 937: ?cfgh([auth, ldap, uids], [{<<"uid1">>, <<"user=%u">>}], 938: auth_ldap_raw(#{<<"uids">> => [#{<<"attr">> => <<"uid1">>, 939: <<"format">> => <<"user=%u">>}]})), 940: ?cfgh([auth, ldap, uids], [<<"uid1">>], 941: auth_ldap_raw(#{<<"uids">> => [#{<<"attr">> => <<"uid1">>}]})), 942: ?errh(auth_ldap_raw(#{<<"uids">> => [#{<<"format">> => <<"user=%u">>}]})). 943: 944: auth_ldap_filter(_Config) -> 945: ?cfgh([auth, ldap, filter], <<>>, auth_ldap_raw(#{})), % default 946: ?cfgh([auth, ldap, filter], <<"(objectClass=inetOrgPerson)">>, 947: auth_ldap_raw(#{<<"filter">> => <<"(objectClass=inetOrgPerson)">>})), 948: ?errh(auth_ldap_raw(#{<<"filter">> => 10})). 949: 950: auth_ldap_dn_filter(_Config) -> 951: ?cfgh([auth, ldap, dn_filter], {undefined, []}, auth_ldap_raw(#{})), % default 952: ?cfgh([auth, ldap, dn_filter], {<<"(user=%u@%d)">>, []}, 953: auth_ldap_raw(#{<<"dn_filter">> => #{<<"filter">> => <<"(user=%u@%d)">>}})), 954: Pattern = <<"(&(name=%s)(owner=%D)(user=%u@%d))">>, 955: ?cfgh([auth, ldap, dn_filter], {Pattern, [<<"sn">>]}, 956: auth_ldap_raw(#{<<"dn_filter">> => #{<<"filter">> => Pattern, 957: <<"attributes">> => [<<"sn">>]}})), 958: ?errh(auth_ldap_raw(#{<<"dn_filter">> => #{<<"attributes">> => [<<"sn">>]}})), 959: ?errh(auth_ldap_raw(#{<<"dn_filter">> => #{<<"filter">> => 12}})), 960: ?errh(auth_ldap_raw(#{<<"dn_filter">> => #{<<"filter">> => Pattern, 961: <<"attributes">> => <<"sn">>}})). 962: 963: auth_ldap_local_filter(_Config) -> 964: ?cfgh([auth, ldap, local_filter], undefined, auth_ldap_raw(#{})), % default 965: Filter = #{<<"operation">> => <<"equal">>, 966: <<"attribute">> => <<"accountStatus">>, 967: <<"values">> => [<<"enabled">>]}, 968: ?cfgh([auth, ldap, local_filter], {equal, {"accountStatus", ["enabled"]}}, 969: auth_ldap_raw(#{<<"local_filter">> => Filter})), 970: [?errh(auth_ldap_raw(#{<<"local_filter">> => maps:remove(K, Filter)})) || 971: K <- maps:keys(Filter)], 972: ?errh(auth_ldap_raw(#{<<"local_filter">> => Filter#{<<"operation">> := <<"lt">>}})), 973: ?errh(auth_ldap_raw(#{<<"local_filter">> => Filter#{<<"attribute">> := <<>>}})), 974: ?errh(auth_ldap_raw(#{<<"local_filter">> => Filter#{<<"values">> := []}})). 975: 976: auth_ldap_deref(_Config) -> 977: ?cfgh([auth, ldap, deref], never, auth_ldap_raw(#{})), % default 978: ?cfgh([auth, ldap, deref], always, auth_ldap_raw(#{<<"deref">> => <<"always">>})), 979: ?errh(auth_ldap_raw(#{<<"deref">> => <<"sometimes">>})). 980: 981: auth_external(_Config) -> 982: RequiredOpts = #{<<"program">> => <<"/usr/bin/auth">>}, 983: Config = #{program => "/usr/bin/auth", 984: instances => 1}, % default 985: ?cfgh([auth, external], Config, 986: auth_raw(<<"external">>, RequiredOpts)), 987: ?cfgh([auth, external, instances], 2, 988: auth_raw(<<"external">>, RequiredOpts#{<<"instances">> => 2})), 989: ?errh(auth_raw(<<"external">>, #{<<"program">> => <<>>})), 990: ?errh(auth_raw(<<"external">>, #{<<"instances">> => 2})), 991: ?errh(auth_raw(<<"external">>, RequiredOpts#{<<"instances">> => 0})). 992: 993: auth_http_basic_auth(_Config) -> 994: ?cfgh([auth, http, basic_auth], "admin:admin123", 995: auth_raw(<<"http">>, #{<<"basic_auth">> => <<"admin:admin123">>})), 996: ?errh(auth_raw(<<"http">>, #{<<"basic_auth">> => true})). 997: 998: auth_jwt(_Config) -> 999: Opts = #{<<"secret">> => #{<<"value">> => <<"secret123">>}, 1000: <<"algorithm">> => <<"HS512">>, 1001: <<"username_key">> => <<"user">>}, % tested together as all options are required 1002: Config = #{algorithm => <<"HS512">>, 1003: secret => {value, "secret123"}, 1004: username_key => user}, 1005: ?cfgh([auth, jwt], Config, 1006: auth_raw(<<"jwt">>, Opts)), 1007: ?cfgh([auth, jwt, secret], {file, "/home/user/jwt_secret"}, 1008: auth_raw(<<"jwt">>, Opts#{<<"secret">> := #{<<"file">> => <<"/home/user/jwt_secret">>}})), 1009: ?cfgh([auth, jwt, secret], {env, "SECRET"}, 1010: auth_raw(<<"jwt">>, Opts#{<<"secret">> := #{<<"env">> => <<"SECRET">>}})), 1011: ?errh(auth_raw(<<"jwt">>, Opts#{<<"secret">> := #{<<"value">> => 123}})), 1012: ?errh(auth_raw(<<"jwt">>, Opts#{<<"secret">> := #{<<"file">> => <<>>}})), 1013: ?errh(auth_raw(<<"jwt">>, Opts#{<<"secret">> := #{<<"env">> => <<>>}})), 1014: ?errh(auth_raw(<<"jwt">>, Opts#{<<"secret">> := #{<<"file">> => <<"/jwt_secret">>, 1015: <<"env">> => <<"SECRET">>}})), 1016: ?errh(auth_raw(<<"jwt">>, Opts#{<<"algorithm">> := <<"bruteforce">>})), 1017: ?errh(auth_raw(<<"jwt">>, Opts#{<<"username_key">> := <<>>})), 1018: [?errh(auth_raw(<<"jwt">>, maps:without([K], Opts))) || K <- maps:keys(Opts)]. 1019: 1020: auth_riak_bucket_type(_Config) -> 1021: ?cfgh([auth, riak, bucket_type], <<"users">>, auth_raw(<<"riak">>, #{})), % default 1022: ?cfgh([auth, riak, bucket_type], <<"buckethead">>, 1023: auth_raw(<<"riak">>, #{<<"bucket_type">> => <<"buckethead">>})), 1024: ?errh(auth_raw(<<"riak">>, #{<<"bucket_type">> => <<>>})). 1025: 1026: auth_rdbms_users_number_estimate(_Config) -> 1027: ?cfgh([auth, rdbms, users_number_estimate], false, auth_raw(<<"rdbms">>, #{})), % default 1028: ?cfgh([auth, rdbms, users_number_estimate], true, 1029: auth_raw(<<"rdbms">>, #{<<"users_number_estimate">> => true})), 1030: ?errh(auth_raw(<<"rdbms">>, #{<<"users_number_estimate">> => 1200})). 1031: 1032: auth_dummy(_Config) -> 1033: ?cfgh([auth, dummy], #{base_time => 50, variance => 450}, auth_raw(<<"dummy">>, #{})), % default 1034: ?cfgh([auth, dummy, base_time], 0, auth_raw(<<"dummy">>, #{<<"base_time">> => 0})), 1035: ?cfgh([auth, dummy, variance], 10, auth_raw(<<"dummy">>, #{<<"variance">> => 10})), 1036: ?errh(auth_raw(<<"dummy">>, #{<<"base_time">> => -5})), 1037: ?errh(auth_raw(<<"dummy">>, #{<<"variance">> => 0})). 1038: 1039: %% tests: outgoing_pools 1040: 1041: pool_type(_Config) -> 1042: ?cfg(pool_config(#{type => http}), 1043: pool_raw(<<"http">>, <<"default">>, #{})), 1044: ?err(pool_raw(<<"swimming_pool">>, <<"default">>, #{})). 1045: 1046: pool_tag(_Config) -> 1047: ?cfg(pool_config(#{type => http, tag => my_pool}), 1048: pool_raw(<<"http">>, <<"my_pool">>, #{})), 1049: ?err(pool_raw(<<"http">>, 1000, #{})). 1050: 1051: pool_scope(_Config) -> 1052: ?cfg(pool_config(#{type => http, scope => host}), 1053: pool_raw(<<"http">>, <<"default">>, #{<<"scope">> => <<"host">>})), 1054: ?cfg(pool_config(#{type => http, scope => <<"localhost">>}), 1055: pool_raw(<<"http">>, <<"default">>, #{<<"scope">> => <<"single_host">>, 1056: <<"host">> => <<"localhost">>})), 1057: ?err(pool_raw(<<"http">>, <<"default">>, #{<<"scope">> => <<"whatever">>})), 1058: ?err(pool_raw(<<"http">>, <<"default">>, #{<<"scope">> => <<"single_host">>})). 1059: 1060: pool_workers(_Config) -> 1061: ?cfg(pool_config(#{type => http, opts => #{workers => 11}}), 1062: pool_raw(<<"http">>, <<"default">>, #{<<"workers">> => 11})), 1063: ?err(pool_raw(<<"http">>, <<"default">>, #{<<"workers">> => 0})). 1064: 1065: pool_strategy(_Config) -> 1066: ?cfg(pool_config(#{type => http, opts => #{strategy => random_worker}}), 1067: pool_raw(<<"http">>, <<"default">>, #{<<"strategy">> => <<"random_worker">>})), 1068: ?err(pool_raw(<<"http">>, <<"default">>, #{<<"strategy">> => <<"worst_worker">>})). 1069: 1070: pool_call_timeout(_Config) -> 1071: ?cfg(pool_config(#{type => http, opts => #{call_timeout => 999}}), 1072: pool_raw(<<"http">>, <<"default">>, #{<<"call_timeout">> => 999})), 1073: ?err(pool_raw(<<"http">>, <<"default">>, #{<<"call_timeout">> => 0})). 1074: 1075: pool_rdbms_settings(_Config) -> 1076: ?cfg(pool_config(#{type => rdbms, conn_opts => #{server => "DSN=mydb"}}), 1077: pool_conn_raw(<<"rdbms">>, #{<<"driver">> => <<"odbc">>, 1078: <<"settings">> => <<"DSN=mydb">>})), 1079: ?err(pool_conn_raw(<<"rdbms">>, #{<<"driver">> => <<"mysql">>, 1080: <<"settings">> => <<"DSN=mydb">>})), 1081: ?err(pool_conn_raw(<<"rdbms">>, #{<<"driver">> => <<"odbc">>, 1082: <<"settings">> => true})), 1083: ?err(pool_conn_raw(<<"rdbms">>, #{<<"driver">> => <<"odbc">>})). 1084: 1085: pool_rdbms_keepalive_interval(_Config) -> 1086: ?cfg(pool_config(#{type => rdbms, conn_opts => #{server => "DSN=mydb", 1087: keepalive_interval => 1000}}), 1088: pool_conn_raw(<<"rdbms">>, #{<<"driver">> => <<"odbc">>, 1089: <<"settings">> => <<"DSN=mydb">>, 1090: <<"keepalive_interval">> => 1000})), 1091: ?err(pool_conn_raw(<<"rdbms">>, #{<<"driver">> => <<"odbc">>, 1092: <<"settings">> => <<"DSN=mydb">>, 1093: <<"keepalive_interval">> => false})). 1094: 1095: pool_rdbms_server(_Config) -> 1096: ServerOpts = rdbms_opts(), 1097: ?cfg(pool_config(#{type => rdbms, 1098: conn_opts => #{server => {pgsql, "localhost", "db", "dbuser", "secret"}}}), 1099: pool_conn_raw(<<"rdbms">>, ServerOpts)), 1100: ?err(pool_conn_raw(<<"rdbms">>, ServerOpts#{<<"driver">> := <<"odbc">>})), 1101: [?err(pool_conn_raw(<<"rdbms">>, maps:without([K], ServerOpts))) || 1102: K <- maps:keys(ServerOpts)], 1103: [?err(pool_conn_raw(<<"rdbms">>, ServerOpts#{K := 123})) || 1104: K <- maps:keys(ServerOpts)]. 1105: 1106: pool_rdbms_port(_Config) -> 1107: ServerOpts = rdbms_opts(), 1108: ?cfg(pool_config(#{type => rdbms, 1109: conn_opts => #{server => {pgsql, "localhost", 1234, "db", "dbuser", "secret"}}}), 1110: pool_conn_raw(<<"rdbms">>, ServerOpts#{<<"port">> => 1234})), 1111: ?err(pool_conn_raw(<<"rdbms">>, ServerOpts#{<<"port">> => <<"airport">>})). 1112: 1113: pool_rdbms_tls(_Config) -> 1114: ServerOpts = rdbms_opts(), 1115: ?cfg(pool_config(#{type => rdbms, 1116: conn_opts => #{server => {pgsql, "localhost", "db", "dbuser", "secret", 1117: [{ssl, required}]}}}), 1118: pool_conn_raw(<<"rdbms">>, ServerOpts#{<<"tls">> => #{<<"required">> => true}})), 1119: ?cfg(pool_config(#{type => rdbms, 1120: conn_opts => #{server => {pgsql, "localhost", "db", "dbuser", "secret", 1121: [{ssl, true}]}}}), 1122: pool_conn_raw(<<"rdbms">>, ServerOpts#{<<"tls">> => #{}})), 1123: ?cfg(pool_config(#{type => rdbms, 1124: conn_opts => #{server => {mysql, "localhost", "db", "dbuser", "secret", []}}}), 1125: pool_conn_raw(<<"rdbms">>, ServerOpts#{<<"driver">> => <<"mysql">>, 1126: <<"tls">> => #{}})), 1127: ?cfg(pool_config(#{type => rdbms, 1128: conn_opts => #{server => {pgsql, "localhost", 1234, "db", "dbuser", "secret", 1129: [{ssl, true}]}}}), 1130: pool_conn_raw(<<"rdbms">>, ServerOpts#{<<"tls">> => #{}, 1131: <<"port">> => 1234})), 1132: 1133: %% one option tested here as they are all checked by 'listen_tls_*' tests 1134: ?cfg(pool_config(#{type => rdbms, 1135: conn_opts => #{server => {pgsql, "localhost", "db", "dbuser", "secret", 1136: [{ssl, true}, {ssl_opts, [{certfile, "cert.pem"}]}]}}}), 1137: pool_conn_raw(<<"rdbms">>, ServerOpts#{<<"tls">> => 1138: #{<<"certfile">> => <<"cert.pem">>}})), 1139: ?err(pool_conn_raw(<<"rdbms">>, ServerOpts#{<<"tls">> => 1140: #{<<"certfile">> => true}})), 1141: ?err(pool_conn_raw(<<"rdbms">>, ServerOpts#{<<"tls">> => <<"secure">>})). 1142: 1143: pool_http_host(_Config) -> 1144: ?cfg(pool_config(#{type => http, conn_opts => #{server => "https://localhost:8443"}}), 1145: pool_conn_raw(<<"http">>, #{<<"host">> => <<"https://localhost:8443">>})), 1146: ?err(pool_conn_raw(<<"http">>, #{<<"host">> => 8443})), 1147: ?err(pool_conn_raw(<<"http">>, #{<<"host">> => ""})). 1148: 1149: pool_http_path_prefix(_Config) -> 1150: ?cfg(pool_config(#{type => http, conn_opts => #{path_prefix => "/my_path/"}}), 1151: pool_conn_raw(<<"http">>, #{<<"path_prefix">> => <<"/my_path/">>})), 1152: ?err(pool_conn_raw(<<"http">>, #{<<"path_prefix">> => 8443})), 1153: ?err(pool_conn_raw(<<"http">>, #{<<"path_prefix">> => ""})). 1154: 1155: pool_http_request_timeout(_Config) -> 1156: ?cfg(pool_config(#{type => http, conn_opts => #{request_timeout => 999}}), 1157: pool_conn_raw(<<"http">>, #{<<"request_timeout">> => 999})), 1158: ?err(pool_conn_raw(<<"http">>, #{<<"request_timeout">> => -1000})), 1159: ?err(pool_conn_raw(<<"http">>, #{<<"request_timeout">> => <<"infinity">>})). 1160: 1161: pool_http_tls(_Config) -> 1162: ?cfg(pool_config(#{type => http, conn_opts => #{http_opts => [{certfile, "cert.pem"}]}}), 1163: pool_conn_raw(<<"http">>, #{<<"tls">> => #{<<"certfile">> => <<"cert.pem">>}})), 1164: ?cfg(pool_config(#{type => http, 1165: conn_opts => #{http_opts => [{certfile, "cert.pem"}, 1166: {verify, verify_peer}, 1167: {cacertfile, "priv/ca.pem"}, 1168: {server_name_indication, disable}]}}), 1169: pool_conn_raw(<<"http">>, #{<<"tls">> => #{<<"certfile">> => <<"cert.pem">>, 1170: <<"verify_peer">> => true, 1171: <<"cacertfile">> => <<"priv/ca.pem">>, 1172: <<"server_name_indication">> => false}})), 1173: ?cfg(pool_config(#{type => http, 1174: conn_opts => #{http_opts => [{certfile, "cert.pem"}, 1175: {verify, verify_peer}, 1176: {cacertfile, "priv/ca.pem"}, 1177: {server_name_indication, "domain.com"}]}}), 1178: pool_conn_raw(<<"http">>, #{<<"tls">> => #{<<"certfile">> => <<"cert.pem">>, 1179: <<"verify_peer">> => true, 1180: <<"cacertfile">> => <<"priv/ca.pem">>, 1181: <<"server_name_indication">> => true, 1182: <<"server_name_indication_host">> => <<"domain.com">>}})), 1183: ?cfg(pool_config(#{type => http, 1184: conn_opts => #{http_opts => [{certfile, "cert.pem"}, 1185: {verify, verify_peer}, 1186: {cacertfile, "priv/ca.pem"}, 1187: {server_name_indication, "domain.com"}, 1188: {customize_hostname_check, 1189: [{match_fun, public_key:pkix_verify_hostname_match_fun(https)}]}]}}), 1190: pool_conn_raw(<<"http">>, #{<<"tls">> => #{<<"certfile">> => <<"cert.pem">>, 1191: <<"verify_peer">> => true, 1192: <<"cacertfile">> => <<"priv/ca.pem">>, 1193: <<"server_name_indication">> => true, 1194: <<"server_name_indication_host">> => <<"domain.com">>, 1195: <<"server_name_indication_protocol">> => <<"https">>}})), 1196: ?cfg(pool_config(#{type => http, 1197: conn_opts => #{http_opts => [{verify, verify_peer}, 1198: {cacertfile, "priv/ca.pem"}]}}), 1199: pool_conn_raw(<<"http">>, #{<<"tls">> => #{<<"verify_peer">> => true, 1200: <<"cacertfile">> => <<"priv/ca.pem">>}})), 1201: ?err(pool_conn_raw(<<"http">>, #{<<"tls">> => #{<<"verify_peer">> => true, 1202: <<"cacertfile">> => <<"priv/ca.pem">>, 1203: <<"server_name_indication">> => <<"domain.com">>, 1204: <<"server_name_indication_host">> => <<"domain.com">>}})), 1205: ?err(pool_conn_raw(<<"http">>, #{<<"tls">> => #{<<"verify_peer">> => true, 1206: <<"cacertfile">> => <<"priv/ca.pem">>, 1207: <<"server_name_indication">> => <<"true">>, 1208: <<"server_name_indication_host">> => <<"domain.com">>, 1209: <<"server_name_indication_protocol">> => <<"non_value">>}})), 1210: ?err(pool_conn_raw(<<"http">>, #{<<"tls">> => #{<<"certfile">> => true}})), 1211: ?err(pool_conn_raw(<<"http">>, #{<<"tls">> => <<"secure">>})). 1212: 1213: pool_redis_host(_Config) -> 1214: ?cfg(pool_config(#{type => redis, conn_opts => #{host => "my_host"}}), 1215: pool_conn_raw(<<"redis">>, #{<<"host">> => <<"my_host">>})), 1216: ?err(pool_conn_raw(<<"redis">>, #{<<"host">> => 8443})), 1217: ?err(pool_conn_raw(<<"redis">>, #{<<"host">> => ""})). 1218: 1219: pool_redis_port(_Config) -> 1220: ?cfg(pool_config(#{type => redis, conn_opts => #{port => 9999}}), 1221: pool_conn_raw(<<"redis">>, #{<<"port">> => 9999})), 1222: ?err(pool_conn_raw(<<"redis">>, #{<<"port">> => 666666})), 1223: ?err(pool_conn_raw(<<"redis">>, #{<<"port">> => <<"airport">>})). 1224: 1225: pool_redis_database(_Config) -> 1226: ?cfg(pool_config(#{type => redis, conn_opts => #{database => 1}}), 1227: pool_conn_raw(<<"redis">>, #{<<"database">> => 1})), 1228: ?err(pool_conn_raw(<<"redis">>, #{<<"database">> => -1})), 1229: ?err(pool_conn_raw(<<"redis">>, #{<<"database">> => <<"my_database">>})). 1230: 1231: pool_redis_password(_Config) -> 1232: ?cfg(pool_config(#{type => redis, conn_opts => #{password => "password1"}}), 1233: pool_conn_raw(<<"redis">>, #{<<"password">> => <<"password1">>})), 1234: ?err(pool_conn_raw(<<"redis">>, #{<<"password">> => 0})). 1235: 1236: pool_riak_address(_Config) -> 1237: ?cfg(pool_config(#{type => riak, conn_opts => #{address => "127.0.0.1"}}), 1238: pool_conn_raw(<<"riak">>, #{<<"address">> => <<"127.0.0.1">>})), 1239: ?err(pool_conn_raw(<<"riak">>, #{<<"address">> => 66})), 1240: ?err(pool_conn_raw(<<"riak">>, #{<<"address">> => <<"">>})). 1241: 1242: pool_riak_port(_Config) -> 1243: ?cfg(pool_config(#{type => riak, conn_opts => #{port => 8087}}), 1244: pool_conn_raw(<<"riak">>, #{<<"port">> => 8087})), 1245: ?err(pool_conn_raw(<<"riak">>, #{<<"port">> => 666666})), 1246: ?err(pool_conn_raw(<<"riak">>, #{<<"port">> => <<"airport">>})). 1247: 1248: pool_riak_credentials(_Config) -> 1249: ?cfg(pool_config(#{type => riak, conn_opts => #{credentials => {"user", "pass"}}}), 1250: pool_conn_raw(<<"riak">>, #{<<"credentials">> => 1251: #{<<"user">> => <<"user">>, <<"password">> => <<"pass">>}})), 1252: ?err(pool_conn_raw(<<"riak">>, #{<<"credentials">> => #{<<"user">> => <<"user">>}})), 1253: ?err(pool_conn_raw(<<"riak">>, #{<<"credentials">> => 1254: #{<<"user">> => <<"">>, <<"password">> => 011001}})). 1255: 1256: pool_riak_cacertfile(_Config) -> 1257: ?cfg(pool_config(#{type => riak, conn_opts => #{cacertfile => "cacert.pem"}}), 1258: pool_conn_raw(<<"riak">>, #{<<"tls">> => #{<<"cacertfile">> => <<"cacert.pem">>}})), 1259: ?err(pool_conn_raw(<<"riak">>, #{<<"cacertfile">> => <<"">>})). 1260: 1261: pool_riak_tls(_Config) -> 1262: %% make sure these options are not extracted out of 'ssl_opts' 1263: %% all the TLS options are checked by 'listen_tls_*' tests 1264: ?cfg(pool_config(#{type => riak, 1265: conn_opts => #{ssl_opts => [{certfile, "path/to/cert.pem"}, 1266: {dhfile, "cert.pem"}, 1267: {keyfile, "path/to/key.pem"}]}}), 1268: pool_conn_raw(<<"riak">>, #{<<"tls">> => #{<<"certfile">> => <<"path/to/cert.pem">>, 1269: <<"dhfile">> => <<"cert.pem">>, 1270: <<"keyfile">> => <<"path/to/key.pem">>}})), 1271: ?err(pool_conn_raw(<<"riak">>, #{<<"tls">> => #{<<"dhfile">> => true}})), 1272: ?err(pool_conn_raw(<<"riak">>, #{<<"tls">> => <<"secure">>})). 1273: 1274: pool_cassandra_servers(_Config) -> 1275: ?cfg(pool_config(#{type => cassandra, 1276: conn_opts => #{servers => [{"cassandra_server1.example.com", 9042}, 1277: {"cassandra_server2.example.com", 9042}]}}), 1278: pool_conn_raw(<<"cassandra">>, 1279: #{<<"servers">> => [#{<<"ip_address">> => <<"cassandra_server1.example.com">>, 1280: <<"port">> => 9042}, 1281: #{<<"ip_address">> => <<"cassandra_server2.example.com">>, 1282: <<"port">> => 9042}]})), 1283: ?err(pool_conn_raw(<<"cassandra">>, 1284: #{<<"servers">> => #{<<"ip_address">> => <<"cassandra_server1.example.com">>, 1285: <<"port">> => 9042}})). 1286: 1287: pool_cassandra_keyspace(_Config) -> 1288: ?cfg(pool_config(#{type => cassandra, conn_opts => #{keyspace => big_mongooseim}}), 1289: pool_conn_raw(<<"cassandra">>, #{<<"keyspace">> => <<"big_mongooseim">>})), 1290: ?err(pool_conn_raw(<<"cassandra">>, #{<<"keyspace">> => <<"">>})). 1291: 1292: pool_cassandra_auth(_Config) -> 1293: ?cfg(pool_config(#{type => cassandra, 1294: conn_opts => #{auth => {cqerl_auth_plain_handler, 1295: [{<<"auser">>, <<"secretpass">>}]}}}), 1296: pool_conn_raw(<<"cassandra">>, 1297: #{<<"auth">> => #{<<"plain">> => #{<<"username">> => <<"auser">>, 1298: <<"password">> => <<"secretpass">>}}})), 1299: ?err(pool_conn_raw(<<"cassandra">>, #{<<"tls">> => #{<<"verify">> => <<"verify_none">>}})). 1300: 1301: pool_cassandra_tls(_Config) -> 1302: %% one option tested here as they are all checked by 'listen_tls_*' tests 1303: ?cfg(pool_config(#{type => cassandra, conn_opts => #{ssl => [{verify, verify_none}]}}), 1304: pool_conn_raw(<<"cassandra">>, #{<<"tls">> => #{<<"verify_peer">> => false}})), 1305: ?err(pool_conn_raw(<<"cassandra">>, #{<<"tls">> => #{<<"verify">> => <<"verify_none">>}})). 1306: 1307: pool_elastic_host(_Config) -> 1308: ?cfg(pool_config(#{type => elastic, conn_opts => #{host => "my_host"}}), 1309: pool_conn_raw(<<"elastic">>, #{<<"host">> => <<"my_host">>})), 1310: ?err(pool_conn_raw(<<"elastic">>, #{<<"host">> => <<"">>})). 1311: 1312: pool_elastic_port(_Config) -> 1313: ?cfg(pool_config(#{type => elastic, conn_opts => #{port => 9999}}), 1314: pool_conn_raw(<<"elastic">>, #{<<"port">> => 9999})), 1315: ?err(pool_conn_raw(<<"elastic">>, #{<<"port">> => 122333})), 1316: ?err(pool_conn_raw(<<"elastic">>, #{<<"port">> => <<"airport">>})). 1317: 1318: pool_rabbit_amqp_host(_Config) -> 1319: ?cfg(pool_config(#{type => rabbit, conn_opts => #{amqp_host => "localhost"}}), 1320: pool_conn_raw(<<"rabbit">>, #{<<"amqp_host">> => <<"localhost">>})), 1321: ?err(pool_conn_raw(<<"rabbit">>, #{<<"amqp_host">> => <<"">>})). 1322: 1323: pool_rabbit_amqp_port(_Config) -> 1324: ?cfg(pool_config(#{type => rabbit, conn_opts => #{amqp_port => 5672}}), 1325: pool_conn_raw(<<"rabbit">>, #{<<"amqp_port">> => 5672})), 1326: ?err(pool_conn_raw(<<"rabbit">>, #{<<"amqp_port">> => <<"airport">>})). 1327: 1328: pool_rabbit_amqp_username(_Config) -> 1329: ?cfg(pool_config(#{type => rabbit, conn_opts => #{amqp_username => "guest"}}), 1330: pool_conn_raw(<<"rabbit">>, #{<<"amqp_username">> => <<"guest">>})), 1331: ?err(pool_conn_raw(<<"rabbit">>, #{<<"amqp_username">> => <<"">>})). 1332: 1333: pool_rabbit_amqp_password(_Config) -> 1334: ?cfg(pool_config(#{type => rabbit, conn_opts => #{amqp_password => "guest"}}), 1335: pool_conn_raw(<<"rabbit">>, #{<<"amqp_password">> => <<"guest">>})), 1336: ?err(pool_conn_raw(<<"rabbit">>, #{<<"amqp_password">> => <<"">>})). 1337: 1338: pool_rabbit_amqp_confirms_enabled(_Config) -> 1339: ?cfg(pool_config(#{type => rabbit, conn_opts => #{confirms_enabled => true}}), 1340: pool_conn_raw(<<"rabbit">>, #{<<"confirms_enabled">> => true})), 1341: ?err(pool_conn_raw(<<"rabbit">>, #{<<"confirms_enabled">> => <<"yes">>})). 1342: 1343: pool_rabbit_amqp_max_worker_queue_len(_Config) -> 1344: ?cfg(pool_config(#{type => rabbit, conn_opts => #{max_worker_queue_len => 100}}), 1345: pool_conn_raw(<<"rabbit">>, #{<<"max_worker_queue_len">> => 100})), 1346: ?err(pool_conn_raw(<<"rabbit">>, #{<<"max_worker_queue_len">> => 0})). 1347: 1348: pool_ldap_port(_Config) -> 1349: ?cfg(pool_config(#{type => ldap, conn_opts => #{port => 389}}), 1350: pool_conn_raw(<<"ldap">>, #{<<"port">> => 389})), 1351: ?err(pool_conn_raw(<<"ldap">>, #{<<"port">> => <<"airport">>})). 1352: 1353: pool_ldap_servers(_Config) -> 1354: ?cfg(pool_config(#{type => ldap, 1355: conn_opts => #{servers => ["primary-ldap-server.example.com", 1356: "secondary-ldap-server.example.com"]}}), 1357: pool_conn_raw(<<"ldap">>, #{<<"servers">> => [<<"primary-ldap-server.example.com">>, 1358: <<"secondary-ldap-server.example.com">>]})), 1359: ?err(pool_conn_raw(<<"ldap">>, #{<<"servers">> => #{<<"server">> => <<"example.com">>}})). 1360: 1361: pool_ldap_encrypt(_Config) -> 1362: ?cfg(pool_config(#{type => ldap, conn_opts => #{encrypt => tls}}), 1363: pool_conn_raw(<<"ldap">>, #{<<"encrypt">> => <<"tls">>})), 1364: ?err(pool_conn_raw(<<"ldap">>, #{<<"encrypt">> => true})). 1365: 1366: pool_ldap_rootdn(_Config) -> 1367: ?cfg(pool_config(#{type => ldap, conn_opts => #{rootdn => "my_rootdn"}}), 1368: pool_conn_raw(<<"ldap">>, #{<<"rootdn">> => <<"my_rootdn">>})), 1369: ?err(pool_conn_raw(<<"ldap">>, #{<<"rootdn">> => false})). 1370: 1371: pool_ldap_password(_Config) -> 1372: ?cfg(pool_config(#{type => ldap, conn_opts => #{password => "pass"}}), 1373: pool_conn_raw(<<"ldap">>, #{<<"password">> => <<"pass">>})), 1374: ?err(pool_conn_raw(<<"ldap">>, #{<<"password">> => true})). 1375: 1376: pool_ldap_connect_interval(_Config) -> 1377: ?cfg(pool_config(#{type => ldap, conn_opts => #{connect_interval => 9999}}), 1378: pool_conn_raw(<<"ldap">>, #{<<"connect_interval">> => 9999})), 1379: ?err(pool_conn_raw(<<"ldap">>, #{<<"connect_interval">> => <<"infinity">>})). 1380: 1381: pool_ldap_tls(_Config) -> 1382: %% one option tested here as they are all checked by 'listen_tls_*' tests 1383: ?cfg(pool_config(#{type => ldap, conn_opts => #{tls_options => [{verify, verify_peer}]}}), 1384: pool_conn_raw(<<"ldap">>, #{<<"tls">> => #{<<"verify_peer">> => true}})), 1385: ?err(pool_conn_raw(<<"ldap">>, #{<<"tls">> => #{<<"verify">> => <<"verify_none">>}})). 1386: 1387: %% tests: shaper, acl, access 1388: shaper(_Config) -> 1389: ?cfg([shaper, normal], #{max_rate => 1000}, 1390: #{<<"shaper">> => #{<<"normal">> => #{<<"max_rate">> => 1000}}}), 1391: ?err(#{<<"shaper">> => #{<<"unlimited">> => #{<<"max_rate">> => <<"infinity">>}}}), 1392: ?err(#{<<"shaper">> => #{<<"fast">> => #{}}}). 1393: 1394: acl(_Config) -> 1395: ?cfgh([acl, local], [#{match => all}], 1396: #{<<"acl">> => #{<<"local">> => [#{<<"match">> => <<"all">>}]}}), 1397: ?cfgh([acl, local], [#{match => any_hosted_domain}], 1398: #{<<"acl">> => #{<<"local">> => [#{<<"match">> => <<"any_hosted_domain">>}]}}), 1399: ?cfgh([acl, local], [#{match => current_domain, 1400: user_regexp => <<>>}], 1401: #{<<"acl">> => #{<<"local">> => [#{<<"user_regexp">> => <<>>}]}}), 1402: ?cfgh([acl, alice], [#{match => current_domain, 1403: user_regexp => <<"ali.*">>, 1404: server_regexp => <<".*host">>}], 1405: #{<<"acl">> => #{<<"alice">> => [#{<<"user_regexp">> => <<"aLi.*">>, 1406: <<"server_regexp">> => <<".*HosT">>}]}}), 1407: ?cfgh([acl, alice], [#{match => current_domain, 1408: user => <<"alice">>, 1409: server => <<"localhost">>}], 1410: #{<<"acl">> => #{<<"alice">> => [#{<<"user">> => <<"alice">>, 1411: <<"server">> => <<"localhost">>}]}}), 1412: ?errh(#{<<"acl">> => #{<<"local">> => <<"everybody">>}}), 1413: ?errh(#{<<"acl">> => #{<<"local">> => [#{<<"match">> => <<"lit">>}]}}), 1414: ?errh(#{<<"acl">> => #{<<"alice">> => [#{<<"user_glob">> => <<"a*">>, 1415: <<"server_blog">> => <<"bloghost">>}]}}), 1416: ?errh([#{reason := incorrect_acl_condition_value}], 1417: #{<<"acl">> => #{<<"local">> => [#{<<"user">> => <<"@@@">>}]}}). 1418: 1419: acl_merge_host_and_global(_Config) -> 1420: G = #{<<"acl">> => #{<<"admin">> => [#{<<"user">> => <<"george">>}]}}, 1421: H1 = #{<<"acl">> => #{<<"admin">> => [#{<<"user">> => <<"henry">>}]}}, 1422: H2 = #{<<"acl">> => #{<<"hostile">> => [#{<<"user">> => <<"hacker">>}]}}, 1423: ?cfg([{{acl, global}, #{admin => [#{user => <<"george">>, match => current_domain}]}}, 1424: {{acl, ?HOST}, #{admin => [#{user => <<"george">>, match => current_domain}]}}], 1425: maps:merge(G, host_config(G))), 1426: ?cfg([{{acl, global}, #{admin => [#{user => <<"george">>, match => current_domain}]}}, 1427: {{acl, ?HOST}, #{admin => [#{user => <<"george">>, match => current_domain}, 1428: #{user => <<"henry">>, match => current_domain}]}}], 1429: maps:merge(G, host_config(H1))), 1430: ?cfg([{{acl, global}, #{admin => [#{user => <<"george">>, match => current_domain}]}}, 1431: {{acl, ?HOST}, #{admin => [#{user => <<"george">>, match => current_domain}], 1432: hostile => [#{user => <<"hacker">>, match => current_domain}]}}], 1433: maps:merge(G, host_config(H2))). 1434: 1435: access(_Config) -> 1436: ?cfgh([access, c2s], [#{acl => blocked, value => deny}, 1437: #{acl => all, value => allow}], 1438: access_raw(<<"c2s">>, [#{<<"acl">> => <<"blocked">>, <<"value">> => <<"deny">>}, 1439: #{<<"acl">> => <<"all">>, <<"value">> => <<"allow">>}])), 1440: ?cfgh([access, max_user_sessions], [#{acl => all, value => 10}], 1441: access_raw(<<"max_user_sessions">>, [#{<<"acl">> => <<"all">>, <<"value">> => 10}])), 1442: ?errh(access_raw(<<"max_user_sessions">>, [#{<<"acl">> => <<"all">>}])), 1443: ?errh(access_raw(<<"max_user_sessions">>, [#{<<"value">> => 10}])), 1444: ?errh(access_raw(<<"max_user_sessions">>, [#{<<"acl">> => 10, <<"value">> => 10}])). 1445: 1446: access_merge_host_and_global(_Config) -> 1447: G1 = access_raw(<<"c2s">>, [#{<<"acl">> => <<"good">>, <<"value">> => <<"allow">>}]), 1448: G2 = access_raw(<<"c2s">>, [#{<<"acl">> => <<"gangsters">>, <<"value">> => <<"deny">>}, 1449: #{<<"acl">> => <<"all">>, <<"value">> => <<"allow">>}]), 1450: H1 = access_raw(<<"c2s">>, [#{<<"acl">> => <<"harmless">>, <<"value">> => <<"allow">>}]), 1451: H2 = access_raw(<<"s2s">>, [#{<<"acl">> => <<"harmless">>, <<"value">> => <<"allow">>}]), 1452: H3 = access_raw(<<"c2s">>, [#{<<"acl">> => <<"hackers">>, <<"value">> => <<"deny">>}]), 1453: ?cfg([{{access, global}, #{c2s => [#{acl => good, value => allow}]}}, 1454: {{access, ?HOST}, #{c2s => [#{acl => good, value => allow}]}}], 1455: maps:merge(G1, host_config(G1))), 1456: ?cfg([{{access, global}, #{c2s => [#{acl => good, value => allow}]}}, 1457: {{access, ?HOST}, #{c2s => [#{acl => good, value => allow}, 1458: #{acl => harmless, value => allow}]}}], 1459: maps:merge(G1, host_config(H1))), 1460: ?cfg([{{access, global}, #{c2s => [#{acl => good, value => allow}]}}, 1461: {{access, ?HOST}, #{c2s => [#{acl => good, value => allow}], 1462: s2s => [#{acl => harmless, value => allow}]}}], 1463: maps:merge(G1, host_config(H2))), 1464: ?cfg([{{access, global}, #{c2s => [#{acl => gangsters, value => deny}, 1465: #{acl => all, value => allow}]}}, 1466: {{access, ?HOST}, #{c2s => [#{acl => gangsters, value => deny}, 1467: #{acl => hackers, value => deny}, 1468: #{acl => all, value => allow}]}}], 1469: maps:merge(G2, host_config(H3))). 1470: 1471: %% tests: s2s 1472: 1473: s2s_host_config(_Config) -> 1474: DefaultS2S = default_s2s(), 1475: EmptyHostConfig = host_config(#{<<"s2s">> => #{}}), 1476: ?cfg(host_key(s2s), DefaultS2S, 1477: EmptyHostConfig#{<<"s2s">> => #{<<"dns">> => #{<<"timeout">> => 5}}}), 1478: StartTLSHostConfig = host_config(#{<<"s2s">> => #{<<"use_starttls">> => <<"required">>}}), 1479: ?cfg(host_key(s2s), DefaultS2S#{use_starttls => required}, 1480: StartTLSHostConfig#{<<"s2s">> => #{<<"dns">> => #{<<"timeout">> => 5}}}). 1481: 1482: s2s_dns_timeout(_Config) -> 1483: ?cfgh([s2s, dns, timeout], 10, #{}), % default 1484: ?cfgh([s2s, dns, timeout], 5, #{<<"s2s">> => #{<<"dns">> => #{<<"timeout">> => 5}}}), 1485: ?errh(#{<<"s2s">> => #{<<"dns">> => #{<<"timeout">> => 0}}}). 1486: 1487: s2s_dns_retries(_Config) -> 1488: ?cfgh([s2s, dns, retries], 2, #{}), % default 1489: ?cfgh([s2s, dns, retries], 1, #{<<"s2s">> => #{<<"dns">> => #{<<"retries">> => 1}}}), 1490: ?errh(#{<<"s2s">> => #{<<"dns">> => #{<<"retries">> => 0}}}). 1491: 1492: s2s_outgoing_port(_Config) -> 1493: ?cfgh([s2s, outgoing, port], 5269, #{}), % default 1494: ?cfgh([s2s, outgoing, port], 5270, #{<<"s2s">> => #{<<"outgoing">> => #{<<"port">> => 5270}}}), 1495: ?errh(#{<<"s2s">> => #{<<"outgoing">> => #{<<"port">> => <<"http">>}}}). 1496: 1497: s2s_outgoing_ip_versions(_Config) -> 1498: ?cfgh([s2s, outgoing, ip_versions], [4, 6], #{}), % default 1499: ?cfgh([s2s, outgoing, ip_versions], [6, 4], 1500: #{<<"s2s">> => #{<<"outgoing">> => #{<<"ip_versions">> => [6, 4]}}}), 1501: ?errh(#{<<"s2s">> => #{<<"outgoing">> => #{<<"ip_versions">> => []}}}), 1502: ?errh(#{<<"s2s">> => #{<<"outgoing">> => #{<<"ip_versions">> => [<<"http">>]}}}). 1503: 1504: s2s_outgoing_timeout(_Config) -> 1505: ?cfgh([s2s, outgoing, connection_timeout], 10000, #{}), % default 1506: ?cfgh([s2s, outgoing, connection_timeout], 5000, 1507: #{<<"s2s">> => #{<<"outgoing">> => #{<<"connection_timeout">> => 5000}}}), 1508: ?cfgh([s2s, outgoing, connection_timeout], infinity, 1509: #{<<"s2s">> => #{<<"outgoing">> => #{<<"connection_timeout">> => <<"infinity">>}}}), 1510: ?errh(#{<<"s2s">> => #{<<"outgoing">> => #{<<"connection_timeout">> => 0}}}). 1511: 1512: s2s_use_starttls(_Config) -> 1513: ?cfgh([s2s, use_starttls], false, #{}), % default 1514: ?cfgh([s2s, use_starttls], required, #{<<"s2s">> => #{<<"use_starttls">> => <<"required">>}}), 1515: ?errh(#{<<"s2s">> => #{<<"use_starttls">> => <<"unnecessary">>}}). 1516: 1517: s2s_certfile(_Config) -> 1518: ?cfgh([s2s, certfile], "priv/server.pem", #{<<"s2s">> => #{<<"certfile">> => <<"priv/server.pem">>}}), 1519: ?errh([#{reason := invalid_filename}], #{<<"s2s">> => #{<<"certfile">> => <<"nofile.pem">>}}), 1520: ?errh(#{<<"s2s">> => #{<<"certfile">> => []}}). 1521: 1522: s2s_default_policy(_Config) -> 1523: ?cfgh([s2s, default_policy], allow, #{}), % default 1524: ?cfgh([s2s, default_policy], deny, #{<<"s2s">> => #{<<"default_policy">> => <<"deny">>}}), 1525: ?errh(#{<<"s2s">> => #{<<"default_policy">> => <<"ask">>}}). 1526: 1527: s2s_host_policy(_Config) -> 1528: Policy = #{<<"host">> => <<"host1">>, 1529: <<"policy">> => <<"allow">>}, 1530: ?cfgh([s2s, host_policy], #{<<"host1">> => allow}, 1531: #{<<"s2s">> => #{<<"host_policy">> => [Policy]}}), 1532: ?cfgh([s2s, host_policy], #{<<"host1">> => allow, 1533: <<"host2">> => deny}, 1534: #{<<"s2s">> => #{<<"host_policy">> => [Policy, #{<<"host">> => <<"host2">>, 1535: <<"policy">> => <<"deny">>}]}}), 1536: ?errh(#{<<"s2s">> => #{<<"host_policy">> => [maps:without([<<"host">>], Policy)]}}), 1537: ?errh(#{<<"s2s">> => #{<<"host_policy">> => [maps:without([<<"policy">>], Policy)]}}), 1538: ?errh(#{<<"s2s">> => #{<<"host_policy">> => [Policy#{<<"host">> => <<>>}]}}), 1539: ?errh(#{<<"s2s">> => #{<<"host_policy">> => [Policy#{<<"policy">> => <<"huh">>}]}}), 1540: ?errh(#{<<"s2s">> => #{<<"host_policy">> => [Policy, 1541: Policy#{<<"policy">> => <<"deny">>}]}}). 1542: 1543: s2s_address(_Config) -> 1544: Addr = #{<<"host">> => <<"host1">>, 1545: <<"ip_address">> => <<"192.168.1.2">>, 1546: <<"port">> => 5321}, 1547: ?cfgh([s2s, address], #{<<"host1">> => #{ip_address => "192.168.1.2", port => 5321}}, 1548: #{<<"s2s">> => #{<<"address">> => [Addr]}}), 1549: ?cfgh([s2s, address], #{<<"host1">> => #{ip_address => "192.168.1.2"}}, 1550: #{<<"s2s">> => #{<<"address">> => [maps:without([<<"port">>], Addr)]}}), 1551: ?errh(#{<<"s2s">> => #{<<"address">> => [maps:without([<<"host">>], Addr)]}}), 1552: ?errh(#{<<"s2s">> => #{<<"address">> => [maps:without([<<"ip_address">>], Addr)]}}), 1553: ?errh(#{<<"s2s">> => #{<<"address">> => [Addr#{<<"host">> => <<>>}]}}), 1554: ?errh(#{<<"s2s">> => #{<<"address">> => [Addr#{<<"ip_address">> => <<"host2">>}]}}), 1555: ?errh(#{<<"s2s">> => #{<<"address">> => [Addr#{<<"port">> => <<"seaport">>}]}}), 1556: ?errh(#{<<"s2s">> => #{<<"address">> => [Addr, maps:remove(<<"port">>, Addr)]}}). 1557: 1558: s2s_ciphers(_Config) -> 1559: ?cfgh([s2s, ciphers], ejabberd_tls:default_ciphers(), #{}), % default 1560: ?cfgh([s2s, ciphers], "TLSv1.2", 1561: #{<<"s2s">> => #{<<"ciphers">> => <<"TLSv1.2">>}}), 1562: ?errh(#{<<"s2s">> => #{<<"ciphers">> => [<<"cipher1">>, <<"cipher2">>]}}). 1563: 1564: s2s_shared(_Config) -> 1565: ?cfgh([s2s, shared], <<"secret">>, #{<<"s2s">> => #{<<"shared">> => <<"secret">>}}), 1566: ?errh(#{<<"s2s">> => #{<<"shared">> => 536837}}). 1567: 1568: s2s_max_retry_delay(_Config) -> 1569: ?cfgh([s2s, max_retry_delay], 120, #{<<"s2s">> => #{<<"max_retry_delay">> => 120}}), 1570: ?errh(#{<<"s2s">> => #{<<"max_retry_delay">> => 0}}). 1571: 1572: %% modules 1573: 1574: mod_adhoc(_Config) -> 1575: check_module_defaults(mod_adhoc), 1576: check_iqdisc_map(mod_adhoc), 1577: P = [modules, mod_adhoc], 1578: T = fun(K, V) -> #{<<"modules">> => #{<<"mod_adhoc">> => #{K => V}}} end, 1579: %% report_commands_node is boolean 1580: ?cfgh(P ++ [report_commands_node], true, T(<<"report_commands_node">>, true)), 1581: ?cfgh(P ++ [report_commands_node], false, T(<<"report_commands_node">>, false)), 1582: %% not boolean 1583: ?errh(T(<<"report_commands_node">>, <<"hello">>)). 1584: 1585: mod_auth_token(_Config) -> 1586: check_module_defaults(mod_auth_token), 1587: check_iqdisc_map(mod_auth_token), 1588: P = [modules, mod_auth_token], 1589: T = fun(K, V) -> #{<<"modules">> => #{<<"mod_auth_token">> => #{K => V}}} end, 1590: ?cfgh(P ++ [backend], rdbms, T(<<"backend">>, <<"rdbms">>)), 1591: ?cfgh(P ++ [validity_period, access], #{unit => minutes, value => 13}, 1592: T(<<"validity_period">>, 1593: #{<<"access">> => #{<<"value">> => 13, <<"unit">> => <<"minutes">>}})), 1594: ?cfgh(P ++ [validity_period, refresh], #{unit => days, value => 31}, 1595: T(<<"validity_period">>, 1596: #{<<"refresh">> => #{<<"value">> => 31, <<"unit">> => <<"days">>}})), 1597: ?errh(T(<<"backend">>, <<"nosql">>)), 1598: ?errh(T(<<"validity_period">>, 1599: #{<<"access">> => #{<<"value">> => -1, <<"unit">> => <<"minutes">>}})), 1600: ?errh(T(<<"validity_period">>, 1601: #{<<"access">> => #{<<"value">> => 10, <<"unit">> => <<"centuries">>}})), 1602: ?errh(T(<<"validity_period">>, #{<<"access">> => #{<<"value">> => 10}})), 1603: ?errh(T(<<"validity_period">>, #{<<"access">> => #{<<"unit">> => <<"days">>}})). 1604: 1605: mod_bosh(_Config) -> 1606: check_module_defaults(mod_bosh), 1607: P = [modules, mod_bosh], 1608: T = fun(K, V) -> #{<<"modules">> => #{<<"mod_bosh">> => #{K => V}}} end, 1609: ?cfgh(P ++ [backend], mnesia, T(<<"backend">>, <<"mnesia">>)), 1610: ?cfgh(P ++ [inactivity], 10, T(<<"inactivity">>, 10)), 1611: ?cfgh(P ++ [inactivity], infinity, T(<<"inactivity">>, <<"infinity">>)), 1612: ?cfgh(P ++ [max_wait], 10, T(<<"max_wait">>, 10)), 1613: ?cfgh(P ++ [max_wait], infinity, T(<<"max_wait">>, <<"infinity">>)), 1614: ?cfgh(P ++ [server_acks], true, T(<<"server_acks">>, true)), 1615: ?cfgh(P ++ [server_acks], false, T(<<"server_acks">>, false)), 1616: ?cfgh(P ++ [max_pause], 10, T(<<"max_pause">>, 10)), 1617: ?errh(T(<<"backend">>, <<"nodejs">>)), 1618: ?errh(T(<<"inactivity">>, 0)), 1619: ?errh(T(<<"inactivity">>, <<"10">>)), 1620: ?errh(T(<<"inactivity">>, <<"inactivity">>)), 1621: ?errh(T(<<"max_wait">>, <<"10">>)), 1622: ?errh(T(<<"max_wait">>, 0)), 1623: ?errh(T(<<"server_acks">>, -1)), 1624: ?errh(T(<<"maxpause">>, 0)). 1625: 1626: mod_caps(_Config) -> 1627: T = fun(K, V) -> #{<<"modules">> => #{<<"mod_caps">> => #{K => V}}} end, 1628: M = fun(K, V) -> modopts(mod_caps, [{K, V}]) end, 1629: ?cfgh(M(cache_size, 10), T(<<"cache_size">>, 10)), 1630: ?cfgh(M(cache_life_time, 10), T(<<"cache_life_time">>, 10)), 1631: ?errh(T(<<"cache_size">>, 0)), 1632: ?errh(T(<<"cache_size">>, <<"infinity">>)), 1633: ?errh(T(<<"cache_life_time">>, 0)), 1634: ?errh(T(<<"cache_life_time">>, <<"infinity">>)). 1635: 1636: mod_cache_users(_Config) -> 1637: T = fun(K, V) -> #{<<"modules">> => #{<<"mod_cache_users">> => #{K => V}}} end, 1638: M = fun(K, V) -> modopts(mod_cache_users, [{K, V}]) end, 1639: ?cfgh(M(time_to_live, 8600), T(<<"time_to_live">>, 8600)), 1640: ?cfgh(M(time_to_live, infinity), T(<<"time_to_live">>, <<"infinity">>)), 1641: ?cfgh(M(number_of_segments, 10), T(<<"number_of_segments">>, 10)), 1642: ?cfgh(M(strategy, fifo), T(<<"strategy">>, <<"fifo">>)), 1643: ?errh(T(<<"time_to_live">>, 0)), 1644: ?errh(T(<<"strategy">>, <<"lifo">>)), 1645: ?errh(T(<<"number_of_segments">>, 0)), 1646: ?errh(T(<<"number_of_segments">>, <<"infinity">>)). 1647: 1648: mod_carboncopy(_Config) -> 1649: check_iqdisc(mod_carboncopy). 1650: 1651: mod_csi(_Config) -> 1652: T = fun(K, V) -> #{<<"modules">> => #{<<"mod_csi">> => #{K => V}}} end, 1653: M = fun(K, V) -> modopts(mod_csi, [{K, V}]) end, 1654: ?cfgh(M(buffer_max, 10), T(<<"buffer_max">>, 10)), 1655: ?cfgh(M(buffer_max, infinity), T(<<"buffer_max">>, <<"infinity">>)), 1656: ?errh(T(<<"buffer_max">>, -1)). 1657: 1658: mod_disco(_Config) -> 1659: check_module_defaults(mod_disco), 1660: check_iqdisc_map(mod_disco), 1661: P = [modules, mod_disco], 1662: T = fun(K, V) -> #{<<"modules">> => #{<<"mod_disco">> => #{K => V}}} end, 1663: ?cfgh(P ++ [users_can_see_hidden_services], true, 1664: T(<<"users_can_see_hidden_services">>, true)), 1665: ?cfgh(P ++ [users_can_see_hidden_services], false, 1666: T(<<"users_can_see_hidden_services">>, false)), 1667: %% extra_domains are binaries 1668: ?cfgh(P ++ [extra_domains], [<<"localhost">>, <<"erlang-solutions.com">>], 1669: T(<<"extra_domains">>, [<<"localhost">>, <<"erlang-solutions.com">>])), 1670: ?cfgh(P ++ [extra_domains], [], 1671: T(<<"extra_domains">>, [])), 1672: Info = #{<<"name">> => <<"abuse-address">>, 1673: <<"urls">> => [<<"admin@example.com">>]}, 1674: SpiritUrls = [<<"spirit1@localhost">>, <<"spirit2@localhost">>], 1675: ?cfgh(P ++ [server_info], 1676: [#{name => <<"abuse-address">>, urls => [<<"admin@example.com">>]}, 1677: #{name => <<"friendly-spirits">>, urls => SpiritUrls, modules => [mod_muc, mod_disco]}], 1678: T(<<"server_info">>, [Info, #{<<"name">> => <<"friendly-spirits">>, 1679: <<"urls">> => SpiritUrls, 1680: <<"modules">> => [<<"mod_muc">>, <<"mod_disco">>]}])), 1681: ?errh(T(<<"users_can_see_hidden_services">>, 1)), 1682: ?errh(T(<<"users_can_see_hidden_services">>, <<"true">>)), 1683: ?errh(T(<<"extra_domains">>, [<<"user@localhost">>])), 1684: ?errh(T(<<"extra_domains">>, [1])), 1685: ?errh(T(<<"extra_domains">>, <<"domains domains domains">>)), 1686: ?errh(T(<<"server_info">>, [Info#{<<"name">> => 1}])), 1687: ?errh(T(<<"server_info">>, [Info#{<<"name">> => <<"">>}])), 1688: ?errh(T(<<"server_info">>, [Info#{<<"modules">> => <<"roll">>}])), 1689: ?errh(T(<<"server_info">>, [Info#{<<"modules">> => [<<"meow_meow_meow">>]}])), 1690: ?errh(T(<<"server_info">>, [Info#{<<"urls">> => [1]}])), 1691: ?errh(T(<<"server_info">>, [Info#{<<"urls">> => [<<"">>]}])), 1692: ?errh(T(<<"server_info">>, [maps:remove(<<"name">>, Info)])), 1693: ?errh(T(<<"server_info">>, [maps:remove(<<"urls">>, Info)])). 1694: 1695: mod_extdisco(_Config) -> 1696: check_module_defaults(mod_extdisco), 1697: check_iqdisc_map(mod_extdisco), 1698: P = [modules, mod_extdisco, service], 1699: T = fun(Opts) -> #{<<"modules">> => 1700: #{<<"mod_extdisco">> => 1701: #{<<"service">> => [Opts]}}} 1702: end, 1703: RequiredOpts = #{<<"type">> => <<"stun">>, <<"host">> => <<"stun1">>}, 1704: Service = #{type => stun, host => <<"stun1">>}, 1705: ?cfgh(P, [Service], T(RequiredOpts)), 1706: ?cfgh(P, [Service#{port => 3478}], T(RequiredOpts#{<<"port">> => 3478})), 1707: ?cfgh(P, [Service#{transport => <<"udp">>}], T(RequiredOpts#{<<"transport">> => <<"udp">>})), 1708: ?cfgh(P, [Service#{username => <<"user">>}], T(RequiredOpts#{<<"username">> => <<"user">>})), 1709: ?cfgh(P, [Service#{password => <<"pass">>}], T(RequiredOpts#{<<"password">> => <<"pass">>})), 1710: [?errh(T(maps:remove(Key, RequiredOpts))) || Key <- maps:keys(RequiredOpts)], 1711: [?errh(T(RequiredOpts#{Key => 1})) || Key <- maps:keys(RequiredOpts)], 1712: ?errh(T(RequiredOpts#{<<"type">> => <<>>})), 1713: ?errh(T(RequiredOpts#{<<"host">> => <<>>})), 1714: ?errh(T(RequiredOpts#{<<"port">> => -1})), 1715: ?errh(T(RequiredOpts#{<<"transport">> => <<>>})), 1716: ?errh(T(RequiredOpts#{<<"username">> => <<>>})), 1717: ?errh(T(RequiredOpts#{<<"password">> => <<>>})). 1718: 1719: mod_inbox(_Config) -> 1720: check_module_defaults(mod_inbox), 1721: check_iqdisc_map(mod_inbox), 1722: P = [modules, mod_inbox], 1723: T = fun(Opts) -> #{<<"modules">> => #{<<"mod_inbox">> => Opts}} end, 1724: ChatMarkers = [<<"displayed">>, <<"received">>, <<"acknowledged">>], 1725: ?cfgh(P ++ [backend], rdbms, T(#{<<"backend">> => <<"rdbms">>})), 1726: ?cfgh(P ++ [async_writer], #{pool_size => 8}, T(#{<<"async_writer">> => #{<<"pool_size">> => 8}})), 1727: ?cfgh(P ++ [reset_markers], ChatMarkers, T(#{<<"reset_markers">> => ChatMarkers})), 1728: ?cfgh(P ++ [groupchat], [muc, muclight], T(#{<<"groupchat">> => [<<"muc">>, <<"muclight">>]})), 1729: ?cfgh(P ++ [aff_changes], true, T(#{<<"aff_changes">> => true})), 1730: ?cfgh(P ++ [remove_on_kicked], false, T(#{<<"remove_on_kicked">> => false})), 1731: ?errh(T(#{<<"backend">> => <<"nodejs">>})), 1732: ?errh(T(#{<<"reset_markers">> => 1})), 1733: ?errh(T(#{<<"reset_markers">> => [<<"destroyed">>]})), 1734: ?errh(T(#{<<"groupchat">> => [<<"test">>]})), 1735: ?errh(T(#{<<"aff_changes">> => 1})), 1736: ?errh(T(#{<<"remove_on_kicked">> => 1})). 1737: 1738: mod_global_distrib(_Config) -> 1739: T = fun(Opts) -> #{<<"modules">> => #{<<"mod_global_distrib">> => Opts}} end, 1740: M = fun(Cfg) -> modopts(mod_global_distrib, Cfg) end, 1741: RequiredOpts = global_distrib_required_opts(), 1742: ExpectedCfg = global_distrib_expected_config(), 1743: ?cfgh(M(ExpectedCfg), T(RequiredOpts)), 1744: ?cfgh(M(ExpectedCfg ++ [{message_ttl, 42}]), 1745: T(RequiredOpts#{<<"message_ttl">> => 42})), 1746: ?cfgh(M(ExpectedCfg ++ [{hosts_refresh_interval, 100}]), 1747: T(RequiredOpts#{<<"hosts_refresh_interval">> => 100})), 1748: [?errh(T(maps:remove(Key, RequiredOpts))) || Key <- maps:keys(RequiredOpts)], 1749: ?errh(T(RequiredOpts#{<<"global_host">> => <<"">>})), 1750: ?errh(T(RequiredOpts#{<<"local_host">> => <<"">>})), 1751: ?errh(T(RequiredOpts#{<<"message_ttl">> => -1})), 1752: ?errh(T(RequiredOpts#{<<"hosts_refresh_interval">> => -1})). 1753: 1754: mod_global_distrib_connections(_Config) -> 1755: RequiredOpts = global_distrib_required_opts(), 1756: T = fun(Opts) -> #{<<"modules">> => 1757: #{<<"mod_global_distrib">> => 1758: RequiredOpts#{<<"connections">> => Opts}}} 1759: end, 1760: M = fun(Cfg) -> modopts(mod_global_distrib, 1761: global_distrib_expected_config() ++ [{connections, Cfg}]) 1762: end, 1763: ?cfgh(M([]), T(#{})), 1764: ?cfgh(M([{connections_per_endpoint, 22}]), 1765: T(#{<<"connections_per_endpoint">> => 22})), 1766: ?cfgh(M([{endpoint_refresh_interval, 120}]), 1767: T(#{<<"endpoint_refresh_interval">> => 120})), 1768: ?cfgh(M([{endpoint_refresh_interval_when_empty, 5}]), 1769: T(#{<<"endpoint_refresh_interval_when_empty">> => 5})), 1770: ?cfgh(M([{disabled_gc_interval, 60}]), 1771: T(#{<<"disabled_gc_interval">> => 60})), 1772: ?errh(T(#{<<"connections_per_endpoint">> => -1})), 1773: ?errh(T(#{<<"endpoint_refresh_interval">> => 0})), 1774: ?errh(T(#{<<"endpoint_refresh_interval_when_empty">> => 0})), 1775: ?errh(T(#{<<"disabled_gc_interval">> => 0})). 1776: 1777: mod_global_distrib_connections_endpoints(_Config) -> 1778: check_mod_global_distrib_endpoints(<<"endpoints">>). 1779: 1780: mod_global_distrib_connections_advertised_endpoints(_Config) -> 1781: check_mod_global_distrib_endpoints(<<"advertised_endpoints">>). 1782: 1783: check_mod_global_distrib_endpoints(OptKey) -> 1784: CfgKey = binary_to_atom(OptKey, utf8), 1785: RequiredModOpts = global_distrib_required_opts(), 1786: T = fun(Opts) -> #{<<"modules">> => 1787: #{<<"mod_global_distrib">> => 1788: RequiredModOpts#{<<"connections">> => #{OptKey => Opts}}}} 1789: end, 1790: M = fun(Cfg) -> modopts(mod_global_distrib, 1791: global_distrib_expected_config() ++ 1792: [{connections, [{CfgKey, Cfg}]}]) 1793: end, 1794: RequiredOpts = #{<<"host">> => <<"172.16.0.2">>, 1795: <<"port">> => 5555}, 1796: ?cfgh(M([{"172.16.0.2", 5555}]), T([RequiredOpts])), 1797: [?errh(T(maps:remove(Key, RequiredOpts))) || Key <- maps:keys(RequiredOpts)], 1798: ?errh(T([RequiredOpts#{<<"host">> => <<>>}])), 1799: ?errh(T([RequiredOpts#{<<"port">> => -1}])). 1800: 1801: mod_global_distrib_connections_tls(_Config) -> 1802: RequiredModOpts = global_distrib_required_opts(), 1803: T = fun(Opts) -> #{<<"modules">> => 1804: #{<<"mod_global_distrib">> => 1805: RequiredModOpts#{<<"connections">> => #{<<"tls">> => Opts}}}} 1806: end, 1807: M = fun(Cfg) -> modopts(mod_global_distrib, 1808: global_distrib_expected_config() ++ 1809: [{connections, [{tls_opts, Cfg}]}]) 1810: end, 1811: RequiredOpts = #{<<"certfile">> => <<"priv/cert.pem">>, 1812: <<"cacertfile">> => <<"priv/ca.pem">>}, 1813: ExpectedCfg = [{certfile, "priv/cert.pem"}, 1814: {cafile, "priv/ca.pem"}], 1815: ?cfgh(M(ExpectedCfg), T(RequiredOpts)), 1816: ?cfgh(M(ExpectedCfg ++ [{ciphers, "TLS_AES_256_GCM_SHA384"}]), 1817: T(RequiredOpts#{<<"ciphers">> => <<"TLS_AES_256_GCM_SHA384">>})), 1818: ?cfgh(M(ExpectedCfg ++ [{dhfile, "priv/cert.pem"}]), 1819: T(RequiredOpts#{<<"dhfile">> => <<"priv/cert.pem">>})), 1820: [?errh(T(maps:remove(Key, RequiredOpts))) || Key <- maps:keys(RequiredOpts)], 1821: ?errh(T(RequiredOpts#{<<"certfile">> => <<"/this/does/not/exist">>})), 1822: ?errh(T(RequiredOpts#{<<"cacertfile">> => <<"/this/does/not/exist">>})), 1823: ?errh(T(RequiredOpts#{<<"dhfile">> => <<"/this/does/not/exist">>})), 1824: ?errh(T(RequiredOpts#{<<"ciphers">> => 42})). 1825: 1826: mod_global_distrib_redis(_Config) -> 1827: RequiredModOpts = global_distrib_required_opts(), 1828: T = fun(Opts) -> #{<<"modules">> => 1829: #{<<"mod_global_distrib">> => 1830: RequiredModOpts#{<<"redis">> => Opts}}} 1831: end, 1832: M = fun(Cfg) -> modopts(mod_global_distrib, 1833: global_distrib_expected_config() ++ [{redis, Cfg}]) 1834: end, 1835: ?cfgh(M([]), T(#{})), 1836: ?cfgh(M([{pool, global_distrib}]), 1837: T(#{<<"pool">> => <<"global_distrib">>})), 1838: ?cfgh(M([{expire_after, 120}]), 1839: T(#{<<"expire_after">> => 120})), 1840: ?cfgh(M([{refresh_after, 60}]), 1841: T(#{<<"refresh_after">> => 60})), 1842: ?errh(T(#{<<"pool">> => <<"">>})), 1843: ?errh(T(#{<<"expire_after">> => 0})), 1844: ?errh(T(#{<<"refresh_after">> => -1})). 1845: 1846: mod_global_distrib_cache(_Config) -> 1847: RequiredModOpts = global_distrib_required_opts(), 1848: T = fun(Opts) -> #{<<"modules">> => 1849: #{<<"mod_global_distrib">> => 1850: RequiredModOpts#{<<"cache">> => Opts}}} 1851: end, 1852: M = fun(Cfg) -> modopts(mod_global_distrib, 1853: global_distrib_expected_config() ++ [{cache, Cfg}]) 1854: end, 1855: ?cfgh(M([]), T(#{})), 1856: ?cfgh(M([{cache_missed, false}]), 1857: T(#{<<"cache_missed">> => false})), 1858: ?cfgh(M([{domain_lifetime_seconds, 60}]), 1859: T(#{<<"domain_lifetime_seconds">> => 60})), 1860: ?cfgh(M([{jid_lifetime_seconds, 30}]), 1861: T(#{<<"jid_lifetime_seconds">> => 30})), 1862: ?cfgh(M([{max_jids, 9999}]), 1863: T(#{<<"max_jids">> => 9999})), 1864: ?errh(T(#{<<"cache_missed">> => <<"yes">>})), 1865: ?errh(T(#{<<"domain_lifetime_seconds">> => -1})), 1866: ?errh(T(#{<<"jid_lifetime_seconds">> => -1})), 1867: ?errh(T(#{<<"max_jids">> => -1})). 1868: 1869: mod_global_distrib_bounce(_Config) -> 1870: RequiredModOpts = global_distrib_required_opts(), 1871: T = fun(Opts) -> #{<<"modules">> => 1872: #{<<"mod_global_distrib">> => 1873: RequiredModOpts#{<<"bounce">> => Opts}}} 1874: end, 1875: M = fun(Cfg) -> modopts(mod_global_distrib, 1876: global_distrib_expected_config() ++ [{bounce, Cfg}]) 1877: end, 1878: ?cfgh(M(false), 1879: T(#{<<"enabled">> => false})), 1880: ?cfgh(M([]), 1881: T(#{<<"enabled">> => true})), 1882: ?cfgh(M([{resend_after_ms, 300}]), 1883: T(#{<<"resend_after_ms">> => 300})), 1884: ?cfgh(M([{max_retries, 3}]), 1885: T(#{<<"max_retries">> => 3})), 1886: ?errh(T(#{<<"enabled">> => <<"">>})), 1887: ?errh(T(#{<<"resend_after_ms">> => -1})), 1888: ?errh(T(#{<<"max_retries">> => -1})). 1889: 1890: global_distrib_required_opts() -> 1891: #{<<"global_host">> => <<"example.com">>, 1892: <<"local_host">> => <<"datacenter1.example.com">>}. 1893: 1894: global_distrib_expected_config() -> 1895: [{global_host, "example.com"}, 1896: {local_host, "datacenter1.example.com"}]. 1897: 1898: mod_event_pusher_sns(_Config) -> 1899: RequiredOpts = #{<<"access_key_id">> => <<"AKIAIOSFODNN7EXAMPLE">>, 1900: <<"secret_access_key">> => <<"KEY">>, 1901: <<"region">> => <<"eu-west-1">>, 1902: <<"account_id">> => <<"123456789012">>, 1903: <<"sns_host">> => <<"sns.eu-west-1.amazonaws.com">>}, 1904: ExpectedCfg = [{access_key_id, "AKIAIOSFODNN7EXAMPLE"}, 1905: {secret_access_key, "KEY"}, 1906: {region, "eu-west-1"}, 1907: {account_id, "123456789012"}, 1908: {sns_host, "sns.eu-west-1.amazonaws.com"}], 1909: T = fun(Opts) -> #{<<"modules">> => 1910: #{<<"mod_event_pusher">> => 1911: #{<<"backend">> => #{<<"sns">> => Opts}}}} 1912: end, 1913: M = fun(Cfg) -> modopts(mod_event_pusher, [{backends, [{sns, Cfg}]}]) end, 1914: ?cfgh(M(ExpectedCfg), 1915: T(RequiredOpts)), 1916: ?cfgh(M(ExpectedCfg ++ [{presence_updates_topic, "pres"}]), 1917: T(RequiredOpts#{<<"presence_updates_topic">> => <<"pres">>})), 1918: ?cfgh(M(ExpectedCfg ++ [{pm_messages_topic, "pm"}]), 1919: T(RequiredOpts#{<<"pm_messages_topic">> => <<"pm">>})), 1920: ?cfgh(M(ExpectedCfg ++ [{muc_messages_topic, "muc"}]), 1921: T(RequiredOpts#{<<"muc_messages_topic">> => <<"muc">>})), 1922: ?cfgh(M(ExpectedCfg ++ [{plugin_module, mod_event_pusher_sns_defaults}]), 1923: T(RequiredOpts#{<<"plugin_module">> => <<"mod_event_pusher_sns_defaults">>})), 1924: ?cfgh(M(ExpectedCfg ++ [{pool_size, 10}]), 1925: T(RequiredOpts#{<<"pool_size">> => 10})), 1926: ?cfgh(M(ExpectedCfg ++ [{publish_retry_count, 1}]), 1927: T(RequiredOpts#{<<"publish_retry_count">> => 1})), 1928: ?cfgh(M(ExpectedCfg ++ [{publish_retry_time_ms, 100}]), 1929: T(RequiredOpts#{<<"publish_retry_time_ms">> => 100})), 1930: [?errh(T(maps:remove(Key, RequiredOpts))) || Key <- maps:keys(RequiredOpts)], 1931: [?errh(T(RequiredOpts#{Key => 1})) || Key <- maps:keys(RequiredOpts)], 1932: ?errh(T(RequiredOpts#{<<"presence_updates_topic">> => #{}})), 1933: ?errh(T(RequiredOpts#{<<"pm_messages_topic">> => true})), 1934: ?errh(T(RequiredOpts#{<<"muc_messages_topic">> => [1, 2]})), 1935: ?errh(T(RequiredOpts#{<<"plugin_module">> => <<"plug_and_play">>})), 1936: ?errh(T(RequiredOpts#{<<"pool_size">> => 0})), 1937: ?errh(T(RequiredOpts#{<<"publish_retry_count">> => -1})), 1938: ?errh(T(RequiredOpts#{<<"publish_retry_time_ms">> => -1})). 1939: 1940: mod_event_pusher_push(_Config) -> 1941: T = fun(Opts) -> #{<<"modules">> => 1942: #{<<"mod_event_pusher">> => 1943: #{<<"backend">> => #{<<"push">> => Opts}}}} 1944: end, 1945: M = fun(Cfg) -> modopts(mod_event_pusher, [{backends, [{push, Cfg}]}]) end, 1946: ?cfgh(M([{backend, rdbms}]), 1947: T(#{<<"backend">> => <<"rdbms">>})), 1948: ?cfgh(M([{wpool, [{workers, 200}]}]), 1949: T(#{<<"wpool">> => #{<<"workers">> => 200}})), 1950: ?cfgh(M([{plugin_module, mod_event_pusher_push_plugin_defaults}]), 1951: T(#{<<"plugin_module">> => <<"mod_event_pusher_push_plugin_defaults">>})), 1952: ?cfgh(M([{virtual_pubsub_hosts, [{fqdn, <<"host1">>}, {fqdn, <<"host2">>}]}]), 1953: T(#{<<"virtual_pubsub_hosts">> => [<<"host1">>, <<"host2">>]})), 1954: ?cfgh(M([{virtual_pubsub_hosts, [{prefix, <<"pubsub.">>}, {prefix, <<"pub-sub.">>}]}]), 1955: T(#{<<"virtual_pubsub_hosts">> => [<<"pubsub.@HOST@">>, <<"pub-sub.@HOST@">>]})), 1956: ?errh(T(#{<<"backend">> => <<"redis">>})), 1957: ?errh(T(#{<<"wpool">> => true})), 1958: ?errh(T(#{<<"wpool">> => #{<<"workers">> => <<"500">>}})), 1959: ?errh(T(#{<<"plugin_module">> => <<"wow_cool_but_missing">>})), 1960: ?errh(T(#{<<"plugin_module">> => 1})), 1961: ?errh(T(#{<<"virtual_pubsub_hosts">> => [<<"host with whitespace">>]})), 1962: ?errh(T(#{<<"virtual_pubsub_hosts">> => [<<"invalid.sub@HOST@">>]})), 1963: ?errh(T(#{<<"virtual_pubsub_hosts">> => [<<"invalid.sub.@HOST@.as.well">>]})). 1964: 1965: mod_event_pusher_http(_Config) -> 1966: T = fun(Opts) -> #{<<"modules">> => 1967: #{<<"mod_event_pusher">> => 1968: #{<<"backend">> => #{<<"http">> => Opts}}}} 1969: end, 1970: M = fun(Cfg) -> modopts(mod_event_pusher, [{backends, [{http, Cfg}]}]) end, 1971: ?cfgh(M([{pool_name, http_pool}]), 1972: T(#{<<"pool_name">> => <<"http_pool">>})), 1973: ?cfgh(M([{path, "/notifications"}]), 1974: T(#{<<"path">> => <<"/notifications">>})), 1975: ?cfgh(M([{callback_module, mod_event_pusher_http_defaults}]), 1976: T(#{<<"callback_module">> => <<"mod_event_pusher_http_defaults">>})), 1977: ?errh(T(#{<<"pool_name">> => <<>>})), 1978: ?errh(T(#{<<"path">> => true})), 1979: ?errh(T(#{<<"callback_module">> => <<"wow_cool_but_missing">>})), 1980: ?errh(T(#{<<"callback_module">> => 1})). 1981: 1982: mod_event_pusher_rabbit(_Config) -> 1983: T = fun(Opts) -> #{<<"modules">> => 1984: #{<<"mod_event_pusher">> => 1985: #{<<"backend">> => #{<<"rabbit">> => Opts}}}} 1986: end, 1987: M = fun(Cfg) -> modopts(mod_event_pusher, [{backends, [{rabbit, Cfg}]}]) end, 1988: ?cfgh(M([{presence_exchange, [{name, <<"pres">>}]}]), 1989: T(#{<<"presence_exchange">> => #{<<"name">> => <<"pres">>}})), 1990: ?cfgh(M([{presence_exchange, [{type, <<"topic">>}]}]), 1991: T(#{<<"presence_exchange">> => #{<<"type">> => <<"topic">>}})), 1992: 1993: %% first two keys are the same as before, test them together 1994: ?cfgh(M([{chat_msg_exchange, [{name, <<"pres1">>}, 1995: {type, <<"topic1">>}]}]), 1996: T(#{<<"chat_msg_exchange">> => #{<<"name">> => <<"pres1">>, 1997: <<"type">> => <<"topic1">>}})), 1998: ?cfgh(M([{chat_msg_exchange, [{sent_topic, <<"sent_topic1">>}]}]), 1999: T(#{<<"chat_msg_exchange">> => #{<<"sent_topic">> => <<"sent_topic1">>}})), 2000: ?cfgh(M([{chat_msg_exchange, [{recv_topic, <<"recv_topic1">>}]}]), 2001: T(#{<<"chat_msg_exchange">> => #{<<"recv_topic">> => <<"recv_topic1">>}})), 2002: 2003: %% all keys are the same as before, test them together 2004: ?cfgh(M([{groupchat_msg_exchange, [{name, <<"pres2">>}, 2005: {type, <<"topic2">>}, 2006: {sent_topic, <<"sent_topic2">>}, 2007: {recv_topic, <<"recv_topic2">>}]}]), 2008: T(#{<<"groupchat_msg_exchange">> => #{<<"name">> => <<"pres2">>, 2009: <<"type">> => <<"topic2">>, 2010: <<"sent_topic">> => <<"sent_topic2">>, 2011: <<"recv_topic">> => <<"recv_topic2">>}})), 2012: 2013: Exchanges = [<<"presence_exchange">>, <<"chat_msg_exchange">>, <<"groupchat_msg_exchange">>], 2014: Keys = [<<"name">>, <<"topic">>, <<"sent_topic">>, <<"recv_topic">>], 2015: [?errh(T(#{Exch => #{Key => <<>>}})) || Exch <- Exchanges, Key <- Keys], 2016: [?errh(T(#{Exch => #{<<"badkey">> => <<"goodvalue">>}})) || Exch <- Exchanges], 2017: ?errh(T(#{<<"money_exchange">> => #{<<"name">> => <<"kantor">>}})). 2018: 2019: mod_http_upload(_Config) -> 2020: T = fun(Opts) -> #{<<"modules">> => #{<<"mod_http_upload">> => Opts}} end, 2021: M = fun(Cfg) -> modopts(mod_http_upload, Cfg) end, 2022: RequiredOpts = #{<<"s3">> => http_upload_s3_required_opts()}, 2023: ExpectedCfg = [{s3, http_upload_s3_expected_cfg()}], 2024: ?cfgh(M(ExpectedCfg), T(RequiredOpts)), 2025: ?cfgh(M(ExpectedCfg ++ [{host, {prefix, <<"upload.">>}}]), 2026: T(RequiredOpts#{<<"host">> => <<"upload.@HOST@">>})), 2027: ?cfgh(M(ExpectedCfg ++ [{host, {fqdn, <<"upload.test">>}}]), 2028: T(RequiredOpts#{<<"host">> => <<"upload.test">>})), 2029: ?cfgh(M(ExpectedCfg ++ [{backend, s3}]), 2030: T(RequiredOpts#{<<"backend">> => <<"s3">>})), 2031: ?cfgh(M(ExpectedCfg ++ [{expiration_time, 666}]), 2032: T(RequiredOpts#{<<"expiration_time">> => 666})), 2033: ?cfgh(M(ExpectedCfg ++ [{token_bytes, 32}]), 2034: T(RequiredOpts#{<<"token_bytes">> => 32})), 2035: ?cfgh(M(ExpectedCfg ++ [{max_file_size, 42}]), 2036: T(RequiredOpts#{<<"max_file_size">> => 42})), 2037: ?errh(T(#{})), %% missing 's3' 2038: ?errh(T(RequiredOpts#{<<"backend">> => <<"">>})), 2039: ?errh(T(RequiredOpts#{<<"expiration_time">> => 0})), 2040: ?errh(T(RequiredOpts#{<<"token_bytes">> => 0})), 2041: ?errh(T(RequiredOpts#{<<"max_file_size">> => 0})), 2042: ?errh(T(RequiredOpts#{<<"host">> => <<"is this a host? no.">>})), 2043: ?errh(T(RequiredOpts#{<<"host">> => [<<"invalid.sub@HOST@">>]})), 2044: ?errh(T(RequiredOpts#{<<"host">> => [<<"invalid.sub.@HOST@.as.well">>]})), 2045: ?errh(T(RequiredOpts#{<<"host">> => [<<"not.supported.any.more.@HOSTS@">>]})), 2046: check_iqdisc(mod_http_upload, ExpectedCfg, RequiredOpts). 2047: 2048: mod_http_upload_s3(_Config) -> 2049: T = fun(Opts) -> #{<<"modules">> => #{<<"mod_http_upload">> => 2050: #{<<"s3">> => Opts}}} end, 2051: M = fun(Cfg) -> modopts(mod_http_upload, [{s3, Cfg}]) end, 2052: RequiredOpts = http_upload_s3_required_opts(), 2053: ExpectedCfg = http_upload_s3_expected_cfg(), 2054: ?cfgh(M(ExpectedCfg), T(RequiredOpts)), 2055: ?cfgh(M(ExpectedCfg ++ [{add_acl, true}]), 2056: T(RequiredOpts#{<<"add_acl">> => true})), 2057: [?errh(T(maps:remove(Key, RequiredOpts))) || Key <- maps:keys(RequiredOpts)], 2058: ?errh(T(RequiredOpts#{<<"bucket_url">> => <<>>})), 2059: ?errh(T(RequiredOpts#{<<"region">> => true})), 2060: ?errh(T(RequiredOpts#{<<"access_key_id">> => []})), 2061: ?errh(T(RequiredOpts#{<<"secret_access_key">> => 3})), 2062: ?errh(T(RequiredOpts#{<<"add_acl">> => <<"true">>})). 2063: 2064: http_upload_s3_required_opts() -> 2065: #{<<"bucket_url">> => <<"https://s3-eu-west-1.amazonaws.com/mybucket">>, 2066: <<"region">> => <<"antarctica-1">>, 2067: <<"access_key_id">> => <<"PLEASE">>, 2068: <<"secret_access_key">> => <<"ILOVEU">>}. 2069: 2070: http_upload_s3_expected_cfg() -> 2071: [{access_key_id, "PLEASE"}, 2072: {bucket_url, "https://s3-eu-west-1.amazonaws.com/mybucket"}, 2073: {region, "antarctica-1"}, 2074: {secret_access_key, "ILOVEU"}]. 2075: 2076: mod_jingle_sip(_Config) -> 2077: T = fun(Opts) -> #{<<"modules">> => #{<<"mod_jingle_sip">> => Opts}} end, 2078: M = fun(Cfg) -> modopts(mod_jingle_sip, Cfg) end, 2079: ?cfgh(M([{proxy_host, "proxxxy"}]), 2080: T(#{<<"proxy_host">> => <<"proxxxy">>})), 2081: ?cfgh(M([{proxy_port, 5601}]), 2082: T(#{<<"proxy_port">> => 5601})), 2083: ?cfgh(M([{listen_port, 5602}]), 2084: T(#{<<"listen_port">> => 5602})), 2085: ?cfgh(M([{local_host, "localhost"}]), 2086: T(#{<<"local_host">> => <<"localhost">>})), 2087: ?cfgh(M([{sdp_origin, "127.0.0.1"}]), 2088: T(#{<<"sdp_origin">> => <<"127.0.0.1">>})), 2089: ?errh(T(#{<<"proxy_host">> => 1})), 2090: ?errh(T(#{<<"proxy_port">> => 1000000})), 2091: ?errh(T(#{<<"listen_port">> => -1})), 2092: ?errh(T(#{<<"local_host">> => <<>>})), 2093: ?errh(T(#{<<"sdp_origin">> => <<"abc">>})). 2094: 2095: mod_keystore(_Config) -> 2096: T = fun(Opts) -> #{<<"modules">> => #{<<"mod_keystore">> => Opts}} end, 2097: M = fun(Cfg) -> modopts(mod_keystore, Cfg) end, 2098: ?cfgh(M([{ram_key_size, 1024}]), 2099: T(#{<<"ram_key_size">> => 1024})), 2100: ?errh(T(#{<<"ram_key_size">> => -1})). 2101: 2102: mod_keystore_keys(_Config) -> 2103: T = fun(Opts) -> #{<<"modules">> => #{<<"mod_keystore">> => 2104: #{<<"keys">> => Opts}}} 2105: end, 2106: M = fun(Cfg) -> modopts(mod_keystore, [{keys, Cfg}]) end, 2107: RequiredOpts = #{<<"name">> => <<"access_secret">>, 2108: <<"type">> => <<"ram">>}, 2109: ?cfgh(M([{access_secret, ram}]), 2110: T([RequiredOpts])), 2111: ?cfgh(M([{access_secret, {file, "priv/access_psk"}}]), 2112: T([RequiredOpts#{<<"type">> => <<"file">>, 2113: <<"path">> => <<"priv/access_psk">>}])), 2114: [?errh(T([maps:remove(Key, RequiredOpts)])) || Key <- maps:keys(RequiredOpts)], 2115: ?errh(T([RequiredOpts#{<<"name">> => <<>>}])), 2116: ?errh(T([RequiredOpts#{<<"type">> => <<"rampampam">>}])), 2117: ?errh(T([RequiredOpts#{<<"type">> => <<"file">>}])), 2118: ?errh(T([RequiredOpts#{<<"type">> => <<"file">>, 2119: <<"path">> => <<"does/not/exists">>}])). 2120: 2121: mod_last(_Config) -> 2122: check_iqdisc_map(mod_last), 2123: check_module_defaults(mod_last), 2124: T = fun(Opts) -> #{<<"modules">> => #{<<"mod_last">> => Opts}} end, 2125: P = [modules, mod_last], 2126: ?cfgh(P ++ [backend], mnesia, T(#{<<"backend">> => <<"mnesia">>})), 2127: ?cfgh(P ++ [backend], rdbms, T(#{<<"backend">> => <<"rdbms">>})), 2128: ?cfgh(P ++ [riak, bucket_type], <<"last">>, T(#{<<"backend">> => <<"riak">>})), 2129: ?cfgh(P ++ [riak, bucket_type], <<"test">>, 2130: T(#{<<"backend">> => <<"riak">>, <<"riak">> => #{<<"bucket_type">> => <<"test">>}})), 2131: ?errh(T(#{<<"backend">> => <<"frontend">>})), 2132: ?errh(T(#{<<"riak">> => #{<<"bucket_type">> => 1}})). 2133: 2134: mod_mam_meta(_Config) -> 2135: check_module_defaults(mod_mam_meta), 2136: T = fun(Opts) -> #{<<"modules">> => #{<<"mod_mam_meta">> => Opts}} end, 2137: P = [modules, mod_mam_meta], 2138: test_segmented_cache_config(<<"cache">>, cache, T, 2139: fun([{cache, Opts}]) -> [{P ++ [cache], Opts}] end), 2140: test_mod_mam_meta(T, P). 2141: 2142: mod_mam_meta_riak(_Config) -> 2143: T = fun(Opts) -> 2144: #{<<"modules">> => #{<<"mod_mam_meta">> => Opts#{<<"backend">> => <<"riak">>}}} 2145: end, 2146: P = [modules, mod_mam_meta, riak], 2147: ?cfgh(P, default_config([modules, mod_mam_meta, riak]), T(#{})), 2148: ?cfgh(P ++ [bucket_type], <<"mam_bucket">>, 2149: T(#{<<"riak">> => #{<<"bucket_type">> => <<"mam_bucket">>}})), 2150: ?cfgh(P ++ [search_index], <<"mam_index">>, 2151: T(#{<<"riak">> => #{<<"search_index">> => <<"mam_index">>}})), 2152: ?errh(T(#{<<"riak">> => #{<<"bucket_type">> => <<>>}})), 2153: ?errh(T(#{<<"riak">> => #{<<"search_index">> => <<>>}})). 2154: 2155: mod_mam_meta_pm(_Config) -> 2156: T = fun(Opts) -> #{<<"modules">> => #{<<"mod_mam_meta">> => #{<<"pm">> => Opts}}} end, 2157: P = [modules, mod_mam_meta, pm], 2158: test_mod_mam_meta(T, P), 2159: ?cfgh(P, default_config(P), T(#{})), 2160: ?cfgh(P ++ [archive_groupchats], true, T(#{<<"archive_groupchats">> => true})), 2161: ?cfgh(P ++ [same_mam_id_for_peers], true, T(#{<<"same_mam_id_for_peers">> => true})), 2162: ?errh(T(#{<<"host">> => <<"muc.@HOST@">>})), % muc-only 2163: ?errh(T(#{<<"archive_groupchats">> => <<"not really">>})), 2164: ?errh(T(#{<<"same_mam_id_for_peers">> => <<"not really">>})). 2165: 2166: mod_mam_meta_muc(_Config) -> 2167: T = fun(Opts) -> #{<<"modules">> => #{<<"mod_mam_meta">> => #{<<"muc">> => Opts}}} end, 2168: P = [modules, mod_mam_meta, muc], 2169: test_mod_mam_meta(T, P), 2170: ?cfgh(P, default_config(P), T(#{})), 2171: ?cfgh(P ++ [host], {prefix, <<"muc.">>}, T(#{<<"host">> => <<"muc.@HOST@">>})), 2172: ?cfgh(P ++ [host], {fqdn, <<"muc.test">>}, T(#{<<"host">> => <<"muc.test">>})), 2173: ?errh(T(#{<<"host">> => <<"is this a host? no.">>})), 2174: ?errh(T(#{<<"host">> => [<<"invalid.sub@HOST@">>]})), 2175: ?errh(T(#{<<"host">> => [<<"invalid.sub.@HOST@.as.well">>]})), 2176: ?errh(T(#{<<"archive_groupchats">> => true})), % pm-only 2177: ?errh(T(#{<<"same_mam_id_for_peers">> => true})). % pm-only 2178: 2179: test_mod_mam_meta(T, P) -> 2180: test_async_writer(T, P), 2181: ?cfgh(P ++ [backend], rdbms, 2182: T(#{<<"backend">> => <<"rdbms">>})), 2183: ?cfgh(P ++ [no_stanzaid_element], true, 2184: T(#{<<"no_stanzaid_element">> => true})), 2185: ?cfgh(P ++ [is_archivable_message], mod_mam_utils, 2186: T(#{<<"is_archivable_message">> => <<"mod_mam_utils">>})), 2187: ?cfgh(P ++ [archive_chat_markers], true, 2188: T(#{<<"archive_chat_markers">> => true})), 2189: ?cfgh(P ++ [message_retraction], false, 2190: T(#{<<"message_retraction">> => false})), 2191: ?cfgh(P ++ [user_prefs_store], rdbms, 2192: T(#{<<"user_prefs_store">> => <<"rdbms">>})), 2193: ?cfgh(P ++ [full_text_search], false, 2194: T(#{<<"full_text_search">> => false})), 2195: ?cfgh(P ++ [cache_users], false, 2196: T(#{<<"cache_users">> => false})), 2197: ?cfgh(P ++ [default_result_limit], 100, 2198: T(#{<<"default_result_limit">> => 100})), 2199: ?cfgh(P ++ [max_result_limit], 1000, 2200: T(#{<<"max_result_limit">> => 1000})), 2201: ?cfgh(P ++ [db_jid_format], mam_jid_rfc, 2202: T(#{<<"db_jid_format">> => <<"mam_jid_rfc">>})), 2203: ?cfgh(P ++ [db_message_format], mam_message_xml, 2204: T(#{<<"db_message_format">> => <<"mam_message_xml">>})), 2205: ?cfgh(P ++ [extra_fin_element], mod_mam_utils, 2206: T(#{<<"extra_fin_element">> => <<"mod_mam_utils">>})), 2207: ?cfgh(P ++ [extra_lookup_params], mod_mam_utils, 2208: T(#{<<"extra_lookup_params">> => <<"mod_mam_utils">>})), 2209: ?errh(T(#{<<"backend">> => <<"notepad">>})), 2210: ?errh(T(#{<<"no_stanzaid_element">> => <<"true">>})), 2211: ?errh(T(#{<<"is_archivable_message">> => <<"mod_mam_fake">>})), 2212: ?errh(T(#{<<"archive_chat_markers">> => <<"maybe">>})), 2213: ?errh(T(#{<<"message_retraction">> => 1})), 2214: ?errh(T(#{<<"user_prefs_store">> => <<"textfile">>})), 2215: ?errh(T(#{<<"full_text_search">> => <<"disabled">>})), 2216: ?errh(T(#{<<"cache_users">> => []})), 2217: ?errh(T(#{<<"default_result_limit">> => -1})), 2218: ?errh(T(#{<<"max_result_limit">> => -2})), 2219: ?errh(T(#{<<"db_jid_format">> => <<"not_a_module">>})), 2220: ?errh(T(#{<<"db_message_format">> => <<"not_a_module">>})), 2221: ?errh(T(#{<<"extra_fin_element">> => <<"bad_module">>})), 2222: ?errh(T(#{<<"extra_lookup_params">> => <<"bad_module">>})). 2223: 2224: test_cache_config(T, M) -> 2225: ?cfgh(M([{cache_users, false}]), 2226: T(#{<<"cache_users">> => false})), 2227: ?errh(T(#{<<"cache_users">> => []})), 2228: test_segmented_cache_config(<<"cache">>, cache, T, M). 2229: 2230: test_segmented_cache_config(NameK, NameV, T, M) -> 2231: ?cfgh(M([{NameV, [{module, internal}]}]), 2232: T(#{NameK => #{<<"module">> => <<"internal">>}})), 2233: ?cfgh(M([{NameV, [{time_to_live, 8600}]}]), 2234: T(#{NameK => #{<<"time_to_live">> => 8600}})), 2235: ?cfgh(M([{NameV, [{time_to_live, infinity}]}]), 2236: T(#{NameK => #{<<"time_to_live">> => <<"infinity">>}})), 2237: ?cfgh(M([{NameV, [{number_of_segments, 10}]}]), 2238: T(#{NameK => #{<<"number_of_segments">> => 10}})), 2239: ?cfgh(M([{NameV, [{strategy, fifo}]}]), 2240: T(#{NameK => #{<<"strategy">> => <<"fifo">>}})), 2241: ?errh(T(#{NameK => #{<<"module">> => <<"mod_wrong_cache">>}})), 2242: ?errh(T(#{NameK => #{<<"module">> => <<"mod_cache_users">>, 2243: <<"time_to_live">> => 8600}})), 2244: ?errh(T(#{NameK => #{<<"time_to_live">> => 0}})), 2245: ?errh(T(#{NameK => #{<<"strategy">> => <<"lifo">>}})), 2246: ?errh(T(#{NameK => #{<<"number_of_segments">> => 0}})), 2247: ?errh(T(#{NameK => #{<<"number_of_segments">> => <<"infinity">>}})). 2248: 2249: test_async_writer(ParentT, ParentP) -> 2250: P = ParentP ++ [async_writer], 2251: T = fun(Opts) -> ParentT(#{<<"async_writer">> => Opts}) end, 2252: ?cfgh(P ++ [flush_interval], 1500, T(#{<<"flush_interval">> => 1500})), 2253: ?cfgh(P ++ [batch_size], 1500, T(#{<<"batch_size">> => 1500})), 2254: ?cfgh(P ++ [pool_size], 1500, T(#{<<"pool_size">> => 1500})), 2255: ?cfgh(P ++ [enabled], false, T(#{<<"enabled">> => false})), 2256: ?errh(T(#{<<"flush_interval">> => -1})), 2257: ?errh(T(#{<<"batch_size">> => -1})), 2258: ?errh(T(#{<<"pool_size">> => -1})), 2259: ?errh(T(#{<<"enabled">> => <<"wrong">>})). 2260: 2261: mod_muc(_Config) -> 2262: T = fun(Opts) -> #{<<"modules">> => #{<<"mod_muc">> => Opts}} end, 2263: M = fun(Cfg) -> modopts(mod_muc, Cfg) end, 2264: ?cfgh(M([{host, {prefix, <<"conference.">>}}]), 2265: T(#{<<"host">> => <<"conference.@HOST@">>})), 2266: ?cfgh(M([{host, {fqdn, <<"conference.test">>}}]), 2267: T(#{<<"host">> => <<"conference.test">>})), 2268: ?cfgh(M([{backend, mnesia}]), 2269: T(#{<<"backend">> => <<"mnesia">>})), 2270: ?cfgh(M([{access, all}]), 2271: T(#{<<"access">> => <<"all">>})), 2272: ?cfgh(M([{access_create, admin}]), 2273: T(#{<<"access_create">> => <<"admin">>})), 2274: ?cfgh(M([{access_admin, none}]), 2275: T(#{<<"access_admin">> => <<"none">>})), 2276: ?cfgh(M([{access_persistent, all}]), 2277: T(#{<<"access_persistent">> => <<"all">>})), 2278: ?cfgh(M([{history_size, 20}]), 2279: T(#{<<"history_size">> => 20})), 2280: ?cfgh(M([{room_shaper, muc_room_shaper}]), 2281: T(#{<<"room_shaper">> => <<"muc_room_shaper">>})), 2282: ?cfgh(M([{max_room_id, infinity}]), 2283: T(#{<<"max_room_id">> => <<"infinity">>})), 2284: ?cfgh(M([{max_room_name, 30}]), 2285: T(#{<<"max_room_name">> => 30})), 2286: ?cfgh(M([{max_room_desc, 0}]), 2287: T(#{<<"max_room_desc">> => 0})), 2288: ?cfgh(M([{min_message_interval, 10}]), 2289: T(#{<<"min_message_interval">> => 10})), 2290: ?cfgh(M([{min_presence_interval, 0}]), 2291: T(#{<<"min_presence_interval">> => 0})), 2292: ?cfgh(M([{max_users, 30}]), 2293: T(#{<<"max_users">> => 30})), 2294: ?cfgh(M([{max_users_admin_threshold, 2}]), 2295: T(#{<<"max_users_admin_threshold">> => 2})), 2296: ?cfgh(M([{user_message_shaper, muc_msg_shaper}]), 2297: T(#{<<"user_message_shaper">> => <<"muc_msg_shaper">>})), 2298: ?cfgh(M([{user_presence_shaper, muc_pres_shaper}]), 2299: T(#{<<"user_presence_shaper">> => <<"muc_pres_shaper">>})), 2300: ?cfgh(M([{max_user_conferences, 10}]), 2301: T(#{<<"max_user_conferences">> => 10})), 2302: ?cfgh(M([{http_auth_pool, external_auth}]), 2303: T(#{<<"http_auth_pool">> => <<"external_auth">>})), 2304: ?cfgh(M([{load_permanent_rooms_at_startup, true}]), 2305: T(#{<<"load_permanent_rooms_at_startup">> => true})), 2306: ?cfgh(M([{hibernate_timeout, infinity}]), 2307: T(#{<<"hibernate_timeout">> => <<"infinity">>})), 2308: ?cfgh(M([{hibernated_room_check_interval, 5000}]), 2309: T(#{<<"hibernated_room_check_interval">> => 5000})), 2310: ?cfgh(M([{hibernated_room_timeout, 0}]), 2311: T(#{<<"hibernated_room_timeout">> => 0})), 2312: ?errh(T(#{<<"host">> => <<>>})), 2313: ?errh(T(#{<<"host">> => <<"is this a host? no.">>})), 2314: ?errh(T(#{<<"host">> => [<<"invalid.sub@HOST@">>]})), 2315: ?errh(T(#{<<"host">> => [<<"invalid.sub.@HOST@.as.well">>]})), 2316: ?errh(T(#{<<"backend">> => <<"amnesia">>})), 2317: ?errh(T(#{<<"access">> => <<>>})), 2318: ?errh(T(#{<<"access_create">> => 1})), 2319: ?errh(T(#{<<"access_admin">> => []})), 2320: ?errh(T(#{<<"access_persistent">> => true})), 2321: ?errh(T(#{<<"history_size">> => <<"20">>})), 2322: ?errh(T(#{<<"room_shaper">> => <<>>})), 2323: ?errh(T(#{<<"max_room_id">> => #{}})), 2324: ?errh(T(#{<<"max_room_name">> => <<"infinite!">>})), 2325: ?errh(T(#{<<"max_room_desc">> => -1})), 2326: ?errh(T(#{<<"min_message_interval">> => -10})), 2327: ?errh(T(#{<<"min_presence_interval">> => <<"infinity">>})), 2328: ?errh(T(#{<<"max_users">> => 0})), 2329: ?errh(T(#{<<"max_users_admin_threshold">> => 0})), 2330: ?errh(T(#{<<"user_message_shaper">> => []})), 2331: ?errh(T(#{<<"user_presence_shaper">> => <<>>})), 2332: ?errh(T(#{<<"max_user_conferences">> => -1})), 2333: ?errh(T(#{<<"http_auth_pool">> => <<>>})), 2334: ?errh(T(#{<<"load_permanent_rooms_at_startup">> => <<"true">>})), 2335: ?errh(T(#{<<"hibernate_timeout">> => <<"really big">>})), 2336: ?errh(T(#{<<"hibernated_room_check_interval">> => -1})), 2337: ?errh(T(#{<<"hibernated_room_timeout">> => false})). 2338: 2339: mod_muc_default_room(_Config) -> 2340: T = fun(Opts) -> #{<<"modules">> => 2341: #{<<"mod_muc">> => #{<<"default_room">> => Opts}}} end, 2342: M = fun(Cfg) -> modopts(mod_muc, [{default_room_options, Cfg}]) end, 2343: ?cfgh(M([]), T(#{})), 2344: ?cfgh(M([{title, <<"living room">>}]), 2345: T(#{<<"title">> => <<"living room">>})), 2346: ?cfgh(M([{description, <<"a room that is alive">>}]), 2347: T(#{<<"description">> => <<"a room that is alive">>})), 2348: ?cfgh(M([{allow_change_subj, true}]), 2349: T(#{<<"allow_change_subj">> => true})), 2350: ?cfgh(M([{allow_query_users, false}]), 2351: T(#{<<"allow_query_users">> => false})), 2352: ?cfgh(M([{allow_private_messages, true}]), 2353: T(#{<<"allow_private_messages">> => true})), 2354: ?cfgh(M([{allow_visitor_status, false}]), 2355: T(#{<<"allow_visitor_status">> => false})), 2356: ?cfgh(M([{allow_visitor_nickchange, true}]), 2357: T(#{<<"allow_visitor_nickchange">> => true})), 2358: ?cfgh(M([{public, false}]), 2359: T(#{<<"public">> => false})), 2360: ?cfgh(M([{public_list, true}]), 2361: T(#{<<"public_list">> => true})), 2362: ?cfgh(M([{persistent, true}]), 2363: T(#{<<"persistent">> => true})), 2364: ?cfgh(M([{moderated, false}]), 2365: T(#{<<"moderated">> => false})), 2366: ?cfgh(M([{members_by_default, true}]), 2367: T(#{<<"members_by_default">> => true})), 2368: ?cfgh(M([{members_only, false}]), 2369: T(#{<<"members_only">> => false})), 2370: ?cfgh(M([{allow_user_invites, true}]), 2371: T(#{<<"allow_user_invites">> => true})), 2372: ?cfgh(M([{allow_multiple_sessions, false}]), 2373: T(#{<<"allow_multiple_sessions">> => false})), 2374: ?cfgh(M([{password_protected, true}]), 2375: T(#{<<"password_protected">> => true})), 2376: ?cfgh(M([{password, <<"secret">>}]), 2377: T(#{<<"password">> => <<"secret">>})), 2378: ?cfgh(M([{anonymous, true}]), 2379: T(#{<<"anonymous">> => true})), 2380: ?cfgh(M([{max_users, 100}]), 2381: T(#{<<"max_users">> => 100})), 2382: ?cfgh(M([{logging, false}]), 2383: T(#{<<"logging">> => false})), 2384: ?cfgh(M([{maygetmemberlist, [moderator]}]), 2385: T(#{<<"maygetmemberlist">> => [<<"moderator">>]})), 2386: ?cfgh(M([{subject, <<"Lambda days">>}]), 2387: T(#{<<"subject">> => <<"Lambda days">>})), 2388: ?cfgh(M([{subject_author, <<"Alice">>}]), 2389: T(#{<<"subject_author">> => <<"Alice">>})), 2390: ?errh(T(<<"bad value">>)), 2391: ?errh(T(#{<<"title">> => true})), 2392: ?errh(T(#{<<"description">> => 1})), 2393: ?errh(T(#{<<"allow_change_subj">> => <<"true">>})), 2394: ?errh(T(#{<<"allow_query_users">> => <<>>})), 2395: ?errh(T(#{<<"allow_private_messages">> => 1})), 2396: ?errh(T(#{<<"allow_visitor_status">> => []})), 2397: ?errh(T(#{<<"allow_visitor_nickchange">> => #{}})), 2398: ?errh(T(#{<<"public">> => 0})), 2399: ?errh(T(#{<<"public_list">> => [false]})), 2400: ?errh(T(#{<<"persistent">> => 1})), 2401: ?errh(T(#{<<"moderated">> => <<"yes">>})), 2402: ?errh(T(#{<<"members_by_default">> => 0})), 2403: ?errh(T(#{<<"members_only">> => [true]})), 2404: ?errh(T(#{<<"allow_user_invites">> => <<>>})), 2405: ?errh(T(#{<<"allow_multiple_sessions">> => []})), 2406: ?errh(T(#{<<"password_protected">> => #{}})), 2407: ?errh(T(#{<<"password">> => false})), 2408: ?errh(T(#{<<"anonymous">> => <<"maybe">>})), 2409: ?errh(T(#{<<"max_users">> => 0})), 2410: ?errh(T(#{<<"logging">> => [true, false]})), 2411: ?errh(T(#{<<"maygetmemberlist">> => <<"moderator">>})), 2412: ?errh(T(#{<<"maygetmemberlist">> => [<<>>]})), 2413: ?errh(T(#{<<"subject">> => [<<"subjective">>]})), 2414: ?errh(T(#{<<"subject_author">> => 1})). 2415: 2416: mod_muc_default_room_affiliations(_Config) -> 2417: T = fun(Opts) -> #{<<"modules">> => 2418: #{<<"mod_muc">> => 2419: #{<<"default_room">> => #{<<"affiliations">> => Opts}}}} end, 2420: M = fun(Cfg) -> modopts(mod_muc, [{default_room_options, [{affiliations, Cfg}]}]) end, 2421: RequiredOpts = #{<<"user">> => <<"alice">>, 2422: <<"server">> => <<"localhost">>, 2423: <<"resource">> => <<"phone">>, 2424: <<"affiliation">> => <<"moderator">>}, 2425: ExpectedCfg = {{<<"alice">>, <<"localhost">>, <<"phone">>}, moderator}, 2426: ?cfgh(M([]), T([])), 2427: ?cfgh(M([ExpectedCfg]), T([RequiredOpts])), 2428: [?errh(T([maps:remove(Key, RequiredOpts)])) || Key <- maps:keys(RequiredOpts)], 2429: ?errh(T([RequiredOpts#{<<"user">> := <<>>}])), 2430: ?errh(T([RequiredOpts#{<<"server">> := <<"domain? not really!">>}])), 2431: ?errh(T([RequiredOpts#{<<"resource">> := false}])), 2432: ?errh(T([RequiredOpts#{<<"affiliation">> := <<>>}])). 2433: 2434: mod_muc_log(_Config) -> 2435: T = fun(Opts) -> #{<<"modules">> => #{<<"mod_muc_log">> => Opts}} end, 2436: M = fun(Cfg) -> modopts(mod_muc_log, Cfg) end, 2437: ?cfgh(M([{outdir, "www/muc"}]), 2438: T(#{<<"outdir">> => <<"www/muc">>})), 2439: ?cfgh(M([{access_log, muc_admin}]), 2440: T(#{<<"access_log">> => <<"muc_admin">>})), 2441: ?cfgh(M([{dirtype, subdirs}]), 2442: T(#{<<"dirtype">> => <<"subdirs">>})), 2443: ?cfgh(M([{dirname, room_name}]), 2444: T(#{<<"dirname">> => <<"room_name">>})), 2445: ?cfgh(M([{file_format, html}]), 2446: T(#{<<"file_format">> => <<"html">>})), 2447: ?cfgh(M([{cssfile, <<"path/to/css_file">>}]), 2448: T(#{<<"css_file">> => <<"path/to/css_file">>})), 2449: ?cfgh(M([{timezone, local}]), 2450: T(#{<<"timezone">> => <<"local">>})), 2451: ?cfgh(M([{spam_prevention, false}]), 2452: T(#{<<"spam_prevention">> => false})), 2453: ?errh(T(#{<<"outdir">> => <<"does/not/exist">>})), 2454: ?errh(T(#{<<"access_log">> => 1})), 2455: ?errh(T(#{<<"dirtype">> => <<"imaginary">>})), 2456: ?errh(T(#{<<"dirname">> => <<"dyrektory">>})), 2457: ?errh(T(#{<<"file_format">> => <<"none">>})), 2458: ?errh(T(#{<<"css_file">> => <<>>})), 2459: ?errh(T(#{<<"timezone">> => <<"yes">>})), 2460: ?errh(T(#{<<"spam_prevention">> => <<"spam and eggs and spam">>})). 2461: 2462: mod_muc_log_top_link(_Config) -> 2463: T = fun(Opts) -> #{<<"modules">> => #{<<"mod_muc_log">> => #{<<"top_link">> => Opts}}} end, 2464: M = fun(Cfg) -> modopts(mod_muc_log, [{top_link, Cfg}]) end, 2465: RequiredOpts = #{<<"target">> => <<"https://esl.github.io/MongooseDocs/">>, 2466: <<"text">> => <<"Docs">>}, 2467: ExpectedCfg = {"https://esl.github.io/MongooseDocs/", "Docs"}, 2468: ?cfgh(M(ExpectedCfg), T(RequiredOpts)), 2469: [?errh(T(maps:remove(K, RequiredOpts))) || K <- maps:keys(RequiredOpts)], 2470: ?errh(T(RequiredOpts#{<<"target">> => true})), 2471: ?errh(T(RequiredOpts#{<<"text">> => <<"">>})). 2472: 2473: mod_muc_light(_Config) -> 2474: T = fun(Opts) -> #{<<"modules">> => #{<<"mod_muc_light">> => Opts}} end, 2475: M = fun(Cfg) -> modopts(mod_muc_light, Cfg) end, 2476: test_segmented_cache_config(<<"cache_affs">>, cache_affs, T, M), 2477: ?cfgh(M([{backend, mnesia}]), 2478: T(#{<<"backend">> => <<"mnesia">>})), 2479: ?cfgh(M([{host, {prefix, <<"muclight.">>}}]), 2480: T(#{<<"host">> => <<"muclight.@HOST@">>})), 2481: ?cfgh(M([{host, {fqdn, <<"muclight.test">>}}]), 2482: T(#{<<"host">> => <<"muclight.test">>})), 2483: ?cfgh(M([{equal_occupants, true}]), 2484: T(#{<<"equal_occupants">> => true})), 2485: ?cfgh(M([{legacy_mode, false}]), 2486: T(#{<<"legacy_mode">> => false})), 2487: ?cfgh(M([{rooms_per_user, 100}]), 2488: T(#{<<"rooms_per_user">> => 100})), 2489: ?cfgh(M([{blocking, false}]), 2490: T(#{<<"blocking">> => false})), 2491: ?cfgh(M([{all_can_configure, true}]), 2492: T(#{<<"all_can_configure">> => true})), 2493: ?cfgh(M([{all_can_invite, false}]), 2494: T(#{<<"all_can_invite">> => false})), 2495: ?cfgh(M([{max_occupants, infinity}]), 2496: T(#{<<"max_occupants">> => <<"infinity">>})), 2497: ?cfgh(M([{rooms_per_page, 10}]), 2498: T(#{<<"rooms_per_page">> => 10})), 2499: ?cfgh(M([{rooms_in_rosters, true}]), 2500: T(#{<<"rooms_in_rosters">> => true})), 2501: ?errh(T(#{<<"backend">> => <<"frontend">>})), 2502: ?errh(T(#{<<"host">> => <<"what is a domain?!">>})), 2503: ?errh(T(#{<<"host">> => [<<"invalid.sub@HOST@">>]})), 2504: ?errh(T(#{<<"host">> => [<<"invalid.sub.@HOST@.as.well">>]})), 2505: ?errh(T(#{<<"equal_occupants">> => <<"true">>})), 2506: ?errh(T(#{<<"legacy_mode">> => 1234})), 2507: ?errh(T(#{<<"rooms_per_user">> => 0})), 2508: ?errh(T(#{<<"blocking">> => <<"true">>})), 2509: ?errh(T(#{<<"all_can_configure">> => []})), 2510: ?errh(T(#{<<"all_can_invite">> => #{}})), 2511: ?errh(T(#{<<"max_occupants">> => <<"seven">>})), 2512: ?errh(T(#{<<"rooms_per_page">> => false})), 2513: ?errh(T(#{<<"rooms_in_rosters">> => [1, 2, 3]})). 2514: 2515: mod_muc_light_config_schema(_Config) -> 2516: T = fun(Opts) -> #{<<"modules">> => 2517: #{<<"mod_muc_light">> => #{<<"config_schema">> => Opts}}} end, 2518: M = fun(Cfg) -> modopts(mod_muc_light, [{config_schema, Cfg}]) end, 2519: Field = #{<<"field">> => <<"my_field">>}, 2520: ?cfgh(M([]), T([])), 2521: ?cfgh(M([{<<"my_field">>, <<"My Room">>, my_field, binary}]), 2522: T([Field#{<<"string_value">> => <<"My Room">>}])), 2523: ?cfgh(M([{<<"my_field">>, 1, my_field, integer}]), 2524: T([Field#{<<"integer_value">> => 1}])), 2525: ?cfgh(M([{<<"my_field">>, 0.5, my_field, float}]), 2526: T([Field#{<<"float_value">> => 0.5}])), 2527: ?cfgh(M([{<<"my_field">>, 0, your_field, integer}]), 2528: T([Field#{<<"integer_value">> => 0, 2529: <<"internal_key">> => <<"your_field">>}])), 2530: ?cfgh(M([{<<"żółć"/utf8>>, <<"Рентгеноэлектрокардиографический"/utf8>>, 'żółć', binary}]), 2531: T([#{<<"field">> => <<"żółć"/utf8>>, 2532: <<"string_value">> => <<"Рентгеноэлектрокардиографический"/utf8>>}])), 2533: ?cfgh(M([{<<"first">>, 1, first, integer}, % the config is u-key-sorted 2534: {<<"second">>, <<"two">>, second, binary}]), 2535: T([#{<<"field">> => <<"second">>, <<"string_value">> => <<"two">>}, 2536: #{<<"field">> => <<"second">>, <<"float_value">> => 2.0}, 2537: #{<<"field">> => <<"first">>, <<"integer_value">> => 1}])), 2538: ?errh(T([#{<<"string_value">> => <<"My Room">>}])), 2539: ?errh(T([#{<<"field">> => <<>>, 2540: <<"string_value">> => <<"My Room">>}])), 2541: ?errh(T([Field#{<<"string_value">> => 0}])), 2542: ?errh(T([Field#{<<"integer_value">> => 1.5}])), 2543: ?errh(T([Field#{<<"float_value">> => 1}])), 2544: ?errh(T([Field#{<<"integer_value">> => 0, 2545: <<"string_value">> => <<"My Room">>}])), 2546: ?errh(T([Field#{<<"integer_value">> => 0, 2547: <<"internal_key">> => <<>>}])). 2548: 2549: mod_offline(_Config) -> 2550: T = fun(Opts) -> #{<<"modules">> => #{<<"mod_offline">> => Opts}} end, 2551: M = fun(Cfg) -> modopts(mod_offline, Cfg) end, 2552: ?cfgh(M([{access_max_user_messages, max_user_offline_messages}]), 2553: T(#{<<"access_max_user_messages">> => <<"max_user_offline_messages">>})), 2554: ?cfgh(M([{backend, rdbms}]), 2555: T(#{<<"backend">> => <<"rdbms">>})), 2556: ?cfgh(M([{bucket_type, <<"test">>}]), 2557: T(#{<<"riak">> => #{<<"bucket_type">> => <<"test">>}})), 2558: ?errh(T(#{<<"access_max_user_messages">> => 1})), 2559: ?errh(T(#{<<"backend">> => <<"riak_is_the_best">>})), 2560: ?errh(T(#{<<"riak">> => #{<<"bucket_type">> => 1}})), 2561: ?errh(T(#{<<"riak">> => #{<<"bucket">> => <<"leaky">>}})). 2562: 2563: mod_ping(_Config) -> 2564: T = fun(Opts) -> #{<<"modules">> => #{<<"mod_ping">> => Opts}} end, 2565: M = fun(Cfg) -> modopts(mod_ping, Cfg) end, 2566: ?cfgh(M([{send_pings, true}]), 2567: T(#{<<"send_pings">> => true})), 2568: ?cfgh(M([{ping_interval, timer:seconds(10)}]), 2569: T(#{<<"ping_interval">> => 10})), 2570: ?cfgh(M([{timeout_action, kill}]), 2571: T(#{<<"timeout_action">> => <<"kill">>})), 2572: ?cfgh(M([{ping_req_timeout, timer:seconds(20)}]), 2573: T(#{<<"ping_req_timeout">> => 20})), 2574: ?errh(T(#{<<"send_pings">> => 1})), 2575: ?errh(T(#{<<"ping_interval">> => 0})), 2576: ?errh(T(#{<<"timeout_action">> => <<"kill_them_all">>})), 2577: ?errh(T(#{<<"ping_req_timeout">> => 0})), 2578: check_iqdisc(mod_ping). 2579: 2580: mod_privacy(_Config) -> 2581: T = fun(Opts) -> #{<<"modules">> => #{<<"mod_privacy">> => Opts}} end, 2582: M = fun(Cfg) -> modopts(mod_privacy, Cfg) end, 2583: ?cfgh(M([{backend, mnesia}]), 2584: T(#{<<"backend">> => <<"mnesia">>})), 2585: ?cfgh(M([{defaults_bucket_type, <<"defaults">>}]), 2586: T(#{<<"riak">> => #{<<"defaults_bucket_type">> => <<"defaults">>}})), 2587: ?cfgh(M([{names_bucket_type, <<"names">>}]), 2588: T(#{<<"riak">> => #{<<"names_bucket_type">> => <<"names">>}})), 2589: ?cfgh(M([{bucket_type, <<"bucket">>}]), 2590: T(#{<<"riak">> => #{<<"bucket_type">> => <<"bucket">>}})), 2591: ?errh(T(#{<<"backend">> => <<"mongoddt">>})), 2592: ?errh(T(#{<<"riak">> => #{<<"defaults_bucket_type">> => <<>>}})), 2593: ?errh(T(#{<<"riak">> => #{<<"names_bucket_type">> => 1}})), 2594: ?errh(T(#{<<"riak">> => #{<<"bucket_type">> => 1}})). 2595: 2596: mod_private(_Config) -> 2597: check_iqdisc_map(mod_private), 2598: check_module_defaults(mod_private), 2599: T = fun(Opts) -> #{<<"modules">> => #{<<"mod_private">> => Opts}} end, 2600: P = [modules, mod_private], 2601: ?cfgh(P ++ [backend], riak, T(#{<<"backend">> => <<"riak">>})), 2602: ?cfgh(P ++ [riak, bucket_type], <<"private">>, T(#{<<"backend">> => <<"riak">>})), 2603: ?cfgh(P ++ [riak, bucket_type], <<"private_stuff">>, T(#{<<"backend">> => <<"riak">>, 2604: <<"riak">> => #{<<"bucket_type">> => <<"private_stuff">>}})), 2605: ?errh(T(#{<<"backend">> => <<"mssql">>})), 2606: ?errh(T(#{<<"riak">> => #{<<"bucket_type">> => 1}})). 2607: 2608: mod_pubsub(_Config) -> 2609: check_iqdisc(mod_pubsub), 2610: T = fun(Opts) -> #{<<"modules">> => #{<<"mod_pubsub">> => Opts}} end, 2611: M = fun(Cfg) -> modopts(mod_pubsub, Cfg) end, 2612: ?cfgh(M([{host, {prefix, <<"pubsub.">>}}]), 2613: T(#{<<"host">> => <<"pubsub.@HOST@">>})), 2614: ?cfgh(M([{host, {fqdn, <<"pubsub.test">>}}]), 2615: T(#{<<"host">> => <<"pubsub.test">>})), 2616: ?cfgh(M([{backend, rdbms}]), 2617: T(#{<<"backend">> => <<"rdbms">>})), 2618: ?cfgh(M([{access_createnode, all}]), 2619: T(#{<<"access_createnode">> => <<"all">>})), 2620: ?cfgh(M([{max_items_node, 20}]), 2621: T(#{<<"max_items_node">> => 20})), 2622: ?cfgh(M([{max_subscriptions_node, 30}]), 2623: T(#{<<"max_subscriptions_node">> => 30})), 2624: ?cfgh(M([{nodetree, <<"tree">>}]), 2625: T(#{<<"nodetree">> => <<"tree">>})), 2626: ?cfgh(M([{ignore_pep_from_offline, false}]), 2627: T(#{<<"ignore_pep_from_offline">> => false})), 2628: ?cfgh(M([{last_item_cache, rdbms}]), 2629: T(#{<<"last_item_cache">> => <<"rdbms">>})), 2630: ?cfgh(M([{plugins, [<<"flat">>, <<"dag">>]}]), 2631: T(#{<<"plugins">> => [<<"flat">>, <<"dag">>]})), 2632: ?cfgh(M([{item_publisher, true}]), 2633: T(#{<<"item_publisher">> => true})), 2634: ?cfgh(M([{sync_broadcast, false}]), 2635: T(#{<<"sync_broadcast">> => false})), 2636: ?errh(T(#{<<"host">> => <<"">>})), 2637: ?errh(T(#{<<"host">> => <<"is this a host? no.">>})), 2638: ?errh(T(#{<<"host">> => [<<"invalid.sub@HOST@">>]})), 2639: ?errh(T(#{<<"host">> => [<<"invalid.sub.@HOST@.as.well">>]})), 2640: ?errh(T(#{<<"backend">> => <<"amnesia">>})), 2641: ?errh(T(#{<<"access_createnode">> => <<"">>})), 2642: ?errh(T(#{<<"max_items_node">> => -1})), 2643: ?errh(T(#{<<"max_subscriptions_node">> => 3.1415})), 2644: ?errh(T(#{<<"nodetree">> => <<"christmas_tree">>})), 2645: ?errh(T(#{<<"ignore_pep_from_offline">> => <<"maybe">>})), 2646: ?errh(T(#{<<"last_item_cache">> => false})), 2647: ?errh(T(#{<<"plugins">> => [<<"deep">>]})), 2648: ?errh(T(#{<<"item_publisher">> => 1})), 2649: ?errh(T(#{<<"sync_broadcast">> => []})). 2650: 2651: mod_pubsub_pep_mapping(_Config) -> 2652: T = fun(Opts) -> #{<<"modules">> => #{<<"mod_pubsub">> => 2653: #{<<"pep_mapping">> => Opts}}} end, 2654: M = fun(Cfg) -> modopts(mod_pubsub, [{pep_mapping, Cfg}]) end, 2655: RequiredOpts = #{<<"namespace">> => <<"urn:xmpp:microblog:0">>, 2656: <<"node">> => <<"mb">>}, 2657: ?cfgh(M([{<<"urn:xmpp:microblog:0">>, <<"mb">>}]), 2658: T([RequiredOpts])), 2659: [?errh(T([maps:remove(Key, RequiredOpts)])) || Key <- maps:keys(RequiredOpts)], 2660: [?errh(T([RequiredOpts#{Key => <<>>}])) || Key <- maps:keys(RequiredOpts)]. 2661: 2662: mod_pubsub_default_node_config(_Config) -> 2663: T = fun(Opts) -> #{<<"modules">> => #{<<"mod_pubsub">> => 2664: #{<<"default_node_config">> => Opts}}} end, 2665: M = fun(Cfg) -> modopts(mod_pubsub, [{default_node_config, Cfg}]) end, 2666: ?cfgh(M([{access_model, open}]), 2667: T(#{<<"access_model">> => <<"open">>})), 2668: ?cfgh(M([{deliver_notifications, true}]), 2669: T(#{<<"deliver_notifications">> => true})), 2670: ?cfgh(M([{deliver_payloads, false}]), 2671: T(#{<<"deliver_payloads">> => false})), 2672: ?cfgh(M([{max_items, 1000}]), 2673: T(#{<<"max_items">> => 1000})), 2674: ?cfgh(M([{max_payload_size, 1000}]), 2675: T(#{<<"max_payload_size">> => 1000})), 2676: ?cfgh(M([{node_type, dag}]), 2677: T(#{<<"node_type">> => <<"dag">>})), 2678: ?cfgh(M([{notification_type, headline}]), 2679: T(#{<<"notification_type">> => <<"headline">>})), 2680: ?cfgh(M([{notify_config, true}]), 2681: T(#{<<"notify_config">> => true})), 2682: ?cfgh(M([{notify_delete, false}]), 2683: T(#{<<"notify_delete">> => false})), 2684: ?cfgh(M([{notify_retract, true}]), 2685: T(#{<<"notify_retract">> => true})), 2686: ?cfgh(M([{persist_items, false}]), 2687: T(#{<<"persist_items">> => false})), 2688: ?cfgh(M([{presence_based_delivery, true}]), 2689: T(#{<<"presence_based_delivery">> => true})), 2690: ?cfgh(M([{publish_model, open}]), 2691: T(#{<<"publish_model">> => <<"open">>})), 2692: ?cfgh(M([{purge_offline, false}]), 2693: T(#{<<"purge_offline">> => false})), 2694: ?cfgh(M([{roster_groups_allowed, [<<"friends">>]}]), 2695: T(#{<<"roster_groups_allowed">> => [<<"friends">>]})), 2696: ?cfgh(M([{send_last_published_item, on_sub_and_presence}]), 2697: T(#{<<"send_last_published_item">> => <<"on_sub_and_presence">>})), 2698: ?cfgh(M([{subscribe, true}]), 2699: T(#{<<"subscribe">> => true})), 2700: ?errh(T(#{<<"access_model">> => <<>>})), 2701: ?errh(T(#{<<"deliver_notifications">> => <<"yes">>})), 2702: ?errh(T(#{<<"deliver_payloads">> => 0})), 2703: ?errh(T(#{<<"max_items">> => -1})), 2704: ?errh(T(#{<<"max_payload_size">> => -1})), 2705: ?errh(T(#{<<"node_type">> => [<<"dag">>]})), 2706: ?errh(T(#{<<"notification_type">> => <<>>})), 2707: ?errh(T(#{<<"notify_config">> => <<"false">>})), 2708: ?errh(T(#{<<"notify_delete">> => [true]})), 2709: ?errh(T(#{<<"notify_retract">> => #{}})), 2710: ?errh(T(#{<<"persist_items">> => 1})), 2711: ?errh(T(#{<<"presence_based_delivery">> => []})), 2712: ?errh(T(#{<<"publish_model">> => <<"">>})), 2713: ?errh(T(#{<<"purge_offline">> => 1})), 2714: ?errh(T(#{<<"roster_groups_allowed">> => [<<>>]})), 2715: ?errh(T(#{<<"send_last_published_item">> => <<>>})), 2716: ?errh(T(#{<<"subscribe">> => <<"never">>})). 2717: 2718: mod_push_service_mongoosepush(_Config) -> 2719: T = fun(Opts) -> #{<<"modules">> => #{<<"mod_push_service_mongoosepush">> => Opts}} end, 2720: M = fun(Cfg) -> modopts(mod_push_service_mongoosepush, Cfg) end, 2721: ?cfgh(M([{pool_name, test_pool}]), 2722: T(#{<<"pool_name">> => <<"test_pool">>})), 2723: ?cfgh(M([{api_version, "v3"}]), 2724: T(#{<<"api_version">> => <<"v3">>})), 2725: ?cfgh(M([{max_http_connections, 100}]), 2726: T(#{<<"max_http_connections">> => 100})), 2727: ?errh(T(#{<<"pool_name">> => 1})), 2728: ?errh(T(#{<<"api_version">> => <<"v4">>})), 2729: ?errh(T(#{<<"max_http_connections">> => -1})). 2730: 2731: mod_register(_Config) -> 2732: ?cfgh(modopts(mod_register, [{access,register}, 2733: {ip_access, [{allow,"127.0.0.0/8"}, 2734: {deny,"0.0.0.0"}]} 2735: ]), 2736: ip_access_register(<<"0.0.0.0">>)), 2737: ?cfgh(modopts(mod_register, [{access,register}, 2738: {ip_access, [{allow,"127.0.0.0/8"}, 2739: {deny,"0.0.0.4"}]} 2740: ]), 2741: ip_access_register(<<"0.0.0.4">>)), 2742: ?cfgh(modopts(mod_register, [{access,register}, 2743: {ip_access, [{allow,"127.0.0.0/8"}, 2744: {deny,"::1"}]} 2745: ]), 2746: ip_access_register(<<"::1">>)), 2747: ?cfgh(modopts(mod_register, [{access,register}, 2748: {ip_access, [{allow,"127.0.0.0/8"}, 2749: {deny,"::1/128"}]} 2750: ]), 2751: ip_access_register(<<"::1/128">>)), 2752: ?errh(invalid_ip_access_register()), 2753: ?errh(invalid_ip_access_register_ipv6()), 2754: ?errh(ip_access_register(<<"hello">>)), 2755: ?errh(ip_access_register(<<"0.d">>)), 2756: ?cfgh(modopts(mod_register, [{welcome_message, {"Subject", "Body"}}]), 2757: welcome_message()), 2758: %% List of jids 2759: ?cfgh(modopts(mod_register, [{registration_watchers, 2760: [<<"alice@bob">>, <<"ilovemongoose@help">>]}]), 2761: registration_watchers([<<"alice@bob">>, <<"ilovemongoose@help">>])), 2762: ?errh(registration_watchers([<<"alice@bob">>, <<"jids@have@no@feelings!">>])), 2763: %% non-negative integer 2764: ?cfgh(modopts(mod_register, [{password_strength, 42}]), 2765: password_strength_register(42)), 2766: ?errh(password_strength_register(<<"42">>)), 2767: ?errh(password_strength_register(<<"strong">>)), 2768: ?errh(password_strength_register(-150)), 2769: ?errh(welcome_message(<<"Subject">>, 1)), 2770: ?errh(welcome_message(1, <<"Body">>)), 2771: check_iqdisc(mod_register). 2772: 2773: welcome_message() -> 2774: welcome_message(<<"Subject">>, <<"Body">>). 2775: 2776: welcome_message(S, B) -> 2777: Opts = #{<<"welcome_message">> => #{<<"subject">> => S, <<"body">> => B}}, 2778: #{<<"modules">> => #{<<"mod_register">> => Opts}}. 2779: 2780: password_strength_register(Strength) -> 2781: Opts = #{<<"password_strength">> => Strength}, 2782: #{<<"modules">> => #{<<"mod_register">> => Opts}}. 2783: 2784: ip_access_register(Ip) -> 2785: Opts = #{<<"access">> => <<"register">>, 2786: <<"ip_access">> => 2787: [#{<<"address">> => <<"127.0.0.0/8">>, <<"policy">> => <<"allow">>}, 2788: #{<<"address">> => Ip, <<"policy">> => <<"deny">>}]}, 2789: #{<<"modules">> => #{<<"mod_register">> => Opts}}. 2790: 2791: invalid_ip_access_register() -> 2792: Opts = #{<<"access">> => <<"register">>, 2793: <<"ip_access">> => 2794: [#{<<"address">> => <<"127.0.0.0/8">>, <<"policy">> => <<"allawww">>}, 2795: #{<<"address">> => <<"8.8.8.8">>, <<"policy">> => <<"denyh">>}]}, 2796: #{<<"modules">> => #{<<"mod_register">> => Opts}}. 2797: 2798: invalid_ip_access_register_ipv6() -> 2799: Opts = #{<<"access">> => <<"register">>, 2800: <<"ip_access">> => 2801: [#{<<"address">> => <<"::1/129">>, <<"policy">> => <<"allow">>}]}, 2802: #{<<"modules">> => #{<<"mod_register">> => Opts}}. 2803: 2804: registration_watchers(JidBins) -> 2805: Opts = #{<<"registration_watchers">> => JidBins}, 2806: #{<<"modules">> => #{<<"mod_register">> => Opts}}. 2807: 2808: mod_roster(_Config) -> 2809: check_iqdisc_map(mod_roster), 2810: check_module_defaults(mod_roster), 2811: P = [modules, mod_roster], 2812: T = fun(Opts) -> #{<<"modules">> => #{<<"mod_roster">> => Opts}} end, 2813: ?cfgh(P ++ [versioning], true, 2814: T(#{<<"versioning">> => true})), 2815: ?cfgh(P ++ [store_current_id], true, 2816: T(#{<<"store_current_id">> => true})), 2817: ?cfgh(P ++ [backend], rdbms, 2818: T(#{<<"backend">> => <<"rdbms">>})), 2819: ?cfgh(P ++ [riak], config_parser_helper:default_config(P ++ [riak]), 2820: T(#{<<"backend">> => <<"riak">>})), 2821: ?cfgh(P ++ [riak, bucket_type], <<"my_type">>, 2822: T(#{<<"backend">> => <<"riak">>, <<"riak">> => #{<<"bucket_type">> => <<"my_type">>}})), 2823: ?cfgh(P ++ [riak, version_bucket_type], <<"my_versions">>, 2824: T(#{<<"backend">> => <<"riak">>, <<"riak">> => #{<<"version_bucket_type">> => <<"my_versions">>}})), 2825: 2826: ?errh(T(#{<<"versioning">> => 1})), 2827: ?errh(T(#{<<"store_current_id">> => 1})), 2828: ?errh(T(#{<<"backend">> => 1})), 2829: ?errh(T(#{<<"backend">> => <<"iloveyou">>})), 2830: ?errh(T(#{<<"riak">> => #{<<"version_bucket_type">> => 1}})), 2831: ?errh(T(#{<<"riak">> => #{<<"bucket_type">> => 1}})). 2832: 2833: mod_shared_roster_ldap(_Config) -> 2834: T = fun(Opts) -> #{<<"modules">> => #{<<"mod_shared_roster_ldap">> => Opts}} end, 2835: M = fun(Cfg) -> modopts(mod_shared_roster_ldap, Cfg) end, 2836: ?cfgh(M([{ldap_pool_tag, default}]), 2837: T(#{<<"ldap_pool_tag">> => <<"default">>})), 2838: ?cfgh(M([{ldap_base, "string"}]), 2839: T(#{<<"ldap_base">> => <<"string">>})), 2840: ?cfgh(M([{ldap_deref, never}]), 2841: T(#{<<"ldap_deref">> => <<"never">>})), 2842: %% Options: attributes 2843: ?cfgh(M([ {ldap_groupattr, "cn"}]), 2844: T(#{<<"ldap_groupattr">> => <<"cn">>})), 2845: ?cfgh(M([{ldap_groupdesc, "default"}]), 2846: T(#{<<"ldap_groupdesc">> => <<"default">>})), 2847: ?cfgh(M([{ldap_userdesc, "cn"}]), 2848: T(#{<<"ldap_userdesc">> => <<"cn">>})), 2849: ?cfgh(M([{ldap_useruid, "cn"}]), 2850: T(#{<<"ldap_useruid">> => <<"cn">>})), 2851: ?cfgh(M([{ldap_memberattr, "memberUid"}]), 2852: T(#{<<"ldap_memberattr">> => <<"memberUid">>})), 2853: ?cfgh(M([{ldap_memberattr_format, "%u"}]), 2854: T(#{<<"ldap_memberattr_format">> => <<"%u">>})), 2855: ?cfgh(M([{ldap_memberattr_format_re,""}]), 2856: T(#{<<"ldap_memberattr_format_re">> => <<"">>})), 2857: %% Options: parameters 2858: ?cfgh(M([ {ldap_auth_check, true}]), 2859: T(#{<<"ldap_auth_check">> => true})), 2860: ?cfgh(M([{ldap_user_cache_validity, 300}]), 2861: T(#{<<"ldap_user_cache_validity">> => 300})), 2862: ?cfgh(M([{ldap_group_cache_validity, 300}]), 2863: T(#{<<"ldap_group_cache_validity">> => 300})), 2864: ?cfgh(M([{ldap_user_cache_size, 300}]), 2865: T(#{<<"ldap_user_cache_size">> => 300})), 2866: ?cfgh(M([{ldap_group_cache_size, 300}]), 2867: T(#{<<"ldap_group_cache_size">> => 300})), 2868: %% Options: LDAP filters 2869: ?cfgh(M([{ldap_rfilter, "rfilter_test"}]), 2870: T(#{<<"ldap_rfilter">> => <<"rfilter_test">>})), 2871: ?cfgh(M([{ldap_gfilter, "gfilter_test"}]), 2872: T(#{<<"ldap_gfilter">> => <<"gfilter_test">>})), 2873: ?cfgh(M([{ldap_ufilter, "ufilter_test"}]), 2874: T(#{<<"ldap_ufilter">> => <<"ufilter_test">>})), 2875: ?cfgh(M([{ldap_filter, "filter_test"}]), 2876: T(#{<<"ldap_filter">> => <<"filter_test">>})), 2877: ?errh(T(#{<<"ldap_pool_tag">> => 1})), 2878: ?errh(T(#{<<"ldap_base">> => 1})), 2879: ?errh(T(#{<<"ldap_deref">> => 1})), 2880: %% Options: attributes 2881: ?errh(T(#{<<"ldap_groupattr">> => 1})), 2882: ?errh(T(#{<<"ldap_groupdesc">> => 1})), 2883: ?errh(T(#{<<"ldap_userdesc">> => 1})), 2884: ?errh(T(#{<<"ldap_useruid">> => 1})), 2885: ?errh(T(#{<<"ldap_memberattr">> => 1})), 2886: ?errh(T(#{<<"ldap_memberattr_format">> => 1})), 2887: ?errh(T(#{<<"ldap_memberattr_format_re">> => 1})), 2888: %% Options: parameters 2889: ?errh(T(#{<<"ldap_auth_check">> => 1})), 2890: ?errh(T(#{<<"ldap_user_cache_validity">> => -1})), 2891: ?errh(T(#{<<"ldap_group_cache_validity">> => -1})), 2892: ?errh(T(#{<<"ldap_user_cache_size">> => -1})), 2893: ?errh(T(#{<<"ldap_group_cache_size">> => -1})), 2894: %% Options: LDAP filters 2895: ?errh(T(#{<<"ldap_rfilter">> => 1})), 2896: ?errh(T(#{<<"ldap_gfilter">> => 1})), 2897: ?errh(T(#{<<"ldap_ufilter">> => 1})), 2898: ?errh(T(#{<<"ldap_filter">> => 1})). 2899: 2900: mod_sic(_Config) -> 2901: check_module_defaults(mod_sic), 2902: check_iqdisc_map(mod_sic). 2903: 2904: mod_stream_management(_Config) -> 2905: T = fun(Opts) -> #{<<"modules">> => #{<<"mod_stream_management">> => Opts}} end, 2906: M = fun(Cfg) -> modopts(mod_stream_management, Cfg) end, 2907: ?cfgh(M([{buffer_max, no_buffer}]), T(#{<<"buffer">> => false})), 2908: ?cfgh(M([{buffer_max, 10}]), T(#{<<"buffer_max">> => 10})), 2909: ?cfgh(M([{ack_freq, never}]), T(#{<<"ack">> => false})), 2910: ?cfgh(M([{ack_freq, 1}]), T(#{<<"ack_freq">> => 1})), 2911: ?cfgh(M([{resume_timeout, 600}]), T(#{<<"resume_timeout">> => 600})), 2912: ?cfgh(M([{backend, mnesia}]), 2913: T(#{<<"backend">> => <<"mnesia">>})), 2914: 2915: ?errh(T(#{<<"buffer">> => 0})), 2916: ?errh(T(#{<<"buffer_max">> => -1})), 2917: ?errh(T(#{<<"ack">> => <<"false">>})), 2918: ?errh(T(#{<<"ack_freq">> => 0})), 2919: ?errh(T(#{<<"resume_timeout">> => true})), 2920: ?errh(T(#{<<"backend">> => <<"iloveyou">>})). 2921: 2922: mod_stream_management_stale_h(_Config) -> 2923: T = fun(Opts) -> #{<<"modules">> => 2924: #{<<"mod_stream_management">> => #{<<"stale_h">> => Opts}}} end, 2925: M = fun(Cfg) -> modopts(mod_stream_management, [{stale_h, Cfg}]) end, 2926: ?cfgh(M([{enabled, true}]), T(#{<<"enabled">> => true})), 2927: ?cfgh(M([{stale_h_repeat_after, 1800}]), T(#{<<"repeat_after">> => 1800})), 2928: ?cfgh(M([{stale_h_geriatric, 3600}]), T(#{<<"geriatric">> => 3600})), 2929: 2930: ?errh(T(#{<<"enabled">> => <<"true">>})), 2931: ?errh(T(#{<<"repeat_after">> => -1})), 2932: ?errh(T(#{<<"geriatric">> => <<"one">>})). 2933: 2934: mod_time(_Config) -> 2935: check_iqdisc_map(mod_time), 2936: check_module_defaults(mod_time). 2937: 2938: mod_vcard(_Config) -> 2939: check_module_defaults(mod_vcard), 2940: check_iqdisc_map(mod_vcard), 2941: P = [modules, mod_vcard], 2942: T = fun(Opts) -> #{<<"modules">> => #{<<"mod_vcard">> => Opts}} end, 2943: ?cfgh(P ++ [iqdisc], one_queue, 2944: T(#{<<"iqdisc">> => #{<<"type">> => <<"one_queue">>}})), 2945: ?cfgh(P ++ [host], {prefix, <<"vjud.">>}, 2946: T(#{<<"host">> => <<"vjud.@HOST@">>})), 2947: ?cfgh(P ++ [host], {fqdn, <<"vjud.test">>}, 2948: T(#{<<"host">> => <<"vjud.test">>})), 2949: ?cfgh(P ++ [search], true, 2950: T(#{<<"search">> => true})), 2951: ?cfgh(P ++ [backend], mnesia, 2952: T(#{<<"backend">> => <<"mnesia">>})), 2953: ?cfgh(P ++ [matches], infinity, 2954: T(#{<<"matches">> => <<"infinity">>})), 2955: %% ldap 2956: ?cfgh(P ++ [ldap_pool_tag], default, 2957: T(#{<<"ldap_pool_tag">> => <<"default">>})), 2958: ?cfgh(P ++ [ldap_base], "ou=Users,dc=ejd,dc=com", 2959: T(#{<<"ldap_base">> => <<"ou=Users,dc=ejd,dc=com">>})), 2960: ?cfgh(P ++ [ldap_filter], <<"(&(objectClass=shadowAccount)(memberOf=Jabber Users))">>, 2961: T(#{<<"ldap_filter">> => <<"(&(objectClass=shadowAccount)(memberOf=Jabber Users))">>})), 2962: ?cfgh(P ++ [ldap_deref], never, 2963: T(#{<<"ldap_deref">> => <<"never">>})), 2964: ?cfgh(P ++ [ldap_search_operator], 'or', 2965: T(#{<<"ldap_search_operator">> => <<"or">>})), 2966: ?cfgh(P ++ [ldap_binary_search_fields], [<<"PHOTO">>], 2967: T(#{<<"ldap_binary_search_fields">> => [<<"PHOTO">>]})), 2968: %% riak 2969: ?cfgh(P ++ [riak, bucket_type], <<"vcard">>, 2970: T(#{<<"backend">> => <<"riak">>, <<"riak">> => #{<<"bucket_type">> => <<"vcard">>}})), 2971: ?cfgh(P ++ [riak, search_index], <<"vcard">>, 2972: T(#{<<"backend">> => <<"riak">>, <<"riak">> => #{<<"search_index">> => <<"vcard">>}})), 2973: 2974: ?errh(T(#{<<"host">> => 1})), 2975: ?errh(T(#{<<"host">> => <<"is this a host? no.">>})), 2976: ?errh(T(#{<<"host">> => [<<"invalid.sub@HOST@">>]})), 2977: ?errh(T(#{<<"host">> => [<<"invalid.sub.@HOST@.as.well">>]})), 2978: ?errh(T(#{<<"search">> => 1})), 2979: ?errh(T(#{<<"backend">> => <<"mememesia">>})), 2980: ?errh(T(#{<<"matches">> => -1})), 2981: %% ldap 2982: ?errh(T(#{<<"ldap_pool_tag">> => -1})), 2983: ?errh(T(#{<<"ldap_base">> => -1})), 2984: ?errh(T(#{<<"ldap_field">> => -1})), 2985: ?errh(T(#{<<"ldap_deref">> => <<"nevernever">>})), 2986: ?errh(T(#{<<"ldap_search_operator">> => <<"more">>})), 2987: ?errh(T(#{<<"ldap_binary_search_fields">> => [1]})), 2988: %% riak 2989: ?errh(T(#{<<"riak">> => #{<<"bucket_type">> => 1}})), 2990: ?errh(T(#{<<"riak">> => #{<<"search_index">> => 1}})). 2991: 2992: mod_vcard_ldap_uids(_Config) -> 2993: P = [modules, mod_vcard, ldap_uids], 2994: T = fun(Opts) -> #{<<"modules">> => 2995: #{<<"mod_vcard">> => #{<<"ldap_uids">> => Opts}}} end, 2996: RequiredOpts = #{<<"attr">> => <<"name">>}, 2997: ExpectedCfg = <<"name">>, 2998: ?cfgh(P, [], T([])), 2999: ?cfgh(P, [ExpectedCfg], T([RequiredOpts])), 3000: ?cfgh(P, [{<<"name">>, <<"%u@mail.example.org">>}], 3001: T([RequiredOpts#{<<"format">> => <<"%u@mail.example.org">>}])), 3002: ?cfgh(P, [{<<"name">>, <<"%u@mail.example.org">>}, ExpectedCfg], 3003: T([RequiredOpts#{<<"format">> => <<"%u@mail.example.org">>}, RequiredOpts])), 3004: [?errh(T([maps:remove(Key, RequiredOpts)])) || Key <- maps:keys(RequiredOpts)], 3005: ?errh(T(RequiredOpts#{<<"attr">> := 1})), 3006: ?errh(T(RequiredOpts#{<<"format">> => true})). 3007: 3008: mod_vcard_ldap_vcard_map(_Config) -> 3009: P = [modules, mod_vcard, ldap_vcard_map], 3010: T = fun(Opts) -> #{<<"modules">> => 3011: #{<<"mod_vcard">> => #{<<"ldap_vcard_map">> => Opts}}} end, 3012: RequiredOpts = #{<<"vcard_field">> => <<"FAMILY">>, 3013: <<"ldap_pattern">> => <<"%s">>, 3014: <<"ldap_field">> => <<"sn">>}, 3015: ExpectedCfg = {<<"FAMILY">>, <<"%s">>, [<<"sn">>]}, 3016: ?cfgh(P, [], T([])), 3017: ?cfgh(P, [ExpectedCfg], T([RequiredOpts])), 3018: [?errh(T([maps:remove(Key, RequiredOpts)])) || Key <- maps:keys(RequiredOpts)], 3019: ?errh(T(RequiredOpts#{<<"vcard_field">> := false})), 3020: ?errh(T(RequiredOpts#{<<"ldap_pattern">> := false})), 3021: ?errh(T(RequiredOpts#{<<"ldap_field">> := -1})). 3022: 3023: mod_vcard_ldap_search_fields(_Config) -> 3024: P = [modules, mod_vcard, ldap_search_fields], 3025: T = fun(Opts) -> #{<<"modules">> => 3026: #{<<"mod_vcard">> => #{<<"ldap_search_fields">> => Opts}}} end, 3027: RequiredOpts = #{<<"search_field">> => <<"Full Name">>, 3028: <<"ldap_field">> => <<"cn">>}, 3029: ExpectedCfg = {<<"Full Name">>, <<"cn">>}, 3030: ?cfgh(P, [], T([])), 3031: ?cfgh(P, [ExpectedCfg], T([RequiredOpts])), 3032: [?errh(T([maps:remove(Key, RequiredOpts)])) || Key <- maps:keys(RequiredOpts)], 3033: ?errh(T(RequiredOpts#{<<"search_field">> := false})), 3034: ?errh(T(RequiredOpts#{<<"ldap_field">> := -1})). 3035: 3036: mod_vcard_ldap_search_reported(_Config) -> 3037: P = [modules, mod_vcard, ldap_search_reported], 3038: T = fun(Opts) -> #{<<"modules">> => 3039: #{<<"mod_vcard">> => #{<<"ldap_search_reported">> => Opts}}} end, 3040: RequiredOpts = #{<<"search_field">> => <<"Full Name">>, 3041: <<"vcard_field">> => <<"FN">>}, 3042: ExpectedCfg = {<<"Full Name">>, <<"FN">>}, 3043: ?cfgh(P, [], T([])), 3044: ?cfgh(P, [ExpectedCfg], T([RequiredOpts])), 3045: [?errh(T([maps:remove(Key, RequiredOpts)])) || Key <- maps:keys(RequiredOpts)], 3046: ?errh(T(RequiredOpts#{<<"search_field">> := false})), 3047: ?errh(T(RequiredOpts#{<<"vcard_field">> := -1})). 3048: 3049: mod_version(_Config) -> 3050: check_module_defaults(mod_version), 3051: check_iqdisc_map(mod_version), 3052: P = [modules, mod_version], 3053: T = fun(Opts) -> #{<<"modules">> => #{<<"mod_version">> => Opts}} end, 3054: ?cfgh(P ++ [os_info], true, T(#{<<"os_info">> => true})), 3055: ?errh(T(#{<<"os_info">> => 1})). 3056: 3057: modules_without_config(_Config) -> 3058: ?cfgh(modopts(mod_amp, []), #{<<"modules">> => #{<<"mod_amp">> => #{}}}), 3059: ?errh(#{<<"modules">> => #{<<"mod_wrong">> => #{}}}). 3060: 3061: incorrect_module(_Config) -> 3062: ?errh(#{<<"modules">> => #{<<"mod_incorrect">> => #{}}}). 3063: 3064: %% Services 3065: 3066: service_admin_extra(_Config) -> 3067: T = fun(Opts) -> #{<<"services">> => #{<<"service_admin_extra">> => Opts}} end, 3068: ?cfg(servopts(service_admin_extra, [{submods, [node]}]), 3069: T(#{<<"submods">> => [<<"node">>]})), 3070: ?err(T(#{<<"submods">> => 1})), 3071: ?err(T(#{<<"submods">> => [1]})), 3072: ?err(T(#{<<"submods">> => [<<"nodejshaha">>]})), 3073: ok. 3074: 3075: service_mongoose_system_metrics(_Config) -> 3076: M = service_mongoose_system_metrics, 3077: T = fun(Opts) -> #{<<"services">> => #{<<"service_mongoose_system_metrics">> => Opts}} end, 3078: ?cfg(servopts(M, [{initial_report, 5000}]), 3079: T(#{<<"initial_report">> => 5000})), 3080: ?cfg(servopts(M, [{periodic_report, 5000}]), 3081: T(#{<<"periodic_report">> => 5000})), 3082: ?cfg(servopts(M, [{tracking_id, "UA-123456789"}]), 3083: T(#{<<"tracking_id">> => <<"UA-123456789">>})), 3084: ?cfg(servopts(M, [no_report]), 3085: T(#{<<"report">> => false})), 3086: %% error cases 3087: ?err(T(#{<<"initial_report">> => <<"forever">>})), 3088: ?err(T(#{<<"periodic_report">> => <<"forever">>})), 3089: ?err(T(#{<<"initial_report">> => -1})), 3090: ?err(T(#{<<"periodic_report">> => -1})), 3091: ?err(T(#{<<"tracking_id">> => 666})), 3092: ok. 3093: 3094: %% Helpers for module tests 3095: 3096: iqdisc({queues, Workers}) -> #{<<"type">> => <<"queues">>, <<"workers">> => Workers}; 3097: iqdisc(Atom) -> #{<<"type">> => atom_to_binary(Atom, utf8)}. 3098: 3099: iq_disc_generic(Module, RequiredOpts, Value) -> 3100: Opts = RequiredOpts#{<<"iqdisc">> => Value}, 3101: #{<<"modules">> => #{atom_to_binary(Module, utf8) => Opts}}. 3102: 3103: check_iqdisc(Module) -> 3104: check_iqdisc(Module, [], #{}). 3105: 3106: check_iqdisc(Module, ExpectedCfg, RequiredOpts) -> 3107: ?cfgh(modopts(Module, ExpectedCfg ++ [{iqdisc, {queues, 10}}]), 3108: iq_disc_generic(Module, RequiredOpts, iqdisc({queues, 10}))), 3109: ?cfgh(modopts(Module, ExpectedCfg ++ [{iqdisc, parallel}]), 3110: iq_disc_generic(Module, RequiredOpts, iqdisc(parallel))), 3111: ?errh(iq_disc_generic(Module, RequiredOpts, iqdisc(bad_haha))). 3112: 3113: check_iqdisc_map(Module) -> 3114: check_iqdisc_map(Module, #{}). 3115: 3116: check_iqdisc_map(Module, RequiredOpts) -> 3117: ?cfgh([modules, Module, iqdisc], {queues, 10}, 3118: iq_disc_generic(Module, RequiredOpts, iqdisc({queues, 10}))), 3119: ?cfgh([modules, Module, iqdisc], parallel, 3120: iq_disc_generic(Module, RequiredOpts, iqdisc(parallel))), 3121: ?errh(iq_disc_generic(Module, RequiredOpts, iqdisc(bad_haha))). 3122: 3123: check_module_defaults(Mod) -> 3124: ExpectedCfg = default_mod_config(Mod), 3125: ?cfgh([modules, Mod], ExpectedCfg, #{<<"modules">> => #{atom_to_binary(Mod) => #{}}}). 3126: 3127: modopts(Mod, Opts) -> 3128: [{[modules, Mod], Opts}]. 3129: 3130: servopts(Service, Opts) -> 3131: [{services, [{Service, Opts}]}]. 3132: 3133: %% helpers for 'listen' tests 3134: 3135: listener_config(Mod, Opts) -> 3136: [{listen, [listener(Mod, Opts)]}]. 3137: 3138: listener(Mod, Opts) -> 3139: maps:merge(#{port => 5222, 3140: ip_address => "0", 3141: ip_tuple => {0, 0, 0, 0}, 3142: ip_version => 4, 3143: proto => tcp, 3144: module => Mod}, Opts). 3145: 3146: http_handler_raw(Type, Opts) -> 3147: listen_raw(<<"http">>, #{<<"handlers">> => 3148: #{Type => 3149: [Opts#{<<"host">> => <<"localhost">>, 3150: <<"path">> => <<"/api">>}] 3151: }}). 3152: 3153: listen_raw(Type, Opts) -> 3154: #{<<"listen">> => #{Type => [Opts#{<<"port">> => 5222}]}}. 3155: 3156: %% helpers for 'auth' tests 3157: 3158: auth_ldap_raw(Opts) -> 3159: auth_raw(<<"ldap">>, Opts). 3160: 3161: auth_raw(Method, Opts) -> 3162: #{<<"auth">> => #{Method => Opts}}. 3163: 3164: %% helpers for 'pool' tests 3165: 3166: pool_config(PoolIn) -> 3167: Pool = merge_with_default_pool_config(PoolIn), 3168: [{outgoing_pools, [Pool]}]. 3169: 3170: pool_raw(Type, Tag, Opts) -> 3171: #{<<"outgoing_pools">> => #{Type => #{Tag => Opts}}}. 3172: 3173: pool_conn_raw(Type, Opts) -> 3174: #{<<"outgoing_pools">> => #{Type => #{<<"default">> => #{<<"connection">> => Opts}}}}. 3175: 3176: rdbms_opts() -> 3177: #{<<"driver">> => <<"pgsql">>, 3178: <<"host">> => <<"localhost">>, 3179: <<"database">> => <<"db">>, 3180: <<"username">> => <<"dbuser">>, 3181: <<"password">> => <<"secret">>}. 3182: 3183: %% helpers for 'access' tests 3184: 3185: access_raw(RuleName, RuleSpec) -> 3186: #{<<"access">> => #{RuleName => RuleSpec}}. 3187: 3188: %% helpers for 'host_config' tests 3189: 3190: host_config(Config) -> 3191: #{<<"host_config">> => [Config#{<<"host_type">> => ?HOST}]}. 3192: 3193: %% helpers for parsing 3194: 3195: -spec parse(map()) -> [mongoose_config_parser_toml:config()]. 3196: parse(M0) -> 3197: %% As 'hosts' (or 'host_types') and 'default_server_domain' options are mandatory, 3198: %% this function inserts them with dummy values if they are missing. 3199: %% To prevent the insertion, add a 'without' option to the map, e.g. without => [<<"hosts">>] 3200: %% The resulting map is then passed to the TOML config parser. 3201: M = maybe_insert_dummy_domain(M0), 3202: mongoose_config_parser:get_opts(mongoose_config_parser_toml:process(M)). 3203: 3204: maybe_insert_dummy_domain(M) -> 3205: DummyGenM = #{<<"default_server_domain">> => ?HOST, 3206: <<"hosts">> => [?HOST]}, 3207: {FilteredGenM, RawConfig} = case maps:take(without, M) of 3208: {Keys, Cfg} -> {maps:without(Keys, DummyGenM), Cfg}; 3209: error -> {DummyGenM, M} 3210: end, 3211: OldGenM = maps:get(<<"general">>, RawConfig, #{}), 3212: NewGenM = maps:merge(FilteredGenM, OldGenM), 3213: RawConfig#{<<"general">> => NewGenM}. 3214: 3215: %% helpers for testing individual options 3216: 3217: -spec host_opts([{key_prefix(), mongoose_config:value()}]) -> 3218: [{mongoose_config:key() | mongoose_config:key_path(), mongoose_config:value()}]. 3219: host_opts(ExpectedOptions) -> 3220: lists:map(fun({Key, Value}) -> {host_key(Key), Value} end, ExpectedOptions). 3221: 3222: %% @doc Build full per-host config key for host-or-global options 3223: -spec host_key(top_level_key_prefix()) -> mongoose_config:key(); 3224: (key_path_prefix()) -> mongoose_config:key_path(). 3225: host_key([TopKey | Rest]) when is_atom(TopKey) -> 3226: [{TopKey, ?HOST} | Rest]; 3227: host_key(Key) when is_atom(Key) -> 3228: {Key, ?HOST}. 3229: 3230: -spec assert_options([{mongoose_config:key() | mongoose_config:key_path(), mongoose_config:value()}], 3231: [mongoose_config_parser_toml:config()]) -> any(). 3232: assert_options(ExpectedOptions, Config) -> 3233: lists:foreach(fun({Key, Value}) -> assert_option(Key, Value, Config) end, ExpectedOptions). 3234: 3235: -spec assert_option(mongoose_config:key() | mongoose_config:key_path(), mongoose_config:value(), 3236: [mongoose_config_parser_toml:config()]) -> any(). 3237: assert_option(KeyPath, Value, Config) when is_list(KeyPath) -> 3238: compare_nodes(KeyPath, Value, get_config_value(KeyPath, Config)); 3239: assert_option(Key, Value, Config) -> 3240: assert_option([Key], Value, Config). 3241: 3242: -spec get_config_value(mongoose_config:key_path(), [mongoose_config_parser_toml:config()]) -> 3243: mongoose_config:value(). 3244: get_config_value([TopKey | Rest], Config) -> 3245: case lists:keyfind(TopKey, 1, Config) of 3246: false -> ct:fail({"option not found", TopKey, Config}); 3247: {_, TopValue} -> lists:foldl(fun maps:get/2, TopValue, Rest) 3248: end. 3249: 3250: -spec assert_error([mongoose_config_parser_toml:config()]) -> 3251: [mongoose_config_parser_toml:config_error()]. 3252: assert_error(Config) -> 3253: case extract_errors(Config) of 3254: [] -> 3255: ct:fail({"Expected errors but found none", Config}); 3256: Errors -> 3257: [?assertMatch(#{class := error, 3258: what := toml_processing_failed}, Error) || Error <- Errors], 3259: Errors 3260: end. 3261: 3262: %% helpers for file tests 3263: 3264: test_config_file(Config, File) -> 3265: OptionsPath = ejabberd_helper:data(Config, File ++ ".options"), 3266: ExpectedOpts = config_parser_helper:options(File), 3267: 3268: TOMLPath = ejabberd_helper:data(Config, File ++ ".toml"), 3269: State = mongoose_config_parser:parse_file(TOMLPath), 3270: TOMLOpts = mongoose_config_parser:get_opts(State), 3271: 3272: %% Save the parsed TOML options 3273: %% - for debugging 3274: %% - to update tests after a config change - always check the diff! 3275: save_opts(OptionsPath ++ ".parsed", TOMLOpts), 3276: compare_config(ExpectedOpts, TOMLOpts). 3277: 3278: save_opts(Path, Opts) -> 3279: FormattedOpts = [io_lib:format("~p.~n", [Opt]) || Opt <- lists:sort(Opts)], 3280: file:write_file(Path, FormattedOpts). 3281: 3282: compare_config(C1, C2) -> 3283: compare_unordered_lists(C1, C2, fun handle_config_option/2). 3284: 3285: handle_config_option({K1, V1}, {K2, V2}) -> 3286: ?eq(K1, K2), 3287: compare_nodes([K1], V1, V2); 3288: handle_config_option(Opt1, Opt2) -> 3289: ?eq(Opt1, Opt2). 3290: 3291: %% Comparisons for config options that have paths (top-level or nested in maps) 3292: 3293: -spec compare_nodes(mongoose_config:key_path(), mongoose_config:value(), mongoose_config:value()) -> 3294: any(). 3295: compare_nodes([listen], V1, V2) -> 3296: compare_unordered_lists(V1, V2, fun handle_listener/2); 3297: compare_nodes([outgoing_pools], V1, V2) -> 3298: compare_unordered_lists(V1, V2, fun handle_conn_pool/2); 3299: compare_nodes([services], V1, V2) -> 3300: compare_unordered_lists(V1, V2, fun handle_item_with_opts/2); 3301: compare_nodes([{auth_method, _}], V1, V2) when is_atom(V1) -> 3302: ?eq([V1], V2); 3303: compare_nodes([{s2s_addr, _}], {_, _, _, _} = IP1, IP2) -> 3304: ?eq(inet:ntoa(IP1), IP2); 3305: compare_nodes(Node, V1, V2) when is_map(V1), is_map(V2) -> 3306: compare_maps(V1, V2, fun({K1, MV1}, {K2, MV2}) -> 3307: ?eq(K1, K2), 3308: compare_nodes(Node ++ [K1], MV1, MV2) 3309: end); 3310: compare_nodes([{modules, _}, _Module], V1, V2) -> 3311: compare_unordered_lists(V1, V2, fun handle_module_options/2); 3312: compare_nodes(Node, V1, V2) -> 3313: ?eq({Node, V1}, {Node, V2}). 3314: 3315: %% Comparisons of internal config option parts 3316: 3317: handle_listener(V1, V2) -> 3318: compare_maps(V1, V2, fun handle_listener_option/2). 3319: 3320: handle_listener_option({tls, O1}, {tls, O2}) -> 3321: compare_unordered_lists(O1, O2); 3322: handle_listener_option({ssl, O1}, {ssl, O2}) -> 3323: compare_unordered_lists(O1, O2); 3324: handle_listener_option({modules, M1}, {modules, M2}) -> 3325: compare_unordered_lists(M1, M2, fun handle_listener_module/2); 3326: handle_listener_option({transport_options, O1}, {transport_options, O2}) -> 3327: compare_unordered_lists(O1, O2); 3328: handle_listener_option(V1, V2) -> ?eq(V1, V2). 3329: 3330: handle_listener_module({H1, P1, M1}, M2) -> 3331: handle_listener_module({H1, P1, M1, []}, M2); 3332: handle_listener_module({H1, P1, M1, O1}, {H2, P2, M2, O2}) -> 3333: ?eq(H1, H2), 3334: ?eq(P1, P2), 3335: ?eq(M1, M2), 3336: compare_listener_module_options(M1, O1, O2). 3337: 3338: compare_listener_module_options(mod_websockets, L1, L2) -> 3339: E1 = proplists:get_value(ejabberd_service, L1, []), 3340: E2 = proplists:get_value(ejabberd_service, L2, []), 3341: T1 = proplists:delete(ejabberd_service, L1), 3342: T2 = proplists:delete(ejabberd_service, L2), 3343: compare_unordered_lists(E1, E2), 3344: compare_unordered_lists(T1, T2); 3345: compare_listener_module_options(_, O1, O2) -> 3346: ?eq(O1, O2). 3347: 3348: handle_item_with_opts({M1, O1}, {M2, O2}) -> 3349: ?eq(M1, M2), 3350: compare_unordered_lists(O1, O2). 3351: 3352: handle_conn_pool(#{type := Type1, scope := Scope1, tag := Tag1, opts := POpts1, conn_opts := COpts1}, 3353: #{type := Type2, scope := Scope2, tag := Tag2, opts := POpts2, conn_opts := COpts2}) -> 3354: ?eq(Type1, Type2), 3355: ?eq(Scope1, Scope2), 3356: ?eq(Tag1, Tag2), 3357: compare_maps(POpts1, POpts2), 3358: compare_maps(COpts1, COpts2, fun handle_conn_opt/2). 3359: 3360: handle_conn_opt({server, {D1, H1, DB1, U1, P1, O1}}, 3361: {server, {D2, H2, DB2, U2, P2, O2}}) -> 3362: ?eq(D1, D2), 3363: ?eq(H1, H2), 3364: ?eq(DB1, DB2), 3365: ?eq(U1, U2), 3366: ?eq(P1, P2), 3367: compare_unordered_lists(O1, O2, fun handle_db_server_opt/2); 3368: handle_conn_opt({http_opts, O1}, {http_opts, O2}) -> 3369: compare_unordered_lists(O1, O2); 3370: handle_conn_opt(V1, V2) -> ?eq(V1, V2). 3371: 3372: handle_db_server_opt({ssl_opts, O1}, {ssl_opts, O2}) -> 3373: compare_unordered_lists(O1, O2); 3374: handle_db_server_opt(V1, V2) -> ?eq(V1, V2). 3375: 3376: handle_module_options({configs, [Configs1]}, {configs, [Configs2]}) -> 3377: compare_unordered_lists(Configs1, Configs2, fun handle_module_options/2); 3378: handle_module_options({Name, Opts = [{_, _}|_]}, {Name2, Opts2 = [{_, _}|_]}) -> 3379: ?eq(Name, Name2), 3380: compare_unordered_lists(Opts, Opts2, fun handle_module_options/2); 3381: handle_module_options(V1, V2) -> 3382: ?eq(V1, V2). 3383: 3384: %% Generic assertions, use the 'F' handler for any custom cases 3385: compare_unordered_lists(L1, L2) -> 3386: compare_unordered_lists(L1, L2, fun(V1, V2) -> ?eq(V1, V2) end). 3387: 3388: compare_unordered_lists(L1, L2, F) -> 3389: SL1 = lists:sort(L1), 3390: SL2 = lists:sort(L2), 3391: compare_ordered_lists(SL1, SL2, F). 3392: 3393: compare_ordered_lists([H1|T1], [H1|T2], F) -> 3394: compare_ordered_lists(T1, T2, F); 3395: compare_ordered_lists([H1|T1] = L1, [H2|T2] = L2, F) -> 3396: try F(H1, H2) 3397: catch error:R:S -> 3398: ct:fail({"Failed to compare ordered lists", L1, L2, R, S}) 3399: end, 3400: compare_ordered_lists(T1, T2, F); 3401: compare_ordered_lists([], [], _) -> 3402: ok. 3403: 3404: compare_maps(M1, M2) -> 3405: compare_maps(M1, M2, fun(V1, V2) -> ?eq(V1, V2) end). 3406: 3407: compare_maps(M1, M2, F) -> 3408: compare_unordered_lists(maps:to_list(M1), maps:to_list(M2), F). 3409: 3410: create_files(Config) -> 3411: %% The files must exist for validation to pass 3412: Root = small_path_helper:repo_dir(Config), 3413: file:make_dir("priv"), 3414: [ensure_copied(filename:join(Root, From), To) || {From, To} <- files_to_copy()], 3415: ok = file:write_file("priv/access_psk", ""), 3416: ok = file:write_file("priv/provision_psk", ""), 3417: ok = filelib:ensure_dir("www/muc/dummy"). 3418: 3419: ensure_copied(From, To) -> 3420: case file:copy(From, To) of 3421: {ok,_} -> 3422: ok; 3423: Other -> 3424: error(#{what => ensure_copied_failed, from => From, to => To, 3425: reason => Other}) 3426: end. 3427: 3428: files_to_copy() -> 3429: [{"tools/ssl/mongooseim/privkey.pem", "priv/dc1.pem"}, 3430: {"tools/ssl/mongooseim/cert.pem", "priv/cert.pem"}, 3431: {"tools/ssl/mongooseim/dh_server.pem", "priv/dh.pem"}, 3432: {"tools/ssl/mongooseim/server.pem", "priv/server.pem"}, 3433: {"tools/ssl/ca/cacert.pem", "priv/ca.pem"}].