aboutsummaryrefslogtreecommitdiffstats
path: root/lib/stdlib/test
diff options
context:
space:
mode:
Diffstat (limited to 'lib/stdlib/test')
-rw-r--r--lib/stdlib/test/Makefile1
-rw-r--r--lib/stdlib/test/base64_SUITE.erl40
-rw-r--r--lib/stdlib/test/binary_module_SUITE.erl40
-rw-r--r--lib/stdlib/test/dets_SUITE.erl19
-rw-r--r--lib/stdlib/test/dict_SUITE.erl16
-rw-r--r--lib/stdlib/test/epp_SUITE.erl79
-rw-r--r--lib/stdlib/test/erl_anno_SUITE.erl72
-rw-r--r--lib/stdlib/test/erl_eval_SUITE.erl23
-rw-r--r--lib/stdlib/test/erl_lint_SUITE.erl115
-rw-r--r--lib/stdlib/test/erl_pp_SUITE.erl20
-rw-r--r--lib/stdlib/test/erl_scan_SUITE.erl279
-rw-r--r--lib/stdlib/test/error_logger_h_SUITE.erl406
-rw-r--r--lib/stdlib/test/ets_SUITE.erl98
-rw-r--r--lib/stdlib/test/ets_tough_SUITE.erl10
-rw-r--r--lib/stdlib/test/filelib_SUITE.erl2
-rw-r--r--lib/stdlib/test/filename_SUITE.erl35
-rw-r--r--lib/stdlib/test/gen_event_SUITE.erl11
-rw-r--r--lib/stdlib/test/id_transform_SUITE.erl53
-rw-r--r--lib/stdlib/test/io_SUITE.erl213
-rw-r--r--lib/stdlib/test/io_proto_SUITE.erl162
-rw-r--r--lib/stdlib/test/lists_SUITE.erl185
-rw-r--r--lib/stdlib/test/proc_lib_SUITE.erl228
-rw-r--r--lib/stdlib/test/qlc_SUITE.erl15
-rw-r--r--lib/stdlib/test/queue_SUITE.erl10
-rw-r--r--lib/stdlib/test/rand_SUITE.erl26
-rw-r--r--lib/stdlib/test/random_iolist.erl16
-rw-r--r--lib/stdlib/test/random_unicode_list.erl18
-rw-r--r--lib/stdlib/test/re_SUITE.erl129
-rw-r--r--lib/stdlib/test/run_pcre_tests.erl10
-rw-r--r--lib/stdlib/test/select_SUITE.erl21
-rw-r--r--lib/stdlib/test/sets_SUITE.erl22
-rw-r--r--lib/stdlib/test/timer_SUITE.erl24
-rw-r--r--lib/stdlib/test/zip_SUITE.erl20
33 files changed, 1532 insertions, 886 deletions
diff --git a/lib/stdlib/test/Makefile b/lib/stdlib/test/Makefile
index d4ab674486..e366c2b755 100644
--- a/lib/stdlib/test/Makefile
+++ b/lib/stdlib/test/Makefile
@@ -30,6 +30,7 @@ MODULES= \
erl_lint_SUITE \
erl_pp_SUITE \
erl_scan_SUITE \
+ error_logger_h_SUITE \
escript_SUITE \
ets_SUITE \
ets_tough_SUITE \
diff --git a/lib/stdlib/test/base64_SUITE.erl b/lib/stdlib/test/base64_SUITE.erl
index cca9b967d5..f750145ef0 100644
--- a/lib/stdlib/test/base64_SUITE.erl
+++ b/lib/stdlib/test/base64_SUITE.erl
@@ -30,7 +30,8 @@
%% Test cases must be exported.
-export([base64_encode/1, base64_decode/1, base64_otp_5635/1,
base64_otp_6279/1, big/1, illegal/1, mime_decode/1,
- mime_decode_to_string/1, roundtrip/1]).
+ mime_decode_to_string/1,
+ roundtrip_1/1, roundtrip_2/1, roundtrip_3/1, roundtrip_4/1]).
init_per_testcase(_, Config) ->
Dog = test_server:timetrap(?t:minutes(4)),
@@ -50,10 +51,11 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[base64_encode, base64_decode, base64_otp_5635,
base64_otp_6279, big, illegal, mime_decode, mime_decode_to_string,
- roundtrip].
+ {group, roundtrip}].
groups() ->
- [].
+ [{roundtrip, [parallel],
+ [roundtrip_1, roundtrip_2, roundtrip_3, roundtrip_4]}].
init_per_suite(Config) ->
Config.
@@ -242,21 +244,33 @@ mime_decode_to_string(Config) when is_list(Config) ->
%%-------------------------------------------------------------------------
-roundtrip(Config) when is_list(Config) ->
- Sizes = lists:seq(1, 255) ++ lists:seq(2400-5, 2440),
- roundtrip_1(Sizes, []).
+roundtrip_1(Config) when is_list(Config) ->
+ do_roundtrip(1).
-roundtrip_1([NextSize|Sizes], Current) ->
+roundtrip_2(Config) when is_list(Config) ->
+ do_roundtrip(2).
+
+roundtrip_3(Config) when is_list(Config) ->
+ do_roundtrip(3).
+
+roundtrip_4(Config) when is_list(Config) ->
+ do_roundtrip(4).
+
+do_roundtrip(Offset) ->
+ Sizes = lists:seq(Offset, 255, 4) ++ lists:seq(2400-6+Offset, 2440, 4),
+ do_roundtrip_1(Sizes, []).
+
+do_roundtrip_1([NextSize|Sizes], Current) ->
Len = length(Current),
io:format("~p", [Len]),
- do_roundtrip(Current),
+ do_roundtrip_2(Current),
Next = random_byte_list(NextSize - Len, Current),
- roundtrip_1(Sizes, Next);
-roundtrip_1([], Last) ->
+ do_roundtrip_1(Sizes, Next);
+do_roundtrip_1([], Last) ->
io:format("~p", [length(Last)]),
- do_roundtrip(Last).
+ do_roundtrip_2(Last).
-do_roundtrip(List) ->
+do_roundtrip_2(List) ->
Bin = list_to_binary(List),
Base64Bin = base64:encode(List),
Base64Bin = base64:encode(Bin),
@@ -326,7 +340,7 @@ interleaved_ws_roundtrip_1([], Base64List, Bin, List) ->
random_byte_list(0, Acc) ->
Acc;
random_byte_list(N, Acc) ->
- random_byte_list(N-1, [random:uniform(255)|Acc]).
+ random_byte_list(N-1, [rand:uniform(255)|Acc]).
make_big_binary(N) ->
list_to_binary(mbb(N, [])).
diff --git a/lib/stdlib/test/binary_module_SUITE.erl b/lib/stdlib/test/binary_module_SUITE.erl
index 70c946bdb9..8a2df2bf85 100644
--- a/lib/stdlib/test/binary_module_SUITE.erl
+++ b/lib/stdlib/test/binary_module_SUITE.erl
@@ -536,6 +536,12 @@ do_interesting(Module) ->
?line [<<3>>,<<6>>] = Module:split(<<1,2,3,4,5,6,7,8>>,
[<<1>>,<<2>>,<<4>>,<<5>>,<<7>>,<<8>>],
[global,trim_all]),
+ [<<>>] = binary:split(<<>>, <<",">>, []),
+ [] = binary:split(<<>>, <<",">>, [trim]),
+ [] = binary:split(<<>>, <<",">>, [trim_all]),
+ [] = binary:split(<<>>, <<",">>, [global,trim]),
+ [] = binary:split(<<>>, <<",">>, [global,trim_all]),
+
?line badarg = ?MASK_ERROR(
Module:replace(<<1,2,3,4,5,6,7,8>>,
[<<4,5>>,<<7>>,<<8>>],<<99>>,
@@ -710,7 +716,7 @@ do_interesting(Module) ->
encode_decode(doc) ->
["test binary:encode_unsigned/1,2 and binary:decode_unsigned/1,2"];
encode_decode(Config) when is_list(Config) ->
- ?line random:seed({1271,769940,559934}),
+ rand:seed(exsplus, {1271,769940,559934}),
?line ok = encode_decode_loop({1,200},1000), % Need to be long enough
% to create offheap binaries
ok.
@@ -817,7 +823,7 @@ copy(Config) when is_list(Config) ->
?line badarg = ?MASK_ERROR(binary:copy(<<1,2,3>>,
16#FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)),
?line <<>> = binary:copy(<<>>,10000),
- ?line random:seed({1271,769940,559934}),
+ rand:seed(exsplus, {1271,769940,559934}),
?line ok = random_copy(3000),
?line erts_debug:set_internal_state(available_internal_state,true),
?line io:format("oldlimit: ~p~n",
@@ -855,7 +861,7 @@ random_copy(0) ->
ok;
random_copy(N) ->
Str = random_string({0,N}),
- Num = random:uniform(N div 10+1),
+ Num = rand:uniform(N div 10+1),
A = ?MASK_ERROR(binary:copy(Str,Num)),
B = ?MASK_ERROR(binref:copy(Str,Num)),
C = ?MASK_ERROR(binary:copy(make_unaligned(Str),Num)),
@@ -896,7 +902,7 @@ bin_to_list(Config) when is_list(Config) ->
?line [5] = lists:nthtail(byte_size(X)-1,LX),
?line [0,5] = lists:nthtail(byte_size(X)-2,LX),
?line [0,5] = lists:nthtail(byte_size(Y)-2,LY),
- ?line random:seed({1271,769940,559934}),
+ rand:seed(exsplus, {1271,769940,559934}),
?line ok = random_bin_to_list(5000),
ok.
@@ -963,7 +969,7 @@ parts(Config) when is_list(Config) ->
?line badarg = ?MASK_ERROR(binary:part(Simple,{-1,0})),
?line badarg = ?MASK_ERROR(binary:part(Simple,{7,2})),
?line <<8>> = binary:part(Simple,{7,1}),
- ?line random:seed({1271,769940,559934}),
+ rand:seed(exsplus, {1271,769940,559934}),
?line random_parts(5000),
ok.
@@ -987,15 +993,15 @@ random_parts(N) ->
random_parts(0,_) ->
[];
random_parts(X,N) ->
- Pos = random:uniform(N),
- Len = random:uniform((Pos * 12) div 10),
+ Pos = rand:uniform(N),
+ Len = rand:uniform((Pos * 12) div 10),
[{Pos,Len} | random_parts(X-1,N)].
random_ref_comp(doc) ->
["Test pseudorandomly generated cases against reference imlementation"];
random_ref_comp(Config) when is_list(Config) ->
put(success_counter,0),
- random:seed({1271,769940,559934}),
+ rand:seed(exsplus, {1271,769940,559934}),
Nr = {1,40},
Hr = {30,1000},
I1 = 1500,
@@ -1025,7 +1031,7 @@ random_ref_sr_comp(doc) ->
["Test pseudorandomly generated cases against reference imlementation of split and replace"];
random_ref_sr_comp(Config) when is_list(Config) ->
put(success_counter,0),
- random:seed({1271,769940,559934}),
+ rand:seed(exsplus, {1271,769940,559934}),
Nr = {1,40},
Hr = {30,1000},
I1 = 1500,
@@ -1043,7 +1049,7 @@ random_ref_fla_comp(doc) ->
["Test pseudorandomly generated cases against reference imlementation of split and replace"];
random_ref_fla_comp(Config) when is_list(Config) ->
?line put(success_counter,0),
- ?line random:seed({1271,769940,559934}),
+ rand:seed(exsplus, {1271,769940,559934}),
?line do_random_first_comp(5000,{1,1000}),
?line do_random_last_comp(5000,{1,1000}),
?line do_random_at_comp(5000,{1,1000}),
@@ -1377,24 +1383,24 @@ one_random(N) ->
random_number({Min,Max}) -> % Min and Max are *length* of number in
% decimal positions
- X = random:uniform(Max - Min + 1) + Min - 1,
- list_to_integer([one_random_number(random:uniform(10)) || _ <- lists:seq(1,X)]).
+ X = rand:uniform(Max - Min + 1) + Min - 1,
+ list_to_integer([one_random_number(rand:uniform(10)) || _ <- lists:seq(1,X)]).
random_length({Min,Max}) ->
- random:uniform(Max - Min + 1) + Min - 1.
+ rand:uniform(Max - Min + 1) + Min - 1.
random_string({Min,Max}) ->
- X = random:uniform(Max - Min + 1) + Min - 1,
- list_to_binary([one_random(random:uniform(68)) || _ <- lists:seq(1,X)]).
+ X = rand:uniform(Max - Min + 1) + Min - 1,
+ list_to_binary([one_random(rand:uniform(68)) || _ <- lists:seq(1,X)]).
random_substring({Min,Max},Hay) ->
- X = random:uniform(Max - Min + 1) + Min - 1,
+ X = rand:uniform(Max - Min + 1) + Min - 1,
Y = byte_size(Hay),
Z = if
X > Y -> Y;
true -> X
end,
PMax = Y - Z,
- Pos = random:uniform(PMax + 1) - 1,
+ Pos = rand:uniform(PMax + 1) - 1,
<<_:Pos/binary,Res:Z/binary,_/binary>> = Hay,
Res.
diff --git a/lib/stdlib/test/dets_SUITE.erl b/lib/stdlib/test/dets_SUITE.erl
index 7f5e06524a..e061e16e4c 100644
--- a/lib/stdlib/test/dets_SUITE.erl
+++ b/lib/stdlib/test/dets_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1996-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.
@@ -53,7 +53,7 @@
simultaneous_open/1, insert_new/1, repair_continuation/1,
otp_5487/1, otp_6206/1, otp_6359/1, otp_4738/1, otp_7146/1,
otp_8070/1, otp_8856/1, otp_8898/1, otp_8899/1, otp_8903/1,
- otp_8923/1, otp_9282/1, otp_11245/1, otp_11709/1]).
+ otp_8923/1, otp_9282/1, otp_11245/1, otp_11709/1, otp_13229/1]).
-export([dets_dirty_loop/0]).
@@ -110,7 +110,8 @@ all() ->
many_clients, otp_4906, otp_5402, simultaneous_open,
insert_new, repair_continuation, otp_5487, otp_6206,
otp_6359, otp_4738, otp_7146, otp_8070, otp_8856, otp_8898,
- otp_8899, otp_8903, otp_8923, otp_9282, otp_11245, otp_11709
+ otp_8899, otp_8903, otp_8923, otp_9282, otp_11245, otp_11709,
+ otp_13229
].
groups() ->
@@ -3988,6 +3989,18 @@ otp_11709(Config) when is_list(Config) ->
_ = file:delete(File),
ok.
+otp_13229(doc) ->
+ ["OTP-13229. open_file() exits with badarg when given binary file name."];
+otp_13229(_Config) ->
+ F = <<"binfile.tab">>,
+ try dets:open_file(name, [{file, F}]) of
+ R ->
+ exit({open_succeeded, R})
+ catch
+ error:badarg ->
+ ok
+ end.
+
%%
%% Parts common to several test cases
%%
diff --git a/lib/stdlib/test/dict_SUITE.erl b/lib/stdlib/test/dict_SUITE.erl
index 648154ebbe..aff73b176d 100644
--- a/lib/stdlib/test/dict_SUITE.erl
+++ b/lib/stdlib/test/dict_SUITE.erl
@@ -108,7 +108,7 @@ iterate_1(M) ->
M(empty, []).
iterate_2(M) ->
- random:seed(1, 2, 42),
+ rand:seed(exsplus, {1,2,42}),
iter_tree(M, 1000).
iter_tree(_M, 0) ->
@@ -117,7 +117,7 @@ iter_tree(M, N) ->
L = [{I, I} || I <- lists:seq(1, N)],
T = M(from_list, L),
L = lists:reverse(iterate_tree(M, T)),
- R = random:uniform(N),
+ R = rand:uniform(N),
KV = lists:reverse(iterate_tree_from(M, R, T)),
KV = [P || P={K,_} <- L, K >= R],
iter_tree(M, N-1).
@@ -156,7 +156,7 @@ test_all(Tester) ->
spawn_tester(M, Tester) ->
Parent = self(),
spawn_link(fun() ->
- random:seed(1, 2, 42),
+ rand:seed(exsplus, {1,2,42}),
S = Tester(M),
Res = {M(size, S),lists:sort(M(to_list, S))},
Parent ! {result,self(),Res}
@@ -194,12 +194,12 @@ rnd_list_1(0, Acc) ->
Acc;
rnd_list_1(N, Acc) ->
Key = atomic_rnd_term(),
- Value = random:uniform(100),
+ Value = rand:uniform(100),
rnd_list_1(N-1, [{Key,Value}|Acc]).
atomic_rnd_term() ->
- case random:uniform(3) of
- 1 -> list_to_atom(integer_to_list($\s+random:uniform(94))++"rnd");
- 2 -> random:uniform();
- 3 -> random:uniform(50)-37
+ case rand:uniform(3) of
+ 1 -> list_to_atom(integer_to_list($\s+rand:uniform(94))++"rnd");
+ 2 -> rand:uniform();
+ 3 -> rand:uniform(50)-37
end.
diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl
index 4e5df661b3..4c007e76ad 100644
--- a/lib/stdlib/test/epp_SUITE.erl
+++ b/lib/stdlib/test/epp_SUITE.erl
@@ -27,7 +27,7 @@
pmod/1, not_circular/1, skip_header/1, otp_6277/1, otp_7702/1,
otp_8130/1, overload_mac/1, otp_8388/1, otp_8470/1, otp_8503/1,
otp_8562/1, otp_8665/1, otp_8911/1, otp_10302/1, otp_10820/1,
- otp_11728/1, encoding/1]).
+ otp_11728/1, encoding/1, extends/1]).
-export([epp_parse_erl_form/2]).
@@ -70,7 +70,7 @@ all() ->
not_circular, skip_header, otp_6277, otp_7702, otp_8130,
overload_mac, otp_8388, otp_8470, otp_8503, otp_8562,
otp_8665, otp_8911, otp_10302, otp_10820, otp_11728,
- encoding].
+ encoding, extends].
groups() ->
[{upcase_mac, [], [upcase_mac_1, upcase_mac_2]},
@@ -621,6 +621,10 @@ otp_8130(Config) when is_list(Config) ->
" 2 end,\n"
" 7),\n"
" {2,7} =\n"
+ " ?M1(begin 1 = fun _Name () -> 1 end(),\n"
+ " 2 end,\n"
+ " 7),\n"
+ " {2,7} =\n"
" ?M1(begin 1 = fun t0/0(),\n"
" 2 end,\n"
" 7),\n"
@@ -645,6 +649,9 @@ otp_8130(Config) when is_list(Config) ->
" ?M1(begin yes = try 1 of 1 -> yes after foo end,\n"
" 2 end,\n"
" 7),\n"
+ " {[42],7} =\n"
+ " ?M1([42],\n"
+ " 7),\n"
"ok.\n">>,
ok},
@@ -728,11 +735,16 @@ otp_8130(Config) when is_list(Config) ->
{errors,[{{2,2},epp,{include,lib,"$apa/foo.hrl"}}],[]}},
- {otp_8130_c9,
+ {otp_8130_c9a,
<<"-define(S, ?S).\n"
"t() -> ?S.\n">>,
{errors,[{{2,9},epp,{circular,'S', none}}],[]}},
+ {otp_8130_c9b,
+ <<"-define(S(), ?S()).\n"
+ "t() -> ?S().\n">>,
+ {errors,[{{2,9},epp,{circular,'S', 0}}],[]}},
+
{otp_8130_c10,
<<"\n-file.">>,
{errors,[{{2,2},epp,{bad,file}}],[]}},
@@ -799,6 +811,10 @@ otp_8130(Config) when is_list(Config) ->
<<"\n-include(\"no such file.erl\").\n">>,
{errors,[{{2,2},epp,{include,file,"no such file.erl"}}],[]}},
+ {otp_8130_c25,
+ <<"\n-define(A.\n">>,
+ {errors,[{{2,2},epp,{bad,define}}],[]}},
+
{otp_8130_7,
<<"-record(b, {b}).\n"
"-define(A, {{a,#b.b.\n"
@@ -826,14 +842,14 @@ otp_8130(Config) when is_list(Config) ->
"-define(a, 3.14).\n"
"t() -> ?a.\n"),
?line {ok,Epp} = epp:open(File, []),
- ?line ['BASE_MODULE','BASE_MODULE_STRING','BEAM','FILE','LINE',
- 'MACHINE','MODULE','MODULE_STRING'] = macs(Epp),
+ PreDefMacs = macs(Epp),
+ ['BASE_MODULE','BASE_MODULE_STRING','BEAM','FILE','LINE',
+ 'MACHINE','MODULE','MODULE_STRING'] = PreDefMacs,
?line {ok,[{'-',_},{atom,_,file}|_]} = epp:scan_erl_form(Epp),
?line {ok,[{'-',_},{atom,_,module}|_]} = epp:scan_erl_form(Epp),
?line {ok,[{atom,_,t}|_]} = epp:scan_erl_form(Epp),
?line {eof,_} = epp:scan_erl_form(Epp),
- ?line ['BASE_MODULE','BASE_MODULE_STRING','BEAM','FILE','LINE',
- 'MACHINE','MODULE','MODULE_STRING',a] = macs(Epp),
+ [a] = macs(Epp) -- PreDefMacs,
?line epp:close(Epp),
%% escript
@@ -1476,6 +1492,20 @@ encoding(Config) when is_list(Config) ->
epp_parse_file(ErlFile, [{default_encoding,utf8},extra]),
ok.
+extends(Config) ->
+ Cs = [{extends_c1,
+ <<"-extends(some.other.module).\n">>,
+ {errors,[{1,erl_parse,["syntax error before: ","'.'"]}],[]}}],
+ [] = compile(Config, Cs),
+
+ Ts = [{extends_1,
+ <<"-extends(some_other_module).\n"
+ "t() -> {?BASE_MODULE,?BASE_MODULE_STRING}.\n">>,
+ {some_other_module,"some_other_module"}}],
+
+ [] = run(Config, Ts),
+ ok.
+
check(Config, Tests) ->
eval_tests(Config, fun check_test/2, Tests).
@@ -1504,15 +1534,17 @@ eval_tests(Config, Fun, Tests) ->
check_test(Config, Test) ->
Filename = "epp_test.erl",
- ?line PrivDir = ?config(priv_dir, Config),
- ?line File = filename:join(PrivDir, Filename),
- ?line ok = file:write_file(File, Test),
- ?line case epp:parse_file(File, [PrivDir], []) of
- {ok,Forms} ->
- [E || E={error,_} <- Forms];
- {error,Error} ->
- Error
- end.
+ PrivDir = ?config(priv_dir, Config),
+ File = filename:join(PrivDir, Filename),
+ ok = file:write_file(File, Test),
+ case epp:parse_file(File, [PrivDir], []) of
+ {ok,Forms} ->
+ Errors = [E || E={error,_} <- Forms],
+ call_format_error([E || {error,E} <- Errors]),
+ Errors;
+ {error,Error} ->
+ Error
+ end.
compile_test(Config, Test0) ->
Test = [<<"-module(epp_test). -compile(export_all). ">>, Test0],
@@ -1528,8 +1560,11 @@ compile_test(Config, Test0) ->
warnings(File, Ws) ->
case lists:append([W || {F, W} <- Ws, F =:= File]) of
- [] -> [];
- L -> {warnings, L}
+ [] ->
+ [];
+ L ->
+ call_format_error(L),
+ {warnings, L}
end.
compile_file(File, Opts) ->
@@ -1540,12 +1575,20 @@ compile_file(File, Opts) ->
end.
errs([{File,Es}|L], File) ->
+ call_format_error(Es),
Es ++ errs(L, File);
errs([_|L], File) ->
errs(L, File);
errs([], _File) ->
[].
+%% Smoke test and coverage of format_error/1.
+call_format_error([{_,M,E}|T]) ->
+ _ = M:format_error(E),
+ call_format_error(T);
+call_format_error([]) ->
+ ok.
+
epp_parse_file(File, Opts) ->
case epp:parse_file(File, Opts) of
{ok, Forms} ->
diff --git a/lib/stdlib/test/erl_anno_SUITE.erl b/lib/stdlib/test/erl_anno_SUITE.erl
index 66b02151a0..0369455846 100644
--- a/lib/stdlib/test/erl_anno_SUITE.erl
+++ b/lib/stdlib/test/erl_anno_SUITE.erl
@@ -34,7 +34,7 @@
init_per_testcase/2, end_per_testcase/2]).
-export([new/1, is_anno/1, generated/1, end_location/1, file/1,
- line/1, location/1, record/1, text/1, bad/1, neg_line/1]).
+ line/1, location/1, record/1, text/1, bad/1]).
-export([parse_abstract/1, mapfold_anno/1]).
@@ -43,7 +43,7 @@ all() ->
groups() ->
[{anno, [], [new, is_anno, generated, end_location, file,
- line, location, record, text, bad, neg_line]},
+ line, location, record, text, bad]},
{parse, [], [parse_abstract, mapfold_anno]}].
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -229,74 +229,6 @@ bad(_Config) ->
(catch erl_anno:record(bad)), % 1st arg not opaque
ok.
-neg_line(doc) ->
- ["Test negative line numbers (OTP 18)"];
-neg_line(_Config) ->
- neg_line1(false),
- neg_line1(true),
- ok.
-
-neg_line1(TextToo) ->
- Minus8_0 = erl_anno:new(-8),
- Plus8_0 = erl_anno:new(8),
- Minus8C_0 = erl_anno:new({-8, 17}),
- Plus8C_0 = erl_anno:new({8, 17}),
-
- [Minus8, Plus8, Minus8C, Plus8C] =
- [case TextToo of
- true ->
- erl_anno:set_text("foo", A);
- false ->
- A
- end || A <- [Minus8_0, Plus8_0, Minus8C_0, Plus8C_0]],
-
- tst(-3, erl_anno:set_location(3, Minus8)),
- tst(-3, erl_anno:set_location(-3, Plus8)),
- tst(-3, erl_anno:set_location(-3, Minus8)),
- tst({-3,9}, erl_anno:set_location({3, 9}, Minus8)),
- tst({-3,9}, erl_anno:set_location({-3, 9}, Plus8)),
- tst({-3,9}, erl_anno:set_location({-3, 9}, Minus8)),
- tst(-3, erl_anno:set_location(3, Minus8C)),
- tst(-3, erl_anno:set_location(-3, Plus8C)),
- tst(-3, erl_anno:set_location(-3, Minus8C)),
- tst({-3,9}, erl_anno:set_location({3, 9}, Minus8C)),
- tst({-3,9}, erl_anno:set_location({-3, 9}, Plus8C)),
- tst({-3,9}, erl_anno:set_location({-3, 9}, Minus8C)),
-
- tst(-8, erl_anno:set_generated(true, Plus8)),
- tst(-8, erl_anno:set_generated(true, Minus8)),
- tst({-8,17}, erl_anno:set_generated(true, Plus8C)),
- tst({-8,17}, erl_anno:set_generated(true, Minus8C)),
- tst(8, erl_anno:set_generated(false, Plus8)),
- tst(8, erl_anno:set_generated(false, Minus8)),
- tst({8,17}, erl_anno:set_generated(false, Plus8C)),
- tst({8,17}, erl_anno:set_generated(false, Minus8C)),
-
- tst(-3, erl_anno:set_line(3, Minus8)),
- tst(-3, erl_anno:set_line(-3, Plus8)),
- tst(-3, erl_anno:set_line(-3, Minus8)),
- tst({-3,17}, erl_anno:set_line(3, Minus8C)),
- tst({-3,17}, erl_anno:set_line(-3, Plus8C)),
- tst({-3,17}, erl_anno:set_line(-3, Minus8C)),
- ok.
-
-tst(Term, Anno) ->
- ?format("Term: ~p\n", [Term]),
- ?format("Anno: ~p\n", [Anno]),
- case anno_to_term(Anno) of
- Term ->
- ok;
- Else ->
- case lists:keyfind(location, 1, Else) of
- {location, Term} ->
- ok;
- _Else2 ->
- ?format("Else2 ~p\n", [_Else2]),
- io:format("expected ~p\n got ~p\n", [Term, Else]),
- exit({Term, Else})
- end
- end.
-
parse_abstract(doc) ->
["Test erl_parse:new_anno/1, erl_parse:anno_to_term/1"
", and erl_parse:anno_from_term/1"];
diff --git a/lib/stdlib/test/erl_eval_SUITE.erl b/lib/stdlib/test/erl_eval_SUITE.erl
index b9c4ad0a46..c21c4e61ee 100644
--- a/lib/stdlib/test/erl_eval_SUITE.erl
+++ b/lib/stdlib/test/erl_eval_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1998-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.
@@ -39,6 +39,7 @@
otp_7550/1,
otp_8133/1,
otp_10622/1,
+ otp_13228/1,
funs/1,
try_catch/1,
eval_expr_5/1,
@@ -83,7 +84,8 @@ all() ->
pattern_expr, match_bin, guard_3, guard_4, guard_5, lc,
simple_cases, unary_plus, apply_atom, otp_5269,
otp_6539, otp_6543, otp_6787, otp_6977, otp_7550,
- otp_8133, otp_10622, funs, try_catch, eval_expr_5, zero_width,
+ otp_8133, otp_10622, otp_13228,
+ funs, try_catch, eval_expr_5, zero_width,
eep37, eep43].
groups() ->
@@ -1042,6 +1044,13 @@ otp_10622(Config) when is_list(Config) ->
ok.
+otp_13228(doc) ->
+ ["OTP-13228. ERL-32: non-local function handler bug."];
+otp_13228(_Config) ->
+ LFH = {value, fun(foo, [io_fwrite]) -> worked end},
+ EFH = {value, fun({io, fwrite}, [atom]) -> io_fwrite end},
+ {value, worked, []} = parse_and_run("foo(io:fwrite(atom)).", LFH, EFH).
+
funs(doc) ->
["Simple cases, just to cover some code."];
funs(suite) ->
@@ -1483,6 +1492,16 @@ eep43(Config) when is_list(Config) ->
" #{ K1 := 1, K2 := 2, K3 := 3, {2,2} := 4} = Map "
"end.",
#{ 1 => 1, <<42:301>> => 2, {3,<<42:301>>} => 3, {2,2} => 4}),
+ check(fun () ->
+ X = key,
+ (fun(#{X := value}) -> true end)(#{X => value})
+ end,
+ "begin "
+ " X = key, "
+ " (fun(#{X := value}) -> true end)(#{X => value}) "
+ "end.",
+ true),
+
error_check("[camembert]#{}.", {badmap,[camembert]}),
error_check("[camembert]#{nonexisting:=v}.", {badmap,[camembert]}),
error_check("#{} = 1.", {badmatch,1}),
diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl
index 0424e2b967..c5e2e5609d 100644
--- a/lib/stdlib/test/erl_lint_SUITE.erl
+++ b/lib/stdlib/test/erl_lint_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1999-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.
@@ -65,7 +65,7 @@
too_many_arguments/1,
basic_errors/1,bin_syntax_errors/1,
predef/1,
- maps/1,maps_type/1,otp_11851/1,otp_12195/1
+ maps/1,maps_type/1,otp_11851/1,otp_11879/1,otp_13230/1
]).
% Default timetrap timeout (set in init_per_testcase).
@@ -94,7 +94,7 @@ all() ->
bif_clash, behaviour_basic, behaviour_multiple, otp_11861,
otp_7550, otp_8051, format_warn, {group, on_load},
too_many_arguments, basic_errors, bin_syntax_errors, predef,
- maps, maps_type, otp_11851, otp_12195].
+ maps, maps_type, otp_11851, otp_11879, otp_13230].
groups() ->
[{unused_vars_warn, [],
@@ -1296,12 +1296,16 @@ unsized_binary_in_bin_gen_pattern(Config) when is_list(Config) ->
Ts = [{unsized_binary_in_bin_gen_pattern,
<<"t({bc,binary,Bin}) ->
<< <<X,Tail/binary>> || <<X,Tail/binary>> <= Bin >>;
+ t({bc,bytes,Bin}) ->
+ << <<X,Tail/binary>> || <<X,Tail/bytes>> <= Bin >>;
t({bc,bits,Bin}) ->
<< <<X,Tail/bits>> || <<X,Tail/bits>> <= Bin >>;
t({bc,bitstring,Bin}) ->
<< <<X,Tail/bits>> || <<X,Tail/bitstring>> <= Bin >>;
t({lc,binary,Bin}) ->
[ {X,Tail} || <<X,Tail/binary>> <= Bin ];
+ t({lc,bytes,Bin}) ->
+ [ {X,Tail} || <<X,Tail/bytes>> <= Bin ];
t({lc,bits,Bin}) ->
[ {X,Tail} || <<X,Tail/bits>> <= Bin ];
t({lc,bitstring,Bin}) ->
@@ -1313,7 +1317,9 @@ unsized_binary_in_bin_gen_pattern(Config) when is_list(Config) ->
{6,erl_lint,unsized_binary_in_bin_gen_pattern},
{8,erl_lint,unsized_binary_in_bin_gen_pattern},
{10,erl_lint,unsized_binary_in_bin_gen_pattern},
- {12,erl_lint,unsized_binary_in_bin_gen_pattern}],
+ {12,erl_lint,unsized_binary_in_bin_gen_pattern},
+ {14,erl_lint,unsized_binary_in_bin_gen_pattern},
+ {16,erl_lint,unsized_binary_in_bin_gen_pattern}],
[]}}],
[] = run(Config, Ts),
ok.
@@ -3604,7 +3610,10 @@ bin_syntax_errors(Config) ->
t(<<X/unit:8>>) -> X;
t(<<X:7/float>>) -> X;
t(<< <<_:8>> >>) -> ok;
- t(<<(x ! y):8/integer>>) -> ok.
+ t(<<(x ! y):8/integer>>) -> ok;
+ t(X) ->
+ {<<X/binary-integer>>,<<X/signed-unsigned-integer>>,
+ <<X/little-big>>,<<X/unit:4-unit:8>>}.
">>,
[],
{error,[{1,erl_lint,illegal_bitsize},
@@ -3613,7 +3622,12 @@ bin_syntax_errors(Config) ->
{4,erl_lint,{undefined_bittype,bad_type}},
{5,erl_lint,bittype_unit},
{7,erl_lint,illegal_pattern},
- {8,erl_lint,illegal_pattern}],
+ {8,erl_lint,illegal_pattern},
+ {10,erl_lint,{bittype_mismatch,integer,binary,"type"}},
+ {10,erl_lint,{bittype_mismatch,unsigned,signed,"sign"}},
+ {11,erl_lint,{bittype_mismatch,8,4,"unit"}},
+ {11,erl_lint,{bittype_mismatch,big,little,"endianness"}}
+ ],
[{6,erl_lint,{bad_bitsize,"float"}}]}}
],
[] = run(Config, Ts),
@@ -3835,38 +3849,36 @@ otp_11851(Config) when is_list(Config) ->
[] = run(Config, Ts),
ok.
-otp_12195(doc) ->
- "OTP-12195: Check obsolete types (tailor made for OTP 18).";
-otp_12195(Config) when is_list(Config) ->
- Ts = [{otp_12195_1,
- <<"-export_type([r1/0]).
- -type r1() :: erl_scan:line()
- | erl_scan:column()
- | erl_scan:location()
- | erl_anno:line().">>,
- [],
- {warnings,[{2,erl_lint,
- {deprecated_type,{erl_scan,line,0},
- "deprecated (will be removed in OTP 19); "
- "use erl_anno:line() instead"}},
- {3,erl_lint,
- {deprecated_type,{erl_scan,column,0},
- "deprecated (will be removed in OTP 19); use "
- "erl_anno:column() instead"}},
- {4,erl_lint,
- {deprecated_type,{erl_scan,location,0},
- "deprecated (will be removed in OTP 19); "
- "use erl_anno:location() instead"}}]}},
- {otp_12195_2,
- <<"-export_type([r1/0]).
- -compile(nowarn_deprecated_type).
- -type r1() :: erl_scan:line()
- | erl_scan:column()
- | erl_scan:location()
- | erl_anno:line().">>,
- [],
- []}],
- [] = run(Config, Ts),
+otp_11879(doc) ->
+ "OTP-11879: The -spec f/a :: (As) -> B; syntax removed, "
+ "and is_subtype/2 deprecated";
+otp_11879(_Config) ->
+ Fs = [{attribute,0,file,{"file.erl",0}},
+ {attribute,0,module,m},
+ {attribute,1,spec,
+ {{f,1},
+ [{type,2,'fun',[{type,3,product,[{var,4,'V1'},
+ {var,5,'V1'}]},
+ {type,6,integer,[]}]}]}},
+ {attribute,20,callback,
+ {{cb,21},
+ [{type,22,'fun',[{type,23,product,[{var,24,'V1'},
+ {var,25,'V1'}]},
+ {type,6,integer,[]}]}]}}],
+ {error,[{"file.erl",
+ [{1,erl_lint,{spec_fun_undefined,{f,1}}},
+ {2,erl_lint,spec_wrong_arity},
+ {22,erl_lint,callback_wrong_arity}]}],
+ []} = compile:forms(Fs, [return,report]),
+ ok.
+
+otp_13230(doc) ->
+ "OTP-13230: -deprecated without -module";
+otp_13230(Config) when is_list(Config) ->
+ Abstr = <<"-deprecated([{frutt,0,next_version}]).">>,
+ {errors,[{1,erl_lint,undefined_module},
+ {1,erl_lint,{bad_deprecated,{frutt,0}}}],
+ []} = run_test2(Config, Abstr, []),
ok.
run(Config, Tests) ->
@@ -3920,22 +3932,35 @@ run_test2(Conf, Test, Warnings0) ->
%% is no reason to produce an output file since we are only
%% interested in the errors and warnings.
- %% Print warnings, call erl_lint:format_error/1.
+ %% Print warnings, call erl_lint:format_error/1. (But note that
+ %% the compiler will ignore failing calls to erl_lint:format_error/1.)
compile:file(File, [binary,report|Opts]),
case compile:file(File, [binary|Opts]) of
- {ok, _M, Code, Ws} when is_binary(Code) -> warnings(File, Ws);
- {error, [{File,Es}], []} -> {errors, Es, []};
- {error, [{File,Es}], [{File,Ws}]} -> {error, Es, Ws};
- {error, [{File,Es1},{File,Es2}], []} -> {errors2, Es1, Es2}
+ {ok, _M, Code, Ws} when is_binary(Code) ->
+ warnings(File, Ws);
+ {error, [{File,Es}], []} ->
+ {errors, call_format_error(Es), []};
+ {error, [{File,Es}], [{File,Ws}]} ->
+ {error, call_format_error(Es), call_format_error(Ws)};
+ {error, [{File,Es1},{File,Es2}], []} ->
+ {errors2, Es1, Es2}
end.
warnings(File, Ws) ->
case lists:append([W || {F, W} <- Ws, F =:= File]) of
- [] -> [];
- L -> {warnings, L}
+ [] ->
+ [];
+ L ->
+ {warnings, call_format_error(L)}
end.
+call_format_error(L) ->
+ %% Smoke test of format_error/1 to make sure that no crashes
+ %% slip through.
+ _ = [Mod:format_error(Term) || {_,Mod,Term} <- L],
+ L.
+
fail() ->
io:format("failed~n"),
?t:fail().
diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl
index 389fd059f6..8a128b3815 100644
--- a/lib/stdlib/test/erl_pp_SUITE.erl
+++ b/lib/stdlib/test/erl_pp_SUITE.erl
@@ -876,6 +876,9 @@ type_examples() ->
{ex30,<<"-type t99() ::"
"{t2(),'\\'t::4'(),t5(),t6(),t7(),t8(),t10(),t14(),"
"t15(),t20(),t21(), t22(),t25()}. ">>},
+ %% Writing constraints as is_subtype(V, T) is not supported since
+ %% Erlang/OTP 19.0, but as long as the parser recognizes the
+ %% is_subtype(V, T) syntax, we need a few examples of the syntax.
{ex31,<<"-spec t1(FooBar :: t99()) -> t99();"
"(t2()) -> t2();"
"('\\'t::4'()) -> '\\'t::4'() when is_subtype('\\'t::4'(), t24);"
@@ -928,7 +931,9 @@ otp_8522(Config) when is_list(Config) ->
?line {ok, _} = compile:file(FileName, [{outdir,?privdir},debug_info]),
BF = filename("otp_8522", Config),
?line {ok, A} = beam_lib:chunks(BF, [abstract_code]),
- ?line 5 = count_atom(A, undefined),
+ %% OTP-12719: Since 'undefined' is no longer added by the Erlang
+ %% Parser, the number of 'undefined' is 4. It used to be 5.
+ ?line 4 = count_atom(A, undefined),
ok.
count_atom(A, A) ->
@@ -960,6 +965,9 @@ maps_syntax(Config) when is_list(Config) ->
"-compile(export_all).\n"
"-type t1() :: map().\n"
"-type t2() :: #{ atom() => integer(), atom() => float() }.\n"
+ "-type u() :: #{a => (I :: integer()) | (A :: atom()),\n"
+ " (X :: atom()) | (Y :: atom()) =>\n"
+ " (I :: integer()) | (A :: atom())}.\n"
"-spec f1(t1()) -> 'true'.\n"
"f1(M) when is_map(M) -> true.\n"
"-spec f2(t2()) -> integer().\n"
@@ -995,18 +1003,10 @@ otp_8567(Config) when is_list(Config) ->
"t() ->\n"
" 3.\n"
"\n"
- "-spec(t1/1 :: (ot()) -> ot1()).\n"
- "t1(A) ->\n"
- " A.\n"
- "\n"
"-spec(t2 (ot()) -> ot1()).\n"
"t2(A) ->\n"
" A.\n"
"\n"
- "-spec(otp_8567:t3/1 :: (ot()) -> ot1()).\n"
- "t3(A) ->\n"
- " A.\n"
- "\n"
"-spec(otp_8567:t4 (ot()) -> ot1()).\n"
"t4(A) ->\n"
" A.\n">>,
@@ -1062,7 +1062,7 @@ otp_9147(Config) when is_list(Config) ->
?line {ok, Bin} = file:read_file(PFileName),
%% The parentheses around "F1 :: a | b" are new (bugfix).
?line true =
- lists:member("-record(undef,{f1 :: undefined | (F1 :: a | b)}).",
+ lists:member("-record(undef,{f1 :: F1 :: a | b}).",
string:tokens(binary_to_list(Bin), "\n")),
ok.
diff --git a/lib/stdlib/test/erl_scan_SUITE.erl b/lib/stdlib/test/erl_scan_SUITE.erl
index 12ea3d128c..db669aae99 100644
--- a/lib/stdlib/test/erl_scan_SUITE.erl
+++ b/lib/stdlib/test/erl_scan_SUITE.erl
@@ -191,8 +191,7 @@ otp_7810(Config) when is_list(Config) ->
?line ok = more_chars(),
?line ok = more_options(),
- ?line ok = attributes_info(),
- ?line ok = set_attribute(),
+ ?line ok = anno_info(),
ok.
@@ -269,7 +268,7 @@ punctuations() ->
comments() ->
?line test("a %%\n b"),
- {ok,[],1} = erl_scan_string("%"),
+ ?line {ok,[],1} = erl_scan_string("%"),
?line test("a %%\n b"),
{ok,[{atom,{1,1},a},{atom,{2,2},b}],{2,3}} =
erl_scan_string("a %%\n b", {1,1}),
@@ -338,7 +337,7 @@ base_integers() ->
erl_scan:string(Str)
end || {BS,S} <- [{"3","3"},{"15","f"}, {"12","c"}] ],
- {ok,[{integer,1,239},{'@',1}],1} = erl_scan_string("16#ef@"),
+ ?line {ok,[{integer,1,239},{'@',1}],1} = erl_scan_string("16#ef@"),
{ok,[{integer,{1,1},239},{'@',{1,6}}],{1,7}} =
erl_scan_string("16#ef@", {1,1}, []),
{ok,[{integer,{1,1},14},{atom,{1,5},g@}],{1,7}} =
@@ -387,20 +386,15 @@ dots() ->
R2 = erl_scan_string(S, {1,1}, [])
end || {S, R, R2} <- Dot],
- ?line {ok,[{dot,_}=T1],{1,2}} = erl_scan:string(".", {1,1}, text),
- ?line [{column,1},{length,1},{line,1},{text,"."}] =
- erl_scan:token_info(T1, [column, length, line, text]),
- ?line {ok,[{dot,_}=T2],{1,3}} = erl_scan:string(".%", {1,1}, text),
- ?line [{column,1},{length,1},{line,1},{text,"."}] =
- erl_scan:token_info(T2, [column, length, line, text]),
- ?line {ok,[{dot,_}=T3],{1,6}} =
+ {ok,[{dot,_}=T1],{1,2}} = erl_scan:string(".", {1,1}, text),
+ [1, 1, "."] = token_info(T1),
+ {ok,[{dot,_}=T2],{1,3}} = erl_scan:string(".%", {1,1}, text),
+ [1, 1, "."] = token_info(T2),
+ {ok,[{dot,_}=T3],{1,6}} =
erl_scan:string(".% öh", {1,1}, text),
- ?line [{column,1},{length,1},{line,1},{text,"."}] =
- erl_scan:token_info(T3, [column, length, line, text]),
- ?line {error,{{1,2},erl_scan,char},{1,3}} =
- erl_scan:string(".$", {1,1}),
- ?line {error,{{1,2},erl_scan,char},{1,4}} =
- erl_scan:string(".$\\", {1,1}),
+ [1, 1, "."] = token_info(T3),
+ {error,{{1,2},erl_scan,char},{1,3}} = erl_scan:string(".$", {1,1}),
+ {error,{{1,2},erl_scan,char},{1,4}} = erl_scan:string(".$\\", {1,1}),
test_string(". ", [{dot,{1,1}}]),
test_string(". ", [{dot,{1,1}}]),
@@ -413,18 +407,18 @@ dots() ->
test_string(".a", [{'.',{1,1}},{atom,{1,2},a}]),
test_string("%. \n. ", [{dot,{2,1}}]),
- ?line {more,C} = erl_scan:tokens([], "%. ",{1,1}, return),
+ {more,C} = erl_scan:tokens([], "%. ",{1,1}, return),
{done,{ok,[{comment,{1,1},"%. "},
{white_space,{1,4},"\n"},
{dot,{2,1}}],
{2,3}}, ""} =
erl_scan_tokens(C, "\n. ", {1,1}, return), % any loc, any options
- ?line [test_string(S, R) ||
- {S, R} <- [{".$\n", [{'.',{1,1}},{char,{1,2},$\n}]},
- {"$\\\n", [{char,{1,1},$\n}]},
- {"'\\\n'", [{atom,{1,1},'\n'}]},
- {"$\n", [{char,{1,1},$\n}]}] ],
+ [test_string(S, R) ||
+ {S, R} <- [{".$\n", [{'.',{1,1}},{char,{1,2},$\n}]},
+ {"$\\\n", [{char,{1,1},$\n}]},
+ {"'\\\n'", [{atom,{1,1},'\n'}]},
+ {"$\n", [{char,{1,1},$\n}]}] ],
ok.
chars() ->
@@ -540,8 +534,8 @@ eof() ->
%% A dot followed by eof is special:
?line {more, C} = erl_scan:tokens([], "a.", 1),
- {done,{ok,[{atom,1,a},{dot,1}],1},eof} = erl_scan_tokens(C,eof,1),
- {ok,[{atom,1,foo},{dot,1}],1} = erl_scan_string("foo."),
+ ?line {done,{ok,[{atom,1,a},{dot,1}],1},eof} = erl_scan_tokens(C,eof,1),
+ ?line {ok,[{atom,1,foo},{dot,1}],1} = erl_scan_string("foo."),
%% With column.
{more, CCol} = erl_scan:tokens([], "a.", {1,1}),
@@ -655,145 +649,72 @@ options() ->
ok.
more_options() ->
- ?line {ok,[{atom,A1,foo}],{19,20}} =
+ {ok,[{atom,_,foo}=T1],{19,20}} =
erl_scan:string("foo", {19,17},[]),
- ?line [{column,17},{line,19}] = erl_scan:attributes_info(A1),
- ?line {done,{ok,[{atom,A2,foo},{dot,_}],{19,22}},[]} =
+ {19,17} = erl_scan:location(T1),
+ {done,{ok,[{atom,_,foo}=T2,{dot,_}],{19,22}},[]} =
erl_scan:tokens([], "foo. ", {19,17}, [bad_opt]), % type error
- ?line [{column,17},{line,19}] = erl_scan:attributes_info(A2),
- ?line {ok,[{atom,A3,foo}],{19,20}} =
+ {19,17} = erl_scan:location(T2),
+ {ok,[{atom,_,foo}=T3],{19,20}} =
erl_scan:string("foo", {19,17},[text]),
- ?line [{column,17},{length,3},{line,19},{text,"foo"}] =
- erl_scan:attributes_info(A3),
+ {19,17} = erl_scan:location(T3),
+ "foo" = erl_scan:text(T3),
- ?line {ok,[{atom,A4,foo}],1} = erl_scan:string("foo", 1, [text]),
- ?line [{length,3},{line,1},{text,"foo"}] = erl_scan:attributes_info(A4),
+ {ok,[{atom,_,foo}=T4],1} = erl_scan:string("foo", 1, [text]),
+ 1 = erl_scan:line(T4),
+ 1 = erl_scan:location(T4),
+ "foo" = erl_scan:text(T4),
ok.
token_info() ->
- ?line {ok,[T1],_} = erl_scan:string("foo", {1,18}, [text]),
+ {ok,[T1],_} = erl_scan:string("foo", {1,18}, [text]),
{'EXIT',{badarg,_}} =
- (catch {foo, erl_scan:token_info(T1, foo)}), % type error
- ?line {line,1} = erl_scan:token_info(T1, line),
- ?line {column,18} = erl_scan:token_info(T1, column),
- ?line {length,3} = erl_scan:token_info(T1, length),
- ?line {text,"foo"} = erl_scan:token_info(T1, text),
- ?line [{category,atom},{column,18},{length,3},{line,1},
- {symbol,foo},{text,"foo"}] =
- erl_scan:token_info(T1),
- ?line [{length,3},{column,18}] =
- erl_scan:token_info(T1, [length, column]),
- ?line [{location,{1,18}}] =
- erl_scan:token_info(T1, [location]),
- ?line {category,atom} = erl_scan:token_info(T1, category),
- ?line [{symbol,foo}] = erl_scan:token_info(T1, [symbol]),
-
- ?line {ok,[T2],_} = erl_scan:string("foo", 1, []),
- ?line {line,1} = erl_scan:token_info(T2, line),
- ?line undefined = erl_scan:token_info(T2, column),
- ?line undefined = erl_scan:token_info(T2, length),
- ?line undefined = erl_scan:token_info(T2, text),
- ?line {location,1} = erl_scan:token_info(T2, location),
- ?line [{category,atom},{line,1},{symbol,foo}] = erl_scan:token_info(T2),
- ?line [{line,1}] = erl_scan:token_info(T2, [length, line]),
-
- ?line {ok,[T3],_} = erl_scan:string("=", 1, []),
- ?line [{line,1}] = erl_scan:token_info(T3, [column, line]),
- ?line {category,'='} = erl_scan:token_info(T3, category),
- ?line [{symbol,'='}] = erl_scan:token_info(T3, [symbol]),
+ (catch {foo, erl_scan:category(foo)}), % type error
+ {'EXIT',{badarg,_}} =
+ (catch {foo, erl_scan:symbol(foo)}), % type error
+ atom = erl_scan:category(T1),
+ foo = erl_scan:symbol(T1),
+
+ {ok,[T2],_} = erl_scan:string("foo", 1, []),
+ 1 = erl_scan:line(T2),
+ undefined = erl_scan:column(T2),
+ undefined = erl_scan:text(T2),
+ 1 = erl_scan:location(T2),
+
+ {ok,[T3],_} = erl_scan:string("=", 1, []),
+ '=' = erl_scan:category(T3),
+ '=' = erl_scan:symbol(T3),
ok.
-attributes_info() ->
- ?line {'EXIT',_} =
- (catch {foo,erl_scan:attributes_info(foo)}), % type error
- [{line,18}] = erl_scan:attributes_info(erl_anno:new(18)),
- {location,19} =
- erl_scan:attributes_info(erl_anno:new(19), location),
- ?line {ok,[{atom,A0,foo}],_} = erl_scan:string("foo", 19, [text]),
- ?line {location,19} = erl_scan:attributes_info(A0, location),
-
- ?line {ok,[{atom,A3,foo}],_} = erl_scan:string("foo", {1,3}, [text]),
- ?line {line,1} = erl_scan:attributes_info(A3, line),
- ?line {column,3} = erl_scan:attributes_info(A3, column),
- ?line {location,{1,3}} = erl_scan:attributes_info(A3, location),
- ?line {text,"foo"} = erl_scan:attributes_info(A3, text),
-
- ?line {ok,[{atom,A4,foo}],_} = erl_scan:string("foo", 2, [text]),
- ?line {line,2} = erl_scan:attributes_info(A4, line),
- ?line undefined = erl_scan:attributes_info(A4, column),
- ?line {location,2} = erl_scan:attributes_info(A4, location),
- ?line {text,"foo"} = erl_scan:attributes_info(A4, text),
-
- ?line {ok,[{atom,A5,foo}],_} = erl_scan:string("foo", {1,3}, []),
- ?line {line,1} = erl_scan:attributes_info(A5, line),
- ?line {column,3} = erl_scan:attributes_info(A5, column),
- ?line {location,{1,3}} = erl_scan:attributes_info(A5, location),
- ?line undefined = erl_scan:attributes_info(A5, text),
-
- ?line undefined = erl_scan:attributes_info([], line), % type error
+anno_info() ->
+ {'EXIT',_} =
+ (catch {foo,erl_scan:line(foo)}), % type error
+ {ok,[{atom,_,foo}=T0],_} = erl_scan:string("foo", 19, [text]),
+ 19 = erl_scan:location(T0),
+ 19 = erl_scan:end_location(T0),
+
+ {ok,[{atom,_,foo}=T3],_} = erl_scan:string("foo", {1,3}, [text]),
+ 1 = erl_scan:line(T3),
+ 3 = erl_scan:column(T3),
+ {1,3} = erl_scan:location(T3),
+ {1,6} = erl_scan:end_location(T3),
+ "foo" = erl_scan:text(T3),
+
+ {ok,[{atom,_,foo}=T4],_} = erl_scan:string("foo", 2, [text]),
+ 2 = erl_scan:line(T4),
+ undefined = erl_scan:column(T4),
+ 2 = erl_scan:location(T4),
+ "foo" = erl_scan:text(T4),
+
+ {ok,[{atom,_,foo}=T5],_} = erl_scan:string("foo", {1,3}, []),
+ 1 = erl_scan:line(T5),
+ 3 = erl_scan:column(T5),
+ {1,3} = erl_scan:location(T5),
+ undefined = erl_scan:text(T5),
ok.
-set_attribute() ->
- F = fun(Line) -> -Line end,
- Anno2 = erl_anno:new(2),
- A0 = erl_scan:set_attribute(line, Anno2, F),
- {line, -2} = erl_scan:attributes_info(A0, line),
- ?line {ok,[{atom,A1,foo}],_} = erl_scan:string("foo", {9,17}),
- ?line A2 = erl_scan:set_attribute(line, A1, F),
- ?line {line,-9} = erl_scan:attributes_info(A2, line),
- ?line {location,{-9,17}} = erl_scan:attributes_info(A2, location),
- ?line [{line,-9},{column,17}] =
- erl_scan:attributes_info(A2, [line,column,text]),
-
- F2 = fun(Line) -> {17,Line} end,
- ?line Attr1 = erl_scan:set_attribute(line, 2, F2),
- ?line {line,{17,2}} = erl_scan:attributes_info(Attr1, line),
- ?line undefined = erl_scan:attributes_info(Attr1, column),
- ?line {location,{17,2}} = % a bit mixed up
- erl_scan:attributes_info(Attr1, location),
-
- ?line A3 = erl_scan:set_attribute(line, A1, F2),
- ?line {line,{17,9}} = erl_scan:attributes_info(A3, line),
- ?line {location,{{17,9},17}} = erl_scan:attributes_info(A3, location),
- ?line [{line,{17,9}},{column,17}] =
- erl_scan:attributes_info(A3, [line,column,text]),
-
- ?line {ok,[{atom,A4,foo}],_} = erl_scan:string("foo", {9,17}, [text]),
- ?line A5 = erl_scan:set_attribute(line, A4, F),
- ?line {line,-9} = erl_scan:attributes_info(A5, line),
- ?line {location,{-9,17}} = erl_scan:attributes_info(A5, location),
- ?line [{line,-9},{column,17},{text,"foo"}] =
- erl_scan:attributes_info(A5, [line,column,text]),
-
- ?line {ok,[{atom,A6,foo}],_} = erl_scan:string("foo", 11, [text]),
- ?line A7 = erl_scan:set_attribute(line, A6, F2),
- %% Incompatible with pre 18:
- %% {line,{17,11}} = erl_scan:attributes_info(A7, line),
- {line,17} = erl_scan:attributes_info(A7, line),
- ?line {location,{17,11}} = % mixed up
- erl_scan:attributes_info(A7, location),
- %% Incompatible with pre 18:
- %% [{line,{17,11}},{text,"foo"}] =
- %% erl_scan:attributes_info(A7, [line,column,text]),
- [{line,17},{column,11},{text,"foo"}] =
- erl_scan:attributes_info(A7, [line,column,text]),
-
- ?line {'EXIT',_} =
- (catch {foo, erl_scan:set_attribute(line, [], F2)}), % type error
- ?line {'EXIT',{badarg,_}} =
- (catch {foo, erl_scan:set_attribute(column, [], F2)}), % type error
-
- Attr10 = erl_anno:new(8),
- Attr20 = erl_scan:set_attribute(line, Attr10,
- fun(L) -> {nos,'X',L} end),
- %% OTP-9412
- Attr30 = erl_scan:set_attribute(line, Attr20,
- fun({nos,_V,VL}) -> VL end),
- 8 = erl_anno:to_term(Attr30),
- ok.
-
column_errors() ->
?line {error,{{1,1},erl_scan,{string,$',""}},{1,3}} = % $'
erl_scan:string("'\\",{1,1}),
@@ -892,14 +813,13 @@ unicode() ->
erl_scan_string(Qs, 1),
{ok,[Q2],{1,9}} =
erl_scan:string("$\\x{aaa}", {1,1}, [text]),
- [{category,char},{column,1},{length,8},
- {line,1},{symbol,16#aaa},{text,Qs}] =
- erl_scan:token_info(Q2),
+ [{category,char},{column,1},{line,1},{symbol,16#aaa},{text,Qs}] =
+ token_info_long(Q2),
U1 = "\"\\x{aaa}\"",
- {ok,[{string,A1,[2730]}],{1,10}} = erl_scan:string(U1, {1,1}, [text]),
- [{line,1},{column,1},{text,"\"\\x{aaa}\""}] =
- erl_scan:attributes_info(A1, [line, column, text]),
+ {ok,[{string,_,[2730]}=T1],{1,10}} = erl_scan:string(U1, {1,1}, [text]),
+ {1,1} = erl_scan:location(T1),
+ "\"\\x{aaa}\"" = erl_scan:text(T1),
{ok,[{string,1,[2730]}],1} = erl_scan_string(U1, 1),
U2 = "\"\\x41\\x{fff}\\x42\"",
@@ -1012,16 +932,13 @@ otp_10302(Config) when is_list(Config) ->
Qs = "$\\x{aaa}",
{ok,[{char,1,2730}],1} = erl_scan_string(Qs, 1),
{ok,[Q2],{1,9}} = erl_scan:string(Qs,{1,1},[text]),
- [{category,char},{column,1},{length,8},
- {line,1},{symbol,16#aaa},{text,Qs}] =
- erl_scan:token_info(Q2),
-
- Tags = [category, column, length, line, symbol, text],
+ [{category,char},{column,1},{line,1},{symbol,16#aaa},{text,Qs}] =
+ token_info_long(Q2),
U1 = "\"\\x{aaa}\"",
{ok,[T1],{1,10}} = erl_scan:string(U1, {1,1}, [text]),
- [{category,string},{column,1},{length,9},{line,1},
- {symbol,[16#aaa]},{text,U1}] = erl_scan:token_info(T1, Tags),
+ [{category,string},{column,1},{line,1},{symbol,[16#aaa]},{text,U1}] =
+ token_info_long(T1),
U2 = "\"\\x41\\x{fff}\\x42\"",
{ok,[{string,1,[65,4095,66]}],1} = erl_scan_string(U2, 1),
@@ -1353,9 +1270,7 @@ test_wsc([], []) ->
ok;
test_wsc([Token|Tokens], [Token2|Tokens2]) ->
[Text, Text2] = [Text ||
- {text, Text} <-
- [erl_scan:token_info(T, text) ||
- T <- [Token, Token2]]],
+ Text <- [erl_scan:text(T) || T <- [Token, Token2]]],
Sz = erts_debug:size(Text),
Sz2 = erts_debug:size({Text, Text2}),
IsCompacted = Sz2 < 2*Sz+erts_debug:size({a,a}),
@@ -1394,7 +1309,7 @@ all_same(L, Char) ->
newlines_first([]) ->
ok;
newlines_first([Token|Tokens]) ->
- {text,Text} = erl_scan:token_info(Token, text),
+ Text = erl_scan:text(Token),
Nnls = length([C || C <- Text, C =:= $\n]),
OK = case Text of
[$\n|_] ->
@@ -1414,7 +1329,7 @@ select_tokens(Tokens, Tags) ->
lists:filter(fun(T) -> lists:member(element(1, T), Tags) end, Tokens).
simplify([Token|Tokens]) ->
- {line,Line} = erl_scan:token_info(Token, line),
+ Line = erl_scan:line(Token),
[setelement(2, Token, erl_anno:new(Line)) | simplify(Tokens)];
simplify([]) ->
[].
@@ -1423,17 +1338,31 @@ get_text(Tokens) ->
lists:flatten(
[T ||
Token <- Tokens,
- ({text,T} = erl_scan:token_info(Token, text)) =/= []]).
+ (T = erl_scan:text(Token)) =/= []]).
test_decorated_tokens(String, Tokens) ->
ToksAttrs = token_attrs(Tokens),
test_strings(ToksAttrs, String, 1, 1).
token_attrs(Tokens) ->
- [{L,C,Len,T} ||
+ [{L,C,length(T),T} ||
Token <- Tokens,
- ([{line,L},{column,C},{length,Len},{text,T}] =
- erl_scan:token_info(Token, [line,column,length,text])) =/= []].
+ ([C,L,T] = token_info(Token)) =/= []].
+
+token_info(T) ->
+ Column = erl_scan:column(T),
+ Line = erl_scan:line(T),
+ Text = erl_scan:text(T),
+ [Column, Line, Text].
+
+token_info_long(T) ->
+ Column = erl_scan:column(T),
+ Line = erl_scan:line(T),
+ Text = erl_scan:text(T),
+ Category = erl_scan:category(T),
+ Symbol = erl_scan:symbol(T),
+ [{category,Category},{column,Column},{line,Line},
+ {symbol,Symbol},{text,Text}].
test_strings([], _S, Line, Column) ->
{Line,Column};
@@ -1514,8 +1443,7 @@ consistent_attributes([Ts | TsL]) ->
L = [T || T <- Ts, is_integer(element(2, T))],
case L of
[] ->
- TagsL = [[Tag || {Tag,_} <-
- erl_scan:attributes_info(element(2, T))] ||
+ TagsL = [[Tag || {Tag,_} <- defined(token_info_long(T))] ||
T <- Ts],
case lists:usort(TagsL) of
[_] ->
@@ -1531,6 +1459,9 @@ consistent_attributes([Ts | TsL]) ->
Ts
end.
+defined(L) ->
+ [{T,V} || {T,V} <- L, V =/= undefined].
+
family_list(L) ->
sofs:to_external(family(L)).
diff --git a/lib/stdlib/test/error_logger_h_SUITE.erl b/lib/stdlib/test/error_logger_h_SUITE.erl
new file mode 100644
index 0000000000..c82b1b62ef
--- /dev/null
+++ b/lib/stdlib/test/error_logger_h_SUITE.erl
@@ -0,0 +1,406 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2015. 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(error_logger_h_SUITE).
+-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+ init_per_group/2,end_per_group/2]).
+-export([logfile/1,logfile_truncated/1,tty/1,tty_truncated/1]).
+
+%% Event handler exports.
+-export([init/1,handle_event/2,terminate/2]).
+
+-include_lib("test_server/include/test_server.hrl").
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [logfile,logfile_truncated,tty,tty_truncated].
+
+groups() ->
+ [].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+logfile(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ LogDir = filename:join(PrivDir, ?MODULE),
+ Log = filename:join(LogDir, "logfile.log"),
+ ok = filelib:ensure_dir(Log),
+
+ Ev = event_templates(),
+
+ do_one_logfile(Log, Ev, unlimited),
+
+ Pa = "-pa " ++ filename:dirname(code:which(?MODULE)),
+ {ok,Node} = start_node(logfile, Pa),
+ error_logger:logfile({open,Log}),
+ ok = rpc:call(Node, erlang, apply, [fun gen_events/1,[Ev]]),
+ AtNode = iolist_to_binary(["** at node ",atom_to_list(Node)," **"]),
+ error_logger:logfile(close),
+ analyse_events(Log, Ev, [AtNode], unlimited),
+
+ [] = [{X, file:pid2name(X)} || X <- processes(), Data <- [process_info(X, [current_function])],
+ Data =/= undefined,
+ element(1, element(2, lists:keyfind(current_function, 1, Data)))
+ =:= file_io_server,
+ file:pid2name(X) =:= {ok, Log}],
+
+ test_server:stop_node(Node),
+
+ cleanup(Log),
+ ok.
+
+logfile_truncated(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ LogDir = filename:join(PrivDir, ?MODULE),
+ Log = filename:join(LogDir, "logfile_truncated.log"),
+ ok = filelib:ensure_dir(Log),
+
+ Ev = event_templates(),
+
+ Depth = 20,
+ application:set_env(kernel, error_logger_format_depth, Depth),
+ try
+ do_one_logfile(Log, Ev, Depth)
+ after
+ application:unset_env(kernel, error_logger_format_depth)
+ end,
+
+ cleanup(Log),
+ ok.
+
+do_one_logfile(Log, Ev, Depth) ->
+ error_logger:logfile({open,Log}),
+ gen_events(Ev),
+ error_logger:logfile(close),
+ analyse_events(Log, Ev, [], Depth).
+
+tty(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ LogDir = filename:join(PrivDir, ?MODULE),
+ Log = filename:join(LogDir, "tty.log"),
+ ok = filelib:ensure_dir(Log),
+
+ Ev = event_templates(),
+
+ do_one_tty(Log, Ev, unlimited),
+
+ Pa = "-pa " ++ filename:dirname(code:which(?MODULE)),
+ {ok,Node} = start_node(logfile, Pa),
+ tty_log_open(Log),
+ ok = rpc:call(Node, erlang, apply, [fun gen_events/1,[Ev]]),
+ tty_log_close(),
+ AtNode = iolist_to_binary(["** at node ",atom_to_list(Node)," **"]),
+ analyse_events(Log, Ev, [AtNode], unlimited),
+
+ test_server:stop_node(Node),
+
+ cleanup(Log),
+ ok.
+
+tty_truncated(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ LogDir = filename:join(PrivDir, ?MODULE),
+ Log = filename:join(LogDir, "tty_truncated.log"),
+ ok = filelib:ensure_dir(Log),
+
+ Ev = event_templates(),
+
+ Depth = 20,
+ application:set_env(kernel, error_logger_format_depth, Depth),
+ try
+ do_one_tty(Log, Ev, Depth)
+ after
+ application:unset_env(kernel, error_logger_format_depth)
+ end,
+
+ cleanup(Log),
+ ok.
+
+do_one_tty(Log, Ev, Depth) ->
+ tty_log_open(Log),
+ gen_events(Ev),
+ tty_log_close(),
+ analyse_events(Log, Ev, [], Depth).
+
+tty_log_open(Log) ->
+ {ok,Fd} = file:open(Log, [write]),
+ Depth = case application:get_env(kernel, error_logger_format_depth) of
+ {ok,D} -> D;
+ _ -> unlimited
+ end,
+ error_logger:add_report_handler(?MODULE, {Fd,Depth}),
+ Fd.
+
+tty_log_close() ->
+ error_logger:delete_report_handler(?MODULE),
+ ok.
+
+event_templates() ->
+ [{error_msg,["Pure error string\n",[]]},
+ {error_msg,["Pure error string with error ~p\n",[]]},
+ {error_msg,["Error string with ~p\n", [format]]},
+ {error_msg,["Error string with bad format ~p\n", []]},
+
+ {error_report,[error_atom]},
+ {error_report,["error string"]},
+ {error_report,[[{error_tag,value},error_value]]},
+
+ {info_msg,["Pure info string\n",[]]},
+ {info_msg,["Pure info string with error ~p\n",[]]},
+ {info_msg,["Pure string with ~p\n", [format]]},
+ {info_msg,["Pure string with bad format ~p\n", []]},
+
+ {info_report,[info_atom]},
+ {info_report,["info string"]},
+ {info_report,[[{info_tag,value},info_value]]},
+
+ {warning_msg,["Pure warning string\n",[]]},
+ {warning_msg,["Pure warning string with error ~p\n",[]]},
+ {warning_msg,["Warning string with ~p\n", [format]]},
+ {warning_msg,["Warning string with bad format ~p\n", []]},
+
+ {warning_report,[warning_atom]},
+ {warning_report,["warning string"]},
+ {warning_report,[[{warning_tag,value},warning_value]]},
+
+ %% Bigger terms.
+ {error_msg,["fairly big: ~p\n",[lists:seq(1, 128)]]},
+ {error_report,[list_to_tuple(lists:seq(1, 100))]},
+ {error_report,[lists:seq(32, 126)]},
+ {error_report,[[{tag,lists:seq(1, 64)}]]}
+ ].
+
+gen_events(Ev) ->
+ io:format("node = ~p\n", [node()]),
+ io:format("group leader = ~p\n", [group_leader()]),
+ io:format("~p\n", [gen_event:which_handlers(error_logger)]),
+ call_error_logger(Ev),
+
+ {Pid,Ref} = spawn_monitor(fun() -> error(ouch) end),
+ receive
+ {'DOWN',Ref,process,Pid,_} ->
+ ok
+ end,
+
+ %% The following calls with a custom type will be ignored.
+ error_logger:error_report(ignored, value),
+ error_logger:warning_report(ignored, value),
+ error_logger:info_report(ignored, value),
+ receive after 100 -> ok end,
+ ok.
+
+analyse_events(Log, Ev, AtNode, Depth) ->
+ {ok,Bin} = file:read_file(Log),
+
+ io:format("*** Contents of log file ***\n\n~s\n", [Bin]),
+
+ Lines = binary:split(Bin, <<"\n">>, [global,trim_all]),
+ io:format("~p\n", [Lines]),
+
+ Rest = match_output(Ev, Lines, AtNode, Depth),
+ io:format("~p\n", [Rest]),
+
+ [] = match_emulator_error(Rest),
+ ok.
+
+
+call_error_logger([{F,Args}|T]) ->
+ apply(error_logger, F, Args),
+ call_error_logger(T);
+call_error_logger([]) -> ok.
+
+
+match_emulator_error([Head,Second,Third,_|Lines]) ->
+ match_head(<<"ERROR">>, Head),
+ {match,[{0,_}]} = re:run(Second,
+ "^Error in process <\\d+[.]\\d+[.]\\d+> on "
+ "node [^ ]* with exit value:"),
+ {match,[{0,_}]} = re:run(Third, "^[{]ouch,"),
+ Lines.
+
+match_output([Item|T], Lines0, AtNode, Depth) ->
+ try match_item(Item, Lines0, AtNode, Depth) of
+ Lines ->
+ match_output(T, Lines, AtNode, Depth)
+ catch
+ C:E ->
+ Stk = erlang:get_stacktrace(),
+ io:format("ITEM: ~p", [Item]),
+ io:format("LINES: ~p", [Lines0]),
+ erlang:raise(C, E, Stk)
+ end;
+match_output([], Lines, _, _) -> Lines.
+
+match_item(Item, Lines, AtNode, Depth) ->
+ case item_type(Item) of
+ {msg,Head,Args} ->
+ match_format(Head, Args, Lines, AtNode, Depth);
+ {report,Head,Args} ->
+ match_term(Head, Args, Lines, AtNode, Depth)
+ end.
+
+item_type({error_msg,Args}) ->
+ {msg,<<"ERROR">>,Args};
+item_type({info_msg,Args}) ->
+ {msg,<<"INFO">>,Args};
+item_type({warning_msg,Args}) ->
+ {msg,<<"WARNING">>,Args};
+item_type({error_report,Args}) ->
+ {report,<<"ERROR">>,Args};
+item_type({info_report,Args}) ->
+ {report,<<"INFO">>,Args};
+item_type({warning_report,Args}) ->
+ {report,<<"WARNING">>,Args}.
+
+match_format(Tag, [Format,Args], [Head|Lines], AtNode, Depth) ->
+ match_head(Tag, Head),
+ Bin = try dl_format(Depth, Format, Args) of
+ Str ->
+ iolist_to_binary(Str)
+ catch
+ _:_ ->
+ S = dl_format(Depth, "ERROR: ~p - ~p~n", [Format,Args]),
+ iolist_to_binary(S)
+ end,
+ Expected0 = binary:split(Bin, <<"\n">>, [global,trim]),
+ Expected = Expected0 ++ AtNode,
+ match_term_lines(Expected, Lines).
+
+match_term(Tag, [Arg], [Head|Lines], AtNode, Depth) ->
+ match_head(Tag, Head),
+ Expected0 = match_term_get_expected(Arg, Depth),
+ Expected = Expected0 ++ AtNode,
+ match_term_lines(Expected, Lines).
+
+match_term_get_expected(List, Depth) when is_list(List) ->
+ Bin = try iolist_to_binary(dl_format(Depth, "~s\n", [List])) of
+ Bin0 -> Bin0
+ catch
+ _:_ ->
+ iolist_to_binary(format_rep(List, Depth))
+ end,
+ binary:split(Bin, <<"\n">>, [global,trim]);
+match_term_get_expected(Term, Depth) ->
+ S = dl_format(Depth, "~p\n", [Term]),
+ Bin = iolist_to_binary(S),
+ binary:split(Bin, <<"\n">>, [global,trim]).
+
+format_rep([{Tag,Data}|Rep], Depth) ->
+ [dl_format(Depth, " ~p: ~p\n", [Tag,Data])|
+ format_rep(Rep, Depth)];
+format_rep([Other|Rep], Depth) ->
+ [dl_format(Depth, " ~p\n", [Other])|
+ format_rep(Rep, Depth)];
+format_rep([], _Depth) -> [].
+
+match_term_lines([Line|T], [Line|Lines]) ->
+ match_term_lines(T, Lines);
+match_term_lines([], Lines) -> Lines.
+
+match_head(Tag, Head) ->
+ Re = <<"^=",Tag/binary,
+ " REPORT==== \\d\\d?-[A-Z][a-z][a-z]-\\d{4}::"
+ "\\d\\d:\\d\\d:\\d\\d ===$">>,
+ {match,_} = re:run(Head, Re).
+
+start_node(Name, Args) ->
+ case test_server:start_node(Name, slave, [{args,Args}]) of
+ {ok,Node} ->
+ {ok,Node};
+ Error ->
+ test_server:fail(Error)
+ end.
+
+cleanup(File) ->
+ %% The point of this test case is not to test file operations.
+ %% Therefore ignore any failures.
+ case file:delete(File) of
+ ok ->
+ ok;
+ {error,Error1} ->
+ io:format("file:delete(~s) failed with error ~p",
+ [File,Error1])
+ end,
+ Dir = filename:dirname(File),
+ case file:del_dir(Dir) of
+ ok ->
+ ok;
+ {error,Error2} ->
+ io:format("file:del_dir(~s) failed with error ~p",
+ [Dir,Error2])
+ end,
+ ok.
+
+
+%% Depth-limited io_lib:format. Intentionally implemented here instead
+%% of using io_lib:scan_format/2 to avoid using the same implementation
+%% as in the error_logger handlers.
+
+dl_format(unlimited, Format, Args) ->
+ io_lib:format(Format, Args);
+dl_format(Depth, Format0, Args0) ->
+ {Format,Args} = dl_format_1(Format0, Args0, Depth, [], []),
+ io_lib:format(Format, Args).
+
+dl_format_1("~p"++Fs, [A|As], Depth, Facc, Acc) ->
+ dl_format_1(Fs, As, Depth, [$P,$~|Facc], [Depth,A|Acc]);
+dl_format_1("~w"++Fs, [A|As], Depth, Facc, Acc) ->
+ dl_format_1(Fs, As, Depth, [$W,$~|Facc], [Depth,A|Acc]);
+dl_format_1("~s"++Fs, [A|As], Depth, Facc, Acc) ->
+ dl_format_1(Fs, As, Depth, [$s,$~|Facc], [A|Acc]);
+dl_format_1([F|Fs], As, Depth, Facc, Aacc) ->
+ dl_format_1(Fs, As, Depth, [F|Facc], Aacc);
+dl_format_1([], [], _, Facc, Aacc) ->
+ {lists:reverse(Facc),lists:reverse(Aacc)}.
+
+%%%
+%%% Our own event handler. There is no way to intercept the output
+%%% from error_logger_tty_h, but we can use the same code by
+%%% calling error_logger_tty_h:write_event/2.
+%%%
+
+init({_,_}=St) ->
+ {ok,St}.
+
+handle_event(Event, {Fd,Depth}=St) ->
+ case error_logger_tty_h:write_event(tag_event(Event), io_lib, Depth) of
+ ok ->
+ ok;
+ Str when is_list(Str) ->
+ io:put_chars(Fd, Str)
+ end,
+ {ok,St}.
+
+terminate(_Reason, {Fd,_}) ->
+ ok = file:close(Fd),
+ [].
+
+tag_event(Event) ->
+ {erlang:universaltime(),Event}.
diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl
index ae431d66d9..3e63d19213 100644
--- a/lib/stdlib/test/ets_SUITE.erl
+++ b/lib/stdlib/test/ets_SUITE.erl
@@ -112,9 +112,8 @@
-define(m(A,B), ?line assert_eq(A,B)).
init_per_testcase(Case, Config) ->
- Seed = {S1,S2,S3} = random:seed0(), %now(),
- random:seed(S1,S2,S3),
- io:format("*** SEED: ~p ***\n", [Seed]),
+ rand:seed(exsplus),
+ io:format("*** SEED: ~p ***\n", [rand:export_seed()]),
start_spawn_logger(),
wait_for_test_procs(), %% Ensure previous case cleaned up
Dog=test_server:timetrap(test_server:minutes(20)),
@@ -731,10 +730,6 @@ chk_normal_tab_struct_size() ->
% ?line ok
% end.
--define(DB_TREE_STACK_NEED,50). % The static stack for a tree, in halfword pointers are two internal words
- % so the stack gets twice as big
--define(DB_HASH_SIZEOF_EXTSEG,260). % The segment size in words, in halfword this will be twice as large.
-
adjust_xmem([T1,T2,T3,T4], {A0,B0,C0,D0} = _Mem0) ->
%% Adjust for 64-bit, smp, and os:
%% Table struct size may differ.
@@ -748,19 +743,7 @@ adjust_xmem([T1,T2,T3,T4], {A0,B0,C0,D0} = _Mem0) ->
% end,
TabDiff = ?TAB_STRUCT_SZ,
- Mem1 = {A0+TabDiff, B0+TabDiff, C0+TabDiff, D0+TabDiff},
-
- case {erlang:system_info({wordsize,internal}),erlang:system_info({wordsize,external})} of
- %% Halfword, corrections for regular pointers occupying two internal words.
- {4,8} ->
- {A1,B1,C1,D1} = Mem1,
- {A1+4*ets:info(T1, size)+?DB_TREE_STACK_NEED,
- B1+3*ets:info(T2, size)+?DB_HASH_SIZEOF_EXTSEG,
- C1+3*ets:info(T3, size)+?DB_HASH_SIZEOF_EXTSEG,
- D1+3*ets:info(T4, size)+?DB_HASH_SIZEOF_EXTSEG};
- _ ->
- Mem1
- end.
+ {A0+TabDiff, B0+TabDiff, C0+TabDiff, D0+TabDiff}.
t_whitebox(doc) ->
["Diverse whitebox testes"];
@@ -1346,7 +1329,7 @@ drop_match() ->
ets_match(Tab,Expr) ->
- case random:uniform(2) of
+ case rand:uniform(2) of
1 ->
ets:match(Tab,Expr);
_ ->
@@ -1355,14 +1338,14 @@ ets_match(Tab,Expr) ->
match_chunked(Tab,Expr) ->
match_chunked_collect(ets:match(Tab,Expr,
- random:uniform(1999) + 1)).
+ rand:uniform(1999) + 1)).
match_chunked_collect('$end_of_table') ->
[];
match_chunked_collect({Results, Continuation}) ->
Results ++ match_chunked_collect(ets:match(Continuation)).
ets_match_object(Tab,Expr) ->
- case random:uniform(2) of
+ case rand:uniform(2) of
1 ->
ets:match_object(Tab,Expr);
_ ->
@@ -1371,7 +1354,7 @@ ets_match_object(Tab,Expr) ->
match_object_chunked(Tab,Expr) ->
match_object_chunked_collect(ets:match_object(Tab,Expr,
- random:uniform(1999) + 1)).
+ rand:uniform(1999) + 1)).
match_object_chunked_collect('$end_of_table') ->
[];
match_object_chunked_collect({Results, Continuation}) ->
@@ -1383,19 +1366,15 @@ random_test() ->
?line ReadDir = get(where_to_read),
?line WriteDir = get(where_to_write),
?line (catch file:make_dir(WriteDir)),
- ?line Seed = case file:consult(filename:join([ReadDir,
- "preset_random_seed.txt"])) of
- {ok,[X]} ->
- X;
- _ ->
- {A,B,C} = erlang:timestamp(),
- random:seed(A,B,C),
- get(random_seed)
- end,
- put(random_seed,Seed),
- ?line {ok, F} = file:open(filename:join([WriteDir,
- "last_random_seed.txt"]),
- [write]),
+ case file:consult(filename:join([ReadDir,"preset_random_seed.txt"])) of
+ {ok,[X]} ->
+ rand:seed(X);
+ _ ->
+ rand:seed(exsplus)
+ end,
+ Seed = rand:export_seed(),
+ {ok,F} = file:open(filename:join([WriteDir,"last_random_seed.txt"]),
+ [write]),
io:format(F,"~p. ~n",[Seed]),
file:close(F),
io:format("Random seed ~p written to ~s, copy to ~s to rerun with "
@@ -1417,7 +1396,7 @@ do_random_test() ->
end, 5000),
?line io:format("~nData inserted~n"),
?line do_n_times(fun() ->
- ?line I = random:uniform(25),
+ I = rand:uniform(25),
?line Key = create_random_string(I) ++ '_',
?line L1 = ets_match_object(OrdSet,{Key,'_'}),
?line L2 = lists:sort(ets_match_object(Set,{Key,'_'})),
@@ -1977,7 +1956,7 @@ evil_update_counter(Config) when is_list(Config) ->
gb_sets:module_info(),
math:module_info(),
ordsets:module_info(),
- random:module_info(),
+ rand:module_info(),
repeat_for_opts(evil_update_counter_do).
@@ -2011,7 +1990,7 @@ evil_counter(I,Opts) ->
1 -> 16#12345678FFFFFFFF;
2 -> 16#7777777777FFFFFFFF863648726743
end,
- Start = Start0 + random:uniform(100000),
+ Start = Start0 + rand:uniform(100000),
ets:insert(T, {dracula,Start}),
Iter = 40000,
End = Start + Iter,
@@ -4661,11 +4640,11 @@ create_random_string(0) ->
[];
create_random_string(OfLength) ->
- C = case random:uniform(2) of
+ C = case rand:uniform(2) of
1 ->
- (random:uniform($Z - $A + 1) - 1) + $A;
+ (rand:uniform($Z - $A + 1) - 1) + $A;
_ ->
- (random:uniform($z - $a + 1) - 1) + $a
+ (rand:uniform($z - $a + 1) - 1) + $a
end,
[C | create_random_string(OfLength - 1)].
@@ -4676,7 +4655,7 @@ create_random_tuple(OfLength) ->
end,create_random_string(OfLength))).
create_partly_bound_tuple(OfLength) ->
- case random:uniform(2) of
+ case rand:uniform(2) of
1 ->
create_partly_bound_tuple1(OfLength);
_ ->
@@ -4685,14 +4664,14 @@ create_partly_bound_tuple(OfLength) ->
create_partly_bound_tuple1(OfLength) ->
T0 = create_random_tuple(OfLength),
- I = random:uniform(OfLength),
+ I = rand:uniform(OfLength),
setelement(I,T0,'$1').
set_n_random_elements(T0,0,_,_) ->
T0;
set_n_random_elements(T0,N,OfLength,GenFun) ->
- I = random:uniform(OfLength),
+ I = rand:uniform(OfLength),
What = GenFun(I),
case element(I,T0) of
What ->
@@ -4706,12 +4685,12 @@ make_dollar_atom(I) ->
list_to_atom([$$] ++ integer_to_list(I)).
create_partly_bound_tuple2(OfLength) ->
T0 = create_random_tuple(OfLength),
- I = random:uniform(OfLength - 1),
+ I = rand:uniform(OfLength - 1),
set_n_random_elements(T0,I,OfLength,fun make_dollar_atom/1).
create_partly_bound_tuple3(OfLength) ->
T0 = create_random_tuple(OfLength),
- I = random:uniform(OfLength - 1),
+ I = rand:uniform(OfLength - 1),
set_n_random_elements(T0,I,OfLength,fun(_) -> '_' end).
do_n_times(_,0) ->
@@ -5074,11 +5053,12 @@ meta_wb_do(Opts) ->
io:format("Colliding names = ~p\n",[Names]),
F = fun(0,_,_) -> ok;
- (N,Tabs,Me) -> Name1 = lists:nth(random:uniform(Len),Names),
- Name2 = lists:nth(random:uniform(Len),Names),
- Op = element(random:uniform(3),OpFuns),
- NTabs = Op(Name1, Name2, Tabs, Opts),
- Me(N-1,NTabs,Me)
+ (N,Tabs,Me) ->
+ Name1 = lists:nth(rand:uniform(Len), Names),
+ Name2 = lists:nth(rand:uniform(Len), Names),
+ Op = element(rand:uniform(3),OpFuns),
+ NTabs = Op(Name1, Name2, Tabs, Opts),
+ Me(N-1, NTabs, Me)
end,
F(Len*100, [], F),
@@ -5344,7 +5324,7 @@ smp_insert(suite) -> [];
smp_insert(Config) when is_list(Config) ->
ets_new(smp_insert,[named_table,public,{write_concurrency,true}]),
InitF = fun(_) -> ok end,
- ExecF = fun(_) -> true = ets:insert(smp_insert,{random:uniform(10000)})
+ ExecF = fun(_) -> true = ets:insert(smp_insert,{rand:uniform(10000)})
end,
FiniF = fun(_) -> ok end,
run_workers(InitF,ExecF,FiniF,100000),
@@ -5595,10 +5575,10 @@ smp_select_delete(Config) when is_list(Config) ->
Zeros = erlang:make_tuple(Mod,0),
InitF = fun(_) -> Zeros end,
ExecF = fun(Diffs0) ->
- case random:uniform(20) of
+ case rand:uniform(20) of
1 ->
Mod = 17,
- Eq = random:uniform(Mod) - 1,
+ Eq = rand:uniform(Mod) - 1,
Deleted = ets:select_delete(T,
[{{'_', '$1'},
[{'=:=', {'rem', '$1', Mod}, Eq}],
@@ -5607,7 +5587,7 @@ smp_select_delete(Config) when is_list(Config) ->
element(Eq+1,Diffs0) - Deleted),
Diffs1;
_ ->
- Key = random:uniform(10000),
+ Key = rand:uniform(10000),
Eq = Key rem Mod,
?line case ets:insert_new(T,{Key,Key}) of
true ->
@@ -5811,7 +5791,7 @@ run_workers_do(InitF,ExecF,FiniF,Laps, Exclude) ->
N when (N > Exclude) -> N - Exclude
end,
io:format("smp starting ~p workers\n",[NumOfProcs]),
- Seeds = [{ProcN,random:uniform(9999)} || ProcN <- lists:seq(1,NumOfProcs)],
+ Seeds = [{ProcN,rand:uniform(9999)} || ProcN <- lists:seq(1,NumOfProcs)],
Parent = self(),
Pids = [my_spawn_link(fun()-> worker(Seed,InitF,ExecF,FiniF,Laps,Parent,NumOfProcs) end)
|| Seed <- Seeds],
@@ -5822,7 +5802,7 @@ run_workers_do(InitF,ExecF,FiniF,Laps, Exclude) ->
worker({ProcN,Seed}, InitF, ExecF, FiniF, Laps, Parent, NumOfProcs) ->
io:format("smp worker ~p, seed=~p~n",[self(),Seed]),
- random:seed(Seed,Seed,Seed),
+ rand:seed(exsplus, {Seed,Seed,Seed}),
State1 = InitF([ProcN, NumOfProcs]),
State2 = worker_loop(Laps, ExecF, State1),
Result = FiniF(State2),
diff --git a/lib/stdlib/test/ets_tough_SUITE.erl b/lib/stdlib/test/ets_tough_SUITE.erl
index c6f24fc670..8a7f2b1ec2 100644
--- a/lib/stdlib/test/ets_tough_SUITE.erl
+++ b/lib/stdlib/test/ets_tough_SUITE.erl
@@ -92,7 +92,7 @@ ex1_sub(Config) ->
ok.
prep(Config) ->
- random:seed(),
+ rand:seed(exsplus),
put(dump_ticket,none),
DumpDir = filename:join(?config(priv_dir,Config), "ets_tough"),
file:make_dir(DumpDir),
@@ -221,19 +221,19 @@ random_class() ->
random_element(Classes).
random_key() ->
- random:uniform(8).
+ rand:uniform(8).
random_value() ->
- case random:uniform(5) of
+ case rand:uniform(5) of
1 -> ok;
2 -> {data,random_key()};
3 -> {foo,bar,random_class()};
- 4 -> random:uniform(1000);
+ 4 -> rand:uniform(1000);
5 -> {recursive,random_value()}
end.
random_element(T) ->
- I = random:uniform(tuple_size(T)),
+ I = rand:uniform(tuple_size(T)),
element(I,T).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/stdlib/test/filelib_SUITE.erl b/lib/stdlib/test/filelib_SUITE.erl
index 01b798faef..c39ff842ee 100644
--- a/lib/stdlib/test/filelib_SUITE.erl
+++ b/lib/stdlib/test/filelib_SUITE.erl
@@ -318,7 +318,7 @@ same_lists(Expected0, Actual0, BaseDir) ->
mkfiles([H|T], Dir) ->
Name = filename:join(Dir, H),
- Garbage = [31+random:uniform(95) || _ <- lists:seq(1, random:uniform(1024))],
+ Garbage = [31+rand:uniform(95) || _ <- lists:seq(1, rand:uniform(1024))],
file:write_file(Name, Garbage),
[Name|mkfiles(T, Dir)];
mkfiles([], _) -> [].
diff --git a/lib/stdlib/test/filename_SUITE.erl b/lib/stdlib/test/filename_SUITE.erl
index fd47da8150..4372e77df9 100644
--- a/lib/stdlib/test/filename_SUITE.erl
+++ b/lib/stdlib/test/filename_SUITE.erl
@@ -97,20 +97,11 @@ absname(Config) when is_list(Config) ->
?line file:set_cwd(Cwd),
ok;
- Type ->
- case Type of
- {unix, _} ->
- ?line ok = file:set_cwd("/usr"),
- ?line "/usr/foo" = filename:absname(foo),
- ?line "/usr/foo" = filename:absname("foo"),
- ?line "/usr/../ebin" = filename:absname("../ebin");
- {ose, _} ->
- ?line ok = file:set_cwd("/romfs"),
- ?line "/romfs/foo" = filename:absname(foo),
- ?line "/romfs/foo" = filename:absname("foo"),
- ?line "/romfs/../ebin" = filename:absname("../ebin")
- end,
-
+ {unix, _} ->
+ ?line ok = file:set_cwd("/usr"),
+ ?line "/usr/foo" = filename:absname(foo),
+ ?line "/usr/foo" = filename:absname("foo"),
+ ?line "/usr/../ebin" = filename:absname("../ebin"),
?line file:set_cwd("/"),
?line "/foo" = filename:absname(foo),
?line "/foo" = filename:absname("foo"),
@@ -494,18 +485,10 @@ absname_bin(Config) when is_list(Config) ->
?line file:set_cwd(Cwd),
ok;
- Type ->
- case Type of
- {unix,_} ->
- ?line ok = file:set_cwd(<<"/usr">>),
- ?line <<"/usr/foo">> = filename:absname(<<"foo">>),
- ?line <<"/usr/../ebin">> = filename:absname(<<"../ebin">>);
- {ose,_} ->
- ?line ok = file:set_cwd(<<"/romfs">>),
- ?line <<"/romfs/foo">> = filename:absname(<<"foo">>),
- ?line <<"/romfs/../ebin">> = filename:absname(<<"../ebin">>)
- end,
-
+ {unix, _} ->
+ ?line ok = file:set_cwd(<<"/usr">>),
+ ?line <<"/usr/foo">> = filename:absname(<<"foo">>),
+ ?line <<"/usr/../ebin">> = filename:absname(<<"../ebin">>),
?line file:set_cwd(<<"/">>),
?line <<"/foo">> = filename:absname(<<"foo">>),
?line <<"/../ebin">> = filename:absname(<<"../ebin">>),
diff --git a/lib/stdlib/test/gen_event_SUITE.erl b/lib/stdlib/test/gen_event_SUITE.erl
index 7a6fcba4e5..b019f98b69 100644
--- a/lib/stdlib/test/gen_event_SUITE.erl
+++ b/lib/stdlib/test/gen_event_SUITE.erl
@@ -412,7 +412,6 @@ notify(Config) when is_list(Config) ->
ok
end,
?line ok = gen_event:notify(my_dummy_handler, {swap_event,dummy1_h,swap}),
- ?t:sleep(1000),
?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
?line ok = gen_event:notify(my_dummy_handler, Event),
?line receive
@@ -445,7 +444,6 @@ notify(Config) when is_list(Config) ->
end,
?line ok = gen_event:notify(my_dummy_handler,
{swap_event, {dummy1_h, 9}, swap}),
- ?t:sleep(1000),
?line [{dummy1_h,9}] = gen_event:which_handlers(my_dummy_handler),
?line ok = gen_event:notify(my_dummy_handler, Event),
?line receive
@@ -485,7 +483,6 @@ notify(Config) when is_list(Config) ->
?line ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
?line ok = gen_event:notify(my_dummy_handler, {swap_event,dummy1_h,swap}),
- ?t:sleep(1000),
?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
?line ok = gen_event:notify(my_dummy_handler, do_crash),
@@ -496,7 +493,6 @@ notify(Config) when is_list(Config) ->
?line ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
?line ok = gen_event:notify(my_dummy_handler, {swap_event,dummy1_h,swap}),
- ?t:sleep(1000),
?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
?line ok = gen_event:notify(my_dummy_handler, delete_event),
@@ -529,7 +525,6 @@ sync_notify(Config) when is_list(Config) ->
end,
?line ok = gen_event:sync_notify(my_dummy_handler,
{swap_event, dummy1_h, swap}),
- ?t:sleep(1000),
?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
?line ok = gen_event:sync_notify(my_dummy_handler, Event),
?line receive
@@ -562,7 +557,6 @@ sync_notify(Config) when is_list(Config) ->
end,
?line ok = gen_event:sync_notify(my_dummy_handler,
{swap_event, {dummy1_h, 9}, swap}),
- ?t:sleep(1000),
?line [{dummy1_h,9}] = gen_event:which_handlers(my_dummy_handler),
?line ok = gen_event:sync_notify(my_dummy_handler, Event),
?line receive
@@ -603,7 +597,6 @@ sync_notify(Config) when is_list(Config) ->
?line ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
?line ok = gen_event:sync_notify(my_dummy_handler,
{swap_event,dummy1_h,swap}),
- ?t:sleep(1000),
?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
?line ok = gen_event:sync_notify(my_dummy_handler, do_crash),
@@ -615,7 +608,6 @@ sync_notify(Config) when is_list(Config) ->
?line ok = gen_event:add_sup_handler(my_dummy_handler, dummy_h, [self()]),
?line ok = gen_event:sync_notify(my_dummy_handler,
{swap_event,dummy1_h,swap}),
- ?t:sleep(1000),
?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
?line ok = gen_event:sync_notify(my_dummy_handler, delete_event),
@@ -789,7 +781,6 @@ info(Config) when is_list(Config) ->
ok
end,
?line my_dummy_handler ! {swap_info,dummy1_h,swap},
- ?t:sleep(1000),
?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
?line my_dummy_handler ! Info,
?line receive
@@ -821,7 +812,6 @@ info(Config) when is_list(Config) ->
ok
end,
?line my_dummy_handler ! {swap_info,{dummy1_h,2},swap},
- ?t:sleep(1000),
?line [{dummy1_h,2}] = gen_event:which_handlers(my_dummy_handler),
?line my_dummy_handler ! Info,
?line receive
@@ -853,7 +843,6 @@ info(Config) when is_list(Config) ->
ok
end,
?line my_dummy_handler ! {swap_info,dummy1_h,swap},
- ?t:sleep(1000),
?line [dummy1_h] = gen_event:which_handlers(my_dummy_handler),
?line my_dummy_handler ! Info,
?line receive
diff --git a/lib/stdlib/test/id_transform_SUITE.erl b/lib/stdlib/test/id_transform_SUITE.erl
index 41de016f8d..1cff990697 100644
--- a/lib/stdlib/test/id_transform_SUITE.erl
+++ b/lib/stdlib/test/id_transform_SUITE.erl
@@ -56,47 +56,26 @@ end_per_group(_GroupName, Config) ->
id_transform(doc) -> "Test erl_id_trans.";
id_transform(Config) when is_list(Config) ->
- ?line File=filename:join([code:lib_dir(stdlib),"examples",
- "erl_id_trans.erl"]),
- ?line {ok,erl_id_trans,Bin}=compile:file(File,[binary]),
- ?line {module,erl_id_trans}=code:load_binary(erl_id_trans,File,Bin),
- ?line case test_server:purify_is_running() of
- false ->
- Dog = ct:timetrap(?t:hours(1)),
- ?line Res = run_in_test_suite(),
- ?t:timetrap_cancel(Dog),
- Res;
- true ->
- {skip,"Purify (too slow)"}
- end.
+ File = filename:join([code:lib_dir(stdlib),"examples",
+ "erl_id_trans.erl"]),
+ {ok,erl_id_trans,Bin} = compile:file(File,[binary]),
+ {module,erl_id_trans} = code:load_binary(erl_id_trans, File, Bin),
+ case test_server:purify_is_running() of
+ false ->
+ Dog = ct:timetrap(?t:hours(1)),
+ Res = run_in_test_suite(),
+ ?t:timetrap_cancel(Dog),
+ Res;
+ true ->
+ {skip,"Valgrind (too slow)"}
+ end.
run_in_test_suite() ->
- LibDir = code:lib_dir(),
SuperDir = filename:dirname(filename:dirname(code:which(?MODULE))),
TestDirs = filelib:wildcard(filename:join([SuperDir,"*_test"])),
- {All,Res} = case LibDir of
- "/clearcase/otp/erts/lib" ->
- %% Only test_suites 'cause clearcase is too slow...
- {false,run_list(TestDirs)};
- _ ->
- {true,run_codepath_and(TestDirs)}
- end,
- Comment0 = case All of
- true -> [];
- false -> "Only testsuite directories traversed"
- end,
- case Res of
- {error,Reason} when Comment0 =/= [] ->
- {failed,Comment0++"; "++Reason};
- {error,Reason} ->
- {failed,Reason};
- ok ->
- {comment,Comment0}
- end.
-
-run_codepath_and(DirList) ->
AbsDirs = [filename:absname(X) || X <- code:get_path()],
- run_list(ordsets:from_list([X || X <- AbsDirs] ++ DirList)).
+ Dirs = ordsets:from_list(AbsDirs ++ TestDirs),
+ run_list(Dirs).
run_list(PathL) ->
io:format("Where to search for beam files:\n~p\n", [PathL]),
@@ -123,7 +102,7 @@ run_list(PathL) ->
end,
case length(SevereFailures) of
0 -> ok;
- Len -> {error,integer_to_list(Len)++" failures"}
+ Len -> {failed,integer_to_list(Len)++" failures"}
end.
diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl
index 5df09b6a79..0e897631ff 100644
--- a/lib/stdlib/test/io_SUITE.erl
+++ b/lib/stdlib/test/io_SUITE.erl
@@ -29,10 +29,11 @@
manpage/1, otp_6708/1, otp_7084/1, otp_7421/1,
io_lib_collect_line_3_wb/1, cr_whitespace_in_string/1,
io_fread_newlines/1, otp_8989/1, io_lib_fread_literal/1,
- printable_range/1,
+ printable_range/1, bad_printable_range/1,
io_lib_print_binary_depth_one/1, otp_10302/1, otp_10755/1,
otp_10836/1, io_lib_width_too_small/1,
- io_with_huge_message_queue/1, format_string/1]).
+ io_with_huge_message_queue/1, format_string/1,
+ maps/1, coverage/1]).
-export([pretty/2]).
@@ -70,10 +71,10 @@ all() ->
manpage, otp_6708, otp_7084, otp_7421,
io_lib_collect_line_3_wb, cr_whitespace_in_string,
io_fread_newlines, otp_8989, io_lib_fread_literal,
- printable_range,
+ printable_range, bad_printable_range,
io_lib_print_binary_depth_one, otp_10302, otp_10755, otp_10836,
io_lib_width_too_small, io_with_huge_message_queue,
- format_string].
+ format_string, maps, coverage].
groups() ->
[].
@@ -2062,8 +2063,6 @@ printable_range(Suite) when is_list(Suite) ->
[{args, " +pclatin1 -pa " ++ Pa}]),
unicode = rpc:call(UNode,io,printable_range,[]),
latin1 = rpc:call(LNode,io,printable_range,[]),
- {error, _} = test_server:start_node(printable_range_unnicode, slave,
- [{args, " +pcunnicode -pa " ++ Pa}]),
PrettyOptions = [{column,1},
{line_length,109},
{depth,30},
@@ -2071,48 +2070,69 @@ printable_range(Suite) when is_list(Suite) ->
{record_print_fun,
fun(_,_) -> no end},
{encoding,unicode}],
- 1025 = lists:max(lists:flatten(rpc:call(UNode,io_lib_pretty,print,
- [{hello, [1024,1025]},
- PrettyOptions]))),
- 125 = lists:max(lists:flatten(rpc:call(LNode,io_lib_pretty,print,
- [{hello, [1024,1025]},
- PrettyOptions]))),
- 125 = lists:max(lists:flatten(rpc:call(DNode,io_lib_pretty,print,
- [{hello, [1024,1025]},
- PrettyOptions]))),
- 1025 = lists:max(lists:flatten(rpc:call(UNode,io_lib_pretty,print,
- [{hello, <<1024/utf8,1025/utf8>>},
- PrettyOptions]))),
- 125 = lists:max(lists:flatten(rpc:call(LNode,io_lib_pretty,print,
- [{hello, <<1024/utf8,1025/utf8>>},
- PrettyOptions]))),
- 125 = lists:max(lists:flatten(rpc:call(DNode,io_lib_pretty,print,
- [{hello, <<1024/utf8,1025/utf8>>},
- PrettyOptions]))),
+ PrintableControls = "\t\v\b\f\e\r\n",
+
+ 1025 = print_max(UNode, [{hello, [1024,1025]},
+ PrettyOptions]),
+ 125 = print_max(LNode, [{hello, [1024,1025]},
+ PrettyOptions]),
+ 125 = print_max(DNode, [{hello, [1024,1025]},
+ PrettyOptions]),
+ 1025 = print_max(UNode, [{hello, <<1024/utf8,1025/utf8>>},
+ PrettyOptions]),
+ 125 = print_max(LNode, [{hello, <<1024/utf8,1025/utf8>>},
+ PrettyOptions]),
+ 125 = print_max(DNode, [{hello, <<1024/utf8,1025/utf8>>},
+ PrettyOptions]),
+ $v = print_max(UNode, [PrintableControls,PrettyOptions]),
+ $v = print_max(LNode, [PrintableControls,PrettyOptions]),
+ $v = print_max(DNode, [PrintableControls,PrettyOptions]),
+ 16#10FFFF = print_max(UNode,
+ [<<16#10FFFF/utf8,"\t\v\b\f\e\r\n">>,
+ PrettyOptions]),
+ $> = print_max(LNode,
+ [<<16#10FFFF/utf8,"\t\v\b\f\e\r\n">>,
+ PrettyOptions]),
+ $> = print_max(DNode,
+ [<<16#10FFFF/utf8,"\t\v\b\f\e\r\n">>,
+ PrettyOptions]),
- 1025 = lists:max(lists:flatten(rpc:call(UNode,io_lib,format,
- ["~tp",[{hello, [1024,1025]}]]))),
- 125 = lists:max(lists:flatten(rpc:call(LNode,io_lib,format,
- ["~tp",[{hello, [1024,1025]}]]))),
- 125 = lists:max(lists:flatten(rpc:call(DNode,io_lib,format,
- ["~tp",[{hello, [1024,1025]}]]))),
- 1025 = lists:max(lists:flatten(rpc:call(UNode,io_lib,format,
- ["~tp",
- [{hello,
- <<1024/utf8,1025/utf8>>}]]))),
- 125 = lists:max(lists:flatten(rpc:call(LNode,io_lib,format,
- ["~tp",
- [{hello,
- <<1024/utf8,1025/utf8>>}]]))),
- 125 = lists:max(lists:flatten(rpc:call(DNode,io_lib,format,
- ["~tp",
- [{hello,
- <<1024/utf8,1025/utf8>>}]]))),
+ 1025 = format_max(UNode, ["~tp", [{hello, [1024,1025]}]]),
+ 125 = format_max(LNode, ["~tp", [{hello, [1024,1025]}]]),
+ 125 = format_max(DNode, ["~tp", [{hello, [1024,1025]}]]),
+ 1025 = format_max(UNode, ["~tp", [{hello, <<1024/utf8,1025/utf8>>}]]),
+ 125 = format_max(LNode, ["~tp", [{hello, <<1024/utf8,1025/utf8>>}]]),
+ 125 = format_max(DNode, ["~tp", [{hello, <<1024/utf8,1025/utf8>>}]]),
+
+ $\e = format_max(UNode, ["~ts", [PrintableControls]]),
+ $\e = format_max(LNode, ["~ts", [PrintableControls]]),
+ $\e = format_max(DNode, ["~ts", [PrintableControls]]),
+
test_server:stop_node(UNode),
test_server:stop_node(LNode),
test_server:stop_node(DNode),
ok.
+print_max(Node, Args) ->
+ rpc_call_max(Node, io_lib_pretty, print, Args).
+
+format_max(Node, Args) ->
+ rpc_call_max(Node, io_lib, format, Args).
+
+rpc_call_max(Node, M, F, Args) ->
+ lists:max(lists:flatten(rpc:call(Node, M, F, Args))).
+
+%% Make sure that a bad specification for a printable range is rejected.
+bad_printable_range(Config) when is_list(Config) ->
+ Cmd = lists:concat([lib:progname()," +pcunnnnnicode -run erlang halt"]),
+ case os:cmd(Cmd) of
+ "bad range of printable characters" ++ _ ->
+ ok;
+ String ->
+ io:format("~s\n", [String]),
+ ?t:fail()
+ end.
+
io_lib_print_binary_depth_one(doc) ->
"Test binaries printed with a depth of one behave correctly";
io_lib_print_binary_depth_one(Suite) when is_list(Suite) ->
@@ -2225,7 +2245,7 @@ compile_file(File, Text, Config) ->
after ok %file:delete(Fname)
end.
-io_lib_width_too_small(Config) ->
+io_lib_width_too_small(_Config) ->
"**" = lists:flatten(io_lib:format("~2.3w", [3.14])),
"**" = lists:flatten(io_lib:format("~2.5w", [3.14])),
ok.
@@ -2271,8 +2291,113 @@ writes(N, F1) ->
file:write(F1, "hello\n"),
writes(N - 1, F1).
-format_string(Config) ->
+format_string(_Config) ->
%% All but padding is tested by fmt/2.
"xxxxxxsssx" = fmt("~10.4.xs", ["sss"]),
"xxxxxxsssx" = fmt("~10.4.*s", [$x, "sss"]),
ok.
+
+maps(_Config) ->
+ %% Note that order in which a map is printed is arbitrary. In
+ %% practice, small maps (non-HAMT) are printed in key order, but
+ %% the breakpoint for creating big maps (HAMT) is lower in the
+ %% debug-compiled run-time system than in the optimized run-time
+ %% system.
+ %%
+ %% Therefore, play it completely safe by not assuming any order
+ %% in a map with more than one element.
+
+ "#{}" = fmt("~w", [#{}]),
+ "#{a=>b}" = fmt("~w", [#{a=>b}]),
+ re_fmt(<<"#\\{(a=>b|c=>d),[.][.][.]=>[.][.][.]\\}">>,
+ "~W", [#{a=>b,c=>d},2]),
+ re_fmt(<<"#\\{(a=>b|c=>d|e=>f),[.][.][.]=>[.][.][.],[.][.][.]\\}">>,
+ "~W", [#{a=>b,c=>d,e=>f},2]),
+
+ "#{}" = fmt("~p", [#{}]),
+ "#{a => b}" = fmt("~p", [#{a=>b}]),
+ "#{...}" = fmt("~P", [#{a=>b},1]),
+ re_fmt(<<"#\\{(a => b|c => d),[.][.][.]\\}">>,
+ "~P", [#{a=>b,c=>d},2]),
+ re_fmt(<<"#\\{(a => b|c => d|e => f),[.][.][.]\\}">>,
+ "~P", [#{a=>b,c=>d,e=>f},2]),
+
+ List = [{I,I*I} || I <- lists:seq(1, 20)],
+ Map = maps:from_list(List),
+
+ "#{...}" = fmt("~P", [Map,1]),
+
+ %% Print a map and parse it back to a map.
+ S = fmt("~p\n", [Map]),
+ io:format("~p\n", [S]),
+ Map = parse_map(S),
+
+ %% Smoke test of a map as key.
+ MapAsKey = #{Map => "value"},
+ io:format("~s\n", [fmt("~p", [MapAsKey])]),
+ ok.
+
+re_fmt(Pattern, Format, Args) ->
+ S = list_to_binary(fmt(Format, Args)),
+ case re:run(S, Pattern, [{capture,none}]) of
+ nomatch ->
+ io:format("Pattern: ~s", [Pattern]),
+ io:format("Result: ~s", [S]),
+ ?t:fail();
+ match ->
+ ok
+ end.
+
+%% Parse a map consisting of integer keys and values.
+parse_map(S0) ->
+ S1 = parse_expect(S0, "#{"),
+ {M,S2} = parse_map_1(S1),
+ S = parse_expect(S2, "}"),
+ S = "",
+ M.
+
+parse_map_1(S0) ->
+ {Key,S1} = parse_number(S0),
+ S2 = parse_expect(S1, "=>"),
+ {Val,S3} = parse_number(S2),
+ case S3 of
+ ","++S4 ->
+ S5 = parse_skip_ws(S4),
+ {Map,S} = parse_map_1(S5),
+ {Map#{Key=>Val},S};
+ S ->
+ {#{Key=>Val},S}
+ end.
+
+parse_number(S) ->
+ parse_number(S, none).
+
+parse_number([C|S], Acc0) when $0 =< C, C =< $9 ->
+ Acc = case Acc0 of
+ none -> 0;
+ _ when is_integer(Acc0) -> Acc0
+ end,
+ parse_number(S, Acc*10+C-$0);
+parse_number(S, Acc) ->
+ {Acc,parse_skip_ws(S)}.
+
+parse_expect([H|T1], [H|T2]) ->
+ parse_expect(T1, T2);
+parse_expect(S, []) ->
+ parse_skip_ws(S).
+
+parse_skip_ws([C|S]) when C =< $\s ->
+ parse_skip_ws(S);
+parse_skip_ws(S) ->
+ S.
+
+%% Cover the last uncovered lines for completeness.
+coverage(_Config) ->
+ S1 = io_lib_pretty:print({a,term}, fun(_, _) -> no end),
+ io:format("~s\n", [S1]),
+
+ %% The tuple of arity three will be ignored.
+ S2 = io_lib_pretty:print(lists:seq(1, 100), [{depth,1,1}]),
+ io:format("~s\n", [S2]),
+
+ ok.
diff --git a/lib/stdlib/test/io_proto_SUITE.erl b/lib/stdlib/test/io_proto_SUITE.erl
index 1337b7dde2..811c7ed7bb 100644
--- a/lib/stdlib/test/io_proto_SUITE.erl
+++ b/lib/stdlib/test/io_proto_SUITE.erl
@@ -1378,47 +1378,43 @@ rtnode(C,N) ->
rtnode(Commands,Nodename,ErlPrefix) ->
rtnode(Commands,Nodename,ErlPrefix,[]).
rtnode(Commands,Nodename,ErlPrefix,Extra) ->
- ?line case get_progs() of
- {error,_Reason} ->
- ?line {skip,"No runerl present"};
- {RunErl,ToErl,Erl} ->
- ?line case create_tempdir() of
- {error, Reason2} ->
- ?line {skip, Reason2};
- Tempdir ->
- ?line SPid =
- start_runerl_node(RunErl,ErlPrefix++
- "\\\""++Erl++"\\\"",
- Tempdir,Nodename, Extra),
- ?line CPid = start_toerl_server(ToErl,Tempdir),
- ?line erase(getline_skipped),
- ?line Res =
- (catch get_and_put(CPid, Commands,1)),
- ?line case stop_runerl_node(CPid) of
- {error,_} ->
- ?line CPid2 =
- start_toerl_server
- (ToErl,Tempdir),
- ?line erase(getline_skipped),
- ?line ok = get_and_put
- (CPid2,
- [{putline,[7]},
- {sleep,
- timeout(short)},
- {putline,""},
- {getline," -->"},
- {putline,"s"},
- {putline,"c"},
- {putline,""}],1),
- ?line stop_runerl_node(CPid2);
- _ ->
- ?line ok
- end,
- ?line wait_for_runerl_server(SPid),
- ?line ok = ?RM_RF(Tempdir),
- ?line ok = Res
- end
- end.
+ case get_progs() of
+ {error,_Reason} ->
+ {skip,"No runerl present"};
+ {RunErl,ToErl,Erl} ->
+ case create_tempdir() of
+ {error, Reason2} ->
+ {skip, Reason2};
+ Tempdir ->
+ SPid = start_runerl_node(RunErl, ErlPrefix++
+ "\\\""++Erl++"\\\"",
+ Tempdir, Nodename, Extra),
+ CPid = start_toerl_server(ToErl, Tempdir),
+ put(getline_skipped, []),
+ Res = (catch get_and_put(CPid, Commands, 1)),
+ case stop_runerl_node(CPid) of
+ {error,_} ->
+ CPid2 = start_toerl_server(ToErl, Tempdir),
+ put(getline_skipped, []),
+ ok = get_and_put
+ (CPid2,
+ [{putline,[7]},
+ {sleep,
+ timeout(short)},
+ {putline,""},
+ {getline," -->"},
+ {putline,"s"},
+ {putline,"c"},
+ {putline,""}], 1),
+ stop_runerl_node(CPid2);
+ _ ->
+ ok
+ end,
+ wait_for_runerl_server(SPid),
+ ok = ?RM_RF(Tempdir),
+ ok = Res
+ end
+ end.
timeout(long) ->
2 * timeout(normal);
@@ -1462,57 +1458,51 @@ get_and_put(CPid, [{sleep, X}|T],N) ->
after X ->
get_and_put(CPid,T,N+1)
end;
-get_and_put(CPid, [{getline, Match}|T],N) ->
+get_and_put(CPid, [{getline_pred,Pred,Msg}|T]=T0, N)
+ when is_function(Pred) ->
?dbg({getline, Match}),
CPid ! {self(), {get_line, timeout(normal)}},
receive
{get_line, timeout} ->
error_logger:error_msg("~p: getline timeout waiting for \"~s\" "
"(command number ~p, skipped: ~p)~n",
- [?MODULE, Match,N,get(getline_skipped)]),
+ [?MODULE,Msg,N,get(getline_skipped)]),
{error, timeout};
{get_line, Data} ->
?dbg({data,Data}),
- case lists:prefix(Match, Data) of
- true ->
- erase(getline_skipped),
+ case Pred(Data) of
+ yes ->
+ put(getline_skipped, []),
get_and_put(CPid, T,N+1);
- false ->
- case get(getline_skipped) of
- undefined ->
- put(getline_skipped,[Data]);
- List ->
- put(getline_skipped,List ++ [Data])
- end,
- get_and_put(CPid, [{getline, Match}|T],N)
+ no ->
+ error_logger:error_msg("~p: getline match failure "
+ "\"~s\" "
+ "(command number ~p)\n",
+ [?MODULE,Msg,N]),
+ {error, no_match};
+ maybe ->
+ List = get(getline_skipped),
+ put(getline_skipped, List ++ [Data]),
+ get_and_put(CPid, T0, N)
end
end;
+get_and_put(CPid, [{getline, Match}|T],N) ->
+ ?dbg({getline, Match}),
+ F = fun(Data) ->
+ case lists:prefix(Match, Data) of
+ true -> yes;
+ false -> maybe
+ end
+ end,
+ get_and_put(CPid, [{getline_pred,F,Match}|T], N);
get_and_put(CPid, [{getline_re, Match}|T],N) ->
- ?dbg({getline_re, Match}),
- CPid ! {self(), {get_line, timeout(normal)}},
- receive
- {get_line, timeout} ->
- error_logger:error_msg("~p: getline_re timeout waiting for \"~s\" "
- "(command number ~p, skipped: ~p)~n",
- [?MODULE, Match,N,get(getline_skipped)]),
- {error, timeout};
- {get_line, Data} ->
- ?dbg({data,Data}),
- case re:run(Data, Match,[{capture,none}]) of
- match ->
- erase(getline_skipped),
- get_and_put(CPid, T,N+1);
- _ ->
- case get(getline_skipped) of
- undefined ->
- put(getline_skipped,[Data]);
- List ->
- put(getline_skipped,List ++ [Data])
- end,
- get_and_put(CPid, [{getline_re, Match}|T],N)
- end
- end;
-
+ F = fun(Data) ->
+ case re:run(Data, Match, [{capture,none}]) of
+ match -> yes;
+ _ -> maybe
+ end
+ end,
+ get_and_put(CPid, [{getline_pred,F,Match}|T], N);
get_and_put(CPid, [{putline_raw, Line}|T],N) ->
?dbg({putline_raw, Line}),
CPid ! {self(), {send_line, Line}},
@@ -1801,10 +1791,22 @@ get_data_within(Port, Timeout, Acc) ->
end.
get_default_shell() ->
+ Match = fun(Data) ->
+ case lists:prefix("undefined", Data) of
+ true ->
+ yes;
+ false ->
+ case re:run(Data, "<\\d+[.]\\d+[.]\\d+>",
+ [{capture,none}]) of
+ match -> no;
+ _ -> maybe
+ end
+ end
+ end,
try
rtnode([{putline,""},
{putline, "whereis(user_drv)."},
- {getline, "undefined"}],[]),
+ {getline_pred, Match, "matching of user_drv pid"}], []),
old
catch _E:_R ->
?dbg({_E,_R}),
diff --git a/lib/stdlib/test/lists_SUITE.erl b/lib/stdlib/test/lists_SUITE.erl
index e886a797f0..bd68c93779 100644
--- a/lib/stdlib/test/lists_SUITE.erl
+++ b/lib/stdlib/test/lists_SUITE.erl
@@ -38,13 +38,13 @@
% Test cases must be exported.
-export([member/1, reverse/1,
keymember/1, keysearch_keyfind/1,
- keystore/1, keytake/1,
+ keystore/1, keytake/1, keyreplace/1,
append_1/1, append_2/1,
seq_loop/1, seq_2/1, seq_3/1, seq_2_e/1, seq_3_e/1,
sublist_2/1, sublist_3/1, sublist_2_e/1, sublist_3_e/1,
flatten_1/1, flatten_2/1, flatten_1_e/1, flatten_2_e/1,
- dropwhile/1,
+ dropwhile/1, takewhile/1,
sort_1/1, sort_stable/1, merge/1, rmerge/1, sort_rand/1,
usort_1/1, usort_stable/1, umerge/1, rumerge/1,usort_rand/1,
keymerge/1, rkeymerge/1,
@@ -62,7 +62,7 @@
zip_unzip/1, zip_unzip3/1, zipwith/1, zipwith3/1,
filter_partition/1,
otp_5939/1, otp_6023/1, otp_6606/1, otp_7230/1,
- suffix/1, subtract/1, droplast/1]).
+ suffix/1, subtract/1, droplast/1, hof/1]).
%% Sort randomized lists until stopped.
%%
@@ -81,37 +81,51 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [{group, append}, reverse, member, keymember,
- keysearch_keyfind, keystore, keytake, dropwhile, {group,sort},
- {group, usort}, {group, keysort}, {group, ukeysort},
- {group, funsort}, {group, ufunsort}, {group, sublist},
- {group, flatten}, {group, seq}, zip_unzip, zip_unzip3,
- zipwith, zipwith3, filter_partition, {group, tickets},
- suffix, subtract].
+ [{group, append},
+ {group, key},
+ {group,sort},
+ {group, usort},
+ {group, keysort},
+ {group, ukeysort},
+ {group, funsort},
+ {group, ufunsort},
+ {group, sublist},
+ {group, flatten},
+ {group, seq},
+ {group, tickets},
+ {group, zip},
+ {group, misc}].
groups() ->
- [{append, [], [append_1, append_2]},
- {usort, [],
+ [{append, [parallel], [append_1, append_2]},
+ {usort, [parallel],
[umerge, rumerge, usort_1, usort_rand, usort_stable]},
- {keysort, [],
+ {keysort, [parallel],
[keymerge, rkeymerge, keysort_1, keysort_rand,
keysort_i, keysort_stable, keysort_error]},
- {sort,[],[merge, rmerge, sort_1, sort_rand]},
- {ukeysort, [],
+ {key, [parallel], [keymember, keysearch_keyfind, keystore,
+ keytake, keyreplace]},
+ {sort,[parallel],[merge, rmerge, sort_1, sort_rand]},
+ {ukeysort, [parallel],
[ukeymerge, rukeymerge, ukeysort_1, ukeysort_rand,
ukeysort_i, ukeysort_stable, ukeysort_error]},
- {funsort, [],
+ {funsort, [parallel],
[funmerge, rfunmerge, funsort_1, funsort_stable,
funsort_error, funsort_rand]},
- {ufunsort, [],
+ {ufunsort, [parallel],
[ufunmerge, rufunmerge, ufunsort_1, ufunsort_stable,
ufunsort_error, ufunsort_rand]},
- {seq, [], [seq_loop, seq_2, seq_3, seq_2_e, seq_3_e]},
- {sublist, [],
+ {seq, [parallel], [seq_loop, seq_2, seq_3, seq_2_e, seq_3_e]},
+ {sublist, [parallel],
[sublist_2, sublist_3, sublist_2_e, sublist_3_e]},
- {flatten, [],
+ {flatten, [parallel],
[flatten_1, flatten_2, flatten_1_e, flatten_2_e]},
- {tickets, [], [otp_5939, otp_6023, otp_6606, otp_7230]}].
+ {tickets, [parallel], [otp_5939, otp_6023, otp_6606, otp_7230]},
+ {zip, [parallel], [zip_unzip, zip_unzip3, zipwith, zipwith3]},
+ {misc, [parallel], [reverse, member, dropwhile, takewhile,
+ filter_partition, suffix, subtract,
+ hof]}
+ ].
init_per_suite(Config) ->
Config.
@@ -345,6 +359,33 @@ dropwhile(Config) when is_list(Config) ->
ok.
+takewhile(Config) when is_list(Config) ->
+ F = fun(C) -> C =/= $@ end,
+
+ [] = lists:takewhile(F, []),
+ [a] = lists:takewhile(F, [a]),
+ [a,b] = lists:takewhile(F, [a,b]),
+ [a,b,c] = lists:takewhile(F, [a,b,c]),
+
+ [] = lists:takewhile(F, [$@]),
+ [] = lists:takewhile(F, [$@,$@]),
+ [a] = lists:takewhile(F, [a,$@]),
+
+ [$k] = lists:takewhile(F, [$k,$@]),
+ [$k,$l] = lists:takewhile(F, [$k,$l,$@,$@]),
+ [a] = lists:takewhile(F, [a,$@,$@,$@]),
+
+ [] = lists:takewhile(F, [$@,a,$@,b]),
+ [] = lists:takewhile(F, [$@,$@,a,$@,b]),
+ [] = lists:takewhile(F, [$@,$@,$@,a,$@,b]),
+
+ Long = lists:seq(1, 1024),
+ Shorter = lists:seq(1, 400),
+
+ Shorter = lists:takewhile(fun(E) -> E =< 400 end, Long),
+
+ ok.
+
keystore(doc) ->
["OTP-XXX."];
keystore(suite) -> [];
@@ -382,6 +423,17 @@ keytake(Config) when is_list(Config) ->
?line false = lists:keytake(4, 2, L),
ok.
+%% Test lists:keyreplace/4.
+keyreplace(Config) when is_list(Config) ->
+ [{new,42}] = lists:keyreplace(k, 1, [{k,1}], {new,42}),
+ [atom,{new,a,b}] = lists:keyreplace(k, 1, [atom,{k,1}], {new,a,b}),
+ [a,{x,y,z}] = lists:keyreplace(a, 5, [a,{x,y,z}], {no,use}),
+
+ %% Error cases.
+ {'EXIT',_} = (catch lists:keyreplace(k, 1, [], not_tuple)),
+ {'EXIT',_} = (catch lists:keyreplace(k, 0, [], {a,b})),
+ ok.
+
merge(doc) -> ["merge functions"];
merge(suite) -> [];
merge(Config) when is_list(Config) ->
@@ -1625,8 +1677,7 @@ check_stab(L, U, S, US, SS) ->
%%% Element 3 in the tuple is the position of the tuple in the list.
biglist(N) ->
- {A, B, C} = get_seed(),
- random:seed(A, B, C),
+ rand:seed(exsplus),
biglist(N, []).
biglist(0, L) ->
@@ -1642,8 +1693,7 @@ biglist(N, L) ->
%%% No sequence number.
ubiglist(N) ->
- {A, B, C} = get_seed(),
- random:seed(A, B, C),
+ rand:seed(exsplus),
ubiglist(N, []).
ubiglist(0, L) ->
@@ -1667,8 +1717,7 @@ urandom_tuple(N, I) ->
%%% sequence number.
bigfunlist(N) ->
- {A, B, C} = get_seed(),
- random:seed(A, B, C),
+ rand:seed(exsplus),
bigfunlist_1(N).
bigfunlist_1(N) when N < 30000 -> % Now (R8) max 32000 different pids.
@@ -1702,21 +1751,13 @@ make_fun(Pid) ->
fun_pid(Fun) ->
erlang:fun_info(Fun, pid).
-get_seed() ->
- case random:seed() of
- undefined ->
- erlang:timestamp();
- Tuple ->
- Tuple
- end.
-
random_tuple(N, Seq) ->
R1 = randint(N),
R2 = randint(N),
{R1, R2, Seq}.
randint(N) ->
- trunc(random:uniform() * N).
+ trunc(rand:uniform() * N).
%% The first "duplicate" is kept.
no_dups([]) ->
@@ -1778,8 +1819,7 @@ sort_loop_1(Pid) ->
end.
sloop(N) ->
- {A, B, C} = get_seed(),
- random:seed(A, B, C),
+ rand:seed(exsplus),
sloop(N, #state{}).
sloop(N, S) ->
@@ -2326,19 +2366,25 @@ sublist_3_e(Config) when is_list(Config) ->
-define(flatten_error1(X), ?line {'EXIT', _} = (catch lists:flatten(X))).
-define(flatten_error2(X,Y), ?line {'EXIT', _} = (catch lists:flatten(X,Y))).
-flatten_1(doc) -> ["flatten/1"];
-flatten_1(suite) -> [];
+%% Test lists:flatten/1,2 and lists:flatlength/1.
flatten_1(Config) when is_list(Config) ->
- ?line [] = lists:flatten([]),
- ?line [1,2] = lists:flatten([1,2]),
- ?line [1,2] = lists:flatten([1,[2]]),
- ?line [1,2] = lists:flatten([[1],2]),
- ?line [1,2] = lists:flatten([[1],[2]]),
- ?line [1,2] = lists:flatten([[1,2]]),
- ?line [a,b,c,d] = lists:flatten([[a],[b,c,[d]]]),
+ [] = lists_flatten([]),
+ [1,2] = lists_flatten([1,2]),
+ [1,2] = lists_flatten([1,[2]]),
+ [1,2] = lists_flatten([[1],2]),
+ [1,2] = lists_flatten([[1],[2]]),
+ [1,2] = lists_flatten([[1,2]]),
+ [a,b,c,d] = lists_flatten([[a],[b,c,[d]]]),
ok.
+lists_flatten(List) ->
+ Flat = lists:flatten(List),
+ Flat = lists:flatten(List, []),
+ Len = lists:flatlength(List),
+ Len = length(Flat),
+ Flat.
+
flatten_1_e(doc) -> ["flatten/1 error cases"];
flatten_1_e(suite) -> [];
flatten_1_e(Config) when is_list(Config) ->
@@ -2351,11 +2397,11 @@ flatten_1_e(Config) when is_list(Config) ->
%%% clear-cut. Right now, I think that any term should be allowed.
%%% But I also wish this function didn't exist at all.
-flatten_2(doc) -> ["flatten/2"];
-flatten_2(suite) -> [];
+%% Test lists:flatten/2.
flatten_2(Config) when is_list(Config) ->
- ?line [] = lists:flatten([]),
- ?line [a] = lists:flatten([a]),
+ [] = lists:flatten([], []),
+ [a] = lists:flatten([a], []),
+ [a,b,c,[no,flatten]] = lists:flatten([[a,[b,c]]], [[no,flatten]]),
ok.
flatten_2_e(doc) -> ["flatten/2 error cases"];
@@ -2651,3 +2697,40 @@ droplast(Config) when is_list(Config) ->
?line {'EXIT', {function_clause, _}} = (catch lists:droplast(x)),
ok.
+
+%% Briefly test the common high-order functions to ensure they
+%% are covered.
+hof(Config) when is_list(Config) ->
+ L = [1,2,3],
+ [1,4,9] = lists:map(fun(N) -> N*N end, L),
+ [1,4,5,6] = lists:flatmap(fun(1) -> [1];
+ (2) -> [];
+ (3) -> [4,5,6]
+ end, L),
+ [{1,[a]},{2,[b]},{3,[c]}] =
+ lists:keymap(fun(A) -> [A] end, 2, [{1,a},{2,b},{3,c}]),
+
+ [1,3] = lists:filter(fun(N) -> N rem 2 =:= 1 end, L),
+ FilterMapFun = fun(1) -> true;
+ (2) -> {true,42};
+ (3) -> false
+ end,
+ [1,42] = lists:filtermap(FilterMapFun, L),
+ [1,42] = lists:zf(FilterMapFun, L),
+
+ [3,2,1] = lists:foldl(fun(E, A) -> [E|A] end, [], L),
+ [1,2,3] = lists:foldr(fun(E, A) -> [E|A] end, [], L),
+ {[1,4,9],[3,2,1]} = lists:mapfoldl(fun(E, A) ->
+ {E*E,[E|A]}
+ end, [], L),
+ {[1,4,9],[1,2,3]} = lists:mapfoldr(fun(E, A) ->
+ {E*E,[E|A]}
+ end, [], L),
+
+ true = lists:any(fun(N) -> N =:= 2 end, L),
+ false = lists:any(fun(N) -> N =:= 42 end, L),
+
+ true = lists:all(fun(N) -> is_integer(N) end, L),
+ false = lists:all(fun(N) -> N rem 2 =:= 0 end, L),
+
+ ok.
diff --git a/lib/stdlib/test/proc_lib_SUITE.erl b/lib/stdlib/test/proc_lib_SUITE.erl
index 36f009eec6..f7a6a38138 100644
--- a/lib/stdlib/test/proc_lib_SUITE.erl
+++ b/lib/stdlib/test/proc_lib_SUITE.erl
@@ -28,7 +28,7 @@
init_per_group/2,end_per_group/2,
crash/1, sync_start_nolink/1, sync_start_link/1,
spawn_opt/1, sp1/0, sp2/0, sp3/1, sp4/2, sp5/1,
- hibernate/1, stop/1]).
+ hibernate/1, stop/1, t_format/1]).
-export([ otp_6345/1, init_dont_hang/1]).
-export([hib_loop/1, awaken/1]).
@@ -51,7 +51,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[crash, {group, sync_start}, spawn_opt, hibernate,
- {group, tickets}, stop].
+ {group, tickets}, stop, t_format].
groups() ->
[{tickets, [], [otp_6345, init_dont_hang]},
@@ -80,77 +80,123 @@ end_per_group(_GroupName, Config) ->
crash(Config) when is_list(Config) ->
error_logger:add_report_handler(?MODULE, self()),
- Pid = proc_lib:spawn(?MODULE, sp1, []),
- Pid ! die,
- ?line Report = receive
- {crash_report, Pid, Report0} -> Report0
- after 2000 -> test_server:fail(no_crash_report)
- end,
- ?line proc_lib:format(Report),
- ?line [PidRep, []] = Report,
- ?line {value, {initial_call,{?MODULE,sp1,[]}}} =
- lists:keysearch(initial_call, 1, PidRep),
- Self = self(),
- ?line {value, {ancestors,[Self]}} =
- lists:keysearch(ancestors, 1, PidRep),
- ?line {value, {error_info,{exit,die,_StackTrace1}}} =
- lists:keysearch(error_info, 1, PidRep),
-
- F = fun sp1/0,
- Pid1 = proc_lib:spawn(node(), F),
- Pid1 ! die,
- ?line [PidRep1, []] = receive
- {crash_report, Pid1, Report1} -> Report1
- after 2000 -> test_server:fail(no_crash_report)
- end,
- ?line {value, {initial_call,{Fmod,Fname,[]}}} =
- lists:keysearch(initial_call, 1, PidRep1),
- ?line {module,Fmod} = erlang:fun_info(F, module),
- ?line {name,Fname} = erlang:fun_info(F, name),
- ?line {value, {ancestors,[Self]}} =
- lists:keysearch(ancestors, 1, PidRep1),
- ?line {value, {error_info,{exit,die,_StackTrace2}}} =
- lists:keysearch(error_info, 1, PidRep1),
-
- Pid2 = proc_lib:spawn(?MODULE, sp2, []),
- test_server:sleep(100),
- ?line {?MODULE,sp2,[]} = proc_lib:initial_call(Pid2),
- ?line {?MODULE,sp2,0} = proc_lib:translate_initial_call(Pid2),
- Pid2 ! die,
- ?line [Pid2Rep, [{neighbour, LinkRep}]] =
- receive
- {crash_report, Pid2, Report2} -> Report2
- after 2000 -> test_server:fail(no_crash_report)
- end,
- ?line {value, {initial_call,{?MODULE,sp2,[]}}} =
- lists:keysearch(initial_call, 1, Pid2Rep),
- ?line {value, {ancestors,[Self]}} =
- lists:keysearch(ancestors, 1, Pid2Rep),
- ?line {value, {error_info,{exit,die,_StackTrace3}}} =
- lists:keysearch(error_info, 1, Pid2Rep),
- ?line {value, {initial_call,{?MODULE,sp1,[]}}} =
- lists:keysearch(initial_call, 1, LinkRep),
-
%% Make sure that we don't get a crash report if a process
%% terminates with reason 'shutdown' or reason {shutdown,Reason}.
- ?line process_flag(trap_exit, true),
- ?line Pid3 = proc_lib:spawn_link(erlang, apply,
- [fun() -> exit(shutdown) end,[]]),
+ process_flag(trap_exit, true),
+ Pid0 = proc_lib:spawn_link(erlang, apply,
+ [fun() -> exit(shutdown) end,[]]),
+ Pid1 = proc_lib:spawn_link(erlang, apply,
+ [fun() -> exit({shutdown,{a,b,c}}) end,[]]),
+
+ receive {'EXIT',Pid0,shutdown} -> ok end,
+ receive {'EXIT',Pid1,{shutdown,{a,b,c}}} -> ok end,
+ process_flag(trap_exit, false),
+ %% We expect any unexpected messages to be caught below,
+ %% so we don't have explicitly wait some time to be sure.
+
+ %% Spawn export function.
+ Pid2 = proc_lib:spawn(?MODULE, sp1, []),
+ Pid2 ! die,
+ Exp2 = [{initial_call,{?MODULE,sp1,[]}},
+ {ancestors,[self()]},
+ {error_info,{exit,die,{stacktrace}}}],
+ analyse_crash(Pid2, Exp2, []),
- ?line Pid4 = proc_lib:spawn_link(erlang, apply,
- [fun() -> exit({shutdown,{a,b,c}}) end,[]]),
+ %% Spawn fun.
+ F = fun sp1/0,
+ Pid3 = proc_lib:spawn(node(), F),
+ Pid3 ! die,
+ {module,?MODULE} = erlang:fun_info(F, module),
+ {name,Fname} = erlang:fun_info(F, name),
+ Exp3 = [{initial_call,{?MODULE,Fname,[]}},
+ {ancestors,[self()]},
+ {error_info,{exit,die,{stacktrace}}}],
+ analyse_crash(Pid3, Exp3, []),
- ?line receive {'EXIT',Pid3,shutdown} -> ok end,
- ?line receive {'EXIT',Pid4,{shutdown,{a,b,c}}} -> ok end,
- ?line process_flag(trap_exit, false),
+ %% Spawn function with neighbour.
+ Pid4 = proc_lib:spawn(?MODULE, sp2, []),
+ test_server:sleep(100),
+ {?MODULE,sp2,[]} = proc_lib:initial_call(Pid4),
+ {?MODULE,sp2,0} = proc_lib:translate_initial_call(Pid4),
+ Pid4 ! die,
+ Exp4 = [{initial_call,{?MODULE,sp2,[]}},
+ {ancestors,[self()]},
+ {error_info,{exit,die,{stacktrace}}}],
+ Links4 = [[{initial_call,{?MODULE,sp1,[]}},
+ {ancestors,[Pid4,self()]}]],
+ analyse_crash(Pid4, Exp4, Links4),
+
+ %% Make sure that we still get a crash report if the
+ %% process dictionary have been tampered with.
+
+ Pid5 = proc_lib:spawn(erlang, apply,
+ [fun() ->
+ erase(),
+ exit(abnormal)
+ end,[]]),
+ Exp5 = [{initial_call,absent},
+ {ancestors,[]},
+ {error_info,{exit,abnormal,{stacktrace}}}],
+ analyse_crash(Pid5, Exp5, []),
+
+ error_logger:delete_report_handler(?MODULE),
+ ok.
+analyse_crash(Pid, Expected0, ExpLinks) ->
+ Expected = [{pid,Pid}|Expected0],
receive
- Any ->
- ?line ?t:fail({unexpected_message,Any})
- after 2000 ->
- ok
- end.
+ {crash_report, Pid, Report} ->
+ _ = proc_lib:format(Report), %Smoke test.
+ [Crash,Links] = Report,
+ analyse_crash_1(Expected, Crash),
+ analyse_links(ExpLinks, Links);
+ Unexpected ->
+ io:format("~p\n", [Unexpected]),
+ test_server:fail(unexpected_message)
+ after 5000 ->
+ test_server:fail(no_crash_report)
+ end.
+analyse_links([H|Es], [{neighbour,N}|Links]) ->
+ analyse_crash_1(H, N),
+ analyse_links(Es, Links);
+analyse_links([], []) ->
+ ok.
+
+analyse_crash_1([{Key,absent}|T], Report) ->
+ false = lists:keymember(Key, 1, Report),
+ analyse_crash_1(T, Report);
+analyse_crash_1([{Key,Pattern}|T], Report) ->
+ case lists:keyfind(Key, 1, Report) of
+ false ->
+ io:format("~p", [Report]),
+ test_server:fail({missing_key,Key});
+ {Key,Info} ->
+ try
+ match_info(Pattern, Info)
+ catch
+ no_match ->
+ io:format("key: ~p", [Key]),
+ io:format("pattern: ~p", [Pattern]),
+ io:format("actual: ~p", [Report]),
+ test_server:fail(no_match)
+ end,
+ analyse_crash_1(T, Report)
+ end;
+analyse_crash_1([], _Report) ->
+ [].
+
+match_info(T, T) ->
+ ok;
+match_info({stacktrace}, Stk) when is_list(Stk) ->
+ ok;
+match_info([H1|T1], [H2|T2]) ->
+ match_info(H1, H2),
+ match_info(T1, T2);
+match_info(Tuple1, Tuple2) when tuple_size(Tuple1) =:= tuple_size(Tuple2) ->
+ match_info(tuple_to_list(Tuple1), tuple_to_list(Tuple2));
+match_info(_, _) ->
+ throw(no_match).
sync_start_nolink(Config) when is_list(Config) ->
_Pid = spawn_link(?MODULE, sp5, [self()]),
@@ -301,6 +347,7 @@ hibernate(Config) when is_list(Config) ->
?line {value,{initial_call,{?MODULE,hib_loop,[_]}}} =
lists:keysearch(initial_call, 1, Report),
+ error_logger:delete_report_handler(?MODULE),
ok.
hib_loop(LoopData) ->
@@ -364,7 +411,7 @@ init_dont_hang(Config) when is_list(Config) ->
end.
init_dont_hang_init(_Parent) ->
- 1 = 2.
+ error(bad_init).
%% Test proc_lib:stop/1,3
stop(_Config) ->
@@ -448,10 +495,55 @@ stop(_Config) ->
ok.
system_terminate(crash,_Parent,_Deb,_State) ->
- 1 = 2;
+ error({badmatch,2});
system_terminate(Reason,_Parent,_Deb,_State) ->
exit(Reason).
+
+t_format(_Config) ->
+ error_logger:tty(false),
+ try
+ t_format()
+ after
+ error_logger:tty(true)
+ end,
+ ok.
+
+t_format() ->
+ error_logger:add_report_handler(?MODULE, self()),
+ Pid = proc_lib:spawn(fun t_format_looper/0),
+ HugeData = gb_sets:from_list(lists:seq(1, 100)),
+ Pid ! {die,HugeData},
+ Report = receive
+ {crash_report, Pid, Report0} -> Report0
+ end,
+ Usz = do_test_format(Report, unlimited),
+ Tsz = do_test_format(Report, 20),
+
+ if
+ Tsz >= Usz ->
+ ?t:fail();
+ true ->
+ ok
+ end,
+
+ ok.
+
+do_test_format(Report, Depth) ->
+ io:format("*** Depth = ~p", [Depth]),
+ S0 = proc_lib:format(Report, latin1, Depth),
+ S = lists:flatten(S0),
+ io:put_chars(S),
+ length(S).
+
+t_format_looper() ->
+ receive
+ {die,Data} ->
+ exit(Data);
+ _ ->
+ t_format_looper()
+ end.
+
%%-----------------------------------------------------------------
%% The error_logger handler used.
%%-----------------------------------------------------------------
diff --git a/lib/stdlib/test/qlc_SUITE.erl b/lib/stdlib/test/qlc_SUITE.erl
index 72216bfa0d..52fdb69b73 100644
--- a/lib/stdlib/test/qlc_SUITE.erl
+++ b/lib/stdlib/test/qlc_SUITE.erl
@@ -74,6 +74,7 @@
otp_5644/1, otp_5195/1, otp_6038_bug/1, otp_6359/1, otp_6562/1,
otp_6590/1, otp_6673/1, otp_6964/1, otp_7114/1, otp_7238/1,
otp_7232/1, otp_7552/1, otp_6674/1, otp_7714/1, otp_11758/1,
+ otp_12946/1,
manpage/1,
@@ -143,7 +144,7 @@ groups() ->
{tickets, [],
[otp_5644, otp_5195, otp_6038_bug, otp_6359, otp_6562,
otp_6590, otp_6673, otp_6964, otp_7114, otp_7232,
- otp_7238, otp_7552, otp_6674, otp_7714, otp_11758]},
+ otp_7238, otp_7552, otp_6674, otp_7714, otp_11758, otp_12946]},
{compat, [], [backward, forward]}].
init_per_suite(Config) ->
@@ -7154,6 +7155,18 @@ otp_6674(Config) when is_list(Config) ->
?line run(Config, Ts).
+otp_12946(doc) ->
+ ["Syntax error."];
+otp_12946(suite) -> [];
+otp_12946(Config) when is_list(Config) ->
+ Text =
+ <<"-export([init/0]).
+ init() ->
+ ok.
+ y">>,
+ {errors,[{4,erl_parse,_}],[]} = compile_file(Config, Text, []),
+ ok.
+
manpage(doc) ->
"Examples from qlc(3).";
manpage(suite) -> [];
diff --git a/lib/stdlib/test/queue_SUITE.erl b/lib/stdlib/test/queue_SUITE.erl
index c965a8b218..5165ac3a3a 100644
--- a/lib/stdlib/test/queue_SUITE.erl
+++ b/lib/stdlib/test/queue_SUITE.erl
@@ -470,7 +470,7 @@ oops(suite) ->
oops(Config) when is_list(Config) ->
?line N = 3142,
?line Optab = optab(),
- ?line Seed0 = random:seed0(),
+ ?line Seed0 = rand:seed(exsplus, {1,2,4}),
?line {Is,Seed} = random_list(N, tuple_size(Optab), Seed0, []),
?line io:format("~p ", [Is]),
?line QA = queue:new(),
@@ -562,20 +562,20 @@ args([], _, Seed, R) ->
args([q|Ts], [Q|Qs]=Qss, Seed, R) ->
args(Ts, if Qs =:= [] -> Qss; true -> Qs end, Seed, [Q|R]);
args([l|Ts], Qs, Seed0, R) ->
- {N,Seed1} = random:uniform_s(17, Seed0),
+ {N,Seed1} = rand:uniform_s(17, Seed0),
{L,Seed} = random_list(N, 4711, Seed1, []),
args(Ts, Qs, Seed, [L|R]);
args([t|Ts], Qs, Seed0, R) ->
- {T,Seed} = random:uniform_s(4711, Seed0),
+ {T,Seed} = rand:uniform_s(4711, Seed0),
args(Ts, Qs, Seed, [T|R]);
args([n|Ts], Qs, Seed0, R) ->
- {N,Seed} = random:uniform_s(17, Seed0),
+ {N,Seed} = rand:uniform_s(17, Seed0),
args(Ts, Qs, Seed, [N|R]).
random_list(0, _, Seed, R) ->
{R,Seed};
random_list(N, M, Seed0, R) ->
- {X,Seed} = random:uniform_s(M, Seed0),
+ {X,Seed} = rand:uniform_s(M, Seed0),
random_list(N-1, M, Seed, [X|R]).
call(Func, As) ->
diff --git a/lib/stdlib/test/rand_SUITE.erl b/lib/stdlib/test/rand_SUITE.erl
index b03caebe91..03b5ce1a25 100644
--- a/lib/stdlib/test/rand_SUITE.erl
+++ b/lib/stdlib/test/rand_SUITE.erl
@@ -25,7 +25,9 @@
]).
-export([interval_int/1, interval_float/1, seed/1,
- api_eq/1, reference/1, basic_stats/1,
+ api_eq/1, reference/1,
+ basic_stats_uniform_1/1, basic_stats_uniform_2/1,
+ basic_stats_normal/1,
plugin/1, measure/1
]).
@@ -51,11 +53,13 @@ all() ->
[seed, interval_int, interval_float,
api_eq,
reference,
- basic_stats,
+ {group, basic_stats},
plugin, measure
].
-groups() -> [].
+groups() ->
+ [{basic_stats, [parallel],
+ [basic_stats_uniform_1, basic_stats_uniform_2, basic_stats_normal]}].
init_per_suite(Config) -> Config.
end_per_suite(_Config) -> ok.
@@ -122,6 +126,9 @@ seed_1(Alg) ->
false = (S1 =:= rand:seed_s(Alg)),
%% Negative integers works
_ = rand:seed_s(Alg, {-1,-1,-1}),
+ %% Check that export_seed/1 returns 'undefined' if there is no seed
+ erase(rand_seed),
+ undefined = rand:export_seed(),
%% Other term do not work
{'EXIT', _} = (catch rand:seed_s(foobar, os:timestamp())),
@@ -291,14 +298,19 @@ gen(_, _, Acc) -> lists:reverse(Acc).
%% The algorithms must have good properties to begin with
%%
-basic_stats(doc) -> ["Check that the algorithms generate sound values."];
-basic_stats(suite) -> [];
-basic_stats(Config) when is_list(Config) ->
- io:format("Testing uniform~n",[]),
+%% Check that the algorithms generate sound values.
+
+basic_stats_uniform_1(Config) when is_list(Config) ->
[basic_uniform_1(?LOOP, rand:seed_s(Alg), 0.0, array:new([{default, 0}]))
|| Alg <- algs()],
+ ok.
+
+basic_stats_uniform_2(Config) when is_list(Config) ->
[basic_uniform_2(?LOOP, rand:seed_s(Alg), 0, array:new([{default, 0}]))
|| Alg <- algs()],
+ ok.
+
+basic_stats_normal(Config) when is_list(Config) ->
io:format("Testing normal~n",[]),
[basic_normal_1(?LOOP, rand:seed_s(Alg), 0, 0) || Alg <- algs()],
ok.
diff --git a/lib/stdlib/test/random_iolist.erl b/lib/stdlib/test/random_iolist.erl
index 9a0f034e72..6da7da04de 100644
--- a/lib/stdlib/test/random_iolist.erl
+++ b/lib/stdlib/test/random_iolist.erl
@@ -36,7 +36,7 @@ run2(Iter,Fun1,Fun2) ->
compare2(Iter,Fun1,Fun2).
random_byte() ->
- random:uniform(256) - 1.
+ rand:uniform(256) - 1.
random_list(0,Acc) ->
Acc;
@@ -45,7 +45,7 @@ random_list(N,Acc) ->
random_binary(N) ->
B = list_to_binary(random_list(N,[])),
- case {random:uniform(2),size(B)} of
+ case {rand:uniform(2),size(B)} of
{2,M} when M > 1 ->
S = M-1,
<<_:3,C:S/binary,_:5>> = B,
@@ -57,7 +57,7 @@ random_list(N) ->
random_list(N,[]).
front() ->
- case random:uniform(10) of
+ case rand:uniform(10) of
10 ->
false;
_ ->
@@ -65,7 +65,7 @@ front() ->
end.
any_type() ->
- case random:uniform(10) of
+ case rand:uniform(10) of
1 ->
list;
2 ->
@@ -77,7 +77,7 @@ any_type() ->
end.
tail_type() ->
- case random:uniform(5) of
+ case rand:uniform(5) of
1 ->
list;
2 ->
@@ -90,9 +90,9 @@ random_length(N) ->
UpperLimit = 255,
case N of
M when M > UpperLimit ->
- random:uniform(UpperLimit+1) - 1;
+ rand:uniform(UpperLimit+1) - 1;
_ ->
- random:uniform(N+1) - 1
+ rand:uniform(N+1) - 1
end.
random_iolist(0,Acc) ->
@@ -139,7 +139,7 @@ random_iolist(N) ->
standard_seed() ->
- random:seed(1201,855653,380975).
+ rand:seed(exsplus, {1201,855653,380975}).
do_comp(List,F1,F2) ->
X = F1(List),
diff --git a/lib/stdlib/test/random_unicode_list.erl b/lib/stdlib/test/random_unicode_list.erl
index ecafe42318..3bc86a8430 100644
--- a/lib/stdlib/test/random_unicode_list.erl
+++ b/lib/stdlib/test/random_unicode_list.erl
@@ -85,7 +85,7 @@ int_to_utf32_little(I) ->
id(I) -> I.
random_char() ->
- case random:uniform(16#10FFFF+1) - 1 of
+ case rand:uniform(16#10FFFF+1) - 1 of
X when X >= 16#D800,
X =< 16#DFFF ->
random_char();
@@ -116,13 +116,13 @@ random_binary(N,Enc) ->
int_to(Enc,X)
end,
L)),
- case {random:uniform(3),size(B)} of
+ case {rand:uniform(3),size(B)} of
{2,M} when M > 1 ->
B2 = id(<<1:3,B/binary,1:5>>),
<<_:3,C:M/binary,_:5>> = B2,
C;
{3,M} when M > 1 ->
- X = random:uniform(M+1)-1,
+ X = rand:uniform(M+1)-1,
<<B1:X/binary,B2/binary>> = B,
[B1,B2];
_ ->
@@ -132,7 +132,7 @@ random_list(N) ->
random_list(N,[]).
front() ->
- case random:uniform(10) of
+ case rand:uniform(10) of
10 ->
false;
_ ->
@@ -140,7 +140,7 @@ front() ->
end.
any_type() ->
- case random:uniform(10) of
+ case rand:uniform(10) of
1 ->
list;
2 ->
@@ -152,7 +152,7 @@ any_type() ->
end.
tail_type() ->
- case random:uniform(5) of
+ case rand:uniform(5) of
1 ->
list;
2 ->
@@ -165,9 +165,9 @@ random_length(N) ->
UpperLimit = 255,
case N of
M when M > UpperLimit ->
- random:uniform(UpperLimit+1) - 1;
+ rand:uniform(UpperLimit+1) - 1;
_ ->
- random:uniform(N+1) - 1
+ rand:uniform(N+1) - 1
end.
random_unicode_list(0,Acc,_Enc) ->
@@ -214,7 +214,7 @@ random_unicode_list(N,Enc) ->
standard_seed() ->
- random:seed(1201,855653,380975).
+ rand:seed(exsplus, {1201,855653,380975}).
do_comp(List,F1,F2) ->
X = F1(List),
diff --git a/lib/stdlib/test/re_SUITE.erl b/lib/stdlib/test/re_SUITE.erl
index b8c20d9745..d78d6153da 100644
--- a/lib/stdlib/test/re_SUITE.erl
+++ b/lib/stdlib/test/re_SUITE.erl
@@ -28,7 +28,7 @@
pcre_compile_workspace_overflow/1,re_infinite_loop/1,
re_backwards_accented/1,opt_dupnames/1,opt_all_names/1,inspect/1,
opt_no_start_optimize/1,opt_never_utf/1,opt_ucp/1,
- match_limit/1,sub_binaries/1]).
+ match_limit/1,sub_binaries/1,copt/1]).
-include_lib("test_server/include/test_server.hrl").
-include_lib("kernel/include/file.hrl").
@@ -319,32 +319,26 @@ replace_return(doc) ->
["Tests return options of replace together with global searching"];
replace_return(Config) when is_list(Config) ->
Dog = ?t:timetrap(?t:minutes(3)),
- ?line {'EXIT',{badarg,_}} = (catch re:replace("na","(a","")),
- ?line <<"nasse">> = re:replace(<<"nisse">>,"i","a",[{return,binary}]),
- ?line <<"ABCÅXABCXA">> = re:replace("ABC\305abcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,binary}]),
-
- ?line [<<"ABCÅ">>,
- <<"X">>,
- <<"ABC">>,
- <<"X">> |
- <<"A">> ] =
- re:replace("ABCÅabcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,iodata}]),
- ?line "ABCÅXABCXA" = re:replace("ABCÅabcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,list},unicode]),
- ?line <<65,66,67,195,133,88,65,66,67,88,65>> = re:replace("ABCÅabcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,binary},unicode]),
- ?line <<65,66,67,195,133,88,65,66,67,97,98,99,100,65>> = re:replace("ABCÅabcdABCabcdA","a(?<FOO>bcd)","X",[{return,binary},unicode]),
- ?line <<"iXk">> = re:replace("abcdefghijk","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\9X",[{return,binary}]),
- ?line <<"jXk">> = re:replace("abcdefghijk","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\10X",[{return,binary}]),
- ?line <<"Xk">> = re:replace("abcdefghijk","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\11X",[{return,binary}]),
- ?line <<"9X1">> = re:replace("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g9X",[{return,binary}]),
- ?line <<"0X1">> = re:replace("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g10X",[{return,binary}]),
- ?line <<"X1">> = re:replace("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g11X",[{return,binary}]),
- ?line <<"971">> = re:replace("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g{9}7",[{return,binary}]),
- ?line <<"071">> = re:replace("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g{10}7",[{return,binary}]),
- ?line <<"71">> = re:replace("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g{11}7",[{return,binary}]),
- ?line "a\x{400}bcX" = re:replace("a\x{400}bcd","d","X",[global,{return,list},unicode]),
- ?line <<"a",208,128,"bcX">> = re:replace("a\x{400}bcd","d","X",[global,{return,binary},unicode]),
- ?line "a\x{400}bcd" = re:replace("a\x{400}bcd","Z","X",[global,{return,list},unicode]),
- ?line <<"a",208,128,"bcd">> = re:replace("a\x{400}bcd","Z","X",[global,{return,binary},unicode]),
+ {'EXIT',{badarg,_}} = (catch re:replace("na","(a","")),
+ ok = replacetest(<<"nisse">>,"i","a",[{return,binary}],<<"nasse">>),
+ ok = replacetest("ABC\305abcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,binary}],<<"ABCÅXABCXA">>),
+ ok = replacetest("ABCÅabcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,iodata}],[<<"ABCÅ">>,<<"X">>,<<"ABC">>,<<"X">>|<<"A">>]),
+ ok = replacetest("ABCÅabcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,list},unicode],"ABCÅXABCXA"),
+ ok = replacetest("ABCÅabcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,binary},unicode],<<65,66,67,195,133,88,65,66,67,88,65>>),
+ ok = replacetest("ABCÅabcdABCabcdA","a(?<FOO>bcd)","X",[{return,binary},unicode],<<65,66,67,195,133,88,65,66,67,97,98,99,100,65>>),
+ ok = replacetest("abcdefghijk","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\9X",[{return,binary}],<<"iXk">>),
+ ok = replacetest("abcdefghijk","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\10X",[{return,binary}],<<"jXk">>),
+ ok = replacetest("abcdefghijk","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\11X",[{return,binary}],<<"Xk">>),
+ ok = replacetest("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g9X",[{return,binary}],<<"9X1">>),
+ ok = replacetest("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g10X",[{return,binary}],<<"0X1">>),
+ ok = replacetest("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g11X",[{return,binary}],<<"X1">>),
+ ok = replacetest("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g{9}7",[{return,binary}],<<"971">>),
+ ok = replacetest("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g{10}7",[{return,binary}],<<"071">>),
+ ok = replacetest("12345678901","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\g{11}7",[{return,binary}],<<"71">>),
+ ok = replacetest("a\x{400}bcd","d","X",[global,{return,list},unicode],"a\x{400}bcX"),
+ ok = replacetest("a\x{400}bcd","d","X",[global,{return,binary},unicode],<<"a",208,128,"bcX">>),
+ ok = replacetest("a\x{400}bcd","Z","X",[global,{return,list},unicode],"a\x{400}bcd"),
+ ok = replacetest("a\x{400}bcd","Z","X",[global,{return,binary},unicode],<<"a",208,128,"bcd">>),
?t:timetrap_cancel(Dog),
ok.
@@ -389,6 +383,35 @@ crtest(Subject,RE,Options,true,Result) ->
error
end.
+replacetest(Subject,RE,Replacement,Options,Result) ->
+ Result = re:replace(Subject,RE,Replacement,Options),
+ {CompileOptions,ReplaceOptions} = lists:partition(fun copt/1, Options),
+ {ok,MP} = re:compile(RE,CompileOptions),
+ Result = re:replace(Subject,MP,Replacement,ReplaceOptions),
+ ok.
+
+splittest(Subject,RE,Options,Result) ->
+ Result = re:split(Subject,RE,Options),
+ {CompileOptions,SplitOptions} = lists:partition(fun copt/1, Options),
+ {ok,MP} = re:compile(RE,CompileOptions),
+ Result = re:split(Subject,MP,SplitOptions),
+ ok.
+
+copt(caseless) -> true;
+copt(no_start_optimize) -> true;
+copt(never_utf) -> true;
+copt(ucp) -> true;
+copt(dollar_endonly) -> true;
+copt(dotall) -> true;
+copt(extended) -> true;
+copt(firstline) -> true;
+copt(multiline) -> true;
+copt(no_auto_capture) -> true;
+copt(dupnames) -> true;
+copt(ungreedy) -> true;
+copt(unicode) -> true;
+copt(_) -> false.
+
split_autogen(doc) ->
["Test split with autogenerated erlang module"];
split_autogen(Config) when is_list(Config) ->
@@ -401,43 +424,23 @@ split_options(doc) ->
["Test special options to split."];
split_options(Config) when is_list(Config) ->
Dog = ?t:timetrap(?t:minutes(1)),
- ?line [[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>]] = re:split("a b c ","( )",[group,trim]),
- ?line [[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>]] = re:split("a b c ","( )",[group,{parts,0}]),
- ?line [[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>],[<<>>]] =
- re:split("a b c ","( )",[{parts,infinity},group]),
- ?line [[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>],[<<>>]] =
- re:split("a b c ","( )",[group]),
- ?line [[<<>>,<<" ">>],[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],
- [<<"c">>,<<" ">>],[<<"d">>,<<" ">>]] =
- re:split(" a b c d ","( +)",[group,trim]),
- ?line [[<<>>,<<" ">>],[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],
- [<<"c">>,<<" ">>],[<<"d">>,<<" ">>]] =
- re:split(" a b c d ","( +)",[{parts,0},group]),
- ?line [[<<>>,<<" ">>],[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],
- [<<"c">>,<<" ">>],[<<"d">>,<<" ">>],[<<>>]] =
- re:split(" a b c d ","( +)",[{parts,infinity},group]),
- ?line [[<<"a">>,<<" ">>],[<<"b c d">>]] =
- re:split("a b c d","( +)",[{parts,2},group]),
- ?line [[[967]," "],["b c d"]] =
- re:split([967]++" b c d","( +)",
- [{parts,2},group,{return,list},unicode]),
- ?line [[<<207,135>>,<<" ">>],[<<"b c d">>]] =
- re:split([967]++" b c d","( +)",
- [{parts,2},group,{return,binary},unicode]),
- ?line {'EXIT',{badarg,_}} =
- (catch re:split([967]++" b c d","( +)",
- [{parts,2},group,{return,binary}])),
- ?line {'EXIT',{badarg,_}} =
- (catch re:split("a b c d","( +)",[{parts,-2}])),
- ?line {'EXIT',{badarg,_}} =
- (catch re:split("a b c d","( +)",[{parts,banan}])),
- ?line {'EXIT',{badarg,_}} =
- (catch re:split("a b c d","( +)",[{capture,all}])),
- ?line {'EXIT',{badarg,_}} =
- (catch re:split("a b c d","( +)",[{capture,[],binary}])),
+ ok = splittest("a b c ","( )",[group,trim],[[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>]]),
+ ok = splittest("a b c ","( )",[group,{parts,0}],[[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>]]),
+ ok = splittest("a b c ","( )",[{parts,infinity},group],[[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>],[<<>>]]),
+ ok = splittest("a b c ","( )",[group],[[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>],[<<>>]]),
+ ok = splittest(" a b c d ","( +)",[group,trim],[[<<>>,<<" ">>],[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>],[<<"d">>,<<" ">>]]),
+ ok = splittest(" a b c d ","( +)",[{parts,0},group],[[<<>>,<<" ">>],[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>],[<<"d">>,<<" ">>]]),
+ ok = splittest(" a b c d ","( +)",[{parts,infinity},group],[[<<>>,<<" ">>],[<<"a">>,<<" ">>],[<<"b">>,<<" ">>],[<<"c">>,<<" ">>],[<<"d">>,<<" ">>],[<<>>]]),
+ ok = splittest("a b c d","( +)",[{parts,2},group],[[<<"a">>,<<" ">>],[<<"b c d">>]]),
+ ok = splittest([967]++" b c d","( +)",[{parts,2},group,{return,list},unicode],[[[967]," "],["b c d"]]),
+ ok = splittest([967]++" b c d","( +)",[{parts,2},group,{return,binary},unicode],[[<<207,135>>,<<" ">>],[<<"b c d">>]]),
+ {'EXIT',{badarg,_}} = (catch re:split([967]++" b c d","( +)",[{parts,2},group,{return,binary}])),
+ {'EXIT',{badarg,_}} = (catch re:split("a b c d","( +)",[{parts,-2}])),
+ {'EXIT',{badarg,_}} = (catch re:split("a b c d","( +)",[{parts,banan}])),
+ {'EXIT',{badarg,_}} = (catch re:split("a b c d","( +)",[{capture,all}])),
+ {'EXIT',{badarg,_}} = (catch re:split("a b c d","( +)",[{capture,[],binary}])),
% Parts 0 is equal to no parts specification (implicit strip)
- ?line ["a"," ","b"," ","c"," ","d"] =
- re:split("a b c d","( *)",[{parts,0},{return,list}]),
+ ok = splittest("a b c d","( *)",[{parts,0},{return,list}],["a"," ","b"," ","c"," ","d"]),
?t:timetrap_cancel(Dog),
ok.
diff --git a/lib/stdlib/test/run_pcre_tests.erl b/lib/stdlib/test/run_pcre_tests.erl
index 1fdc777470..b7d1df39b8 100644
--- a/lib/stdlib/test/run_pcre_tests.erl
+++ b/lib/stdlib/test/run_pcre_tests.erl
@@ -1083,7 +1083,7 @@ dumponesplit(F,{RE,Line,O,TS}) ->
%% Generate replacement tests from indatafile,
%% you will need perl on the machine
gen_repl_test(OneFile) ->
- random:seed(1219,687731,62804),
+ rand:seed(exsplus, {1219,687731,62804}),
{ok,Bin} = file:read_file(OneFile),
Lines = splitfile(0,Bin,1),
Structured = stru(Lines),
@@ -1237,15 +1237,15 @@ btr(_) ->
ranchar() ->
- case random:uniform(10) of
+ case rand:uniform(10) of
9 -> $&;
10 -> <<"\\1">>;
N when N < 5 ->
- random:uniform($Z-$A)+$A-1;
+ rand:uniform($Z-$A)+$A-1;
M when M < 9 ->
- random:uniform($z-$a)+$a-1
+ rand:uniform($z-$a)+$a-1
end.
ranstring() ->
- iolist_to_binary([ranchar() || _ <- lists:duplicate(random:uniform(20),0) ]).
+ iolist_to_binary([ranchar() || _ <- lists:duplicate(rand:uniform(20),0) ]).
diff --git a/lib/stdlib/test/select_SUITE.erl b/lib/stdlib/test/select_SUITE.erl
index ead64ffc75..6796676179 100644
--- a/lib/stdlib/test/select_SUITE.erl
+++ b/lib/stdlib/test/select_SUITE.erl
@@ -212,11 +212,10 @@ init_random(Config) ->
{ok,[X]} ->
X;
_ ->
- {A,B,C} = erlang:timestamp(),
- random:seed(A,B,C),
- get(random_seed)
+ rand:seed(exsplus),
+ rand:export_seed()
end,
- put(random_seed,Seed),
+ rand:seed(Seed),
{ok, F} = file:open(filename:join([WriteDir, "last_random_seed2.txt"]),
[write]),
io:format(F,"~p. ~n",[Seed]),
@@ -224,11 +223,11 @@ init_random(Config) ->
ok.
create_random_key(N,Type) ->
- gen_key(random:uniform(N),Type).
+ gen_key(rand:uniform(N),Type).
create_pb_key(N,list) ->
- X = random:uniform(N),
- case random:uniform(4) of
+ X = rand:uniform(N),
+ case rand:uniform(4) of
3 -> {[X, X+1, '_'], fun([Z,Z1,P1]) ->
[Z,Z1,P1] =:= [X,X+1,P1] end};
2 -> {[X, '_', '_'], fun([Z,P1,P2]) -> [Z,P1,P2] =:= [X,P1,P2] end};
@@ -237,14 +236,14 @@ create_pb_key(N,list) ->
_ -> {[X, '$1', '$2'], fun([Z,P1,P2]) -> [Z,P1,P2] =:= [X,P1,P2] end}
end;
create_pb_key(N, tuple) ->
- X = random:uniform(N),
- case random:uniform(2) of
+ X = rand:uniform(N),
+ case rand:uniform(2) of
1 -> {{X, X+1, '$1'},fun({Z,Z1,P1}) -> {Z,Z1,P1} =:= {X,X+1,P1} end};
_ -> {{X, '$1', '$2'},fun({Z,P1,P2}) -> {Z,P1,P2} =:= {X,P1,P2} end}
end;
create_pb_key(N, complex) ->
- X = random:uniform(N),
- case random:uniform(2) of
+ X = rand:uniform(N),
+ case rand:uniform(2) of
1 -> {{[X, X+1], '$1'}, fun({[Z,Z1],P1}) ->
{[Z,Z1],P1} =:= {[X,X+1],P1} end};
_ -> {{[X, '$1'], '$2'},fun({[Z,P1],P2}) ->
diff --git a/lib/stdlib/test/sets_SUITE.erl b/lib/stdlib/test/sets_SUITE.erl
index 972a812072..e7fc5595a9 100644
--- a/lib/stdlib/test/sets_SUITE.erl
+++ b/lib/stdlib/test/sets_SUITE.erl
@@ -107,9 +107,9 @@ add_element_del([H|T], M, S, Del, []) ->
add_element_del(T, M, M(add_element, {H,S}), Del, [H]);
add_element_del([H|T], M, S0, Del, Inserted) ->
S1 = M(add_element, {H,S0}),
- case random:uniform(3) of
+ case rand:uniform(3) of
1 ->
- OldEl = lists:nth(random:uniform(length(Inserted)), Inserted),
+ OldEl = lists:nth(rand:uniform(length(Inserted)), Inserted),
S = M(del_element, {OldEl,S1}),
add_element_del(T, M, S, [OldEl|Del], [H|Inserted]);
_ ->
@@ -438,7 +438,7 @@ iterate_1(M) ->
M(empty, []).
iterate_2(M) ->
- random:seed(1, 2, 42),
+ rand:seed(exsplus, {1,2,42}),
iter_set(M, 1000).
iter_set(_M, 0) ->
@@ -447,7 +447,7 @@ iter_set(M, N) ->
L = [I || I <- lists:seq(1, N)],
T = M(from_list, L),
L = lists:reverse(iterate_set(M, T)),
- R = random:uniform(N),
+ R = rand:uniform(N),
S = lists:reverse(iterate_set(M, R, T)),
S = [E || E <- L, E >= R],
iter_set(M, N-1).
@@ -481,7 +481,7 @@ sets_mods() ->
test_all(Tester) ->
Res = [begin
- random:seed(1, 2, 42),
+ rand:seed(exsplus, {1,2,42}),
S = Tester(M),
{M(size, S),lists:sort(M(to_list, S))}
end || M <- sets_mods()],
@@ -492,7 +492,7 @@ test_all([{Low,High}|T], Tester) ->
test_all([Sz|T], Tester) when is_integer(Sz) ->
List = rnd_list(Sz),
Res = [begin
- random:seed(19, 2, Sz),
+ rand:seed(exsplus, {19,2,Sz}),
S = Tester(List, M),
{M(size, S),lists:sort(M(to_list, S))}
end || M <- sets_mods()],
@@ -512,10 +512,10 @@ rnd_list(Sz) ->
rnd_list_1(Sz, []).
atomic_rnd_term() ->
- case random:uniform(3) of
- 1 -> list_to_atom(integer_to_list($\s+random:uniform(94))++"rnd");
- 2 -> random:uniform();
- 3 -> random:uniform(50)-37
+ case rand:uniform(3) of
+ 1 -> list_to_atom(integer_to_list($\s+rand:uniform(94))++"rnd");
+ 2 -> rand:uniform();
+ 3 -> rand:uniform(50)-37
end.
rnd_list_1(0, Acc) -> Acc;
@@ -543,7 +543,7 @@ remove_some(List0, P) ->
end.
remove_some([H|T], P, Acc) ->
- case random:uniform() of
+ case rand:uniform() of
F when F < P -> %Remove.
remove_some(T, P, Acc);
_ ->
diff --git a/lib/stdlib/test/timer_SUITE.erl b/lib/stdlib/test/timer_SUITE.erl
index 057d82fb65..10dcfad76f 100644
--- a/lib/stdlib/test/timer_SUITE.erl
+++ b/lib/stdlib/test/timer_SUITE.erl
@@ -80,8 +80,6 @@ report_result(Error) -> ?line test_server:fail(Error).
big_test(N) ->
C = start_collect(),
system_time(), system_time(), system_time(),
- random:seed(erlang:timestamp()),
- random:uniform(100),random:uniform(100),random:uniform(100),
big_loop(C, N, []),
@@ -127,17 +125,17 @@ big_loop(C, N, Pids) ->
after 0 ->
%% maybe start an interval timer test
- Pids1 = maybe_start_i_test(Pids, C, random:uniform(4)),
+ Pids1 = maybe_start_i_test(Pids, C, rand:uniform(4)),
%% start 1-4 "after" tests
- Pids2 = start_after_test(Pids1, C, random:uniform(4)),
+ Pids2 = start_after_test(Pids1, C, rand:uniform(4)),
%%Pids2=Pids1,
%% wait a little while
- timer:sleep(random:uniform(200)*3),
+ timer:sleep(rand:uniform(200)*3),
%% spawn zero, one or two nrev to get some load ;-/
- Pids3 = start_nrev(Pids2, random:uniform(100)),
+ Pids3 = start_nrev(Pids2, rand:uniform(100)),
big_loop(C, N-1, Pids3)
end.
@@ -148,20 +146,20 @@ start_nrev(Pids, N) when N < 25 ->
start_nrev(Pids, N) when N < 75 ->
[spawn_link(timer_SUITE, do_nrev, [1])|Pids];
start_nrev(Pids, _N) ->
- NrevPid1 = spawn_link(timer_SUITE, do_nrev, [random:uniform(1000)*10]),
+ NrevPid1 = spawn_link(timer_SUITE, do_nrev, [rand:uniform(1000)*10]),
NrevPid2 = spawn_link(timer_SUITE, do_nrev, [1]),
[NrevPid1,NrevPid2|Pids].
start_after_test(Pids, C, 1) ->
- TO1 = random:uniform(100)*47,
+ TO1 = rand:uniform(100)*47,
[s_a_t(C, TO1)|Pids];
start_after_test(Pids, C, 2) ->
- TO1 = random:uniform(100)*47,
- TO2 = TO1 div random:uniform(3) + 101,
+ TO1 = rand:uniform(100)*47,
+ TO2 = TO1 div rand:uniform(3) + 101,
[s_a_t(C, TO1),s_a_t(C, TO2)|Pids];
start_after_test(Pids, C, N) ->
- TO1 = random:uniform(100)*47,
+ TO1 = rand:uniform(100)*47,
start_after_test([s_a_t(C, TO1)|Pids], C, N-1).
s_a_t(C, TimeOut) ->
@@ -187,8 +185,8 @@ a_t(C, TimeOut) ->
maybe_start_i_test(Pids, C, 1) ->
%% ok do it
- TOI = random:uniform(53)*49,
- CountI = random:uniform(10) + 3, % at least 4 times
+ TOI = rand:uniform(53)*49,
+ CountI = rand:uniform(10) + 3, % at least 4 times
[spawn_link(timer_SUITE, i_t, [C, TOI, CountI])|Pids];
maybe_start_i_test(Pids, _C, _) ->
Pids.
diff --git a/lib/stdlib/test/zip_SUITE.erl b/lib/stdlib/test/zip_SUITE.erl
index 9d48d092cf..c275053691 100644
--- a/lib/stdlib/test/zip_SUITE.erl
+++ b/lib/stdlib/test/zip_SUITE.erl
@@ -556,9 +556,10 @@ unzip_to_binary(doc) ->
unzip_to_binary(Config) when is_list(Config) ->
DataDir = ?config(data_dir, Config),
PrivDir = ?config(priv_dir, Config),
+ WorkDir = filename:join(PrivDir, "unzip_to_binary"),
+ _ = file:make_dir(WorkDir),
- delete_all_in(PrivDir),
- file:set_cwd(PrivDir),
+ ok = file:set_cwd(WorkDir),
Long = filename:join(DataDir, "abc.zip"),
%% Unzip a zip file into a binary
@@ -569,7 +570,7 @@ unzip_to_binary(Config) when is_list(Config) ->
end, FBList),
%% Make sure no files created in cwd
- {ok,[]} = file:list_dir(PrivDir),
+ {ok,[]} = file:list_dir(WorkDir),
ok.
@@ -578,8 +579,10 @@ zip_to_binary(doc) ->
zip_to_binary(Config) when is_list(Config) ->
DataDir = ?config(data_dir, Config),
PrivDir = ?config(priv_dir, Config),
- delete_all_in(PrivDir),
- file:set_cwd(PrivDir),
+ WorkDir = filename:join(PrivDir, "zip_to_binary"),
+ _ = file:make_dir(WorkDir),
+
+ file:set_cwd(WorkDir),
FileName = "abc.txt",
ZipName = "t.zip",
FilePath = filename:join(DataDir, FileName),
@@ -589,7 +592,7 @@ zip_to_binary(Config) when is_list(Config) ->
{ok, {ZipName, ZipB}} = zip:zip(ZipName, [FileName], [memory]),
%% Make sure no files created in cwd
- {ok,[FileName]} = file:list_dir(PrivDir),
+ {ok,[FileName]} = file:list_dir(WorkDir),
%% Zip to a file
{ok, ZipName} = zip:zip(ZipName, [FileName]),
@@ -696,11 +699,6 @@ do_delete_files([Item|Rest], Cnt) ->
end,
do_delete_files(Rest, Cnt + DelCnt).
-delete_all_in(Dir) ->
- {ok, Files} = file:list_dir(Dir),
- delete_files(lists:map(fun(F) -> filename:join(Dir,F) end,
- Files)).
-
compress_control(doc) ->
["Test control of which files that should be compressed"];
compress_control(suite) -> [];