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