diff options
| -rw-r--r-- | Makefile | 3 | ||||
| -rw-r--r-- | priv/schema/rabbitmq.schema | 17 | ||||
| -rw-r--r-- | src/rabbit_connection_tracking.erl | 13 | ||||
| -rw-r--r-- | src/rabbit_connection_tracking_handler.erl | 24 | ||||
| -rw-r--r-- | src/rabbit_credential_validation.erl | 53 | ||||
| -rw-r--r-- | src/rabbit_credential_validator.erl | 28 | ||||
| -rw-r--r-- | src/rabbit_credential_validator_accept_everything.erl | 32 | ||||
| -rw-r--r-- | src/rabbit_credential_validator_min_password_length.erl | 56 | ||||
| -rw-r--r-- | src/rabbit_credential_validator_password_regexp.erl | 51 | ||||
| -rw-r--r-- | src/rabbit_plugins.erl | 2 | ||||
| -rw-r--r-- | src/rabbit_table.erl | 9 | ||||
| -rw-r--r-- | src/rabbit_variable_queue.erl | 53 | ||||
| -rw-r--r-- | test/clustering_management_SUITE.erl | 2 | ||||
| -rw-r--r-- | test/config_schema_SUITE_data/snippets.config | 21 | ||||
| -rw-r--r-- | test/credential_validation_SUITE.erl | 275 | ||||
| -rw-r--r-- | test/per_user_connection_tracking_SUITE.erl | 280 | ||||
| -rw-r--r-- | test/unit_inbroker_SUITE.erl | 12 | ||||
| -rw-r--r-- | test/worker_pool_SUITE.erl | 15 |
18 files changed, 903 insertions, 43 deletions
@@ -110,7 +110,8 @@ define PROJECT_ENV ]}, %% rabbitmq-server-973 - {lazy_queue_explicit_gc_run_operation_threshold, 250}, + {queue_explicit_gc_run_operation_threshold, 1000}, + {lazy_queue_explicit_gc_run_operation_threshold, 1000}, {background_gc_enabled, true}, {background_gc_target_interval, 60000} ] diff --git a/priv/schema/rabbitmq.schema b/priv/schema/rabbitmq.schema index 187e77017c..71032c4ffb 100644 --- a/priv/schema/rabbitmq.schema +++ b/priv/schema/rabbitmq.schema @@ -396,6 +396,23 @@ end}. {datatype, atom} ]}. +%% Credential validation. +%% + +{mapping, "credential_validator.validation_backend", "rabbit.credential_validator.validation_backend", [ + {datatype, atom} +]}. + +{mapping, "credential_validator.min_length", "rabbit.credential_validator.min_length", [ + {datatype, integer}, {validators, ["non_negative_integer"]} +]}. + +{mapping, "credential_validator.regexp", "rabbit.credential_validator.regexp", [ + {datatype, string} +]}. + + + %% %% Default User / VHost %% ==================== diff --git a/src/rabbit_connection_tracking.erl b/src/rabbit_connection_tracking.erl index 460bf964a0..38684482ef 100644 --- a/src/rabbit_connection_tracking.erl +++ b/src/rabbit_connection_tracking.erl @@ -34,7 +34,7 @@ delete_tracked_connections_table_for_node/1, delete_per_vhost_tracked_connections_table_for_node/1, clear_tracked_connection_tables_for_this_node/0, register_connection/1, unregister_connection/1, - list/0, list/1, list_on_node/1, + list/0, list/1, list_on_node/1, list_of_user/1, tracked_connection_from_connection_created/1, tracked_connection_from_connection_state/1, count_connections_in/1]). @@ -217,6 +217,17 @@ list_on_node(Node) -> catch exit:{aborted, {no_exists, _}} -> [] end. +-spec list_of_user(rabbit_types:username()) -> [rabbit_types:tracked_connection()]. + +list_of_user(Username) -> + lists:foldl( + fun (Node, Acc) -> + Tab = tracked_connection_table_name_for(Node), + Acc ++ mnesia:dirty_match_object( + Tab, + #tracked_connection{username = Username, _ = '_'}) + end, [], rabbit_mnesia:cluster_nodes(running)). + -spec count_connections_in(rabbit_types:vhost()) -> non_neg_integer(). count_connections_in(VirtualHost) -> diff --git a/src/rabbit_connection_tracking_handler.erl b/src/rabbit_connection_tracking_handler.erl index 598fe686c3..739b8049c0 100644 --- a/src/rabbit_connection_tracking_handler.erl +++ b/src/rabbit_connection_tracking_handler.erl @@ -27,6 +27,8 @@ -export([init/1, handle_call/2, handle_event/2, handle_info/2, terminate/2, code_change/3]). +-export([close_connections/3]). + -include_lib("rabbit.hrl"). -import(rabbit_misc, [pget/2]). @@ -77,13 +79,14 @@ handle_event(#event{type = connection_closed, props = Details}, State) -> handle_event(#event{type = vhost_deleted, props = Details}, State) -> VHost = pget(name, Details), rabbit_log_connection:info("Closing all connections in vhost '~s' because it's being deleted", [VHost]), - [close_connection(Conn, rabbit_misc:format("vhost '~s' is deleted", [VHost])) - || Conn <- rabbit_connection_tracking:list(VHost)], + close_connections(rabbit_connection_tracking:list(VHost), + rabbit_misc:format("vhost '~s' is deleted", [VHost])), {ok, State}; handle_event(#event{type = user_deleted, props = Details}, State) -> - _Username = pget(name, Details), - %% TODO: force close and unregister connections from - %% this user. Moved to rabbitmq/rabbitmq-server#628. + Username = pget(name, Details), + rabbit_log_connection:info("Closing all connections from user '~s' because it's being deleted", [Username]), + close_connections(rabbit_connection_tracking:list_of_user(Username), + rabbit_misc:format("user '~s' is deleted", [Username])), {ok, State}; %% A node had been deleted from the cluster. handle_event(#event{type = node_deleted, props = Details}, State) -> @@ -107,6 +110,17 @@ terminate(_Arg, _State) -> code_change(_OldVsn, State, _Extra) -> {ok, State}. + +close_connections(Tracked, Message) -> + close_connections(Tracked, Message, 0). + +close_connections(Tracked, Message, Delay) -> + [begin + close_connection(Conn, Message), + timer:sleep(Delay) + end || Conn <- Tracked], + ok. + close_connection(#tracked_connection{pid = Pid, type = network}, Message) -> rabbit_networking:close_connection(Pid, Message); close_connection(#tracked_connection{pid = Pid, type = direct}, Message) -> diff --git a/src/rabbit_credential_validation.erl b/src/rabbit_credential_validation.erl new file mode 100644 index 0000000000..4a629da14f --- /dev/null +++ b/src/rabbit_credential_validation.erl @@ -0,0 +1,53 @@ +%% 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) 2007-2016 Pivotal Software, Inc. All rights reserved. +%% + +-module(rabbit_credential_validation). + +-include("rabbit.hrl"). + +%% used for backwards compatibility +-define(DEFAULT_BACKEND, rabbit_credential_validator_accept_everything). + +%% +%% API +%% + +-export([validate/2, backend/0]). + +-spec validate(rabbit_types:username(), rabbit_types:password()) -> 'ok' | {'error', string()}. + +%% Validates a username/password pair by delegating to the effective +%% `rabbit_credential_validator`. Used by `rabbit_auth_backend_internal`. +%% Note that some validators may choose to only validate passwords. +%% +%% Possible return values: +%% +%% * ok: provided credentials passed validation. +%% * {error, Error, Args}: provided password password failed validation. + +validate(Username, Password) -> + Backend = backend(), + Backend:validate(Username, Password). + +-spec backend() -> atom(). + +backend() -> + case application:get_env(rabbit, credential_validator) of + undefined -> + ?DEFAULT_BACKEND; + {ok, Proplist} -> + proplists:get_value(validation_backend, Proplist, ?DEFAULT_BACKEND) + end. diff --git a/src/rabbit_credential_validator.erl b/src/rabbit_credential_validator.erl new file mode 100644 index 0000000000..dd12f6d2d6 --- /dev/null +++ b/src/rabbit_credential_validator.erl @@ -0,0 +1,28 @@ +%% 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) 2007-2016 Pivotal Software, Inc. All rights reserved. +%% + +-module(rabbit_credential_validator). + +-include("rabbit.hrl"). + +%% Validates a password. Used by `rabbit_auth_backend_internal`. +%% +%% Possible return values: +%% +%% * ok: provided password passed validation. +%% * {error, Error, Args}: provided password password failed validation. + +-callback validate(rabbit_types:username(), rabbit_types:password()) -> 'ok' | {'error', string()}. diff --git a/src/rabbit_credential_validator_accept_everything.erl b/src/rabbit_credential_validator_accept_everything.erl new file mode 100644 index 0000000000..f572d67e7f --- /dev/null +++ b/src/rabbit_credential_validator_accept_everything.erl @@ -0,0 +1,32 @@ +%% 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) 2007-2016 Pivotal Software, Inc. All rights reserved. +%% + +-module(rabbit_credential_validator_accept_everything). + +-include("rabbit.hrl"). + +-behaviour(rabbit_credential_validator). + +%% +%% API +%% + +-export([validate/2]). + +-spec validate(rabbit_types:username(), rabbit_types:password()) -> 'ok' | {'error', string()}. + +validate(_Username, _Password) -> + ok. diff --git a/src/rabbit_credential_validator_min_password_length.erl b/src/rabbit_credential_validator_min_password_length.erl new file mode 100644 index 0000000000..78239fc71b --- /dev/null +++ b/src/rabbit_credential_validator_min_password_length.erl @@ -0,0 +1,56 @@ +%% 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) 2007-2016 Pivotal Software, Inc. All rights reserved. +%% + +-module(rabbit_credential_validator_min_password_length). + +-include("rabbit.hrl"). + +-behaviour(rabbit_credential_validator). + +%% accommodates default (localhost-only) user credentials, +%% guest/guest +-define(DEFAULT_MIN_LENGTH, 5). + +%% +%% API +%% + +-export([validate/2]). +%% for tests +-export([validate/3]). + +-spec validate(rabbit_types:username(), rabbit_types:password()) -> 'ok' | {'error', string()}. + +validate(Username, Password) -> + MinLength = case application:get_env(rabbit, credential_validator) of + undefined -> + ?DEFAULT_MIN_LENGTH; + {ok, Proplist} -> + case proplists:get_value(min_length, Proplist) of + undefined -> ?DEFAULT_MIN_LENGTH; + Value -> rabbit_data_coercion:to_integer(Value) + end + end, + validate(Username, Password, MinLength). + + +-spec validate(rabbit_types:username(), rabbit_types:password(), integer()) -> 'ok' | {'error', string(), [any()]}. + +validate(_Username, Password, MinLength) -> + case size(Password) >= MinLength of + true -> ok; + false -> {error, rabbit_misc:format("minimum required password length is ~B", [MinLength])} + end. diff --git a/src/rabbit_credential_validator_password_regexp.erl b/src/rabbit_credential_validator_password_regexp.erl new file mode 100644 index 0000000000..b516175126 --- /dev/null +++ b/src/rabbit_credential_validator_password_regexp.erl @@ -0,0 +1,51 @@ +%% 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) 2007-2016 Pivotal Software, Inc. All rights reserved. +%% + + +%% A `rabbit_credential_validator` implementation that matches +%% password against a pre-configured regular expression. +-module(rabbit_credential_validator_password_regexp). + +-include("rabbit.hrl"). + +-behaviour(rabbit_credential_validator). + +%% +%% API +%% + +-export([validate/2]). +%% for tests +-export([validate/3]). + +-spec validate(rabbit_types:username(), rabbit_types:password()) -> 'ok' | {'error', string()}. + +validate(Username, Password) -> + {ok, Proplist} = application:get_env(rabbit, credential_validator), + Regexp = case proplists:get_value(regexp, Proplist) of + undefined -> {error, "rabbit.credential_validator.regexp config key is undefined"}; + Value -> rabbit_data_coercion:to_list(Value) + end, + validate(Username, Password, Regexp). + + +-spec validate(rabbit_types:username(), rabbit_types:password(), string()) -> 'ok' | {'error', string(), [any()]}. + +validate(_Username, Password, Pattern) -> + case re:run(rabbit_data_coercion:to_list(Password), Pattern) of + {match, _} -> ok; + nomatch -> {error, "provided password does not match the validator regular expression"} + end. diff --git a/src/rabbit_plugins.erl b/src/rabbit_plugins.erl index 54f4180244..262f20913f 100644 --- a/src/rabbit_plugins.erl +++ b/src/rabbit_plugins.erl @@ -15,7 +15,7 @@ %% -module(rabbit_plugins). --include("rabbit.hrl"). +-include_lib("rabbit_common/include/rabbit.hrl"). -include_lib("stdlib/include/zip.hrl"). -export([setup/0, active/0, read_enabled/1, list/1, list/2, dependencies/3, running_plugins/0]). diff --git a/src/rabbit_table.erl b/src/rabbit_table.erl index 5154f91494..040075ea87 100644 --- a/src/rabbit_table.erl +++ b/src/rabbit_table.erl @@ -18,7 +18,8 @@ -export([create/0, create_local_copy/1, wait_for_replicated/1, wait/1, force_load/0, is_present/0, is_empty/0, needs_default_data/0, - check_schema_integrity/1, clear_ram_only_tables/0, retry_timeout/0]). + check_schema_integrity/1, clear_ram_only_tables/0, retry_timeout/0, + wait_for_replicated/0]). %% for testing purposes -export([definitions/0]). @@ -31,6 +32,7 @@ -spec create() -> 'ok'. -spec create_local_copy('disc' | 'ram') -> 'ok'. -spec wait_for_replicated(retry()) -> 'ok'. +-spec wait_for_replicated() -> 'ok'. -spec wait([atom()]) -> 'ok'. -spec retry_timeout() -> {non_neg_integer() | infinity, non_neg_integer()}. -spec force_load() -> 'ok'. @@ -79,6 +81,11 @@ create_local_copy(ram) -> create_local_copies(ram), create_local_copy(schema, ram_copies). +%% This arity only exists for backwards compatibility with certain +%% plugins. See https://github.com/rabbitmq/rabbitmq-clusterer/issues/19. +wait_for_replicated() -> + wait_for_replicated(false). + wait_for_replicated(Retry) -> wait([Tab || {Tab, TabDef} <- definitions(), not lists:member({local_content, true}, TabDef)], Retry). diff --git a/src/rabbit_variable_queue.erl b/src/rabbit_variable_queue.erl index 9dbd4fdbf2..5581143e69 100644 --- a/src/rabbit_variable_queue.erl +++ b/src/rabbit_variable_queue.erl @@ -447,21 +447,28 @@ %% rabbit_amqqueue_process need fairly fresh rates. -define(MSGS_PER_RATE_CALC, 100). - %% we define the garbage collector threshold -%% it needs to tune the GC calls inside `reduce_memory_use` -%% see: rabbitmq-server-973 and `maybe_execute_gc` function --define(DEFAULT_EXPLICIT_GC_RUN_OP_THRESHOLD, 250). --define(EXPLICIT_GC_RUN_OP_THRESHOLD, +%% it needs to tune the `reduce_memory_use` calls. Thus, the garbage collection. +%% see: rabbitmq-server-973 and rabbitmq-server-964 +-define(DEFAULT_EXPLICIT_GC_RUN_OP_THRESHOLD, 1000). +-define(EXPLICIT_GC_RUN_OP_THRESHOLD(Mode), case get(explicit_gc_run_operation_threshold) of undefined -> - Val = rabbit_misc:get_env(rabbit, lazy_queue_explicit_gc_run_operation_threshold, - ?DEFAULT_EXPLICIT_GC_RUN_OP_THRESHOLD), + Val = explicit_gc_run_operation_threshold_for_mode(Mode), put(explicit_gc_run_operation_threshold, Val), Val; Val -> Val end). +explicit_gc_run_operation_threshold_for_mode(Mode) -> + {Key, Fallback} = case Mode of + lazy -> {lazy_queue_explicit_gc_run_operation_threshold, + ?DEFAULT_EXPLICIT_GC_RUN_OP_THRESHOLD}; + _ -> {queue_explicit_gc_run_operation_threshold, + ?DEFAULT_EXPLICIT_GC_RUN_OP_THRESHOLD} + end, + rabbit_misc:get_env(rabbit, Key, Fallback). + %%---------------------------------------------------------------------------- %% Public API %%---------------------------------------------------------------------------- @@ -637,27 +644,27 @@ publish(Msg, MsgProps, IsDelivered, ChPid, Flow, State) -> publish1(Msg, MsgProps, IsDelivered, ChPid, Flow, fun maybe_write_to_disk/4, State), - a(reduce_memory_use(maybe_update_rates(State1))). + a(maybe_reduce_memory_use(maybe_update_rates(State1))). batch_publish(Publishes, ChPid, Flow, State) -> {ChPid, Flow, State1} = lists:foldl(fun batch_publish1/2, {ChPid, Flow, State}, Publishes), State2 = ui(State1), - a(reduce_memory_use(maybe_update_rates(State2))). + a(maybe_reduce_memory_use(maybe_update_rates(State2))). publish_delivered(Msg, MsgProps, ChPid, Flow, State) -> {SeqId, State1} = publish_delivered1(Msg, MsgProps, ChPid, Flow, fun maybe_write_to_disk/4, State), - {SeqId, a(reduce_memory_use(maybe_update_rates(State1)))}. + {SeqId, a(maybe_reduce_memory_use(maybe_update_rates(State1)))}. batch_publish_delivered(Publishes, ChPid, Flow, State) -> {ChPid, Flow, SeqIds, State1} = lists:foldl(fun batch_publish_delivered1/2, {ChPid, Flow, [], State}, Publishes), State2 = ui(State1), - {lists:reverse(SeqIds), a(reduce_memory_use(maybe_update_rates(State2)))}. + {lists:reverse(SeqIds), a(maybe_reduce_memory_use(maybe_update_rates(State2)))}. discard(_MsgId, _ChPid, _Flow, State) -> State. @@ -761,7 +768,7 @@ requeue(AckTags, #vqstate { mode = default, {Delta1, MsgIds2, State3} = delta_merge(SeqIds1, Delta, MsgIds1, State2), MsgCount = length(MsgIds2), - {MsgIds2, a(reduce_memory_use( + {MsgIds2, a(maybe_reduce_memory_use( maybe_update_rates(ui( State3 #vqstate { delta = Delta1, q3 = Q3a, @@ -779,7 +786,7 @@ requeue(AckTags, #vqstate { mode = lazy, {Delta1, MsgIds1, State2} = delta_merge(SeqIds, Delta, MsgIds, State1), MsgCount = length(MsgIds1), - {MsgIds1, a(reduce_memory_use( + {MsgIds1, a(maybe_reduce_memory_use( maybe_update_rates(ui( State2 #vqstate { delta = Delta1, q3 = Q3a, @@ -829,7 +836,7 @@ set_ram_duration_target( (TargetRamCount =/= infinity andalso TargetRamCount1 >= TargetRamCount) of true -> State1; - false -> reduce_memory_use(State1) + false -> maybe_reduce_memory_use(State1) end). maybe_update_rates(State = #vqstate{ in_counter = InCount, @@ -911,7 +918,7 @@ timeout(State = #vqstate { index_state = IndexState }) -> handle_pre_hibernate(State = #vqstate { index_state = IndexState }) -> State #vqstate { index_state = rabbit_queue_index:flush(IndexState) }. -resume(State) -> a(reduce_memory_use(State)). +resume(State) -> a(maybe_reduce_memory_use(State)). msg_rates(#vqstate { rates = #rates { in = AvgIngressRate, out = AvgEgressRate } }) -> @@ -2364,12 +2371,12 @@ ifold(Fun, Acc, Its, State) -> %% Phase changes %%---------------------------------------------------------------------------- -maybe_execute_gc(State = #vqstate {memory_reduction_run_count = MRedRunCount}) -> - case MRedRunCount >= ?EXPLICIT_GC_RUN_OP_THRESHOLD of - true -> garbage_collect(), - State#vqstate{memory_reduction_run_count = 0}; - false -> State#vqstate{memory_reduction_run_count = MRedRunCount + 1} - +maybe_reduce_memory_use(State = #vqstate {memory_reduction_run_count = MRedRunCount, + mode = Mode}) -> + case MRedRunCount >= ?EXPLICIT_GC_RUN_OP_THRESHOLD(Mode) of + true -> State1 = reduce_memory_use(State), + State1#vqstate{memory_reduction_run_count = 0}; + false -> State#vqstate{memory_reduction_run_count = MRedRunCount + 1} end. reduce_memory_use(State = #vqstate { target_ram_count = infinity }) -> @@ -2384,7 +2391,6 @@ reduce_memory_use(State = #vqstate { out = AvgEgress, ack_in = AvgAckIngress, ack_out = AvgAckEgress } }) -> - State1 = #vqstate { q2 = Q2, q3 = Q3 } = case chunk_size(RamMsgCount + gb_trees:size(RPA), TargetRamCount) of 0 -> State; @@ -2444,7 +2450,8 @@ reduce_memory_use(State = #vqstate { S2 -> push_betas_to_deltas(S2, State1) end, - maybe_execute_gc(State3). + garbage_collect(), + State3. limit_ram_acks(0, State) -> {0, ui(State)}; diff --git a/test/clustering_management_SUITE.erl b/test/clustering_management_SUITE.erl index 9b605d07ae..3253695364 100644 --- a/test/clustering_management_SUITE.erl +++ b/test/clustering_management_SUITE.erl @@ -644,7 +644,7 @@ assert_not_clustered(Node) -> assert_failure(Fun) -> case catch Fun() of - {error, Code, Reason} -> Reason; + {error, _Code, Reason} -> Reason; {error, Reason} -> Reason; {error_string, Reason} -> Reason; {badrpc, {'EXIT', Reason}} -> Reason; diff --git a/test/config_schema_SUITE_data/snippets.config b/test/config_schema_SUITE_data/snippets.config index f5832981bc..7a854a10e1 100644 --- a/test/config_schema_SUITE_data/snippets.config +++ b/test/config_schema_SUITE_data/snippets.config @@ -786,5 +786,26 @@ background_gc_target_interval = 30000", [{rabbit, [ {background_gc_enabled, false}, {background_gc_target_interval, 30000} +]}],[]}, + +{78.1, +"credential_validator.validation_backend = rabbit_credential_validator_min_password_length +credential_validator.min_length = 10", +[{rabbit, [ + {credential_validator, [ + {validation_backend, rabbit_credential_validator_min_password_length}, + {min_length, 10} + ]} +]}],[]}, + +{78.2, +"credential_validator.validation_backend = rabbit_credential_validator_password_regexp +credential_validator.regexp = ^abc\\d+", +[{rabbit, [ + {credential_validator, [ + {validation_backend, rabbit_credential_validator_password_regexp}, + {regexp, "^abc\\d+"} + ]} ]}],[]} + ]. diff --git a/test/credential_validation_SUITE.erl b/test/credential_validation_SUITE.erl new file mode 100644 index 0000000000..3ed2e832bd --- /dev/null +++ b/test/credential_validation_SUITE.erl @@ -0,0 +1,275 @@ +%% 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) 2007-2016 Pivotal Software, Inc. All rights reserved. +%% + +-module(credential_validation_SUITE). + +-compile(export_all). +-include_lib("proper/include/proper.hrl"). +-include_lib("common_test/include/ct.hrl"). +-include_lib("eunit/include/eunit.hrl"). + +all() -> + [ + {group, unit}, + {group, integration} + ]. + +groups() -> + [ + {integration, [], [ + min_length_integration_fails + , regexp_integration_fails + , min_length_integration_succeeds + , regexp_integration_succeeds + , min_length_change_password_integration_fails + , regexp_change_password_integration_fails + , min_length_change_password_integration_succeeds + , regexp_change_password_integration_succeeds + ]}, + {unit, [parallel], [ + basic_unconditionally_accepting_succeeds, + min_length_fails, + min_length_succeeds, + min_length_proper_fails, + min_length_proper_succeeds, + regexp_fails, + regexp_succeeds, + regexp_proper_fails, + regexp_proper_succeeds + ]} +]. + +suite() -> + [ + {timetrap, {minutes, 4}} + ]. + +%% +%% 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(integration, Config) -> + Suffix = rabbit_ct_helpers:testcase_absname(Config, "", "-"), + Config1 = rabbit_ct_helpers:set_config(Config, [ + {rmq_nodes_count, 1}, + {rmq_nodename_suffix, Suffix} + ]), + rabbit_ct_helpers:run_steps(Config1, + rabbit_ct_broker_helpers:setup_steps()); + +init_per_group(unit, Config) -> + Config. + +end_per_group(integration, Config) -> + rabbit_ct_broker_helpers:switch_credential_validator(Config, accept_everything), + rabbit_ct_helpers:run_steps(Config, + rabbit_ct_broker_helpers:teardown_steps()); +end_per_group(unit, Config) -> + Config. + +-define(USERNAME, <<"abc">>). + +init_per_testcase(Testcase, Config) -> + rabbit_ct_helpers:testcase_started(Config, Testcase). + +end_per_testcase(Testcase, Config) -> + rabbit_ct_helpers:testcase_finished(Config, Testcase). + +%% +%% Test Cases +%% + +basic_unconditionally_accepting_succeeds(_Config) -> + F = fun rabbit_credential_validator_accept_everything:validate/2, + + Pwd1 = crypto:strong_rand_bytes(1), + ?assertEqual(ok, F(?USERNAME, Pwd1)), + Pwd2 = crypto:strong_rand_bytes(5), + ?assertEqual(ok, F(?USERNAME, Pwd2)), + Pwd3 = crypto:strong_rand_bytes(10), + ?assertEqual(ok, F(?USERNAME, Pwd3)), + Pwd4 = crypto:strong_rand_bytes(50), + ?assertEqual(ok, F(?USERNAME, Pwd4)), + Pwd5 = crypto:strong_rand_bytes(100), + ?assertEqual(ok, F(?USERNAME, Pwd5)), + Pwd6 = crypto:strong_rand_bytes(1000), + ?assertEqual(ok, F(?USERNAME, Pwd6)). + +min_length_fails(_Config) -> + F = fun rabbit_credential_validator_min_password_length:validate/3, + + Pwd1 = crypto:strong_rand_bytes(1), + ?assertMatch({error, _}, F(?USERNAME, Pwd1, 5)), + Pwd2 = crypto:strong_rand_bytes(5), + ?assertMatch({error, _}, F(?USERNAME, Pwd2, 6)), + Pwd3 = crypto:strong_rand_bytes(10), + ?assertMatch({error, _}, F(?USERNAME, Pwd3, 15)), + Pwd4 = crypto:strong_rand_bytes(50), + ?assertMatch({error, _}, F(?USERNAME, Pwd4, 60)). + +min_length_succeeds(_Config) -> + F = fun rabbit_credential_validator_min_password_length:validate/3, + + ?assertEqual(ok, F(?USERNAME, crypto:strong_rand_bytes(1), 1)), + ?assertEqual(ok, F(?USERNAME, crypto:strong_rand_bytes(6), 6)), + ?assertEqual(ok, F(?USERNAME, crypto:strong_rand_bytes(7), 6)), + ?assertEqual(ok, F(?USERNAME, crypto:strong_rand_bytes(20), 20)), + ?assertEqual(ok, F(?USERNAME, crypto:strong_rand_bytes(40), 30)), + ?assertEqual(ok, F(?USERNAME, crypto:strong_rand_bytes(50), 50)). + +min_length_proper_fails(_Config) -> + rabbit_ct_proper_helpers:run_proper(fun prop_min_length_fails_validation/0, [], 500). + +min_length_proper_succeeds(_Config) -> + rabbit_ct_proper_helpers:run_proper(fun prop_min_length_passes_validation/0, [], 500). + +regexp_fails(_Config) -> + F = fun rabbit_credential_validator_password_regexp:validate/3, + + ?assertMatch({error, _}, F(?USERNAME, <<"abc">>, "^xyz")), + ?assertMatch({error, _}, F(?USERNAME, <<"abcdef">>, "^xyz")), + ?assertMatch({error, _}, F(?USERNAME, <<"abcxyz">>, "^abc\\d+")). + +regexp_succeeds(_Config) -> + F = fun rabbit_credential_validator_password_regexp:validate/3, + + ?assertEqual(ok, F(?USERNAME, <<"abc">>, "^abc")), + ?assertEqual(ok, F(?USERNAME, <<"abcdef">>, "^abc")), + ?assertEqual(ok, F(?USERNAME, <<"abc123">>, "^abc\\d+")). + +regexp_proper_fails(_Config) -> + rabbit_ct_proper_helpers:run_proper(fun prop_regexp_fails_validation/0, [], 500). + +regexp_proper_succeeds(_Config) -> + rabbit_ct_proper_helpers:run_proper(fun prop_regexp_passes_validation/0, [], 500). + +min_length_integration_fails(Config) -> + rabbit_ct_broker_helpers:delete_user(Config, ?USERNAME), + rabbit_ct_broker_helpers:switch_credential_validator(Config, min_length, 50), + ?assertMatch(rabbit_credential_validator_min_password_length, validator_backend(Config)), + ?assertMatch({error, "minimum required password length is 50"}, + rabbit_ct_broker_helpers:add_user(Config, ?USERNAME, <<"_">>)). + +regexp_integration_fails(Config) -> + rabbit_ct_broker_helpers:delete_user(Config, ?USERNAME), + rabbit_ct_broker_helpers:switch_credential_validator(Config, regexp), + ?assertMatch(rabbit_credential_validator_password_regexp, validator_backend(Config)), + ?assertMatch({error, _}, rabbit_ct_broker_helpers:add_user(Config, ?USERNAME, <<"_">>)). + +min_length_integration_succeeds(Config) -> + rabbit_ct_broker_helpers:delete_user(Config, ?USERNAME), + rabbit_ct_broker_helpers:switch_credential_validator(Config, min_length, 5), + ?assertMatch(rabbit_credential_validator_min_password_length, validator_backend(Config)), + ?assertMatch(ok, rabbit_ct_broker_helpers:add_user(Config, ?USERNAME, <<"abcdefghi">>)). + +regexp_integration_succeeds(Config) -> + rabbit_ct_broker_helpers:delete_user(Config, ?USERNAME), + rabbit_ct_broker_helpers:switch_credential_validator(Config, regexp), + ?assertMatch(rabbit_credential_validator_password_regexp, validator_backend(Config)), + ?assertMatch(ok, rabbit_ct_broker_helpers:add_user(Config, ?USERNAME, <<"xyz12345678901">>)). + +min_length_change_password_integration_fails(Config) -> + rabbit_ct_broker_helpers:delete_user(Config, ?USERNAME), + rabbit_ct_broker_helpers:switch_credential_validator(Config, accept_everything), + rabbit_ct_broker_helpers:add_user(Config, ?USERNAME, <<"abcdefghi">>), + rabbit_ct_broker_helpers:switch_credential_validator(Config, min_length, 50), + ?assertMatch(rabbit_credential_validator_min_password_length, validator_backend(Config)), + ?assertMatch({error, "minimum required password length is 50"}, + rabbit_ct_broker_helpers:change_password(Config, ?USERNAME, <<"_">>)). + +regexp_change_password_integration_fails(Config) -> + rabbit_ct_broker_helpers:delete_user(Config, ?USERNAME), + rabbit_ct_broker_helpers:switch_credential_validator(Config, accept_everything), + rabbit_ct_broker_helpers:add_user(Config, ?USERNAME, <<"abcdefghi">>), + rabbit_ct_broker_helpers:switch_credential_validator(Config, regexp), + ?assertMatch(rabbit_credential_validator_password_regexp, validator_backend(Config)), + ?assertMatch({error, _}, rabbit_ct_broker_helpers:change_password(Config, ?USERNAME, <<"_">>)). + +min_length_change_password_integration_succeeds(Config) -> + rabbit_ct_broker_helpers:delete_user(Config, ?USERNAME), + rabbit_ct_broker_helpers:switch_credential_validator(Config, accept_everything), + rabbit_ct_broker_helpers:add_user(Config, ?USERNAME, <<"abcdefghi">>), + rabbit_ct_broker_helpers:switch_credential_validator(Config, min_length, 5), + ?assertMatch(rabbit_credential_validator_min_password_length, validator_backend(Config)), + ?assertMatch(ok, rabbit_ct_broker_helpers:change_password(Config, ?USERNAME, <<"abcdefghi">>)). + +regexp_change_password_integration_succeeds(Config) -> + rabbit_ct_broker_helpers:delete_user(Config, ?USERNAME), + rabbit_ct_broker_helpers:switch_credential_validator(Config, accept_everything), + rabbit_ct_broker_helpers:add_user(Config, ?USERNAME, <<"abcdefghi">>), + rabbit_ct_broker_helpers:switch_credential_validator(Config, regexp), + ?assertMatch(rabbit_credential_validator_password_regexp, validator_backend(Config)), + ?assertMatch(ok, rabbit_ct_broker_helpers:change_password(Config, ?USERNAME, <<"xyz12345678901">>)). + +%% +%% PropEr +%% + +prop_min_length_fails_validation() -> + N = 5, + F = fun rabbit_credential_validator_min_password_length:validate/3, + ?FORALL(Val, binary(N), + ?FORALL(Length, choose(N + 1, 100), + failed_validation(F(?USERNAME, Val, Length + 1)))). + +prop_min_length_passes_validation() -> + N = 20, + F = fun rabbit_credential_validator_min_password_length:validate/3, + ?FORALL(Val, binary(N), + ?FORALL(Length, choose(1, N - 1), + passed_validation(F(?USERNAME, Val, Length)))). + +prop_regexp_fails_validation() -> + N = 5, + F = fun rabbit_credential_validator_password_regexp:validate/3, + ?FORALL(Val, binary(N), + ?FORALL(Length, choose(N + 1, 100), + failed_validation(F(?USERNAME, Val, regexp_that_requires_length_of_at_least(Length + 1))))). + +prop_regexp_passes_validation() -> + N = 5, + F = fun rabbit_credential_validator_password_regexp:validate/3, + ?FORALL(Val, binary(N), + passed_validation(F(?USERNAME, Val, regexp_that_requires_length_of_at_most(size(Val) + 1)))). + +%% +%% Helpers +%% + +passed_validation(ok) -> + true; +passed_validation({error, _}) -> + false. + +failed_validation(Result) -> + not passed_validation(Result). + +regexp_that_requires_length_of_at_least(N) when is_integer(N) -> + rabbit_misc:format("^[a-zA-Z0-9]{~p,~p}", [N, N + 10]). + +regexp_that_requires_length_of_at_most(N) when is_integer(N) -> + rabbit_misc:format("^[a-zA-Z0-9]{0,~p}", [N]). + +validator_backend(Config) -> + rabbit_ct_broker_helpers:rpc(Config, 0, rabbit_credential_validation, backend, []). + diff --git a/test/per_user_connection_tracking_SUITE.erl b/test/per_user_connection_tracking_SUITE.erl new file mode 100644 index 0000000000..7f93aef1ac --- /dev/null +++ b/test/per_user_connection_tracking_SUITE.erl @@ -0,0 +1,280 @@ +%% 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) 2011-2016 Pivotal Software, Inc. All rights reserved. +%% + +-module(per_user_connection_tracking_SUITE). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("amqp_client/include/amqp_client.hrl"). +-include_lib("eunit/include/eunit.hrl"). + +-compile(export_all). + +all() -> + [ + {group, cluster_size_1_network}, + {group, cluster_size_2_network}, + {group, cluster_size_1_direct}, + {group, cluster_size_2_direct} + ]. + +groups() -> + ClusterSize1Tests = [ + single_node_list_of_user, + single_node_user_deletion_forces_connection_closure + ], + ClusterSize2Tests = [ + cluster_user_deletion_forces_connection_closure + ], + [ + {cluster_size_1_network, [], ClusterSize1Tests}, + {cluster_size_2_network, [], ClusterSize2Tests}, + {cluster_size_1_direct, [], ClusterSize1Tests}, + {cluster_size_2_direct, [], ClusterSize2Tests} + ]. + +suite() -> + [ + %% If a test hangs, no need to wait for 30 minutes. + {timetrap, {minutes, 8}} + ]. + +%% ------------------------------------------------------------------- +%% Testsuite setup/teardown. +%% ------------------------------------------------------------------- + +init_per_suite(Config) -> + rabbit_ct_helpers:log_environment(), + rabbit_ct_helpers:run_setup_steps(Config, [ + fun rabbit_ct_broker_helpers:enable_dist_proxy_manager/1 + ]). + +end_per_suite(Config) -> + rabbit_ct_helpers:run_teardown_steps(Config). + +init_per_group(cluster_size_1_network, Config) -> + Config1 = rabbit_ct_helpers:set_config(Config, [{connection_type, network}]), + init_per_multinode_group(cluster_size_1_network, Config1, 1); +init_per_group(cluster_size_2_network, Config) -> + Config1 = rabbit_ct_helpers:set_config(Config, [{connection_type, network}]), + init_per_multinode_group(cluster_size_2_network, Config1, 2); +init_per_group(cluster_size_1_direct, Config) -> + Config1 = rabbit_ct_helpers:set_config(Config, [{connection_type, direct}]), + init_per_multinode_group(cluster_size_1_direct, Config1, 1); +init_per_group(cluster_size_2_direct, Config) -> + Config1 = rabbit_ct_helpers:set_config(Config, [{connection_type, direct}]), + init_per_multinode_group(cluster_size_2_direct, Config1, 2). + +init_per_multinode_group(_Group, Config, NodeCount) -> + Suffix = rabbit_ct_helpers:testcase_absname(Config, "", "-"), + Config1 = rabbit_ct_helpers:set_config(Config, [ + {rmq_nodes_count, NodeCount}, + {rmq_nodename_suffix, Suffix} + ]), + rabbit_ct_helpers:run_steps(Config1, + rabbit_ct_broker_helpers:setup_steps() ++ + rabbit_ct_client_helpers:setup_steps()). + +end_per_group(_Group, Config) -> + rabbit_ct_helpers:run_steps(Config, + rabbit_ct_client_helpers:teardown_steps() ++ + rabbit_ct_broker_helpers:teardown_steps()). + +init_per_testcase(Testcase, Config) -> + rabbit_ct_helpers:testcase_started(Config, Testcase), + clear_all_connection_tracking_tables(Config), + Config. + +end_per_testcase(Testcase, Config) -> + clear_all_connection_tracking_tables(Config), + rabbit_ct_helpers:testcase_finished(Config, Testcase). + +clear_all_connection_tracking_tables(Config) -> + [rabbit_ct_broker_helpers:rpc(Config, + N, + rabbit_connection_tracking, + clear_tracked_connection_tables_for_this_node, + []) || N <- rabbit_ct_broker_helpers:get_node_configs(Config, nodename)]. + +%% ------------------------------------------------------------------- +%% Test cases. +%% ------------------------------------------------------------------- +single_node_list_of_user(Config) -> + Username = proplists:get_value(rmq_username, Config), + Username2 = <<"guest2">>, + + Vhost = proplists:get_value(rmq_vhost, Config), + + rabbit_ct_broker_helpers:add_user(Config, Username2), + rabbit_ct_broker_helpers:set_full_permissions(Config, Username2, Vhost), + + ?assertEqual(0, length(connections_in(Config, Username))), + ?assertEqual(0, length(connections_in(Config, Username2))), + + [Conn1] = open_connections(Config, [0]), + [#tracked_connection{username = Username}] = connections_in(Config, Username), + close_connections([Conn1]), + ?assertEqual(0, length(connections_in(Config, Username))), + + [Conn2] = open_connections(Config, [{0, Username2}]), + [#tracked_connection{username = Username2}] = connections_in(Config, Username2), + + [Conn3] = open_connections(Config, [0]), + [#tracked_connection{username = Username}] = connections_in(Config, Username), + + [Conn4] = open_connections(Config, [0]), + kill_connections([Conn4]), + [#tracked_connection{username = Username}] = connections_in(Config, Username), + + [Conn5] = open_connections(Config, [0]), + [Username, Username] = + lists:map(fun (#tracked_connection{username = U}) -> U end, + connections_in(Config, Username)), + + close_connections([Conn2, Conn3, Conn5]), + rabbit_ct_broker_helpers:delete_user(Config, Username2), + ?assertEqual(0, length(all_connections(Config))). + +single_node_user_deletion_forces_connection_closure(Config) -> + Username = proplists:get_value(rmq_username, Config), + Username2 = <<"guest2">>, + + Vhost = proplists:get_value(rmq_vhost, Config), + + rabbit_ct_broker_helpers:add_user(Config, Username2), + rabbit_ct_broker_helpers:set_full_permissions(Config, Username2, Vhost), + + ?assertEqual(0, count_connections_in(Config, Username)), + ?assertEqual(0, count_connections_in(Config, Username2)), + + [Conn1] = open_connections(Config, [0]), + ?assertEqual(1, count_connections_in(Config, Username)), + + [_Conn2] = open_connections(Config, [{0, Username2}]), + ?assertEqual(1, count_connections_in(Config, Username2)), + + rabbit_ct_broker_helpers:delete_user(Config, Username2), + timer:sleep(200), + ?assertEqual(0, count_connections_in(Config, Username2)), + + close_connections([Conn1]), + ?assertEqual(0, count_connections_in(Config, Username)). + +cluster_user_deletion_forces_connection_closure(Config) -> + Username = proplists:get_value(rmq_username, Config), + Username2 = <<"guest2">>, + + Vhost = proplists:get_value(rmq_vhost, Config), + + rabbit_ct_broker_helpers:add_user(Config, Username2), + rabbit_ct_broker_helpers:set_full_permissions(Config, Username2, Vhost), + + ?assertEqual(0, count_connections_in(Config, Username)), + ?assertEqual(0, count_connections_in(Config, Username2)), + + [Conn1] = open_connections(Config, [{0, Username}]), + ?assertEqual(1, count_connections_in(Config, Username)), + + [_Conn2] = open_connections(Config, [{1, Username2}]), + ?assertEqual(1, count_connections_in(Config, Username2)), + + rabbit_ct_broker_helpers:delete_user(Config, Username2), + timer:sleep(200), + ?assertEqual(0, count_connections_in(Config, Username2)), + + close_connections([Conn1]), + ?assertEqual(0, count_connections_in(Config, Username)). + +%% ------------------------------------------------------------------- +%% Helpers +%% ------------------------------------------------------------------- + +open_connections(Config, NodesAndUsers) -> + % Randomly select connection type + OpenConnectionFun = case ?config(connection_type, Config) of + network -> open_unmanaged_connection; + direct -> open_unmanaged_connection_direct + end, + Conns = lists:map(fun + ({Node, User}) -> + rabbit_ct_client_helpers:OpenConnectionFun(Config, Node, + User, User); + (Node) -> + rabbit_ct_client_helpers:OpenConnectionFun(Config, Node) + end, NodesAndUsers), + timer:sleep(500), + Conns. + +close_connections(Conns) -> + lists:foreach(fun + (Conn) -> + rabbit_ct_client_helpers:close_connection(Conn) + end, Conns), + timer:sleep(500). + +kill_connections(Conns) -> + lists:foreach(fun + (Conn) -> + (catch exit(Conn, please_terminate)) + end, Conns), + timer:sleep(500). + + +count_connections_in(Config, Username) -> + length(connections_in(Config, Username)). + +connections_in(Config, Username) -> + connections_in(Config, 0, Username). +connections_in(Config, NodeIndex, Username) -> + rabbit_ct_broker_helpers:rpc(Config, NodeIndex, + rabbit_connection_tracking, + list_of_user, [Username]). + +all_connections(Config) -> + all_connections(Config, 0). +all_connections(Config, NodeIndex) -> + rabbit_ct_broker_helpers:rpc(Config, NodeIndex, + rabbit_connection_tracking, + list, []). + +set_up_vhost(Config, VHost) -> + rabbit_ct_broker_helpers:add_vhost(Config, VHost), + rabbit_ct_broker_helpers:set_full_permissions(Config, <<"guest">>, VHost), + set_vhost_connection_limit(Config, VHost, -1). + +set_vhost_connection_limit(Config, VHost, Count) -> + set_vhost_connection_limit(Config, 0, VHost, Count). + +set_vhost_connection_limit(Config, NodeIndex, VHost, Count) -> + Node = rabbit_ct_broker_helpers:get_node_config( + Config, NodeIndex, nodename), + ok = rabbit_ct_broker_helpers:control_action( + set_vhost_limits, Node, + ["{\"max-connections\": " ++ integer_to_list(Count) ++ "}"], + [{"-p", binary_to_list(VHost)}]). + +await_running_node_refresh(_Config, _NodeIndex) -> + timer:sleep(250). + +expect_that_client_connection_is_rejected(Config) -> + expect_that_client_connection_is_rejected(Config, 0). + +expect_that_client_connection_is_rejected(Config, NodeIndex) -> + {error, not_allowed} = + rabbit_ct_client_helpers:open_unmanaged_connection(Config, NodeIndex). + +expect_that_client_connection_is_rejected(Config, NodeIndex, VHost) -> + {error, not_allowed} = + rabbit_ct_client_helpers:open_unmanaged_connection(Config, NodeIndex, VHost). diff --git a/test/unit_inbroker_SUITE.erl b/test/unit_inbroker_SUITE.erl index af86371fc2..91a3eb32a6 100644 --- a/test/unit_inbroker_SUITE.erl +++ b/test/unit_inbroker_SUITE.erl @@ -237,9 +237,21 @@ orelse Group =:= backing_queue_embed_limit_1024 -> end_per_group1(_, Config) -> Config. +init_per_testcase(Testcase, Config) when Testcase == variable_queue_requeue; + Testcase == variable_queue_fold -> + ok = rabbit_ct_broker_helpers:rpc( + Config, 0, application, set_env, + [rabbit, queue_explicit_gc_run_operation_threshold, 0]), + rabbit_ct_helpers:testcase_started(Config, Testcase); init_per_testcase(Testcase, Config) -> rabbit_ct_helpers:testcase_started(Config, Testcase). +end_per_testcase(Testcase, Config) when Testcase == variable_queue_requeue; + Testcase == variable_queue_fold -> + ok = rabbit_ct_broker_helpers:rpc( + Config, 0, application, set_env, + [rabbit, queue_explicit_gc_run_operation_threshold, 1000]), + rabbit_ct_helpers:testcase_finished(Config, Testcase); end_per_testcase(Testcase, Config) -> rabbit_ct_helpers:testcase_finished(Config, Testcase). diff --git a/test/worker_pool_SUITE.erl b/test/worker_pool_SUITE.erl index 7eb4d6fd04..9b6b0721a2 100644 --- a/test/worker_pool_SUITE.erl +++ b/test/worker_pool_SUITE.erl @@ -41,7 +41,7 @@ end_per_testcase(_, Config) -> unlink(Pool), exit(Pool, kill). -run_code_synchronously(Config) -> +run_code_synchronously(_) -> Self = self(), Test = make_ref(), Sleep = 200, @@ -63,7 +63,7 @@ run_code_synchronously(Config) -> % Worker is a separate process true = (Self /= Result). -run_code_asynchronously(Config) -> +run_code_asynchronously(_) -> Self = self(), Test = make_ref(), Sleep = 200, @@ -84,7 +84,7 @@ run_code_asynchronously(Config) -> % Worker is a separate process true = (Self /= Result). -set_timeout(Config) -> +set_timeout(_) -> Self = self(), Test = make_ref(), Worker = worker_pool:submit(?POOL_NAME, @@ -112,7 +112,7 @@ set_timeout(Config) -> end. -cancel_timeout(Config) -> +cancel_timeout(_) -> Self = self(), Test = make_ref(), Worker = worker_pool:submit(?POOL_NAME, @@ -146,7 +146,7 @@ cancel_timeout(Config) -> after 0 -> ok end. -cancel_timeout_by_setting(Config) -> +cancel_timeout_by_setting(_) -> Self = self(), Test = make_ref(), Worker = worker_pool:submit(?POOL_NAME, @@ -186,8 +186,3 @@ cancel_timeout_by_setting(Config) -> receive {hello_reset, Worker, Test} -> ok after 1000 -> exit(timeout_is_late) end. - - - - - |
