aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/test/z_SUITE.erl
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/test/z_SUITE.erl')
-rw-r--r--erts/emulator/test/z_SUITE.erl312
1 files changed, 312 insertions, 0 deletions
diff --git a/erts/emulator/test/z_SUITE.erl b/erts/emulator/test/z_SUITE.erl
new file mode 100644
index 0000000000..67d2b288a2
--- /dev/null
+++ b/erts/emulator/test/z_SUITE.erl
@@ -0,0 +1,312 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% 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.
+%%
+%% %CopyrightEnd%
+%%
+
+%%%-------------------------------------------------------------------
+%%% File : z_SUITE.erl
+%%% Author : Rickard Green <[email protected]>
+%%% Description : Misc tests that should be run last
+%%%
+%%% Created : 15 Jul 2005 by Rickard Green <[email protected]>
+%%%-------------------------------------------------------------------
+-module(z_SUITE).
+-author('[email protected]').
+
+%-define(line_trace, 1).
+
+-include("test_server.hrl").
+
+%-compile(export_all).
+-export([all/1, init_per_testcase/2, fin_per_testcase/2]).
+
+-export([schedulers_alive/1, node_container_refc_check/1,
+ long_timers/1, pollset_size/1,
+ check_io_debug/1]).
+
+-define(DEFAULT_TIMEOUT, ?t:minutes(5)).
+
+all(doc) -> [];
+all(suite) ->
+ [schedulers_alive,
+ node_container_refc_check,
+ long_timers,
+ pollset_size,
+ check_io_debug].
+
+init_per_testcase(_Case, Config) when is_list(Config) ->
+ Dog = ?t:timetrap(?DEFAULT_TIMEOUT),
+ [{watchdog, Dog}|Config].
+
+fin_per_testcase(_Case, Config) when is_list(Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+%%%
+%%% The test cases -------------------------------------------------------------
+%%%
+
+schedulers_alive(doc) -> ["Tests that all schedulers are actually used"];
+schedulers_alive(suite) -> [];
+schedulers_alive(Config) when is_list(Config) ->
+ ?line Master = self(),
+ ?line NoSchedulersOnline = erlang:system_flag(
+ schedulers_online,
+ erlang:system_info(schedulers)),
+ ?line NoSchedulers = erlang:system_info(schedulers),
+ UsedScheds =
+ try
+ ?line ?t:format("Number of schedulers configured: ~p~n", [NoSchedulers]),
+ ?line case erlang:system_info(multi_scheduling) of
+ blocked ->
+ ?line ?t:fail(multi_scheduling_blocked);
+ disabled ->
+ ?line ok;
+ enabled ->
+ ?t:format("Testing blocking process exit~n"),
+ BF = fun () ->
+ blocked = erlang:system_flag(multi_scheduling,
+ block),
+ Master ! {self(), blocking},
+ receive after infinity -> ok end
+ end,
+ ?line Blocker = spawn_link(BF),
+ ?line Mon = erlang:monitor(process, Blocker),
+ ?line receive {Blocker, blocking} -> ok end,
+ ?line [Blocker]
+ = erlang:system_info(multi_scheduling_blockers),
+ ?line unlink(Blocker),
+ ?line exit(Blocker, kill),
+ ?line receive {'DOWN', Mon, _, _, _} -> ok end,
+ ?line enabled = erlang:system_info(multi_scheduling),
+ ?line [] = erlang:system_info(multi_scheduling_blockers),
+ ?line ok
+ end,
+ ?t:format("Testing blocked~n"),
+ ?line erlang:system_flag(multi_scheduling, block),
+ ?line case erlang:system_info(multi_scheduling) of
+ enabled ->
+ ?line ?t:fail(multi_scheduling_enabled);
+ blocked ->
+ ?line [Master] = erlang:system_info(multi_scheduling_blockers);
+ disabled -> ?line ok
+ end,
+ ?line Ps = lists:map(
+ fun (_) ->
+ spawn_link(fun () ->
+ run_on_schedulers(none,
+ [],
+ Master)
+ end)
+ end,
+ lists:seq(1,NoSchedulers)),
+ ?line receive after 1000 -> ok end,
+ ?line {_, 1} = verify_all_schedulers_used({[],0}, 1),
+ ?line lists:foreach(fun (P) ->
+ unlink(P),
+ exit(P, bang)
+ end,
+ Ps),
+ ?line case erlang:system_flag(multi_scheduling, unblock) of
+ blocked -> ?line ?t:fail(multi_scheduling_blocked);
+ disabled -> ?line ok;
+ enabled -> ?line ok
+ end,
+ erts_debug:set_internal_state(available_internal_state, true),
+ %% node_and_dist_references will use emulator interal thread blocking...
+ erts_debug:get_internal_state(node_and_dist_references),
+ erts_debug:set_internal_state(available_internal_state, false),
+ ?t:format("Testing not blocked~n"),
+ ?line Ps2 = lists:map(
+ fun (_) ->
+ spawn_link(fun () ->
+ run_on_schedulers(none,
+ [],
+ Master)
+ end)
+ end,
+ lists:seq(1,NoSchedulers)),
+ ?line receive after 1000 -> ok end,
+ ?line {_, NoSIDs} = verify_all_schedulers_used({[],0},NoSchedulers),
+ ?line lists:foreach(fun (P) ->
+ unlink(P),
+ exit(P, bang)
+ end,
+ Ps2),
+ NoSIDs
+ after
+ NoSchedulers = erlang:system_flag(schedulers_online,
+ NoSchedulersOnline),
+ NoSchedulersOnline = erlang:system_info(schedulers_online)
+ end,
+ ?line {comment, "Number of schedulers " ++ integer_to_list(UsedScheds)}.
+
+
+run_on_schedulers(LastSID, SIDs, ReportTo) ->
+ case erlang:system_info(scheduler_id) of
+ LastSID ->
+ erlang:yield(),
+ run_on_schedulers(LastSID, SIDs, ReportTo);
+ SID ->
+ NewSIDs = case lists:member(SID, SIDs) of
+ true ->
+ SIDs;
+ false ->
+ ReportTo ! {scheduler_used, SID},
+ [SID | SIDs]
+ end,
+ erlang:yield(),
+ run_on_schedulers(SID, NewSIDs, ReportTo)
+ end.
+
+wait_on_used_scheduler({SIDs, SIDsLen} = State) ->
+ receive
+ {scheduler_used, SID} ->
+ case lists:member(SID, SIDs) of
+ true ->
+ wait_on_used_scheduler(State);
+ false ->
+ ?t:format("Scheduler ~p used~n", [SID]),
+ {[SID|SIDs], SIDsLen+1}
+ end
+ end.
+
+verify_all_schedulers_used({UsedSIDs, UsedSIDsLen} = State, NoSchedulers) ->
+ ?line case NoSchedulers of
+ UsedSIDsLen ->
+ ?line State;
+ NoSchdlrs when NoSchdlrs < UsedSIDsLen ->
+ ?line ?t:fail({more_schedulers_used_than_exist,
+ {existing_schedulers, NoSchdlrs},
+ {used_schedulers, UsedSIDsLen},
+ {used_scheduler_ids, UsedSIDs}});
+ _ ->
+ ?line NewState = wait_on_used_scheduler(State),
+ ?line verify_all_schedulers_used(NewState, NoSchedulers)
+ end.
+
+node_container_refc_check(doc) -> [];
+node_container_refc_check(suite) -> [];
+node_container_refc_check(Config) when is_list(Config) ->
+ ?line node_container_SUITE:node_container_refc_check(node()),
+ ?line ok.
+
+long_timers(doc) ->
+ [];
+long_timers(suite) ->
+ [];
+long_timers(Config) when is_list(Config) ->
+ ?line ok = long_timers_test:check_result().
+
+pollset_size(doc) ->
+ [];
+pollset_size(suite) ->
+ [];
+pollset_size(Config) when is_list(Config) ->
+ ?line Name = pollset_size_testcase_initial_state_holder,
+ ?line Mon = erlang:monitor(process, Name),
+ ?line (catch Name ! {get_initial_check_io_result, self()}),
+ ?line InitChkIo = receive
+ {initial_check_io_result, ICIO} ->
+ ?line erlang:demonitor(Mon, [flush]),
+ ?line ICIO;
+ {'DOWN', Mon, _, _, Reason} ->
+ ?line ?t:fail({non_existing, Name, Reason})
+ end,
+ ?line FinChkIo = get_check_io_info(),
+ ?line io:format("Initial: ~p~nFinal: ~p~n", [InitChkIo, FinChkIo]),
+ ?line InitPollsetSize = lists:keysearch(total_poll_set_size, 1, InitChkIo),
+ ?line FinPollsetSize = lists:keysearch(total_poll_set_size, 1, FinChkIo),
+ ?line case InitPollsetSize =:= FinPollsetSize of
+ true ->
+ case InitPollsetSize of
+ {value, {total_poll_set_size, Size}} ->
+ ?line {comment,
+ "Pollset size: " ++ integer_to_list(Size)};
+ _ ->
+ ?line {skipped,
+ "Pollset size information not available"}
+ end;
+ false ->
+ %% Somtimes we have fewer descriptors in the
+ %% pollset at the end than when we started, but
+ %% that is ok as long as there are at least 2
+ %% descriptors (dist listen socket and
+ %% epmd socket) in the pollset.
+ ?line {value, {total_poll_set_size, InitSize}}
+ = InitPollsetSize,
+ ?line {value, {total_poll_set_size, FinSize}}
+ = FinPollsetSize,
+ ?line true = FinSize < InitSize,
+ ?line true = 2 =< FinSize,
+ ?line {comment,
+ "Start pollset size: "
+ ++ integer_to_list(InitSize)
+ ++ " End pollset size: "
+ ++ integer_to_list(FinSize)}
+ end.
+
+check_io_debug(doc) ->
+ [];
+check_io_debug(suite) ->
+ [];
+check_io_debug(Config) when is_list(Config) ->
+ ?line case lists:keysearch(name, 1, erlang:system_info(check_io)) of
+ {value, {name, erts_poll}} -> ?line check_io_debug_test();
+ _ -> ?line {skipped, "Not implemented in this emulator"}
+ end.
+
+check_io_debug_test() ->
+ ?line erts_debug:set_internal_state(available_internal_state, true),
+ ?line erlang:display(erlang:system_info(check_io)),
+ ?line NoOfErrorFds = erts_debug:get_internal_state(check_io_debug),
+ ?line erts_debug:set_internal_state(available_internal_state, false),
+ ?line 0 = NoOfErrorFds,
+ ?line ok.
+
+
+
+%%
+%% Internal functions...
+%%
+
+display_check_io(ChkIo) ->
+ catch erlang:display('--- CHECK IO INFO ---'),
+ catch erlang:display(ChkIo),
+ catch erts_debug:set_internal_state(available_internal_state, true),
+ NoOfErrorFds = (catch erts_debug:get_internal_state(check_io_debug)),
+ catch erlang:display({'NoOfErrorFds', NoOfErrorFds}),
+ catch erts_debug:set_internal_state(available_internal_state, false),
+ catch erlang:display('--- CHECK IO INFO ---'),
+ ok.
+
+get_check_io_info() ->
+ ChkIo = erlang:system_info(check_io),
+ case lists:keysearch(pending_updates, 1, ChkIo) of
+ {value, {pending_updates, 0}} ->
+ display_check_io(ChkIo),
+ ChkIo;
+ false ->
+ ChkIo;
+ _ ->
+ receive after 10 -> ok end,
+ get_check_io_info()
+ end.
+
+
+