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