summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Sébastien Pédron <jean-sebastien.pedron@dumbbell.fr>2016-05-27 10:41:32 +0200
committerJean-Sébastien Pédron <jean-sebastien.pedron@dumbbell.fr>2016-05-27 10:41:32 +0200
commitc8bdf334f626e6b5de7837234be8c541396fe2d4 (patch)
tree9f78f7c6888debad8a64ad3479c6a31ce5c641f7
parentdc941fed07171ecbc2a356e095c6e45f8af65de6 (diff)
downloadrabbitmq-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.erl113
-rw-r--r--test/channel_operation_timeout_test_queue.erl6
-rw-r--r--test/config_schema_SUITE.erl153
-rw-r--r--test/config_schema_SUITE_data/certs/cacert.pem1
-rw-r--r--test/config_schema_SUITE_data/certs/cert.pem1
-rw-r--r--test/config_schema_SUITE_data/certs/key.pem1
-rw-r--r--test/config_schema_SUITE_data/rabbit-mgmt/access.log0
-rw-r--r--test/config_schema_SUITE_data/snippets.config714
-rw-r--r--test/dummy_interceptor.erl26
-rw-r--r--test/plugin_versioning_SUITE.erl177
-rw-r--r--test/unit_SUITE.erl3
-rw-r--r--test/unit_inbroker_SUITE.erl272
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) ->