diff options
| author | Jean-Sébastien Pédron <jean-sebastien.pedron@dumbbell.fr> | 2016-05-27 10:41:32 +0200 |
|---|---|---|
| committer | Jean-Sébastien Pédron <jean-sebastien.pedron@dumbbell.fr> | 2016-05-27 10:41:32 +0200 |
| commit | c8bdf334f626e6b5de7837234be8c541396fe2d4 (patch) | |
| tree | 9f78f7c6888debad8a64ad3479c6a31ce5c641f7 | |
| parent | dc941fed07171ecbc2a356e095c6e45f8af65de6 (diff) | |
| download | rabbitmq-server-git-c8bdf334f626e6b5de7837234be8c541396fe2d4.tar.gz | |
Switch testsuite to common_test, part #4
This is a follow-up to the previous merge of the stable branch. It
covers tests which were modified or added only to the master branch.
References #725.
[#116526487]
| -rw-r--r-- | test/channel_interceptor_SUITE.erl | 113 | ||||
| -rw-r--r-- | test/channel_operation_timeout_test_queue.erl | 6 | ||||
| -rw-r--r-- | test/config_schema_SUITE.erl | 153 | ||||
| -rw-r--r-- | test/config_schema_SUITE_data/certs/cacert.pem | 1 | ||||
| -rw-r--r-- | test/config_schema_SUITE_data/certs/cert.pem | 1 | ||||
| -rw-r--r-- | test/config_schema_SUITE_data/certs/key.pem | 1 | ||||
| -rw-r--r-- | test/config_schema_SUITE_data/rabbit-mgmt/access.log | 0 | ||||
| -rw-r--r-- | test/config_schema_SUITE_data/snippets.config | 714 | ||||
| -rw-r--r-- | test/dummy_interceptor.erl | 26 | ||||
| -rw-r--r-- | test/plugin_versioning_SUITE.erl | 177 | ||||
| -rw-r--r-- | test/unit_SUITE.erl | 3 | ||||
| -rw-r--r-- | test/unit_inbroker_SUITE.erl | 272 |
12 files changed, 1316 insertions, 151 deletions
diff --git a/test/channel_interceptor_SUITE.erl b/test/channel_interceptor_SUITE.erl new file mode 100644 index 0000000000..0e4948ea3c --- /dev/null +++ b/test/channel_interceptor_SUITE.erl @@ -0,0 +1,113 @@ +%% The contents of this file are subject to the Mozilla Public License +%% Version 1.1 (the "License"); you may not use this file except in +%% compliance with the License. You may obtain a copy of the License at +%% http://www.mozilla.org/MPL/ +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +%% License for the specific language governing rights and limitations +%% under the License. +%% +%% The Original Code is RabbitMQ. +%% +%% The Initial Developer of the Original Code is GoPivotal, Inc. +%% Copyright (c) 2016 Pivotal Software, Inc. All rights reserved. +%% + +-module(channel_interceptor_SUITE). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("amqp_client/include/amqp_client.hrl"). + +-compile(export_all). + +all() -> + [ + {group, non_parallel_tests} + ]. + +groups() -> + [ + {non_parallel_tests, [], [ + register_interceptor + ]} + ]. + +%% ------------------------------------------------------------------- +%% Testsuite setup/teardown. +%% ------------------------------------------------------------------- + +init_per_suite(Config) -> + rabbit_ct_helpers:log_environment(), + rabbit_ct_helpers:run_setup_steps(Config). + +end_per_suite(Config) -> + rabbit_ct_helpers:run_teardown_steps(Config). + +init_per_group(_, Config) -> + Config. + +end_per_group(_, Config) -> + Config. + +init_per_testcase(Testcase, Config) -> + rabbit_ct_helpers:testcase_started(Config, Testcase), + Config1 = rabbit_ct_helpers:set_config(Config, [ + {rmq_nodename_suffix, Testcase} + ]), + rabbit_ct_helpers:run_steps(Config1, + rabbit_ct_broker_helpers:setup_steps() ++ + rabbit_ct_client_helpers:setup_steps()). + +end_per_testcase(Testcase, Config) -> + Config1 = rabbit_ct_helpers:run_steps(Config, + rabbit_ct_client_helpers:teardown_steps() ++ + rabbit_ct_broker_helpers:teardown_steps()), + rabbit_ct_helpers:testcase_finished(Config1, Testcase). + +%% ------------------------------------------------------------------- +%% Testcases. +%% ------------------------------------------------------------------- + +register_interceptor(Config) -> + passed = rabbit_ct_broker_helpers:rpc(Config, 0, + ?MODULE, register_interceptor1, [Config]). + +register_interceptor1(Config) -> + PredefinedChannels = rabbit_channel:list(), + + Ch1 = rabbit_ct_client_helpers:open_channel(Config, 0), + + QName = <<"register_interceptor-q">>, + amqp_channel:call(Ch1, #'queue.declare'{queue = QName}), + + [ChannelProc] = rabbit_channel:list() -- PredefinedChannels, + + [{interceptors, []}] = rabbit_channel:info(ChannelProc, [interceptors]), + + check_send_receive(Ch1, QName, <<"bar">>, <<"bar">>), + + ok = rabbit_registry:register(channel_interceptor, + <<"dummy interceptor">>, + dummy_interceptor), + [{interceptors, [{dummy_interceptor, undefined}]}] = + rabbit_channel:info(ChannelProc, [interceptors]), + + check_send_receive(Ch1, QName, <<"bar">>, <<"">>), + + ok = rabbit_registry:unregister(channel_interceptor, + <<"dummy interceptor">>), + [{interceptors, []}] = rabbit_channel:info(ChannelProc, [interceptors]), + + check_send_receive(Ch1, QName, <<"bar">>, <<"bar">>), + passed. + + +check_send_receive(Ch1, QName, Send, Receive) -> + amqp_channel:call(Ch1, + #'basic.publish'{routing_key = QName}, + #amqp_msg{payload = Send}), + + {#'basic.get_ok'{}, #amqp_msg{payload = Receive}} = + amqp_channel:call(Ch1, #'basic.get'{queue = QName, + no_ack = true}). diff --git a/test/channel_operation_timeout_test_queue.erl b/test/channel_operation_timeout_test_queue.erl index 55cd5f42fa..87c33bea87 100644 --- a/test/channel_operation_timeout_test_queue.erl +++ b/test/channel_operation_timeout_test_queue.erl @@ -563,7 +563,7 @@ update_rates(State = #vqstate{ in_counter = InCount, ack_in = AckInRate, ack_out = AckOutRate, timestamp = TS }}) -> - Now = time_compat:monotonic_time(), + Now = erlang:monotonic_time(), Rates = #rates { in = update_rate(Now, TS, InCount, InRate), out = update_rate(Now, TS, OutCount, OutRate), @@ -578,7 +578,7 @@ update_rates(State = #vqstate{ in_counter = InCount, rates = Rates }. update_rate(Now, TS, Count, Rate) -> - Time = time_compat:convert_time_unit(Now - TS, native, micro_seconds) / + Time = erlang:convert_time_unit(Now - TS, native, micro_seconds) / ?MICROS_PER_SECOND, if Time == 0 -> Rate; @@ -1076,7 +1076,7 @@ init(IsDurable, IndexState, DeltaCount, DeltaBytes, Terms, count = DeltaCount1, end_seq_id = NextSeqId }) end, - Now = time_compat:monotonic_time(), + Now = erlang:monotonic_time(), IoBatchSize = rabbit_misc:get_env(rabbit, msg_store_io_batch_size, ?IO_BATCH_SIZE), diff --git a/test/config_schema_SUITE.erl b/test/config_schema_SUITE.erl new file mode 100644 index 0000000000..b1362aac28 --- /dev/null +++ b/test/config_schema_SUITE.erl @@ -0,0 +1,153 @@ +%% The contents of this file are subject to the Mozilla Public License +%% Version 1.1 (the "License"); you may not use this file except in +%% compliance with the License. You may obtain a copy of the License at +%% http://www.mozilla.org/MPL/ +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +%% License for the specific language governing rights and limitations +%% under the License. +%% +%% The Original Code is RabbitMQ. +%% +%% The Initial Developer of the Original Code is GoPivotal, Inc. +%% Copyright (c) 2016 Pivotal Software, Inc. All rights reserved. +%% + +-module(config_schema_SUITE). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("amqp_client/include/amqp_client.hrl"). + +-compile(export_all). + +all() -> + [ + {group, non_parallel_tests} + ]. + +groups() -> + [ + {non_parallel_tests, [], [ + run_snippets + ]} + ]. + +%% ------------------------------------------------------------------- +%% Testsuite setup/teardown. +%% ------------------------------------------------------------------- + +init_per_suite(Config) -> + rabbit_ct_helpers:log_environment(), + rabbit_ct_helpers:run_setup_steps(Config). + +end_per_suite(Config) -> + rabbit_ct_helpers:run_teardown_steps(Config). + +init_per_group(_, Config) -> + Config. + +end_per_group(_, Config) -> + Config. + +init_per_testcase(Testcase, Config) -> + rabbit_ct_helpers:testcase_started(Config, Testcase), + Config1 = rabbit_ct_helpers:set_config(Config, [ + {rmq_nodename_suffix, Testcase} + ]), + Config2 = case Testcase of + run_snippets -> + SchemaDir = filename:join(?config(priv_dir, Config1), "schema"), + ResultsDir = filename:join(?config(priv_dir, Config1), "results"), + Snippets = filename:join(?config(data_dir, Config1), + "snippets.config"), + ok = file:make_dir(SchemaDir), + ok = file:make_dir(ResultsDir), + rabbit_ct_helpers:set_config(Config1, [ + {schema_dir, SchemaDir}, + {results_dir, ResultsDir}, + {conf_snippets, Snippets} + ]) + end, + rabbit_ct_helpers:run_steps(Config2, + rabbit_ct_broker_helpers:setup_steps() ++ + rabbit_ct_client_helpers:setup_steps()). + +end_per_testcase(Testcase, Config) -> + Config1 = rabbit_ct_helpers:run_steps(Config, + rabbit_ct_client_helpers:teardown_steps() ++ + rabbit_ct_broker_helpers:teardown_steps()), + rabbit_ct_helpers:testcase_finished(Config1, Testcase). + +%% ------------------------------------------------------------------- +%% Testcases. +%% ------------------------------------------------------------------- + +run_snippets(Config) -> + passed = rabbit_ct_broker_helpers:rpc(Config, 0, + ?MODULE, run_snippets1, [Config]). + +run_snippets1(Config) -> + prepare_plugin_schemas(Config), + {ok, [Snippets]} = file:consult(?config(conf_snippets, Config)), + lists:map( + fun({N, S, C, P}) -> ok = test_snippet(Config, {integer_to_list(N), S, []}, C, P); + ({N, S, A, C, P}) -> ok = test_snippet(Config, {integer_to_list(N), S, A}, C, P) + end, + Snippets), + passed. + +test_snippet(Config, Snippet, Expected, _Plugins) -> + {ConfFile, AdvancedFile} = write_snippet(Config, Snippet), + {ok, GeneratedFile} = generate_config(Config, ConfFile, AdvancedFile), + {ok, [Generated]} = file:consult(GeneratedFile), + Gen = deepsort(Generated), + Exp = deepsort(Expected), + case Exp of + Gen -> ok; + _ -> + error({config_mismatch, Snippet, Exp, Gen}) + end. + +write_snippet(Config, {Name, Conf, Advanced}) -> + ResultsDir = ?config(results_dir, Config), + file:make_dir(filename:join(ResultsDir, Name)), + ConfFile = filename:join([ResultsDir, Name, "config.conf"]), + AdvancedFile = filename:join([ResultsDir, Name, "advanced.config"]), + + file:write_file(ConfFile, Conf), + rabbit_file:write_term_file(AdvancedFile, [Advanced]), + {ConfFile, AdvancedFile}. + +generate_config(Config, ConfFile, AdvancedFile) -> + SchemaDir = ?config(schema_dir, Config), + ResultsDir = ?config(results_dir, Config), + Rabbitmqctl = ?config(rabbitmqctl_cmd, Config), + ScriptDir = filename:dirname(Rabbitmqctl), + ct:pal("ConfFile=~p ScriptDir=~p SchemaDir=~p AdvancedFile=~p", [ConfFile, ScriptDir, SchemaDir, AdvancedFile]), + rabbit_config:generate_config_file([ConfFile], ResultsDir, ScriptDir, + SchemaDir, AdvancedFile). + +prepare_plugin_schemas(Config) -> + SchemaDir = ?config(schema_dir, Config), + DepsDir = ?config(erlang_mk_depsdir, Config), + Files = filelib:wildcard( + filename:join(DepsDir, "*/priv/schema/*.schema")), + [ file:copy(File, filename:join([SchemaDir, filename:basename(File)])) + || File <- Files ]. + +deepsort(List) -> + case is_proplist(List) of + true -> + lists:keysort(1, lists:map(fun({K, V}) -> {K, deepsort(V)}; + (V) -> V end, + List)); + false -> + case is_list(List) of + true -> lists:sort(List); + false -> List + end + end. + +is_proplist([{_Key, _Val}|_] = List) -> lists:all(fun({_K, _V}) -> true; (_) -> false end, List); +is_proplist(_) -> false. diff --git a/test/config_schema_SUITE_data/certs/cacert.pem b/test/config_schema_SUITE_data/certs/cacert.pem new file mode 100644 index 0000000000..eaf6b67806 --- /dev/null +++ b/test/config_schema_SUITE_data/certs/cacert.pem @@ -0,0 +1 @@ +I'm not a certificate diff --git a/test/config_schema_SUITE_data/certs/cert.pem b/test/config_schema_SUITE_data/certs/cert.pem new file mode 100644 index 0000000000..eaf6b67806 --- /dev/null +++ b/test/config_schema_SUITE_data/certs/cert.pem @@ -0,0 +1 @@ +I'm not a certificate diff --git a/test/config_schema_SUITE_data/certs/key.pem b/test/config_schema_SUITE_data/certs/key.pem new file mode 100644 index 0000000000..eaf6b67806 --- /dev/null +++ b/test/config_schema_SUITE_data/certs/key.pem @@ -0,0 +1 @@ +I'm not a certificate diff --git a/test/config_schema_SUITE_data/rabbit-mgmt/access.log b/test/config_schema_SUITE_data/rabbit-mgmt/access.log new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/config_schema_SUITE_data/rabbit-mgmt/access.log diff --git a/test/config_schema_SUITE_data/snippets.config b/test/config_schema_SUITE_data/snippets.config new file mode 100644 index 0000000000..22c9f2b7cd --- /dev/null +++ b/test/config_schema_SUITE_data/snippets.config @@ -0,0 +1,714 @@ +[ +{1, +"auth_backends.1 = internal", +[{rabbit, [{auth_backends, [rabbit_auth_backend_internal]}]}],[]} +, +{2, +"auth_backends.1 = ldap", +[{rabbit, [{auth_backends, [rabbit_auth_backend_ldap]}]}],[]} +, + +{3, +"auth_backends.1 = ldap +auth_backends.2 = internal", + +[{rabbit, [ + {auth_backends, [rabbit_auth_backend_ldap, rabbit_auth_backend_internal]} + ] + }],[]} + +, + +{4, +"auth_backends.1 = ldap +# uses module name instead of a short alias, \"http\" +auth_backends.2 = rabbit_auth_backend_http", + +[{rabbit, [{auth_backends, [rabbit_auth_backend_ldap, rabbit_auth_backend_http]}]}],[]} + +, + +{5, +"auth_backends.1.authn = internal +# uses module name because this backend is from a 3rd party +auth_backends.1.authz = rabbit_auth_backend_ip_range", +[{rabbit, [{auth_backends, [{rabbit_auth_backend_internal, rabbit_auth_backend_ip_range}]}]}],[]} +, +{6, +"auth_backends.1.authn = ldap +auth_backends.1.authz = internal", +[{rabbit, [{auth_backends, [{rabbit_auth_backend_ldap, rabbit_auth_backend_internal}]}]}],[]} +, + +{7, +"auth_backends.1.authn = ldap +auth_backends.1.authz = internal +auth_backends.2 = internal", +[{rabbit, [ + {auth_backends, [{rabbit_auth_backend_ldap, rabbit_auth_backend_internal}, + rabbit_auth_backend_internal]} + ] + }],[]} +, + + +{8, +"ssl_options.cacertfile = test/config_schema_SUITE_data/certs/cacert.pem +ssl_options.certfile = test/config_schema_SUITE_data/certs/cert.pem +ssl_options.keyfile = test/config_schema_SUITE_data/certs/key.pem +ssl_options.verify = verify_peer +ssl_options.fail_if_no_peer_cert = true", +[ + {rabbit, [{ssl_options, [{cacertfile, "test/config_schema_SUITE_data/certs/cacert.pem"}, + {certfile, "test/config_schema_SUITE_data/certs/cert.pem"}, + {keyfile, "test/config_schema_SUITE_data/certs/key.pem"}, + {verify, verify_peer}, + {fail_if_no_peer_cert, true}]} + ]}],[]} +, + +{9, +"listeners.tcp.default = 5673", +[{rabbit, [{tcp_listeners, [5673]}]}],[]} +, + +{10, +"listeners.ssl = none", +[{rabbit, [{ssl_listeners, []}]}],[]} +, +{11, +"num_acceptors.ssl = 1", +[{rabbit, [{num_ssl_acceptors, 1}]}],[]} +, +{12, +"default_user = guest +default_pass = guest +default_user_tags.administrator = true +default_permissions.configure = .* +default_permissions.read = .* +default_permissions.write = .*", +[{rabbit, [ +{default_user, <<"guest">>}, +{default_pass, <<"guest">>}, +{default_user_tags, [administrator]}, +{default_permissions, [<<".*">>, <<".*">>, <<".*">>]}]}],[]} +, +{13, +"cluster_nodes.disc.1 = rabbit@hostname1 +cluster_nodes.disc.2 = rabbit@hostname2", +[{rabbit, [ + {cluster_nodes, {[rabbit@hostname2,rabbit@hostname1], disc}} +]}],[]} +, +{14, +"tcp_listen_options.backlog = 128 +tcp_listen_options.nodelay = true +tcp_listen_options.exit_on_close = false", +[{rabbit, [{tcp_listen_options, [{backlog, 128}, +{nodelay, true}, +{exit_on_close, false}]}]}],[]} +, +{15, +"auth_backends.1.authn = ldap +auth_backends.1.authz = internal +auth_backends.2 = internal", +[{rabbit,[{auth_backends, [{rabbit_auth_backend_ldap, rabbit_auth_backend_internal}, + rabbit_auth_backend_internal]}]}],[]} +, +{16, +"rabbitmq_auth_backend_ldap.servers.1 = some_server + rabbitmq_auth_backend_ldap.servers.2 = some_other_server", +[{rabbitmq_auth_backend_ldap, [{servers, ["some_server", "some_other_server"]}]}], +[rabbitmq_auth_backend_ldap]} +, +{17, +"rabbitmq_auth_backend_ldap.dn_lookup_attribute = userPrincipalName +rabbitmq_auth_backend_ldap.dn_lookup_base = DC=gopivotal,DC=com +rabbitmq_auth_backend_ldap.dn_lookup_bind = as_user", +[{rabbitmq_auth_backend_ldap, [{dn_lookup_attribute, "userPrincipalName"}, +{dn_lookup_base, "DC=gopivotal,DC=com"}, +{dn_lookup_bind, as_user}]}], +[rabbitmq_auth_backend_ldap]} +, +{18, +"rabbitmq_auth_backend_ldap.dn_lookup_bind.user_dn = username +rabbitmq_auth_backend_ldap.dn_lookup_bind.password = password", +[{rabbitmq_auth_backend_ldap, [ +{dn_lookup_bind, {"username", "password"}}]}], +[rabbitmq_auth_backend_ldap]} +, +{19, +"rabbitmq_auth_backend_ldap.other_bind = anon", +[{rabbitmq_auth_backend_ldap, [{other_bind, anon}]}], +[rabbitmq_auth_backend_ldap]} +, +{20, +"rabbitmq_auth_backend_ldap.other_bind = as_user", +[{rabbitmq_auth_backend_ldap, [{other_bind, as_user}]}], +[rabbitmq_auth_backend_ldap]} +, +{21, +"rabbitmq_auth_backend_ldap.other_bind.user_dn = username +rabbitmq_auth_backend_ldap.other_bind.password = password", +[{rabbitmq_auth_backend_ldap, [{other_bind, {"username", "password"}}]}], +[rabbitmq_auth_backend_ldap]} +, +{22, +"listeners.tcp.default = 5672 +collect_statistics_interval = 10000 +management.http_log_dir = test/config_schema_SUITE_data/rabbit-mgmt +management.rates_mode = basic", +[{rabbit, [ {tcp_listeners, [5672]}, + {collect_statistics_interval, 10000}]}, + {rabbitmq_management, [ {http_log_dir, "test/config_schema_SUITE_data/rabbit-mgmt"}, + {rates_mode, basic}]} +], +[rabbitmq_management]} +, +{23, +"management.listener.port = 12345", +[{rabbitmq_management, [{listener, [{port, 12345}]}]}], +[rabbitmq_management]} +, +{24, +"management.listener.port = 15671 +management.listener.ssl = true +management.listener.ssl_opts.cacertfile = test/config_schema_SUITE_data/certs/cacert.pem +management.listener.ssl_opts.certfile = test/config_schema_SUITE_data/certs/cert.pem +management.listener.ssl_opts.keyfile = test/config_schema_SUITE_data/certs/key.pem", +[{rabbitmq_management, + [{listener, [{port, 15671}, + {ssl, true}, + {ssl_opts, [{cacertfile, "test/config_schema_SUITE_data/certs/cacert.pem"}, + {certfile, "test/config_schema_SUITE_data/certs/cert.pem"}, + {keyfile, "test/config_schema_SUITE_data/certs/key.pem"}]} + ]} + ]} +], +[rabbitmq_management]} +, +{25, +"management.sample_retention_policies.global.minute = 5 +management.sample_retention_policies.global.hour = 60 +management.sample_retention_policies.global.day = 1200 + +management.sample_retention_policies.basic.minute = 5 +management.sample_retention_policies.basic.hour = 60 + +management.sample_retention_policies.detailed.10 = 5", +[{rabbitmq_management,[ + {sample_retention_policies, + %% List of {MaxAgeInSeconds, SampleEveryNSeconds} + [{global, [{60, 5}, {3600, 60}, {86400, 1200}]}, + {basic, [{60, 5}, {3600, 60}]}, + {detailed, [{10, 5}]}]} +]}], +[rabbitmq_management]} +, +{26, +"vm_memory_high_watermark.absolute = 1073741824", +[{rabbit, [{vm_memory_high_watermark, {absolute, 1073741824}}]}],[]} +, +{27, +"vm_memory_high_watermark.absolute = 1024MB", +[{rabbit, [{vm_memory_high_watermark, {absolute, "1024MB"}}]}],[]} +, +{28, +"vm_memory_high_watermark_paging_ratio = 0.75 +vm_memory_high_watermark.relative = 0.4", +[{rabbit, [{vm_memory_high_watermark_paging_ratio, 0.75}, + {vm_memory_high_watermark, 0.4}]}],[]} +, +{29, +"listeners.tcp.default = 5672 +mqtt.default_user = guest +mqtt.default_pass = guest +mqtt.allow_anonymous = true +mqtt.vhost = / +mqtt.exchange = amq.topic +mqtt.subscription_ttl = 1800000 +mqtt.prefetch = 10 +mqtt.listeners.ssl = none +## Default MQTT with TLS port is 8883 +# mqtt.listeners.ssl.default = 8883 +mqtt.listeners.tcp.default = 1883 +mqtt.tcp_listen_options.backlog = 128 +mqtt.tcp_listen_options.nodelay = true", +[{rabbit, [{tcp_listeners, [5672]}]}, + {rabbitmq_mqtt, [{default_user, <<"guest">>}, + {default_pass, <<"guest">>}, + {allow_anonymous, true}, + {vhost, <<"/">>}, + {exchange, <<"amq.topic">>}, + {subscription_ttl, 1800000}, + {prefetch, 10}, + {ssl_listeners, []}, + %% Default MQTT with TLS port is 8883 + %% {ssl_listeners, [8883]} + {tcp_listeners, [1883]}, + {tcp_listen_options, [{backlog, 128}, + {nodelay, true}]}]} + ], +[rabbitmq_mqtt]} +, +{30, +"ssl_options.cacertfile = test/config_schema_SUITE_data/certs/cacert.pem +ssl_options.certfile = test/config_schema_SUITE_data/certs/cert.pem +ssl_options.keyfile = test/config_schema_SUITE_data/certs/key.pem +ssl_options.verify = verify_peer +ssl_options.fail_if_no_peer_cert = true + +mqtt.listeners.ssl.default = 8883 +mqtt.listeners.tcp.default = 1883", +[{rabbit, [ + {ssl_options, [{cacertfile, "test/config_schema_SUITE_data/certs/cacert.pem"}, + {certfile, "test/config_schema_SUITE_data/certs/cert.pem"}, + {keyfile, "test/config_schema_SUITE_data/certs/key.pem"}, + {verify, verify_peer}, + {fail_if_no_peer_cert, true}]} + ]}, + {rabbitmq_mqtt, [ + {ssl_listeners, [8883]}, + {tcp_listeners, [1883]} + ]} + ], +[rabbitmq_mqtt]} +, +{31, +"mqtt.ssl_cert_login = true", +[{rabbitmq_mqtt, [{ssl_cert_login, true}]}], [rabbitmq_mqtt]} +, + +{32, +"ssl_cert_login_from = common_name", +[{rabbit, [{ssl_cert_login_from, common_name}]}], [rabbitmq_mqtt]} +, + + +{33, +"listeners.tcp.default = 5672 +mqtt.default_user = guest +mqtt.default_pass = guest +mqtt.allow_anonymous = true +mqtt.vhost = / +mqtt.exchange = amq.topic +mqtt.subscription_ttl = undefined +mqtt.prefetch = 10", +[{rabbit, [{tcp_listeners, [5672]}]}, + {rabbitmq_mqtt, [{default_user, <<"guest">>}, + {default_pass, <<"guest">>}, + {allow_anonymous, true}, + {vhost, <<"/">>}, + {exchange, <<"amq.topic">>}, + {subscription_ttl, undefined}, + {prefetch, 10}]} + ], +[rabbitmq_mqtt]} +, +{34, +"mqtt.default_user = guest +mqtt.default_pass = guest +mqtt.allow_anonymous = true +mqtt.vhost = / +mqtt.exchange = amq.topic +mqtt.subscription_ttl = 1800000 +mqtt.prefetch = 10 +## use DETS (disk-based) store for retained messages +mqtt.retained_message_store = rabbit_mqtt_retained_msg_store_dets +## only used by DETS store +mqtt.retained_message_store_dets_sync_interval = 2000 + +mqtt.listeners.ssl = none +mqtt.listeners.tcp.default = 1883", +[{rabbitmq_mqtt, [{default_user, <<"guest">>}, + {default_pass, <<"guest">>}, + {allow_anonymous, true}, + {vhost, <<"/">>}, + {exchange, <<"amq.topic">>}, + {subscription_ttl, 1800000}, + {prefetch, 10}, + %% use DETS (disk-based) store for retained messages + {retained_message_store, rabbit_mqtt_retained_msg_store_dets}, + %% only used by DETS store + {retained_message_store_dets_sync_interval, 2000}, + {ssl_listeners, []}, + {tcp_listeners, [1883]}]} + ], +[rabbitmq_mqtt]} +, + +{35, +"listeners.tcp.1 = 192.168.1.99:5672", +[ + {rabbit, [ + {tcp_listeners, [{"192.168.1.99", 5672}]} + ]} +], []} +, +{36, +"listeners.tcp.1 = 127.0.0.1:5672 +listeners.tcp.2 = ::1:5672", +[ + {rabbit, [ + {tcp_listeners, [{"127.0.0.1", 5672}, + {"::1", 5672}]} + ]} +], []} +, +{37, +"listeners.tcp.1 = :::5672", +[ + {rabbit, [ + {tcp_listeners, [{"::", 5672}]} + ]} +], []} +, +{38, +"listeners.tcp.1 = 192.168.1.99:5672", +[ + {rabbit, [ + {tcp_listeners, [{"192.168.1.99", 5672}]} + ]} +], []} +, +{39, +"listeners.tcp.1 = fe80::2acf:e9ff:fe17:f97b:5672", +[ + {rabbit, [ + {tcp_listeners, [{"fe80::2acf:e9ff:fe17:f97b", 5672}]} + ]} +], []} +, +{40, +"tcp_listen_options.backlog = 128 +tcp_listen_options.nodelay = true +tcp_listen_options.sndbuf = 196608 +tcp_listen_options.recbuf = 196608", +[ + {rabbit, [ + {tcp_listen_options, [ + {backlog, 128}, + {nodelay, true}, + {sndbuf, 196608}, + {recbuf, 196608} + ]} + ]} +], []} +, + +{42, +"tcp_listen_options.backlog = 4096 +tcp_listen_options.nodelay = true", +[ + {kernel, [ + {inet_default_connect_options, [{nodelay, true}]}, + {inet_default_listen_options, [{nodelay, true}]} + ]}] +, +[ + {kernel, [ + {inet_default_connect_options, [{nodelay, true}]}, + {inet_default_listen_options, [{nodelay, true}]} + ]}, + {rabbit, [ + {tcp_listen_options, [ + {backlog, 4096}, + {nodelay, true} + ]} + ]} +], []} +, + +{43, +"tcp_listen_options.backlog = 4096 +tcp_listen_options.nodelay = true", +[ + {rabbit, [ + {tcp_listen_options, [ + {backlog, 4096}, + {nodelay, true} + ]} + ]} +], []} +, + +{44, +"ssl_handshake_timeout = 10000", +[ + {rabbit, [ + %% 10 seconds + {ssl_handshake_timeout, 10000} + ]} +], []} +, + +{45, +"cluster_partition_handling = pause_if_all_down + +## Recover strategy. Can be either 'autoheal' or 'ignore' +cluster_partition_handling.pause_if_all_down.recover = ignore + +## Node names to check +cluster_partition_handling.pause_if_all_down.nodes.1 = rabbit@myhost1 +cluster_partition_handling.pause_if_all_down.nodes.2 = rabbit@myhost2", +[{rabbit, [{cluster_partition_handling, {pause_if_all_down, [rabbit@myhost2, rabbit@myhost1], ignore}}]}], []} +, +{46, +"cluster_partition_handling = autoheal", +[{rabbit, [{cluster_partition_handling, autoheal}]}], []} +, +{47, +"password_hashing_module = rabbit_password_hashing_sha512", +[ + {rabbit, [{password_hashing_module, rabbit_password_hashing_sha512}]} +],[]} +, + +{48, +"listeners.ssl.1 = 5671 +ssl_options.cacertfile = test/config_schema_SUITE_data/certs/cacert.pem +ssl_options.certfile = test/config_schema_SUITE_data/certs/cert.pem +ssl_options.keyfile = test/config_schema_SUITE_data/certs/key.pem +ssl_options.verify = verify_peer +ssl_options.fail_if_no_peer_cert = false" +, +[ + {rabbit, [ + {ssl_listeners, [5671]}, + {ssl_options, [{cacertfile,"test/config_schema_SUITE_data/certs/cacert.pem"}, + {certfile,"test/config_schema_SUITE_data/certs/cert.pem"}, + {keyfile,"test/config_schema_SUITE_data/certs/key.pem"}, + {verify,verify_peer}, + {fail_if_no_peer_cert,false}]} + ]} +],[]} +, + + +{49, +"listeners.ssl.1 = 5671 +ssl_options.cacertfile = test/config_schema_SUITE_data/certs/cacert.pem +ssl_options.certfile = test/config_schema_SUITE_data/certs/cert.pem +ssl_options.keyfile = test/config_schema_SUITE_data/certs/key.pem +ssl_options.password = t0p$3kRe7", +[ + {rabbit, [ + {ssl_listeners, [5671]}, + {ssl_options, [{cacertfile,"test/config_schema_SUITE_data/certs/cacert.pem"}, + {certfile, "test/config_schema_SUITE_data/certs/cert.pem"}, + {keyfile, "test/config_schema_SUITE_data/certs/key.pem"}, + {password, "t0p$3kRe7"} + ]} + ]} +],[]} +, + +{50, +"listeners.ssl.1 = 5671 +ssl_options.cacertfile = test/config_schema_SUITE_data/certs/cacert.pem +ssl_options.certfile = test/config_schema_SUITE_data/certs/cert.pem +ssl_options.keyfile = test/config_schema_SUITE_data/certs/key.pem +ssl_options.versions.tls1_2 = tlsv1.2 +ssl_options.versions.tls1_1 = tlsv1.1 +ssl_options.versions.tls1 = tlsv1", +[{ssl, [{versions, ['tlsv1.2', 'tlsv1.1', tlsv1]}]}], +[{ssl, [{versions, ['tlsv1.2', 'tlsv1.1', tlsv1]}]}, + {rabbit, [ + {ssl_listeners, [5671]}, + {ssl_options, [{cacertfile,"test/config_schema_SUITE_data/certs/cacert.pem"}, + {certfile, "test/config_schema_SUITE_data/certs/cert.pem"}, + {keyfile, "test/config_schema_SUITE_data/certs/key.pem"}, + {versions, ['tlsv1.2', 'tlsv1.1', tlsv1]} + ]} + ]} +],[]} +, +{51, +"listeners.ssl.1 = 5671 +ssl_options.cacertfile = test/config_schema_SUITE_data/certs/cacert.pem +ssl_options.certfile = test/config_schema_SUITE_data/certs/cert.pem +ssl_options.keyfile = test/config_schema_SUITE_data/certs/key.pem +ssl_options.versions.tls1_2 = tlsv1.2 +ssl_options.versions.tls1_1 = tlsv1.1", +[{ssl, [{versions, ['tlsv1.2', 'tlsv1.1']}]}], +[ + {ssl, [{versions, ['tlsv1.2', 'tlsv1.1']}]}, + {rabbit, [ + {ssl_listeners, [5671]}, + {ssl_options, [{cacertfile,"test/config_schema_SUITE_data/certs/cacert.pem"}, + {certfile, "test/config_schema_SUITE_data/certs/cert.pem"}, + {keyfile, "test/config_schema_SUITE_data/certs/key.pem"}, + {versions, ['tlsv1.2', 'tlsv1.1']} + ]} + ]} +],[]} +, +{52, +"listeners.ssl.1 = 5671 +ssl_allow_poodle_attack = true +ssl_options.cacertfile = test/config_schema_SUITE_data/certs/cacert.pem +ssl_options.certfile = test/config_schema_SUITE_data/certs/cert.pem +ssl_options.keyfile = test/config_schema_SUITE_data/certs/key.pem +ssl_options.verify = verify_peer +ssl_options.fail_if_no_peer_cert = false", +[ + {rabbit, [ + {ssl_listeners, [5671]}, + {ssl_allow_poodle_attack, true}, + {ssl_options, [{cacertfile,"test/config_schema_SUITE_data/certs/cacert.pem"}, + {certfile,"test/config_schema_SUITE_data/certs/cert.pem"}, + {keyfile,"test/config_schema_SUITE_data/certs/key.pem"}, + {verify,verify_peer}, + {fail_if_no_peer_cert,false}]} + ]} +],[]} +, +{53, +"listeners.ssl.1 = 5671 +ssl_options.cacertfile = test/config_schema_SUITE_data/certs/cacert.pem +ssl_options.certfile = test/config_schema_SUITE_data/certs/cert.pem +ssl_options.keyfile = test/config_schema_SUITE_data/certs/key.pem +ssl_options.depth = 2 +ssl_options.verify = verify_peer +ssl_options.fail_if_no_peer_cert = false", +[ + {rabbit, [ + {ssl_listeners, [5671]}, + {ssl_options, [{cacertfile,"test/config_schema_SUITE_data/certs/cacert.pem"}, + {certfile,"test/config_schema_SUITE_data/certs/cert.pem"}, + {keyfile,"test/config_schema_SUITE_data/certs/key.pem"}, + {depth, 2}, + {verify,verify_peer}, + {fail_if_no_peer_cert,false}]} + ]} +],[]} +, +{54, +"stomp.listeners.tcp.1 = 12345", +[{rabbitmq_stomp, [{tcp_listeners, [12345]}]}],[rabbitmq_stomp]} +, +{55, +"stomp.listeners.tcp.1 = 127.0.0.1:61613 +stomp.listeners.tcp.2 = ::1:61613", +[{rabbitmq_stomp, [{tcp_listeners, [{"127.0.0.1", 61613}, + {"::1", 61613}]}]}],[rabbitmq_stomp]} +, +{56, +"ssl_options.cacertfile = test/config_schema_SUITE_data/certs/cacert.pem +ssl_options.certfile = test/config_schema_SUITE_data/certs/cert.pem +ssl_options.keyfile = test/config_schema_SUITE_data/certs/key.pem +ssl_options.verify = verify_peer +ssl_options.fail_if_no_peer_cert = true + +stomp.listeners.tcp.1 = 61613 +stomp.listeners.ssl.1 = 61614", +[{rabbit,[ +{ssl_options, [{cacertfile, "test/config_schema_SUITE_data/certs/cacert.pem"}, + {certfile, "test/config_schema_SUITE_data/certs/cert.pem"}, + {keyfile, "test/config_schema_SUITE_data/certs/key.pem"}, + {verify, verify_peer}, + {fail_if_no_peer_cert, true}]}]}, +{rabbitmq_stomp, [{tcp_listeners, [61613]}, +{ssl_listeners, [61614]}]} + ],[]} +, + +{57, +"stomp.default_user = guest +stomp.default_pass = guest", +[{rabbitmq_stomp, [{default_user, [{login, "guest"},{passcode, "guest"}]}]}], +[rabbitmq_stomp]} +, +{58, +"stomp.ssl_cert_login = true", +[{rabbitmq_stomp, [{ssl_cert_login, true}]}], +[rabbitmq_stomp]} +, +{59, +"ssl_cert_login_from = common_name", +[{rabbit, [{ssl_cert_login_from, common_name}]}], []} +, +{60, +"stomp.default_user = guest +stomp.default_pass = guest +stomp.implicit_connect = true", +[{rabbitmq_stomp, [{default_user,[{login, "guest"}, {passcode, "guest"}]},{implicit_connect, true}]}], +[rabbitmq_stomp]} +, +{61, +"stomp.default_vhost = /", +[{rabbitmq_stomp, [{default_vhost, <<"/">>}]}], +[rabbitmq_stomp]} +, +{62, +"management.listener.port = 15672 +management.listener.ip = 127.0.0.1", +[{rabbitmq_management, + [{listener, [{port, 15672}, + {ip, "127.0.0.1"} + ]} + ]} +], +[rabbitmq_management]} +, +{63, +"management.listener.port = 15672 +management.listener.ssl = true + +management.listener.ssl_opts.cacertfile = test/config_schema_SUITE_data/certs/cacert.pem +management.listener.ssl_opts.certfile = test/config_schema_SUITE_data/certs/cert.pem +management.listener.ssl_opts.keyfile = test/config_schema_SUITE_data/certs/key.pem", +[{rabbitmq_management, + [{listener, [{port, 15672}, + {ssl, true}, + {ssl_opts, [{cacertfile, "test/config_schema_SUITE_data/certs/cacert.pem"}, + {certfile, "test/config_schema_SUITE_data/certs/cert.pem"}, + {keyfile, "test/config_schema_SUITE_data/certs/key.pem"}]} + ]} + ]} +], +[rabbitmq_management]}, +{64, +"web_stomp.port = 12345", +[{rabbitmq_web_stomp, [{port, 12345}]}], +[rabbitmq_web_stomp]}, +{65, +"web_stomp.ssl.port = 15671 +web_stomp.ssl.backlog = 1024 +web_stomp.ssl.certfile = test/config_schema_SUITE_data/certs/cert.pem +web_stomp.ssl.keyfile = test/config_schema_SUITE_data/certs/key.pem +web_stomp.ssl.cacertfile = test/config_schema_SUITE_data/certs/cacert.pem +web_stomp.ssl.password = changeme", +[{rabbitmq_web_stomp, + [{ssl_config, [{port, 15671}, + {backlog, 1024}, + {certfile, "test/config_schema_SUITE_data/certs/cert.pem"}, + {keyfile, "test/config_schema_SUITE_data/certs/key.pem"}, + {cacertfile, "test/config_schema_SUITE_data/certs/cacert.pem"}, + {password, "changeme"}]}]}], +[rabbitmq_web_stomp]}, +{66, +"web_stomp.ws_frame = binary", +[{rabbitmq_web_stomp, [{ws_frame, binary}]}], +[rabbitmq_web_stomp]}, +{67, +"web_stomp.cowboy_opts.max_keepalive = 10", +[{rabbitmq_web_stomp,[{cowboy_opts, [{max_keepalive, 10}]}]}], +[rabbitmq_web_stomp]}, +{68, +"web_stomp.sockjs_opts.url = https://cdn.jsdelivr.net/sockjs/0.3.4/sockjs.min.js", +[{rabbitmq_web_stomp, + [{sockjs_opts, [{sockjs_url, "https://cdn.jsdelivr.net/sockjs/0.3.4/sockjs.min.js"}]}]}], +[rabbitmq_web_stomp]}, +{69, +"auth_backends.1 = http +rabbitmq_auth_backend_http.user_path = http://some-server/auth/user +rabbitmq_auth_backend_http.vhost_path = http://some-server/auth/vhost +rabbitmq_auth_backend_http.resource_path = http://some-server/auth/resource", +[{rabbit, [{auth_backends, [rabbit_auth_backend_http]}]}, + {rabbitmq_auth_backend_http, + [{user_path, "http://some-server/auth/user"}, + {vhost_path, "http://some-server/auth/vhost"}, + {resource_path, "http://some-server/auth/resource"}]}], +[rabbitmq_auth_backend_http]} +]. diff --git a/test/dummy_interceptor.erl b/test/dummy_interceptor.erl new file mode 100644 index 0000000000..6d510a3073 --- /dev/null +++ b/test/dummy_interceptor.erl @@ -0,0 +1,26 @@ +-module(dummy_interceptor). + +-behaviour(rabbit_channel_interceptor). + +-include_lib("rabbit_common/include/rabbit.hrl"). +-include_lib("rabbit_common/include/rabbit_framing.hrl"). + + +-compile(export_all). + +init(_Ch) -> + undefined. + +description() -> + [{description, + <<"Empties payload on publish">>}]. + +intercept(#'basic.publish'{} = Method, Content, _IState) -> + Content2 = Content#content{payload_fragments_rev = []}, + {Method, Content2}; + +intercept(Method, Content, _VHost) -> + {Method, Content}. + +applies_to() -> + ['basic.publish']. diff --git a/test/plugin_versioning_SUITE.erl b/test/plugin_versioning_SUITE.erl new file mode 100644 index 0000000000..7fcfe433e0 --- /dev/null +++ b/test/plugin_versioning_SUITE.erl @@ -0,0 +1,177 @@ +%% The contents of this file are subject to the Mozilla Public License +%% Version 1.1 (the "License"); you may not use this file except in +%% compliance with the License. You may obtain a copy of the License at +%% http://www.mozilla.org/MPL/ +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +%% License for the specific language governing rights and limitations +%% under the License. +%% +%% The Original Code is RabbitMQ. +%% +%% The Initial Developer of the Original Code is GoPivotal, Inc. +%% Copyright (c) 2016 Pivotal Software, Inc. All rights reserved. +%% + +-module(plugin_versioning_SUITE). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("amqp_client/include/amqp_client.hrl"). + +-compile(export_all). + +all() -> + [ + {group, parallel_tests} + ]. + +groups() -> + [ + {parallel_tests, [parallel], [ + version_support, + plugin_validation + ]} + ]. + +%% ------------------------------------------------------------------- +%% Testsuite setup/teardown. +%% ------------------------------------------------------------------- + +init_per_suite(Config) -> + rabbit_ct_helpers:log_environment(), + rabbit_ct_helpers:run_setup_steps(Config). + +end_per_suite(Config) -> + rabbit_ct_helpers:run_teardown_steps(Config). + +init_per_group(_, Config) -> + Config. + +end_per_group(_, Config) -> + Config. + +init_per_testcase(Testcase, Config) -> + rabbit_ct_helpers:testcase_started(Config, Testcase). + +end_per_testcase(Testcase, Config) -> + rabbit_ct_helpers:testcase_finished(Config, Testcase). + +%% ------------------------------------------------------------------- +%% Testcases. +%% ------------------------------------------------------------------- + +version_support(_Config) -> + Examples = [ + {[], "any version", true} %% anything goes + ,{[], "0.0.0", true} %% ditto + ,{[], "3.5.6", true} %% ditto + ,{["something"], "something", true} %% equal values match + ,{["3.5.4"], "something", false} + ,{["3.4.5", "3.6.0"], "0.0.0", true} %% zero version always match + ,{["3.4.5", "3.6.0"], "", true} %% empty version always match + ,{["something", "3.5.6"], "3.5.7", true} %% 3.5.7 matches ~> 3.5.6 + ,{["3.4.0", "3.5.6"], "3.6.1", false} %% 3.6.x isn't supported + ,{["3.5.2", "3.6.1", "3.7.1"], "3.5.2", true} %% 3.5.2 matches ~> 3.5.2 + ,{["3.5.2", "3.6.1", "3.7.1"], "3.5.1", false} %% lesser than the lower boundary + ,{["3.5.2", "3.6.1", "3.7.1"], "3.6.2", true} %% 3.6.2 matches ~> 3.6.1 + ,{["3.5.2", "3.6.1", "3.6.8"], "3.6.2", true} %% 3.6.2 still matches ~> 3.6.1 + ,{["3.5", "3.6", "3.7"], "3.5.1", false} %% x.y values are not supported + ,{["3"], "3.5.1", false} %% x values are not supported + ,{["3.5.2", "3.6.1"], "3.6.2.999", true} %% x.y.z.p values are supported + ,{["3.5.2", "3.6.2.333"], "3.6.2.999", true} %% x.y.z.p values are supported + ,{["3.5.2", "3.6.2.333"], "3.6.2.222", false} %% x.y.z.p values are supported + ], + + lists:foreach( + fun({Versions, RabbitVersion, Expected}) -> + {Expected, RabbitVersion, Versions} = + {rabbit_plugins:is_version_supported(RabbitVersion, Versions), + RabbitVersion, Versions} + end, + Examples), + ok. + +-record(validation_example, {rabbit_version, plugins, errors, valid}). + +plugin_validation(_Config) -> + Examples = [ + #validation_example{ + rabbit_version = "3.7.1", + plugins = + [{plugin_a, "3.7.2", ["3.5.6", "3.7.1"], []}, + {plugin_b, "3.7.2", ["3.7.0"], [{plugin_a, ["3.6.3", "3.7.1"]}]}], + errors = [], + valid = [plugin_a, plugin_b]}, + + #validation_example{ + rabbit_version = "3.7.1", + plugins = + [{plugin_a, "3.7.1", ["3.7.6"], []}, + {plugin_b, "3.7.2", ["3.7.0"], [{plugin_a, ["3.6.3", "3.7.0"]}]}], + errors = + [{plugin_a, [{broker_version_mismatch, "3.7.1", ["3.7.6"]}]}, + {plugin_b, [{missing_dependency, plugin_a}]}], + valid = [] + }, + + #validation_example{ + rabbit_version = "3.7.1", + plugins = + [{plugin_a, "3.7.1", ["3.7.6"], []}, + {plugin_b, "3.7.2", ["3.7.0"], [{plugin_a, ["3.7.0"]}]}, + {plugin_c, "3.7.2", ["3.7.0"], [{plugin_b, ["3.7.3"]}]}], + errors = + [{plugin_a, [{broker_version_mismatch, "3.7.1", ["3.7.6"]}]}, + {plugin_b, [{missing_dependency, plugin_a}]}, + {plugin_c, [{missing_dependency, plugin_b}]}], + valid = [] + }, + + #validation_example{ + rabbit_version = "3.7.1", + plugins = + [{plugin_a, "3.7.1", ["3.7.1"], []}, + {plugin_b, "3.7.2", ["3.7.0"], [{plugin_a, ["3.7.3"]}]}, + {plugin_d, "3.7.2", ["3.7.0"], [{plugin_c, ["3.7.3"]}]}], + errors = + [{plugin_b, [{{dependency_version_mismatch, "3.7.1", ["3.7.3"]}, plugin_a}]}, + {plugin_d, [{missing_dependency, plugin_c}]}], + valid = [plugin_a] + }, + #validation_example{ + rabbit_version = "0.0.0", + plugins = + [{plugin_a, "", ["3.7.1"], []}, + {plugin_b, "3.7.2", ["3.7.0"], [{plugin_a, ["3.7.3"]}]}], + errors = [], + valid = [plugin_a, plugin_b] + }], + lists:foreach( + fun(#validation_example{rabbit_version = RabbitVersion, + plugins = PluginsExamples, + errors = Errors, + valid = ExpectedValid}) -> + Plugins = make_plugins(PluginsExamples), + {Valid, Invalid} = rabbit_plugins:validate_plugins(Plugins, + RabbitVersion), + Errors = lists:reverse(Invalid), + ExpectedValid = lists:reverse(lists:map(fun(#plugin{name = Name}) -> + Name + end, + Valid)) + end, + Examples), + ok. + +make_plugins(Plugins) -> + lists:map( + fun({Name, Version, RabbitVersions, PluginsVersions}) -> + Deps = [K || {K,_V} <- PluginsVersions], + #plugin{name = Name, + version = Version, + dependencies = Deps, + broker_version_requirements = RabbitVersions, + dependency_version_requirements = PluginsVersions} + end, + Plugins). diff --git a/test/unit_SUITE.erl b/test/unit_SUITE.erl index ba0f43f11e..30bf4d937c 100644 --- a/test/unit_SUITE.erl +++ b/test/unit_SUITE.erl @@ -728,8 +728,9 @@ version_equivalance(_Config) -> true = rabbit_misc:version_minor_equivalent("3.0.0", "3.0.0"), true = rabbit_misc:version_minor_equivalent("3.0.0", "3.0.1"), true = rabbit_misc:version_minor_equivalent("%%VSN%%", "%%VSN%%"), + % Support for 4-number versions + true = rabbit_misc:version_minor_equivalent("3.0.0", "3.0.0.1"), false = rabbit_misc:version_minor_equivalent("3.0.0", "3.1.0"), false = rabbit_misc:version_minor_equivalent("3.0.0", "3.0"), - false = rabbit_misc:version_minor_equivalent("3.0.0", "3.0.0.1"), false = rabbit_misc:version_minor_equivalent("3.0.0", "3.0.foo"), passed. diff --git a/test/unit_inbroker_SUITE.erl b/test/unit_inbroker_SUITE.erl index dfde1fba22..5e521df105 100644 --- a/test/unit_inbroker_SUITE.erl +++ b/test/unit_inbroker_SUITE.erl @@ -116,7 +116,7 @@ groups() -> log_management, %% Check log files. log_management_during_startup, %% Check log files. memory_high_watermark, %% Trigger alarm. - rotate_logs_without_suffix, %% Check log files. + externally_rotated_logs_are_automatically_reopened, %% Check log files. server_status %% Trigger alarm. ]}, {backing_queue_tests, [], [ @@ -1834,69 +1834,74 @@ log_management(Config) -> ?MODULE, log_management1, [Config]). log_management1(_Config) -> - override_group_leader(), + [LogFile] = rabbit:log_locations(), + Suffix = ".0", - MainLog = rabbit:log_location(kernel), - SaslLog = rabbit:log_location(sasl), - Suffix = ".1", - - ok = test_logs_working(MainLog, SaslLog), + ok = test_logs_working([LogFile]), %% prepare basic logs - file:delete([MainLog, Suffix]), - file:delete([SaslLog, Suffix]), - - %% simple logs reopening - ok = control_action(rotate_logs, []), - ok = test_logs_working(MainLog, SaslLog), + file:delete(LogFile ++ Suffix), + ok = test_logs_working([LogFile]), %% simple log rotation - ok = control_action(rotate_logs, [Suffix]), - [true, true] = non_empty_files([[MainLog, Suffix], [SaslLog, Suffix]]), - [true, true] = empty_files([MainLog, SaslLog]), - ok = test_logs_working(MainLog, SaslLog), - - %% reopening logs with log rotation performed first - ok = clean_logs([MainLog, SaslLog], Suffix), ok = control_action(rotate_logs, []), - ok = file:rename(MainLog, [MainLog, Suffix]), - ok = file:rename(SaslLog, [SaslLog, Suffix]), - ok = test_logs_working([MainLog, Suffix], [SaslLog, Suffix]), + %% FIXME: rabbit:rotate_logs/0 is asynchronous due to a limitation + %% in Lager. Therefore, we have no choice but to wait an arbitrary + %% amount of time. + timer:sleep(2000), + [true, true] = non_empty_files([LogFile ++ Suffix, LogFile]), + ok = test_logs_working([LogFile]), + + %% log rotation on empty files + ok = clean_logs([LogFile], Suffix), ok = control_action(rotate_logs, []), - ok = test_logs_working(MainLog, SaslLog), + timer:sleep(2000), + [{error, enoent}, true] = non_empty_files([LogFile ++ Suffix, LogFile]), - %% log rotation on empty files (the main log will have a ctl action logged) - ok = clean_logs([MainLog, SaslLog], Suffix), + %% logs with suffix are not writable + ok = control_action(rotate_logs, []), + timer:sleep(2000), + ok = make_files_non_writable([LogFile ++ Suffix]), ok = control_action(rotate_logs, []), - ok = control_action(rotate_logs, [Suffix]), - [false, true] = empty_files([[MainLog, Suffix], [SaslLog, Suffix]]), + timer:sleep(2000), + ok = test_logs_working([LogFile]), - %% logs with suffix are not writable - ok = control_action(rotate_logs, [Suffix]), - ok = make_files_non_writable([[MainLog, Suffix], [SaslLog, Suffix]]), - ok = control_action(rotate_logs, [Suffix]), - ok = test_logs_working(MainLog, SaslLog), + %% rotate when original log files are not writable + ok = make_files_non_writable([LogFile]), + ok = control_action(rotate_logs, []), + timer:sleep(2000), %% logging directed to tty (first, remove handlers) - ok = delete_log_handlers([rabbit_sasl_report_file_h, - rabbit_error_logger_file_h]), - ok = clean_logs([MainLog, SaslLog], Suffix), - ok = application:set_env(rabbit, sasl_error_logger, tty), - ok = application:set_env(rabbit, error_logger, tty), - ok = control_action(rotate_logs, []), - [{error, enoent}, {error, enoent}] = empty_files([MainLog, SaslLog]), + ok = control_action(stop_app, []), + ok = clean_logs([LogFile], Suffix), + ok = application:set_env(rabbit, lager_handler, tty), + application:unset_env(lager, handlers), + application:unset_env(lager, extra_sinks), + ok = control_action(start_app, []), + timer:sleep(200), + rabbit_log:info("test info"), + [{error, enoent}] = empty_files([LogFile]), %% rotate logs when logging is turned off - ok = application:set_env(rabbit, sasl_error_logger, false), - ok = application:set_env(rabbit, error_logger, silent), - ok = control_action(rotate_logs, []), - [{error, enoent}, {error, enoent}] = empty_files([MainLog, SaslLog]), + ok = control_action(stop_app, []), + ok = clean_logs([LogFile], Suffix), + ok = application:set_env(rabbit, lager_handler, false), + application:unset_env(lager, handlers), + application:unset_env(lager, extra_sinks), + ok = control_action(start_app, []), + timer:sleep(200), + rabbit_log:error("test error"), + timer:sleep(200), + [{error, enoent}] = empty_files([LogFile]), %% cleanup - ok = application:set_env(rabbit, sasl_error_logger, {file, SaslLog}), - ok = application:set_env(rabbit, error_logger, {file, MainLog}), - ok = add_log_handlers([{rabbit_error_logger_file_h, MainLog}, - {rabbit_sasl_report_file_h, SaslLog}]), + ok = control_action(stop_app, []), + ok = clean_logs([LogFile], Suffix), + ok = application:set_env(rabbit, lager_handler, LogFile), + application:unset_env(lager, handlers), + application:unset_env(lager, extra_sinks), + ok = control_action(start_app, []), + ok = test_logs_working([LogFile]), passed. log_management_during_startup(Config) -> @@ -1904,137 +1909,111 @@ log_management_during_startup(Config) -> ?MODULE, log_management_during_startup1, [Config]). log_management_during_startup1(_Config) -> - MainLog = rabbit:log_location(kernel), - SaslLog = rabbit:log_location(sasl), + [LogFile] = rabbit:log_locations(), + Suffix = ".0", %% start application with simple tty logging ok = control_action(stop_app, []), - ok = application:set_env(rabbit, error_logger, tty), - ok = application:set_env(rabbit, sasl_error_logger, tty), - ok = add_log_handlers([{error_logger_tty_h, []}, - {sasl_report_tty_h, []}]), + ok = clean_logs([LogFile], Suffix), + ok = application:set_env(rabbit, lager_handler, tty), + application:unset_env(lager, handlers), + application:unset_env(lager, extra_sinks), ok = control_action(start_app, []), - %% start application with tty logging and - %% proper handlers not installed - ok = control_action(stop_app, []), - ok = error_logger:tty(false), - ok = delete_log_handlers([sasl_report_tty_h]), - ok = case catch control_action(start_app, []) of - ok -> exit({got_success_but_expected_failure, - log_rotation_tty_no_handlers_test}); - {badrpc, {'EXIT', {error, - {cannot_log_to_tty, _, not_installed}}}} -> ok - end, - - %% fix sasl logging - ok = application:set_env(rabbit, sasl_error_logger, {file, SaslLog}), - %% start application with logging to non-existing directory - TmpLog = "/tmp/rabbit-tests/test.log", - delete_file(TmpLog), + NonExistent = "/tmp/non-existent/test.log", + delete_file(NonExistent), + delete_file(filename:dirname(NonExistent)), ok = control_action(stop_app, []), - ok = application:set_env(rabbit, error_logger, {file, TmpLog}), - - ok = delete_log_handlers([rabbit_error_logger_file_h]), - ok = add_log_handlers([{error_logger_file_h, MainLog}]), + ok = application:set_env(rabbit, lager_handler, NonExistent), + application:unset_env(lager, handlers), + application:unset_env(lager, extra_sinks), ok = control_action(start_app, []), %% start application with logging to directory with no %% write permissions ok = control_action(stop_app, []), - TmpDir = "/tmp/rabbit-tests", - ok = set_permissions(TmpDir, 8#00400), - ok = delete_log_handlers([rabbit_error_logger_file_h]), - ok = add_log_handlers([{error_logger_file_h, MainLog}]), + NoPermission1 = "/var/empty/test.log", + delete_file(NoPermission1), + delete_file(filename:dirname(NoPermission1)), + ok = control_action(stop_app, []), + ok = application:set_env(rabbit, lager_handler, NoPermission1), + application:unset_env(lager, handlers), + application:unset_env(lager, extra_sinks), ok = case control_action(start_app, []) of ok -> exit({got_success_but_expected_failure, log_rotation_no_write_permission_dir_test}); - {badrpc, {'EXIT', - {error, {cannot_log_to_file, _, _}}}} -> ok + {badrpc, + {'EXIT', {error, {cannot_log_to_file, _, Reason1}}}} + when Reason1 =:= enoent orelse Reason1 =:= eacces -> ok; + {badrpc, + {'EXIT', + {error, {cannot_log_to_file, _, + {cannot_create_parent_dirs, _, Reason1}}}}} + when Reason1 =:= eperm orelse + Reason1 =:= eacces orelse + Reason1 =:= enoent-> ok end, %% start application with logging to a subdirectory which %% parent directory has no write permissions - ok = control_action(stop_app, []), - TmpTestDir = "/tmp/rabbit-tests/no-permission/test/log", - ok = application:set_env(rabbit, error_logger, {file, TmpTestDir}), - ok = add_log_handlers([{error_logger_file_h, MainLog}]), + NoPermission2 = "/var/empty/non-existent/test.log", + delete_file(NoPermission2), + delete_file(filename:dirname(NoPermission2)), + case control_action(stop_app, []) of + ok -> ok; + {error, lager_not_running} -> ok + end, + ok = application:set_env(rabbit, lager_handler, NoPermission2), + application:unset_env(lager, handlers), + application:unset_env(lager, extra_sinks), ok = case control_action(start_app, []) of ok -> exit({got_success_but_expected_failure, log_rotatation_parent_dirs_test}); {badrpc, + {'EXIT', {error, {cannot_log_to_file, _, Reason2}}}} + when Reason2 =:= enoent orelse Reason2 =:= eacces -> ok; + {badrpc, {'EXIT', {error, {cannot_log_to_file, _, - {error, - {cannot_create_parent_dirs, _, eacces}}}}}} -> ok + {cannot_create_parent_dirs, _, Reason2}}}}} + when Reason2 =:= eperm orelse + Reason2 =:= eacces orelse + Reason2 =:= enoent-> ok end, - ok = set_permissions(TmpDir, 8#00700), - ok = set_permissions(TmpLog, 8#00600), - ok = delete_file(TmpLog), - ok = file:del_dir(TmpDir), - %% start application with standard error_logger_file_h - %% handler not installed - ok = control_action(stop_app, []), - ok = application:set_env(rabbit, error_logger, {file, MainLog}), - ok = control_action(start_app, []), - - %% start application with standard sasl handler not installed - %% and rabbit main log handler installed correctly - ok = control_action(stop_app, []), - ok = delete_log_handlers([rabbit_sasl_report_file_h]), + %% cleanup + ok = application:set_env(rabbit, lager_handler, LogFile), + application:unset_env(lager, handlers), + application:unset_env(lager, extra_sinks), ok = control_action(start_app, []), passed. -%% "rabbitmqctl rotate_logs" without additional parameters -%% shouldn't truncate files. -rotate_logs_without_suffix(Config) -> +externally_rotated_logs_are_automatically_reopened(Config) -> passed = rabbit_ct_broker_helpers:rpc(Config, 0, - ?MODULE, rotate_logs_without_suffix1, [Config]). - -rotate_logs_without_suffix1(_Config) -> - override_group_leader(), - - MainLog = rabbit:log_location(kernel), - SaslLog = rabbit:log_location(sasl), - Suffix = ".1", - file:delete(MainLog), - file:delete(SaslLog), + ?MODULE, externally_rotated_logs_are_automatically_reopened1, [Config]). - %% Empty log-files should be created - ok = control_action(rotate_logs, []), - [true, true] = empty_files([MainLog, SaslLog]), +externally_rotated_logs_are_automatically_reopened1(_Config) -> + [LogFile] = rabbit:log_locations(), - %% Write something to log files and simulate external log rotation - ok = test_logs_working(MainLog, SaslLog), - ok = file:rename(MainLog, [MainLog, Suffix]), - ok = file:rename(SaslLog, [SaslLog, Suffix]), + %% Make sure log file is opened + ok = test_logs_working([LogFile]), - %% Create non-empty files - TestData = "test-data\n", - file:write_file(MainLog, TestData), - file:write_file(SaslLog, TestData), + %% Move it away - i.e. external log rotation happened + file:rename(LogFile, [LogFile, ".rotation_test"]), - %% Nothing should be truncated - neither moved files which are still - %% opened by server, nor new log files that should be just reopened. - ok = control_action(rotate_logs, []), - [true, true, true, true] = - non_empty_files([MainLog, SaslLog, [MainLog, Suffix], - [SaslLog, Suffix]]), - - %% And log files should be re-opened - new log records should go to - %% new files. - ok = test_logs_working(MainLog, SaslLog), - true = (rabbit_file:file_size(MainLog) > length(TestData)), - true = (rabbit_file:file_size(SaslLog) > length(TestData)), + %% New files should be created - test_logs_working/1 will check that + %% LogFile is not empty after doing some logging. And it's exactly + %% what we need to check here. + ok = test_logs_working([LogFile]), passed. -override_group_leader() -> - %% Override group leader, otherwise SASL fake events are ignored by - %% the error_logger local to RabbitMQ. - {group_leader, Leader} = erlang:process_info(whereis(rabbit), group_leader), - erlang:group_leader(Leader, self()). +empty_or_nonexist_files(Files) -> + [case file:read_file_info(File) of + {ok, FInfo} -> FInfo#file_info.size == 0; + {error, enoent} -> true; + Error -> Error + end || File <- Files]. empty_files(Files) -> [case file:read_file_info(File) of @@ -2048,12 +2027,11 @@ non_empty_files(Files) -> _ -> not(EmptyFile) end || EmptyFile <- empty_files(Files)]. -test_logs_working(MainLogFile, SaslLogFile) -> - ok = rabbit_log:error("Log a test message~n"), - ok = error_logger:error_report(crash_report, [fake_crash_report, ?MODULE]), +test_logs_working(LogFiles) -> + ok = rabbit_log:error("Log a test message"), %% give the error loggers some time to catch up - timer:sleep(100), - [true, true] = non_empty_files([MainLogFile, SaslLogFile]), + timer:sleep(200), + lists:all(fun(LogFile) -> [true] =:= non_empty_files([LogFile]) end, LogFiles), ok. set_permissions(Path, Mode) -> |
