aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/test
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/test')
-rw-r--r--erts/emulator/test/nif_SUITE.erl95
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_SUITE.c25
-rw-r--r--erts/emulator/test/num_bif_SUITE.erl14
-rw-r--r--erts/emulator/test/persistent_term_SUITE.erl80
-rw-r--r--erts/emulator/test/process_SUITE.erl14
-rw-r--r--erts/emulator/test/system_info_SUITE.erl84
6 files changed, 226 insertions, 86 deletions
diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl
index edad62a9fb..0d0930e124 100644
--- a/erts/emulator/test/nif_SUITE.erl
+++ b/erts/emulator/test/nif_SUITE.erl
@@ -486,6 +486,7 @@ t_on_load(Config) when is_list(Config) ->
-define(ERL_NIF_SELECT_WRITE, (1 bsl 1)).
-define(ERL_NIF_SELECT_STOP, (1 bsl 2)).
-define(ERL_NIF_SELECT_CANCEL, (1 bsl 3)).
+-define(ERL_NIF_SELECT_CUSTOM_MSG, (1 bsl 4)).
-define(ERL_NIF_SELECT_STOP_CALLED, (1 bsl 0)).
-define(ERL_NIF_SELECT_STOP_SCHEDULED, (1 bsl 1)).
@@ -496,100 +497,106 @@ t_on_load(Config) when is_list(Config) ->
select(Config) when is_list(Config) ->
ensure_lib_loaded(Config),
+ select_do(0, make_ref(), make_ref(), null),
+
+ RefBin = list_to_binary(lists:duplicate(100, $x)),
+ [select_do(?ERL_NIF_SELECT_CUSTOM_MSG,
+ small, {a, tuple, with, "some", RefBin}, MSG_ENV)
+ || MSG_ENV <- [null, alloc_env]],
+ ok.
+
+select_do(Flag, Ref, Ref2, MSG_ENV) ->
+ io:format("select_do(~p, ~p, ~p)\n", [Ref, Ref2, MSG_ENV]),
- Ref = make_ref(),
- Ref2 = make_ref(),
{{R, R_ptr}, {W, W_ptr}} = pipe_nif(),
ok = write_nif(W, <<"hej">>),
<<"hej">> = read_nif(R, 3),
%% Wait for read
eagain = read_nif(R, 3),
- 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,null,Ref),
+ 0 = select_nif(R,?ERL_NIF_SELECT_READ bor Flag, R,null,Ref,MSG_ENV),
[] = flush(0),
ok = write_nif(W, <<"hej">>),
- [{select, R, Ref, ready_input}] = flush(),
- 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,self(),Ref2),
- [{select, R, Ref2, ready_input}] = flush(),
+ receive_ready(R, Ref, ready_input),
+ 0 = select_nif(R,?ERL_NIF_SELECT_READ bor Flag,R,self(),Ref2,MSG_ENV),
+ receive_ready(R, Ref2, ready_input),
Papa = self(),
Pid = spawn_link(fun() ->
- [{select, R, Ref, ready_input}] = flush(),
+ receive_ready(R, Ref, ready_input),
Papa ! {self(), done}
end),
- 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,Pid,Ref),
+ 0 = select_nif(R, ?ERL_NIF_SELECT_READ bor Flag, R, Pid, Ref,MSG_ENV),
{Pid, done} = receive_any(1000),
%% Cancel read
- 0 = select_nif(R,?ERL_NIF_SELECT_READ bor ?ERL_NIF_SELECT_CANCEL,R,null,Ref),
+ 0 = select_nif(R,?ERL_NIF_SELECT_READ bor ?ERL_NIF_SELECT_CANCEL,R,null,Ref,null),
<<"hej">> = read_nif(R, 3),
- 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,null,Ref),
+ 0 = select_nif(R, ?ERL_NIF_SELECT_READ bor Flag, R, null, Ref, MSG_ENV),
?ERL_NIF_SELECT_READ_CANCELLED =
- select_nif(R,?ERL_NIF_SELECT_READ bor ?ERL_NIF_SELECT_CANCEL,R,null,Ref),
+ select_nif(R,?ERL_NIF_SELECT_READ bor ?ERL_NIF_SELECT_CANCEL,R,null,Ref,null),
ok = write_nif(W, <<"hej again">>),
[] = flush(0),
<<"hej again">> = read_nif(R, 9),
%% Wait for write
Written = write_full(W, $a),
- 0 = select_nif(W,?ERL_NIF_SELECT_WRITE,W,self(),Ref),
+ 0 = select_nif(W, ?ERL_NIF_SELECT_WRITE bor Flag, W, self(), Ref, MSG_ENV),
[] = flush(0),
Written = read_nif(R,byte_size(Written)),
- [{select, W, Ref, ready_output}] = flush(),
+ receive_ready(W, Ref, ready_output),
%% Cancel write
- 0 = select_nif(W,?ERL_NIF_SELECT_WRITE bor ?ERL_NIF_SELECT_CANCEL,W,null,Ref),
+ 0 = select_nif(W, ?ERL_NIF_SELECT_WRITE bor ?ERL_NIF_SELECT_CANCEL, W, null, Ref, null),
Written2 = write_full(W, $b),
- 0 = select_nif(W,?ERL_NIF_SELECT_WRITE,W,null,Ref),
+ 0 = select_nif(W, ?ERL_NIF_SELECT_WRITE bor Flag, W, null, Ref, MSG_ENV),
?ERL_NIF_SELECT_WRITE_CANCELLED =
- select_nif(W,?ERL_NIF_SELECT_WRITE bor ?ERL_NIF_SELECT_CANCEL,W,null,Ref),
+ select_nif(W, ?ERL_NIF_SELECT_WRITE bor ?ERL_NIF_SELECT_CANCEL, W, null, Ref, null),
Written2 = read_nif(R,byte_size(Written2)),
[] = flush(0),
%% Close write and wait for EOF
eagain = read_nif(R, 1),
- check_stop_ret(select_nif(W,?ERL_NIF_SELECT_STOP,W,null,Ref)),
+ check_stop_ret(select_nif(W, ?ERL_NIF_SELECT_STOP, W, null, Ref, null)),
[{fd_resource_stop, W_ptr, _}] = flush(),
{1, {W_ptr,_}} = last_fd_stop_call(),
true = is_closed_nif(W),
[] = flush(0),
- 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,self(),Ref),
- [{select, R, Ref, ready_input}] = flush(),
+ 0 = select_nif(R, ?ERL_NIF_SELECT_READ bor Flag, R, self(), Ref, MSG_ENV),
+ receive_ready(R, Ref, ready_input),
eof = read_nif(R,1),
- check_stop_ret(select_nif(R,?ERL_NIF_SELECT_STOP,R,null,Ref)),
+ check_stop_ret(select_nif(R, ?ERL_NIF_SELECT_STOP, R, null, Ref, null)),
[{fd_resource_stop, R_ptr, _}] = flush(),
{1, {R_ptr,_}} = last_fd_stop_call(),
true = is_closed_nif(R),
- select_2(Config).
+ select_2(Flag, Ref, Ref2, MSG_ENV).
-select_2(Config) ->
+select_2(Flag, Ref1, Ref2, MSG_ENV) ->
erlang:garbage_collect(),
{_,_,2} = last_resource_dtor_call(),
- Ref1 = make_ref(),
- Ref2 = make_ref(),
{{R, R_ptr}, {W, W_ptr}} = pipe_nif(),
%% Change ref
eagain = read_nif(R, 1),
- 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,null,Ref1),
- 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,self(),Ref2),
+ 0 = select_nif(R, ?ERL_NIF_SELECT_READ bor Flag, R, null, Ref1, MSG_ENV),
+ 0 = select_nif(R, ?ERL_NIF_SELECT_READ bor Flag, R, self(), Ref2, MSG_ENV),
[] = flush(0),
ok = write_nif(W, <<"hej">>),
- [{select, R, Ref2, ready_input}] = flush(),
+ receive_ready(R, Ref2, ready_input),
<<"hej">> = read_nif(R, 3),
%% Change pid
eagain = read_nif(R, 1),
- 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,null,Ref1),
+ 0 = select_nif(R, ?ERL_NIF_SELECT_READ bor Flag, R, null, Ref1, MSG_ENV),
Papa = self(),
spawn_link(fun() ->
- 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,null,Ref1),
+ 0 = select_nif(R, ?ERL_NIF_SELECT_READ bor Flag, R, null, Ref1, MSG_ENV),
[] = flush(0),
Papa ! sync,
- [{select, R, Ref1, ready_input}] = flush(),
+ receive_ready(R, Ref1, ready_input),
<<"hej">> = read_nif(R, 3),
Papa ! done
end),
@@ -598,24 +605,30 @@ select_2(Config) ->
done = receive_any(),
[] = flush(0),
- check_stop_ret(select_nif(R,?ERL_NIF_SELECT_STOP,R,null,Ref1)),
+ check_stop_ret(select_nif(R,?ERL_NIF_SELECT_STOP,R,null,Ref1, null)),
[{fd_resource_stop, R_ptr, _}] = flush(),
{1, {R_ptr,_}} = last_fd_stop_call(),
true = is_closed_nif(R),
%% Stop without previous read/write select
- ?ERL_NIF_SELECT_STOP_CALLED = select_nif(W,?ERL_NIF_SELECT_STOP,W,null,Ref1),
+ ?ERL_NIF_SELECT_STOP_CALLED = select_nif(W,?ERL_NIF_SELECT_STOP,W,null,Ref1,null),
[{fd_resource_stop, W_ptr, 1}] = flush(),
{1, {W_ptr,1}} = last_fd_stop_call(),
true = is_closed_nif(W),
- select_3(Config).
+ select_3().
-select_3(_Config) ->
+select_3() ->
erlang:garbage_collect(),
{_,_,2} = last_resource_dtor_call(),
ok.
+receive_ready(R, Ref, IOatom) when is_reference(Ref) ->
+ [{select, R, Ref, IOatom}] = flush();
+receive_ready(_, Msg, _) ->
+ [Got] = flush(),
+ {true,_,_} = {Got=:=Msg, Got, Msg}.
+
%% @doc The stealing child process for the select_steal test. Duplicates given
%% W/RFds and runs select on them to steal
select_steal_child_process(Parent, RFd) ->
@@ -624,7 +637,7 @@ select_steal_child_process(Parent, RFd) ->
Ref2 = make_ref(),
%% Try to select from the child pid (steal from parent)
- ?assertEqual(0, select_nif(R2Fd, ?ERL_NIF_SELECT_READ, R2Fd, null, Ref2)),
+ ?assertEqual(0, select_nif(R2Fd, ?ERL_NIF_SELECT_READ, R2Fd, null, Ref2, null)),
?assertEqual([], flush(0)),
?assertEqual(eagain, read_nif(R2Fd, 1)),
@@ -632,7 +645,7 @@ select_steal_child_process(Parent, RFd) ->
Parent ! {self(), stage1}, % signal parent to send the <<"stolen1">>
%% Receive <<"stolen1">> via enif_select
- ?assertEqual(0, select_nif(R2Fd, ?ERL_NIF_SELECT_READ, R2Fd, null, Ref2)),
+ ?assertEqual(0, select_nif(R2Fd, ?ERL_NIF_SELECT_READ, R2Fd, null, Ref2, null)),
?assertMatch([{select, R2Fd, Ref2, ready_input}], flush()),
?assertEqual(<<"stolen1">>, read_nif(R2Fd, 7)),
@@ -650,7 +663,7 @@ select_steal(Config) when is_list(Config) ->
{{RFd, RPtr}, {WFd, WPtr}} = pipe_nif(),
%% Bind the socket to current pid in enif_select
- ?assertEqual(0, select_nif(RFd, ?ERL_NIF_SELECT_READ, RFd, null, Ref)),
+ ?assertEqual(0, select_nif(RFd, ?ERL_NIF_SELECT_READ, RFd, null, Ref, null)),
?assertEqual([], flush(0)),
%% Spawn a process and do some stealing
@@ -664,15 +677,15 @@ select_steal(Config) when is_list(Config) ->
?assertMatch([{Pid, done}], flush(1)), % synchronize with the child
%% Try to select from the parent pid (steal back)
- ?assertEqual(0, select_nif(RFd, ?ERL_NIF_SELECT_READ, RFd, Pid, Ref)),
+ ?assertEqual(0, select_nif(RFd, ?ERL_NIF_SELECT_READ, RFd, Pid, Ref, null)),
%% Ensure that no data is hanging and close.
%% Rfd is stolen at this point.
- check_stop_ret(select_nif(WFd, ?ERL_NIF_SELECT_STOP, WFd, null, Ref)),
+ check_stop_ret(select_nif(WFd, ?ERL_NIF_SELECT_STOP, WFd, null, Ref, null)),
?assertMatch([{fd_resource_stop, WPtr, _}], flush()),
{1, {WPtr, 1}} = last_fd_stop_call(),
- check_stop_ret(select_nif(RFd, ?ERL_NIF_SELECT_STOP, RFd, null, Ref)),
+ check_stop_ret(select_nif(RFd, ?ERL_NIF_SELECT_STOP, RFd, null, Ref, null)),
?assertMatch([{fd_resource_stop, RPtr, _}], flush()),
{1, {RPtr, _DirectCall}} = last_fd_stop_call(),
@@ -3396,7 +3409,7 @@ term_to_binary_nif(_, _) -> ?nif_stub.
binary_to_term_nif(_, _, _) -> ?nif_stub.
port_command_nif(_, _) -> ?nif_stub.
format_term_nif(_,_) -> ?nif_stub.
-select_nif(_,_,_,_,_) -> ?nif_stub.
+select_nif(_,_,_,_,_,_) -> ?nif_stub.
dupe_resource_nif(_) -> ?nif_stub.
pipe_nif() -> ?nif_stub.
write_nif(_,_) -> ?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 f2ce6dbe67..21af4b05b3 100644
--- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
+++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
@@ -2486,7 +2486,8 @@ static ERL_NIF_TERM select_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
enum ErlNifSelectFlags mode;
void* obj;
ErlNifPid nifpid, *pid = NULL;
- ERL_NIF_TERM ref;
+ ERL_NIF_TERM ref_or_msg;
+ ErlNifEnv* msg_env = NULL;
int retval;
if (!get_fd(env, argv[0], &fdr)
@@ -2501,11 +2502,27 @@ static ERL_NIF_TERM select_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
return enif_make_badarg(env);
pid = &nifpid;
}
- ref = argv[4];
+ ref_or_msg = argv[4];
+ if (argv[5] != atom_null) {
+ msg_env = enif_alloc_env();
+ ref_or_msg = enif_make_copy(msg_env, ref_or_msg);
+ }
fdr->was_selected = 1;
enif_self(env, &fdr->pid);
- retval = enif_select(env, fdr->fd, mode, obj, pid, ref);
+ switch (mode) {
+ case ERL_NIF_SELECT_CUSTOM_MSG | ERL_NIF_SELECT_READ:
+ retval = enif_select_read(env, fdr->fd, obj, pid, ref_or_msg, msg_env);
+ break;
+ case ERL_NIF_SELECT_CUSTOM_MSG | ERL_NIF_SELECT_WRITE:
+ retval = enif_select_write(env, fdr->fd, obj, pid, ref_or_msg, msg_env);
+ break;
+ default:
+ retval = enif_select(env, fdr->fd, mode, obj, pid, ref_or_msg);
+ }
+
+ if (msg_env)
+ enif_free_env(msg_env);
return enif_make_int(env, retval);
}
@@ -3565,7 +3582,7 @@ static ErlNifFunc nif_funcs[] =
{"binary_to_term_nif", 3, binary_to_term},
{"port_command_nif", 2, port_command},
{"format_term_nif", 2, format_term},
- {"select_nif", 5, select_nif},
+ {"select_nif", 6, select_nif},
#ifndef __WIN32__
{"pipe_nif", 0, pipe_nif},
{"write_nif", 2, write_nif},
diff --git a/erts/emulator/test/num_bif_SUITE.erl b/erts/emulator/test/num_bif_SUITE.erl
index f15217814a..6b834705cf 100644
--- a/erts/emulator/test/num_bif_SUITE.erl
+++ b/erts/emulator/test/num_bif_SUITE.erl
@@ -504,6 +504,10 @@ t_integer_to_string(Config) when is_list(Config) ->
test_its("A", 10, 16),
test_its("D4BE", 54462, 16),
test_its("-D4BE", -54462, 16),
+ test_its("FFFFFFFFFF", 1099511627775, 16),
+ test_its("123456789ABCDEF123456789ABCDEF123456789ABCDEF",
+ 108977460683796539709587792812439445667270661579197935,
+ 16),
lists:foreach(fun(Value) ->
{'EXIT', {badarg, _}} =
@@ -515,12 +519,14 @@ t_integer_to_string(Config) when is_list(Config) ->
ok.
test_its(List,Int) ->
- Int = list_to_integer(List),
- Int = binary_to_integer(list_to_binary(List)).
+ List = integer_to_list(Int),
+ Binary = list_to_binary(List),
+ Binary = integer_to_binary(Int).
test_its(List,Int,Base) ->
- Int = list_to_integer(List, Base),
- Int = binary_to_integer(list_to_binary(List), Base).
+ List = integer_to_list(Int, Base),
+ Binary = list_to_binary(List),
+ Binary = integer_to_binary(Int, Base).
%% Tests binary_to_integer/1.
diff --git a/erts/emulator/test/persistent_term_SUITE.erl b/erts/emulator/test/persistent_term_SUITE.erl
index 58cd3276b0..58038e24b7 100644
--- a/erts/emulator/test/persistent_term_SUITE.erl
+++ b/erts/emulator/test/persistent_term_SUITE.erl
@@ -21,7 +21,7 @@
-module(persistent_term_SUITE).
-include_lib("common_test/include/ct.hrl").
--export([all/0,suite/0,
+-export([all/0,suite/0,init_per_suite/1,end_per_suite/1,
basic/1,purging/1,sharing/1,get_trapping/1,
info/1,info_trapping/1,killed_while_trapping/1,
off_heap_values/1,keys/1,collisions/1,
@@ -39,39 +39,49 @@ all() ->
killed_while_trapping,off_heap_values,keys,collisions,
init_restart].
+init_per_suite(Config) ->
+ %% Put a term in the dict so that we know that the testcases handle
+ %% stray terms left by stdlib or other test suites.
+ persistent_term:put(init_per_suite, {?MODULE}),
+ Config.
+
+end_per_suite(Config) ->
+ persistent_term:erase(init_per_suite),
+ Config.
+
basic(_Config) ->
Chk = chk(),
N = 777,
Seq = lists:seq(1, N),
- par(2, N, Seq),
- seq(3, Seq),
- seq(3, Seq), %Same values.
+ par(2, N, Seq, Chk),
+ seq(3, Seq, Chk),
+ seq(3, Seq, Chk), %Same values.
_ = [begin
Key = {?MODULE,{key,I}},
true = persistent_term:erase(Key),
false = persistent_term:erase(Key),
{'EXIT',{badarg,_}} = (catch persistent_term:get(Key))
end || I <- Seq],
- [] = [P || {{?MODULE,_},_}=P <- persistent_term:get()],
+ [] = [P || {{?MODULE,_},_}=P <- pget(Chk)],
chk(Chk).
-par(C, N, Seq) ->
+par(C, N, Seq, Chk) ->
_ = [spawn_link(fun() ->
ok = persistent_term:put({?MODULE,{key,I}},
{value,C*I})
end) || I <- Seq],
- Result = wait(N),
+ Result = wait(N, Chk),
_ = [begin
Double = C*I,
{{?MODULE,{key,I}},{value,Double}} = Res
end || {I,Res} <- lists:zip(Seq, Result)],
ok.
-seq(C, Seq) ->
+seq(C, Seq, Chk) ->
_ = [ok = persistent_term:put({?MODULE,{key,I}}, {value,C*I}) ||
I <- Seq],
- All = persistent_term:get(),
- All = [P || {{?MODULE,_},_}=P <- persistent_term:get()],
+ All = pget(Chk),
+ All = [P || {{?MODULE,_},_}=P <- All],
All = [{Key,persistent_term:get(Key)} || {Key,_} <- All],
Result = lists:sort(All),
_ = [begin
@@ -80,15 +90,15 @@ seq(C, Seq) ->
end || {I,Res} <- lists:zip(Seq, Result)],
ok.
-wait(N) ->
- All = [P || {{?MODULE,_},_}=P <- persistent_term:get()],
+wait(N, Chk) ->
+ All = [P || {{?MODULE,_},_}=P <- pget(Chk)],
case length(All) of
N ->
All = [{Key,persistent_term:get(Key)} || {Key,_} <- All],
lists:sort(All);
_ ->
receive after 10 -> ok end,
- wait(N)
+ wait(N, Chk)
end.
%% Make sure that terms that have been erased are copied into all
@@ -200,23 +210,23 @@ get_trapping(_Config) ->
_ -> 1000
end,
spawn_link(fun() -> get_trapping_create(N) end),
- All = do_get_trapping(N, []),
+ All = do_get_trapping(N, [], Chk),
N = get_trapping_check_result(lists:sort(All), 1),
erlang:garbage_collect(),
get_trapping_erase(N),
chk(Chk).
-do_get_trapping(N, Prev) ->
- case persistent_term:get() of
+do_get_trapping(N, Prev, Chk) ->
+ case pget(Chk) of
Prev when length(Prev) >= N ->
All = [P || {{?MODULE,{get_trapping,_}},_}=P <- Prev],
case length(All) of
N -> All;
- _ -> do_get_trapping(N, Prev)
+ _ -> do_get_trapping(N, Prev, Chk)
end;
New ->
receive after 1 -> ok end,
- do_get_trapping(N, New)
+ do_get_trapping(N, New, Chk)
end.
get_trapping_create(0) ->
@@ -331,25 +341,25 @@ info_trapping(_Config) ->
_ -> 1000
end,
spawn_link(fun() -> info_trapping_create(N) end),
- All = do_info_trapping(N, 0),
+ All = do_info_trapping(N, 0, Chk),
N = info_trapping_check_result(lists:sort(All), 1),
erlang:garbage_collect(),
info_trapping_erase(N),
chk(Chk).
-do_info_trapping(N, PrevMem) ->
+do_info_trapping(N, PrevMem, Chk) ->
case info_info() of
- {N,Mem} ->
+ {M,Mem} when M >= N ->
true = Mem >= PrevMem,
- All = [P || {{?MODULE,{info_trapping,_}},_}=P <- persistent_term:get()],
+ All = [P || {{?MODULE,{info_trapping,_}},_}=P <- pget(Chk)],
case length(All) of
N -> All;
- _ -> do_info_trapping(N, PrevMem)
+ _ -> do_info_trapping(N, PrevMem, Chk)
end;
{_,Mem} ->
true = Mem >= PrevMem,
receive after 1 -> ok end,
- do_info_trapping(N, Mem)
+ do_info_trapping(N, Mem, Chk)
end.
info_trapping_create(0) ->
@@ -462,17 +472,17 @@ collisions(_Config) ->
_ = [V = persistent_term:get(K) || {K,V} <- Kvs],
%% Now delete the persistent terms in random order.
- collisions_delete(lists:keysort(2, Kvs)),
+ collisions_delete(lists:keysort(2, Kvs), Chk),
chk(Chk).
-collisions_delete([{Key,Val}|Kvs]) ->
+collisions_delete([{Key,Val}|Kvs], Chk) ->
Val = persistent_term:get(Key),
true = persistent_term:erase(Key),
- true = lists:sort(persistent_term:get()) =:= lists:sort(Kvs),
+ true = lists:sort(pget(Chk)) =:= lists:sort(Kvs),
_ = [V = persistent_term:get(K) || {K,V} <- Kvs],
- collisions_delete(Kvs);
-collisions_delete([]) ->
+ collisions_delete(Kvs, Chk);
+collisions_delete([], _) ->
ok.
colliding_keys() ->
@@ -589,15 +599,16 @@ do_test_init_restart_cmd(File) ->
%% and after each test case.
chk() ->
- persistent_term:info().
+ {persistent_term:info(), persistent_term:get()}.
-chk(Chk) ->
- Chk = persistent_term:info(),
+chk({Info, _Initial} = Chk) ->
+ Info = persistent_term:info(),
Key = {?MODULE,?FUNCTION_NAME},
- ok = persistent_term:put(Key, {term,Chk}),
+ ok = persistent_term:put(Key, {term,Info}),
Term = persistent_term:get(Key),
true = persistent_term:erase(Key),
chk_not_stuck(Term),
+ [persistent_term:erase(K) || {K, _} <- pget(Chk)],
ok.
chk_not_stuck(Term) ->
@@ -612,3 +623,6 @@ chk_not_stuck(Term) ->
_ ->
ok
end.
+
+pget({_, Initial}) ->
+ persistent_term:get() -- Initial.
diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl
index f4b1d885fe..edf08ce0bd 100644
--- a/erts/emulator/test/process_SUITE.erl
+++ b/erts/emulator/test/process_SUITE.erl
@@ -2104,6 +2104,13 @@ spawn_opt_max_heap_size(_Config) ->
error_logger:add_report_handler(?MODULE, self()),
+ %% flush any prior messages in error_logger
+ Pid = spawn(fun() -> ok = nok end),
+ receive
+ {error, _, {emulator, _, [Pid|_]}} ->
+ flush()
+ end,
+
%% Test that numerical limit works
max_heap_size_test(1024, 1024, true, true),
@@ -2208,6 +2215,13 @@ receive_unexpected() ->
ok
end.
+flush() ->
+ receive
+ _M -> flush()
+ after 0 ->
+ ok
+ end.
+
%% error_logger report handler proxy
init(Pid) ->
{ok, Pid}.
diff --git a/erts/emulator/test/system_info_SUITE.erl b/erts/emulator/test/system_info_SUITE.erl
index 8ea2d88ec4..55b1162cfb 100644
--- a/erts/emulator/test/system_info_SUITE.erl
+++ b/erts/emulator/test/system_info_SUITE.erl
@@ -37,8 +37,9 @@
-export([process_count/1, system_version/1, misc_smoke_tests/1,
heap_size/1, wordsize/1, memory/1, ets_limit/1, atom_limit/1,
- ets_count/1,
- atom_count/1]).
+ ets_count/1, atom_count/1, system_logger/1]).
+
+-export([init/1, handle_event/2, handle_call/2]).
suite() ->
[{ct_hooks,[ts_install_cth]},
@@ -46,8 +47,8 @@ suite() ->
all() ->
[process_count, system_version, misc_smoke_tests,
- ets_count,
- heap_size, wordsize, memory, ets_limit, atom_limit, atom_count].
+ ets_count, heap_size, wordsize, memory, ets_limit, atom_limit, atom_count,
+ system_logger].
%%%
%%% The test cases -------------------------------------------------------------
@@ -578,3 +579,78 @@ atom_count(Config) when is_list(Config) ->
true = Limit >= Count2,
true = Count2 > Count1,
ok.
+
+
+system_logger(Config) when is_list(Config) ->
+
+ TC = self(),
+
+ ok = error_logger:add_report_handler(?MODULE, [TC]),
+
+ generate_log_event(),
+
+ flush(1, report_handler),
+
+ Initial = erlang:system_info(system_logger),
+
+ {Logger,_} = spawn_monitor(fun F() -> receive M -> TC ! {system_logger,M}, F() end end),
+
+ Initial = erlang:system_flag(system_logger, Logger),
+ Logger = erlang:system_info(system_logger),
+
+ generate_log_event(),
+ flush(1, system_logger),
+
+ Logger = erlang:system_flag(system_logger, Logger),
+
+ generate_log_event(),
+ flush(1, system_logger),
+
+ exit(Logger, die),
+ receive {'DOWN',_,_,_,_} -> ok end,
+
+ generate_log_event(),
+ flush(1, report_handler),
+
+ logger = erlang:system_info(system_logger),
+
+ logger = erlang:system_flag(system_logger, undefined),
+ generate_log_event(),
+ flush(),
+
+ undefined = erlang:system_flag(system_logger, Initial),
+
+ ok.
+
+flush() ->
+ receive
+ M ->
+ ct:fail({unexpected_message, M})
+ after 0 ->
+ ok
+ end.
+
+flush(0, _Pat) ->
+ flush();
+flush(Cnt, Pat) ->
+ receive
+ M when element(1,M) =:= Pat ->
+ ct:log("~p",[M]),
+ flush(Cnt-1, Pat)
+ after 500 ->
+ ct:fail({missing, Cnt, Pat})
+ end.
+
+generate_log_event() ->
+ {_Pid, Ref} = spawn_monitor(fun() -> ok = nok end),
+ receive {'DOWN', Ref, _, _, _} -> ok end.
+
+init([To]) ->
+ {ok, To}.
+
+handle_call(Msg, State) ->
+ {ok, Msg, State}.
+
+handle_event(Event, State) ->
+ State ! {report_handler, Event},
+ {ok, State}.