diff options
Diffstat (limited to 'erts/emulator/test')
-rw-r--r-- | erts/emulator/test/bif_SUITE.erl | 15 | ||||
-rw-r--r-- | erts/emulator/test/bs_construct_SUITE.erl | 48 | ||||
-rw-r--r-- | erts/emulator/test/code_SUITE.erl | 132 | ||||
-rw-r--r-- | erts/emulator/test/dirty_nif_SUITE.erl | 129 | ||||
-rw-r--r-- | erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c | 24 | ||||
-rw-r--r-- | erts/emulator/test/distribution_SUITE.erl | 69 | ||||
-rw-r--r-- | erts/emulator/test/lttng_SUITE.erl | 21 | ||||
-rw-r--r-- | erts/emulator/test/message_queue_data_SUITE.erl | 42 | ||||
-rw-r--r-- | erts/emulator/test/tracer_SUITE.erl | 103 | ||||
-rw-r--r-- | erts/emulator/test/tracer_SUITE_data/tracer_test.c | 4 | ||||
-rw-r--r-- | erts/emulator/test/tracer_test.erl | 4 |
11 files changed, 462 insertions, 129 deletions
diff --git a/erts/emulator/test/bif_SUITE.erl b/erts/emulator/test/bif_SUITE.erl index 26bb416bf0..d31399e4af 100644 --- a/erts/emulator/test/bif_SUITE.erl +++ b/erts/emulator/test/bif_SUITE.erl @@ -141,9 +141,11 @@ guard_bifs_in_erl_bif_types(_Config) -> shadow_comments(_Config) -> ensure_erl_bif_types_compiled(), + ErlangList = [{erlang,F,A} || {F,A} <- erlang:module_info(exports), + not is_operator(F,A)], List0 = erlang:system_info(snifs), - List1 = [MFA || {M,_,_}=MFA <- List0, M =/= hipe_bifs], - List = [MFA || MFA <- List1, not is_operator(MFA)], + List1 = [MFA || {M,_,_}=MFA <- List0, M =/= hipe_bifs, M =/= erlang], + List = List1 ++ ErlangList, HasTypes = [MFA || {M,F,A}=MFA <- List, erl_bif_types:is_known(M, F, A)], Path = get_code_path(), @@ -253,12 +255,15 @@ specs(_) -> end. is_operator({erlang,F,A}) -> + is_operator(F,A); +is_operator(_) -> false. + +is_operator(F,A) -> erl_internal:arith_op(F, A) orelse erl_internal:bool_op(F, A) orelse erl_internal:comp_op(F, A) orelse erl_internal:list_op(F, A) orelse - erl_internal:send_op(F, A); -is_operator(_) -> false. + erl_internal:send_op(F, A). extract_specs(M, Abstr) -> [{make_mfa(M, Name),Spec} || {attribute,_,spec,{Name,Spec}} <- Abstr]. @@ -646,6 +651,8 @@ erlang_halt(Config) when is_list(Config) -> {badrpc,nodedown} = rpc:call(N2, erlang, halt, [0]), {ok,N3} = slave:start(H, halt_node3), {badrpc,nodedown} = rpc:call(N3, erlang, halt, [0,[]]), + {ok,N4} = slave:start(H, halt_node4), + {badrpc,nodedown} = rpc:call(N4, erlang, halt, [lists:duplicate(300,$x)]), % This test triggers a segfault when dumping a crash dump % to make sure that we can handle it properly. diff --git a/erts/emulator/test/bs_construct_SUITE.erl b/erts/emulator/test/bs_construct_SUITE.erl index 941cb435f7..22a1c0b765 100644 --- a/erts/emulator/test/bs_construct_SUITE.erl +++ b/erts/emulator/test/bs_construct_SUITE.erl @@ -527,7 +527,7 @@ huge_float_check({'EXIT',{system_limit,_}}) -> ok; huge_float_check({'EXIT',{badarg,_}}) -> ok. huge_binary(Config) when is_list(Config) -> - ct:timetrap({seconds, 30}), + ct:timetrap({seconds, 60}), 16777216 = size(<<0:(id(1 bsl 26)),(-1):(id(1 bsl 26))>>), garbage_collect(), {Shift,Return} = case free_mem() of @@ -561,30 +561,13 @@ huge_binary(Config) when is_list(Config) -> end. free_mem() -> - Cmd = "uname; free", - Output = string:tokens(os:cmd(Cmd), "\n"), - io:format("Output from command ~p\n~p\n",[Cmd,Output]), - case Output of - [OS, ColumnNames, Values | _] -> - case string:str(OS,"Linux") of - 0 -> - io:format("Unknown OS\n",[]), - undefined; - _ -> - case {string:tokens(ColumnNames, " \t"), - string:tokens(Values, " \t")} of - {[_,_,"free"|_],["Mem:",_,_,FreeKb|_]} -> - list_to_integer(FreeKb) div 1024; - _ -> - io:format("Failed to parse output from 'free':\n",[]), - undefined - end - end; - _ -> - io:format("Too few lines in output\n",[]), - undefined + {ok,Apps} = application:ensure_all_started(os_mon), + Mem = memsup:get_system_memory_data(), + [ok = application:stop(App)||App <- Apps], + case proplists:get_value(free_memory,Mem) of + undefined -> undefined; + Val -> Val div 1024 end. - system_limit(Config) when is_list(Config) -> WordSize = erlang:system_info(wordsize), @@ -614,8 +597,7 @@ system_limit_32() -> {'EXIT',{system_limit,_}} = (catch <<42:536870912/unit:8>>), {'EXIT',{system_limit,_}} = (catch <<42:(id(536870912))/unit:8>>), {'EXIT',{system_limit,_}} = (catch <<0:(id(8)),42:536870912/unit:8>>), - {'EXIT',{system_limit,_}} = - (catch <<0:(id(8)),42:(id(536870912))/unit:8>>), + {'EXIT',{system_limit,_}} = (catch <<0:(id(8)),42:(id(536870912))/unit:8>>), %% The size would be silently truncated, resulting in a crash. {'EXIT',{system_limit,_}} = (catch <<0:(1 bsl 35)>>), @@ -627,16 +609,10 @@ system_limit_32() -> ok. badarg(Config) when is_list(Config) -> - {'EXIT',{badarg,_}} = - (catch <<0:(id(1 bsl 100)),0:(id(-1))>>), - {'EXIT',{badarg,_}} = - (catch <<0:(id(1 bsl 100)),0:(id(-(1 bsl 70)))>>), - {'EXIT',{badarg,_}} = - (catch <<0:(id(-(1 bsl 70))),0:(id(1 bsl 100))>>), - - {'EXIT',{badarg,_}} = - (catch <<(id(<<>>))/binary,0:(id(-(1 bsl 100)))>>), - + {'EXIT',{badarg,_}} = (catch <<0:(id(1 bsl 100)),0:(id(-1))>>), + {'EXIT',{badarg,_}} = (catch <<0:(id(1 bsl 100)),0:(id(-(1 bsl 70)))>>), + {'EXIT',{badarg,_}} = (catch <<0:(id(-(1 bsl 70))),0:(id(1 bsl 100))>>), + {'EXIT',{badarg,_}} = (catch <<(id(<<>>))/binary,0:(id(-(1 bsl 100)))>>), ok. copy_writable_binary(Config) when is_list(Config) -> diff --git a/erts/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl index 29b95ef674..2347a3d4ef 100644 --- a/erts/emulator/test/code_SUITE.erl +++ b/erts/emulator/test/code_SUITE.erl @@ -26,7 +26,7 @@ external_fun/1,get_chunk/1,module_md5/1,make_stub/1, make_stub_many_funs/1,constant_pools/1,constant_refc_binaries/1, false_dependency/1,coverage/1,fun_confusion/1, - t_copy_literals/1]). + t_copy_literals/1, t_copy_literals_frags/1]). -define(line_trace, 1). -include_lib("common_test/include/ct.hrl"). @@ -38,7 +38,7 @@ all() -> t_check_process_code_ets, t_check_old_code, external_fun, get_chunk, module_md5, make_stub, make_stub_many_funs, constant_pools, constant_refc_binaries, false_dependency, - coverage, fun_confusion, t_copy_literals]. + coverage, fun_confusion, t_copy_literals, t_copy_literals_frags]. init_per_suite(Config) -> erts_debug:set_internal_state(available_internal_state, true), @@ -766,6 +766,134 @@ t_copy_literals(Config) when is_list(Config) -> ok = flush(), ok. +-define(mod, t_copy_literals_frags). +t_copy_literals_frags(Config) when is_list(Config) -> + Bin = gen_lit(?mod,[{a,{1,2,3,4,5,6,7}}, + {b,"hello world"}, + {c, <<"hello world">>}, + {d, {"hello world", {1.0, 2.0, <<"some">>, "string"}}}, + {e, <<"off heap", 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9,10,11,12,13,14,15, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9,10,11,12,13,14,15, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9,10,11,12,13,14,15, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9,10,11,12,13,14,15>>}]), + + {module, ?mod} = erlang:load_module(?mod, Bin), + N = 6000, + Recv = spawn_opt(fun() -> receive + read -> + io:format("reading"), + literal_receiver() + end + end, [link,{min_heap_size, 10000}]), + Switcher = spawn_link(fun() -> literal_switcher() end), + Pids = [spawn_opt(fun() -> receive + {Pid, go, Recv, N} -> + io:format("sender batch (~w) start ~w~n",[N,self()]), + literal_sender(N,Recv), + Pid ! {self(), ok} + end + end, [link,{min_heap_size,800}]) || _ <- lists:seq(1,100)], + _ = [Pid ! {self(), go, Recv, N} || Pid <- Pids], + %% don't read immediately + timer:sleep(5), + Recv ! read, + Switcher ! {switch,?mod,Bin,[Recv|Pids],200}, + _ = [receive {Pid, ok} -> ok end || Pid <- Pids], + Switcher ! {self(), done}, + receive {Switcher, ok} -> ok end, + Recv ! {self(), done}, + receive {Recv, ok} -> ok end, + ok. + +literal_receiver() -> + receive + {Pid, done} -> + io:format("reader_done~n"), + Pid ! {self(), ok}; + {_Pid, msg, [A,B,C,D,E]} -> + A = ?mod:a(), + B = ?mod:b(), + C = ?mod:c(), + D = ?mod:d(), + E = ?mod:e(), + literal_receiver(); + {Pid, sender_confirm} -> + io:format("sender confirm ~w~n", [Pid]), + Pid ! {self(), ok}, + literal_receiver() + end. + +literal_sender(0, Recv) -> + Recv ! {self(), sender_confirm}, + receive {Recv, ok} -> ok end; +literal_sender(N, Recv) -> + Recv ! {self(), msg, [?mod:a(), + ?mod:b(), + ?mod:c(), + ?mod:d(), + ?mod:e()]}, + literal_sender(N - 1, Recv). + +literal_switcher() -> + receive + {switch,Mod,Bin,Pids,Tmo} -> + literal_switcher(Mod,Bin,Pids,Tmo) + end. +literal_switcher(Mod,Bin,Pids,Tmo) -> + receive + {Pid,done} -> + Pid ! {self(),ok} + after Tmo -> + io:format("load module ~w~n", [Mod]), + {module, Mod} = erlang:load_module(Mod,Bin), + ok = check_and_purge(Pids,Mod), + io:format("purge complete ~w~n", [Mod]), + literal_switcher(Mod,Bin,Pids,Tmo+Tmo) + end. + +check_and_purge([],Mod) -> + erlang:purge_module(Mod), + ok; +check_and_purge(Pids,Mod) -> + io:format("purge ~w~n", [Mod]), + Tag = make_ref(), + _ = [begin + erlang:check_process_code(Pid,Mod,[{async,{Tag,Pid}}]) + end || Pid <- Pids], + Retry = check_and_purge_receive(Pids,Tag,[]), + check_and_purge(Retry,Mod). + +check_and_purge_receive([Pid|Pids],Tag,Retry) -> + receive + {check_process_code, {Tag, Pid}, false} -> + check_and_purge_receive(Pids,Tag,Retry); + {check_process_code, {Tag, Pid}, true} -> + check_and_purge_receive(Pids,Tag,[Pid|Retry]) + end; +check_and_purge_receive([],_,Retry) -> + Retry. + + +gen_lit(Module,Terms) -> + FunStrings = [lists:flatten(io_lib:format("~w() -> ~w.~n", [F,Term]))||{F,Term}<-Terms], + FunForms = function_forms(FunStrings), + Forms = [{attribute,erl_anno:new(1),module,Module}, + {attribute,erl_anno:new(2),export,[FA || {FA,_} <- FunForms]}] ++ + [Function || {_, Function} <- FunForms], + {ok, Module, Bin} = compile:forms(Forms), + Bin. + +function_forms([]) -> []; +function_forms([S|Ss]) -> + {ok, Ts,_} = erl_scan:string(S), + {ok, Form} = erl_parse:parse_form(Ts), + Fun = element(3, Form), + Arity = element(4, Form), + [{{Fun,Arity}, Form}|function_forms(Ss)]. chase_msg(0, Pid) -> chase_loop(Pid); diff --git a/erts/emulator/test/dirty_nif_SUITE.erl b/erts/emulator/test/dirty_nif_SUITE.erl index c3afbc0803..83b098a704 100644 --- a/erts/emulator/test/dirty_nif_SUITE.erl +++ b/erts/emulator/test/dirty_nif_SUITE.erl @@ -32,19 +32,23 @@ dirty_nif/1, dirty_nif_send/1, dirty_nif_exception/1, call_dirty_nif_exception/1, dirty_scheduler_exit/1, dirty_call_while_terminated/1, - dirty_heap_access/1]). + dirty_heap_access/1, dirty_process_info/1, + dirty_process_register/1, dirty_process_trace/1]). -define(nif_stub,nif_stub_error(?LINE)). suite() -> [{ct_hooks,[ts_install_cth]}]. -all() -> +all() -> [dirty_nif, dirty_nif_send, dirty_nif_exception, dirty_scheduler_exit, dirty_call_while_terminated, - dirty_heap_access]. + dirty_heap_access, + dirty_process_info, + dirty_process_register, + dirty_process_trace]. init_per_suite(Config) -> try erlang:system_info(dirty_cpu_schedulers) of @@ -187,7 +191,7 @@ dirty_call_while_terminated(Config) when is_list(Config) -> blipp:blupp(Bin) end, [monitor,link]), - receive {dirty_alive, Pid} -> ok end, + receive {dirty_alive, _Pid} -> ok end, {value, {BinAddr, 4711, 2}} = lists:keysearch(4711, 2, element(2, process_info(self(), @@ -241,7 +245,7 @@ dirty_heap_access(Config) when is_list(Config) -> end), {N, R} = access_dirty_heap(Dirty, RGL, 0, 0), receive - {Pid, Res} -> + {_Pid, Res} -> 1000 = length(Res), lists:foreach(fun (X) -> Ref = X end, Res) end, @@ -269,12 +273,123 @@ access_dirty_heap(Dirty, RGL, N, R) -> end) end. +%% These tests verify that processes that access a process executing a +%% dirty NIF where the main lock is needed for that access do not get +%% blocked. Each test passes its pid to dirty_sleeper, which sends a +%% 'ready' message when it's running on a dirty scheduler and just before +%% it starts a 6 second sleep. When it receives the message, it verifies +%% that access to the dirty process is as it expects. After the dirty +%% process finishes its 6 second sleep but before it returns from the dirty +%% scheduler, it sends a 'done' message. If the tester already received +%% that message, the test fails because it means attempting to access the +%% dirty process waited for that process to return to a regular scheduler, +%% so verify that we haven't received that message, and also verify that +%% the dirty process is still alive immediately after accessing it. +dirty_process_info(Config) when is_list(Config) -> + access_dirty_process( + Config, + fun() -> ok end, + fun(NifPid) -> + PI = process_info(NifPid), + {current_function,{?MODULE,dirty_sleeper,1}} = + lists:keyfind(current_function, 1, PI), + ok + end, + fun(_) -> ok end). + +dirty_process_register(Config) when is_list(Config) -> + access_dirty_process( + Config, + fun() -> ok end, + fun(NifPid) -> + register(test_dirty_process_register, NifPid), + NifPid = whereis(test_dirty_process_register), + unregister(test_dirty_process_register), + false = lists:member(test_dirty_process_register, + registered()), + ok + end, + fun(_) -> ok end). + +dirty_process_trace(Config) when is_list(Config) -> + access_dirty_process( + Config, + fun() -> + erlang:trace_pattern({?MODULE,dirty_sleeper,1}, + [{'_',[],[{return_trace}]}], + [local,meta]), + ok + end, + fun(NifPid) -> + erlang:trace(NifPid, true, [call,timestamp]), + ok + end, + fun(NifPid) -> + receive + done -> + receive + {trace_ts,NifPid,call,{?MODULE,dirty_sleeper,_},_} -> + ok + after + 0 -> + error(missing_trace_call_message) + end, + receive + {trace_ts,NifPid,return_from,{?MODULE,dirty_sleeper,1}, + ok,_} -> + ok + after + 100 -> + error(missing_trace_return_message) + end + after + 6500 -> + error(missing_done_message) + end, + ok + end). + %% %% Internal... %% +access_dirty_process(Config, Start, Test, Finish) -> + {ok, Node} = start_node(Config, ""), + [ok] = mcall(Node, + [fun() -> + Path = ?config(data_dir, Config), + Lib = atom_to_list(?MODULE), + ok = erlang:load_nif(filename:join(Path,Lib), []), + ok = test_dirty_process_access(Start, Test, Finish) + end]), + stop_node(Node), + ok. + +test_dirty_process_access(Start, Test, Finish) -> + ok = Start(), + Self = self(), + NifPid = spawn_link(fun() -> + ok = dirty_sleeper(Self) + end), + ok = receive + ready -> + ok = Test(NifPid), + receive + done -> + error(dirty_process_info_blocked) + after + 0 -> + true = erlang:is_process_alive(NifPid), + ok + end + after + 3000 -> + error(timeout) + end, + ok = Finish(NifPid). + receive_any() -> - receive M -> M end. + receive M -> M end. start_node(Config) -> start_node(Config, ""). @@ -314,13 +429,13 @@ mcall(Node, Funs) -> %% The NIFs: lib_loaded() -> false. -call_nif_schedule(_,_) -> ?nif_stub. call_dirty_nif(_,_,_) -> ?nif_stub. send_from_dirty_nif(_) -> ?nif_stub. call_dirty_nif_exception(_) -> ?nif_stub. call_dirty_nif_zero_args() -> ?nif_stub. dirty_call_while_terminated_nif(_) -> ?nif_stub. dirty_sleeper() -> ?nif_stub. +dirty_sleeper(_) -> ?nif_stub. dirty_heap_access_nif(_) -> ?nif_stub. nif_stub_error(Line) -> diff --git a/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c b/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c index 2013c88167..e38bececde 100644 --- a/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c +++ b/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c @@ -19,7 +19,9 @@ */ #include "erl_nif.h" #include <assert.h> -#ifndef __WIN32__ +#ifdef __WIN32__ +#include <windows.h> +#else #include <unistd.h> #endif @@ -146,12 +148,31 @@ static ERL_NIF_TERM call_dirty_nif_zero_args(ErlNifEnv* env, int argc, const ERL static ERL_NIF_TERM dirty_sleeper(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { + ErlNifPid pid; + ErlNifEnv* msg_env = NULL; + assert(enif_is_on_dirty_scheduler(env)); + + /* If we get a pid argument, it indicates a process involved in the + test wants a message from us. Prior to the sleep we send a 'ready' + message, and then after the sleep, send a 'done' message. */ + if (argc == 1 && enif_get_local_pid(env, argv[0], &pid)) { + msg_env = enif_alloc_env(); + enif_send(env, &pid, msg_env, enif_make_atom(msg_env, "ready")); + } + #ifdef __WIN32__ Sleep(6000); #else sleep(6); #endif + + if (argc == 1) { + assert(msg_env != NULL); + enif_send(env, &pid, msg_env, enif_make_atom(msg_env, "done")); + enif_free_env(msg_env); + } + return enif_make_atom(env, "ok"); } @@ -216,6 +237,7 @@ static ErlNifFunc nif_funcs[] = {"call_dirty_nif_exception", 1, call_dirty_nif_exception, ERL_NIF_DIRTY_JOB_IO_BOUND}, {"call_dirty_nif_zero_args", 0, call_dirty_nif_zero_args, ERL_NIF_DIRTY_JOB_CPU_BOUND}, {"dirty_sleeper", 0, dirty_sleeper, ERL_NIF_DIRTY_JOB_IO_BOUND}, + {"dirty_sleeper", 1, dirty_sleeper, ERL_NIF_DIRTY_JOB_CPU_BOUND}, {"dirty_call_while_terminated_nif", 1, dirty_call_while_terminated_nif, ERL_NIF_DIRTY_JOB_CPU_BOUND}, {"dirty_heap_access_nif", 1, dirty_heap_access_nif, ERL_NIF_DIRTY_JOB_CPU_BOUND} }; diff --git a/erts/emulator/test/distribution_SUITE.erl b/erts/emulator/test/distribution_SUITE.erl index d0096fb1bc..26780f6017 100644 --- a/erts/emulator/test/distribution_SUITE.erl +++ b/erts/emulator/test/distribution_SUITE.erl @@ -55,7 +55,8 @@ bad_dist_ext_receive/1, bad_dist_ext_process_info/1, bad_dist_ext_control/1, - bad_dist_ext_connection_id/1]). + bad_dist_ext_connection_id/1, + start_epmd_false/1, epmd_module/1]). %% Internal exports. -export([sender/3, receiver2/2, dummy_waiter/0, dead_process/0, @@ -64,6 +65,9 @@ dist_evil_parallel_receiver/0, sendersender/4, sendersender2/4]). +%% epmd_module exports +-export([start_link/0, register_node/2, port_please/2]). + suite() -> [{ct_hooks,[ts_install_cth]}, {timetrap, {minutes, 4}}]. @@ -76,7 +80,8 @@ all() -> {group, trap_bif}, {group, dist_auto_connect}, dist_parallel_send, atom_roundtrip, unicode_atom_roundtrip, atom_roundtrip_r15b, contended_atom_cache_entry, contended_unicode_atom_cache_entry, - bad_dist_structure, {group, bad_dist_ext}]. + bad_dist_structure, {group, bad_dist_ext}, + start_epmd_false, epmd_module]. groups() -> [{bulk_send, [], [bulk_send_small, bulk_send_big, bulk_send_bigbig]}, @@ -1881,6 +1886,66 @@ dmsg_ext(Term) -> dmsg_bad_atom_cache_ref() -> [$R, 137]. +start_epmd_false(Config) when is_list(Config) -> + %% Start a node with the option -start_epmd false. + {ok, OtherNode} = start_node(start_epmd_false, "-start_epmd false"), + %% We should be able to ping it, as epmd was started by us: + pong = net_adm:ping(OtherNode), + stop_node(OtherNode), + + ok. + +epmd_module(Config) when is_list(Config) -> + %% We need a relay node to test this, since the test node uses the + %% standard epmd module. + Sock1 = start_relay_node(epmd_module_node1, "-epmd_module " ++ ?MODULE_STRING), + Node1 = inet_rpc_nodename(Sock1), + %% Ask what port it's listening on - it won't have registered with + %% epmd. + {ok, {ok, Port1}} = do_inet_rpc(Sock1, application, get_env, [kernel, dist_listen_port]), + + %% Start a second node, passing the port number as a secret + %% argument. + Sock2 = start_relay_node(epmd_module_node2, "-epmd_module " ++ ?MODULE_STRING + ++ " -other_node_port " ++ integer_to_list(Port1)), + Node2 = inet_rpc_nodename(Sock2), + %% Node 1 can't ping node 2 + {ok, pang} = do_inet_rpc(Sock1, net_adm, ping, [Node2]), + {ok, []} = do_inet_rpc(Sock1, erlang, nodes, []), + {ok, []} = do_inet_rpc(Sock2, erlang, nodes, []), + %% But node 2 can ping node 1 + {ok, pong} = do_inet_rpc(Sock2, net_adm, ping, [Node1]), + {ok, [Node2]} = do_inet_rpc(Sock1, erlang, nodes, []), + {ok, [Node1]} = do_inet_rpc(Sock2, erlang, nodes, []), + + stop_relay_node(Sock2), + stop_relay_node(Sock1). + +%% epmd_module functions: + +start_link() -> + ignore. + +register_node(_Name, Port) -> + %% Save the port number we're listening on. + application:set_env(kernel, dist_listen_port, Port), + Creation = rand:uniform(3), + {ok, Creation}. + +port_please(_Name, _Ip) -> + case init:get_argument(other_node_port) of + error -> + %% None specified. Default to 42. + Port = 42, + Version = 5, + {port, Port, Version}; + {ok, [[PortS]]} -> + %% Port number given on command line. + Port = list_to_integer(PortS), + Version = 5, + {port, Port, Version} + end. + %%% Utilities timestamp() -> diff --git a/erts/emulator/test/lttng_SUITE.erl b/erts/emulator/test/lttng_SUITE.erl index efc79f42ed..1360751aee 100644 --- a/erts/emulator/test/lttng_SUITE.erl +++ b/erts/emulator/test/lttng_SUITE.erl @@ -44,6 +44,7 @@ suite() -> all() -> [t_lttng_list, + t_memory_carrier, t_carrier_pool, t_async_io_pool, t_driver_start_stop, @@ -52,8 +53,7 @@ all() -> t_driver_timeout, t_driver_caller, t_driver_flush, - t_scheduler_poll, - t_memory_carrier]. + t_scheduler_poll]. init_per_suite(Config) -> @@ -120,7 +120,7 @@ t_lttng_list(_Config) -> %% com_ericsson_otp:carrier_pool_get %% com_ericsson_otp:carrier_pool_put t_carrier_pool(Config) -> - case have_carriers() of + case have_carriers(ets_alloc) of false -> {skip, "No Memory Carriers configured on system."}; true -> @@ -137,7 +137,7 @@ t_carrier_pool(Config) -> %% com_ericsson_otp:carrier_destroy %% com_ericsson_otp:carrier_create t_memory_carrier(Config) -> - case have_carriers() of + case have_carriers(ets_alloc) of false -> {skip, "No Memory Carriers configured on system."}; true -> @@ -178,11 +178,13 @@ t_async_io_pool(Config) -> %% com_ericsson_otp:driver_stop t_driver_start_stop(Config) -> ok = lttng_start_event("com_ericsson_otp:driver_*", Config), + timer:sleep(500), Path = proplists:get_value(priv_dir, Config), Name = filename:join(Path, "sometext.txt"), Bin = txt(), ok = file:write_file(Name, Bin), {ok, Bin} = file:read_file(Name), + timer:sleep(500), Res = lttng_stop_and_view(Config), ok = check_tracepoint("com_ericsson_otp:driver_start", Res), ok = check_tracepoint("com_ericsson_otp:driver_stop", Res), @@ -213,6 +215,7 @@ t_driver_control_ready_async(Config) -> %% com_ericsson_otp:driver_ready_output t_driver_ready_input_output(Config) -> ok = lttng_start_event("com_ericsson_otp:driver_ready_*", Config), + timer:sleep(500), Me = self(), Pid = spawn_link(fun() -> tcp_server(Me, active) end), receive {Pid, accept} -> ok end, @@ -225,6 +228,7 @@ t_driver_ready_input_output(Config) -> ok = gen_tcp:close(Sock), receive {Pid, done} -> ok end, + timer:sleep(500), Res = lttng_stop_and_view(Config), ok = check_tracepoint("com_ericsson_otp:driver_ready_input", Res), ok = check_tracepoint("com_ericsson_otp:driver_ready_output", Res), @@ -446,11 +450,10 @@ load_driver(Dir, Driver) -> %% check -have_carriers() -> - Cap = element(3,erlang:system_info(allocator)), - case Cap -- [sys_alloc,sys_aligned_alloc] of - [] -> false; - _ -> true +have_carriers(Alloc) -> + case erlang:system_info({allocator,Alloc}) of + false -> false; + _ -> true end. have_async_threads() -> diff --git a/erts/emulator/test/message_queue_data_SUITE.erl b/erts/emulator/test/message_queue_data_SUITE.erl index 226462676c..44e77dfad0 100644 --- a/erts/emulator/test/message_queue_data_SUITE.erl +++ b/erts/emulator/test/message_queue_data_SUITE.erl @@ -52,18 +52,12 @@ basic(Config) when is_list(Config) -> ok = rpc:call(Node2, ?MODULE, basic_test, [on_heap]), stop_node(Node2), - {ok, Node3} = start_node(Config, "+hmqd mixed"), - ok = rpc:call(Node3, ?MODULE, basic_test, [mixed]), - stop_node(Node3), - ok. is_valid_mqd_value(off_heap) -> true; is_valid_mqd_value(on_heap) -> true; -is_valid_mqd_value(mixed) -> - true; is_valid_mqd_value(_) -> false. @@ -78,9 +72,6 @@ basic_test(Default) -> {message_queue_data, off_heap} = process_info(self(), message_queue_data), off_heap = process_flag(message_queue_data, on_heap), {message_queue_data, on_heap} = process_info(self(), message_queue_data), - on_heap = process_flag(message_queue_data, mixed), - {message_queue_data, mixed} = process_info(self(), message_queue_data), - mixed = process_flag(message_queue_data, Default), {'EXIT', _} = (catch process_flag(message_queue_data, blupp)), P1 = spawn_opt(fun () -> receive after infinity -> ok end end, @@ -101,12 +92,6 @@ basic_test(Default) -> unlink(P3), exit(P3, bye), - P4 = spawn_opt(fun () -> receive after infinity -> ok end end, - [link, {message_queue_data, mixed}]), - {message_queue_data, mixed} = process_info(P4, message_queue_data), - unlink(P4), - exit(P4, bye), - {'EXIT', _} = (catch spawn_opt(fun () -> receive after infinity -> ok end end, [link, {message_queue_data, blapp}])), @@ -116,21 +101,18 @@ process_info_messages(Config) when is_list(Config) -> Tester = self(), P1 = spawn_opt(fun () -> receive after 500 -> ok end, - mixed = process_flag(message_queue_data, off_heap), + on_heap = process_flag(message_queue_data, off_heap), Tester ! first, receive after 500 -> ok end, off_heap = process_flag(message_queue_data, on_heap), Tester ! second, receive after 500 -> ok end, - on_heap = process_flag(message_queue_data, mixed), + on_heap = process_flag(message_queue_data, off_heap), Tester ! third, - receive after 500 -> ok end, - mixed = process_flag(message_queue_data, off_heap), - Tester ! fourth, receive after infinity -> ok end end, - [link, {message_queue_data, mixed}]), + [link, {message_queue_data, on_heap}]), P1 ! "A", receive first -> ok end, @@ -139,25 +121,20 @@ process_info_messages(Config) when is_list(Config) -> P1 ! "C", receive third -> ok end, P1 ! "D", - receive fourth -> ok end, - P1 ! "E", - {messages, ["A", "B", "C", "D", "E"]} = process_info(P1, messages), + {messages, ["A", "B", "C", "D"]} = process_info(P1, messages), P2 = spawn_opt(fun () -> receive after 500 -> ok end, - mixed = process_flag(message_queue_data, off_heap), + on_heap = process_flag(message_queue_data, off_heap), Tester ! first, receive after 500 -> ok end, off_heap = process_flag(message_queue_data, on_heap), Tester ! second, receive after 500 -> ok end, - on_heap = process_flag(message_queue_data, mixed), + on_heap = process_flag(message_queue_data, off_heap), Tester ! third, receive after 500 -> ok end, - mixed = process_flag(message_queue_data, off_heap), - Tester ! fourth, - receive after 500 -> ok end, Tester ! process_info(self(), messages), @@ -165,11 +142,10 @@ process_info_messages(Config) when is_list(Config) -> receive M2 -> M2 = "B" end, receive M3 -> M3 = "C" end, receive M4 -> M4 = "D" end, - receive M5 -> M5 = "E" end, Tester ! self() end, - [link, {message_queue_data, mixed}]), + [link, {message_queue_data, on_heap}]), P2 ! "A", receive first -> ok end, @@ -178,12 +154,10 @@ process_info_messages(Config) when is_list(Config) -> P2 ! "C", receive third -> ok end, P2 ! "D", - receive fourth -> ok end, - P2 ! "E", receive Msg -> - {messages, ["A", "B", "C", "D", "E"]} = Msg + {messages, ["A", "B", "C", "D"]} = Msg end, receive P2 -> ok end, diff --git a/erts/emulator/test/tracer_SUITE.erl b/erts/emulator/test/tracer_SUITE.erl index 20fb7e475e..9eb55c9af3 100644 --- a/erts/emulator/test/tracer_SUITE.erl +++ b/erts/emulator/test/tracer_SUITE.erl @@ -28,9 +28,9 @@ init_per_group/2,end_per_group/2, init_per_testcase/2, end_per_testcase/2]). -export([load/1, unload/1, reload/1, invalid_tracers/1]). --export([send/1, recv/1, spawn/1, exit/1, link/1, unlink/1, - getting_linked/1, getting_unlinked/1, register/1, unregister/1, - in/1, out/1, gc_start/1, gc_end/1]). +-export([send/1, recv/1, call/1, call_return/1, spawn/1, exit/1, + link/1, unlink/1, getting_linked/1, getting_unlinked/1, + register/1, unregister/1, in/1, out/1, gc_start/1, gc_end/1]). suite() -> [{ct_hooks,[ts_install_cth]}, {timetrap, {minutes, 1}}]. @@ -39,9 +39,9 @@ all() -> [load, unload, reload, invalid_tracers, {group, basic}]. groups() -> - [{ basic, [], [send, recv, spawn, exit, link, unlink, getting_linked, - getting_unlinked, register, unregister, in, out, - gc_start, gc_end]}]. + [{ basic, [], [send, recv, call, call_return, spawn, exit, + link, unlink, getting_linked, getting_unlinked, + register, unregister, in, out, gc_start, gc_end]}]. init_per_suite(Config) -> erlang:trace_pattern({'_','_','_'}, false, [local]), @@ -223,8 +223,8 @@ send(_Config) -> Expect = fun(Pid, State, EOpts) -> receive Msg -> - {send, State, Pid, ok, Self, Opts} = Msg, - check_opts(EOpts, Opts) + {send, State, Pid, ok, Opts} = Msg, + check_opts(EOpts, Opts, Self) end end, test(send, Tc, Expect). @@ -239,13 +239,59 @@ recv(_Config) -> Expect = fun(Pid, State, EOpts) -> receive Msg -> - {'receive', State, Pid, ok, undefined, Opts} = Msg, + {'receive', State, Pid, ok, Opts} = Msg, check_opts(EOpts, Opts) end end, test('receive', Tc, Expect, false). +call(_Config) -> + + Self = self(), + Tc = fun(Pid) -> + Pid ! fun() -> call_test(Self), Self ! ok end, + receive ok -> ok after 100 -> ct:fail(timeout) end + end, + + erlang:trace_pattern({?MODULE, call_test, 1}, [], [local]), + + Expect = fun(Pid, State, EOpts) -> + receive + Msg -> + {call, State, Pid, {?MODULE, call_test, [Self]}, Opts} = Msg, + check_opts(EOpts, Opts) + end + end, + test(call, Tc, Expect). + +call_return(_Config) -> + + Self = self(), + Tc = fun(Pid) -> + Pid ! fun() -> call_test(undefined), Self ! ok end, + receive ok -> ok after 100 -> ct:fail(timeout) end + end, + + 1 = erlang:trace_pattern({?MODULE, call_test, 1}, [{'_',[],[{return_trace}]}], [local]), + + Expect = fun(Pid, State, EOpts) -> + receive + CallMsg -> + {call, State, Pid, {?MODULE, call_test, [undefined]}, COpts} = CallMsg, + check_opts(EOpts, COpts) + end, + receive + RetMsg -> + {return_from, State, Pid, {?MODULE, call_test, 1}, ROpts} = RetMsg, + check_opts(EOpts, ROpts, undefined) + end + end, + test(call, Tc, Expect). + +call_test(Arg) -> + Arg. + spawn(_Config) -> Tc = fun(Pid) -> @@ -256,9 +302,8 @@ spawn(_Config) -> fun(Pid, State, EOpts) -> receive Msg -> - {spawn, State, Pid, NewPid, - {lists,seq,[1,10]}, Opts} = Msg, - check_opts(EOpts, Opts), + {spawn, State, Pid, NewPid, Opts} = Msg, + check_opts(EOpts, Opts, {lists,seq,[1,10]}), true = is_pid(NewPid) andalso NewPid /= Pid end end, @@ -274,7 +319,7 @@ exit(_Config) -> fun(Pid, State, EOpts) -> receive Msg -> - {exit, State, Pid, normal, undefined, Opts} = Msg, + {exit, State, Pid, normal, Opts} = Msg, check_opts(EOpts, Opts) end end, @@ -295,7 +340,7 @@ link(_Config) -> fun(Pid, State, EOpts) -> receive Msg -> - {link, State, Pid, NewPid, undefined, Opts} = Msg, + {link, State, Pid, NewPid, Opts} = Msg, check_opts(EOpts, Opts), true = is_pid(NewPid) andalso NewPid /= Pid end @@ -318,7 +363,7 @@ unlink(_Config) -> fun(Pid, State, EOpts) -> receive Msg -> - {unlink, State, Pid, NewPid, undefined, Opts} = Msg, + {unlink, State, Pid, NewPid, Opts} = Msg, check_opts(EOpts, Opts), true = is_pid(NewPid) andalso NewPid /= Pid end @@ -340,7 +385,7 @@ getting_linked(_Config) -> fun(Pid, State, EOpts) -> receive Msg -> - {getting_linked, State, Pid, NewPid, undefined, Opts} = Msg, + {getting_linked, State, Pid, NewPid, Opts} = Msg, check_opts(EOpts, Opts), true = is_pid(NewPid) andalso NewPid /= Pid end @@ -364,7 +409,7 @@ getting_unlinked(_Config) -> fun(Pid, State, EOpts) -> receive Msg -> - {getting_unlinked, State, Pid, NewPid, undefined, Opts} = Msg, + {getting_unlinked, State, Pid, NewPid, Opts} = Msg, check_opts(EOpts, Opts), true = is_pid(NewPid) andalso NewPid /= Pid end @@ -386,7 +431,7 @@ register(_Config) -> fun(Pid, State, EOpts) -> receive Msg -> - {register, State, Pid, ?MODULE, undefined, Opts} = Msg, + {register, State, Pid, ?MODULE, Opts} = Msg, check_opts(EOpts, Opts) end end, @@ -407,7 +452,7 @@ unregister(_Config) -> fun(Pid, State, EOpts) -> receive Msg -> - {unregister, State, Pid, ?MODULE, undefined, Opts} = Msg, + {unregister, State, Pid, ?MODULE, Opts} = Msg, check_opts(EOpts, Opts) end end, @@ -427,8 +472,7 @@ in(_Config) -> N = (fun F(N) -> receive Msg -> - {in, State, Pid, _, - undefined, Opts} = Msg, + {in, State, Pid, _, Opts} = Msg, check_opts(EOpts, Opts), F(N+1) after 0 -> N @@ -452,8 +496,7 @@ out(_Config) -> N = (fun F(N) -> receive Msg -> - {out, State, Pid, _, - undefined, Opts} = Msg, + {out, State, Pid, _, Opts} = Msg, check_opts(EOpts, Opts), F(N+1) after 0 -> N @@ -477,7 +520,7 @@ gc_start(_Config) -> fun(Pid, State, EOpts) -> receive Msg -> - {gc_major_start, State, Pid, _, undefined, Opts} = Msg, + {gc_major_start, State, Pid, _, Opts} = Msg, check_opts(EOpts, Opts) end end, @@ -497,7 +540,7 @@ gc_end(_Config) -> fun(Pid, State, EOpts) -> receive Msg -> - {gc_major_end, State, Pid, _, undefined, Opts} = Msg, + {gc_major_end, State, Pid, _, Opts} = Msg, check_opts(EOpts, Opts) end end, @@ -513,9 +556,7 @@ test(Event, TraceFlag, Tc, Expect, Removes) -> test(Event, TraceFlag, Tc, Expect, _Removes, Dies) -> ComplexState = {fun() -> ok end, <<0:(128*8)>>}, - Opts = #{ timestamp => undefined, - scheduler_id => undefined, - match_spec_result => true }, + Opts = #{ }, %% Test that trace works State1 = {#{ Event => trace }, self(), ComplexState}, @@ -540,8 +581,8 @@ test(Event, TraceFlag, Tc, Expect, _Removes, Dies) -> Tc(Pid1T), ok = trace_delivered(Pid1T), - Expect(Pid1T, State1, Opts#{ scheduler_id := number, - timestamp := timestamp}), + Expect(Pid1T, State1, Opts#{ scheduler_id => number, + timestamp => timestamp}), receive M11T -> ct:fail({unexpected, M11T}) after 0 -> ok end, if not Dies -> {flags, [scheduler_id, TraceFlag, timestamp]} @@ -568,6 +609,8 @@ test(Event, TraceFlag, Tc, Expect, _Removes, Dies) -> ok. +check_opts(E, O, Extra) -> + check_opts(E#{ extra => Extra }, O). check_opts(#{ scheduler_id := number } = E, #{ scheduler_id := N } = O) when is_integer(N) -> E1 = maps:remove(scheduler_id, E), diff --git a/erts/emulator/test/tracer_SUITE_data/tracer_test.c b/erts/emulator/test/tracer_SUITE_data/tracer_test.c index 908f35da9c..a26bb33600 100644 --- a/erts/emulator/test/tracer_SUITE_data/tracer_test.c +++ b/erts/emulator/test/tracer_SUITE_data/tracer_test.c @@ -36,7 +36,7 @@ static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ErlNifFunc nif_funcs[] = { {"enabled", 3, enabled}, - {"trace", 6, trace} + {"trace", 5, trace} }; ERL_NIF_INIT(tracer_test, nif_funcs, load, NULL, upgrade, unload) @@ -100,7 +100,7 @@ static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) ErlNifPid self, to; ERL_NIF_TERM *tuple, msg; const ERL_NIF_TERM *state_tuple; - ASSERT(argc == 6); + ASSERT(argc == 5); enif_get_tuple(env, argv[1], &state_arity, &state_tuple); diff --git a/erts/emulator/test/tracer_test.erl b/erts/emulator/test/tracer_test.erl index d4778f4531..1da80bfe31 100644 --- a/erts/emulator/test/tracer_test.erl +++ b/erts/emulator/test/tracer_test.erl @@ -24,14 +24,14 @@ %%% Test tracer %%% --export([enabled/3, trace/6]). +-export([enabled/3, trace/5]). -export([load/1, load/2]). -on_load(load/0). enabled(_, _, _) -> erlang:nif_error(nif_not_loaded). -trace(_, _, _, _, _, _) -> +trace(_, _, _, _, _) -> erlang:nif_error(nif_not_loaded). load() -> |