diff options
Diffstat (limited to 'erts/emulator/test')
-rw-r--r-- | erts/emulator/test/Makefile | 5 | ||||
-rw-r--r-- | erts/emulator/test/distribution_SUITE.erl | 19 | ||||
-rw-r--r-- | erts/emulator/test/emulator_node_container_SUITE.spec | 2 | ||||
-rw-r--r-- | erts/emulator/test/erts_debug_SUITE.erl | 14 | ||||
-rw-r--r-- | erts/emulator/test/fun_r13_SUITE.erl | 74 | ||||
-rw-r--r-- | erts/emulator/test/list_bif_SUITE.erl | 25 | ||||
-rw-r--r-- | erts/emulator/test/nif_SUITE.erl | 159 | ||||
-rw-r--r-- | erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 26 | ||||
-rw-r--r-- | erts/emulator/test/node_container_SUITE.erl | 32 | ||||
-rw-r--r-- | erts/emulator/test/old_mod.erl | 48 | ||||
-rw-r--r-- | erts/emulator/test/scheduler_SUITE.erl | 94 | ||||
-rw-r--r-- | erts/emulator/test/smoke_test_SUITE.erl | 7 | ||||
-rw-r--r-- | erts/emulator/test/statistics_SUITE.erl | 4 |
13 files changed, 298 insertions, 211 deletions
diff --git a/erts/emulator/test/Makefile b/erts/emulator/test/Makefile index 5478932b13..ca81c9915e 100644 --- a/erts/emulator/test/Makefile +++ b/erts/emulator/test/Makefile @@ -66,7 +66,6 @@ MODULES= \ exception_SUITE \ float_SUITE \ fun_SUITE \ - fun_r13_SUITE \ gc_SUITE \ guard_SUITE \ hash_SUITE \ @@ -122,7 +121,6 @@ MODULES= \ port_trace_SUITE \ unique_SUITE \ z_SUITE \ - old_mod \ long_timers_test \ ignore_cores \ dgawd_handler \ @@ -157,7 +155,8 @@ EMAKEFILE=Emakefile TEST_SPEC_FILES= emulator.spec \ emulator.spec.win \ emulator_bench.spec \ - emulator_smoke.spec + emulator_smoke.spec \ + emulator_node_container_SUITE.spec # ---------------------------------------------------- # Release directory specification diff --git a/erts/emulator/test/distribution_SUITE.erl b/erts/emulator/test/distribution_SUITE.erl index 6994bfef83..4f98cd6cee 100644 --- a/erts/emulator/test/distribution_SUITE.erl +++ b/erts/emulator/test/distribution_SUITE.erl @@ -19,7 +19,7 @@ %% -module(distribution_SUITE). --compile(r15). +-compile(r16). -define(VERSION_MAGIC, 131). @@ -48,7 +48,7 @@ dist_parallel_send/1, atom_roundtrip/1, unicode_atom_roundtrip/1, - atom_roundtrip_r15b/1, + atom_roundtrip_r16b/1, contended_atom_cache_entry/1, contended_unicode_atom_cache_entry/1, bad_dist_structure/1, @@ -78,7 +78,8 @@ all() -> link_to_dead_new_node, applied_monitor_node, ref_port_roundtrip, nil_roundtrip, stop_dist, {group, trap_bif}, {group, dist_auto_connect}, - dist_parallel_send, atom_roundtrip, unicode_atom_roundtrip, atom_roundtrip_r15b, + dist_parallel_send, atom_roundtrip, unicode_atom_roundtrip, + atom_roundtrip_r16b, contended_atom_cache_entry, contended_unicode_atom_cache_entry, bad_dist_structure, {group, bad_dist_ext}, start_epmd_false, epmd_module]. @@ -1032,21 +1033,21 @@ atom_roundtrip(Config) when is_list(Config) -> stop_node(Node), ok. -atom_roundtrip_r15b(Config) when is_list(Config) -> - case test_server:is_release_available("r15b") of +atom_roundtrip_r16b(Config) when is_list(Config) -> + case test_server:is_release_available("r16b") of true -> ct:timetrap({minutes, 6}), - AtomData = atom_data(), + AtomData = unicode_atom_data(), verify_atom_data(AtomData), - case start_node(Config, [], "r15b") of + case start_node(Config, [], "r16b") of {ok, Node} -> do_atom_roundtrip(Node, AtomData), stop_node(Node); {error, timeout} -> - {skip,"Unable to start OTP R15B release"} + {skip,"Unable to start OTP R16B release"} end; false -> - {skip,"No OTP R15B available"} + {skip,"No OTP R16B available"} end. unicode_atom_roundtrip(Config) when is_list(Config) -> diff --git a/erts/emulator/test/emulator_node_container_SUITE.spec b/erts/emulator/test/emulator_node_container_SUITE.spec new file mode 100644 index 0000000000..77c28ba7ae --- /dev/null +++ b/erts/emulator/test/emulator_node_container_SUITE.spec @@ -0,0 +1,2 @@ +{enable_builtin_hooks, false}. +{suites,"../emulator_test",node_container_SUITE}. diff --git a/erts/emulator/test/erts_debug_SUITE.erl b/erts/emulator/test/erts_debug_SUITE.erl index 23871585f7..c9c664de38 100644 --- a/erts/emulator/test/erts_debug_SUITE.erl +++ b/erts/emulator/test/erts_debug_SUITE.erl @@ -23,14 +23,15 @@ -export([all/0, suite/0, test_size/1,flat_size_big/1,df/1,term_type/1, - instructions/1]). + instructions/1, stack_check/1]). suite() -> [{ct_hooks,[ts_install_cth]}, {timetrap, {minutes, 2}}]. all() -> - [test_size, flat_size_big, df, instructions, term_type]. + [test_size, flat_size_big, df, instructions, term_type, + stack_check]. test_size(Config) when is_list(Config) -> ConsCell1 = id([a|b]), @@ -181,6 +182,15 @@ df(Config) when is_list(Config) -> true = (P0 == pps()), ok. +stack_check(Config) when is_list(Config) -> + erts_debug:set_internal_state(available_internal_state,true), + %% Recurses on the C stack until stacklimit is reached. That + %% is, tests that the stack limit functionality works (used + %% by PCRE). VM will crash if it doesn't work... + Size = erts_debug:get_internal_state(stack_check), + erts_debug:set_internal_state(available_internal_state,false), + {comment, "Stack size: "++integer_to_list(Size)++" bytes"}. + df_smoke([M|Ms]) -> io:format("~p", [M]), erts_debug:df(M), diff --git a/erts/emulator/test/fun_r13_SUITE.erl b/erts/emulator/test/fun_r13_SUITE.erl deleted file mode 100644 index a45ed08b9d..0000000000 --- a/erts/emulator/test/fun_r13_SUITE.erl +++ /dev/null @@ -1,74 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2007-2016. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - --module(fun_r13_SUITE). --compile(r13). - --export([all/0, suite/0, - dist_old_release/1]). - --include_lib("common_test/include/ct.hrl"). - -suite() -> - [{ct_hooks,[ts_install_cth]}, - {timetrap, {minutes, 1}}]. - -all() -> - [dist_old_release]. - -dist_old_release(Config) when is_list(Config) -> - case test_server:is_release_available("r12b") of - true -> do_dist_old(Config); - false -> {skip,"No R12B found"} - end. - -do_dist_old(Config) when is_list(Config) -> - Pa = filename:dirname(code:which(?MODULE)), - Name = fun_dist_r12, - {ok,Node} = test_server:start_node(Name, peer, - [{args,"-pa "++Pa}, - {erl,[{release,"r12b"}]}]), - - Pid = spawn_link(Node, - fun() -> - receive - Fun when is_function(Fun) -> - R12BFun = fun(H) -> cons(H, [b,c]) end, - Fun(Fun, R12BFun) - end - end), - Self = self(), - Fun = fun(F, R12BFun) -> - {pid,Self} = erlang:fun_info(F, pid), - {module,?MODULE} = erlang:fun_info(F, module), - Self ! {ok,F,R12BFun} - end, - Pid ! Fun, - receive - {ok,Fun,R12BFun} -> - [a,b,c] = R12BFun(a); - Other -> - ct:fail({bad_message,Other}) - end, - true = test_server:stop_node(Node), - ok. - -cons(H, T) -> - [H|T]. diff --git a/erts/emulator/test/list_bif_SUITE.erl b/erts/emulator/test/list_bif_SUITE.erl index 514dd2f412..08574bff71 100644 --- a/erts/emulator/test/list_bif_SUITE.erl +++ b/erts/emulator/test/list_bif_SUITE.erl @@ -23,7 +23,7 @@ -export([all/0, suite/0]). -export([hd_test/1,tl_test/1,t_length/1,t_list_to_pid/1, - t_list_to_float/1,t_list_to_integer/1]). + t_list_to_port/1,t_list_to_float/1,t_list_to_integer/1]). suite() -> @@ -32,7 +32,7 @@ suite() -> all() -> - [hd_test, tl_test, t_length, t_list_to_pid, + [hd_test, tl_test, t_length, t_list_to_pid, t_list_to_port, t_list_to_float, t_list_to_integer]. %% Tests list_to_integer and string:to_integer @@ -47,9 +47,9 @@ t_list_to_integer(Config) when is_list(Config) -> {12373281903728109372810937209817320981321,"ABC"} = string:to_integer("12373281903728109372810937209817320981321ABC"), {-12373281903728109372810937209817320981321,"ABC"} = string:to_integer("-12373281903728109372810937209817320981321ABC"), {12,[345]} = string:to_integer([$1,$2,345]), - {12,[a]} = string:to_integer([$1,$2,a]), + {error, badarg} = string:to_integer([$1,$2,a]), {error,no_integer} = string:to_integer([$A]), - {error,not_a_list} = string:to_integer($A), + {error,badarg} = string:to_integer($A), ok. %% Test hd/1 with correct and incorrect arguments. @@ -106,10 +106,25 @@ t_list_to_pid(Config) when is_list(Config) -> {'EXIT', {badarg, _}} -> ok; Res -> - ct:fail("list_to_pid/1 with incorrect arg succeeded.~nResult: ~p", [Res]) + ct:fail("list_to_pid/1 with incorrect arg succeeded.~n" + "Result: ~p", [Res]) end, ok. +%% Test list_to_port/1 with correct and incorrect arguments. + +t_list_to_port(Config) when is_list(Config) -> + Me = hd(erlang:ports()), + MyListedPid = port_to_list(Me), + Me = list_to_port(MyListedPid), + case catch list_to_port(id("Incorrect list")) of + {'EXIT', {badarg, _}} -> + ok; + Res -> + ct:fail("list_to_port/1 with incorrect arg succeeded.~n" + "Result: ~p", [Res]) + end, + ok. %% Test list_to_float/1 with correct and incorrect arguments. diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 693db42e58..8ad11d3bf3 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -56,7 +56,10 @@ nif_is_process_alive/1, nif_is_port_alive/1, nif_term_to_binary/1, nif_binary_to_term/1, nif_port_command/1, - nif_snprintf/1 + nif_snprintf/1, + nif_internal_hash/1, + nif_internal_hash_salted/1, + nif_phash2/1 ]). -export([many_args_100/100]). @@ -90,7 +93,10 @@ all() -> nif_is_process_alive, nif_is_port_alive, nif_term_to_binary, nif_binary_to_term, nif_port_command, - nif_snprintf]. + nif_snprintf, + nif_internal_hash, + nif_internal_hash_salted, + nif_phash2]. groups() -> [{G, [], api_repeaters()} || G <- api_groups()] @@ -2610,6 +2616,154 @@ nif_snprintf(Config) -> <<"{{hello,world,-33},",0>> = format_term_nif(20,{{hello,world, -33}, 3.14, self()}), ok. +nif_internal_hash(Config) -> + ensure_lib_loaded(Config), + HashValueBitSize = nif_hash_result_bitsize(internal), + Terms = unique([random_term() || _ <- lists:seq(1, 5000)]), + HashValues = [hash_nif(internal, Term, 0) || Term <- Terms], + test_bit_distribution_fitness(HashValues, HashValueBitSize, 0.05). + +nif_internal_hash_salted(Config) -> + ensure_lib_loaded(Config), + test_salted_nif_hash(internal). + +nif_phash2(Config) -> + ensure_lib_loaded(Config), + HashValueBitSize = nif_hash_result_bitsize(phash2), + Terms = unique([random_term() || _ <- lists:seq(1, 5000)]), + HashValues = + lists:map( + fun (Term) -> + HashValue = erlang:phash2(Term), + Salt = random_uint32(), % phash2 should ignore salt + NifHashValue = hash_nif(phash2, Term, Salt), + (HashValue =:= NifHashValue + orelse ct:fail("Expected: ~p\nActual: ~p", + [HashValue, NifHashValue])), + HashValue + end, + Terms), + test_bit_distribution_fitness(HashValues, HashValueBitSize, 0.05). + +test_salted_nif_hash(HashType) -> + HashValueBitSize = nif_hash_result_bitsize(HashType), + Terms = unique([random_term() || _ <- lists:seq(1, 5000)]), + Salts = unique([random_uint32() || _ <- lists:seq(1, 100)]), + {HashValuesPerSalt, HashValuesPerTerm} = + lists:mapfoldl( + fun (Salt, Acc) -> + {HashValues, NewAcc} = + lists:mapfoldl( + fun (Term, AccB) -> + HashValue = hash_nif(HashType, Term, Salt), + NewAccB = dict:append(Term, HashValue, AccB), + {HashValue, NewAccB} + end, + Acc, + Terms), + {{Salt, HashValues}, NewAcc} + end, + dict:new(), + Salts), + + % Test per-salt hash distribution of different terms + lists:foreach( + fun ({_Salt, HashValues}) -> + test_bit_distribution_fitness(HashValues, HashValueBitSize, 0.05) + end, + HashValuesPerSalt), + + % Test per-term hash distribution of different salts + dict:fold( + fun (_Term, HashValues, Acc) -> + % Be more tolerant of relative deviation, + % as there's fewer hash values here. + test_bit_distribution_fitness(HashValues, HashValueBitSize, 0.30), + Acc + end, + ok, + HashValuesPerTerm). + +test_bit_distribution_fitness(Integers, BitSize, MaxRelativeDeviation) -> + MaxInteger = (1 bsl BitSize) - 1, + OnesPerBit = + lists:foldl( + fun (Integer, Acc) when Integer >= 0, Integer =< MaxInteger -> + lists:foldl( + fun (BitIndex, AccB) -> + BitValue = (Integer band (1 bsl BitIndex)) bsr BitIndex, + orddict:update_counter(BitIndex, BitValue, AccB) + end, + Acc, + lists:seq(0, BitSize - 1)) + end, + orddict:new(), + Integers), + + ExpectedNrOfOnes = length(Integers) div 2, + FailureText = + orddict:fold( + fun (BitIndex, NrOfOnes, Acc) -> + RelativeDeviation = abs(NrOfOnes - ExpectedNrOfOnes) / length(Integers), + case RelativeDeviation >= MaxRelativeDeviation of + false -> Acc; + true -> + [Acc, + io_lib:format( + "Unreasonable deviation on number of set bits (i=~p): " + "expected ~p, got ~p (relative dev. ~.3f)~n", + [BitIndex, ExpectedNrOfOnes, NrOfOnes, RelativeDeviation])] + end + end, + [], + OnesPerBit), + + (FailureText =:= [] orelse ct:fail(FailureText)). + +nif_hash_result_bitsize(internal) -> 32; +nif_hash_result_bitsize(phash2) -> 27. + +unique(List) -> + lists:usort(List). + +random_uint32() -> + rand:uniform(1 bsl 32) - 1. + +random_term() -> + case rand:uniform(6) of + 1 -> rand:uniform(1 bsl 27) - 1; % small + 2 -> (1 bsl 27) + rand:uniform(1 bsl 128); % big + 3 -> random_sign() * (rand:uniform() * (1 bsl 53)); % float + 4 -> random_binary(); + 5 -> random_pid(); + 6 -> + Length = rand:uniform(10), + List = [random_term() || _ <- lists:seq(1, Length)], + case rand:uniform(2) of + 1 -> + List; + 2 -> + list_to_tuple(List) + end + end. + +random_sign() -> + case rand:uniform(2) of + 1 -> -1.0; + 2 -> 1.0 + end. + +random_binary() -> + list_to_binary(random_bytes(rand:uniform(32) - 1)). + +random_bytes(0) -> + []; +random_bytes(N) when N > 0 -> + [rand:uniform(256) - 1 | random_bytes(N - 1)]. + +random_pid() -> + Processes = erlang:processes(), + lists:nth(rand:uniform(length(Processes)), Processes). %% The NIFs: lib_version() -> undefined. @@ -2621,6 +2775,7 @@ type_test() -> ?nif_stub. tuple_2_list(_) -> ?nif_stub. is_identical(_,_) -> ?nif_stub. compare(_,_) -> ?nif_stub. +hash_nif(_Type, _Term, _Salt) -> ?nif_stub. many_args_100(_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_) -> ?nif_stub. clone_bin(_) -> ?nif_stub. make_sub_bin(_,_,_) -> ?nif_stub. diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 8fe5ee809a..a255c9f096 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -687,6 +687,31 @@ static ERL_NIF_TERM compare(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) return enif_make_int(env, enif_compare(argv[0],argv[1])); } +static ERL_NIF_TERM hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + if (argc != 3) { + return enif_make_badarg(env); + } + + ErlNifHash type; + if (enif_is_identical(argv[0], enif_make_atom(env, "internal"))) { + type = ERL_NIF_INTERNAL_HASH; + } + else if (enif_is_identical(argv[0], enif_make_atom(env, "phash2"))) { + type = ERL_NIF_PHASH2; + } + else { + return enif_make_badarg(env); + } + + ErlNifUInt64 salt; + if (! enif_get_uint64(env, argv[2], &salt)) { + return enif_make_badarg(env); + } + + return enif_make_uint64(env, enif_hash(type, argv[1], salt)); +} + static ERL_NIF_TERM many_args_100(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { int i, k; @@ -2864,6 +2889,7 @@ static ErlNifFunc nif_funcs[] = {"tuple_2_list", 1, tuple_2_list}, {"is_identical",2,is_identical}, {"compare",2,compare}, + {"hash_nif",3,hash_nif}, {"many_args_100", 100, many_args_100}, {"clone_bin", 1, clone_bin}, {"make_sub_bin", 3, make_sub_bin}, diff --git a/erts/emulator/test/node_container_SUITE.erl b/erts/emulator/test/node_container_SUITE.erl index 291d3ee30d..30518a5b27 100644 --- a/erts/emulator/test/node_container_SUITE.erl +++ b/erts/emulator/test/node_container_SUITE.erl @@ -45,7 +45,6 @@ ets_refc/1, match_spec_refc/1, timer_refc/1, - otp_4715/1, pid_wrap/1, port_wrap/1, bad_nc/1, @@ -62,7 +61,7 @@ all() -> [term_to_binary_to_term_eq, round_trip_eq, cmp, ref_eq, node_table_gc, dist_link_refc, dist_monitor_refc, node_controller_refc, ets_refc, match_spec_refc, - timer_refc, otp_4715, pid_wrap, port_wrap, bad_nc, + timer_refc, pid_wrap, port_wrap, bad_nc, unique_pid, iter_max_procs, magic_ref]. init_per_suite(Config) -> @@ -684,35 +683,6 @@ timer_refc(Config) when is_list(Config) -> nc_refc_check(node()), ok. -otp_4715(Config) when is_list(Config) -> - case test_server:is_release_available("r9b") of - true -> otp_4715_1(Config); - false -> {skip,"No R9B found"} - end. - -otp_4715_1(Config) -> - case erlang:system_info(compat_rel) of - 9 -> - run_otp_4715(Config); - _ -> - Pa = filename:dirname(code:which(?MODULE)), - test_server:run_on_shielded_node(fun () -> - run_otp_4715(Config) - end, - "+R9 -pa " ++ Pa) - end. - -run_otp_4715(Config) when is_list(Config) -> - erts_debug:set_internal_state(available_internal_state, true), - PidList = [mk_pid({a@b, 1}, 4710, 2), - mk_pid({a@b, 1}, 4712, 1), - mk_pid({c@b, 1}, 4711, 1), - mk_pid({b@b, 3}, 4711, 1), - mk_pid({b@b, 2}, 4711, 1)], - - R9Sorted = old_mod:sort_on_old_node(PidList), - R9Sorted = lists:sort(PidList). - pid_wrap(Config) when is_list(Config) -> pp_wrap(pid). port_wrap(Config) when is_list(Config) -> diff --git a/erts/emulator/test/old_mod.erl b/erts/emulator/test/old_mod.erl deleted file mode 100644 index 866aba79bb..0000000000 --- a/erts/emulator/test/old_mod.erl +++ /dev/null @@ -1,48 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2003-2016. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - --module(old_mod). --compile(r10). - --export([sort_on_old_node/1, sorter/3]). - --include_lib("common_test/include/ct.hrl"). - -sorter(Receiver, Ref, List) -> - Receiver ! {Ref, lists:sort(List)}. - -sort_on_old_node(List) when is_list(List) -> - OldVersion = "r10", - Pa = filename:dirname(code:which(?MODULE)), - {X, Y, Z} = now(), - NodeName = list_to_atom(OldVersion - ++ "_" - ++ integer_to_list(X) - ++ integer_to_list(Y) - ++ integer_to_list(Z)), - {ok, Node} = test_server:start_node(NodeName, - peer, - [{args, " -pa " ++ Pa}, - {erl, [{release, OldVersion++"b_patched"}]}]), - Ref = make_ref(), - spawn_link(Node, ?MODULE, sorter, [self(), Ref, List]), - SortedPids = receive {Ref, SP} -> SP end, - true = test_server:stop_node(Node), - SortedPids. diff --git a/erts/emulator/test/scheduler_SUITE.erl b/erts/emulator/test/scheduler_SUITE.erl index b178dede5b..64e51e7d7c 100644 --- a/erts/emulator/test/scheduler_SUITE.erl +++ b/erts/emulator/test/scheduler_SUITE.erl @@ -807,21 +807,31 @@ update_cpu_info(Config) when is_list(Config) -> %% Nothing much to test; just a smoke test ok; Onln0 -> - %% unset least significant bit - Aff = (OldAff band (OldAff - 1)), - set_affinity_mask(Aff), - Onln1 = Avail - 1, - case adjust_schedulers_online() of - {Onln0, Onln1} -> - Onln1 = erlang:system_info(schedulers_online), - receive after 500 -> ok end, - io:format("TEST - Affinity mask: ~p - Schedulers online: ~p - Scheduler bindings: ~p~n", - [Aff, Onln1, erlang:system_info(scheduler_bindings)]), - unchanged = adjust_schedulers_online(), - ok; - Fail -> - ct:fail(Fail) - end + Cpus = bits_in_mask(OldAff), + RmCpus = case Cpus > Onln0 of + true -> Cpus - Onln0 + 1; + false -> Onln0 - Cpus + 1 + end, + Onln1 = Cpus - RmCpus, + case Onln1 > 0 of + false -> + %% Nothing much to test; just a smoke test + ok; + true -> + Aff = restrict_affinity_mask(OldAff, RmCpus), + set_affinity_mask(Aff), + case adjust_schedulers_online() of + {Onln0, Onln1} -> + Onln1 = erlang:system_info(schedulers_online), + receive after 500 -> ok end, + io:format("TEST - Affinity mask: ~p - Schedulers online: ~p - Scheduler bindings: ~p~n", + [Aff, Onln1, erlang:system_info(scheduler_bindings)]), + unchanged = adjust_schedulers_online(), + ok; + Fail -> + ct:fail(Fail) + end + end end after set_affinity_mask(OldAff), @@ -835,13 +845,49 @@ update_cpu_info(Config) when is_list(Config) -> end end. +bits_in_mask(Mask) -> + bits_in_mask(Mask, 0, 0). + +bits_in_mask(0, Shift, N) -> + N; +bits_in_mask(Mask, Shift, N) -> + case Mask band (1 bsl Shift) of + 0 -> bits_in_mask(Mask, Shift+1, N); + _ -> bits_in_mask(Mask band (bnot (1 bsl Shift)), + Shift+1, N+1) + end. + +restrict_affinity_mask(Mask, N) -> + try + restrict_affinity_mask(Mask, 0, N) + catch + throw : Reason -> + exit({Reason, Mask, N}) + end. + +restrict_affinity_mask(Mask, _Shift, 0) -> + Mask; +restrict_affinity_mask(0, _Shift, _N) -> + throw(overresticted_affinity_mask); +restrict_affinity_mask(Mask, Shift, N) -> + case Mask band (1 bsl Shift) of + 0 -> restrict_affinity_mask(Mask, Shift+1, N); + _ -> restrict_affinity_mask(Mask band (bnot (1 bsl Shift)), + Shift+1, N-1) + end. + adjust_schedulers_online() -> case erlang:system_info(update_cpu_info) of unchanged -> unchanged; changed -> Avail = erlang:system_info(logical_processors_available), - {erlang:system_flag(schedulers_online, Avail), Avail} + Scheds = erlang:system_info(schedulers), + SOnln = case Avail > Scheds of + true -> Scheds; + false -> Avail + end, + {erlang:system_flag(schedulers_online, SOnln), SOnln} end. read_affinity(Data) -> @@ -1041,12 +1087,8 @@ scheduler_threads(Config) when is_list(Config) -> {Sched, SchedOnln, _} = get_sstate(Config, ""), %% Configure half the number of both the scheduler threads and %% the scheduler threads online. - {HalfSched, HalfSchedOnln} = case SmpSupport of - false -> {1,1}; - true -> - {Sched div 2, - SchedOnln div 2} - end, + {HalfSched, HalfSchedOnln} = {lists:max([1,Sched div 2]), + lists:max([1,SchedOnln div 2])}, {HalfSched, HalfSchedOnln, _} = get_sstate(Config, "+SP 50:50"), %% Use +S to configure 4x the number of scheduler threads and %% 4x the number of scheduler threads online, but alter that @@ -1103,12 +1145,8 @@ dirty_scheduler_threads(Config) when is_list(Config) -> dirty_scheduler_threads_test(Config) -> SmpSupport = erlang:system_info(smp_support), {Sched, SchedOnln, _} = get_dsstate(Config, ""), - {HalfSched, HalfSchedOnln} = case SmpSupport of - false -> {1,1}; - true -> - {Sched div 2, - SchedOnln div 2} - end, + {HalfSched, HalfSchedOnln} = {lists:max([1,Sched div 2]), + lists:max([1,SchedOnln div 2])}, Cmd1 = "+SDcpu "++integer_to_list(HalfSched)++":"++ integer_to_list(HalfSchedOnln), {HalfSched, HalfSchedOnln, _} = get_dsstate(Config, Cmd1), diff --git a/erts/emulator/test/smoke_test_SUITE.erl b/erts/emulator/test/smoke_test_SUITE.erl index 5eccdc562b..45b28b28a5 100644 --- a/erts/emulator/test/smoke_test_SUITE.erl +++ b/erts/emulator/test/smoke_test_SUITE.erl @@ -66,17 +66,10 @@ boot_combo(Config) when is_list(Config) -> ok end end, - SMPDisable = fun () -> false = erlang:system_info(smp_support) end, try chk_boot(Config, "+Ktrue", NOOP), chk_boot(Config, "+A42", A42), - chk_boot(Config, "-smp disable", SMPDisable), chk_boot(Config, "+Ktrue +A42", A42), - chk_boot(Config, "-smp disable +A42", - fun () -> SMPDisable(), A42() end), - chk_boot(Config, "-smp disable +Ktrue", SMPDisable), - chk_boot(Config, "-smp disable +Ktrue +A42", - fun () -> SMPDisable(), A42() end), %% A lot more combos could be implemented... ok after diff --git a/erts/emulator/test/statistics_SUITE.erl b/erts/emulator/test/statistics_SUITE.erl index f51244485b..729e86cb4f 100644 --- a/erts/emulator/test/statistics_SUITE.erl +++ b/erts/emulator/test/statistics_SUITE.erl @@ -329,9 +329,9 @@ scheduler_wall_time_test(Type) -> %% 50% load HalfHogs = [StartHog() || _ <- lists:seq(1, (Schedulers-1) div 2)], HalfDirtyCPUHogs = [StartDirtyHog(dirty_cpu) - || _ <- lists:seq(1, DirtyCPUSchedulers div 2)], + || _ <- lists:seq(1, lists:max([1,DirtyCPUSchedulers div 2]))], HalfDirtyIOHogs = [StartDirtyHog(dirty_io) - || _ <- lists:seq(1, DirtyIOSchedulers div 2)], + || _ <- lists:seq(1, lists:max([1,DirtyIOSchedulers div 2]))], HalfLoad = lists:sum(get_load(Type)) div TotLoadSchedulers, if Schedulers < 2, HalfLoad > 80 -> ok; %% Ok only one scheduler online and one hog %% We want roughly 50% load |