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