summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--Makefile2
-rw-r--r--src/truncate.erl75
-rw-r--r--test/credit_flow_SUITE.erl77
-rw-r--r--test/gm_SUITE.erl205
-rw-r--r--test/mirrored_supervisor_SUITE.erl335
-rw-r--r--test/mirrored_supervisor_SUITE_gs.erl66
-rw-r--r--test/msg_store_SUITE.erl62
-rw-r--r--test/password_hashing_SUITE.erl121
-rw-r--r--test/rabbit_ctl_timeout_SUITE.erl173
-rw-r--r--test/resource_monitor_SUITE.erl64
-rw-r--r--test/supervisor2_SUITE.erl90
-rw-r--r--test/truncate_SUITE.erl99
-rw-r--r--test/vm_memory_monitor_SUITE.erl42
14 files changed, 1342 insertions, 71 deletions
diff --git a/.gitignore b/.gitignore
index 3e0b548789..720f17d9b6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
.sw?
.*.sw?
*.beam
+*.coverdata
.erlang.mk/
cover/
debug/
@@ -11,6 +12,7 @@ ebin/
etc/
logs/
plugins/
+test/ct.cover.spec
PACKAGES/
diff --git a/Makefile b/Makefile
index 867ecdf978..266a4ed13d 100644
--- a/Makefile
+++ b/Makefile
@@ -25,6 +25,8 @@ DEP_PLUGINS = rabbit_common/mk/rabbitmq-run.mk \
rabbit_common/mk/rabbitmq-dist.mk \
rabbit_common/mk/rabbitmq-tools.mk
+CT_OPTS += -ct_hooks cth_surefire
+
# FIXME: Use erlang.mk patched for RabbitMQ, while waiting for PRs to be
# reviewed and merged.
diff --git a/src/truncate.erl b/src/truncate.erl
index 1c9b08ed27..a1586b0cb0 100644
--- a/src/truncate.erl
+++ b/src/truncate.erl
@@ -21,8 +21,10 @@
-record(params, {content, struct, content_dec, struct_dec}).
-export([log_event/2, term/2]).
-%% exported for testing
--export([test/0]).
+
+-ifdef(TEST).
+-export([term_size/3]).
+-endif.
log_event({Type, GL, {Pid, Format, Args}}, Params)
when Type =:= error orelse
@@ -123,72 +125,3 @@ tuple_term_size(_T, M, I, S, _W) when I > S ->
M;
tuple_term_size(T, M, I, S, W) ->
tuple_term_size(T, lim(term_size(element(I, T), M, W), 2 * W), I + 1, S, W).
-
-%%----------------------------------------------------------------------------
-
-test() ->
- test_short_examples_exactly(),
- test_term_limit(),
- test_large_examples_for_size(),
- ok.
-
-test_short_examples_exactly() ->
- F = fun (Term, Exp) ->
- Exp = term(Term, {1, {10, 10, 5, 5}}),
- Term = term(Term, {100000, {10, 10, 5, 5}})
- end,
- FSmall = fun (Term, Exp) ->
- Exp = term(Term, {1, {2, 2, 2, 2}}),
- Term = term(Term, {100000, {2, 2, 2, 2}})
- end,
- F([], []),
- F("h", "h"),
- F("hello world", "hello w..."),
- F([[h,e,l,l,o,' ',w,o,r,l,d]], [[h,e,l,l,o,'...']]),
- F([a|b], [a|b]),
- F(<<"hello">>, <<"hello">>),
- F([<<"hello world">>], [<<"he...">>]),
- F(<<1:1>>, <<1:1>>),
- F(<<1:81>>, <<0:56, "...">>),
- F({{{{a}}},{b},c,d,e,f,g,h,i,j,k}, {{{'...'}},{b},c,d,e,f,g,h,i,j,'...'}),
- FSmall({a,30,40,40,40,40}, {a,30,'...'}),
- FSmall([a,30,40,40,40,40], [a,30,'...']),
- P = spawn(fun() -> receive die -> ok end end),
- F([0, 0.0, <<1:1>>, F, P], [0, 0.0, <<1:1>>, F, P]),
- P ! die,
- R = make_ref(),
- F([R], [R]),
- ok.
-
-test_term_limit() ->
- W = erlang:system_info(wordsize),
- S = <<"abc">>,
- 1 = term_size(S, 4, W),
- limit_exceeded = term_size(S, 3, W),
- case 100 - term_size([S, S], 100, W) of
- 22 -> ok; %% 32 bit
- 38 -> ok %% 64 bit
- end,
- case 100 - term_size([S, [S]], 100, W) of
- 30 -> ok; %% ditto
- 54 -> ok
- end,
- limit_exceeded = term_size([S, S], 6, W),
- ok.
-
-test_large_examples_for_size() ->
- %% Real world values
- Shrink = fun(Term) -> term(Term, {1, {1000, 100, 50, 5}}) end,
- TestSize = fun(Term) ->
- true = 5000000 < size(term_to_binary(Term)),
- true = 500000 > size(term_to_binary(Shrink(Term)))
- end,
- TestSize(lists:seq(1, 5000000)),
- TestSize(recursive_list(1000, 10)),
- TestSize(recursive_list(5000, 20)),
- TestSize(gb_sets:from_list([I || I <- lists:seq(1, 1000000)])),
- TestSize(gb_trees:from_orddict([{I, I} || I <- lists:seq(1, 1000000)])),
- ok.
-
-recursive_list(S, 0) -> lists:seq(1, S);
-recursive_list(S, N) -> [recursive_list(S div N, N-1) || _ <- lists:seq(1, S)].
diff --git a/test/credit_flow_SUITE.erl b/test/credit_flow_SUITE.erl
new file mode 100644
index 0000000000..5747f8c8d8
--- /dev/null
+++ b/test/credit_flow_SUITE.erl
@@ -0,0 +1,77 @@
+%% 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-2015 Pivotal Software, Inc. All rights reserved.
+%%
+
+-module(credit_flow_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+
+-compile(export_all).
+
+all() ->
+ [
+ credit_flow_settings
+ ].
+
+%% -------------------------------------------------------------------
+%% Testsuite setup/teardown.
+%% -------------------------------------------------------------------
+
+init_per_suite(Config) ->
+ rabbit_ct_helpers:log_environment(),
+ rabbit_ct_helpers:run_setup_steps(?MODULE, Config).
+
+end_per_suite(Config) ->
+ rabbit_ct_helpers:run_teardown_steps(Config).
+
+%% ---------------------------------------------------------------------------
+%% Test cases
+%% ---------------------------------------------------------------------------
+
+credit_flow_settings(Config) ->
+ passed = rabbit_ct_broker_helpers:run_test_on_broker(
+ ?config(rmq_nodename, Config),
+ ?MODULE, credit_flow_settings1, [Config]).
+
+credit_flow_settings1(_Config) ->
+ %% default values
+ passed = test_proc(200, 50),
+
+ application:set_env(rabbit, credit_flow_default_credit, {100, 20}),
+ passed = test_proc(100, 20),
+
+ application:unset_env(rabbit, credit_flow_default_credit),
+
+ % back to defaults
+ passed = test_proc(200, 50),
+ passed.
+
+test_proc(InitialCredit, MoreCreditAfter) ->
+ Pid = spawn(fun dummy/0),
+ Pid ! {credit, self()},
+ {InitialCredit, MoreCreditAfter} =
+ receive
+ {credit, Val} -> Val
+ end,
+ passed.
+
+dummy() ->
+ credit_flow:send(self()),
+ receive
+ {credit, From} ->
+ From ! {credit, get(credit_flow_default_credit)};
+ _ ->
+ dummy()
+ end.
diff --git a/test/gm_SUITE.erl b/test/gm_SUITE.erl
new file mode 100644
index 0000000000..f5ccf75b70
--- /dev/null
+++ b/test/gm_SUITE.erl
@@ -0,0 +1,205 @@
+%% 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-2015 Pivotal Software, Inc. All rights reserved.
+%%
+
+-module(gm_SUITE).
+
+-behaviour(gm).
+
+-include_lib("common_test/include/ct.hrl").
+
+-include("gm_specs.hrl").
+
+-compile(export_all).
+
+-define(RECEIVE_OR_THROW(Body, Bool, Error),
+ receive Body ->
+ true = Bool,
+ passed
+ after 1000 ->
+ throw(Error)
+ end).
+
+all() ->
+ [
+ join_leave,
+ broadcast,
+ confirmed_broadcast,
+ member_death,
+ receive_in_order
+ ].
+
+init_per_suite(Config) ->
+ ok = application:set_env(mnesia, dir, ?config(priv_dir, Config)),
+ ok = application:start(mnesia),
+ {ok, FHC} = file_handle_cache:start_link(),
+ unlink(FHC),
+ {ok, WPS} = worker_pool_sup:start_link(),
+ unlink(WPS),
+ rabbit_ct_helpers:set_config(Config, [
+ {file_handle_cache_pid, FHC},
+ {worker_pool_sup_pid, WPS}
+ ]).
+
+end_per_suite(Config) ->
+ exit(?config(worker_pool_sup_pid, Config), shutdown),
+ exit(?config(file_handle_cache_pid, Config), shutdown),
+ ok = application:stop(mnesia),
+ Config.
+
+%% ---------------------------------------------------------------------------
+%% Functional tests
+%% ---------------------------------------------------------------------------
+
+join_leave(_Config) ->
+ passed = with_two_members(fun (_Pid, _Pid2) -> passed end).
+
+broadcast(_Config) ->
+ passed = do_broadcast(fun gm:broadcast/2).
+
+confirmed_broadcast(_Config) ->
+ passed = do_broadcast(fun gm:confirmed_broadcast/2).
+
+member_death(_Config) ->
+ passed = with_two_members(
+ fun (Pid, Pid2) ->
+ {ok, Pid3} = gm:start_link(
+ ?MODULE, ?MODULE, self(),
+ fun rabbit_misc:execute_mnesia_transaction/1),
+ passed = receive_joined(Pid3, [Pid, Pid2, Pid3],
+ timeout_joining_gm_group_3),
+ passed = receive_birth(Pid, Pid3, timeout_waiting_for_birth_3_1),
+ passed = receive_birth(Pid2, Pid3, timeout_waiting_for_birth_3_2),
+
+ unlink(Pid3),
+ exit(Pid3, kill),
+
+ %% Have to do some broadcasts to ensure that all members
+ %% find out about the death.
+ passed = (broadcast_fun(fun gm:confirmed_broadcast/2))(
+ Pid, Pid2),
+
+ passed = receive_death(Pid, Pid3, timeout_waiting_for_death_3_1),
+ passed = receive_death(Pid2, Pid3, timeout_waiting_for_death_3_2),
+
+ passed
+ end).
+
+receive_in_order(_Config) ->
+ passed = with_two_members(
+ fun (Pid, Pid2) ->
+ Numbers = lists:seq(1,1000),
+ [begin ok = gm:broadcast(Pid, N), ok = gm:broadcast(Pid2, N) end
+ || N <- Numbers],
+ passed = receive_numbers(
+ Pid, Pid, {timeout_for_msgs, Pid, Pid}, Numbers),
+ passed = receive_numbers(
+ Pid, Pid2, {timeout_for_msgs, Pid, Pid2}, Numbers),
+ passed = receive_numbers(
+ Pid2, Pid, {timeout_for_msgs, Pid2, Pid}, Numbers),
+ passed = receive_numbers(
+ Pid2, Pid2, {timeout_for_msgs, Pid2, Pid2}, Numbers),
+ passed
+ end).
+
+do_broadcast(Fun) ->
+ with_two_members(broadcast_fun(Fun)).
+
+broadcast_fun(Fun) ->
+ fun (Pid, Pid2) ->
+ ok = Fun(Pid, magic_message),
+ passed = receive_or_throw({msg, Pid, Pid, magic_message},
+ timeout_waiting_for_msg),
+ passed = receive_or_throw({msg, Pid2, Pid, magic_message},
+ timeout_waiting_for_msg)
+ end.
+
+with_two_members(Fun) ->
+ ok = gm:create_tables(),
+
+ {ok, Pid} = gm:start_link(?MODULE, ?MODULE, self(),
+ fun rabbit_misc:execute_mnesia_transaction/1),
+ passed = receive_joined(Pid, [Pid], timeout_joining_gm_group_1),
+
+ {ok, Pid2} = gm:start_link(?MODULE, ?MODULE, self(),
+ fun rabbit_misc:execute_mnesia_transaction/1),
+ passed = receive_joined(Pid2, [Pid, Pid2], timeout_joining_gm_group_2),
+ passed = receive_birth(Pid, Pid2, timeout_waiting_for_birth_2),
+
+ passed = Fun(Pid, Pid2),
+
+ ok = gm:leave(Pid),
+ passed = receive_death(Pid2, Pid, timeout_waiting_for_death_1),
+ passed =
+ receive_termination(Pid, normal, timeout_waiting_for_termination_1),
+
+ ok = gm:leave(Pid2),
+ passed =
+ receive_termination(Pid2, normal, timeout_waiting_for_termination_2),
+
+ receive X -> throw({unexpected_message, X})
+ after 0 -> passed
+ end.
+
+receive_or_throw(Pattern, Error) ->
+ ?RECEIVE_OR_THROW(Pattern, true, Error).
+
+receive_birth(From, Born, Error) ->
+ ?RECEIVE_OR_THROW({members_changed, From, Birth, Death},
+ ([Born] == Birth) andalso ([] == Death),
+ Error).
+
+receive_death(From, Died, Error) ->
+ ?RECEIVE_OR_THROW({members_changed, From, Birth, Death},
+ ([] == Birth) andalso ([Died] == Death),
+ Error).
+
+receive_joined(From, Members, Error) ->
+ ?RECEIVE_OR_THROW({joined, From, Members1},
+ lists:usort(Members) == lists:usort(Members1),
+ Error).
+
+receive_termination(From, Reason, Error) ->
+ ?RECEIVE_OR_THROW({termination, From, Reason1},
+ Reason == Reason1,
+ Error).
+
+receive_numbers(_Pid, _Sender, _Error, []) ->
+ passed;
+receive_numbers(Pid, Sender, Error, [N | Numbers]) ->
+ ?RECEIVE_OR_THROW({msg, Pid, Sender, M},
+ M == N,
+ Error),
+ receive_numbers(Pid, Sender, Error, Numbers).
+
+%% -------------------------------------------------------------------
+%% gm behavior callbacks.
+%% -------------------------------------------------------------------
+
+joined(Pid, Members) ->
+ Pid ! {joined, self(), Members},
+ ok.
+
+members_changed(Pid, Births, Deaths) ->
+ Pid ! {members_changed, self(), Births, Deaths},
+ ok.
+
+handle_msg(Pid, From, Msg) ->
+ Pid ! {msg, self(), From, Msg},
+ ok.
+
+handle_terminate(Pid, Reason) ->
+ Pid ! {termination, self(), Reason},
+ ok.
diff --git a/test/mirrored_supervisor_SUITE.erl b/test/mirrored_supervisor_SUITE.erl
new file mode 100644
index 0000000000..5ed17c90bb
--- /dev/null
+++ b/test/mirrored_supervisor_SUITE.erl
@@ -0,0 +1,335 @@
+%% 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-2015 Pivotal Software, Inc. All rights reserved.
+%%
+
+-module(mirrored_supervisor_SUITE).
+
+-behaviour(mirrored_supervisor).
+
+-include_lib("common_test/include/ct.hrl").
+
+-compile(export_all).
+
+-define(MS, mirrored_supervisor).
+-define(SERVER, mirrored_supervisor_SUITE_gs).
+
+all() ->
+ [
+ migrate,
+ migrate_twice,
+ already_there,
+ delete_restart,
+ which_children,
+ large_group,
+ childspecs_at_init,
+ anonymous_supervisors,
+ no_migration_on_shutdown,
+ start_idempotence,
+ unsupported,
+ ignore,
+ startup_failure
+ ].
+
+init_per_suite(Config) ->
+ ok = application:set_env(mnesia, dir, ?config(priv_dir, Config)),
+ ok = application:start(mnesia),
+ lists:foreach(
+ fun ({Tab, TabDef}) ->
+ TabDef1 = proplists:delete(match, TabDef),
+ case mnesia:create_table(Tab, TabDef1) of
+ {atomic, ok} ->
+ ok;
+ {aborted, Reason} ->
+ throw({error,
+ {table_creation_failed, Tab, TabDef1, Reason}})
+ end
+ end, mirrored_supervisor:table_definitions()),
+ Config.
+
+end_per_suite(Config) ->
+ ok = application:stop(mnesia),
+ Config.
+
+%% ---------------------------------------------------------------------------
+%% Functional tests
+%% ---------------------------------------------------------------------------
+
+%% Simplest test
+migrate(_Config) ->
+ passed = with_sups(
+ fun([A, _]) ->
+ {ok, _} = ?MS:start_child(a, childspec(worker)),
+ Pid1 = pid_of(worker),
+ kill_registered(A, Pid1),
+ Pid2 = pid_of(worker),
+ false = (Pid1 =:= Pid2)
+ end, [a, b]).
+
+%% Is migration transitive?
+migrate_twice(_Config) ->
+ passed = with_sups(
+ fun([A, B]) ->
+ {ok, _} = ?MS:start_child(a, childspec(worker)),
+ Pid1 = pid_of(worker),
+ kill_registered(A, Pid1),
+ {ok, C} = start_sup(c),
+ Pid2 = pid_of(worker),
+ kill_registered(B, Pid2),
+ Pid3 = pid_of(worker),
+ false = (Pid1 =:= Pid3),
+ kill(C)
+ end, [a, b]).
+
+%% Can't start the same child twice
+already_there(_Config) ->
+ passed = with_sups(
+ fun([_, _]) ->
+ S = childspec(worker),
+ {ok, Pid} = ?MS:start_child(a, S),
+ {error, {already_started, Pid}} = ?MS:start_child(b, S)
+ end, [a, b]).
+
+%% Deleting and restarting should work as per a normal supervisor
+delete_restart(_Config) ->
+ passed = with_sups(
+ fun([_, _]) ->
+ S = childspec(worker),
+ {ok, Pid1} = ?MS:start_child(a, S),
+ {error, running} = ?MS:delete_child(a, worker),
+ ok = ?MS:terminate_child(a, worker),
+ ok = ?MS:delete_child(a, worker),
+ {ok, Pid2} = ?MS:start_child(b, S),
+ false = (Pid1 =:= Pid2),
+ ok = ?MS:terminate_child(b, worker),
+ {ok, Pid3} = ?MS:restart_child(b, worker),
+ Pid3 = pid_of(worker),
+ false = (Pid2 =:= Pid3),
+ %% Not the same supervisor as the worker is on
+ ok = ?MS:terminate_child(a, worker),
+ ok = ?MS:delete_child(a, worker),
+ {ok, Pid4} = ?MS:start_child(a, S),
+ false = (Pid3 =:= Pid4)
+ end, [a, b]).
+
+which_children(_Config) ->
+ passed = with_sups(
+ fun([A, B] = Both) ->
+ ?MS:start_child(A, childspec(worker)),
+ assert_wc(Both, fun ([C]) -> true = is_pid(wc_pid(C)) end),
+ ok = ?MS:terminate_child(a, worker),
+ assert_wc(Both, fun ([C]) -> undefined = wc_pid(C) end),
+ {ok, _} = ?MS:restart_child(a, worker),
+ assert_wc(Both, fun ([C]) -> true = is_pid(wc_pid(C)) end),
+ ?MS:start_child(B, childspec(worker2)),
+ assert_wc(Both, fun (C) -> 2 = length(C) end)
+ end, [a, b]).
+
+assert_wc(Sups, Fun) ->
+ [Fun(?MS:which_children(Sup)) || Sup <- Sups].
+
+wc_pid(Child) ->
+ {worker, Pid, worker, [?MODULE]} = Child,
+ Pid.
+
+%% Not all the members of the group should actually do the failover
+large_group(_Config) ->
+ passed = with_sups(
+ fun([A, _, _, _]) ->
+ {ok, _} = ?MS:start_child(a, childspec(worker)),
+ Pid1 = pid_of(worker),
+ kill_registered(A, Pid1),
+ Pid2 = pid_of(worker),
+ false = (Pid1 =:= Pid2)
+ end, [a, b, c, d]).
+
+%% Do childspecs work when returned from init?
+childspecs_at_init(_Config) ->
+ S = childspec(worker),
+ passed = with_sups(
+ fun([A, _]) ->
+ Pid1 = pid_of(worker),
+ kill_registered(A, Pid1),
+ Pid2 = pid_of(worker),
+ false = (Pid1 =:= Pid2)
+ end, [{a, [S]}, {b, [S]}]).
+
+anonymous_supervisors(_Config) ->
+ passed = with_sups(
+ fun([A, _B]) ->
+ {ok, _} = ?MS:start_child(A, childspec(worker)),
+ Pid1 = pid_of(worker),
+ kill_registered(A, Pid1),
+ Pid2 = pid_of(worker),
+ false = (Pid1 =:= Pid2)
+ end, [anon, anon]).
+
+%% When a mirrored_supervisor terminates, we should not migrate, but
+%% the whole supervisor group should shut down. To test this we set up
+%% a situation where the gen_server will only fail if it's running
+%% under the supervisor called 'evil'. It should not migrate to
+%% 'good' and survive, rather the whole group should go away.
+no_migration_on_shutdown(_Config) ->
+ passed = with_sups(
+ fun([Evil, _]) ->
+ {ok, _} = ?MS:start_child(Evil, childspec(worker)),
+ try
+ call(worker, ping, 1000, 100),
+ exit(worker_should_not_have_migrated)
+ catch exit:{timeout_waiting_for_server, _, _} ->
+ ok
+ end
+ end, [evil, good]).
+
+start_idempotence(_Config) ->
+ passed = with_sups(
+ fun([_]) ->
+ CS = childspec(worker),
+ {ok, Pid} = ?MS:start_child(a, CS),
+ {error, {already_started, Pid}} = ?MS:start_child(a, CS),
+ ?MS:terminate_child(a, worker),
+ {error, already_present} = ?MS:start_child(a, CS)
+ end, [a]).
+
+unsupported(_Config) ->
+ try
+ ?MS:start_link({global, foo}, get_group(group), fun tx_fun/1, ?MODULE,
+ {one_for_one, []}),
+ exit(no_global)
+ catch error:badarg ->
+ ok
+ end,
+ try
+ {ok, _} = ?MS:start_link({local, foo}, get_group(group),
+ fun tx_fun/1, ?MODULE, {simple_one_for_one, []}),
+ exit(no_sofo)
+ catch error:badarg ->
+ ok
+ end.
+
+%% Just test we don't blow up
+ignore(_Config) ->
+ ?MS:start_link({local, foo}, get_group(group), fun tx_fun/1, ?MODULE,
+ {fake_strategy_for_ignore, []}).
+
+startup_failure(_Config) ->
+ [test_startup_failure(F) || F <- [want_error, want_exit]].
+
+test_startup_failure(Fail) ->
+ process_flag(trap_exit, true),
+ ?MS:start_link(get_group(group), fun tx_fun/1, ?MODULE,
+ {one_for_one, [childspec(Fail)]}),
+ receive
+ {'EXIT', _, shutdown} ->
+ ok
+ after 1000 ->
+ exit({did_not_exit, Fail})
+ end,
+ process_flag(trap_exit, false).
+
+%% ---------------------------------------------------------------------------
+
+with_sups(Fun, Sups) ->
+ inc_group(),
+ Pids = [begin {ok, Pid} = start_sup(Sup), Pid end || Sup <- Sups],
+ Fun(Pids),
+ [kill(Pid) || Pid <- Pids, is_process_alive(Pid)],
+ timer:sleep(500),
+ passed.
+
+start_sup(Spec) ->
+ start_sup(Spec, group).
+
+start_sup({Name, ChildSpecs}, Group) ->
+ {ok, Pid} = start_sup0(Name, get_group(Group), ChildSpecs),
+ %% We are not a supervisor, when we kill the supervisor we do not
+ %% want to die!
+ unlink(Pid),
+ {ok, Pid};
+
+start_sup(Name, Group) ->
+ start_sup({Name, []}, Group).
+
+start_sup0(anon, Group, ChildSpecs) ->
+ ?MS:start_link(Group, fun tx_fun/1, ?MODULE,
+ {one_for_one, ChildSpecs});
+
+start_sup0(Name, Group, ChildSpecs) ->
+ ?MS:start_link({local, Name}, Group, fun tx_fun/1, ?MODULE,
+ {one_for_one, ChildSpecs}).
+
+childspec(Id) ->
+ {Id,{?SERVER, start_link, [Id]}, transient, 16#ffffffff, worker, [?MODULE]}.
+
+pid_of(Id) ->
+ {received, Pid, ping} = call(Id, ping),
+ Pid.
+
+tx_fun(Fun) ->
+ case mnesia:sync_transaction(Fun) of
+ {atomic, Result} -> Result;
+ {aborted, Reason} -> throw({error, Reason})
+ end.
+
+inc_group() ->
+ Count = case get(counter) of
+ undefined -> 0;
+ C -> C
+ end + 1,
+ put(counter, Count).
+
+get_group(Group) ->
+ {Group, get(counter)}.
+
+call(Id, Msg) -> call(Id, Msg, 10*1000, 100).
+
+call(Id, Msg, 0, _Decr) ->
+ exit({timeout_waiting_for_server, {Id, Msg}, erlang:get_stacktrace()});
+
+call(Id, Msg, MaxDelay, Decr) ->
+ try
+ gen_server:call(Id, Msg, infinity)
+ catch exit:_ -> timer:sleep(Decr),
+ call(Id, Msg, MaxDelay - Decr, Decr)
+ end.
+
+kill(Pid) -> kill(Pid, []).
+kill(Pid, Wait) when is_pid(Wait) -> kill(Pid, [Wait]);
+kill(Pid, Waits) ->
+ erlang:monitor(process, Pid),
+ [erlang:monitor(process, P) || P <- Waits],
+ exit(Pid, bang),
+ kill_wait(Pid),
+ [kill_wait(P) || P <- Waits].
+
+kill_registered(Pid, Child) ->
+ {registered_name, Name} = erlang:process_info(Child, registered_name),
+ kill(Pid, Child),
+ false = (Child =:= whereis(Name)),
+ ok.
+
+kill_wait(Pid) ->
+ receive
+ {'DOWN', _Ref, process, Pid, _Reason} ->
+ ok
+ end.
+
+%% ---------------------------------------------------------------------------
+
+init({fake_strategy_for_ignore, _ChildSpecs}) ->
+ ignore;
+
+init({Strategy, ChildSpecs}) ->
+ {ok, {{Strategy, 0, 1}, ChildSpecs}}.
+
diff --git a/test/mirrored_supervisor_SUITE_gs.erl b/test/mirrored_supervisor_SUITE_gs.erl
new file mode 100644
index 0000000000..867754b4a2
--- /dev/null
+++ b/test/mirrored_supervisor_SUITE_gs.erl
@@ -0,0 +1,66 @@
+%% 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-2015 Pivotal Software, Inc. All rights reserved.
+%%
+
+-module(mirrored_supervisor_SUITE_gs).
+
+%% Dumb gen_server we can supervise
+
+-export([start_link/1]).
+
+-export([init/1, handle_call/3, handle_info/2, terminate/2, code_change/3,
+ handle_cast/2]).
+
+-behaviour(gen_server).
+
+-define(MS, mirrored_supervisor).
+
+start_link(want_error) ->
+ {error, foo};
+
+start_link(want_exit) ->
+ exit(foo);
+
+start_link(Id) ->
+ gen_server:start_link({local, Id}, ?MODULE, [], []).
+
+%% ---------------------------------------------------------------------------
+
+init([]) ->
+ {ok, state}.
+
+handle_call(Msg, _From, State) ->
+ die_if_my_supervisor_is_evil(),
+ {reply, {received, self(), Msg}, State}.
+
+handle_cast(_Msg, State) ->
+ {noreply, State}.
+
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+die_if_my_supervisor_is_evil() ->
+ try lists:keysearch(self(), 2, ?MS:which_children(evil)) of
+ false -> ok;
+ _ -> exit(doooom)
+ catch
+ exit:{noproc, _} -> ok
+ end.
diff --git a/test/msg_store_SUITE.erl b/test/msg_store_SUITE.erl
new file mode 100644
index 0000000000..f63f6cb745
--- /dev/null
+++ b/test/msg_store_SUITE.erl
@@ -0,0 +1,62 @@
+%% 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-2015 Pivotal Software, Inc. All rights reserved.
+%%
+
+-module(msg_store_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("rabbit_common/include/rabbit.hrl").
+
+-compile(export_all).
+
+-define(T(Fun, Args), (catch apply(rabbit, Fun, Args))).
+
+all() ->
+ [
+ parameter_validation
+ ].
+
+parameter_validation(_Config) ->
+ %% make sure it works with default values
+ ok = ?T(validate_msg_store_io_batch_size_and_credit_disc_bound,
+ [?CREDIT_DISC_BOUND, ?IO_BATCH_SIZE]),
+
+ %% IO_BATCH_SIZE must be greater than CREDIT_DISC_BOUND initial credit
+ ok = ?T(validate_msg_store_io_batch_size_and_credit_disc_bound,
+ [{2000, 500}, 3000]),
+ {error, _} = ?T(validate_msg_store_io_batch_size_and_credit_disc_bound,
+ [{2000, 500}, 1500]),
+
+ %% All values must be integers
+ {error, _} = ?T(validate_msg_store_io_batch_size_and_credit_disc_bound,
+ [{2000, 500}, "1500"]),
+ {error, _} = ?T(validate_msg_store_io_batch_size_and_credit_disc_bound,
+ [{"2000", 500}, abc]),
+ {error, _} = ?T(validate_msg_store_io_batch_size_and_credit_disc_bound,
+ [{2000, "500"}, 2048]),
+
+ %% CREDIT_DISC_BOUND must be a tuple
+ {error, _} = ?T(validate_msg_store_io_batch_size_and_credit_disc_bound,
+ [[2000, 500], 1500]),
+ {error, _} = ?T(validate_msg_store_io_batch_size_and_credit_disc_bound,
+ [2000, 1500]),
+
+ %% config values can't be smaller than default values
+ {error, _} = ?T(validate_msg_store_io_batch_size_and_credit_disc_bound,
+ [{1999, 500}, 2048]),
+ {error, _} = ?T(validate_msg_store_io_batch_size_and_credit_disc_bound,
+ [{2000, 499}, 2048]),
+ {error, _} = ?T(validate_msg_store_io_batch_size_and_credit_disc_bound,
+ [{2000, 500}, 2047]).
diff --git a/test/password_hashing_SUITE.erl b/test/password_hashing_SUITE.erl
new file mode 100644
index 0000000000..50f0f4e6d1
--- /dev/null
+++ b/test/password_hashing_SUITE.erl
@@ -0,0 +1,121 @@
+%% 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-2015 Pivotal Software, Inc. All rights reserved.
+%%
+
+-module(password_hashing_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("rabbit_common/include/rabbit.hrl").
+
+-compile(export_all).
+
+all() ->
+ [
+ password_hashing,
+ change_password
+ ].
+
+%% -------------------------------------------------------------------
+%% Testsuite setup/teardown.
+%% -------------------------------------------------------------------
+
+init_per_suite(Config) ->
+ rabbit_ct_helpers:log_environment(),
+ rabbit_ct_helpers:run_setup_steps(?MODULE, Config).
+
+end_per_suite(Config) ->
+ rabbit_ct_helpers:run_teardown_steps(Config).
+
+%% ---------------------------------------------------------------------------
+%% Test cases
+%% ---------------------------------------------------------------------------
+
+password_hashing(Config) ->
+ passed = rabbit_ct_broker_helpers:run_test_on_broker(
+ ?config(rmq_nodename, Config),
+ ?MODULE, password_hashing1, [Config]).
+
+password_hashing1(_Config) ->
+ rabbit_password_hashing_sha256 = rabbit_password:hashing_mod(),
+ application:set_env(rabbit, password_hashing_module,
+ rabbit_password_hashing_md5),
+ rabbit_password_hashing_md5 = rabbit_password:hashing_mod(),
+ application:set_env(rabbit, password_hashing_module,
+ rabbit_password_hashing_sha256),
+ rabbit_password_hashing_sha256 = rabbit_password:hashing_mod(),
+
+ rabbit_password_hashing_sha256 =
+ rabbit_password:hashing_mod(rabbit_password_hashing_sha256),
+ rabbit_password_hashing_md5 =
+ rabbit_password:hashing_mod(rabbit_password_hashing_md5),
+ rabbit_password_hashing_md5 =
+ rabbit_password:hashing_mod(undefined),
+
+ rabbit_password_hashing_md5 =
+ rabbit_auth_backend_internal:hashing_module_for_user(
+ #internal_user{}),
+ rabbit_password_hashing_md5 =
+ rabbit_auth_backend_internal:hashing_module_for_user(
+ #internal_user{
+ hashing_algorithm = undefined
+ }),
+ rabbit_password_hashing_md5 =
+ rabbit_auth_backend_internal:hashing_module_for_user(
+ #internal_user{
+ hashing_algorithm = rabbit_password_hashing_md5
+ }),
+
+ rabbit_password_hashing_sha256 =
+ rabbit_auth_backend_internal:hashing_module_for_user(
+ #internal_user{
+ hashing_algorithm = rabbit_password_hashing_sha256
+ }),
+
+ passed.
+
+change_password(Config) ->
+ passed = rabbit_ct_broker_helpers:run_test_on_broker(
+ ?config(rmq_nodename, Config),
+ ?MODULE, change_password1, [Config]).
+
+change_password1(_Config) ->
+ UserName = <<"test_user">>,
+ Password = <<"test_password">>,
+ case rabbit_auth_backend_internal:lookup_user(UserName) of
+ {ok, _} -> rabbit_auth_backend_internal:delete_user(UserName);
+ _ -> ok
+ end,
+ ok = application:set_env(rabbit, password_hashing_module,
+ rabbit_password_hashing_md5),
+ ok = rabbit_auth_backend_internal:add_user(UserName, Password),
+ {ok, #auth_user{username = UserName}} =
+ rabbit_auth_backend_internal:user_login_authentication(
+ UserName, [{password, Password}]),
+ ok = application:set_env(rabbit, password_hashing_module,
+ rabbit_password_hashing_sha256),
+ {ok, #auth_user{username = UserName}} =
+ rabbit_auth_backend_internal:user_login_authentication(
+ UserName, [{password, Password}]),
+
+ NewPassword = <<"test_password1">>,
+ ok = rabbit_auth_backend_internal:change_password(UserName, NewPassword),
+ {ok, #auth_user{username = UserName}} =
+ rabbit_auth_backend_internal:user_login_authentication(
+ UserName, [{password, NewPassword}]),
+
+ {refused, _, [UserName]} =
+ rabbit_auth_backend_internal:user_login_authentication(
+ UserName, [{password, Password}]),
+ passed.
diff --git a/test/rabbit_ctl_timeout_SUITE.erl b/test/rabbit_ctl_timeout_SUITE.erl
new file mode 100644
index 0000000000..92b2867a54
--- /dev/null
+++ b/test/rabbit_ctl_timeout_SUITE.erl
@@ -0,0 +1,173 @@
+%% 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-2015 Pivotal Software, Inc. All rights reserved.
+%%
+
+-module(rabbit_ctl_timeout_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("rabbit_common/include/rabbit.hrl").
+
+-compile(export_all).
+
+-define(TIMEOUT_LIST_OPS_PASS, 1000).
+
+all() ->
+ [
+ list_operations_timeout_pass
+ ].
+
+%% -------------------------------------------------------------------
+%% Testsuite setup/teardown.
+%% -------------------------------------------------------------------
+
+init_per_suite(Config) ->
+ rabbit_ct_helpers:log_environment(),
+ rabbit_ct_helpers:run_setup_steps(?MODULE, Config).
+
+end_per_suite(Config) ->
+ rabbit_ct_helpers:run_teardown_steps(Config).
+
+%% -------------------------------------------------------------------
+%% Test cases.
+%% -------------------------------------------------------------------
+
+list_operations_timeout_pass(Config) ->
+ passed = rabbit_ct_broker_helpers:run_test_on_broker(
+ ?config(rmq_nodename, Config),
+ ?MODULE, list_operations_timeout_pass1, [Config]).
+
+list_operations_timeout_pass1(_Config) ->
+ %% create a few things so there is some useful information to list
+ {_Writer1, Limiter1, Ch1} = rabbit_ct_broker_helpers:test_channel(),
+ {_Writer2, Limiter2, Ch2} = rabbit_ct_broker_helpers:test_channel(),
+
+ [Q, Q2] = [Queue || Name <- [<<"foo">>, <<"bar">>],
+ {new, Queue = #amqqueue{}} <-
+ [rabbit_amqqueue:declare(
+ rabbit_misc:r(<<"/">>, queue, Name),
+ false, false, [], none)]],
+
+ ok = rabbit_amqqueue:basic_consume(
+ Q, true, Ch1, Limiter1, false, 0, <<"ctag1">>, true, [],
+ undefined),
+ ok = rabbit_amqqueue:basic_consume(
+ Q2, true, Ch2, Limiter2, false, 0, <<"ctag2">>, true, [],
+ undefined),
+
+ %% list users
+ ok = rabbit_ct_helpers:control_action(add_user, ["foo", "bar"]),
+ {error, {user_already_exists, _}} =
+ rabbit_ct_helpers:control_action(add_user, ["foo", "bar"]),
+ ok = rabbit_ct_helpers:control_action_t(list_users, [],
+ ?TIMEOUT_LIST_OPS_PASS),
+
+ %% list parameters
+ ok = rabbit_runtime_parameters_test:register(),
+ ok = rabbit_ct_helpers:control_action(set_parameter,
+ ["test", "good", "123"]),
+ ok = rabbit_ct_helpers:control_action_t(list_parameters, [],
+ ?TIMEOUT_LIST_OPS_PASS),
+ ok = rabbit_ct_helpers:control_action(clear_parameter,
+ ["test", "good"]),
+ rabbit_runtime_parameters_test:unregister(),
+
+ %% list vhosts
+ ok = rabbit_ct_helpers:control_action(add_vhost, ["/testhost"]),
+ {error, {vhost_already_exists, _}} =
+ rabbit_ct_helpers:control_action(add_vhost, ["/testhost"]),
+ ok = rabbit_ct_helpers:control_action_t(list_vhosts, [],
+ ?TIMEOUT_LIST_OPS_PASS),
+
+ %% list permissions
+ ok = rabbit_ct_helpers:control_action(set_permissions,
+ ["foo", ".*", ".*", ".*"],
+ [{"-p", "/testhost"}]),
+ ok = rabbit_ct_helpers:control_action_t(list_permissions, [],
+ [{"-p", "/testhost"}],
+ ?TIMEOUT_LIST_OPS_PASS),
+
+ %% list user permissions
+ ok = rabbit_ct_helpers:control_action_t(list_user_permissions, ["foo"],
+ ?TIMEOUT_LIST_OPS_PASS),
+
+ %% list policies
+ ok = rabbit_ct_helpers:control_action_opts(["set_policy", "name", ".*",
+ "{\"ha-mode\":\"all\"}"]),
+ ok = rabbit_ct_helpers:control_action_t(list_policies, [],
+ ?TIMEOUT_LIST_OPS_PASS),
+ ok = rabbit_ct_helpers:control_action(clear_policy, ["name"]),
+
+ %% list queues
+ ok = rabbit_ct_helpers:info_action_t(list_queues,
+ rabbit_amqqueue:info_keys(), false,
+ ?TIMEOUT_LIST_OPS_PASS),
+
+ %% list exchanges
+ ok = rabbit_ct_helpers:info_action_t(list_exchanges,
+ rabbit_exchange:info_keys(), true,
+ ?TIMEOUT_LIST_OPS_PASS),
+
+ %% list bindings
+ ok = rabbit_ct_helpers:info_action_t(list_bindings,
+ rabbit_binding:info_keys(), true,
+ ?TIMEOUT_LIST_OPS_PASS),
+
+ %% list connections
+ {H, P} = rabbit_ct_broker_helpers:find_listener(),
+ {ok, C1} = gen_tcp:connect(H, P, [binary, {active, false}]),
+ gen_tcp:send(C1, <<"AMQP", 0, 0, 9, 1>>),
+ {ok, <<1,0,0>>} = gen_tcp:recv(C1, 3, 100),
+
+ {ok, C2} = gen_tcp:connect(H, P, [binary, {active, false}]),
+ gen_tcp:send(C2, <<"AMQP", 0, 0, 9, 1>>),
+ {ok, <<1,0,0>>} = gen_tcp:recv(C2, 3, 100),
+
+ ok = rabbit_ct_helpers:info_action_t(
+ list_connections, rabbit_networking:connection_info_keys(), false,
+ ?TIMEOUT_LIST_OPS_PASS),
+
+ %% list consumers
+ ok = rabbit_ct_helpers:info_action_t(
+ list_consumers, rabbit_amqqueue:consumer_info_keys(), false,
+ ?TIMEOUT_LIST_OPS_PASS),
+
+ %% list channels
+ ok = rabbit_ct_helpers:info_action_t(
+ list_channels, rabbit_channel:info_keys(), false,
+ ?TIMEOUT_LIST_OPS_PASS),
+
+ %% do some cleaning up
+ ok = rabbit_ct_helpers:control_action(delete_user, ["foo"]),
+ {error, {no_such_user, _}} =
+ rabbit_ct_helpers:control_action(delete_user, ["foo"]),
+
+ ok = rabbit_ct_helpers:control_action(delete_vhost, ["/testhost"]),
+ {error, {no_such_vhost, _}} =
+ rabbit_ct_helpers:control_action(delete_vhost, ["/testhost"]),
+
+ %% close_connection
+ Conns = rabbit_networking:connections(),
+ [ok = rabbit_ct_helpers:control_action(
+ close_connection, [rabbit_misc:pid_to_string(ConnPid), "go away"])
+ || ConnPid <- Conns],
+
+ %% cleanup queues
+ [{ok, _} = rabbit_amqqueue:delete(QR, false, false) || QR <- [Q, Q2]],
+
+ [begin
+ unlink(Chan),
+ ok = rabbit_channel:shutdown(Chan)
+ end || Chan <- [Ch1, Ch2]],
+ passed.
diff --git a/test/resource_monitor_SUITE.erl b/test/resource_monitor_SUITE.erl
new file mode 100644
index 0000000000..378b75cc1a
--- /dev/null
+++ b/test/resource_monitor_SUITE.erl
@@ -0,0 +1,64 @@
+%% 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-2015 Pivotal Software, Inc. All rights reserved.
+%%
+
+-module(resource_monitor_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+
+-compile(export_all).
+
+all() ->
+ [
+ parse_information_unit
+ ].
+
+%% ---------------------------------------------------------------------------
+%% Tests
+%% ---------------------------------------------------------------------------
+
+parse_information_unit(_Config) ->
+ lists:foreach(fun ({S, V}) ->
+ V = rabbit_resource_monitor_misc:parse_information_unit(S)
+ end,
+ [
+ {"1000", {ok, 1000}},
+
+ {"10kB", {ok, 10000}},
+ {"10MB", {ok, 10000000}},
+ {"10GB", {ok, 10000000000}},
+
+ {"10kiB", {ok, 10240}},
+ {"10MiB", {ok, 10485760}},
+ {"10GiB", {ok, 10737418240}},
+
+ {"10k", {ok, 10240}},
+ {"10M", {ok, 10485760}},
+ {"10G", {ok, 10737418240}},
+
+ {"10KB", {ok, 10000}},
+ {"10K", {ok, 10240}},
+ {"10m", {ok, 10485760}},
+ {"10Mb", {ok, 10000000}},
+
+ {"0MB", {ok, 0}},
+
+ {"10 k", {error, parse_error}},
+ {"MB", {error, parse_error}},
+ {"", {error, parse_error}},
+ {"0.5GB", {error, parse_error}},
+ {"10TB", {error, parse_error}}
+ ]),
+ passed.
diff --git a/test/supervisor2_SUITE.erl b/test/supervisor2_SUITE.erl
new file mode 100644
index 0000000000..e2b95146c0
--- /dev/null
+++ b/test/supervisor2_SUITE.erl
@@ -0,0 +1,90 @@
+%% 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-2015 Pivotal Software, Inc. All rights reserved.
+%%
+
+-module(supervisor2_SUITE).
+
+-behaviour(supervisor2).
+
+-include_lib("common_test/include/ct.hrl").
+
+-compile(export_all).
+
+all() ->
+ [
+ check_shutdown_stop,
+ check_shutdown_ignored
+ ].
+
+check_shutdown_stop(_Config) ->
+ ok = check_shutdown(stop, 200, 200, 2000).
+
+check_shutdown_ignored(_Config) ->
+ ok = check_shutdown(ignored, 1, 2, 2000).
+
+check_shutdown(SigStop, Iterations, ChildCount, SupTimeout) ->
+ {ok, Sup} = supervisor2:start_link(?MODULE, [SupTimeout]),
+ Res = lists:foldl(
+ fun (I, ok) ->
+ TestSupPid = erlang:whereis(?MODULE),
+ ChildPids =
+ [begin
+ {ok, ChildPid} =
+ supervisor2:start_child(TestSupPid, []),
+ ChildPid
+ end || _ <- lists:seq(1, ChildCount)],
+ MRef = erlang:monitor(process, TestSupPid),
+ [P ! SigStop || P <- ChildPids],
+ ok = supervisor2:terminate_child(Sup, test_sup),
+ {ok, _} = supervisor2:restart_child(Sup, test_sup),
+ receive
+ {'DOWN', MRef, process, TestSupPid, shutdown} ->
+ ok;
+ {'DOWN', MRef, process, TestSupPid, Reason} ->
+ {error, {I, Reason}}
+ end;
+ (_, R) ->
+ R
+ end, ok, lists:seq(1, Iterations)),
+ unlink(Sup),
+ MSupRef = erlang:monitor(process, Sup),
+ exit(Sup, shutdown),
+ receive
+ {'DOWN', MSupRef, process, Sup, _Reason} ->
+ ok
+ end,
+ Res.
+
+%% -------------------------------------------------------------------
+%% supervisor2 behavior callbacks.
+%% -------------------------------------------------------------------
+
+start_link() ->
+ Pid = spawn_link(fun () ->
+ process_flag(trap_exit, true),
+ receive stop -> ok end
+ end),
+ {ok, Pid}.
+
+init([Timeout]) ->
+ {ok, {{one_for_one, 0, 1},
+ [{test_sup, {supervisor2, start_link,
+ [{local, ?MODULE}, ?MODULE, []]},
+ transient, Timeout, supervisor, [?MODULE]}]}};
+init([]) ->
+ {ok, {{simple_one_for_one, 0, 1},
+ [{test_worker, {?MODULE, start_link, []},
+ temporary, 1000, worker, [?MODULE]}]}}.
+
diff --git a/test/truncate_SUITE.erl b/test/truncate_SUITE.erl
new file mode 100644
index 0000000000..6c78be726d
--- /dev/null
+++ b/test/truncate_SUITE.erl
@@ -0,0 +1,99 @@
+%% 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(truncate_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+
+-compile(export_all).
+
+all() ->
+ [
+ {group, all_tests}
+ ].
+
+groups() ->
+ [
+ {all_tests, [parallel], [
+ short_examples_exactly,
+ term_limit,
+ large_examples_for_size
+ ]}
+ ].
+
+init_per_group(_, Config) -> Config.
+end_per_group(_, Config) -> Config.
+
+short_examples_exactly(_Config) ->
+ F = fun (Term, Exp) ->
+ Exp = truncate:term(Term, {1, {10, 10, 5, 5}}),
+ Term = truncate:term(Term, {100000, {10, 10, 5, 5}})
+ end,
+ FSmall = fun (Term, Exp) ->
+ Exp = truncate:term(Term, {1, {2, 2, 2, 2}}),
+ Term = truncate:term(Term, {100000, {2, 2, 2, 2}})
+ end,
+ F([], []),
+ F("h", "h"),
+ F("hello world", "hello w..."),
+ F([[h,e,l,l,o,' ',w,o,r,l,d]], [[h,e,l,l,o,'...']]),
+ F([a|b], [a|b]),
+ F(<<"hello">>, <<"hello">>),
+ F([<<"hello world">>], [<<"he...">>]),
+ F(<<1:1>>, <<1:1>>),
+ F(<<1:81>>, <<0:56, "...">>),
+ F({{{{a}}},{b},c,d,e,f,g,h,i,j,k}, {{{'...'}},{b},c,d,e,f,g,h,i,j,'...'}),
+ FSmall({a,30,40,40,40,40}, {a,30,'...'}),
+ FSmall([a,30,40,40,40,40], [a,30,'...']),
+ P = spawn(fun() -> receive die -> ok end end),
+ F([0, 0.0, <<1:1>>, F, P], [0, 0.0, <<1:1>>, F, P]),
+ P ! die,
+ R = make_ref(),
+ F([R], [R]),
+ ok.
+
+term_limit(_Config) ->
+ W = erlang:system_info(wordsize),
+ S = <<"abc">>,
+ 1 = truncate:term_size(S, 4, W),
+ limit_exceeded = truncate:term_size(S, 3, W),
+ case 100 - truncate:term_size([S, S], 100, W) of
+ 22 -> ok; %% 32 bit
+ 38 -> ok %% 64 bit
+ end,
+ case 100 - truncate:term_size([S, [S]], 100, W) of
+ 30 -> ok; %% ditto
+ 54 -> ok
+ end,
+ limit_exceeded = truncate:term_size([S, S], 6, W),
+ ok.
+
+large_examples_for_size(_Config) ->
+ %% Real world values
+ Shrink = fun(Term) -> truncate:term(Term, {1, {1000, 100, 50, 5}}) end,
+ TestSize = fun(Term) ->
+ true = 5000000 < size(term_to_binary(Term)),
+ true = 500000 > size(term_to_binary(Shrink(Term)))
+ end,
+ TestSize(lists:seq(1, 5000000)),
+ TestSize(recursive_list(1000, 10)),
+ TestSize(recursive_list(5000, 20)),
+ TestSize(gb_sets:from_list([I || I <- lists:seq(1, 1000000)])),
+ TestSize(gb_trees:from_orddict([{I, I} || I <- lists:seq(1, 1000000)])),
+ ok.
+
+recursive_list(S, 0) -> lists:seq(1, S);
+recursive_list(S, N) -> [recursive_list(S div N, N-1) || _ <- lists:seq(1, S)].
diff --git a/test/vm_memory_monitor_SUITE.erl b/test/vm_memory_monitor_SUITE.erl
new file mode 100644
index 0000000000..195fff7567
--- /dev/null
+++ b/test/vm_memory_monitor_SUITE.erl
@@ -0,0 +1,42 @@
+%% 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-2015 Pivotal Software, Inc. All rights reserved.
+%%
+
+-module(vm_memory_monitor_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+
+-compile(export_all).
+
+all() ->
+ [
+ parse_line_linux
+ ].
+
+%% ---------------------------------------------------------------------------
+%% Test cases
+%% ---------------------------------------------------------------------------
+
+parse_line_linux(_Config) ->
+ lists:foreach(fun ({S, {K, V}}) ->
+ {K, V} = vm_memory_monitor:parse_line_linux(S)
+ end,
+ [{"MemTotal: 0 kB", {'MemTotal', 0}},
+ {"MemTotal: 502968 kB ", {'MemTotal', 515039232}},
+ {"MemFree: 178232 kB", {'MemFree', 182509568}},
+ {"MemTotal: 50296888", {'MemTotal', 50296888}},
+ {"MemTotal 502968 kB", {'MemTotal', 515039232}},
+ {"MemTotal 50296866 ", {'MemTotal', 50296866}}]),
+ ok.