diff options
Diffstat (limited to 'lib/stdlib/test')
19 files changed, 551 insertions, 379 deletions
diff --git a/lib/stdlib/test/base64_SUITE.erl b/lib/stdlib/test/base64_SUITE.erl index c64a961ffa..7b8650f224 100644 --- a/lib/stdlib/test/base64_SUITE.erl +++ b/lib/stdlib/test/base64_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2011. All Rights Reserved. +%% Copyright Ericsson AB 2007-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -20,7 +20,6 @@ -module(base64_SUITE). -include_lib("common_test/include/ct.hrl"). --include("test_server_line.hrl"). %% Test server specific exports -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, @@ -33,7 +32,7 @@ mime_decode_to_string/1, roundtrip/1]). init_per_testcase(_, Config) -> - Dog = test_server:timetrap(?t:minutes(2)), + Dog = test_server:timetrap(?t:minutes(4)), NewConfig = lists:keydelete(watchdog, 1, Config), [{watchdog, Dog} | NewConfig]. diff --git a/lib/stdlib/test/dict_SUITE.erl b/lib/stdlib/test/dict_SUITE.erl index c46fc47b34..df9c769c67 100644 --- a/lib/stdlib/test/dict_SUITE.erl +++ b/lib/stdlib/test/dict_SUITE.erl @@ -53,7 +53,7 @@ end_per_group(_GroupName, Config) -> init_per_testcase(_Case, Config) -> - ?line Dog = ?t:timetrap(?t:minutes(5)), + Dog = ?t:timetrap(?t:minutes(5)), [{watchdog,Dog}|Config]. end_per_testcase(_Case, Config) -> @@ -65,22 +65,22 @@ create(Config) when is_list(Config) -> test_all(fun create_1/1). create_1(M) -> - ?line D0 = M:empty(), - ?line [] = M:to_list(D0), - ?line 0 = M:size(D0), + D0 = M(empty, []), + [] = M(to_list, D0), + 0 = M(size, D0), D0. store(Config) when is_list(Config) -> test_all([{0,132},{253,258},{510,514}], fun store_1/2). store_1(List, M) -> - ?line D0 = M:from_list(List), + D0 = M(from_list, List), %% Make sure that we get the same result by inserting %% elements one at the time. - ?line D1 = foldl(fun({K,V}, Dict) -> M:enter(K, V, Dict) end, - M:empty(), List), - ?line true = M:equal(D0, D1), + D1 = foldl(fun({K,V}, Dict) -> M(enter, {K,V,Dict}) end, + M(empty, []), List), + true = M(equal, {D0,D1}), D0. %%% @@ -98,7 +98,7 @@ dict_mods() -> [Orddict,Dict,Gb]. test_all(Tester) -> - ?line Pids = [spawn_tester(M, Tester) || M <- dict_mods()], + Pids = [spawn_tester(M, Tester) || M <- dict_mods()], collect_all(Pids, []). spawn_tester(M, Tester) -> @@ -106,7 +106,7 @@ spawn_tester(M, Tester) -> spawn_link(fun() -> random:seed(1, 2, 42), S = Tester(M), - Res = {M:size(S),lists:sort(M:to_list(S))}, + Res = {M(size, S),lists:sort(M(to_list, S))}, Parent ! {result,self(),Res} end). diff --git a/lib/stdlib/test/dict_test_lib.erl b/lib/stdlib/test/dict_test_lib.erl index 92a75dad89..7167014310 100644 --- a/lib/stdlib/test/dict_test_lib.erl +++ b/lib/stdlib/test/dict_test_lib.erl @@ -17,67 +17,48 @@ %% %CopyrightEnd% %% --module(dict_test_lib, [Mod,Equal]). +-module(dict_test_lib). --export([module/0,equal/2,empty/0,size/1,to_list/1,from_list/1, - enter/3,delete/2,lookup/2]). +-export([new/2]). -module() -> - Mod. - -equal(X, Y) -> - Equal(X, Y). +new(Mod, Eq) -> + fun (enter, {K,V,D}) -> enter(Mod, K, V, D); + (empty, []) -> empty(Mod); + (equal, {D1,D2}) -> Eq(D1, D2); + (from_list, L) -> from_list(Mod, L); + (module, []) -> Mod; + (size, D) -> Mod:size(D); + (to_list, D) -> to_list(Mod, D) + end. -empty() -> +empty(Mod) -> case erlang:function_exported(Mod, new, 0) of false -> Mod:empty(); true -> Mod:new() end. -size(S) -> - Mod:size(S). - -to_list(S) -> - Mod:to_list(S). +to_list(Mod, D) -> + Mod:to_list(D). -from_list(S) -> +from_list(Mod, L) -> case erlang:function_exported(Mod, from_orddict, 1) of false -> - Mod:from_list(S); + Mod:from_list(L); true -> %% The gb_trees module has no from_list/1 function. %% %% The keys in S are not unique. To make sure %% that we pick the same key/value pairs as %% dict/orddict, first convert the list to an orddict. - Orddict = orddict:from_list(S), + Orddict = orddict:from_list(L), Mod:from_orddict(Orddict) end. %% Store new value into dictionary or update previous value in dictionary. -enter(Key, Val, Dict) -> +enter(Mod, Key, Val, Dict) -> case erlang:function_exported(Mod, store, 3) of false -> Mod:enter(Key, Val, Dict); true -> Mod:store(Key, Val, Dict) end. - -%% Delete an EXISTING key. -delete(Key, Dict) -> - case erlang:function_exported(Mod, delete, 2) of - true -> Mod:delete(Key, Dict); - false -> Mod:erase(Key, Dict) - end. - -%% -> none | {value,Value} -lookup(Key, Dict) -> - case erlang:function_exported(Mod, lookup, 2) of - false -> - case Mod:find(Key, Dict) of - error -> none; - {ok,Value} -> {value,Value} - end; - true -> - Mod:lookup(Key, Dict) - end. diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl index f79414db49..77c615d6d9 100644 --- a/lib/stdlib/test/epp_SUITE.erl +++ b/lib/stdlib/test/epp_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2011. All Rights Reserved. +%% Copyright Ericsson AB 1998-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -1236,6 +1236,13 @@ otp_8911(doc) -> otp_8911(suite) -> []; otp_8911(Config) when is_list(Config) -> + case test_server:is_cover() of + true -> + {skip, "Testing cover, so can not run when cover is already running"}; + false -> + do_otp_8911(Config) + end. +do_otp_8911(Config) -> ?line {ok, CWD} = file:get_cwd(), ?line ok = file:set_cwd(?config(priv_dir, Config)), diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl index d5c1c5276e..dc17e5d33c 100644 --- a/lib/stdlib/test/ets_SUITE.erl +++ b/lib/stdlib/test/ets_SUITE.erl @@ -2170,20 +2170,29 @@ heir_do(Opts) -> ?line undefined = ets:info(foo), %% When heir dies and pid reused before founder dies - NextPidIx = erts_debug:get_internal_state(next_pid), - {Founder4,MrefF4} = my_spawn_monitor(fun()->heir_founder(Master,"The dying heir",Opts)end), - {Heir4,MrefH4} = my_spawn_monitor(fun()->heir_heir(Founder4)end), - Founder4 ! {go, Heir4}, - ?line {'DOWN', MrefH4, process, Heir4, normal} = receive_any(), - erts_debug:set_internal_state(next_pid, NextPidIx), - {Heir4,MrefH4_B} = spawn_monitor_with_pid(Heir4, - fun()-> ?line die_please = receive_any() end), - Founder4 ! die_please, - ?line {'DOWN', MrefF4, process, Founder4, normal} = receive_any(), - Heir4 ! die_please, - ?line {'DOWN', MrefH4_B, process, Heir4, normal} = receive_any(), - ?line undefined = ets:info(foo), - + repeat_while(fun() -> + NextPidIx = erts_debug:get_internal_state(next_pid), + {Founder4,MrefF4} = my_spawn_monitor(fun()->heir_founder(Master,"The dying heir",Opts)end), + {Heir4,MrefH4} = my_spawn_monitor(fun()->heir_heir(Founder4)end), + Founder4 ! {go, Heir4}, + ?line {'DOWN', MrefH4, process, Heir4, normal} = receive_any(), + erts_debug:set_internal_state(next_pid, NextPidIx), + DoppelGanger = spawn_monitor_with_pid(Heir4, + fun()-> ?line die_please = receive_any() end), + Founder4 ! die_please, + ?line {'DOWN', MrefF4, process, Founder4, normal} = receive_any(), + case DoppelGanger of + {Heir4,MrefH4_B} -> + Heir4 ! die_please, + ?line {'DOWN', MrefH4_B, process, Heir4, normal} = receive_any(), + ?line undefined = ets:info(foo), + false; + failed -> + io:format("Failed to spawn process with pid ~p\n", [Heir4]), + true % try again + end + end), + ?line verify_etsmem(EtsMem). heir_founder(Master, HeirData, Opts) -> @@ -5787,25 +5796,20 @@ receive_any_spinning(Loops, N, Tries) when N>0 -> spawn_monitor_with_pid(Pid, Fun) when is_pid(Pid) -> - spawn_monitor_with_pid(Pid, Fun, 1, 10). + spawn_monitor_with_pid(Pid, Fun, 10). -spawn_monitor_with_pid(Pid, Fun, N, M) when N > M*10 -> - spawn_monitor_with_pid(Pid, Fun, N, M*10); -spawn_monitor_with_pid(Pid, Fun, N, M) -> - ?line false = is_process_alive(Pid), +spawn_monitor_with_pid(_, _, 0) -> + failed; +spawn_monitor_with_pid(Pid, Fun, N) -> case my_spawn(fun()-> case self() of Pid -> Fun(); _ -> die end end) of - Pid -> + Pid -> {Pid, erlang:monitor(process, Pid)}; Other -> - case N rem M of - 0 -> io:format("Failed ~p times to get pid ~p (current = ~p)\n",[N,Pid,Other]); - _ -> ok - end, - spawn_monitor_with_pid(Pid,Fun,N+1,M) + spawn_monitor_with_pid(Pid,Fun,N-1) end. diff --git a/lib/stdlib/test/gen_server_SUITE.erl b/lib/stdlib/test/gen_server_SUITE.erl index 2abb01ba24..dffeadb423 100644 --- a/lib/stdlib/test/gen_server_SUITE.erl +++ b/lib/stdlib/test/gen_server_SUITE.erl @@ -1046,8 +1046,9 @@ call_with_huge_message_queue(Config) when is_list(Config) -> io:format("Time for empty message queue: ~p", [Time]), io:format("Time for huge message queue: ~p", [NewTime]), + IsCover = test_server:is_cover(), case (NewTime+1) / (Time+1) of - Q when Q < 10 -> + Q when Q < 10; IsCover -> ok; Q -> io:format("Q = ~p", [Q]), diff --git a/lib/stdlib/test/id_transform_SUITE.erl b/lib/stdlib/test/id_transform_SUITE.erl index 233b0d0a78..ee97ffe7b3 100644 --- a/lib/stdlib/test/id_transform_SUITE.erl +++ b/lib/stdlib/test/id_transform_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2011. All Rights Reserved. +%% Copyright Ericsson AB 2003-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -61,7 +61,7 @@ id_transform(Config) when is_list(Config) -> ?line {module,erl_id_trans}=code:load_binary(erl_id_trans,File,Bin), ?line case test_server:purify_is_running() of false -> - Dog = ?t:timetrap(?t:hours(1)), + Dog = ct:timetrap(?t:hours(1)), ?line Res = run_in_test_suite(), ?t:timetrap_cancel(Dog), Res; diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl index bb02a879c2..74fcdcc7d2 100644 --- a/lib/stdlib/test/io_SUITE.erl +++ b/lib/stdlib/test/io_SUITE.erl @@ -27,7 +27,8 @@ otp_6282/1, otp_6354/1, otp_6495/1, otp_6517/1, otp_6502/1, 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]). + io_fread_newlines/1, otp_8989/1, io_lib_fread_literal/1, + io_lib_print_binary_depth_one/1]). %-define(debug, true). @@ -62,7 +63,8 @@ all() -> otp_6282, otp_6354, otp_6495, otp_6517, otp_6502, 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]. + io_fread_newlines, otp_8989, io_lib_fread_literal, + io_lib_print_binary_depth_one]. groups() -> []. @@ -2021,3 +2023,14 @@ io_lib_fread_literal(Suite) when is_list(Suite) -> ?line {done,{error,{fread,input}},_} = io_lib:fread(C2, eof, " d"), ?line {done,{ok,[]},[]} = io_lib:fread(C2, "d\n", " d"), ok. + +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) -> + ?line "<<>>" = fmt("~W", [<<>>, 1]), + ?line "<<>>" = fmt("~P", [<<>>, 1]), + ?line "<<...>>" = fmt("~W", [<<1>>, 1]), + ?line "<<...>>" = fmt("~P", [<<1>>, 1]), + ?line "<<...>>" = fmt("~W", [<<1:7>>, 1]), + ?line "<<...>>" = fmt("~P", [<<1:7>>, 1]), + ok. diff --git a/lib/stdlib/test/io_proto_SUITE.erl b/lib/stdlib/test/io_proto_SUITE.erl index 661d57c85b..17e69f7c1c 100644 --- a/lib/stdlib/test/io_proto_SUITE.erl +++ b/lib/stdlib/test/io_proto_SUITE.erl @@ -96,7 +96,8 @@ groups() -> []. init_per_suite(Config) -> - Config. + DefShell = get_default_shell(), + [{default_shell,DefShell}|Config]. end_per_suite(_Config) -> ok. @@ -124,20 +125,25 @@ unicode_prompt(doc) -> ["Test that an Unicode prompt does not crash the shell"]; unicode_prompt(Config) when is_list(Config) -> ?line PA = filename:dirname(code:which(?MODULE)), - ?line rtnode([{putline,""}, - {putline, "2."}, - {getline, "2"}, - {putline, "shell:prompt_func({io_proto_SUITE,uprompt})."}, - {getline, "default"}, - {putline, "io:get_line('')."}, - {putline, "hej"}, - {getline, "\"hej\\n\""}, - {putline, "io:setopts([{binary,true}])."}, - {getline, "ok"}, - {putline, "io:get_line('')."}, - {putline, "hej"}, - {getline, "<<\"hej\\n\">>"} - ],[],[],"-pa \""++ PA++"\""), + case proplists:get_value(default_shell,Config) of + old -> + ok; + new -> + ?line rtnode([{putline,""}, + {putline, "2."}, + {getline, "2"}, + {putline, "shell:prompt_func({io_proto_SUITE,uprompt})."}, + {getline, "default"}, + {putline, "io:get_line('')."}, + {putline, "hej"}, + {getline, "\"hej\\n\""}, + {putline, "io:setopts([{binary,true}])."}, + {getline, "ok"}, + {putline, "io:get_line('')."}, + {putline, "hej"}, + {getline, "<<\"hej\\n\">>"} + ],[],[],"-pa \""++ PA++"\"") + end, %% And one with oldshell ?line rtnode([{putline,""}, {putline, "2."}, @@ -234,21 +240,26 @@ setopts_getopts(Config) when is_list(Config) -> lists:sort(io:getopts(RFile)), ?line eof = io:get_line(RFile,''), ?line file:close(RFile), - %% So, lets test another node with new interactive shell - ?line rtnode([{putline,""}, - {putline, "2."}, - {getline, "2"}, - {putline, "lists:keyfind(binary,1,io:getopts())."}, - {getline, "{binary,false}"}, - {putline, "io:get_line('')."}, - {putline, "hej"}, - {getline, "\"hej\\n\""}, - {putline, "io:setopts([{binary,true}])."}, - {getline, "ok"}, - {putline, "io:get_line('')."}, - {putline, "hej"}, - {getline, "<<\"hej\\n\">>"} - ],[]), + case proplists:get_value(default_shell,Config) of + old -> + ok; + new -> + %% So, lets test another node with new interactive shell + ?line rtnode([{putline,""}, + {putline, "2."}, + {getline, "2"}, + {putline, "lists:keyfind(binary,1,io:getopts())."}, + {getline, "{binary,false}"}, + {putline, "io:get_line('')."}, + {putline, "hej"}, + {getline, "\"hej\\n\""}, + {putline, "io:setopts([{binary,true}])."}, + {getline, "ok"}, + {putline, "io:get_line('')."}, + {putline, "hej"}, + {getline, "<<\"hej\\n\">>"} + ],[]) + end, %% And one with oldshell ?line rtnode([{putline,""}, {putline, "2."}, @@ -433,21 +444,27 @@ unicode_options(Config) when is_list(Config) -> end, ?line [ ok = CannotWriteFile(F,FailDir) || F <- AllNoBom ], - %% OK, time for the group_leaders... - ?line rtnode([{putline,""}, - {putline, "2."}, - {getline, "2"}, - {putline, "lists:keyfind(encoding,1,io:getopts())."}, - {getline, "{encoding,latin1}"}, - {putline, "io:format(\"~ts~n\",[[1024]])."}, - {getline, "\\x{400}"}, - {putline, "io:setopts([unicode])."}, - {getline, "ok"}, - {putline, "io:format(\"~ts~n\",[[1024]])."}, - {getline, - binary_to_list(unicode:characters_to_binary( - [1024],unicode,utf8))} - ],[],"LC_CTYPE=\""++get_lc_ctype()++"\"; export LC_CTYPE; "), + case proplists:get_value(default_shell,Config) of + old -> + ok; + new -> + %% OK, time for the group_leaders... + ?line rtnode([{putline,""}, + {putline, "2."}, + {getline, "2"}, + {putline, "lists:keyfind(encoding,1,io:getopts())."}, + {getline, "{encoding,latin1}"}, + {putline, "io:format(\"~ts~n\",[[1024]])."}, + {getline, "\\x{400}"}, + {putline, "io:setopts([unicode])."}, + {getline, "ok"}, + {putline, "io:format(\"~ts~n\",[[1024]])."}, + {getline, + binary_to_list(unicode:characters_to_binary( + [1024],unicode,utf8))} + ],[],"LC_CTYPE=\""++get_lc_ctype()++"\"; " + "export LC_CTYPE; ") + end, ?line rtnode([{putline,""}, {putline, "2."}, {getline_re, ".*2."}, @@ -680,23 +697,28 @@ binary_options(Config) when is_list(Config) -> ?line file:close(F3), %% OK, time for the group_leaders... %% io:format(standard_error,"Hmmm:~w~n",["<<\""++binary_to_list(<<"\345\344\366"/utf8>>)++"\\n\">>"]), - ?line rtnode([{putline,""}, - {putline, "2."}, - {getline, "2"}, - {putline, "lists:keyfind(binary,1,io:getopts())."}, - {getline, "{binary,false}"}, - {putline, "io:get_line('')."}, - {putline, "hej"}, - {getline, "\"hej\\n\""}, - {putline, "io:setopts([{binary,true},unicode])."}, - {getline, "ok"}, - {putline, "io:get_line('')."}, - {putline, "hej"}, - {getline, "<<\"hej\\n\">>"}, - {putline, "io:get_line('')."}, - {putline, binary_to_list(<<"\345\344\366"/utf8>>)}, - {getline, "<<\""++binary_to_list(unicode:characters_to_binary(<<"\345\344\366"/utf8>>,latin1,utf8))++"\\n\">>"} - ],[]), + case proplists:get_value(default_shell,Config) of + old -> + ok; + new -> + ?line rtnode([{putline,""}, + {putline, "2."}, + {getline, "2"}, + {putline, "lists:keyfind(binary,1,io:getopts())."}, + {getline, "{binary,false}"}, + {putline, "io:get_line('')."}, + {putline, "hej"}, + {getline, "\"hej\\n\""}, + {putline, "io:setopts([{binary,true},unicode])."}, + {getline, "ok"}, + {putline, "io:get_line('')."}, + {putline, "hej"}, + {getline, "<<\"hej\\n\">>"}, + {putline, "io:get_line('')."}, + {putline, binary_to_list(<<"\345\344\366"/utf8>>)}, + {getline, "<<\""++binary_to_list(unicode:characters_to_binary(<<"\345\344\366"/utf8>>,latin1,utf8))++"\\n\">>"} + ],[]) + end, %% And one with oldshell ?line rtnode([{putline,""}, {putline, "2."}, @@ -1146,9 +1168,11 @@ read_modes_gl(suite) -> read_modes_gl(doc) -> ["Test various modes when reading from the group leade from another machine"]; read_modes_gl(Config) when is_list(Config) -> - case get_progs() of - {error,Reason} -> + case {get_progs(),proplists:get_value(default_shell,Config)} of + {{error,Reason},_} -> {skipped,Reason}; + {_,old} -> + {skipper,"No new shell"}; _ -> read_modes_gl_1(Config,answering_machine1) end. @@ -1754,6 +1778,17 @@ get_data_within(Port, Timeout, Acc) -> timeout end. +get_default_shell() -> + try + rtnode([{putline,""}, + {putline, "whereis(user_drv)."}, + {getline, "undefined"}],[]), + old + catch E:R -> + ?dbg({E,R}), + new + end. + %% %% Test I/O-server %% diff --git a/lib/stdlib/test/proc_lib_SUITE.erl b/lib/stdlib/test/proc_lib_SUITE.erl index c95089117c..8dca69bac4 100644 --- a/lib/stdlib/test/proc_lib_SUITE.erl +++ b/lib/stdlib/test/proc_lib_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2011. All Rights Reserved. +%% Copyright Ericsson AB 1996-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -28,7 +28,7 @@ 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]). --export([ otp_6345/1]). +-export([ otp_6345/1, init_dont_hang/1]). -export([hib_loop/1, awaken/1]). @@ -36,7 +36,7 @@ handle_event/2, handle_call/2, handle_info/2, terminate/2]). --export([otp_6345_init/1]). +-export([otp_6345_init/1, init_dont_hang_init/1]). -ifdef(STANDALONE). @@ -52,7 +52,7 @@ all() -> {group, tickets}]. groups() -> - [{tickets, [], [otp_6345]}, + [{tickets, [], [otp_6345, init_dont_hang]}, {sync_start, [], [sync_start_nolink, sync_start_link]}]. init_per_suite(Config) -> @@ -343,6 +343,29 @@ otp_6345_loop() -> otp_6345_loop() end. +%% OTP-9803 +init_dont_hang(suite) -> + []; +init_dont_hang(doc) -> + ["Check that proc_lib:start don't hang if spawned process crashes before proc_lib:init_ack/2"]; +init_dont_hang(Config) when is_list(Config) -> + %% Start should behave as start_link + process_flag(trap_exit, true), + StartLinkRes = proc_lib:start_link(?MODULE, init_dont_hang_init, [self()]), + try + StartLinkRes = proc_lib:start(?MODULE, init_dont_hang_init, [self()], 1000), + StartLinkRes = proc_lib:start(?MODULE, init_dont_hang_init, [self()], 1000, []), + ok + catch _:Error -> + io:format("Error ~p /= ~p ~n",[erlang:get_stacktrace(), StartLinkRes]), + exit(Error) + end. + +init_dont_hang_init(Parent) -> + 1 = 2. + + + %%----------------------------------------------------------------- %% The error_logger handler used. %%----------------------------------------------------------------- diff --git a/lib/stdlib/test/sets_SUITE.erl b/lib/stdlib/test/sets_SUITE.erl index f284276bd7..e2bcdd18ce 100644 --- a/lib/stdlib/test/sets_SUITE.erl +++ b/lib/stdlib/test/sets_SUITE.erl @@ -35,7 +35,7 @@ -import(lists, [foldl/3,reverse/1]). init_per_testcase(_Case, Config) -> - ?line Dog = ?t:timetrap(?t:minutes(5)), + Dog = ?t:timetrap(?t:minutes(5)), [{watchdog,Dog}|Config]. end_per_testcase(_Case, Config) -> @@ -70,65 +70,65 @@ create(Config) when is_list(Config) -> test_all(fun create_1/1). create_1(M) -> - ?line S0 = M:empty(), - ?line [] = M:to_list(S0), - ?line 0 = M:size(S0), - ?line true = M:is_empty(S0), + S0 = M(empty, []), + [] = M(to_list, S0), + 0 = M(size, S0), + true = M(is_empty, S0), E = make_ref(), - ?line One = M:singleton(E), - ?line 1 = M:size(One), - ?line false = M:is_empty(One), - [E] = M:to_list(One), + One = M(singleton, E), + 1 = M(size, One), + false = M(is_empty, One), + [E] = M(to_list, One), S0. add_element(Config) when is_list(Config) -> test_all([{0,132},{253,258},{510,514}], fun add_element_1/2). add_element_1(List, M) -> - ?line S = M:from_list(List), - ?line SortedSet = lists:usort(List), - ?line SortedSet = lists:sort(M:to_list(S)), + S = M(from_list, List), + SortedSet = lists:usort(List), + SortedSet = lists:sort(M(to_list, S)), %% Make sure that we get the same result by inserting %% elements one at the time. - ?line S2 = foldl(fun(El, Set) -> M:add_element(El, Set) end, - M:empty(), List), - ?line true = M:equal(S, S2), + S2 = foldl(fun(El, Set) -> M(add_element, {El,Set}) end, + M(empty, []), List), + true = M(equal, {S,S2}), %% Insert elements, randomly delete inserted elements, %% and re-inserted all deleted elements at the end. - ?line S3 = add_element_del(List, M, M:empty(), [], []), - ?line true = M:equal(S2, S3), - ?line true = M:equal(S, S3), + S3 = add_element_del(List, M, M(empty, []), [], []), + true = M(equal, {S2,S3}), + true = M(equal, {S,S3}), S. add_element_del([H|T], M, S, Del, []) -> - add_element_del(T, M, M:add_element(H, S), Del, [H]); + 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), + S1 = M(add_element, {H,S0}), case random:uniform(3) of 1 -> OldEl = lists:nth(random:uniform(length(Inserted)), Inserted), - S = M:del_element(OldEl, S1), + S = M(del_element, {OldEl,S1}), add_element_del(T, M, S, [OldEl|Del], [H|Inserted]); _ -> add_element_del(T, M, S1, Del, [H|Inserted]) end; add_element_del([], M, S, Del, _) -> - M:union(S, M:from_list(Del)). + M(union, {S,M(from_list, Del)}). del_element(Config) when is_list(Config) -> test_all([{0,132},{253,258},{510,514},{1022,1026}], fun del_element_1/2). del_element_1(List, M) -> - ?line S0 = M:from_list(List), - ?line Empty = foldl(fun(El, Set) -> M:del_element(El, Set) end, S0, List), - ?line Empty = M:empty(), - ?line M:is_empty(Empty), - ?line S1 = foldl(fun(El, Set) -> - M:add_element(El, Set) - end, S0, reverse(List)), - ?line true = M:equal(S0, S1), + S0 = M(from_list, List), + Empty = foldl(fun(El, Set) -> M(del_element, {El,Set}) end, S0, List), + Empty = M(empty, []), + true = M(is_empty, Empty), + S1 = foldl(fun(El, Set) -> + M(add_element, {El,Set}) + end, S0, reverse(List)), + true = M(equal, {S0,S1}), S1. subtract(Config) when is_list(Config) -> @@ -138,23 +138,23 @@ subtract(Config) when is_list(Config) -> test_all([{2,69},{126,130},{253,258},511,512,{1023,1030}], fun subtract_1/2). subtract_empty(M) -> - ?line Empty = M:empty(), - ?line true = M:is_empty(M:subtract(Empty, Empty)), - M:subtract(Empty, Empty). + Empty = M(empty, []), + true = M(is_empty, M(subtract, {Empty,Empty})), + M(subtract, {Empty,Empty}). subtract_1(List, M) -> - ?line S0 = M:from_list(List), - ?line Empty = M:empty(), + S0 = M(from_list, List), + Empty = M(empty, []), %% Trivial cases. - ?line true = M:is_empty(M:subtract(Empty, S0)), - ?line true = M:equal(S0, M:subtract(S0, Empty)), + true = M(is_empty, M(subtract, {Empty,S0})), + true = M(equal, {S0,M(subtract, {S0,Empty})}), %% Not so trivial. - ?line subtract_check(List, mutate_some(remove_some(List, 0.4)), M), - ?line subtract_check(List, rnd_list(length(List) div 2 + 5), M), - ?line subtract_check(List, rnd_list(length(List) div 7 + 9), M), - ?line subtract_check(List, mutate_some(List), M). + subtract_check(List, mutate_some(remove_some(List, 0.4)), M), + subtract_check(List, rnd_list(length(List) div 2 + 5), M), + subtract_check(List, rnd_list(length(List) div 7 + 9), M), + subtract_check(List, mutate_some(List), M). subtract_check(A, B, M) -> one_subtract_check(B, A, M), @@ -163,12 +163,12 @@ subtract_check(A, B, M) -> one_subtract_check(A, B, M) -> ASorted = lists:usort(A), BSorted = lists:usort(B), - ASet = M:from_list(A), - BSet = M:from_list(B), - DiffSet = M:subtract(ASet, BSet), + ASet = M(from_list, A), + BSet = M(from_list, B), + DiffSet = M(subtract, {ASet,BSet}), Diff = ASorted -- BSorted, - true = M:equal(DiffSet, M:from_list(Diff)), - Diff = lists:sort(M:to_list(DiffSet)), + true = M(equal, {DiffSet,M(from_list, Diff)}), + Diff = lists:sort(M(to_list, DiffSet)), DiffSet. intersection(Config) when is_list(Config) -> @@ -176,60 +176,60 @@ intersection(Config) when is_list(Config) -> test_all([{1,65},{126,130},{253,259},{499,513},{1023,1025}], fun intersection_1/2). intersection_1(List, M) -> - ?line S0 = M:from_list(List), + S0 = M(from_list, List), %% Intersection with self. - ?line true = M:equal(S0, M:intersection(S0, S0)), - ?line true = M:equal(S0, M:intersection([S0,S0])), - ?line true = M:equal(S0, M:intersection([S0,S0,S0])), - ?line true = M:equal(S0, M:intersection([S0])), + true = M(equal, {S0,M(intersection, {S0,S0})}), + true = M(equal, {S0,M(intersection, [S0,S0])}), + true = M(equal, {S0,M(intersection, [S0,S0,S0])}), + true = M(equal, {S0,M(intersection, [S0])}), %% Intersection with empty. - ?line Empty = M:empty(), - ?line true = M:equal(Empty, M:intersection(S0, Empty)), - ?line true = M:equal(Empty, M:intersection([S0,Empty,S0,Empty])), + Empty = M(empty, []), + true = M(equal, {Empty,M(intersection, {S0,Empty})}), + true = M(equal, {Empty,M(intersection, [S0,Empty,S0,Empty])}), %% The intersection of no sets is undefined. - ?line {'EXIT',_} = (catch M:intersection([])), + {'EXIT',_} = (catch M(intersection, [])), %% Disjoint sets. - ?line Disjoint = [{El} || El <- List], - ?line DisjointSet = M:from_list(Disjoint), - ?line M:is_empty(M:intersection(S0, DisjointSet)), + Disjoint = [{El} || El <- List], + DisjointSet = M(from_list, Disjoint), + true = M(is_empty, M(intersection, {S0,DisjointSet})), %% Disjoint, different sizes. - ?line M:is_empty(M:intersection(S0, M:from_list(remove_some(Disjoint, 0.3)))), - ?line M:is_empty(M:intersection(S0, M:from_list(remove_some(Disjoint, 0.7)))), - ?line M:is_empty(M:intersection(S0, M:from_list(remove_some(Disjoint, 0.9)))), - ?line M:is_empty(M:intersection(M:from_list(remove_some(List, 0.3)), DisjointSet)), - ?line M:is_empty(M:intersection(M:from_list(remove_some(List, 0.5)), DisjointSet)), - ?line M:is_empty(M:intersection(M:from_list(remove_some(List, 0.9)), DisjointSet)), + [begin + SomeRemoved = M(from_list, remove_some(Disjoint, HowMuch)), + true = M(is_empty, M(intersection, {S0,SomeRemoved})), + MoreRemoved = M(from_list, remove_some(List, HowMuch)), + true = M(is_empty, M(intersection, {MoreRemoved,DisjointSet})) + end || HowMuch <- [0.3,0.5,0.7,0.9]], %% Partial overlap (one or more elements in result set). %% The sets have almost the same size. (Almost because a duplicated %% element in the original list could be mutated and not mutated %% at the same time.) - ?line PartialOverlap = mutate_some(List, []), - ?line IntersectionSet = check_intersection(List, PartialOverlap, M), - ?line false = M:is_empty(IntersectionSet), + PartialOverlap = mutate_some(List, []), + IntersectionSet = check_intersection(List, PartialOverlap, M), + false = M(is_empty, IntersectionSet), %% Partial overlap, different set sizes. (Intersection possibly empty.) - ?line check_intersection(List, remove_some(PartialOverlap, 0.1), M), - ?line check_intersection(List, remove_some(PartialOverlap, 0.3), M), - ?line check_intersection(List, remove_some(PartialOverlap, 0.5), M), - ?line check_intersection(List, remove_some(PartialOverlap, 0.7), M), - ?line check_intersection(List, remove_some(PartialOverlap, 0.9), M), + check_intersection(List, remove_some(PartialOverlap, 0.1), M), + check_intersection(List, remove_some(PartialOverlap, 0.3), M), + check_intersection(List, remove_some(PartialOverlap, 0.5), M), + check_intersection(List, remove_some(PartialOverlap, 0.7), M), + check_intersection(List, remove_some(PartialOverlap, 0.9), M), IntersectionSet. check_intersection(Orig, Mutated, M) -> - OrigSet = M:from_list(Orig), - MutatedSet = M:from_list(Mutated), + OrigSet = M(from_list, Orig), + MutatedSet = M(from_list, Mutated), Intersection = [El || El <- Mutated, not is_tuple(El)], SortedIntersection = lists:usort(Intersection), - IntersectionSet = M:intersection(OrigSet, MutatedSet), - true = M:equal(IntersectionSet, M:from_list(SortedIntersection)), - SortedIntersection = lists:sort(M:to_list(IntersectionSet)), + IntersectionSet = M(intersection, {OrigSet,MutatedSet}), + true = M(equal, {IntersectionSet,M(from_list, SortedIntersection)}), + SortedIntersection = lists:sort(M(to_list, IntersectionSet)), IntersectionSet. @@ -239,63 +239,63 @@ union(Config) when is_list(Config) -> test_all([{1,71},{125,129},{254,259},{510,513},{1023,1025}], fun union_1/2). union_1(List, M) -> - ?line S = M:from_list(List), + S = M(from_list, List), %% Union with self and empty. - ?line Empty = M:empty(), - ?line true = M:equal(S, M:union(S, S)), - ?line true = M:equal(S, M:union([S,S])), - ?line true = M:equal(S, M:union([S,S,Empty])), - ?line true = M:equal(S, M:union([S,Empty,S])), - ?line true = M:equal(S, M:union(S, Empty)), - ?line true = M:equal(S, M:union([S])), - ?line true = M:is_empty(M:union([])), + Empty = M(empty, []), + true = M(equal, {S,M(union, {S,S})}), + true = M(equal, {S,M(union, [S,S])}), + true = M(equal, {S,M(union, [S,S,Empty])}), + true = M(equal, {S,M(union, [S,Empty,S])}), + true = M(equal, {S,M(union, {S,Empty})}), + true = M(equal, {S,M(union, [S])}), + true = M(is_empty, M(union, [])), %% Partial overlap. - ?line check_union(List, remove_some(mutate_some(List), 0.9), M), - ?line check_union(List, remove_some(mutate_some(List), 0.7), M), - ?line check_union(List, remove_some(mutate_some(List), 0.5), M), - ?line check_union(List, remove_some(mutate_some(List), 0.3), M), - ?line check_union(List, remove_some(mutate_some(List), 0.1), M), - - ?line check_union(List, mutate_some(remove_some(List, 0.9)), M), - ?line check_union(List, mutate_some(remove_some(List, 0.7)), M), - ?line check_union(List, mutate_some(remove_some(List, 0.5)), M), - ?line check_union(List, mutate_some(remove_some(List, 0.3)), M), - ?line check_union(List, mutate_some(remove_some(List, 0.1)), M). + check_union(List, remove_some(mutate_some(List), 0.9), M), + check_union(List, remove_some(mutate_some(List), 0.7), M), + check_union(List, remove_some(mutate_some(List), 0.5), M), + check_union(List, remove_some(mutate_some(List), 0.3), M), + check_union(List, remove_some(mutate_some(List), 0.1), M), + + check_union(List, mutate_some(remove_some(List, 0.9)), M), + check_union(List, mutate_some(remove_some(List, 0.7)), M), + check_union(List, mutate_some(remove_some(List, 0.5)), M), + check_union(List, mutate_some(remove_some(List, 0.3)), M), + check_union(List, mutate_some(remove_some(List, 0.1)), M). check_union(Orig, Other, M) -> - OrigSet = M:from_list(Orig), - OtherSet = M:from_list(Other), + OrigSet = M(from_list, Orig), + OtherSet = M(from_list, Other), Union = Orig++Other, SortedUnion = lists:usort(Union), - UnionSet = M:union(OrigSet, OtherSet), - SortedUnion = lists:sort(M:to_list(UnionSet)), - M:equal(UnionSet, M:from_list(Union)), + UnionSet = M(union, {OrigSet,OtherSet}), + SortedUnion = lists:sort(M(to_list, UnionSet)), + M(equal, {UnionSet,M(from_list, Union)}), UnionSet. is_subset(Config) when is_list(Config) -> test_all([{1,132},{253,270},{299,311}], fun is_subset_1/2). is_subset_1(List, M) -> - ?line S = M:from_list(List), - ?line Empty = M:empty(), + S = M(from_list, List), + Empty = M(empty, []), %% Subset of empty and self. - ?line true = M:is_subset(Empty, Empty), - ?line true = M:is_subset(Empty, S), - ?line false = M:is_subset(S, Empty), - ?line true = M:is_subset(S, S), + true = M(is_subset, {Empty,Empty}), + true = M(is_subset, {Empty,S}), + false = M(is_subset, {S,Empty}), + true = M(is_subset, {S,S}), %% Other cases. - Res = [?line false = M:is_subset(M:singleton(make_ref()), S), - ?line true = M:is_subset(M:singleton(hd(List)), S), - ?line true = check_subset(remove_some(List, 0.1), List, M), - ?line true = check_subset(remove_some(List, 0.5), List, M), - ?line true = check_subset(remove_some(List, 0.9), List, M), - ?line check_subset(mutate_some(List), List, M), - ?line check_subset(rnd_list(length(List) div 2 + 5), List, M), - ?line subtract_check(List, rnd_list(length(List) div 7 + 9), M) + Res = [false = M(is_subset, {M(singleton, make_ref()),S}), + true = M(is_subset, {M(singleton, hd(List)),S}), + true = check_subset(remove_some(List, 0.1), List, M), + true = check_subset(remove_some(List, 0.5), List, M), + true = check_subset(remove_some(List, 0.9), List, M), + check_subset(mutate_some(List), List, M), + check_subset(rnd_list(length(List) div 2 + 5), List, M), + subtract_check(List, rnd_list(length(List) div 7 + 9), M) ], res_to_set(Res, M, 0, []). @@ -304,12 +304,12 @@ check_subset(X, Y, M) -> check_one_subset(X, Y, M). check_one_subset(X, Y, M) -> - XSet = M:from_list(X), - YSet = M:from_list(Y), + XSet = M(from_list, X), + YSet = M(from_list, Y), SortedX = lists:usort(X), SortedY = lists:usort(Y), IsSubSet = length(SortedY--SortedX) =:= length(SortedY) - length(SortedX), - IsSubSet = M:is_subset(XSet, YSet), + IsSubSet = M(is_subset, {XSet,YSet}), IsSubSet. %% Encode all test results as a set to return. @@ -317,54 +317,54 @@ res_to_set([true|T], M, I, Acc) -> res_to_set(T, M, I+1, [I|Acc]); res_to_set([_|T], M, I, Acc) -> res_to_set(T, M, I+1, Acc); -res_to_set([], M, _, Acc) -> M:from_list(Acc). +res_to_set([], M, _, Acc) -> M(from_list, Acc). is_set(Config) when is_list(Config) -> %% is_set/1 is tested in the other test cases when its argument %% is a set. Here test some arguments that makes it return false. - ?line false = gb_sets:is_set([a,b]), - ?line false = gb_sets:is_set({a,very,bad,tuple}), + false = gb_sets:is_set([a,b]), + false = gb_sets:is_set({a,very,bad,tuple}), - ?line false = sets:is_set([a,b]), - ?line false = sets:is_set({a,very,bad,tuple}), + false = sets:is_set([a,b]), + false = sets:is_set({a,very,bad,tuple}), - ?line false = ordsets:is_set([b,a]), - ?line false = ordsets:is_set({bad,tuple}), + false = ordsets:is_set([b,a]), + false = ordsets:is_set({bad,tuple}), %% Now test values that are known to be bad for all set representations. test_all(fun is_set_1/1). is_set_1(M) -> - ?line false = M:is_set(self()), - ?line false = M:is_set(blurf), - ?line false = M:is_set(make_ref()), - ?line false = M:is_set(<<1,2,3>>), - ?line false = M:is_set(42), - ?line false = M:is_set(math:pi()), - ?line false = M:is_set({}), - M:empty(). + false = M(is_set, self()), + false = M(is_set, blurf), + false = M(is_set, make_ref()), + false = M(is_set, <<1,2,3>>), + false = M(is_set, 42), + false = M(is_set, math:pi()), + false = M(is_set, {}), + M(empty, []). fold(Config) when is_list(Config) -> test_all([{0,71},{125,129},{254,259},{510,513},{1023,1025},{9999,10001}], fun fold_1/2). fold_1(List, M) -> - ?line S = M:from_list(List), - ?line L = M:fold(fun(E, A) -> [E|A] end, [], S), - ?line true = lists:sort(L) =:= lists:usort(List), - M:empty(). + S = M(from_list, List), + L = M(fold, {fun(E, A) -> [E|A] end,[],S}), + true = lists:sort(L) =:= lists:usort(List), + M(empty, []). filter(Config) when is_list(Config) -> test_all([{0,69},{126,130},{254,259},{510,513},{1023,1025},{7999,8000}], fun filter_1/2). filter_1(List, M) -> - ?line S = M:from_list(List), + S = M(from_list, List), IsNumber = fun(X) -> is_number(X) end, - ?line M:equal(M:from_list(lists:filter(IsNumber, List)), - M:filter(IsNumber, S)), - ?line M:filter(fun(X) -> is_atom(X) end, S). + M(equal, {M(from_list, lists:filter(IsNumber, List)), + M(filter, {IsNumber,S})}), + M(filter, {fun(X) -> is_atom(X) end,S}). %%% %%% Test specifics for gb_sets. @@ -375,26 +375,26 @@ take_smallest(Config) when is_list(Config) -> fun take_smallest_1/2). take_smallest_1(List, M) -> - case M:module() of + case M(module, []) of gb_sets -> take_smallest_2(List, M); _ -> ok end, - M:empty(). + M(empty, []). take_smallest_2(List0, M) -> - ?line List = lists:usort(List0), - ?line S = M:from_list(List0), + List = lists:usort(List0), + S = M(from_list, List0), take_smallest_3(S, List, M). take_smallest_3(S0, List0, M) -> - case M:is_empty(S0) of + case M(is_empty, S0) of true -> ok; false -> - ?line Smallest = hd(List0), - ?line Smallest = gb_sets:smallest(S0), - ?line {Smallest,S} = gb_sets:take_smallest(S0), - ?line List = tl(List0), - ?line true = gb_sets:to_list(S) =:= List, + Smallest = hd(List0), + Smallest = gb_sets:smallest(S0), + {Smallest,S} = gb_sets:take_smallest(S0), + List = tl(List0), + true = gb_sets:to_list(S) =:= List, take_smallest_3(S, List, M) end. @@ -403,26 +403,26 @@ take_largest(Config) when is_list(Config) -> fun take_largest_1/2). take_largest_1(List, M) -> - case M:module() of + case M(module, []) of gb_sets -> take_largest_2(List, M); _ -> ok end, - M:empty(). + M(empty, []). take_largest_2(List0, M) -> - ?line List = reverse(lists:usort(List0)), - ?line S = M:from_list(List0), + List = reverse(lists:usort(List0)), + S = M(from_list, List0), take_largest_3(S, List, M). take_largest_3(S0, List0, M) -> - case M:is_empty(S0) of + case M(is_empty, S0) of true -> ok; false -> - ?line Largest = hd(List0), - ?line Largest = gb_sets:largest(S0), - ?line {Largest,S} = gb_sets:take_largest(S0), - ?line List = tl(List0), - ?line true = gb_sets:to_list(S) =:= reverse(List), + Largest = hd(List0), + Largest = gb_sets:largest(S0), + {Largest,S} = gb_sets:take_largest(S0), + List = tl(List0), + true = gb_sets:to_list(S) =:= reverse(List), take_largest_3(S, List, M) end. @@ -441,23 +441,23 @@ sets_mods() -> [Ordsets,Sets,Gb]. test_all(Tester) -> - ?line Res = [begin - random:seed(1, 2, 42), - S = Tester(M), - {M:size(S),lists:sort(M:to_list(S))} - end || M <- sets_mods()], - ?line all_same(Res). + Res = [begin + random:seed(1, 2, 42), + S = Tester(M), + {M(size, S),lists:sort(M(to_list, S))} + end || M <- sets_mods()], + all_same(Res). test_all([{Low,High}|T], Tester) -> test_all(lists:seq(Low, High)++T, Tester); test_all([Sz|T], Tester) when is_integer(Sz) -> List = rnd_list(Sz), - ?line Res = [begin + Res = [begin random:seed(19, 2, Sz), S = Tester(List, M), - {M:size(S),lists:sort(M:to_list(S))} + {M(size, S),lists:sort(M(to_list, S))} end || M <- sets_mods()], - ?line all_same(Res), + all_same(Res), test_all(T, Tester); test_all([], _) -> ok. diff --git a/lib/stdlib/test/sets_test_lib.erl b/lib/stdlib/test/sets_test_lib.erl index bdfb0d59d2..fd4ec2bac3 100644 --- a/lib/stdlib/test/sets_test_lib.erl +++ b/lib/stdlib/test/sets_test_lib.erl @@ -17,91 +17,89 @@ %% %CopyrightEnd% %% --module(sets_test_lib, [Mod,Equal]). - --export([module/0,equal/2,empty/0,from_list/1,to_list/1,singleton/1, - add_element/2,del_element/2,size/1,is_empty/1,is_set/1, - intersection/1,intersection/2,subtract/2, - union/1,union/2,is_subset/2,fold/3,filter/2]). - -module() -> - Mod. - -equal(X, Y) -> - Equal(X, Y). - -empty() -> - Mod:new(). - -from_list(L) -> - Mod:from_list(L). - -to_list(S) -> - Mod:to_list(S). +-module(sets_test_lib). + +-export([new/2]). + +new(Mod, Eq) -> + fun (add_element, {El,S}) -> add_element(Mod, El, S); + (del_element, {El,S}) -> del_element(Mod, El, S); + (empty, []) -> Mod:new(); + (equal, {S1,S2}) -> Eq(S1, S2); + (filter, {F,S}) -> filter(Mod, F, S); + (fold, {F,A,S}) -> fold(Mod, F, A, S); + (from_list, L) -> Mod:from_list(L); + (intersection, {S1,S2}) -> intersection(Mod, Eq, S1, S2); + (intersection, Ss) -> intersection(Mod, Eq, Ss); + (is_empty, S) -> is_empty(Mod, S); + (is_set, S) -> Mod:is_set(S); + (is_subset, {S,Set}) -> is_subset(Mod, Eq, S, Set); + (module, []) -> Mod; + (singleton, E) -> singleton(Mod, E); + (size, S) -> Mod:size(S); + (subtract, {S1,S2}) -> subtract(Mod, S1, S2); + (to_list, S) -> Mod:to_list(S); + (union, {S1,S2}) -> union(Mod, Eq, S1, S2); + (union, Ss) -> union(Mod, Eq, Ss) + end. -singleton(E) -> +singleton(Mod, E) -> case erlang:function_exported(Mod, singleton, 1) of true -> Mod:singleton(E); - false -> from_list([E]) + false -> Mod:from_list([E]) end. -add_element(El, S0) -> +add_element(Mod, El, S0) -> S = Mod:add_element(El, S0), true = Mod:is_element(El, S), - false = is_empty(S), + false = is_empty(Mod, S), true = Mod:is_set(S), S. -del_element(El, S0) -> +del_element(Mod, El, S0) -> S = Mod:del_element(El, S0), false = Mod:is_element(El, S), true = Mod:is_set(S), S. -size(S) -> - Mod:size(S). - -is_empty(S) -> +is_empty(Mod, S) -> true = Mod:is_set(S), case erlang:function_exported(Mod, is_empty, 1) of true -> Mod:is_empty(S); false -> Mod:size(S) == 0 end. -is_set(S) -> - Mod:is_set(S). - -intersection(S1, S2) -> +intersection(Mod, Equal, S1, S2) -> S = Mod:intersection(S1, S2), true = Equal(S, Mod:intersection(S2, S1)), - Disjoint = is_empty(S), + Disjoint = is_empty(Mod, S), Disjoint = Mod:is_disjoint(S1, S2), Disjoint = Mod:is_disjoint(S2, S1), S. -intersection(Ss) -> +intersection(Mod, Equal, Ss) -> S = Mod:intersection(Ss), true = Equal(S, Mod:intersection(lists:reverse(Ss))), S. -subtract(S1, S2) -> +subtract(Mod, S1, S2) -> S = Mod:subtract(S1, S2), true = Mod:is_set(S), true = Mod:size(S) =< Mod:size(S1), S. -union(S1, S2) -> +union(Mod, Equal, S1, S2) -> S = Mod:union(S1, S2), true = Equal(S, Mod:union(S2, S1)), true = Mod:is_set(S), S. -union(Ss) -> +union(Mod, Equal, Ss) -> S = Mod:union(Ss), true = Equal(S, Mod:union(lists:reverse(Ss))), S. -is_subset(S, Set) -> +is_subset(Mod, Equal, S, Set) -> case Mod:is_subset(S, Set) of false -> false; true -> @@ -115,10 +113,10 @@ is_subset(S, Set) -> true end. -fold(F, A, S) -> +fold(Mod, F, A, S) -> true = Mod:is_set(S), Mod:fold(F, A, S). -filter(F, S) -> +filter(Mod, F, S) -> true = Mod:is_set(S), Mod:filter(F, S). diff --git a/lib/stdlib/test/stdlib.cover b/lib/stdlib/test/stdlib.cover index 61f4f064b9..e71be880cb 100644 --- a/lib/stdlib/test/stdlib.cover +++ b/lib/stdlib/test/stdlib.cover @@ -1,17 +1,2 @@ %% -*- erlang -*- {incl_app,stdlib,details}. - -{excl_mods,stdlib, - [erl_parse, - erl_eval, - ets, - filename, - gen_event, - gen_server, - gen, - lists, - io, - io_lib, - io_lib_format, - io_lib_pretty, - proc_lib]}. diff --git a/lib/stdlib/test/supervisor_SUITE.erl b/lib/stdlib/test/supervisor_SUITE.erl index 767ae3d62c..569c66959e 100644 --- a/lib/stdlib/test/supervisor_SUITE.erl +++ b/lib/stdlib/test/supervisor_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2011. All Rights Reserved. +%% Copyright Ericsson AB 1996-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -46,6 +46,7 @@ temporary_normal/1, permanent_shutdown/1, transient_shutdown/1, temporary_shutdown/1, + faulty_application_shutdown/1, permanent_abnormal/1, transient_abnormal/1, temporary_abnormal/1, temporary_bystander/1]). @@ -98,7 +99,8 @@ groups() -> {normal_termination, [], [permanent_normal, transient_normal, temporary_normal]}, {shutdown_termination, [], - [permanent_shutdown, transient_shutdown, temporary_shutdown]}, + [permanent_shutdown, transient_shutdown, temporary_shutdown, + faulty_application_shutdown]}, {abnormal_termination, [], [permanent_abnormal, transient_abnormal, temporary_abnormal]}, @@ -659,6 +661,39 @@ temporary_shutdown(Config) when is_list(Config) -> [0,0,0,0] = get_child_counts(sup_test). %%------------------------------------------------------------------------- +%% Faulty application should shutdown and pass on errors +faulty_application_shutdown(Config) when is_list(Config) -> + + %% Set some paths + AppDir = filename:join(?config(data_dir, Config), "app_faulty"), + EbinDir = filename:join(AppDir, "ebin"), + + %% Start faulty app + code:add_patha(EbinDir), + + %% {error, + %% {{shutdown, + %% {failed_to_start_child, + %% app_faulty, + %% {undef, + %% [{an_undefined_module_with,an_undefined_function,[argument1,argument2], + %% []}, + %% {app_faulty_server,init,1, + %% [{file,"app_faulty/src/app_faulty_server.erl"},{line,16}]}, + %% {gen_server,init_it,6, + %% [{file,"gen_server.erl"},{line,304}]}, + %% {proc_lib,init_p_do_apply,3, + %% [{file,"proc_lib.erl"},{line,227}]}]}}}, + %% {app_faulty,start,[normal,[]]}}} + + {error, Error} = application:start(app_faulty), + {{shutdown, {failed_to_start_child,app_faulty,{undef, CallStack}}}, + {app_faulty,start,_}} = Error, + [{an_undefined_module_with,an_undefined_function,_,_}|_] = CallStack, + ok = application:unload(app_faulty), + ok. + +%%------------------------------------------------------------------------- %% A permanent child should always be restarted. permanent_abnormal(Config) when is_list(Config) -> {ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}), diff --git a/lib/stdlib/test/supervisor_SUITE_data/Makefile.src b/lib/stdlib/test/supervisor_SUITE_data/Makefile.src new file mode 100644 index 0000000000..dbc5729f47 --- /dev/null +++ b/lib/stdlib/test/supervisor_SUITE_data/Makefile.src @@ -0,0 +1,15 @@ +EFLAGS=+debug_info + +APP_FAULTY= \ + app_faulty/ebin/app_faulty_sup.@EMULATOR@ \ + app_faulty/ebin/app_faulty_server.@EMULATOR@ \ + app_faulty/ebin/app_faulty.@EMULATOR@ \ + +all: $(APP_FAULTY) + +app_faulty/ebin/app_faulty_server.@EMULATOR@: app_faulty/src/app_faulty_server.erl + erlc $(EFLAGS) -oapp_faulty/ebin app_faulty/src/app_faulty_server.erl +app_faulty/ebin/app_faulty_sup.@EMULATOR@: app_faulty/src/app_faulty_sup.erl + erlc $(EFLAGS) -oapp_faulty/ebin app_faulty/src/app_faulty_sup.erl +app_faulty/ebin/app_faulty.@EMULATOR@: app_faulty/src/app_faulty.erl + erlc $(EFLAGS) -oapp_faulty/ebin app_faulty/src/app_faulty.erl diff --git a/lib/stdlib/test/supervisor_SUITE_data/app_faulty/ebin/app_faulty.app b/lib/stdlib/test/supervisor_SUITE_data/app_faulty/ebin/app_faulty.app new file mode 100644 index 0000000000..d4ab07e485 --- /dev/null +++ b/lib/stdlib/test/supervisor_SUITE_data/app_faulty/ebin/app_faulty.app @@ -0,0 +1,10 @@ +{application, app_faulty, + [{description, "very simple example faulty application"}, + {id, "app_faulty"}, + {vsn, "1.0"}, + {modules, [app_faulty, app_faulty_sup, app_faulty_server]}, + {registered, [app_faulty]}, + {applications, [kernel, stdlib]}, + {env, [{var,val1}]}, + {mod, {app_faulty, []}} + ]}. diff --git a/lib/stdlib/test/supervisor_SUITE_data/app_faulty/src/app_faulty.erl b/lib/stdlib/test/supervisor_SUITE_data/app_faulty/src/app_faulty.erl new file mode 100644 index 0000000000..c65b411cd6 --- /dev/null +++ b/lib/stdlib/test/supervisor_SUITE_data/app_faulty/src/app_faulty.erl @@ -0,0 +1,17 @@ +-module(app_faulty). + +-behaviour(application). + +%% Application callbacks +-export([start/2, stop/1]). + +start(_Type, _StartArgs) -> + case app_faulty_sup:start_link() of + {ok, Pid} -> + {ok, Pid}; + Error -> + Error + end. + +stop(_State) -> + ok. diff --git a/lib/stdlib/test/supervisor_SUITE_data/app_faulty/src/app_faulty_server.erl b/lib/stdlib/test/supervisor_SUITE_data/app_faulty/src/app_faulty_server.erl new file mode 100644 index 0000000000..6628f92210 --- /dev/null +++ b/lib/stdlib/test/supervisor_SUITE_data/app_faulty/src/app_faulty_server.erl @@ -0,0 +1,32 @@ +-module(app_faulty_server). + +-behaviour(gen_server). + +%% API +-export([start_link/0]). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). + +start_link() -> + gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). + +init([]) -> + an_undefined_module_with:an_undefined_function(argument1, argument2), + {ok, []}. + +handle_call(_Request, _From, State) -> + {reply, ok, State}. + +handle_cast(_Msg, State) -> + {noreply, State}. + +handle_info(_Info, State) -> + {noreply, State}. + +terminate(_Reason, _State) -> + ok. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. diff --git a/lib/stdlib/test/supervisor_SUITE_data/app_faulty/src/app_faulty_sup.erl b/lib/stdlib/test/supervisor_SUITE_data/app_faulty/src/app_faulty_sup.erl new file mode 100644 index 0000000000..8115a88809 --- /dev/null +++ b/lib/stdlib/test/supervisor_SUITE_data/app_faulty/src/app_faulty_sup.erl @@ -0,0 +1,17 @@ +-module(app_faulty_sup). + +-behaviour(supervisor). + +%% API +-export([start_link/0]). + +%% Supervisor callbacks +-export([init/1]). + +start_link() -> + supervisor:start_link(?MODULE, []). + +init([]) -> + AChild = {app_faulty,{app_faulty_server,start_link,[]}, + permanent,2000,worker,[app_faulty_server]}, + {ok,{{one_for_all,0,1}, [AChild]}}. |