diff options
Diffstat (limited to 'lib/runtime_tools/test')
-rw-r--r-- | lib/runtime_tools/test/Makefile | 2 | ||||
-rw-r--r-- | lib/runtime_tools/test/dbg_SUITE.erl | 69 | ||||
-rw-r--r-- | lib/runtime_tools/test/inviso_SUITE.erl | 2838 | ||||
-rw-r--r-- | lib/runtime_tools/test/inviso_testmodule1_foo.erl | 9 | ||||
-rw-r--r-- | lib/runtime_tools/test/runtime_tools_SUITE.erl | 21 |
5 files changed, 45 insertions, 2894 deletions
diff --git a/lib/runtime_tools/test/Makefile b/lib/runtime_tools/test/Makefile index 4979b9c7b1..bcabdf13ed 100644 --- a/lib/runtime_tools/test/Makefile +++ b/lib/runtime_tools/test/Makefile @@ -5,8 +5,6 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk MODULES = \ dyntrace_SUITE \ runtime_tools_SUITE \ - inviso_testmodule1_foo \ - inviso_SUITE \ dbg_SUITE \ erts_alloc_config_SUITE diff --git a/lib/runtime_tools/test/dbg_SUITE.erl b/lib/runtime_tools/test/dbg_SUITE.erl index bd908c1f3a..dfae52ed1d 100644 --- a/lib/runtime_tools/test/dbg_SUITE.erl +++ b/lib/runtime_tools/test/dbg_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2011. All Rights Reserved. +%% Copyright Ericsson AB 2010-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 @@ -394,41 +394,36 @@ file_port2(suite) -> file_port2(doc) -> ["Test tracing to file port with 'follow_file'"]; file_port2(Config) when is_list(Config) -> - case os:type() of - vxworks -> - {skipped, "VxWorks NFS cache ruins it all."}; - _ -> - ?line stop(), - ?line {A,B,C} = erlang:now(), - ?line FTMP = atom_to_list(?MODULE) ++ integer_to_list(A) ++ - "-" ++ integer_to_list(B) ++ "-" ++ integer_to_list(C), - ?line FName = filename:join([?config(data_dir, Config), FTMP]), - %% Ok, lets try with flush and follow_file, not a chance on VxWorks - %% with NFS caching... - ?line Port2 = dbg:trace_port(file, FName), - ?line {ok, _} = dbg:tracer(port, Port2), - try - ?line {ok, [{matched, _node, 1}]} = dbg:p(self(),call), - ?line {ok, _} = dbg:tp(dbg, ltp,[{'_',[],[{message, {self}}]}]), - ?line {ok, _} = dbg:tp(dbg, ln, [{'_',[],[{message, hej}]}]), - ?line ok = dbg:ltp(), - ?line ok = dbg:flush_trace_port(), - ?line dbg:trace_client(follow_file, FName, - {fun myhandler/2, self()}), - ?line S = self(), - ?line [{trace,S,call,{dbg,ltp,[]},S}] = flush(), - ?line ok = dbg:ln(), - ?line ok = dbg:flush_trace_port(), - ?line receive after 1000 -> ok end, %% Polls every second... - ?line [{trace,S,call,{dbg,ln,[]},hej}] = flush(), - ?line stop(), - ?line [] = flush() - after - ?line stop(), - ?line file:delete(FName) - end, - ok - end. + stop(), + {A,B,C} = erlang:now(), + FTMP = atom_to_list(?MODULE) ++ integer_to_list(A) ++ + "-" ++ integer_to_list(B) ++ "-" ++ integer_to_list(C), + FName = filename:join([?config(data_dir, Config), FTMP]), + %% Ok, lets try with flush and follow_file, not a chance on VxWorks + %% with NFS caching... + Port2 = dbg:trace_port(file, FName), + {ok, _} = dbg:tracer(port, Port2), + try + {ok, [{matched, _node, 1}]} = dbg:p(self(),call), + {ok, _} = dbg:tp(dbg, ltp,[{'_',[],[{message, {self}}]}]), + {ok, _} = dbg:tp(dbg, ln, [{'_',[],[{message, hej}]}]), + ok = dbg:ltp(), + ok = dbg:flush_trace_port(), + dbg:trace_client(follow_file, FName, + {fun myhandler/2, self()}), + S = self(), + [{trace,S,call,{dbg,ltp,[]},S}] = flush(), + ok = dbg:ln(), + ok = dbg:flush_trace_port(), + receive after 1000 -> ok end, %% Polls every second... + [{trace,S,call,{dbg,ln,[]},hej}] = flush(), + stop(), + [] = flush() + after + stop(), + file:delete(FName) + end, + ok. file_port_schedfix(suite) -> []; @@ -519,7 +514,7 @@ file_port_schedfix1(Config) when is_list(Config) -> %% Cleanup %% ?line ToBeDeleted = filelib:wildcard(FName++"*"++".wraplog"), - ?line lists:map({file, delete}, ToBeDeleted), + ?line lists:map(fun file:delete/1, ToBeDeleted), % io:format("ToBeDeleted=~p", [ToBeDeleted]), %% %% Present the result diff --git a/lib/runtime_tools/test/inviso_SUITE.erl b/lib/runtime_tools/test/inviso_SUITE.erl deleted file mode 100644 index c64c40b945..0000000000 --- a/lib/runtime_tools/test/inviso_SUITE.erl +++ /dev/null @@ -1,2838 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010-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 -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% %CopyrightEnd% -%% -%% Description: -%% Test suite for inviso (basic parts, i.e not inviso tools). Note that -%% inviso basic parts have modules in both the runtime_tools and -%% inviso applications. -%% -%% Authors: -%% Ann-Marie L�f, [email protected] -%% Lennart �hman, [email protected] -%% ----------------------------------------------------------------------------- - --module(inviso_SUITE). --compile(export_all). - --include_lib("common_test/include/ct.hrl"). --include_lib("kernel/include/file.hrl"). - --define(l,?line). - -suite() -> [{ct_hooks,[ts_install_cth]}]. - -all() -> - [basic_dist_trace_1, basic_dist_trace_2, - basic_dist_trace_3, basic_dist_trace_ti_1, - basic_dist_trace_ti_2, basic_dist_trace_ti_3, - suspend_dist_trace_ti_1, suspend_dist_trace_ti_2, - meta_cleanfunc_dist_1, basic_handlerfun_dist_1, - delete_log_dist_1, autostart_dist_1, autostart_dist_2, - autostart_dist_3, running_alone_dist_1, - running_alone_dist_2, running_alone_dist_3, - running_alone_dist_4, running_alone_dist_5, - overload_dist_1, overload_dist_2, overload_dist_3, - overload_dist_4, overload_dist_5, subscribe_dist_1, - lfm_trace_dist_1, lfm_trace_ti_dist_2, - handle_logfile_sort_wrapset, fetch_log_dist_trace_1, - fetch_log_dist_trace_2, fetch_log_dist_trace_3, - fetch_log_dist_error_1, fetch_log_dist_error_2, - expand_regexp_dist_1, only_loaded_dist_1]. - -groups() -> - []. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - - - -init_per_suite(Config) -> - case test_server:is_native(lists) of - true -> - {skip,"Native libs -- tracing doesn't work"}; - false -> - %% We never know who messed up this node before this suite! :-) - erlang:trace_pattern({'_','_','_'},[],[local]), - erlang:trace_pattern({'_','_','_'},[],[global]), - erlang:trace(all,false,[all]), - - ok=application:start(runtime_tools), - Config - end. - -end_per_suite(_Config) -> - ?l ok=application:stop(runtime_tools). - - -%% For each distributed testcase, we need two other distributed nodes to run the -%% runtime components on. Since they are freshly started every time there is no -%% need to clean them up first. -init_per_testcase(_Case,Config) -> - ?l TH=test_server:timetrap(100000), - ?l {ok,Node1}=test_server:start_node(inviso1,peer,[]), - ?l {ok,Node2}=test_server:start_node(inviso2,peer,[]), - ?l SuiteDir=filename:dirname(code:which(?MODULE)), - - %% Otherwise peer nodes will not find this module! - ?l true=rpc:call(Node1,code,add_patha,[SuiteDir]), - ?l true=rpc:call(Node2,code,add_patha,[SuiteDir]), - - ?l start_side_effect_logger(node()), - ?l start_side_effect_logger(Node1), - ?l start_side_effect_logger(Node2), - - - %% SPECIAL FOR MY PRIVATE TEST ENVIROMENT -% ?l rpc:call(Node1,code,add_patha,["/clearcase/otp/tools/runtime_tools/ebin"]), -% ?l rpc:call(Node1,code,add_patha,["/clearcase/otp/tools/inviso/ebin"]), -% ?l rpc:call(Node2,code,add_patha,["/clearcase/otp/tools/runtime_tools/ebin"]), -% ?l rpc:call(Node2,code,add_patha,["/clearcase/otp/tools/inviso/ebin"]), - -% %% SPECIAL FOR MY PRIVATE TEST ENVIROMENT, windows. -% ?l rpc:call(Node1,code,add_patha,["Z:/DATA/PROJECTS/inviso_project/runtime_tools/ebin"]), -% ?l rpc:call(Node1,code,add_patha,["Z:/DATA/PROJECTS/inviso_project/inviso/ebin"]), -% ?l rpc:call(Node2,code,add_patha,["Z:/DATA/PROJECTS/inviso_project/runtime_tools/ebin"]), -% ?l rpc:call(Node2,code,add_patha,["Z:/DATA/PROJECTS/inviso_project/inviso/ebin"]), - - ?l ok=rpc:call(Node1,application,start,[runtime_tools]), - ?l ok=rpc:call(Node2,application,start,[runtime_tools]), - ?l timer:sleep(100), % Problem with autostarted runtime. - %% The following is a test that the inviso_rt processes which are autostarted - %% are now gone. - - ?l ok=poll(rpc,call,[Node1,erlang,whereis,[inviso_rt]],undefined,20), - ?l ok=poll(rpc,call,[Node2,erlang,whereis,[inviso_rt]],undefined,20), - -% ?l ok=poll(rpc,call,[Node1,supervisor,which_children,[runtime_tools_sup]],[],20), -% ?l ok=poll(rpc,call,[Node2,supervisor,which_children,[runtime_tools_sup]],[],20), - NewConfig1=insert_remotenode_config(inviso1,Node1,Config), - NewConfig2=insert_remotenode_config(inviso2,Node2,NewConfig1), - insert_timetraphandle_config(TH,NewConfig2). -%% ----------------------------------------------------------------------------- - -end_per_testcase(Case,Config) -> - ?l test_server:stop_node(get_remotenode_config(inviso1,Config)), - ?l test_server:stop_node(get_remotenode_config(inviso2,Config)), - - case whereis(inviso_c) of - undefined -> % Should not exist. - true; - Pid when is_pid(Pid) -> % But if it exists... - exit(Pid,kill), % Remove it! - io:format("Had to kill the control component in end_per_testcase,~p.~n",[Case]) - end, - case whereis(inviso_rt) of - undefined -> % Should not exist. - true; - Pid2 when is_pid(Pid2) -> % But if it exists... - exit(Pid2,kill), % Remove it! - io:format("Had to kill local runtime component in end_per_testcase,~p.~n",[Case]) - end, - ?l process_killer([inviso_test_proc, - inviso_tab_proc, - inviso_collector_proc, - global_inviso_test_proc]), - ?l test_server:timetrap_cancel(get_timetraphandle_config(Config)), - - NewConfig1=remove_remotenode_config(inviso1,Config), - NewConfig2=remove_remotenode_config(inviso2,NewConfig1), - remove_timetraphandle_config(NewConfig2). -%% ----------------------------------------------------------------------------- - -%% ============================================================================== -%% Testcases. -%% ============================================================================== - -%% TEST CASE: Basic, distributed, trace only. -basic_dist_trace_1(suite) -> []; -basic_dist_trace_1(doc) -> - ["Basic case, start of distributed tracing, using only trac."]; -basic_dist_trace_1(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataList=lists:map(fun(N)->{N,{file,filename:join([PrivDir, - "tf1_"++ - atom_to_list(N) - ])}} end, - Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok}]}), - activate_local_tracing(Nodes), - deactivate_local_tracing(Nodes), - stop_tracing(Nodes), - stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - - -%% TEST CASE: Basic, distributed, activate global tracing for functions in modules -%% pointed out using a regexp. No tracing will be done. -basic_dist_trace_2(suite) -> []; -basic_dist_trace_2(doc) -> - [""]; -basic_dist_trace_2(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataList=lists:map(fun(N)->{N,{file,filename:join([PrivDir, - "tf1a_"++ - atom_to_list(N) - ])}} end, - Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok}]}), - Funcs1=activate_global_tracing_regexp(Nodes), - deactivate_global_tracing_regexp(Nodes,Funcs1), - stop_tracing(Nodes), - stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Basic, distributed, activate global tracing for functions in modules -%% pointed out using a dir-regexp. No tracing will be done. -basic_dist_trace_3(suite) -> []; -basic_dist_trace_3(doc) -> - [""]; -basic_dist_trace_3(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataList=lists:map(fun(N)->{N,{file,filename:join([PrivDir, - "tf1b_"++ - atom_to_list(N) - ])}} end, - Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok}]}), - Funcs1=activate_global_tracing_regexp_dir(Nodes), - deactivate_global_tracing_regexp_dir(Nodes,Funcs1), - stop_tracing(Nodes), - stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Basic, distributed, trace and ti. -basic_dist_trace_ti_1(suite) -> []; -basic_dist_trace_ti_1(doc) -> - [""]; -basic_dist_trace_ti_1(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataFun= - fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf2_"++atom_to_list(N)])}}, - {ti,{file,filename:join([PrivDir,"tf2_"++atom_to_list(N)++".ti"])}}]} - end, - TracerDataList=lists:map(TracerDataFun,Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), - activate_local_tracing(Nodes), - activate_meta_tracing(Nodes), - ?l true=(is_pid(whereis(inviso_rt))), - ?l true=(is_pid(whereis(inviso_rt_meta))), - deactivate_meta_tracing(Nodes), - deactivate_local_tracing(Nodes), - stop_tracing(Nodes), - ?l true=(is_pid(whereis(inviso_rt))), % Shall still be running. - ?l ok=poll(erlang,whereis,[inviso_rt_meta],undefined,3), - stop(Nodes), - timer:sleep(200), % Give it time to terminate. - ?l ok=poll(erlang,whereis,[inviso_rt],undefined,3),% Shall be gone now. - ?l undefined=whereis(inviso_rt_meta), % Still gone. - ok. -%% ----------------------------------------------------------------------------- - -%% Test CASE: Testing that the tpm_tracer functionality works. That is appending -%% {tracer,Tracer} to a meta match spec. -basic_dist_trace_ti_2(suite) -> []; -basic_dist_trace_ti_2(doc) -> - [""]; -basic_dist_trace_ti_2(Config) when is_list(Config) -> - case erlang:system_info(version) of - "5.4"++_ -> % Perhaps not perfect, but work now :-) - {skip,"Old emulator"}; - _ -> - basic_dist_trace_ti_2_do(Config) - end. - -basic_dist_trace_ti_2_do(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataFun= - fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf3_"++atom_to_list(N)])}}, - {ti,{file,filename:join([PrivDir,"tf3_"++atom_to_list(N)++".ti"])}}]} - end, - TracerDataList=lists:map(TracerDataFun,Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), - activate_deactivate_meta_tracing_tracer(Nodes), - stop_tracing(Nodes), - stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Basic, distributed, trace and ti, where we try to use ctp_all to -%% check that all global and local patterns are removed but that meta patterns -%% remain. -%% This test also checks that if the meta tracer is terminated an error value -%% is generated when trying to do meta tracing at that node. -basic_dist_trace_ti_3(suite) -> []; -basic_dist_trace_ti_3(doc) -> - [""]; -basic_dist_trace_ti_3(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataFun= - fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf4_"++atom_to_list(N)])}}, - {ti,{file,filename:join([PrivDir,"tf4_"++atom_to_list(N)++".ti"])}}]} - end, - TracerDataList=lists:map(TracerDataFun,Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), - activate_local_tracing(Nodes), - activate_global_tracing(Nodes), - activate_meta_tracing(Nodes), - ?l true=(is_pid(whereis(inviso_rt))), - ?l true=(is_pid(whereis(inviso_rt_meta))), - ?l {ok,NodeResults1}=inviso:ctp_all(Nodes), % Removes local and global patterns. - ?l true=check_noderesults(Nodes,ok,NodeResults1), - ?l true=check_on_nodes(Nodes,erlang,trace_info,[{code,which,1},traced],{traced,false}), - ?l true=check_on_nodes(Nodes,erlang,trace_info,[{code,get_path,0},traced],{traced,false}), - %% But meta patters shall remain. - ?l true=check_on_nodes(Nodes, - erlang, - trace_info, - [{lists,module_info,0},meta_match_spec], - fun({meta_match_spec,L})when length(L)>0 ->true end), - ?l true=check_on_nodes(Nodes, - erlang, - trace_info, - [{lists,module_info,0},meta], - fun({meta,P})when is_pid(P) -> - P=rpc:call(node(P),erlang,whereis,[inviso_rt_meta]), - true - end), - %% Now kill the meta tracer somewhere and try to activate meta tracing. - ?l [ANode|_]=Nodes, - ?l AMetaPid=rpc:call(ANode,erlang,whereis,[inviso_rt_meta]), - ?l rpc:call(ANode,erlang,exit,[AMetaPid,kill]), - ?l {ok,NodeResults2}=inviso:tpm(Nodes,math,pi,0,[],void), - ?l {value,{ANode,{error,_}}}=lists:keysearch(ANode,1,NodeResults2), - - ?l stop_tracing(Nodes), - ?l stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - -%% ----------------------------------------------------------------------------- -%% Test cases for SUSPEND -%% ----------------------------------------------------------------------------- - -%% TEST CASE: In this test case a trace with ti is started. Trace flags are set, -%% trace patterns are set and meta trace patterns. We then check that the trace -%% flags and the meta patterns are removed when tracing suspended. -%% The suspension is cancelled and we check that it is possible to reactivate -%% tracing by setting the process flags and meta patterns again. -suspend_dist_trace_ti_1(suite) -> []; -suspend_dist_trace_ti_1(doc) -> - [""]; -suspend_dist_trace_ti_1(Config) when is_list(Config) -> - ?l RemoteNodes=get_remotenodes_config(Config), - ?l Nodes=[node()|RemoteNodes], - ?l PrivDir=filename:join(?config(priv_dir,Config),""), - ?l TracerDataFun= - fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf_suspend1_"++atom_to_list(N)])}}, - {ti,{file,filename:join([PrivDir,"tf_suspend1_"++atom_to_list(N)++".ti"])}}]} - end, - ?l TracerDataList=lists:map(TracerDataFun,Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), - activate_local_tracing(Nodes), - activate_meta_tracing(Nodes), - ?l true=(is_pid(whereis(inviso_rt))), - ?l true=(is_pid(whereis(inviso_rt_meta))), - %% Set some trace flags on some newly started test procs. - activate_traceflags(Nodes), - - %% Now suspend the tracing on all nodes. That shall result in the removal - %% of trace flags and meta trace patterns, but not local trace patterns. - ?l {ok,NodeResults1}=inviso:suspend(Nodes,test), - ?l true=check_noderesults(Nodes,ok,NodeResults1), - %% Trace flags gone? - ?l TestProcs=lists:map(fun(N)->rpc:call(N,erlang,whereis,[inviso_test_proc]) end,Nodes), - ?l lists:foreach(fun(P)-> - {flags,[]}= - rpc:call(node(P),erlang,trace_info,[P,flags]) - end, - TestProcs), - %% Meta patterns shall be gone too, but local functions still there. - ?l lists:foreach(fun(N)-> - {meta,false}= - rpc:call(N, - erlang, - trace_info, - [{math,module_info,1},meta]), - {traced,local}= - rpc:call(N, - erlang, - trace_info, - [{code,which,1},traced]) - end, - Nodes), - - %% Try to activate trace flags, trace patterns and meta tracing while - %% suspended. Should not succeed of course! - ?l ThisNode=node(), - ?l {ok,[{ThisNode,{error,suspended}}]}= - inviso:tf([ThisNode],inviso_test_proc,[call]), - ?l {ok,[{ThisNode,{error,suspended}}]}= - inviso:tpl([ThisNode],math,module_info,1,[]), - ?l {ok,[{ThisNode,{error,suspended}}]}= - inviso:init_tpm([ThisNode], - math, - module_info, - 1, - {?MODULE,tpm_init_func2}, % Does not exist on purpose. - {?MODULE,tpm_call_func2}, % Does not exist on purpose. - {?MODULE,tpm_return_func2}, % Does not exist on purpose. - {?MODULE,tpm_remove_func2}), % Does not exist on purpose. - - %% Now we want to cancel suspension and see that we can reactivate tracing. - ?l {ok,NodeResults2}=inviso:cancel_suspension(Nodes), - ?l true=check_noderesults(Nodes,ok,NodeResults2), - - ?l {ok,NodeResults3}= - inviso:init_tpm(math, - module_info, - 1, - {?MODULE,tpm_init_func2}, % Does not exist on purpose. - {?MODULE,tpm_call_func2}, % Does not exist on purpose. - {?MODULE,tpm_return_func2}, % Does not exist on purpose. - {?MODULE,tpm_remove_func2}), % Does not exist on purpose. - ?l true=check_noderesults(Nodes,ok,NodeResults3), - ?l {ok,NodeResults5}= - inviso:tpm_ms(math,module_info,1,ms1,[{'_',[],[{return_trace}]}]), - ?l true=check_noderesults(Nodes,{ok,1},NodeResults5), - ?l true=check_on_nodes(Nodes, - erlang, - trace_info, - [{math,module_info,1},meta_match_spec], - {meta_match_spec,[{'_',[],[{return_trace}]}]}), - ?l {ok,NodeResults6}=inviso:tf(Nodes,inviso_test_proc,[call]), - ?l true=check_noderesults(Nodes,{ok,[1]},NodeResults6), - - %deactivate_meta_tracing(Nodes), - %deactivate_local_tracing(Nodes), - stop_tracing(Nodes), - ?l true=(is_pid(whereis(inviso_rt))), % Shall still be running. - ?l ok=poll(erlang,whereis,[inviso_rt_meta],undefined,3), - stop(Nodes), - ?l timer:sleep(200), % Give it time to terminate. - ?l ok=poll(erlang,whereis,[inviso_rt],undefined,3),% Shall be gone now. - ?l undefined=whereis(inviso_rt_meta), % Still gone. - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: In this test case a trace with ti is started. Trace flags are set, -%% trace patterns are set and meta trace patterns. We then suspend tracing at -%% all nodes, then stop tracing which shall be allowed. We then try to initiate -%% tracing again which shall not be possible. -suspend_dist_trace_ti_2(suite) -> []; -suspend_dist_trace_ti_2(doc) -> - [""]; -suspend_dist_trace_ti_2(Config) when is_list(Config) -> - ?l RemoteNodes=get_remotenodes_config(Config), - ?l Nodes=[node()|RemoteNodes], - ?l PrivDir=filename:join(?config(priv_dir,Config),""), - ?l TracerDataFun= - fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf_suspend2_"++atom_to_list(N)])}}, - {ti,{file,filename:join([PrivDir,"tf_suspend2_"++atom_to_list(N)++".ti"])}}]} - end, - ?l TracerDataList=lists:map(TracerDataFun,Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), - activate_local_tracing(Nodes), - activate_meta_tracing(Nodes), - ?l true=(is_pid(whereis(inviso_rt))), - ?l true=(is_pid(whereis(inviso_rt_meta))), - %% Set some trace flags on some newly started test procs. - activate_traceflags(Nodes), - - %% Now suspend the tracing on all nodes. That shall result in the removal - %% of trace flags and meta trace patterns, but not local trace patterns. - ?l {ok,NodeResults1}=inviso:suspend(Nodes,test), - ?l true=check_noderesults(Nodes,ok,NodeResults1), - - %% Now stop tracing. - ?l {ok,NodeResults3}=inviso:stop_tracing(Nodes), - ?l true=check_noderesults(Nodes,{ok,idle},NodeResults3), - %% Now try to initiate tracing again. - ThisNode=node(), - ?l {ok,[{ThisNode,{error,suspended}}]}= - inviso:init_tracing([ThisNode], - [{trace,{file,filename:join([PrivDir,"tf_suspend3_"++ - atom_to_list(ThisNode)])}}, - {ti,{file,{filename:join([PrivDir,"tf_suspend3_"++ - atom_to_list(ThisNode)])}}}]), - - %% Cancel the suspension and initiate tracing again. - ?l {ok,NodeResults2}=inviso:cancel_suspension(Nodes), - ?l true=check_noderesults(Nodes,ok,NodeResults2), - ?l TracerDataFun2= - fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf_suspend4_"++atom_to_list(N)])}}, - {ti,{file,filename:join([PrivDir,"tf_suspend4_"++atom_to_list(N)++".ti"])}}]} - end, - ?l TracerDataList2=lists:map(TracerDataFun2,Nodes), - ?l {ok,NodeResults4}=inviso:init_tracing(TracerDataList2), - ?l true=check_noderesults(Nodes,{ok,[{trace_log,ok},{ti_log,ok}]},NodeResults4), - stop_tracing(Nodes), - ?l true=(is_pid(whereis(inviso_rt))), % Shall still be running. - stop(Nodes), - ?l timer:sleep(200), % Give it time to terminate. - ?l ok=poll(erlang,whereis,[inviso_rt],undefined,3),% Shall be gone now. - ok. -%% ----------------------------------------------------------------------------- - - - -%% TEST CASE: This test case tests that the clean function removes (prosumed) -%% expired data from the internal public-loopdata structure in the inviso_rt_meta -%% process. -meta_cleanfunc_dist_1(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataFun= - fun(N)->{N,[{trace,{file,filename:join([PrivDir,"mcf1_"++atom_to_list(N)])}}, - {ti,{file,filename:join([PrivDir,"mcf1_"++atom_to_list(N)++".ti"])}}]} - end, - TracerDataList=lists:map(TracerDataFun,Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), - %% Now initialize meta tracing, but the call_func is a bit "fixed". - ?l {ok,NodeResults1}= - inviso:tpm(Nodes,math,module_info,1,[], - {?MODULE,meta_cleanfunc_initfunc_1}, - {?MODULE,meta_cleanfunc_callfunc_1}, - void,void), - ?l true=check_noderesults(Nodes,{ok,1},NodeResults1), - %% Nothing in the "our" part of the public loop data. - ?l true=check_on_nodes(Nodes, - inviso_rt_meta,get_state,[inviso_rt_meta], - fun({ok,_LD,{{_,[]},_}})->true end), - ?l lists:foreach(fun(N)->rpc:call(N,math,module_info,[exports]) end,Nodes), - %% Check that it has been added to the public loopdata structure. - ?l true=check_on_nodes(Nodes, - ?MODULE,poll,[inviso_rt_meta, - get_state, - [inviso_rt_meta], - fun({ok,_LD,{{_,[{meta_cleanfunc_test1,_Now}]},_}})-> - true; - (_)->false - end, - 20], - ok), - %% While we wait for 60 seconds to pass, we test a few other things. - ?l {ok,NodeResults2}= - inviso:tpm(Nodes,?MODULE,slowfunction2,0,[{'_',[],[{return_trace}]}], - {?MODULE,meta_cleanfunc_initfunc_2}, - {?MODULE,meta_cleanfunc_callfunc_2}, - {?MODULE,meta_cleanfunc_returnfunc_2}, - void), - ?l true=check_noderesults(Nodes,{ok,1},NodeResults2), - ?l lists:foreach(fun(N)->rpc:call(N,?MODULE,slowfunction,[]) end,Nodes), - %% Believe it or not but slowfunction is still running, in its own process, - %% we are therefore free now to examine the meta tracer. - ?l true=check_on_nodes(Nodes, - ?MODULE,poll,[inviso_rt_meta, - get_state, - [inviso_rt_meta], - fun({ok,_LD,{{[],Tuples},_}})-> - {value,_}= - lists:keysearch(meta_cleanfunc_test2, - 1, - Tuples), - {value,_}= - lists:keysearch(meta_cleanfunc_test1, - 1, - Tuples), - true; - (_)-> - false - end, - 20], - ok), - %% Now we wait for slowfunction to return and that the meta_cleanfunc_test2 - %% to be removed from public loopdata strucuture. - ?l timer:sleep(10000), - %% The only thing remaining should be the meta_cleanfunc_test1 which will not - %% go away for less than that the clean functionality removes it. - ?l true=check_on_nodes(Nodes, - ?MODULE,poll,[inviso_rt_meta, - get_state, - [inviso_rt_meta], - fun({ok,_LD,{{_,[{meta_cleanfunc_test1,_Now}]},_}})-> - true; - (_)-> - false - end, - 20], - ok), - %% Wait for the clean function to clean meta_cleanfunc_test1 away. - ?l timer:sleep(51000), % Shall be gone after 5 seconds. - ?l true=check_on_nodes(Nodes, - ?MODULE,poll,[inviso_rt_meta, - get_state, - [inviso_rt_meta], - fun({ok,_LD,{{_,[]},_}})->true; - (_)->false - end, - 20], - ok), - stop_tracing(Nodes), - stop(Nodes), - ok. - -%% This function acts as tpm initialization function when we are going to test -%% that the clean function works. Note that we here assume standard public loop -%% datastructure. -meta_cleanfunc_initfunc_1(_M,_F,_Arity,{E1,_E2}) -> - {ok,{E1,[]},void}. -%% Function that is supposed to be called when the meta traced function is -%% called. -meta_cleanfunc_callfunc_1(_Pid,_Args,{{E1,E2},Global}) -> - {ok,{{E1,[{meta_cleanfunc_test1,now()}|E2]},Global},void}. - -meta_cleanfunc_initfunc_2(_M,_F,_Arity,PublLD) -> - {ok,PublLD,void}. -meta_cleanfunc_callfunc_2(_Pid,_Args,{{E1,E2},Global}) -> - {ok,{{E1,[{meta_cleanfunc_test2,now()}|E2]},Global},void}. -meta_cleanfunc_returnfunc_2(_Pid,_,{{E1,E2},Global}) -> - {value,_}=lists:keysearch(meta_cleanfunc_test2,1,E2), - {ok,{{E1,lists:keydelete(meta_cleanfunc_test2,1,E2)},Global},void}. - -slowfunction() -> - spawn(?MODULE,slowfunction1,[]). -slowfunction1() -> - slowfunction2(). % Meta trace on this function call. -slowfunction2() -> - timer:sleep(2000), - true. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Testing that a runtime component can be started instructing it -%% to use a handler fun. Checks that the handler fun is called if a trace -%% message comes in. -basic_handlerfun_dist_1(suite) -> []; -basic_handlerfun_dist_1(doc) -> - [""]; -basic_handlerfun_dist_1(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - ?l lists:foreach(fun(N)->rpc:call(N,ets,insert,[inviso_sideeffect_tab,{bhf1,0}]) end, - Nodes), - TracerDataFun= - fun(N)->{N,{fun basic_handlerfun_dist_1_fun/2,inviso_sideeffect_tab}} end, - TracerDataList=lists:map(TracerDataFun,Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok}]}), - activate_local_tracing(Nodes), - activate_traceflags(Nodes), - ?l lists:foreach(fun(N)->[{bhf1,0}]= - rpc:call(N,ets,lookup,[inviso_sideeffect_tab,bhf1]) - end, - Nodes), - ?l inviso_test_proc ! {apply,code,which,[lists]}, - ok=poll(ets,lookup,[inviso_sideeffect_tab,bhf1],[{bhf1,1}],20), - deactivate_traceflags(Nodes), - deactivate_local_tracing(Nodes), - stop_tracing(Nodes), - timer:sleep(100), - ?l [{bhf1,1}]=ets:lookup(inviso_sideeffect_tab,bhf1), - stop(Nodes), - ok. - -%% Function used as handler fun for testcase above. -basic_handlerfun_dist_1_fun(_Msg,TId) -> - ets:update_counter(TId,bhf1,1), - TId. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Here we test that delete_log removes the files at the involved -%% runtime nodes. In this case we test that we remove logs according to last -%% used tracer data. -delete_log_dist_1(suite) -> []; -delete_log_dist_1(doc) -> [""]; -delete_log_dist_1(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataFun= - fun(N)->{N,[{trace,{file,filename:join([PrivDir,"dl1_"++atom_to_list(N)])}}, - {ti,{file,filename:join([PrivDir,"dl1_"++atom_to_list(N)++".ti"])}}]} - end, - TracerDataList=lists:map(TracerDataFun,Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), - ?l Files=lists:map(fun({N,TD})-> - ?l {value,{_,{_,TraceFile}}}=lists:keysearch(trace,1,TD), - ?l {value,{_,{_,TiFile}}}=lists:keysearch(ti,1,TD), - ?l {N,{TraceFile,TiFile}} - end, - TracerDataList), - io:format("The Files is:~w~n",[Files]), - ?l {ok,NodeResults1}=inviso:delete_log(Nodes), % Should not work! - ?l true=check_noderesults(Nodes,{error,tracing},NodeResults1), - stop_tracing(Nodes), - %% Files still here. - ?l lists:foreach(fun({N,{F1,F2}})-> - ?l {ok,_}=rpc:call(N,file,read_file_info,[F1]), - ?l {ok,_}=rpc:call(N,file,read_file_info,[F2]) - end, - Files), - ?l {ok,NodeResults2}=inviso:delete_log(Nodes), - ?l true=check_noderesults(Nodes, - fun({_N,{ok,LogInfos}})-> - ?l {value,{_,[{ok,_FName1}]}}= - lists:keysearch(trace_log,1,LogInfos), - ?l {value,{_,[{ok,_FName2}]}}= - lists:keysearch(ti_log,1,LogInfos), - true - end, - NodeResults2), - %% The files shall be gone now. - ?l lists:foreach(fun({N,{F1,F2}})-> - ?l {error,enoent}=rpc:call(N,file,read_file_info,[F1]), - ?l {error,enoent}=rpc:call(N,file,read_file_info,[F2]) - end, - Files), - stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - - -%% TEST CASE: Test of the autostart behaviour of the runtime component. -%% Here we test that a runtime component is started according to the autostart.conf -%% file. Note that the repeat parameter is set to 2. -autostart_dist_1(suite) -> []; -autostart_dist_1(doc) -> - [""]; -autostart_dist_1(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - PrivDir=filename:join(?config(priv_dir,Config),""), - AutoConfFile=filename:join(PrivDir,"autostart1.conf"), - [RNode|_]=RemoteNodes, - ?l ok=rpc:call(RNode,application,stop,[runtime_tools]), - ?l ok=rpc:call(RNode,application,set_env,[runtime_tools, - inviso_autostart_conf, - AutoConfFile]), - ?l {ok,FD}=file:open(AutoConfFile,[write]), - ?l ok=io:format(FD,"~w.~n~w.~n",[{repeat,2},{tag,c_ref}]), - ?l file:close(FD), - ?l ok=rpc:call(RNode,application,start,[runtime_tools]), - timer:sleep(1000), - ?l P1=rpc:call(RNode,erlang,whereis,[inviso_rt]), - ?l true=is_pid(P1), - ?l rpc:call(RNode,erlang,exit,[P1,kill]), - ?l ok=rpc:call(RNode,application,stop,[runtime_tools]), - ?l ok=rpc:call(RNode,application,start,[runtime_tools]), - timer:sleep(1000), - ?l P2=rpc:call(RNode,erlang,whereis,[inviso_rt]), - ?l true=is_pid(P2), - ?l rpc:call(RNode,erlang,exit,[P2,kill]), - ?l ok=rpc:call(RNode,application,stop,[runtime_tools]), - ?l ok=rpc:call(RNode,application,start,[runtime_tools]), - timer:sleep(1000), - ?l undefined=rpc:call(RNode,erlang,whereis,[inviso_rt]), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Test of autostart. Here we focus on that an autostarted -%% runtime component actually follows the trace case command file and -%% initiates tracing. -autostart_dist_2(suite) -> []; -autostart_dist_2(doc) -> - [""]; -autostart_dist_2(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - PrivDir=filename:join(?config(priv_dir,Config),""), - AutoConfFile=filename:join(PrivDir,"autostart2.conf"), - [RNode|_]=RemoteNodes, - ?l ok=rpc:call(RNode,application,stop,[runtime_tools]), - ?l ok=rpc:call(RNode,application,set_env,[runtime_tools, - inviso_autostart_conf, - AutoConfFile]), - ?l CmdFileName=filename:join(PrivDir,"autostart_cmd_as1"), - ?l {ok,FD}=file:open(CmdFileName,[write]), - ?l ok=io:format(FD, - "inviso:tpl(Nodes,M,F,Arity,[]).~n" - "inviso:tf(Nodes,inviso_test_proc,[call]).~n", - []), - ?l file:close(FD), - ?l TraceFileName=filename:join([PrivDir,"as1_"++atom_to_list(RNode)]), - ?l TiFileName=filename:join([PrivDir,"as1_"++atom_to_list(RNode)++".ti"]), - ?l inviso_as_lib:setup_autostart(RNode, - 2, - [], - [{trace,{file,TraceFileName}}, - {ti,{file,TiFileName}}], - [[CmdFileName]], - [{'M',code},{'F',which},{'Arity',1}], - [{{inviso,tpl,5},{inviso_rt,tpl,{erlang,tl}}}, - {{inviso,tf,3},{inviso_rt,tf,{erlang,tl}}}]), - ?l TestP=spawn(RNode,?MODULE,test_proc_init,[]), - ?l ok=rpc:call(RNode,application,start,[runtime_tools]), - ?l timer:sleep(1000), - ?l {ok,_}=file:read_file_info(TraceFileName), - ?l {ok,_}=file:read_file_info(TiFileName), - ?l true=is_pid(P=rpc:call(RNode,erlang,whereis,[inviso_rt])), - ?l ok=poll(rpc,call,[RNode,erlang,trace_info,[{code,which,1},traced]],{traced,local},10), - ?l {flags,[call]}=rpc:call(RNode,erlang,trace_info,[TestP,flags]), - ?l rpc:call(RNode,erlang,exit,[P,kill]), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Here we test that an autostarted runtime component with a dependency -%% to a specific control component tries to connect to that control component -%% during its start-up. -autostart_dist_3(suite) -> []; -autostart_dist_3(doc) -> - [""]; -autostart_dist_3(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - PrivDir=filename:join(?config(priv_dir,Config),""), - AutoConfFile=filename:join(PrivDir,"autostart3.conf"), - [RNode|_]=RemoteNodes, - ?l ok=rpc:call(RNode,application,stop,[runtime_tools]), - ?l ok=rpc:call(RNode,application,set_env,[runtime_tools, - inviso_autostart_conf, - AutoConfFile]), - ?l {ok,FD}=file:open(AutoConfFile,[write]), - ?l ok=io:format(FD,"~w.~n~w.~n~w.~n", - [{options,[{dependency,{infinity,node()}}]},{repeat,2},{tag,c_ref}]), - ?l file:close(FD), - %% Now start inviso at this node here for the runtime to connect. - ?l {ok,_Pid}=inviso:start(), - ?l ok=poll(erlang,whereis,[inviso_c],fun(P) when is_pid(P)->true;(_)->false end,10), - %% Make the runtime component start. - ?l ok=rpc:call(RNode,application,start,[runtime_tools]), - ?l ok=poll(rpc,call,[RNode,erlang,whereis,[inviso_rt]], - fun(P) when is_pid(P)->true;(_)->false end,10), - %% Check that the runtime component started. - ?l ok=poll(inviso,get_status,[[RNode]],{ok,[{RNode,{ok,{new,running}}}]},20), -% ?l {ok,[{RNode,{ok,{new,running}}}]}=inviso:get_status([RNode]), - stop([RNode]), - ok. -%% ----------------------------------------------------------------------------- - - - -%% TEST CASE: Test of the dependency mechanism in the runtime component. -%% Default behaviour is dependency=infinity, i.e the runtime components remains. -%% We also test here that we can reconnect to the runtime. -running_alone_dist_1(suite) -> []; -running_alone_dist_1(doc) -> - [""]; -running_alone_dist_1(Config) when is_list(Config) -> - ?l {ok,_Pid1}=inviso:start(), % Start a control component. - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref,[]), - ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), - ?l shutdown=inviso:stop(), % Stop the control component! - ?l undefined=whereis(inviso_c), - timer:sleep(3000), % How long shall we wait? :-) - ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt])) end, - Nodes), - ?l {ok,_Pid2}=inviso:start(), - ?l {ok,NodeResults2}=inviso:add_nodes(Nodes,b_ref,[]), - ?l true=check_noderesults(Nodes,{ok,{adopted,new,running,a_ref}},NodeResults2), - stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Test of the dependency mechanism in the runtime component. -%% Test that the runtime components terminates after the specified 5000 ms. -running_alone_dist_2(suite) -> []; -running_alone_dist_2(doc) -> - [""]; -running_alone_dist_2(Config) when is_list(Config) -> - ?l {ok,_Pid1}=inviso:start(), % Start a control component. - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref,[{dependency,5000}]), - ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), - ?l shutdown=inviso:stop(), % Stop the control component! - ?l undefined=whereis(inviso_c), - timer:sleep(2000), - ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt])) end, - Nodes), - timer:sleep(4000), % Now they shall be dead! - ?l lists:foreach(fun(N)->undefined=rpc:call(N,erlang,whereis,[inviso_rt]) end, - Nodes), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Test of the dependency mechanism in the runtime component. -%% Test that the runtime components terminates after the specified 5000 ms. -running_alone_dist_3(suite) -> []; -running_alone_dist_3(doc) -> - [""]; -running_alone_dist_3(Config) when is_list(Config) -> - ?l {ok,_Pid1}=inviso:start(), % Start a control component. - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref,[{dependency,1000}]), - ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), - ?l {ok,NodeResults2}=inviso:change_options(Nodes,[{dependency,5000}]), - ?l true=check_noderesults(Nodes,ok,NodeResults2), - ?l shutdown=inviso:stop(), % Stop the control component! - ?l undefined=whereis(inviso_c), - timer:sleep(3000), - ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt])) end, - Nodes), - timer:sleep(3000), % Now they shall be dead! - ?l lists:foreach(fun(N)->undefined=rpc:call(N,erlang,whereis,[inviso_rt]) end, - Nodes), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Test of the dependency mechanism in the runtime component. -%% Test that the runtime components terminates after the specified 5000 ms, -%% like we did in running_alone_dist_2. But now we also start tracing and checks -%% that all inviso processes actually disappears when the time-out is reached. -running_alone_dist_4(suite) -> []; -running_alone_dist_4(doc) -> - [""]; -running_alone_dist_4(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - %% Start some tracing! - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataFun= - fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf_ra4"++atom_to_list(N)])}}, - {ti,{file,filename:join([PrivDir,"tf_ra4_"++atom_to_list(N)++".ti"])}}]} - end, - TracerDataList=lists:map(TracerDataFun,Nodes), - start_and_init_tracing2(Nodes, - [{dependency,5000}], - TracerDataList, - {ok,[{trace_log,ok},{ti_log,ok}]}), - - ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt])) end, - Nodes), - ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt_meta])) end, - Nodes), - %% Stop control component and wait for the runtimes to terminate after - %% running alone timer has expired. - ?l shutdown=inviso:stop(), % Stop the control component! - ?l undefined=whereis(inviso_c), - timer:sleep(2000), - ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt])) end, - Nodes), - ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt_meta])) end, - Nodes), - timer:sleep(4000), % Now they shall be dead! - ?l lists:foreach(fun(N)->undefined=rpc:call(N,erlang,whereis,[inviso_rt]) end, - Nodes), - ?l lists:foreach(fun(N)->undefined=rpc:call(N,erlang,whereis,[inviso_rt_meta]) end, - Nodes), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Test of the dependency mechanism in the runtime component. -%% Test that the runtime components terminates imeediately when the control -%% component is stopped. Check that all processes are gone. -running_alone_dist_5(suite) -> []; -running_alone_dist_5(doc) -> - [""]; -running_alone_dist_5(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - %% Start some tracing! - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataFun= - fun(N)->{N,[{trace,{file,filename:join([PrivDir,"tf_ra5"++atom_to_list(N)])}}, - {ti,{file,filename:join([PrivDir,"tf_ra5_"++atom_to_list(N)++".ti"])}}]} - end, - TracerDataList=lists:map(TracerDataFun,Nodes), - start_and_init_tracing2(Nodes, - [{dependency,0}], - TracerDataList, - {ok,[{trace_log,ok},{ti_log,ok}]}), - - ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt])) end, - Nodes), - ?l lists:foreach(fun(N)->true=is_pid(rpc:call(N,erlang,whereis,[inviso_rt_meta])) end, - Nodes), - %% Stop control component and check that all runtime component processes have - %% terminate more or less immediately afterwards, since dependency==0. - ?l shutdown=inviso:stop(), % Stop the control component! - timer:sleep(100), - ?l undefined=whereis(inviso_c), - timer:sleep(500), - ?l lists:foreach(fun(N)->undefined=rpc:call(N,erlang,whereis,[inviso_rt]) end, - Nodes), - ?l lists:foreach(fun(N)->undefined=rpc:call(N,erlang,whereis,[inviso_rt_meta]) end, - Nodes), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Test of the overload protection mechanism. The mechanism checks -%% for overload using the callback approximately at the interval specified. -%% Check that it does not start protection until start of tracing. -overload_dist_1(suite) -> []; -overload_dist_1(doc) -> - [""]; -overload_dist_1(Config) when is_list(Config) -> - ?l {ok,_Pid1}=inviso:start(), % Start a control component. - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - ?l lists:foreach(fun(N)->true=rpc:call(N,ets,insert,[inviso_sideeffect_tab,{ovl1,0}]) end, - Nodes), % Initiate the counter. - ?l {ok,NodeResults1}=inviso:add_nodes(Nodes, - a_ref, - [{overload,{{?MODULE,overload1},500}}]), - ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), - timer:sleep(1000), % Give the loadcheck time to perform. - ?l [{_,0}]=ets:lookup(inviso_sideeffect_tab,ovl1), % Nothing should have happened. - - %% Overload check shall not start until we start tracing. - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataList=lists:map(fun(N)->{N,[{trace, - {file,filename:join([PrivDir, - "tf_ovl1."++atom_to_list(N) - ])}}]} - end, - Nodes), - ?l {ok,NodeResults2}=inviso:init_tracing(TracerDataList), - ?l true=check_noderesults(Nodes,{ok,[{trace_log,ok}]},NodeResults2), - timer:sleep(1500), % Give the loadcheck time to perform. - ?l [{_,N}]=ets:lookup(inviso_sideeffect_tab,ovl1), - ?l true=(N>=2), % After 1,5 seconds, at least 2 checks. - - %% Now change options and remove overload checking! - ?l {ok,NodeResults3}=inviso:change_options(Nodes,[overload]), - ?l true=check_noderesults(Nodes,ok,NodeResults3), - ?l [{_,N2}]=ets:lookup(inviso_sideeffect_tab,ovl1), - timer:sleep(1000), - ?l [{_,N2}]=ets:lookup(inviso_sideeffect_tab,ovl1), % No more loadchecks! - - stop_tracing(Nodes), - stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Test of the overload protection mechanism. In this case we focus -%% in that the init and remove functions are carried out at change_options and -%% when starting and stoping the runtime component. -overload_dist_2(suite) -> []; -overload_dist_2(doc) -> - [""]; -overload_dist_2(Config) when is_list(Config) -> - ?l {ok,_Pid1}=inviso:start(), % Start a control component. - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - ?l {ok,NodeResults1}=inviso:add_nodes(Nodes, - a_ref, - [{overload,{{?MODULE,overload2}, - 500, - {?MODULE,overload2i,[]}, - {?MODULE,overload2r,[]}}}]), - ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), - ?l [{_,0}]=ets:lookup(inviso_sideeffect_tab,ovl2), - - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataList=lists:map(fun(N)->{N,[{trace, - {file,filename:join([PrivDir, - "tf_ovl2."++atom_to_list(N) - ])}}]} - end, - Nodes), - ?l {ok,NodeResults2}=inviso:init_tracing(TracerDataList), - ?l true=check_noderesults(Nodes,{ok,[{trace_log,ok}]},NodeResults2), - timer:sleep(1500), % Give the loadcheck time to perform. - ?l [{_,N}]=ets:lookup(inviso_sideeffect_tab,ovl2), - io:format("� is:~p~n",[N]), - ?l true=(N>=2), % After 1,5 seconds, at least 2 checks. - ?l {ok,NodeResults3}=inviso:change_options(Nodes,[{overload,{{?MODULE,overload3}, - 500, - {?MODULE,overload3i,[]}, - {?MODULE,overload3r,[]}}}]), - ?l true=check_noderesults(Nodes,ok,NodeResults3), - ?l []=ets:lookup(inviso_sideeffect_tab,ovl2), - timer:sleep(1500), - ?l [{_,N2}]=ets:lookup(inviso_sideeffect_tab,ovl3), - ?l true=(N2>=2), % After 1,5 seconds, at least 2 checks. - stop_tracing(Nodes), - ?l []=ets:lookup(inviso_sideeffect_tab,ovl3r), % Remove function shall not be called. - ?l [{_,N3}]=ets:lookup(inviso_sideeffect_tab,ovl3), - timer:sleep(1000), % Check that overloadchecking has stopped. - ?l [{_,N3}]=ets:lookup(inviso_sideeffect_tab,ovl3), - stop(Nodes), - ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,ovl3r],[{ovl3r,done}],20), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Test of the overload protections mechanism. Here we focus on testing -%% that if overload is reached tracing is really suspended. -overload_dist_3(suite) -> []; -overload_dist_3(doc) -> - [""]; -overload_dist_3(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataList= - lists:map(fun(N)->{N,[{trace,{file,filename:join([PrivDir, - "tf_ovl3."++atom_to_list(N)])}}, - {ti,{file,filename:join([PrivDir, - "tf_ovl3_ti."++atom_to_list(N)])}}]} - end, - Nodes), - ?l lists:foreach(fun(N)-> - true=rpc:call(N,ets,insert,[inviso_sideeffect_tab,{ovl4,0}]) - end, - Nodes), - start_and_init_tracing2(Nodes, - [{overload,{{?MODULE,overload4},500}}], - TracerDataList, - {ok,[{trace_log,ok},{ti_log,ok}]}), - activate_local_tracing(Nodes), - activate_meta_tracing(Nodes), - activate_traceflags(Nodes), - timer:sleep(600), - ?l [{_,N1}]=ets:lookup(inviso_sideeffect_tab,ovl4), - ?l true=(N1>=1), % Overload check has been done! - ?l Node=node(), - ?l {ok,[{Node,{ok,{tracing,running}}}]}=inviso:get_status([node()]), - ?l true=ets:insert(inviso_sideeffect_tab,{ovl4_suspend,true}), - timer:sleep(600), - ?l {ok,[{Node,{ok,{tracing,{suspended,test}}}}]}=inviso:get_status([node()]), - ?l [{_,N2}]=ets:lookup(inviso_sideeffect_tab,ovl4), - ?l {flags,[]}=erlang:trace_info(whereis(inviso_test_proc),flags), - ?l {meta,false}=erlang:trace_info({lists,module_info,0},meta), - ?l {traced,local}=erlang:trace_info({code,which,1},traced), - ?l true=(is_pid(whereis(inviso_rt_meta))), - ?l true=ets:delete(inviso_sideeffect_tab,ovl4_suspend), - timer:sleep(600), - ?l [{_,N2}]=ets:lookup(inviso_sideeffect_tab,ovl4), % No checking while suspended! - ?l {ok,[{Node,ok}]}=inviso:cancel_suspension([node()]), - ?l {ok,NodeResults1}=inviso:get_status(Nodes), - ?l true=check_noderesults(Nodes,{ok,{tracing,running}},NodeResults1), - timer:sleep(600), - ?l [{_,N3}]=ets:lookup(inviso_sideeffect_tab,ovl4), - ?l true=(N3>N2), - ?l deactivate_local_tracing(Nodes), - ?l stop_tracing(Nodes), - ?l stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE. Test that the overload mechanism is triggered by to the runtime -%% component incomming messages, and nothing else. -overload_dist_4(suite) -> []; -overload_dist_4(doc) -> - [""]; -overload_dist_4(Config) when is_list(Config) -> - ?l {ok,_Pid1}=inviso:start(), % Start a control component. - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - ?l {ok,NodeResults1}=inviso:add_nodes(Nodes, - a_ref, - [{overload,{{?MODULE,overload5}, - infinity, - {?MODULE,overload5i,[]}, - {?MODULE,overload5r,[]}}}]), - ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), - ?l [{_,0}]=ets:lookup(inviso_sideeffect_tab,ovl5), - - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataList=lists:map(fun(N)->{N,[{trace, - {file,filename:join([PrivDir, - "tf_ovl4."++atom_to_list(N) - ])}}]} - end, - Nodes), - ?l {ok,NodeResults2}=inviso:init_tracing(TracerDataList), - ?l true=check_noderesults(Nodes,{ok,[{trace_log,ok}]},NodeResults2), - timer:sleep(2000), % Give the loadcheck time to perform. - ?l [{_,N}]=ets:lookup(inviso_sideeffect_tab,ovl5), - ?l true=(N==0), % And nothing shall have happend! - %% Now we send a message to the inviso_rt, then the load check function - %% shall be called. - ?l whereis(inviso_rt) ! test_of_loadcheck, - timer:sleep(200), % Make sure the inviso_rt gets scheduled. - ?l [{_,1}]=ets:lookup(inviso_sideeffect_tab,ovl5), - stop_tracing(Nodes), - ?l []=ets:lookup(inviso_sideeffect_tab,ovl5r), % Remove function shall not be called. - ?l [{_,N3}]=ets:lookup(inviso_sideeffect_tab,ovl5), - ?l whereis(inviso_rt) ! test_of_loadcheck, - timer:sleep(1000), % Check that overloadchecking has stopped. - ?l [{_,N3}]=ets:lookup(inviso_sideeffect_tab,ovl5), - stop(Nodes), - ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,ovl5r],[{ovl5r,done}],20), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE. Test that the overload mechanism correctly calculates remaining time -%% to next load check if a message comes into the runtime component "interupting" -%% the waiting for loadcheck timeout. (Loadcheck timeout is implemented as an after -%% in the receive). -overload_dist_5(suite) -> []; -overload_dist_5(doc) -> - [""]; -overload_dist_5(Config) when is_list(Config) -> - ?l {ok,_Pid1}=inviso:start(), % Start a control component. - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - ?l lists:foreach(fun(N)->true=rpc:call(N,ets,insert,[inviso_sideeffect_tab,{ovl6,0}]) end, - Nodes), % Initiate the counter. - ?l {ok,NodeResults1}=inviso:add_nodes(Nodes, - a_ref, - [{overload,{{?MODULE,overload6},1000}}]), - ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), - %% Overload check shall not start until we start tracing. - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataList=lists:map(fun(N)->{N,[{trace, - {file,filename:join([PrivDir, - "tf_ovl5."++atom_to_list(N) - ])}}]} - end, - Nodes), - ?l {ok,NodeResults2}=inviso:init_tracing(TracerDataList), - ?l true=check_noderesults(Nodes,{ok,[{trace_log,ok}]},NodeResults2), - ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,ovl6],[{ovl6,2}],25), - %% Now we know that exactly 2 checks have been made. Try to Distract the runtime :-) - ?l inviso_rt:state(whereis(inviso_rt)), % Make it have to receive a message. - timer:sleep(500), - ?l [{_,2}]=ets:lookup(inviso_sideeffect_tab,ovl6), % Should still be 2. - timer:sleep(600), - ?l [{_,3}]=ets:lookup(inviso_sideeffect_tab,ovl6), % We expect yet one check. - timer:sleep(1100), - ?l [{_,4}]=ets:lookup(inviso_sideeffect_tab,ovl6), - - stop_tracing(Nodes), - stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - - -%% TEST CASE: Test of the subscription mechanism. -subscribe_dist_1(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - PrivDir=filename:join(?config(priv_dir,Config),""), - Pid=spawn(?MODULE,inviso_msg_collector,[]), - CtrlPid=whereis(inviso_c), - - ?l {ok,_Pid}=inviso:start(), % Start a control component. - ?l ok=inviso:subscribe(Pid), - ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref,[]), - ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), - ?l {ok,NodeResults2}=inviso:get_status(Nodes), - ?l true=check_noderesults(Nodes,{ok,{new,running}},NodeResults2), - check_msg_collector(Nodes, - fun({inviso_event,CP,_,{connected,N,{_Tag,{idle,running}}}}) - when CP==CtrlPid -> - {true,N}; - (_) -> - false - end, - 13), - TracerDataList=lists:map(fun(N)->{N,{file, - filename:join([PrivDir, - "tf_sub1"++atom_to_list(N)])}} - end, - Nodes), - ?l {ok,NodeResults3}=inviso:init_tracing(TracerDataList), - ?l true=check_noderesults(Nodes,{ok,[{trace_log,ok}]},NodeResults3), - check_msg_collector(Nodes, - fun({inviso_event,CP,_,{state_change,N,{tracing,running}}}) - when CP==CtrlPid -> - {true,N}; - (_) -> - false - end, - 13), - ?l {ok,NodeResults4}=inviso:suspend(Nodes,test), - ?l true=check_noderesults(Nodes,ok,NodeResults4), - check_msg_collector(Nodes, - fun({inviso_event,CP,_,{state_change,N,{tracing,{suspended,test}}}}) - when CP==CtrlPid -> - {true,N}; - (_) -> - false - end, - 13), - ?l [RNode|_]=RemoteNodes, - ?l RInvisoPid=rpc:call(RNode,erlang,whereis,[inviso_rt]), - ?l rpc:call(RNode,erlang,exit,[RInvisoPid,kill]), - check_msg_collector([RNode], - fun({inviso_event,CP,_,{disconnected,N,_Info}}) - when CP==CtrlPid -> - {true,N}; - (_) -> - false - end, - 11), - - ?l {ok,_NodeResults5}=inviso:stop_tracing(Nodes), - ?l {ok,_NodeResults6}=inviso:stop_nodes(Nodes), - ?l shutdown=inviso:stop(), - ok. -%% ----------------------------------------------------------------------------- - - -%% TEST CASE: fetch_log test of single straight trace_log file in distributed -%% environment. -fetch_log_dist_trace_1(suite) -> []; -fetch_log_dist_trace_1(doc) -> - ["fetch_log test of single straight trace_log file in distributed" - "environment."]; -fetch_log_dist_trace_1(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataList=lists:map(fun(N)->{N,[{trace,{file,filename:join([PrivDir, - "testfile1."++ - atom_to_list(N) - ])}}]} end, - Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok}]}), - - %% Put some output in the logs. - ?l inviso:tp(Nodes,math,module_info,0,[]), - ?l inviso:tf(Nodes,all,[call]), - ?l lists:foreach(fun(N)->rpc:call(N,math,module_info,[]) end,Nodes), - - stop_tracing(Nodes), - {H,M,S}=time(), - FetchToDir=filename:join([PrivDir, - "fetch_log_test1_"++integer_to_list(H)++"_"++ - integer_to_list(M)++"_"++integer_to_list(S)]), - ?l ok=file:make_dir(FetchToDir), - ?l {ok,NodeResults}=inviso:fetch_log(RemoteNodes,FetchToDir,"p1"), - io:format("~p~n",[NodeResults]), - ?l true=check_noderesults(RemoteNodes, - fun({N,{complete,[{trace_log,[{ok,File}]},{ti_log,[]}]}}) -> - ?l File="p1testfile1."++atom_to_list(N), - true; - (_)-> - false - end, - NodeResults), - ?l ON=filename:join(PrivDir,"testfile1."), - ?l FN=filename:join(FetchToDir,"p1testfile1."), - ?l lists:foreach(fun(N)-> - {ok,#file_info{size=Size}}= - file:read_file_info(ON++atom_to_list(N)), - {ok,#file_info{size=Size}}= - file:read_file_info(FN++atom_to_list(N)) - end, - RemoteNodes), - %% Now we wish to see that we get an incomplete if we try to fetch to a - %% directory that does not exist. - ?l FetchToErrorDir=filename:join([PrivDir,nonexistingingdir]), - ?l {ok,NodeResults2}=inviso:fetch_log(RemoteNodes,FetchToErrorDir,"p1"), - ?l io:format("NodeResults2:~w~n",[NodeResults2]), - ?l true=check_noderesults(RemoteNodes, - fun({_,{incomplete,_}}) -> - true; - (_)-> - false - end, - NodeResults2), - stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - -fetch_log_dist_trace_2(suite) -> []; -fetch_log_dist_trace_2(doc) -> - [""]; -fetch_log_dist_trace_2(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - PrivDir=filename:join(?config(priv_dir,Config),""), - - {H,M,S}=time(), - ?l Name="wrap"++integer_to_list(H)++"_"++integer_to_list(M)++"_"++integer_to_list(S), - ?l BaseName=filename:join(PrivDir,Name), - Fun=fun(N)->{N,[{trace,{file,{BaseName++atom_to_list(N),wrap,".log",512,2}}}, - {ti,{file,BaseName++"_ti_"++atom_to_list(N)++".ti"}}]} - end, - ?l TracerDataList=lists:map(Fun,Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), - fill_and_reach_two_wrapfiles(PrivDir,"^"++Name,Nodes), - - stop_tracing(Nodes), - FetchToDir=filename:join([PrivDir, - "fetch_log_test2_"++integer_to_list(H)++"_"++ - integer_to_list(M)++"_"++integer_to_list(S)]), - ?l ok=file:make_dir(FetchToDir), - ?l {ok,NodeResults}=inviso:fetch_log(RemoteNodes,FetchToDir,"p1"), - io:format("~p~n",[NodeResults]), - CheckFun=fun({N,{complete,[{trace_log,FileResults1},{ti_log,[{ok,TiFile}]}]}}) -> - Fun2=fun({ok,File}) -> - match= - re:run(File, - "^"++"p1"++Name++atom_to_list(N), - [{capture,none}]), - true; - (_) -> - false - end, - ?l true=lists:all(Fun2,FileResults1), - ?l TiFile="p1"++Name++"_ti_"++atom_to_list(N)++".ti", - true; - (_)-> - false - end, - ?l true=check_noderesults(RemoteNodes,CheckFun,NodeResults), - stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - -fetch_log_dist_trace_3(suite) -> []; -fetch_log_dist_trace_3(doc) -> - [""]; -fetch_log_dist_trace_3(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - PrivDir=filename:join(?config(priv_dir,Config),""), - - {H,M,S}=time(), - ?l Name="wrap2_"++integer_to_list(H)++"_"++integer_to_list(M)++"_"++integer_to_list(S), - ?l BaseName=filename:join(PrivDir,Name), - Fun=fun(N)->{N,[{trace,{file,{BaseName++atom_to_list(N),wrap,".log",512,2}}}, - {ti,{file,BaseName++"_ti_"++atom_to_list(N)++".ti"}}]} - end, - ?l TracerDataList=lists:map(Fun,Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), - fill_and_reach_two_wrapfiles(PrivDir,"^"++Name,Nodes), - - stop_tracing(Nodes), - FetchToDir=filename:join([PrivDir, - "fetch_log_test3_"++integer_to_list(H)++"_"++ - integer_to_list(M)++"_"++integer_to_list(S)]), - ?l ok=file:make_dir(FetchToDir), - ?l {ok,NodeResults1}=inviso:list_logs(Nodes), - CheckFun=fun({N,{ok,[{trace_log,PrivDir2,[F1,F2]},{ti_log,PrivDir2,[F3]}]}})-> - PrivDir2=PrivDir, - RegExp="^"++Name++atom_to_list(N)++"[0-9]+"++"\.log", - match=re:run(F1,RegExp,[{capture,none}]), - match=re:run(F2,RegExp,[{capture,none}]), - F3=Name++"_ti_"++atom_to_list(N)++".ti", - true; - (_) -> - false - end, - ?l true=check_noderesults(Nodes,CheckFun,NodeResults1), - ?l NodeFileSpecList=lists:map(fun({N,{ok,L}})->{N,L} end, - lists:keydelete(node(),1,NodeResults1)), - ?l {ok,NodeResults2}=inviso:fetch_log(NodeFileSpecList,FetchToDir,"p1"), -io:format("~p~n",[NodeResults2]), - CheckFun2=fun({N,{complete,[{trace_log,FileResults1},{ti_log,[{ok,TiFile}]}]}}) -> - Fun2=fun({ok,File}) -> - match= - re:run(File, - "^"++"p1"++Name++atom_to_list(N), - [{capture,none}]), - true; - (_) -> - false - end, - ?l true=lists:all(Fun2,FileResults1), - ?l TiFile="p1"++Name++"_ti_"++atom_to_list(N)++".ti", - true; - (_)-> - false - end, - ?l true=check_noderesults(RemoteNodes,CheckFun2,NodeResults2), - stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - -fetch_log_dist_error_1(suite) -> []; -fetch_log_dist_error_1(doc) -> - [""]; -fetch_log_dist_error_1(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - ?l {ok,_Pid}=inviso:start(), % Start a control component. - ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref), - ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), - ?l {ok,NodeResults2}=inviso:fetch_log(RemoteNodes,"foo","bar"), -io:format("~p~n",[NodeResults2]), - ?l true=check_noderesults(RemoteNodes, - fun({_N,{error,no_tracerdata}})->true; - (_)->false - end, - NodeResults2), - stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - -fetch_log_dist_error_2(suite) -> []; -fetch_log_dist_error_2(doc) -> - [""]; -fetch_log_dist_error_2(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - PrivDir=filename:join(?config(priv_dir,Config),""), - ?l {ok,_Pid}=inviso:start(), % Start a control component. - ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref), - ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), - ?l NodeLogList=lists:map(fun(N)->{N,[{trace_log, - PrivDir, - ["f1,fil","f2.fil"]}, - {ti_log, - PrivDir, - ["f.ti"]}]} - end, - RemoteNodes), - ?l {ok,NodeResults2}=inviso:fetch_log(NodeLogList,"foo","bar"), - io:format("~p~n",[NodeResults2]), - ?l true=check_noderesults(RemoteNodes, - fun({_N,{incomplete,_}}) -> - true; - (_) -> - false - end, - NodeResults2), - ?l NodeTracerData=lists:map(fun(N)->{N, - [{trace,{file,filename:join(PrivDir,"foo")}}, - {ti,{file,filename:join(PrivDir,"bar.ti")}}]} - end, - RemoteNodes), - {ok,NodeResults3}=inviso:fetch_log(NodeTracerData,"foo","bar"), - io:format("~p~n",[NodeResults3]), -%% This should work this way. Now it says complete [], which is not entirely -%% incorrect. But to follow the sematics of when fetching named files should -%% say incomplete. -%% Must do some rework to make that work. No real danger leaving it this way -%% for now. -% ?l true=check_noderesults(RemoteNodes, -% fun({_N,{incomplete,_}}) -> -% true; -% (_) -> -% false -% end, -% NodeResults3), - stop(Nodes), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: This case tests that the log file merger merges files in the -%% correct order, based on the timestamps. -lfm_trace_dist_1(suite) -> []; -lfm_trace_dist_1(doc) -> - [""]; -lfm_trace_dist_1(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - [RNode1,RNode2|_]=RemoteNodes, - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataList= - lists:map(fun(N)->{N,{file,filename:join([PrivDir,"lfm1_"++atom_to_list(N)])}} end, - Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok}]}), - activate_local_tracing(Nodes), - activate_traceflags(Nodes), - - {inviso_test_proc,RNode2} ! {apply,code,which,[lists]}, - timer:sleep(300), - {inviso_test_proc,RNode1} ! {apply,code,which,[lists]}, - timer:sleep(300), - {inviso_test_proc,RNode1} ! {apply,code,which,[lists]}, - timer:sleep(300), - inviso_test_proc ! {apply,code,which,[lists]}, - timer:sleep(300), - {inviso_test_proc,RNode2} ! {apply,code,which,[lists]}, - timer:sleep(300), - inviso_test_proc ! {apply,code,which,[lists]}, - - deactivate_traceflags(Nodes), - deactivate_local_tracing(Nodes), - stop_tracing(Nodes), - stop(Nodes), - - DestFile=filename:join(PrivDir,"lfm1_out.txt"), - ?l {ok,6}= - inviso_lfm:merge([{node(), - [{trace_log, - [filename:join(PrivDir,"lfm1_"++atom_to_list(node()))]}]}, - {RNode1, - [{trace_log, - [filename:join(PrivDir,"lfm1_"++atom_to_list(RNode1))]}]}, - {RNode2, - [{trace_log, - [filename:join(PrivDir,"lfm1_"++atom_to_list(RNode2))]}]}], - DestFile), - ?l {ok,FD}=file:open(DestFile,[read]), - ?l S1=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(RNode2),S1), - ?l S2=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(RNode1),S2), - ?l S3=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(RNode1),S3), - ?l S4=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(node()),S4), - ?l S5=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(RNode2),S5), - ?l S6=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(node()),S6), - ?l file:close(FD), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: Testing to the full extent that pid-mappings work with both -%% local and global registration. Also checks that pidmappings can be removed -%% and that consequently the mappings in the resulting merged file stops. -lfm_trace_ti_dist_2(suite) -> []; -lfm_trace_ti_dist_2(doc) -> - [""]; -lfm_trace_ti_dist_2(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - [RNode1,RNode2|_]=RemoteNodes, - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataList= - lists:map(fun(N)->{N,[{trace,{file,filename:join(PrivDir,"lfm2_"++atom_to_list(N))}}, - {ti,{file,filename:join(PrivDir,"lfm2_ti_"++atom_to_list(N))}}]} - end, - Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok},{ti_log,ok}]}), - activate_local_tracing(Nodes), - activate_meta_tracing(Nodes), - activate_traceflags(Nodes), - - {inviso_test_proc,RNode2} ! {apply,code,which,[lists]}, - timer:sleep(300), - {inviso_test_proc,RNode1} ! {apply,code,which,[lists]}, - timer:sleep(300), - {inviso_test_proc,RNode1} ! {apply,code,which,[lists]}, - timer:sleep(300), - inviso_test_proc ! {apply,code,which,[lists]}, - timer:sleep(300), - - P2=spawn(RNode2,?MODULE,test_proc_loop,[]), - P1=spawn(RNode1,?MODULE,test_proc_loop,[]), - P0=spawn_link(?MODULE,test_proc_loop,[]), - ThisNode=node(), - ?l {ok,[{ThisNode,{ok,[1]}}]}=inviso:tf([node()],P0,[call,timestamp]), - ?l {ok,[{RNode1,{ok,[1]}}]}=inviso:tf([RNode1],P1,[call,timestamp]), - ?l {ok,[{RNode2,{ok,[1]}}]}=inviso:tf([RNode2],P2,[call,timestamp]), - P2 ! {apply,code,which,[lists]}, - timer:sleep(300), - P1 ! {apply,code,which,[lists]}, - timer:sleep(300), - P0 ! {apply,code,which,[lists]}, - timer:sleep(300), - - P3=spawn(RNode2,?MODULE,test_proc_loop,[]), - ?l yes=global:register_name(inviso_test_proc_globalname,P3), - ?l {ok,[{RNode2,{ok,[1]}}]}=inviso:tf([RNode2],P3,[call,timestamp]), - timer:sleep(300), - P3 ! {apply,code,which,[lists]}, - timer:sleep(300), - - P4=rpc:call(RNode1,erlang,whereis,[inviso_test_proc]), - ?l true=rpc:call(RNode1,erlang,unregister,[inviso_test_proc]), - timer:sleep(300), - P4 ! {apply,code,which,[lists]}, - timer:sleep(300), - - ?l true=rpc:call(RNode1,erlang,register,[inviso_test_proc,P4]), - - ?l global:unregister_name(inviso_test_proc_globalname), - timer:sleep(300), - ?l P3 ! {apply,code,which,[lists]}, - timer:sleep(300), - - deactivate_traceflags(Nodes), - deactivate_local_tracing(Nodes), - stop_tracing(Nodes), - stop(Nodes), - - DestFile=filename:join(PrivDir,"lfm2_out.txt"), - ?l {ok,10}= - inviso_lfm:merge([ - {node(), - [{trace_log, - [filename:join(PrivDir,"lfm2_"++atom_to_list(node()))]}, - {ti_log, - [filename:join(PrivDir,"lfm2_ti_"++atom_to_list(node()))]}]}, - {RNode1, - [{trace_log, - [filename:join(PrivDir,"lfm2_"++atom_to_list(RNode1))]}, - {ti_log, - [filename:join(PrivDir,"lfm2_ti_"++atom_to_list(RNode1))]}]}, - {RNode2, - [{trace_log, - [filename:join(PrivDir,"lfm2_"++atom_to_list(RNode2))]}, - {ti_log, - [filename:join(PrivDir,"lfm2_ti_"++atom_to_list(RNode2))]}]} - ], - DestFile), - ?l {ok,FD}=file:open(DestFile,[read]), - ?l S1=io:get_line(FD,""), -io:format("S1 is:~p~n",[S1]), - ?l true=lists:prefix(atom_to_list(RNode2)++" [inviso_test_proc",S1), - ?l S2=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(RNode1)++" [inviso_test_proc",S2), - ?l S3=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(RNode1)++" [inviso_test_proc",S3), - ?l S4=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(node())++" [inviso_test_proc",S4), - ?l S5=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(RNode2)++" []",S5), - ?l S6=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(RNode1)++" []",S6), - ?l S7=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(node())++" []",S7), - ?l S8=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(RNode2)++" [{global,inviso_test_proc_globalname}]",S8), - ?l S9=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(RNode1)++" []",S9), - ?l S10=io:get_line(FD,""), - ?l true=lists:prefix(atom_to_list(RNode2)++" []",S10), - ?l file:close(FD), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: This tests that the wrapset sorter works. -handle_logfile_sort_wrapset(suite) -> []; -handle_logfile_sort_wrapset(doc) -> - [""]; -handle_logfile_sort_wrapset(Config) when is_list(Config) -> - File0="prefix10.fil", - File1="prefix11.fil", - File2="prefix12.fil", - File3="prefix13.fil", - ?l [File0,File1,File2,File3]= - inviso_lfm_tpfreader:handle_logfile_sort_wrapset([File2,File1,File0,File3]), - File5="prefix15.fil", - ?l [File5,File0,File1,File2,File3]= - inviso_lfm_tpfreader:handle_logfile_sort_wrapset([File2,File5,File1,File0,File3]), - ok. -%% ----------------------------------------------------------------------------- - -%% TEST CASE: This case tests that the regexp mechanism in the inviso_rt_lib can -%% find modules using regexps and that its only_loaded mechanism works. -%% This test case can not be run when using cover because cover will make the -%% modules no longer loaded from the path containing "runtime_tools". -expand_regexp_dist_1(suite) -> []; -expand_regexp_dist_1(doc) -> - [""]; -expand_regexp_dist_1(Config) when is_list(Config) -> - case ?t:is_cover() of - true -> - {skip,"Cover is running"}; - false -> - expand_regexp_dist_1_nocover(Config) - end. - -expand_regexp_dist_1_nocover(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - [RNode1|_]=RemoteNodes, - ?l NodeResults1=inviso_rt_lib:expand_regexp(Nodes,"^inviso_rt.*",[]), - ?l L1=length(Nodes), - ?l L1=length(NodeResults1), - ?l true=lists:all(fun({_,Mods})-> - ?l 3=length(Mods), - ?l true=lists:member(inviso_rt,Mods), - ?l true=lists:member(inviso_rt_lib,Mods), - ?l true=lists:member(inviso_rt_meta,Mods), - true; - (_) -> - false - end, - NodeResults1), - %% Check the dir-option. In the following inviso_tool_lib shall not be found. - ?l NodeResults2=inviso_rt_lib:expand_regexp(Nodes,"runtime_tools","invi.*lib.*",[]), -?l io:format("NodeResults2:~w~n",[NodeResults2]), - ?l L1=length(NodeResults2), % Same number of nodes replying. - ?l true=lists:all(fun({_,Mods})-> - 2=length(Mods), - true=lists:member(inviso_as_lib,Mods), - true=lists:member(inviso_rt_lib,Mods), - true; - (_) -> - false - end, - NodeResults2), - ?l [{RNode1,[]}]= - inviso_rt_lib:expand_regexp([RNode1],"^inviso_testmodule1.*",[only_loaded]), - ?l [{RNode1,[inviso_testmodule1_foo]}]= - inviso_rt_lib:expand_regexp([RNode1],"^inviso_testmodule1.*",[]), - ok. -%% ----------------------------------------------------------------------------- - - -only_loaded_dist_1(suite) -> []; -only_loaded_dist_1(doc) -> - [""]; -only_loaded_dist_1(Config) when is_list(Config) -> - RemoteNodes=get_remotenodes_config(Config), - Nodes=[node()|RemoteNodes], - [RNode1|_]=RemoteNodes, - PrivDir=filename:join(?config(priv_dir,Config),""), - TracerDataList= - lists:map(fun(N)->{N,[{trace,{file,filename:join(PrivDir,"ol_1_"++atom_to_list(N))}}]} - end, - Nodes), - start_and_init_tracing2(Nodes,[],TracerDataList,{ok,[{trace_log,ok}]}), - ?l false=rpc:call(RNode1,erlang,module_loaded,[inviso_testmodule1_foo]), - ?l {ok,[{RNode1,{ok,[0]}}]}= - inviso:tpl([RNode1],inviso_testmodule1_foo,'_','_',[],[only_loaded]), - ?l false=rpc:call(RNode1,erlang,module_loaded,[inviso_testmodule1_foo]), - ?l {ok,[{RNode1,{ok,[3]}}]}= - inviso:tpl([RNode1],inviso_testmodule1_foo,'_','_',[],[]), - stop_tracing(Nodes), - stop(Nodes), - ok. - - -%% ============================================================================== -%% Common functions setting up inviso. -%% ============================================================================== - -%% Starts controlcomponent and adds runtime components on the nodes specified. -%% Also initiates tracing on the nodes. -start_and_init_tracing1(Nodes,Options,TracerData,Reply) when is_list(Nodes) -> - ?l {ok,_Pid}=inviso:start(), % Start a control component. - ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref,Options), - io:format("~p~n",[NodeResults1]), - ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), - ?l {ok,NodeResults2}=inviso:get_status(Nodes), - ?l true=check_noderesults(Nodes,{ok,{new,running}},NodeResults2), - ?l {ok,NodeResults3}=inviso:init_tracing(Nodes,TracerData), - ?l true=check_noderesults(Nodes,Reply,NodeResults3), - ok. -start_and_init_tracing2(Nodes,Options,TracerDataList,Reply) -> - ?l {ok,_Pid}=inviso:start(), % Start a control component. - ?l {ok,NodeResults1}=inviso:add_nodes(Nodes,a_ref,Options), - io:format("~p~n",[NodeResults1]), - ?l true=check_noderesults(Nodes,{ok,new},NodeResults1), - ?l {ok,NodeResults2}=inviso:get_status(Nodes), - ?l true=check_noderesults(Nodes,{ok,{new,running}},NodeResults2), - ?l {ok,NodeResults4}=inviso:get_tracerdata(Nodes), - ?l true=check_noderesults(Nodes,{ok,no_tracerdata},NodeResults4), - ?l {ok,NodeResults3}=inviso:init_tracing(TracerDataList), - io:format("Tracerdatalist:~p~n",[TracerDataList]), - ?l true=check_noderesults(Nodes,Reply,NodeResults3), - - ?l Fun1=fun({N,{ok,TD}}) when is_list(TD)-> - ?l {value,{trace,Trace}}=lists:keysearch(trace,1,TD), - ?l {value,{N,TD2}}=lists:keysearch(N,1,TracerDataList), - ?l true=lists:member({trace,Trace},TD2), - %% Check that the trace file really exists. - ?l case Trace of % Trace={file,FilePortParameters} - {file,FileName1} when is_list(FileName1) -> - ?l {ok,_}=rpc:call(N,file,read_file_info,[FileName1]); - _ -> % This should be extended with more cases. - true - end, - ?l case lists:keysearch(ti,1,TD2) of - {value,{_,Ti}} -> % Ok, we have ti too. - ?l {value,{_,Ti}}=lists:keysearch(ti,1,TD), - ?l FileName2=element(2,Ti), - ?l {ok,_}=rpc:call(N,file,read_file_info,[FileName2]), - true; - false -> % No ti, we are done now. - true - end; - ({N,{ok,{file,FileName}}}) -> - ?l {value,{N,{file,FileName}}}=lists:keysearch(N,1,TracerDataList), - ?l {ok,_}=rpc:call(N,file,read_file_info,[FileName]), - true; - ({N,{ok,LogTD}}) -> % The case using a fun. - ?l {value,{N,LogTD}}=lists:keysearch(N,1,TracerDataList), - true - end, - ?l {ok,NodeResults5}=inviso:get_tracerdata(Nodes), - ?l true=check_noderesults(Nodes,Fun1,NodeResults5), - ok. -%% ------------------------------------------------------------------------------ - -%% Stops tracing on Nodes. -stop_tracing(Nodes) when is_list(Nodes) -> - ?l {ok,NodeResults1}=inviso:stop_tracing(Nodes), - ?l true=check_noderesults(Nodes,{ok,idle},NodeResults1), - ?l {ok,NodeResults2}=inviso:get_status(Nodes), - ?l true=check_noderesults(Nodes,{ok,{idle,running}},NodeResults2), - %% The implementation says that the meta tracer shall be stopped when - %% tracing is stopped. Check that. - ?l lists:foreach(fun(N)-> - ok=poll(erlang,whereis,[inviso_rt_meta],undefined,20) - end, - Nodes). -%% ------------------------------------------------------------------------------ - -%% Stops the runtime components on Nodes and stops the control component at this -%% Erlang node. -stop(Nodes) when is_list(Nodes) -> - ?l true=check_on_nodes(Nodes,erlang,whereis,[inviso_rt],fun(P) when is_pid(P)->true end), - ?l {ok,NodeResults}=inviso:stop_nodes(Nodes), - ?l true=check_noderesults(Nodes,ok,NodeResults), - ?l true=check_on_nodes(Nodes,erlang,whereis,[inviso_rt],fun(undefined)->true end), - ?l true=is_pid(whereis(inviso_c)), - ?l shutdown=inviso:stop(), - ?l ok=poll(erlang,whereis,[inviso_c],undefined,20). -%% ------------------------------------------------------------------------------ - -%% Help function activating local tracing. -activate_local_tracing(Nodes) when is_list(Nodes) -> - ?l true=check_on_nodes(Nodes, - erlang, - trace_info, - [{code,which,1},traced], - {traced,false}), - ?l {ok,NodeResults}=inviso:tpl(Nodes,code,which,1,[]), - ?l true=check_noderesults(Nodes,fun({_,{ok,[1]}})->true end,NodeResults), - ?l true=check_on_nodes(Nodes, - erlang, - trace_info, - [{code,which,1},traced], - {traced,local}). -%% ------------------------------------------------------------------------------ - -%% Help function activating global tracing. -activate_global_tracing(Nodes) when is_list(Nodes) -> - ?l true=check_on_nodes(Nodes, - erlang, - trace_info, - [{code,get_path,0},traced], - {traced,false}), - ?l {ok,NodeResults}=inviso:tp(Nodes,code,get_path,0,[]), - ?l true=check_noderesults(Nodes,fun({_,{ok,[1]}})->true end,NodeResults), - ?l true=check_on_nodes(Nodes, - erlang, - trace_info, - [{code,get_path,0},traced], - {traced,global}). -%% ------------------------------------------------------------------------------ - - -%% Help function activating local tracing and using a regexp to point out modules. -%% Returns the structure of modules and functions that were activated. Must be used -%% when deactivating. -activate_global_tracing_regexp(Nodes) when is_list(Nodes) -> - %% First find out which modules will be effected. - ?l Mods1=inviso_rt_lib:expand_regexp("application.*",[]), - ?l true=(length(Mods1)>1), % Should find more than one module! - ?l Funcs1=lists:foldl(fun(M,Acc)->[{M,M:module_info(exports)}|Acc] end,[],Mods1), - %% Check that these functions are not traced. - io:format("Modules:~w~n",[Mods1]), - ?l {ok,NodeResults}=inviso:tp(Nodes,"application.*",'_','_',[],[]), - io:format("Here 2~w~n",[NodeResults]), - ?l N=lists:foldl(fun({_,L1},A1)->lists:foldl(fun(_,A2)->A2+1 end,A1,L1) end,0,Funcs1), - ?l true=check_noderesults(Nodes,fun({_,{ok,L}})-> N==lists:sum(L) end,NodeResults), - io:format("Here 3~n",[]), - %% Check again! - ?l lists:foreach(fun({M,Funcs})-> - lists:foreach(fun({F,Arity})-> - true=check_on_nodes(Nodes, - erlang, - trace_info, - [{M,F,Arity},traced], - {traced,global}) - end, - Funcs) - end, - Funcs1), - Funcs1. -%% ------------------------------------------------------------------------------ - -%% Help function as above but uses the dir feature as well. -activate_global_tracing_regexp_dir(Nodes) when is_list(Nodes) -> - %% First find out which modules will be effected. - ?l Mods1=inviso_rt_lib:expand_regexp(".*kernel.*","application.*",[]), - ?l true=(length(Mods1)>1), % Should find more than one module! - ?l Funcs1=lists:foldl(fun(M,Acc)->[{M,M:module_info(exports)}|Acc] end,[],Mods1), - %% Check that these functions are not traced. - io:format("Modules:~w~n",[Mods1]), - ?l {ok,NodeResults}=inviso:tp(Nodes,{".*kernel.*","application.*"},'_','_',[],[]), - io:format("Here 2~w~n",[NodeResults]), - ?l N=lists:foldl(fun({_,L1},A1)->lists:foldl(fun(_,A2)->A2+1 end,A1,L1) end,0,Funcs1), - ?l true=check_noderesults(Nodes,fun({_,{ok,L}})-> N==lists:sum(L) end,NodeResults), - io:format("Here 3~n",[]), - %% Check again! - ?l lists:foreach(fun({M,Funcs})-> - lists:foreach(fun({F,Arity})-> - true=check_on_nodes(Nodes, - erlang, - trace_info, - [{M,F,Arity},traced], - {traced,global}) - end, - Funcs) - end, - Funcs1), - Funcs1. -%% ------------------------------------------------------------------------------ - -deactivate_local_tracing(Nodes) when is_list(Nodes) -> - ?l true=check_on_nodes(Nodes, - erlang, - trace_info, - [{code,which,1},traced], - {traced,local}), - ?l {ok,NodeResults}=inviso:ctpl(Nodes,code,'_','_'), - ?l true=check_noderesults(Nodes,fun({_,{ok,[N]}})when is_integer(N)->true end,NodeResults), - ?l true=check_on_nodes(Nodes, - erlang, - trace_info, - [{code,which,1},traced], - {traced,false}). -%% ------------------------------------------------------------------------------ - -deactivate_global_tracing(Nodes) when is_list(Nodes) -> - ?l true=check_on_nodes(Nodes, - erlang, - trace_info, - [{code,get_path,0},traced], - {traced,global}), - ?l {ok,NodeResults}=inviso:ctp(Nodes,code,'_','_'), - ?l true=check_noderesults(Nodes,fun({_,{ok,[N]}})when is_integer(N)->true end,NodeResults), - ?l true=check_on_nodes(Nodes, - erlang, - trace_info, - [{code,get_path,0},traced], - {traced,false}). -%% ------------------------------------------------------------------------------ - - -%% Function deactivating the functions activated by activate_global_tracing_regexp/1. -deactivate_global_tracing_regexp(Nodes,Funcs1) -> - ?l lists:foreach(fun({M,Funcs})-> - lists:foreach(fun({F,Arity})-> - true=check_on_nodes(Nodes, - erlang, - trace_info, - [{M,F,Arity},traced], - {traced,global}) - end, - Funcs) - end, - Funcs1), - ?l {ok,NodeResults}=inviso:ctp(Nodes,"application.*",'_','_'), - ?l N=lists:foldl(fun({_,L1},A1)->lists:foldl(fun(_,A2)->A2+1 end,A1,L1) end,0,Funcs1), - io:format("Noderesult from deactivate;~w~n",[NodeResults]), - ?l true=check_noderesults(Nodes,fun({_,{ok,L}})-> N==lists:sum(L) end,NodeResults), - ?l lists:foreach(fun({M,Funcs})-> - lists:foreach(fun({F,Arity})-> - true=check_on_nodes(Nodes, - erlang, - trace_info, - [{M,F,Arity},traced], - {traced,false}) - end, - Funcs) - end, - Funcs1). -%% ------------------------------------------------------------------------------ - -%% Function deactivating the functions activated by activate_global_tracing_regexp_dir/1. -deactivate_global_tracing_regexp_dir(Nodes,Funcs1) -> - ?l lists:foreach(fun({M,Funcs})-> - lists:foreach(fun({F,Arity})-> - true=check_on_nodes(Nodes, - erlang, - trace_info, - [{M,F,Arity},traced], - {traced,global}) - end, - Funcs) - end, - Funcs1), - ?l {ok,NodeResults}=inviso:ctp(Nodes,{".*kernel.*","application.*"},'_','_'), - ?l N=lists:foldl(fun({_,L1},A1)->lists:foldl(fun(_,A2)->A2+1 end,A1,L1) end,0,Funcs1), - io:format("Noderesult from deactivate;~w~n",[NodeResults]), - ?l true=check_noderesults(Nodes,fun({_,{ok,L}})-> N==lists:sum(L) end,NodeResults), - ?l lists:foreach(fun({M,Funcs})-> - lists:foreach(fun({F,Arity})-> - true=check_on_nodes(Nodes, - erlang, - trace_info, - [{M,F,Arity},traced], - {traced,false}) - end, - Funcs) - end, - Funcs1). -%% ------------------------------------------------------------------------------ - -%% Help function which starts the inviso_test_proc on all nodes and then sets -%% the call flag on that process. -activate_traceflags(Nodes) -> - ?l lists:foreach(fun(N)->spawn(N,?MODULE,test_proc_init,[]) end,Nodes), - ?l lists:foreach(fun(N)-> - P=rpc:call(N,erlang,whereis,[inviso_test_proc]), - {flags,[]}=rpc:call(N,erlang,trace_info,[P,flags]) - end, - Nodes), - ?l {ok,NodeResults}=inviso:tf(Nodes,inviso_test_proc,[call,timestamp]), - ?l true=check_noderesults(Nodes,{ok,[1]},NodeResults), - ?l lists:foreach(fun(N)-> - P=rpc:call(N,erlang,whereis,[inviso_test_proc]), - {flags,Flags}=rpc:call(N,erlang,trace_info,[P,flags]), - true=lists:member(call,Flags), - true=lists:member(timestamp,Flags) - end, - Nodes), - %% Now try a globally registered process. - ?l [ANode|_]=Nodes, - ?l GPid=spawn(ANode,?MODULE,global_test_proc_init,[]), - ?l ok=poll(global,whereis_name,[global_inviso_test_proc], - fun(P) when is_pid(P)->true;(_)->false end, - 10), - ?l {ok,NodeResults2}= - inviso:tf(Nodes,{global,global_inviso_test_proc},[call,timestamp]), - ?l true=check_noderesults(Nodes, - fun({N,{ok,[1]}}) when N==ANode->true; - ({_,{ok,[0]}})->true; - (_)->false - end, - NodeResults2), - ?l {flags,Flags2}=rpc:call(ANode,erlang,trace_info,[GPid,flags]), - ?l 2=length(Flags2), - ?l true=lists:member(call,Flags2), - ?l true=lists:member(timestamp,Flags2), - true. -%% ------------------------------------------------------------------------------ - -deactivate_traceflags(Nodes) -> - ?l lists:foreach(fun(N)-> - P=rpc:call(N,erlang,whereis,[inviso_test_proc]), - {flags,Flags}=rpc:call(N,erlang,trace_info,[P,flags]), - true=lists:member(call,Flags), - true=lists:member(timestamp,Flags) - end, - Nodes), - ?l {ok,NodeResults}=inviso:ctf(Nodes,inviso_test_proc,[call,timestamp]), - ?l true=check_noderesults(Nodes,{ok,[1]},NodeResults), - ?l lists:foreach(fun(N)-> - P=rpc:call(N,erlang,whereis,[inviso_test_proc]), - {flags,[]}=rpc:call(N,erlang,trace_info,[P,flags]) - end, - Nodes), - ?l GPid=global:whereis_name(global_inviso_test_proc), - ?l ANode=node(GPid), - ?l {flags,Flags2}=rpc:call(ANode,erlang,trace_info,[GPid,flags]), - ?l 2=length(Flags2), - ?l {ok,NodeResults2}=inviso:ctf(Nodes,{global,global_inviso_test_proc},[call,timestamp]), - ?l true=check_noderesults(Nodes, - fun({N,{ok,[1]}}) when N==ANode->true; - ({_,{ok,[0]}})->true; - (_)->false - end, - NodeResults2). -%% ------------------------------------------------------------------------------ - - -activate_meta_tracing(Nodes) -> - ?l {ok,NodeResults1}=inviso:tpm_localnames(), - ?l true=check_noderesults(Nodes,{{ok,1},{ok,1}},NodeResults1), - ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]), - {meta,P}=rpc:call(N,erlang,trace_info,[{erlang,register,2},meta]) - end, - Nodes), - ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]), - {meta,P}=rpc:call(N,erlang,trace_info,[{erlang,unregister,1},meta]) - end, - Nodes), - ?l {ok,NodeResults2}=inviso:tpm_globalnames(), - ?l true=check_noderesults(Nodes,{{ok,1},{ok,1}},NodeResults2), - ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]), - {meta,P}=rpc:call(N, - erlang, - trace_info, - [{global,handle_call,3},meta]) - end, - Nodes), - ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]), - {meta,P}=rpc:call(N, - erlang, - trace_info, - [{global,delete_global_name,2},meta]) - end, - Nodes), - - ?l lists:foreach(fun(N)->true=rpc:call(N, - ets, - insert, - [inviso_sideeffect_tab,{tpm_init_func1,0}]), - true=rpc:call(N, - ets, - insert, - [inviso_sideeffect_tab,{tpm_call_func1,0}]), - true=rpc:call(N, - ets, - insert, - [inviso_sideeffect_tab,{tpm_return_func1,0}]) - end, - Nodes), - ?l {ok,NodeResults3}= - inviso:init_tpm(lists, - module_info, - 0, - {?MODULE,tpm_init_func1}, - {?MODULE,tpm_call_func1}, - {?MODULE,tpm_return_func1}, - {?MODULE,tpm_remove_func1}), - ?l true=check_noderesults(Nodes,ok,NodeResults3), - ?l [{_,1}]=ets:lookup(inviso_sideeffect_tab,tpm_init_func1), - ?l {ok,NodeResults3a}= - inviso:init_tpm(lists, - module_info, - 0, - {?MODULE,tpm_init_func1}, - {?MODULE,tpm_call_func1}, - {?MODULE,tpm_return_func1}, - {?MODULE,tpm_remove_func1}), - ?l true=check_noderesults(Nodes,{error,already_initiated},NodeResults3a), -% %% Try more forbidden things. Wildcards not allowed in meta tracing! -% ?l {ok,NodeResults3b}=inviso:tpm(Nodes,lists,'_',0,[{'_',[],[{return_trace}]}]), -% io:format("The noderesults3b is:~w~n",[NodeResults3b]), -% ?l true=check_noderesults(Nodes,{error,bad_mfa},NodeResults3b), - ?l {ok,NodeResults3c}=inviso:tpm(Nodes,lists,module_info,0,[{'_',[],[{return_trace}]}]), - ?l true=check_noderesults(Nodes,{ok,1},NodeResults3c), - ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]), - {meta,P}=rpc:call(N,erlang,trace_info,[{lists,module_info,0},meta]) - end, - Nodes), - ?l lists:foreach(fun(N)->rpc:call(N,lists,module_info,[]) end,Nodes), - ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_call_func1],[{tpm_call_func1,1}],20), - ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_return_func1],[{tpm_return_func1,1}],20), - ?l lists:foreach(fun(N)->rpc:call(N,lists,module_info,[]) end,Nodes), - ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_call_func1],[{tpm_call_func1,2}],20), - ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_return_func1],[{tpm_return_func1,2}],20), - - ?l {ok,NodeResults4}= - inviso:init_tpm(math, - module_info, - 1, - {?MODULE,tpm_init_func2}, % Does not exist on purpose. - {?MODULE,tpm_call_func2}, % Does not exist on purpose. - {?MODULE,tpm_return_func2}, % Does not exist on purpose. - {?MODULE,tpm_remove_func2}), % Does not exist on purpose. - ?l true=check_noderesults(Nodes,ok,NodeResults4), - ?l {ok,NodeResults5}= - inviso:tpm_ms(math,module_info,1,ms1,[{'_',[],[{return_trace}]}]), - ?l true=check_noderesults(Nodes,{ok,1},NodeResults5), - ?l lists:foreach(fun(N)->{meta_match_spec,[{'_',[],[{return_trace}]}]}= - rpc:call(N,erlang,trace_info,[{math,module_info,1}, - meta_match_spec]) - end, - Nodes), - - ?l {ok,NodeResults6}=inviso:tpm_ms(math,module_info,1,ms2,[{[exports],[],[]}]), - ?l true=check_noderesults(Nodes,{ok,1},NodeResults6), - ?l lists:foreach(fun(N)->{meta_match_spec,[{[exports],[],[]},{'_',[],[{return_trace}]}]}= - rpc:call(N,erlang,trace_info,[{math,module_info,1}, - meta_match_spec]) - end, - Nodes), - ?l {ok,NodeResults7}=inviso:tpm_ms(math,module_info,1,ms3,[{[attributes],[],[]}]), - ?l true=check_noderesults(Nodes,{ok,1},NodeResults7), - ?l lists:foreach(fun(N)->{meta_match_spec,[{[attributes],[],[]}, - {[exports],[],[]}, - {'_',[],[{return_trace}]}]}= - rpc:call(N,erlang,trace_info,[{math,module_info,1}, - meta_match_spec]) - end, - Nodes), - ?l {ok,NodeResults8}=inviso:ctpm_ms(math,module_info,1,ms2), - ?l true=check_noderesults(Nodes,ok,NodeResults8), - ?l lists:foreach(fun(N)->{meta_match_spec,[{[attributes],[],[]}, - {'_',[],[{return_trace}]}]}= - rpc:call(N,erlang,trace_info,[{math,module_info,1}, - meta_match_spec]) - end, - Nodes), - ?l io:format("whereis:~w~n",[lists:map(fun(N)->rpc:call(N,erlang,whereis,[inviso_rt_meta]) end,Nodes)]), - ?l {ok,NodeResults8}=inviso:ctpm_ms(math,module_info,1,ms3), - ?l io:format("whereis:~w~n",[lists:map(fun(N)->rpc:call(N,erlang,whereis,[inviso_rt_meta]) end,Nodes)]), - ?l {ok,NodeResults8}=inviso:ctpm_ms(math,module_info,1,ms1), - ?l lists:foreach(fun(N)->{meta_match_spec,false}= - rpc:call(N,erlang,trace_info,[{math,module_info,1}, - meta_match_spec]) - end, - Nodes), - - %% Now try to do this with exception tracing instead. - %% Reset the side effect tables. - ?l lists:foreach(fun(N)->true=rpc:call(N, - ets, - insert, - [inviso_sideeffect_tab,{tpm_init_func1,0}]), - true=rpc:call(N, - ets, - insert, - [inviso_sideeffect_tab,{tpm_call_func1,0}]), - true=rpc:call(N, - ets, - insert, - [inviso_sideeffect_tab,{tpm_return_func1,0}]) - end, - Nodes), - ?l {ok,NodeResults9}= - inviso:init_tpm(?MODULE, - failing_function, - 1, - {?MODULE,tpm_init_func1}, - {?MODULE,tpm_call_func1}, - {?MODULE,tpm_return_func1}, - {?MODULE,tpm_remove_func1}), - ?l true=check_noderesults(Nodes,ok,NodeResults9), - ?l [{_,1}]=ets:lookup(inviso_sideeffect_tab,tpm_init_func1), - ?l {ok,NodeResults10}=inviso:tpm(Nodes,?MODULE,failing_function,1,[{'_',[],[{exception_trace}]}]), - ?l true=check_noderesults(Nodes,{ok,1},NodeResults10), - ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]), - {meta,P}=rpc:call(N,erlang,trace_info,[{?MODULE,failing_function,1},meta]) - end, - Nodes), - ?l lists:foreach(fun(N)->rpc:call(N,?MODULE,failing_function,[nofailure]) end,Nodes), - ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_call_func1],[{tpm_call_func1,1}],20), - ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_return_func1],[{tpm_return_func1,1}],20), - ?l lists:foreach(fun(N)->rpc:call(N,?MODULE,failing_function,[failure]) end,Nodes), - ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_call_func1],[{tpm_call_func1,2}],20), - ?l ok=poll(ets,lookup,[inviso_sideeffect_tab,tpm_return_func1],[{tpm_return_func1,3}],20), - - ok. -%% ------------------------------------------------------------------------------ - -%% This function is for testing that appending the tracer to a trace action term -%% works. -activate_deactivate_meta_tracing_tracer(Nodes) -> - ?l {ok,NodeResults}= - inviso:tpm_tracer(Nodes,lists,module_info,0,[{'_',[],[{trace,[all],[call]}]}],void), - ?l true=check_noderesults(Nodes,{ok,1},NodeResults), - ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]), - {meta,P}=rpc:call(N,erlang,trace_info,[{lists,module_info,0},meta]), - {meta_match_spec,[{'_',[],[{trace,[all],Enable}]}]}= - rpc:call(N,erlang,trace_info,[{lists,module_info,0}, - meta_match_spec]), - true=list_search(Enable,fun({{tracer,P}}) when is_port(P)->true; - (_) -> false - end) - end, - Nodes), - ?l {ok,NodeResults2}= - inviso:ctpm(Nodes,lists,module_info,0), - ?l true=check_noderesults(Nodes,ok,NodeResults2), - ?l lists:foreach(fun(N)->{meta,false}= - rpc:call(N,erlang,trace_info,[{lists,module_info,0},meta]) - end, - Nodes), - ok. -%% ------------------------------------------------------------------------------ - -deactivate_meta_tracing(Nodes) -> - ?l lists:foreach(fun(N)->{meta,P}= - rpc:call(N,erlang,trace_info,[{erlang,register,2},meta]), - true=is_pid(P) - end, - Nodes), - ?l lists:foreach(fun(N)->{meta,P}= - rpc:call(N,erlang,trace_info,[{erlang,unregister,1},meta]), - true=is_pid(P) - end, - Nodes), - ?l {ok,NodeResults1}=inviso:ctpm_localnames(), - ?l lists:foreach(fun(N)->{meta,false}= - rpc:call(N,erlang,trace_info,[{erlang,register,2},meta]) end, - Nodes), - ?l lists:foreach(fun(N)->{meta,false}= - rpc:call(N,erlang,trace_info,[{erlang,unregister,1},meta]) - end, - Nodes), - ?l true=check_noderesults(Nodes,{ok,ok},NodeResults1), - - ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]), - {meta,P}=rpc:call(N, - erlang, - trace_info, - [{global,handle_call,3},meta]) - end, - Nodes), - ?l lists:foreach(fun(N)->P=rpc:call(N,erlang,whereis,[inviso_rt_meta]), - {meta,P}=rpc:call(N, - erlang, - trace_info, - [{global,delete_global_name,2},meta]) - end, - Nodes), - ?l {ok,NodeResults1b}=inviso:ctpm_globalnames(), - ?l true=check_noderesults(Nodes,{ok,ok},NodeResults1b), - ?l lists:foreach(fun(N)-> - {meta,false}=rpc:call(N, - erlang, - trace_info, - [{global,handle_call,3},meta]) - end, - Nodes), - ?l lists:foreach(fun(N)-> - {meta,false}=rpc:call(N, - erlang, - trace_info, - [{global,delete_global_name,2},meta]) - end, - Nodes), - - ?l lists:foreach(fun(N)->{meta,P}= - rpc:call(N,erlang,trace_info,[{lists,module_info,0},meta]), - true=is_pid(P) - end, - Nodes), - ?l {ok,NodeResults2}=inviso:ctpm(lists,module_info,0), - ?l true=check_noderesults(Nodes,ok,NodeResults2), - ?l lists:foreach(fun(N)->{meta,false}= - rpc:call(N,erlang,trace_info,[{lists,module_info,0},meta]) end, - Nodes), - ?l [{_,0}]=ets:lookup(inviso_sideeffect_tab,tpm_init_func1), - ?l {ok,NodeResults3}=inviso:ctpm(math,module_info,1), - ?l true=check_noderesults(Nodes,ok,NodeResults3), - ok. -%% ------------------------------------------------------------------------------ - -%% Functions acting as callbacks for testing the meta tracing mechanisms. -tpm_init_func1(_M,_F,_Arity,PublLD) -> - ets:update_counter(inviso_sideeffect_tab,tpm_init_func1,1), - {ok,PublLD,void}. -tpm_call_func1(_Pid,{call,_Args,_TS},PublLD) -> - ets:update_counter(inviso_sideeffect_tab,tpm_call_func1,1), - {ok,PublLD,void}. -tpm_return_func1(_Pid,{return_from,_ReturnVal,_TS},PublLD) -> - ets:update_counter(inviso_sideeffect_tab,tpm_return_func1,1), - {ok,PublLD,void}; -tpm_return_func1(_Pid,{exception_from,_ReturnVal,_TS},PublLD) -> - ets:update_counter(inviso_sideeffect_tab,tpm_return_func1,1), - ets:update_counter(inviso_sideeffect_tab,tpm_return_func1,1), - {ok,PublLD,void}. -tpm_remove_func1(_M,_F,_Arity,PublLD) -> - ets:update_counter(inviso_sideeffect_tab,tpm_init_func1,-1), - {ok,PublLD}. -%% ------------------------------------------------------------------------------ - - -%% Help function which traces on a function and makes function calls until there -%% are two files in the wrap-set. -fill_and_reach_two_wrapfiles(PrivDir,RegExp,Nodes) -> - ?l lists:foreach(fun(N)->spawn(N,?MODULE,test_proc_init,[]) end,Nodes), - ?l {ok,NodeResults1}=inviso:tpl(Nodes,?MODULE,test_function,0,[]), - ?l true=check_noderesults(Nodes,{ok,[1]},NodeResults1), - ?l {ok,NodeResults2}=inviso:tf(Nodes,inviso_test_proc,[call]), - ?l true=check_noderesults(Nodes,{ok,[1]},NodeResults2), - fill_and_reach_two_wrapfiles_2(PrivDir,RegExp,Nodes), - ?l {ok,NodeResults3}=inviso:ctf(Nodes,inviso_test_proc,[call]), - ?l true=check_noderesults(Nodes,{ok,[1]},NodeResults3), - ?l {ok,NodeResults4}=inviso:ctpl(Nodes,?MODULE,test_function,0), - ?l true=check_noderesults(Nodes,{ok,[1]},NodeResults4), - ok. - -fill_and_reach_two_wrapfiles_2(PrivDir,RegExp,[Node|Rest]) -> - ?l ok=rpc:call(Node,?MODULE,fill_and_reach_two_wrapfiles_3,[PrivDir,RegExp]), - fill_and_reach_two_wrapfiles_2(PrivDir,RegExp,Rest); -fill_and_reach_two_wrapfiles_2(_,_,[]) -> - ok. - -fill_and_reach_two_wrapfiles_3(Dir,RegExp) -> - ok=send_to_test_proc({apply,?MODULE,test_function,[]}, - fun reach_two_wraps_stopfun/1, - {Dir,RegExp++atom_to_list(node())}, - 100). - -%% Help function intended to be used as fun in a send_to_test_proc/4 call. -%% The function lists the content of Dir and looks for occurancies of String. -%% If two files containing the string String are found, 'done' is returned. -%% Otherwise 'continue'. -reach_two_wraps_stopfun({Dir,RegExp}) -> - case file:list_dir(Dir) of - {ok,FileNames} -> - case how_many_files_regexp(FileNames,RegExp,0) of - {ok,2} -> - done; - _ -> - continue - end; - {error,_Reason} -> - error - end. -%% ------------------------------------------------------------------------------ - -%% ------------------------------------------------------------------------------ -%% Help function for the overload tests. These functions are used as callbacks. -%% ------------------------------------------------------------------------------ - -overload1(_) -> - ets:update_counter(inviso_sideeffect_tab,ovl1,1), - ok. -%% This function is used when timeout occurs inside the runtime component. -%% That is it is time to check for overload. -overload2({timeout,overload2i_data}) -> - ets:update_counter(inviso_sideeffect_tab,ovl2,1), - ok. -overload2i() -> - ets:insert(inviso_sideeffect_tab,{ovl2,0}), - {ok,overload2i_data}. -overload2r(overload2i_data) -> - ets:delete(inviso_sideeffect_tab,ovl2). - -%% This function is used when timeout occurs inside the runtime component. -%% That is it is time to check for overload. -overload3({timeout,overload3i_data}) -> - ets:update_counter(inviso_sideeffect_tab,ovl3,1), - ok; -overload3(_) -> % Must handle garbage too. - ignore. -overload3i() -> - ets:insert(inviso_sideeffect_tab,{ovl3,0}), - {ok,overload3i_data}. -overload3r(overload3i_data) -> - ets:insert(inviso_sideeffect_tab,{ovl3r,done}), - ets:delete(inviso_sideeffect_tab,ovl3). - -overload4(_) -> - case ets:lookup(inviso_sideeffect_tab,ovl4_suspend) of - [] -> % We are supposed to be running. - ets:update_counter(inviso_sideeffect_tab,ovl4,1), - ok; - [_] -> - {suspend,test} - end. - -%% This function is used when overload check is done by icomming message. -overload5({msg,{test_of_loadcheck,overload5i_data}}) -> - ets:update_counter(inviso_sideeffect_tab,ovl5,1), - ok; -overload5(_) -> - ignore. -overload5i() -> - ets:insert(inviso_sideeffect_tab,{ovl5,0}), - {ok,overload5i_data}. -overload5r(overload5i_data) -> - ets:delete(inviso_sideeffect_tab,ovl5), - ets:insert(inviso_sideeffect_tab,{ovl5r,done}); -overload5r(X) -> - erlang:display({'***',overload5r,X}). - -overload6(_) -> - ets:update_counter(inviso_sideeffect_tab,ovl6,1), - ok. -%% ------------------------------------------------------------------------------ - -%% ------------------------------------------------------------------------------ -%% Help function for the subscription tests. These function implements a collector -%% process which will subscribe to inviso_events from the control component. -%% ------------------------------------------------------------------------------ - -%% Function which can be used to check if an inviso_event has arrived. The function -%% takes a fun which tests the messages. -check_msg_collector([],_,_) -> - true; -check_msg_collector(_,_,0) -> - false; -check_msg_collector(Nodes,Fun,T) -> - Ref=make_ref(), - inviso_collector_proc ! {fetch_message,self(),Ref,Fun}, - receive - {inviso,Ref,{true,Node}} -> - check_msg_collector(lists:delete(Node,Nodes),Fun,T-1); - {inviso,Ref,false} -> - timer:sleep(100), - check_msg_collector(Nodes,Fun,T-1) - end. - -%% Spawn on this function to get a subscriber. -inviso_msg_collector() -> - register(inviso_collector_proc,self()), - inviso_msg_collector_loop([]). - -inviso_msg_collector_loop(Msgs) -> - receive - {fetch_message,From,Ref,Fun} -> - {NewMsgs,Reply}=inviso_msg_collector_selector(Msgs,Fun,[]), - From ! {inviso,Ref,Reply}, - inviso_msg_collector_loop(NewMsgs); - Msg -> - inviso_msg_collector_loop([Msg|Msgs]) - end. - -inviso_msg_collector_selector([M|Rest],Fun,Accum) -> - case Fun(M) of - {true,X} -> - {Rest++Accum,{true,X}}; - _ -> - inviso_msg_collector_selector(Rest,Fun,[M|Accum]) - end; -inviso_msg_collector_selector([],_,Accum) -> - {Accum,false}. -%% ------------------------------------------------------------------------------ - - -%% ============================================================================== -%% Help functions -%% ============================================================================== - -list_search([E|Rest],Fun) -> - case Fun(E) of - true -> - true; - false -> - list_search(Rest,Fun) - end; -list_search([],_Fun) -> - false. -%% ------------------------------------------------------------------------------ - -%% Help function checking that there is a Result for each node in Nodes. -%% Returns 'true' if successful. -check_noderesults(Nodes,Fun,[{Node,Result}|Rest]) when is_function(Fun) -> - case Fun({Node,Result}) of - true -> - case lists:member(Node,Nodes) of - true -> - check_noderesults(lists:delete(Node,Nodes),Fun,Rest); - false -> % Not good. - unknown_node_in_returnvalue - end; - _ -> - illegal_result - end; -check_noderesults(Nodes,Result,[{Node,Result}|Rest]) -> - case lists:member(Node,Nodes) of - true -> - check_noderesults(lists:delete(Node,Nodes),Result,Rest); - false -> % Not good. - unknown_node_in_returnvalue - end; -check_noderesults([],_,[]) -> - true; -check_noderesults(X,Y,Z) -> - io:format("Bad arguments to check noderesults:~w~n~w~n~w~n",[X,Y,Z]), - false. -%% ------------------------------------------------------------------------------ - -%% Help function doing rpc on all nodes in Nodes calling M:F. Returns 'true' if -%% successful. -check_on_nodes([Node|Rest],M,F,Args,Result) when Node==node() -> - if - is_function(Result) -> - ?l true=Result(apply(M,F,Args)); - true -> - ?l Result=apply(M,F,Args) - end, - check_on_nodes(Rest,M,F,Args,Result); -check_on_nodes([Node|Rest],M,F,Args,Result) -> - if - is_function(Result) -> - ?l true=Result(rpc:call(Node,M,F,Args)); - true -> - ?l Result=rpc:call(Node,M,F,Args) - end, - check_on_nodes(Rest,M,F,Args,Result); -check_on_nodes([],_,_,_,_) -> - true. -%% ------------------------------------------------------------------------------ - -%% Help function which given a list of files searches through it and returns -%% how many satisfies the RegExp. -%% Returns {ok,N}. -how_many_files_regexp([],_,N) -> - {ok,N}; -how_many_files_regexp([FName|Rest],RegExp,N) -> - case re:run(FName,RegExp,[{capture,none}]) of - match -> - how_many_files_regexp(Rest,RegExp,N+1); - nomatch -> - how_many_files_regexp(Rest,RegExp,N); - {error,Reason} -> - test_server:fail(Reason) - end. -%% ------------------------------------------------------------------------------ - -%% Help function killing a bunch of registered processes. -process_killer([RegName|Rest]) -> - case whereis(RegName) of - undefined -> - case global:whereis_name(RegName) of - undefined -> - process_killer(Rest); - P when is_pid(P) -> - if - node()==node(P) -> - exit(P,kill); - true -> - true - end, - process_killer(Rest) - end; - P when is_pid(P) -> - exit(P,kill), - process_killer(Rest) - end; -process_killer([]) -> - true. -%% ------------------------------------------------------------------------------ - -%% Help function which waits for a function call to become Result. This is useful -%% if what we are waiting for can happend independantly of indications we have -%% access to. -poll(_,_,_,_,0) -> - error; -poll(M,F,Args,Result,Times) -> - try apply(M,F,Args) of - What when is_function(Result) -> - case Result(What) of - true -> - ok; - _ -> - timer:sleep(100), - poll(M,F,Args,Result,Times-1) - end; - Result -> - ok; - _ -> - timer:sleep(100), - poll(M,F,Args,Result,Times-1) - catch - error:Reason -> - io:format("Apply in suite-function poll/5 failed, ~w~n",[Reason]), - timer:sleep(100), - poll(M,F,Args,Result,Times-1) - end. -%% ------------------------------------------------------------------------------ - -insert_remotenode_config(Name,Node,Config) -> - [{remotenode,{Name,Node}}|Config]. -%% ------------------------------------------------------------------------------ - -insert_timetraphandle_config(Handle,Config) -> - [{timetraphandle,Handle}|Config]. -%% ------------------------------------------------------------------------------ - -get_remotenode_config(Name, [{remotenode, {Name, Node}}| _Cs]) -> - Node; -get_remotenode_config(Name, [_ | Cs]) -> - get_remotenode_config(Name, Cs); -get_remotenode_config(Name, []) -> - exit({no_remotenode, Name}). - -%% ------------------------------------------------------------------------------ - -get_timetraphandle_config(Config) -> - {value,{_,Handle}}=lists:keysearch(timetraphandle,1,Config), - Handle. -%% ------------------------------------------------------------------------------ - -get_remotenodes_config([{remotenode,{_Name,Node}}|Config]) -> - [Node|get_remotenodes_config(Config)]; -get_remotenodes_config([_|Config]) -> - get_remotenodes_config(Config); -get_remotenodes_config([]) -> - []. -%% ------------------------------------------------------------------------------ - -remove_remotenode_config(Name, [{remotenode, {Name, _}} | Cs]) -> - Cs; -remove_remotenode_config(Name, [C | Cs]) -> - [C | remove_remotenode_config(Name, Cs)]; -remove_remotenode_config(_Name, []) -> - []. - -%% ------------------------------------------------------------------------------ - -remove_timetraphandle_config(Config) -> - lists:keydelete(timetraphandle,1,Config). -%% ------------------------------------------------------------------------------ - -%% This function can be meta traced in order to check that exception_trace works. -%% Must be exported. -failing_function(nofailure) -> - true; -failing_function(failure) -> - exit(failure). -%% ------------------------------------------------------------------------------ - -%% ============================================================================== -%% Code for a test process which can be started. -%% ============================================================================== - -test_proc_init() -> - register(inviso_test_proc,self()), - test_proc_loop(). - -test_proc_loop() -> - receive - {apply,M,F,Args} -> - apply(M,F,Args), - test_proc_loop(); - X -> - io:format("Got ~w~n",[X]), - test_proc_loop() - end. - -global_test_proc_init() -> - global:register_name(global_inviso_test_proc,self()), - test_proc_loop(). -%% ------------------------------------------------------------------------------ - -send_to_test_proc(_,_,_,0) -> - error; -send_to_test_proc(Msg,Fun,FunArg,N) -> - inviso_test_proc ! Msg, - case Fun(FunArg) of - done -> - ok; - error -> - test_server:fail(send_to_test_proc); - _ -> - send_to_test_proc(Msg,Fun,FunArg,N-1) - end. -%% ------------------------------------------------------------------------------ - - -%% This function is here to be traced on by the inviso_test_proc. Must be exported. -test_function() -> - 1+1. -%% ------------------------------------------------------------------------------ - - -%% ============================================================================== -%% Code for a test side effect table process. -%% ============================================================================== - -%% The side effect logger is a process owning a public ETS table. The idea is that -%% various callback functions can write in the table when called. In that way -%% correct calling of the call-backs can be verified. -start_side_effect_logger(Node) -> - ?l true=is_pid(spawn(Node,?MODULE,side_effect_logger_proc,[])), - ?l ok=poll(rpc,call,[Node,ets,lookup,[inviso_sideeffect_tab,foo]],[],20). - -%% This one must be exported. -side_effect_logger_proc() -> - register(inviso_tab_proc,self()), % So we can kill it later. - ets:new(inviso_sideeffect_tab,[public,named_table]), - side_effect_logger_proc_2(). - -side_effect_logger_proc_2() -> - receive - _X -> % This process is not expecting anything! - side_effect_logger_proc_2() - end. -%% ------------------------------------------------------------------------------ diff --git a/lib/runtime_tools/test/inviso_testmodule1_foo.erl b/lib/runtime_tools/test/inviso_testmodule1_foo.erl deleted file mode 100644 index a7a22cad39..0000000000 --- a/lib/runtime_tools/test/inviso_testmodule1_foo.erl +++ /dev/null @@ -1,9 +0,0 @@ --module(inviso_testmodule1_foo). - --compile(export_all). - -%% The purpose of this module is simply to have a module that is -%% guaranteed not loaded. - -foo() -> - true. diff --git a/lib/runtime_tools/test/runtime_tools_SUITE.erl b/lib/runtime_tools/test/runtime_tools_SUITE.erl index b26f3dd881..62497ab527 100644 --- a/lib/runtime_tools/test/runtime_tools_SUITE.erl +++ b/lib/runtime_tools/test/runtime_tools_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2011. All Rights Reserved. +%% Copyright Ericsson AB 2010-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 @@ -25,7 +25,7 @@ -export([init_per_testcase/2, end_per_testcase/2]). %% Test cases --export([app_file/1]). +-export([app_file/1, start_stop_app/1]). %% Default timetrap timeout (set in init_per_testcase) -define(default_timeout, ?t:minutes(1)). @@ -42,7 +42,8 @@ end_per_testcase(_Case, Config) -> suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [app_file]. + [app_file, + start_stop_app]. groups() -> []. @@ -60,10 +61,14 @@ end_per_group(_GroupName, Config) -> Config. -app_file(suite) -> - []; -app_file(doc) -> - ["Testing .app file"]; -app_file(Config) when is_list(Config) -> +app_file(_Config) -> ?line ok = ?t:app_test(runtime_tools), ok. + +start_stop_app(_Config) -> + ok = application:start(runtime_tools), + Sup = whereis(runtime_tools_sup), + true = is_pid(Sup), + Ref = erlang:monitor(process,Sup), + ok = application:stop(runtime_tools), + receive {'DOWN', Ref, process, Sup, shutdown} -> ok end. |