1: %%
    2: %% %CopyrightBegin%
    3: %% 
    4: %% Copyright Ericsson AB 2001-2013. All Rights Reserved.
    5: %% 
    6: %% The contents of this file are subject to the Erlang Public License,
    7: %% Version 1.1, (the "License"); you may not use this file except in
    8: %% compliance with the License. You should have received a copy of the
    9: %% Erlang Public License along with this software. If not, it can be
   10: %% retrieved online at http://www.erlang.org/.
   11: %% 
   12: %% Software distributed under the License is distributed on an "AS IS"
   13: %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
   14: %% the License for the specific language governing rights and limitations
   15: %% under the License.
   16: %% 
   17: %% %CopyrightEnd%
   18: %%
   19: -module(cover_SUITE).
   20: 
   21: -export([all/0, init_per_testcase/2, end_per_testcase/2,
   22: 	 suite/0,groups/0,init_per_suite/1, end_per_suite/1, 
   23: 	 init_per_group/2,end_per_group/2]).
   24: 
   25: -export([start/1, compile/1, analyse/1, misc/1, stop/1, 
   26: 	 distribution/1, reconnect/1, die_and_reconnect/1,
   27: 	 dont_reconnect_after_stop/1, stop_node_after_disconnect/1,
   28: 	 export_import/1,
   29: 	 otp_5031/1, eif/1, otp_5305/1, otp_5418/1, otp_6115/1, otp_7095/1,
   30:          otp_8188/1, otp_8270/1, otp_8273/1, otp_8340/1,
   31: 	 otp_10979_hanging_node/1, compile_beam_opts/1]).
   32: 
   33: -include_lib("test_server/include/test_server.hrl").
   34: 
   35: %%----------------------------------------------------------------------
   36: %% The following directory structure is assumed:
   37: %%  cwd __________________________________________
   38: %%  |  \   \   \   \   \     \                    \
   39: %%  a   b   cc   d   f  d1   compile_beam_____  otp_6115
   40: %%                      |      \    \  \  \   \    \  \
   41: %%                      e      crypt v  w  x   d   f1  f2
   42: %%                                             |
   43: %%                                             y
   44: %%----------------------------------------------------------------------
   45: 
   46: suite() -> [{ct_hooks,[ts_install_cth]}].
   47: 
   48: all() -> 
   49:     case whereis(cover_server) of
   50: 	undefined ->
   51: 	    [start, compile, analyse, misc, stop,
   52: 	     distribution, reconnect, die_and_reconnect,
   53: 	     dont_reconnect_after_stop, stop_node_after_disconnect,
   54: 	     export_import, otp_5031, eif, otp_5305, otp_5418,
   55: 	     otp_6115, otp_7095, otp_8188, otp_8270, otp_8273,
   56: 	     otp_8340, otp_10979_hanging_node, compile_beam_opts];
   57: 	_pid ->
   58: 	    {skip,
   59: 	     "It looks like the test server is running "
   60: 	     "cover. Can't run cover test."}
   61:     end.
   62: 
   63: groups() -> 
   64:     [].
   65: 
   66: init_per_suite(Config) ->
   67:     Config.
   68: 
   69: end_per_suite(_Config) ->
   70:     ok.
   71: 
   72: init_per_group(_GroupName, Config) ->
   73:     Config.
   74: 
   75: end_per_group(_GroupName, Config) ->
   76:     Config.
   77: 
   78: init_per_testcase(TC, Config) when TC =:= misc; 
   79: 				   TC =:= compile; 
   80: 				   TC =:= analyse;
   81: 				   TC =:= distribution;
   82: 				   TC =:= otp_5031;
   83: 				   TC =:= stop ->
   84:     case code:which(crypto) of
   85: 	Path when is_list(Path) ->
   86: 	    init_per_testcase(dummy_tc, Config);
   87: 	_Else ->
   88: 	    {skip, "No crypto file to test with"}
   89:     end;
   90: init_per_testcase(_TestCase, Config) ->
   91:     Config.
   92: 
   93: end_per_testcase(TestCase, _Config) ->
   94:     case lists:member(TestCase,[start,compile,analyse,misc]) of
   95: 	true -> ok;
   96: 	false -> cover:stop()
   97:     end,
   98:     ok.
   99: 
  100: start(suite) -> [];
  101: start(Config) when is_list(Config) ->
  102:     ?line ok = file:set_cwd(?config(data_dir, Config)),
  103: 
  104:     ?line Files = lsfiles(),
  105:     ?line remove(files(Files, ".out")),
  106: 
  107:     ?line {ok, Pid} = cover:start(),
  108:     ?line {error, {already_started, Pid}} = cover:start().
  109: 
  110: compile(suite) -> [];
  111: compile(Config) when is_list(Config) ->
  112:     ?line ok = file:set_cwd(?config(data_dir, Config)),
  113: 
  114:     ?line Result1 = cover:compile_directory(),
  115:     ?line SortedResult = lists:sort(Result1),
  116:     ?line {ok, CWD} = file:get_cwd(),
  117:     ?line Result2 = cover:compile_directory(CWD),
  118:     ?line SortedResult = lists:sort(Result2),
  119:     ?line [{error,_DFile},{ok,a},{ok,b},{ok,cc},{ok,f}] = SortedResult,
  120:     ?line [{ok,e}] = cover:compile_directory("d1"),
  121:     ?line {error,enoent} = cover:compile_directory("d2"),
  122: 
  123:     ?line {ok,a} = cover:compile(a),
  124:     ?line {ok,b} = compile:file(b),
  125:     ?line code:purge(b),
  126:     ?line {module,b} = code:load_file(b),
  127:     ?line {ok,d} = cover:compile("d.erl", [{d,'AGE',42}]),
  128:     ?line {error,_BBFile} = cover:compile(bb),
  129: 
  130:     ?line StdlibDir = code:lib_dir(stdlib),
  131:     ?line Lists = filename:join([StdlibDir, "src", "lists.erl"]),
  132:     ?line {error, Lists} = cover:compile(Lists),
  133: 
  134:     %% For compiling beam: using dummy files v,w,x,y and z
  135:     ?line file:set_cwd("compile_beam"),
  136:     ?line {ok,_} = compile:file(v,[debug_info,report]),
  137:     ?line {ok,_} = compile:file(w,[debug_info,report]),
  138:     ?line {ok,_} = compile:file(x),
  139:     ?line {ok,_} = compile:file("d/y",[debug_info,{outdir,"d"},report]),
  140:     ?line Key = "A Krypto Key",
  141:     CryptoWorks = crypto_works(),
  142:     case CryptoWorks of
  143: 	false ->
  144: 	    {ok,_} = compile:file(crypt, [debug_info,report]),
  145: 	    {ok,crypt} = cover:compile_beam("crypt.beam");
  146: 	true ->
  147: 	    {ok,_} = compile:file(crypt, [{debug_info_key,Key},report]),
  148: 	    {error,{encrypted_abstract_code,_}} =
  149: 		cover:compile_beam("crypt.beam"),
  150: 	    ok = beam_lib:crypto_key_fun(simple_crypto_fun(Key)),
  151: 	    {ok,crypt} = cover:compile_beam("crypt.beam")
  152:     end,
  153:     Path = filename:join([?config(data_dir, Config), "compile_beam", "v.erl"]),
  154:     ?line {ok,v} = cover:compile_beam(v),
  155:     {source,Path} = lists:keyfind(source, 1, v:module_info(compile)),
  156:     ?line {ok,w} = cover:compile_beam("w.beam"),
  157:     ?line {error,{no_abstract_code,"./x.beam"}} = cover:compile_beam(x),
  158:     ?line {error,{already_cover_compiled,no_beam_found,a}}=cover:compile_beam(a),
  159:     ?line {error,non_existing} = cover:compile_beam(z),
  160:     ?line [{ok,y}] = cover:compile_beam_directory("d"),
  161:     ?line Result3 = lists:sort(cover:compile_beam_directory()),
  162:     ?line [{error,{no_abstract_code,_XBeam}},{ok,crypt},{ok,v},{ok,w}] = Result3,
  163:     ?line {error,enoent} = cover:compile_beam_directory("d2"),
  164:     ?line decompile([v,w,y]),
  165:     ?line Files = lsfiles(),
  166:     ?line remove(files(Files, ".beam")).
  167: 
  168: crypto_works() ->
  169:     try crypto:start() of
  170: 	{error,{already_started,crypto}} -> true;
  171: 	ok -> true
  172:     catch
  173: 	error:_ ->
  174: 	    false
  175:     end.
  176: 
  177: simple_crypto_fun(Key) ->
  178:     fun(init) -> ok;
  179:        ({debug_info, des3_cbc, crypt, _}) -> Key
  180:     end.
  181: 
  182: analyse(suite) -> [];
  183: analyse(Config) when is_list(Config) ->
  184:     ?line ok = file:set_cwd(?config(data_dir, Config)),
  185: 
  186:     ?line done = a:start(5),
  187: 
  188:     ?line {ok, {a,{17,2}}} = cover:analyse(a, coverage, module),
  189:     ?line {ok, [{{a,start,1},{6,0}},
  190: 		{{a,stop,1},{0,1}},
  191: 		{{a,pong,1},{1,0}},
  192: 		{{a,loop,3},{5,1}},
  193: 		{{a,trycatch,1},{4,0}},
  194: 		{{a,exit_kalle,0},{1,0}}]} = cover:analyse(a, coverage, function),
  195:     ?line {ok, [{{a,start,1,1},{6,0}},
  196: 		{{a,stop,1,1},{0,1}},
  197: 		{{a,pong,1,1},{1,0}},
  198: 		{{a,loop,3,1},{3,1}},
  199: 		{{a,loop,3,2},{2,0}},
  200: 		{{a,trycatch,1,1},{4,0}},
  201: 		{{a,exit_kalle,0,1},{1,0}}]} = cover:analyse(a, coverage, clause),
  202:     ?line {ok, [{{a,9},{1,0}},
  203: 		{{a,10},{1,0}},
  204: 		{{a,11},{1,0}},
  205: 		{{a,13},{1,0}},
  206: 		{{a,14},{1,0}},
  207: 		{{a,15},{1,0}},
  208: 		{{a,21},{0,1}},
  209: 		{{a,26},{1,0}},
  210: 		{{a,31},{1,0}},
  211: 		{{a,32},{1,0}},
  212: 		{{a,34},{1,0}},
  213: 		{{a,36},{0,1}},
  214: 		{{a,39},{1,0}},
  215: 		{{a,40},{1,0}},
  216: 		{{a,44},{1,0}},
  217: 		{{a,47},{1,0}},
  218: 		{{a,49},{1,0}},
  219: 		{{a,51},{1,0}},
  220: 		{{a,55},{1,0}}]} = cover:analyse(a, coverage, line),
  221: 
  222:     ?line {ok, {a,15}} = cover:analyse(a, calls, module),
  223:     ?line {ok, [{{a,start,1},1},
  224: 		{{a,stop,1},0},
  225: 		{{a,pong,1},5},
  226: 		{{a,loop,3},6},
  227: 		{{a,trycatch,1},2},
  228: 		{{a,exit_kalle,0},1}]} = cover:analyse(a, calls, function),
  229:     ?line {ok, [{{a,start,1,1},1},
  230: 		{{a,stop,1,1},0},
  231: 		{{a,pong,1,1},5},
  232: 		{{a,loop,3,1},5},
  233: 		{{a,loop,3,2},1},
  234: 		{{a,trycatch,1,1},2},
  235: 		{{a,exit_kalle,0,1},1}]} = cover:analyse(a, calls, clause),
  236:     ?line {ok, [{{a,9},1},
  237: 		{{a,10},1},
  238: 		{{a,11},1},
  239: 		{{a,13},1},
  240: 		{{a,14},1},
  241: 		{{a,15},1},
  242: 		{{a,21},0},
  243: 		{{a,26},5},
  244: 		{{a,31},5},
  245: 		{{a,32},5},
  246: 		{{a,34},5},
  247: 		{{a,36},0},
  248: 		{{a,39},1},
  249: 		{{a,40},1},
  250: 		{{a,44},2},
  251: 		{{a,47},1},
  252: 		{{a,49},1},
  253: 		{{a,51},2},
  254: 		{{a,55},1}]} = cover:analyse(a, calls, line),
  255: 
  256:     ?line {ok, [{{a,start,1},{6,0}},
  257: 		{{a,stop,1},{0,1}},
  258: 		{{a,pong,1},{1,0}},
  259: 		{{a,loop,3},{5,1}},
  260: 		{{a,trycatch,1},{4,0}},
  261: 		{{a,exit_kalle,0},{1,0}}]} = cover:analyse(a),
  262:     ?line {ok, {a,{17,2}}} = cover:analyse(a, module),
  263:     ?line {ok, [{{a,start,1},1},
  264: 		{{a,stop,1},0},
  265: 		{{a,pong,1},5},
  266: 		{{a,loop,3},6},
  267: 		{{a,trycatch,1},2},
  268: 		{{a,exit_kalle,0},1}]} = cover:analyse(a, calls),
  269: 
  270:     ?line {ok, "a.COVER.out"} = cover:analyse_to_file(a),
  271:     ?line {ok, "e.COVER.out"} = cover:analyse_to_file(e),
  272:     ?line {ok, "a.COVER.html"} = cover:analyse_to_file(a,[html]),
  273:     ?line {ok, "e.COVER.html"} = cover:analyse_to_file(e,[html]),
  274: 
  275:     %% analyse_to_file of file which is compiled from beam
  276:     ?line {ok,f} = compile:file(f,[debug_info]),
  277:     ?line code:purge(f),
  278:     ?line {module,f} = code:load_file(f),
  279:     ?line {ok,f} = cover:compile_beam(f),
  280:     ?line f:f2(),
  281:     ?line {ok, "f.COVER.out"} = cover:analyse_to_file(f),
  282: 
  283:     %% Source code can be found via source
  284:     ?line {ok,v} = compile:file("compile_beam/v",[debug_info]),
  285:     ?line code:purge(v),
  286:     ?line {module,v} = code:load_file(v),
  287:     ?line {ok,v} = cover:compile_beam(v),
  288:     {ok,"v.COVER.out"} = cover:analyse_to_file(v),
  289: 
  290:     %% Source code cannot be found
  291:     {ok,_} = file:copy("compile_beam/z.erl", "z.erl"),
  292:     {ok,z} = compile:file(z,[debug_info]),
  293:     code:purge(z),
  294:     {module,z} = code:load_file(z),
  295:     {ok,z} = cover:compile_beam(z),
  296:     ok = file:delete("z.erl"),
  297:     {error,no_source_code_found} = cover:analyse_to_file(z),
  298:     code:purge(z),
  299:     code:delete(z),
  300: 
  301:     ?line {error,{not_cover_compiled,b}} = cover:analyse(b),
  302:     ?line {error,{not_cover_compiled,g}} = cover:analyse(g),
  303:     ?line {error,{not_cover_compiled,b}} = cover:analyse_to_file(b),
  304:     ?line {error,{not_cover_compiled,g}} = cover:analyse_to_file(g).
  305: 
  306: misc(suite) -> [];
  307: misc(Config) when is_list(Config) ->
  308:     ?line ok = file:set_cwd(?config(data_dir, Config)),
  309: 
  310:     ?line [a,cc,crypt,d,e,f,v] = lists:sort(cover:modules()),
  311: 
  312:     ?line {ok,cc} = compile:file(cc),
  313:     ?line code:purge(cc),
  314:     ?line {module,cc} = code:load_file(cc),
  315:     ?line [a,crypt,d,e,f,v] = lists:sort(cover:modules()),
  316: 
  317:     ?line {file, _File} = cover:is_compiled(a),
  318:     ?line false = cover:is_compiled(b),
  319:     ?line false = cover:is_compiled(g),
  320: 
  321:     ?line ok = cover:reset(a),
  322:     ?line {ok, {a,{0,19}}} = cover:analyse(a, module),
  323:     ?line ok = cover:reset().
  324: 
  325: stop(suite) -> [];
  326: stop(Config) when is_list(Config) ->
  327:     ?line ok = file:set_cwd(?config(data_dir, Config)),
  328: 
  329:     ?line cover_compiled = code:which(a),
  330:     ?line {ok,d} = compile:file(d, [{d,'AGE',42}]),
  331:     ?line code:purge(d),
  332:     ?line {module,d} = code:load_file(d),
  333:     ?line ok = cover:stop(),
  334:     ?line Beam = code:which(a),
  335:     ?line true = is_unloaded(Beam),
  336: 
  337:     ?line Files = lsfiles(),
  338:     ?line remove(files(Files, ".out")),
  339:     ?line remove(files(Files, ".html")),
  340:     ?line remove(files(Files, ".beam")).
  341: 
  342: distribution(suite) -> [];
  343: distribution(Config) when is_list(Config) ->
  344:     ?line DataDir = ?config(data_dir, Config),
  345:     ?line ok = file:set_cwd(DataDir),
  346: 
  347:     ?line {ok,N1} = ?t:start_node(cover_SUITE_distribution1,slave,[]),
  348:     ?line {ok,N2} = ?t:start_node(cover_SUITE_distribution2,slave,[]),
  349:     ?line {ok,N3} = ?t:start_node(cover_SUITE_distribution3,slave,[]),
  350:     ?line {ok,N4} = ?t:start_node(cover_SUITE_distribution4,slave,[]),
  351: 
  352:     %% Check that an already compiled module is loaded on new nodes
  353:     ?line {ok,f} = cover:compile(f),
  354:     ?line {ok,[_,_,_,_]} = cover:start(nodes()),
  355:     ?line cover_compiled = code:which(f),
  356:     ?line cover_compiled = rpc:call(N1,code,which,[f]),
  357:     ?line cover_compiled = rpc:call(N2,code,which,[f]),
  358:     ?line cover_compiled = rpc:call(N3,code,which,[f]),
  359:     ?line cover_compiled = rpc:call(N4,code,which,[f]),
  360: 
  361:     %% Check that a node cannot be started twice
  362:     ?line {ok,[]} = cover:start(N2),
  363: 
  364:     %% Check that the current node (i.e. the main node) is not started with
  365:     %% start/1 and not stopped with stop/1
  366:     ?line {ok,[]} = cover:start(node()),
  367:     ?line ok = cover:stop(node()),
  368:     ?line true = is_pid(whereis(cover_server)),
  369: 
  370:     %% Check that a new compiled module is loaded on all existing nodes
  371:     ?line compile:file("compile_beam/v",[debug_info]),
  372:     ?line {ok,v} = cover:compile_beam(v),
  373:     ?line cover_compiled = code:which(v),
  374:     ?line cover_compiled = rpc:call(N1,code,which,[v]),
  375:     ?line cover_compiled = rpc:call(N2,code,which,[v]),
  376:     ?line cover_compiled = rpc:call(N3,code,which,[v]),
  377:     ?line cover_compiled = rpc:call(N4,code,which,[v]),
  378:     
  379:     %% this is lost when the node is killed
  380:     ?line rpc:call(N3,f,f2,[]),
  381:     ?line rpc:call(N3,erlang,halt,[]),
  382: 
  383:     %% this should be visible in analyse
  384:     ?line rpc:call(N1,f,f1,[]),
  385: 
  386:     %% Check that data is collected from remote node when stopped
  387:     ?line ok = cover:stop(N1),
  388:     ?line N1Beam = rpc:call(N1,code,which,[f]),
  389:     ?line true = is_unloaded(N1Beam),
  390:     ?line check_f_calls(1,0),
  391: 
  392:     %% Call f:f1() again on another node and check that number of calls is
  393:     %% accumulated.
  394:     ?line f:f1(),
  395:     ?line check_f_calls(2,0),
  396:     
  397:     %% Check that reset works on all nodes
  398:     ?line f:f1(),
  399:     ?line rpc:call(N2,f,f1,[]),
  400:     ?line ok = cover:reset(f),
  401:     ?line check_f_calls(0,0),
  402:     
  403:     %% Check that data is collected from all nodes
  404:     ?line rpc:call(N2,f,f1,[]),
  405:     ?line f:f2(),
  406:     ?line check_f_calls(1,1),
  407: 
  408:     %% Check that same data is not fetched again (i.e. that analyse does
  409:     %% reset on the remote node(s))
  410:     ?line check_f_calls(1,1),
  411: 
  412:     %% Another checn that data is not fetched twice, i.e. when flushed
  413:     %% then analyse should not add the same data again.
  414:     ?line rpc:call(N4,f,f2,[]),
  415:     ?line ok = cover:flush(N4),
  416:     ?line check_f_calls(1,2),
  417: 
  418:     %% Check that flush collects data so calls are not lost if node is killed
  419:     ?line rpc:call(N4,f,f2,[]),
  420:     ?line ok = cover:flush(N4),
  421:     ?line rpc:call(N4,erlang,halt,[]),
  422:     ?line check_f_calls(1,3),
  423: 
  424:     %% Check that stop() unloads on all nodes
  425:     ?line ok = cover:stop(),
  426:     ?line timer:sleep(100), %% Give nodes time to unload on slow machines.
  427:     ?line LocalBeam = code:which(f),
  428:     ?line N2Beam = rpc:call(N2,code,which,[f]),
  429:     ?line true = is_unloaded(LocalBeam),
  430:     ?line true = is_unloaded(N2Beam),
  431: 
  432:     %% Check that cover_server on remote node does not die if main node dies
  433:     ?line {ok,[N1]} = cover:start(N1),
  434:     ?line true = is_pid(N1Server = rpc:call(N1,erlang,whereis,[cover_server])),
  435:     ?line exit(whereis(cover_server),kill),
  436:     ?line timer:sleep(100),
  437:     ?line N1Server = rpc:call(N1,erlang,whereis,[cover_server]),
  438: 
  439:     %% Cleanup
  440:     ?line Files = lsfiles(),
  441:     ?line remove(files(Files, ".beam")),
  442:     ?line ?t:stop_node(N1),
  443:     ?line ?t:stop_node(N2).
  444: 
  445: %% Test that a lost node is reconnected
  446: reconnect(Config) ->
  447:     DataDir = ?config(data_dir, Config),
  448:     ok = file:set_cwd(DataDir),
  449: 
  450:     {ok,a} = compile:file(a),
  451:     {ok,b} = compile:file(b),
  452:     {ok,f} = compile:file(f),
  453: 
  454:     {ok,N1} = ?t:start_node(cover_SUITE_reconnect,peer,
  455: 			    [{args," -pa " ++ DataDir},{start_cover,false}]),
  456:     {ok,a} = cover:compile(a),
  457:     {ok,f} = cover:compile(f),
  458:     {ok,[N1]} = cover:start(nodes()),
  459: 
  460:     %% Some calls to check later
  461:     rpc:call(N1,f,f1,[]),
  462:     cover:flush(N1),
  463:     rpc:call(N1,f,f1,[]),
  464: 
  465:     %% This will cause a call to f:f2() when nodes()==[] on N1
  466:     rpc:cast(N1,f,call_f2_when_isolated,[]),
  467: 
  468:     %% Disconnect and check that node is removed from main cover node
  469:     net_kernel:disconnect(N1),
  470:     timer:sleep(500), % allow some to detect disconnect and for f:f2() call
  471:     [] = cover:which_nodes(),
  472: 
  473:     %% Do some add one module (b) and remove one module (a)
  474:     code:purge(a),
  475:     {module,a} = code:load_file(a),
  476:     {ok,b} = cover:compile(b),
  477:     cover_compiled = code:which(b),
  478: 
  479:     [] = cover:which_nodes(),
  480:     check_f_calls(1,0), % only the first call - before the flush
  481: 
  482:     %% Reconnect the node and check that b and f are cover compiled but not a
  483:     net_kernel:connect_node(N1),
  484:     timer:sleep(100),
  485:     [N1] = cover:which_nodes(), % we are reconnected
  486:     cover_compiled = rpc:call(N1,code,which,[b]),
  487:     cover_compiled = rpc:call(N1,code,which,[f]),
  488:     ABeam = rpc:call(N1,code,which,[a]),
  489:     false = (cover_compiled==ABeam),
  490: 
  491:     %% Ensure that we have:
  492:     %% * one f1 call from before the flush,
  493:     %% * one f1 call from after the flush but before disconnect
  494:     %% * one f2 call when disconnected
  495:     check_f_calls(2,1),
  496: 
  497:     cover:stop(),
  498:     ?t:stop_node(N1),
  499:     ok.
  500: 
  501: %% Test that a lost node is reconnected - also if it has been dead
  502: die_and_reconnect(Config) ->
  503:     DataDir = ?config(data_dir, Config),
  504:     ok = file:set_cwd(DataDir),
  505: 
  506:     {ok,f} = compile:file(f),
  507: 
  508:     NodeName = cover_SUITE_die_and_reconnect,
  509:     {ok,N1} = ?t:start_node(NodeName,peer,
  510: 			    [{args," -pa " ++ DataDir},{start_cover,false}]),
  511:     %% {ok,a} = cover:compile(a),
  512:     {ok,f} = cover:compile(f),
  513:     {ok,[N1]} = cover:start(nodes()),
  514: 
  515:     %% Some calls to check later
  516:     rpc:call(N1,f,f1,[]),
  517:     cover:flush(N1),
  518:     rpc:call(N1,f,f1,[]),
  519: 
  520:     %% Kill the node
  521:     rpc:call(N1,erlang,halt,[]),
  522:     [] = cover:which_nodes(),
  523: 
  524:     check_f_calls(1,0), % only the first call - before the flush
  525: 
  526:     %% Restart the node and check that cover reconnects
  527:     {ok,N1} = ?t:start_node(NodeName,peer,
  528: 			    [{args," -pa " ++ DataDir},{start_cover,false}]),
  529:     timer:sleep(100),
  530:     [N1] = cover:which_nodes(), % we are reconnected
  531:     cover_compiled = rpc:call(N1,code,which,[f]),
  532: 
  533:     %% One more call...
  534:     rpc:call(N1,f,f1,[]),
  535: 
  536:     %% Ensure that no more calls are counted
  537:     check_f_calls(2,0),
  538: 
  539:     cover:stop(),
  540:     ?t:stop_node(N1),
  541:     ok.
  542: 
  543: %% Test that a stopped node is not marked as lost, i.e. that it is not
  544: %% reconnected if it is restarted (OTP-10638)
  545: dont_reconnect_after_stop(Config) ->
  546:     DataDir = ?config(data_dir, Config),
  547:     ok = file:set_cwd(DataDir),
  548: 
  549:     {ok,f} = compile:file(f),
  550: 
  551:     NodeName = cover_SUITE_dont_reconnect_after_stop,
  552:     {ok,N1} = ?t:start_node(NodeName,peer,
  553: 			    [{args," -pa " ++ DataDir},{start_cover,false}]),
  554:     {ok,f} = cover:compile(f),
  555:     {ok,[N1]} = cover:start(nodes()),
  556: 
  557:     %% A call to check later
  558:     rpc:call(N1,f,f1,[]),
  559: 
  560:     %% Stop cover on the node, then terminate the node
  561:     cover:stop(N1),
  562:     rpc:call(N1,erlang,halt,[]),
  563:     [] = cover:which_nodes(),
  564: 
  565:     check_f_calls(1,0),
  566: 
  567:     %% Restart the node and check that cover does not reconnect
  568:     {ok,N1} = ?t:start_node(NodeName,peer,
  569: 			    [{args," -pa " ++ DataDir},{start_cover,false}]),
  570:     timer:sleep(300),
  571:     [] = cover:which_nodes(),
  572:     Beam = rpc:call(N1,code,which,[f]),
  573:     false = (Beam==cover_compiled),
  574: 
  575:     %% One more call...
  576:     rpc:call(N1,f,f1,[]),
  577:     cover:flush(N1),
  578: 
  579:     %% Ensure that the last call is not counted
  580:     check_f_calls(1,0),
  581: 
  582:     cover:stop(),
  583:     ?t:stop_node(N1),
  584:     ok.
  585: 
  586: %% Test that a node which is stopped while it is marked as lost is not
  587: %% reconnected if it is restarted (OTP-10638)
  588: stop_node_after_disconnect(Config) ->
  589:     DataDir = ?config(data_dir, Config),
  590:     ok = file:set_cwd(DataDir),
  591: 
  592:     {ok,f} = compile:file(f),
  593: 
  594:     NodeName = cover_SUITE_stop_node_after_disconnect,
  595:     {ok,N1} = ?t:start_node(NodeName,peer,
  596: 			    [{args," -pa " ++ DataDir},{start_cover,false}]),
  597:     {ok,f} = cover:compile(f),
  598:     {ok,[N1]} = cover:start(nodes()),
  599: 
  600:     %% A call to check later
  601:     rpc:call(N1,f,f1,[]),
  602: 
  603:     %% Flush the node, then terminate the node to make it marked as lost
  604:     cover:flush(N1),
  605:     rpc:call(N1,erlang,halt,[]),
  606: 
  607:     check_f_calls(1,0),
  608: 
  609:     %% Stop cover on node
  610:     cover:stop(N1),
  611: 
  612:     %% Restart the node and check that cover does not reconnect
  613:     {ok,N1} = ?t:start_node(NodeName,peer,
  614: 			    [{args," -pa " ++ DataDir},{start_cover,false}]),
  615:     timer:sleep(300),
  616:     [] = cover:which_nodes(),
  617:     Beam = rpc:call(N1,code,which,[f]),
  618:     false = (Beam==cover_compiled),
  619: 
  620:     %% One more call...
  621:     rpc:call(N1,f,f1,[]),
  622:     cover:flush(N1),
  623: 
  624:     %% Ensure that the last call is not counted
  625:     check_f_calls(1,0),
  626: 
  627:     cover:stop(),
  628:     ?t:stop_node(N1),
  629:     ok.
  630: 
  631: export_import(suite) -> [];
  632: export_import(Config) when is_list(Config) ->
  633:     ?line DataDir = ?config(data_dir, Config),
  634:     ?line ok = file:set_cwd(DataDir),
  635:     ?line PortCount = length(erlang:ports()),
  636: 
  637:     %% Export one module
  638:     ?line {ok,f} = cover:compile(f),
  639:     ?line f:f1(),
  640:     %% check that no info is written about where data comes from when no
  641:     %% files are imported
  642:     ?line ?t:capture_start(),
  643:     ?line check_f_calls(1,0),
  644:     ?line [] = ?t:capture_get(),
  645:     ?line ?t:capture_stop(),
  646:     ?line ok = cover:export("f_exported",f),
  647:     ?line check_f_calls(1,0),
  648:     ?line ok = cover:stop(),
  649:     
  650:     %% Check that same data exists after import and that info is written about
  651:     %% data comming from imported file
  652:     ?line ok = cover:import("f_exported"),
  653:     ?line ?t:capture_start(),
  654:     ?line check_f_calls(1,0),
  655:     ?line [Text1] = ?t:capture_get(),
  656:     ?line "Analysis includes data from imported files"++_ = lists:flatten(Text1),
  657:     ?line ?t:capture_stop(),
  658: 
  659:     %% Export all modules
  660:     ?line {ok,a} = cover:compile(a),
  661:     ?line ?t:capture_start(),
  662:     ?line ok = cover:export("all_exported"),
  663:     ?line [] = ?t:capture_get(),
  664: %    ?line "Export includes data from imported files"++_ = lists:flatten(Text2),
  665:     ?line ?t:capture_stop(),
  666:     ?line ok = cover:stop(),
  667:     ?line ok = cover:import("all_exported"),
  668:     ?line check_f_calls(1,0),
  669: 
  670:     %% Check that data is reset when module is compiled again, and that
  671:     %% warning is written when data is deleted for imported module.
  672:     ?line ?t:capture_start(),
  673:     ?line {ok,f} = cover:compile(f),
  674:     ?line timer:sleep(10), % capture needs some time
  675:     ?line [Text3] = ?t:capture_get(),
  676:     ?line "WARNING: Deleting data for module f imported from" ++ _ = 
  677: 	lists:flatten(Text3),
  678:     ?line ?t:capture_stop(),
  679:     ?line check_f_calls(0,0),
  680:     
  681:     %% Check that data is summed up when first compiled and then imported
  682:     %% The module which has been compiled (f) is loaded from the file 
  683:     %% all_exported again (since it has been reset during cover compiling), 
  684:     %% but the other module (a) is not loaded since it is already loaded    
  685:     ?line f:f1(),
  686:     ?line f:f2(),
  687:     ?line ok = cover:import("f_exported"),
  688:     ?line ?t:capture_start(),
  689:     ?line ok = cover:import("all_exported"),
  690:     ?line [Text4] = ?t:capture_get(), % a is not loaded again
  691:     ?line "WARNING: Module a already imported from " ++ _ = lists:flatten(Text4),
  692:     ?line ?t:capture_stop(),
  693:     ?line check_f_calls(3,1),
  694: 
  695:     %% Check that warning is written when same file is imported twice,
  696:     %% and that data is not imported again
  697:     ?line ?t:capture_start(),
  698:     ?line ok = cover:import("all_exported"),
  699:     ?line [Text5,Text6] = ?t:capture_get(),
  700:     ?line "WARNING: Module f already imported from " ++ _ = lists:flatten(Text5),
  701:     ?line "WARNING: Module a already imported from " ++ _ = lists:flatten(Text6),
  702:     ?line ?t:capture_stop(),
  703:     ?line check_f_calls(3,1),
  704: 
  705:     %% Check that reset removes all data and that the file which has been
  706:     %% reset can be imported again with no warning
  707:     ?line cover:reset(f),
  708:     ?line check_f_calls(0,0),
  709:     ?line ?t:capture_start(),
  710:     ?line ok = cover:import("all_exported"),
  711:     ?line [Text7] = ?t:capture_get(), % warning only on mod a
  712:     ?line "WARNING: Module a already imported from " ++ _ = lists:flatten(Text7),
  713:     ?line ?t:capture_stop(),
  714:     ?line check_f_calls(1,0),
  715: 
  716:     %% same as above - only reset all
  717:     ?line cover:reset(),
  718:     ?line check_f_calls(0,0),
  719:     ?line ?t:capture_start(),
  720:     ?line ok = cover:import("all_exported"),
  721:     ?line [] = ?t:capture_get(), % no warnings
  722:     ?line ?t:capture_stop(),
  723:     ?line check_f_calls(1,0),
  724: 
  725:     %% Check no raw files are left open
  726:     ?line PortCount = length(erlang:ports()),
  727: 
  728:     %% Cleanup
  729:     ?line ok = cover:stop(),
  730:     ?line Files = lsfiles(),
  731:     ?line remove(["f_exported","all_exported"|files(Files, ".beam")]).
  732: 
  733: 
  734: otp_5031(suite) -> [];
  735: otp_5031(Config) when is_list(Config) ->
  736: 
  737:     Dog = ?t:timetrap(?t:seconds(10)),
  738: 
  739:     ?line {ok,N1} = ?t:start_node(cover_SUITE_distribution1,slave,[]),
  740:     ?line {ok,[N1]} = cover:start(N1),
  741:     ?line {error,not_main_node} = rpc:call(N1,cover,modules,[]),
  742:     ?line cover:stop(),
  743:     
  744:     ?t:timetrap_cancel(Dog),
  745:     ok.
  746: 
  747: eif(doc) ->
  748:     ["Test the \'Exclude Included Functions\' functionality"];
  749: eif(suite) ->
  750:     [];
  751: eif(Config) when is_list(Config) ->
  752:     ?line ok = file:set_cwd(filename:join(?config(data_dir, Config),
  753: 					  "included_functions")),
  754:     ?line {ok, cover_inc} = compile:file(cover_inc,[debug_info]),
  755:     ?line {ok, cover_inc} = cover:compile_beam(cover_inc),
  756: 
  757:     %% This function will cause an included function to be executed.
  758:     %% The analysis should only show the lines that actually exist
  759:     %% in cover_inc.beam - not the ones from the included file.
  760:     ?line cover_inc:func(),
  761:     ?line {ok, [_, _]} = cover:analyse(cover_inc, line),
  762:     ?line cover:stop(),
  763:     ok.
  764:     
  765: otp_5305(suite) -> [];
  766: otp_5305(Config) when is_list(Config) ->
  767:     ?line ok = file:set_cwd(?config(priv_dir, Config)),
  768: 
  769:     File = "t.erl",
  770:     Test = <<"-module(t).
  771:               -export([t/0]).
  772:               -include_lib(\"stdlib/include/ms_transform.hrl\").
  773:               t() ->
  774:                   ets:fun2ms(fun(X) -> X end).
  775:              ">>,
  776:     ?line ok = file:write_file(File, Test),
  777:     ?line {ok, t} = cover:compile(File),
  778:     ?line cover:stop(),
  779:     ?line ok = file:delete(File),
  780: 
  781:     ok.
  782: 
  783: otp_5418(suite) -> [];
  784: otp_5418(Config) when is_list(Config) ->
  785:     ?line ok = file:set_cwd(?config(priv_dir, Config)),
  786: 
  787:     File = "t.erl",
  788:     Test = <<"-module(t).
  789:              ">>,
  790:     ?line ok = file:write_file(File, Test),
  791:     ?line {ok, t} = cover:compile(File),
  792:     ?line {ok,{t,{0,0}}} = cover:analyse(t, module),
  793:     ?line cover:stop(),
  794:     ?line ok = file:delete(File),
  795: 
  796:     ok.
  797: 
  798: otp_6115(Config) when is_list(Config) ->
  799:     ?line {ok, CWD} = file:get_cwd(),
  800:     ?line Dir = filename:join(?config(data_dir, Config), otp_6115),
  801:     ?line ok = file:set_cwd(Dir),
  802:     ?line {ok, f1} = compile:file(f1, [debug_info]),
  803:     ?line {ok, f2} = compile:file(f2, [debug_info]),
  804: 
  805:     %% Cover compile f1, but not f2
  806:     ?line {ok, f1} = cover:compile(f1),
  807: 
  808:     %% If f1 is cover compiled, a process P is started with a
  809:     %% reference to the fun created in start_fail/0, and cover:stop() is
  810:     %% called, then P should be killed.
  811:     %% This is because (the fun held by P) references the cover
  812:     %% compiled code which should be *unloaded* when cover:stop() is
  813:     %% called -- running cover compiled code when there is no cover
  814:     %% server and thus no ets tables to bump counters in, makes no
  815:     %% sense.
  816:     Pid1 = f1:start_a(),
  817:     Pid2 = f1:start_b(),
  818: 
  819:     %% Now stop cover
  820:     ?line cover:stop(),
  821:     
  822:     %% Ensure that f1 is loaded (and not cover compiled), and that
  823:     %% both Pid1 and Pid2 are dead.
  824:     case code:which(f1) of
  825: 	Beam when is_list(Beam) ->
  826: 	    ok;
  827: 	Other ->
  828: 	    ?line ?t:fail({"f1 is not reloaded", Other})
  829:     end,
  830:     case process_info(Pid1) of
  831: 	undefined ->
  832: 	    ok;
  833: 	_PI1 ->
  834: 	    RefToOldP1 = erlang:check_process_code(Pid1, f1),
  835: 	    ?t:fail({"Pid1 still alive", RefToOldP1})
  836:     end,
  837:     case process_info(Pid2) of
  838: 	undefined ->
  839: 	    ok;
  840: 	_PI2 ->
  841: 	    RefToOldP2 = erlang:check_process_code(Pid1, f2),
  842: 	    ?t:fail({"Pid2 still alive", RefToOldP2})
  843:     end,
  844: 
  845:     ?line file:set_cwd(CWD),
  846:     ok.
  847: 
  848: otp_7095(doc) ->
  849:     ["andalso/orelse"];
  850: otp_7095(suite) -> [];
  851: otp_7095(Config) when is_list(Config) ->
  852:     ?line ok = file:set_cwd(?config(priv_dir, Config)),
  853: 
  854:     File = "t.erl",
  855:     Test = <<"-module(t).
  856:               -export([t/0]).
  857:               t() ->
  858:                   t1(),
  859:                   t2(),
  860:                   t3(),
  861:                   t4(),
  862:                   t5(),
  863:                   put(t6, 0),
  864:                   0  = t6(),
  865:                   1 = erase(t6),
  866:                   t7(),
  867:                   put(t8, 0),
  868:                   {'EXIT',{{badarg,0},_}} = (catch t8()),
  869:                   1 = erase(t8),
  870:                   t9(),
  871:                   ok.
  872: 
  873:               t1() ->
  874:                   false        % 20
  875:                     andalso
  876:                   true.        % 22
  877: 
  878:               t2() ->
  879:                   true         % 25
  880:                     andalso
  881:                   true.        % 27
  882: 
  883:               t3() ->
  884:                   false        % 30
  885:                     orelse
  886:                   true.        % 32
  887: 
  888:               t4() ->
  889:                   true         % 35
  890:                     orelse
  891:                   true.        % 37
  892: 
  893:               t5() ->
  894:                   true         % 40
  895:                     andalso
  896:                   true         % 42
  897:                     andalso 
  898:                   false.       % 44
  899: 
  900:               t6() ->
  901:                   true andalso % 47
  902:                   add_one(t6). % 48
  903: 
  904:               t7() ->
  905:                   true         % 51
  906:                     andalso
  907:                   false        % 53
  908:                     andalso 
  909:                   not_ok.      % 55
  910: 
  911:               t8() ->
  912:                   true         % 58
  913:                     andalso 
  914:                   true         % 60
  915:                     andalso
  916:                   add_one(t8)  % 62
  917:                     andalso
  918:                   false.       % 64
  919: 
  920:               t9() ->
  921:                   if           % 67
  922:                       true -> 
  923:                           true % 69
  924:                             andalso 
  925:                           false % 71
  926:                   end
  927:                     orelse
  928:                   case ok of   % 74
  929:                       true -> 
  930:                           a;   % 76
  931:                       _ -> 
  932:                           true % 78
  933:                   end.
  934: 
  935:               add_one(T) ->
  936:                   put(T, get(T) + 1). % 82
  937:              ">>,
  938:     ?line ok = file:write_file(File, Test),
  939:     ?line {ok, t} = cover:compile(File),
  940:     ?line ok = t:t(),
  941:     ?line {ok,[{{t,4},1},{{t,5},1},{{t,6},1},{{t,7},1},{{t,8},1},{{t,9},1},
  942:                {{t,10},1},{{t,11},1},{{t,12},1},{{t,13},1},{{t,14},1},
  943:                {{t,15},1},{{t,16},1},{{t,17},1},
  944:                {{t,20},1},{{t,22},0},
  945:                {{t,25},1},{{t,27},1},
  946:                {{t,30},1},{{t,32},1},
  947:                {{t,35},1},{{t,37},0},
  948:                {{t,40},1},{{t,42},1},{{t,44},1},
  949:                {{t,47},1},{{t,48},1},
  950:                {{t,51},1},{{t,53},1},{{t,55},0},
  951:                {{t,58},1},{{t,60},1},{{t,62},1},{{t,64},0},
  952:                {{t,67},1},{{t,69},1},{{t,71},1},{{t,74},1},
  953:                     {{t,76},0},{{t,78},1},
  954:                {{t,82},2}]} = cover:analyse(t, calls, line),
  955:     ?line cover:stop(),
  956:     ?line ok = file:delete(File),
  957: 
  958:     ok.
  959: 
  960: otp_8270(doc) ->
  961:     ["OTP-8270. Bug."];
  962: otp_8270(suite) -> [];
  963: otp_8270(Config) when is_list(Config) ->
  964:     ?line DataDir = ?config(data_dir, Config),
  965:     ?line ok = file:set_cwd(DataDir),
  966: 
  967:     ?line PrivDir = ?config(priv_dir, Config),
  968: 
  969:     As = [{args," -pa " ++ PrivDir}],
  970:     ?line {ok,N1} = ?t:start_node(cover_n1,slave,As),
  971:     ?line {ok,N2} = ?t:start_node(cover_n2,slave,As),
  972:     ?line {ok,N3} = ?t:start_node(cover_n3,slave,As),
  973:     
  974:     timer:sleep(500),
  975:     cover:start(nodes()),
  976: 
  977:     Test = <<
  978:      "-module(m).\n"
  979:      "-compile(export_all).\n"
  980:      "t() -> t(0).\n"
  981:      "l() ->\n"
  982:      "   catch ets:tab2list(cover_internal_data_table).\n"
  983:      "t(Sz) ->\n"
  984:      "   case ets:info(cover_internal_data_table, size) of\n"
  985:      "       Sz ->\n"
  986:      "           m:t(Sz); % Not a local call! Newly loaded code is entered.\n"
  987:      "       NSz ->\n"
  988:      "           % error_logger:info_msg(\"~p: ~p ~p change~n L1 ~p~n\", \n"
  989:      "           % [node(), Sz, NSz, l()]),\n"
  990:      "           m:t(NSz)\n"
  991:      "   end.\n">>,
  992:     ?line _File = c_mod(m, Test, Config),
  993:     Fun = fun m:t/0,
  994:     ?line Pid1 = spawn(Fun),
  995:     ?line Pid2 = spawn(N1, Fun),
  996:     ?line Pid3 = spawn(N2, Fun),
  997:     ?line Pid4 = spawn(N3, Fun),
  998: 
  999:     ?line {ok, m} = cover:compile_beam(m),
 1000: 
 1001:     timer:sleep(1000),
 1002: 
 1003:     ?line Info = erlang:process_info(Pid1),
 1004:     ?line N1_info = rpc:call(N1, erlang, process_info, [Pid2]),
 1005:     ?line N2_info = rpc:call(N2, erlang, process_info, [Pid3]),
 1006:     ?line N3_info = rpc:call(N3, erlang, process_info, [Pid4]),
 1007: 
 1008:     ?line true = is_list(Info),
 1009:     ?line {N1,true} = {N1,is_list(N1_info)},
 1010:     ?line {N2,true} = {N2,is_list(N2_info)},
 1011:     ?line {N3,true} = {N3,is_list(N3_info)},
 1012: 
 1013:     ?line ?t:stop_node(N1),
 1014:     ?line ?t:stop_node(N2),
 1015:     ?line ?t:stop_node(N3),
 1016:     ok.
 1017: 
 1018: otp_8273(doc) ->
 1019:     ["OTP-8273. Bug."];
 1020: otp_8273(suite) -> [];
 1021: otp_8273(Config) when is_list(Config) ->
 1022:     Test = <<"-module(t).
 1023:               -export([t/0]).
 1024:               t() ->
 1025:                   foo = true andalso foo,
 1026:                   bar = false orelse bar,
 1027:                   ok.
 1028:              ">>,
 1029:     ?line File = cc_mod(t, Test, Config),
 1030:     ?line ok = t:t(),
 1031:     ?line cover:stop(),
 1032:     ?line ok = file:delete(File),
 1033: 
 1034:     ok.
 1035: 
 1036: otp_8340(doc) ->
 1037:     ["OTP-8340. Bug."];
 1038: otp_8340(suite) -> [];
 1039: otp_8340(Config) when is_list(Config) ->
 1040:     ?line [{{t,1},1},{{t,2},1},{{t,4},1}] = 
 1041:         analyse_expr(<<"<< \n"
 1042:                        " <<3:2, \n"
 1043:                        "   SeqId:62>> \n"
 1044:                        "      || SeqId <- [64] >>">>, Config),
 1045: 
 1046:     ok.
 1047: 
 1048: otp_8188(doc) ->
 1049:     ["Clauses on the same line."];
 1050: otp_8188(suite) -> [];
 1051: otp_8188(Config) when is_list(Config) ->
 1052:     %% This example covers the bug report:
 1053:     Test = <<"-module(t).
 1054:               -export([test/1]).
 1055: 
 1056:               -define(FOOBAR(X),
 1057:                       case X of
 1058:                           ok -> true;
 1059:                           _ -> false
 1060:                       end).
 1061: 
 1062:               test(X)->
 1063:                   _Res = 
 1064:                   ?FOOBAR(X).
 1065:              ">>,
 1066:     ?line File = cc_mod(t, Test, Config),
 1067:     ?line false = t:test(nok),
 1068:     ?line {ok,[{{t,11},1},{{t,12},1}]} = cover:analyse(t, calls, line),
 1069:     ?line cover:stop(),
 1070:     ?line ok = file:delete(File),
 1071: 
 1072:     %% Bit string comprehensions are now traversed;
 1073:     %% the handling of list comprehensions has been improved:
 1074:     comprehension_8188(Config),
 1075: 
 1076:     %% Variants of the reported bug:
 1077:     bug_8188(Config),
 1078:     ok.
 1079: 
 1080: bug_8188(Cf) ->
 1081:     ?line [{{t,1},1},{{t,2},1},{{t,3},1}] =
 1082:         analyse_expr(<<"A = 3,\n" % 1
 1083:                        "    case A of\n" % 1
 1084:                        "        2 -> two; 3 -> three end, A + 2">>,  % 1
 1085:                      Cf),
 1086: 
 1087:     ?line [{{t,1},1},
 1088:            {{t,2},0},
 1089:            {{t,3},1},
 1090:            {{t,4},1},
 1091:            {{t,5},1},
 1092:            {{t,6},0},
 1093:            {{t,7},1},
 1094:            {{t,9},2}] =
 1095:         analyse_expr(<<"case two() of\n" % 1
 1096:                        "     1 -> 2;\n" % 0
 1097:                        "    _  -> begin 3 end\n" % 1
 1098:                        "              +\n" % 1
 1099:                        "          begin 4 end end, case two() of\n" % 1
 1100:                        "                               1 -> a;\n" % 0
 1101:                        "                               2 -> b; 3 -> c\n" % 1
 1102:                        "                           end.\n"
 1103:                        "two() -> 2">>, Cf), % 2
 1104: 
 1105:     ?line [{{t,1},1}, {{t,2},1}, {{t,3},1},
 1106:            {{t,4},1}, {{t,5},1}, {{t,6},0}] =
 1107:         analyse_expr(<<"    self() ! 1,\n"
 1108:                        "    receive \n"
 1109:                        "        X=1 -> a;\n"
 1110:                        "        X=2 -> b end, case X of \n"
 1111:                        "                          1 -> a;\n"
 1112:                        "                          2 -> b\n"
 1113:                        "                      end">>, Cf),
 1114: 
 1115:     T0 = <<"t1(X) ->\n "
 1116:            "case X of\n"
 1117:            "  1 -> A=a,B=A,B; % bump Li\n"
 1118:            "  2 -> b; 3 -> case X of % 2 -> b shall bump Li\n"
 1119:            "                  3 -> a; % bump Li\n"
 1120:            "                  2 -> b end; 4 -> d end, case X of  % Li\n"
 1121:            "                                            1 -> a;\n"
 1122:            "                                            2 -> b; 3 -> c;\n"
 1123:            "                                            4 -> d\n"
 1124:            "                                          end">>,
 1125: 
 1126:     T1 = [<<"a = t1(1). ">>,T0],
 1127:     ?line [{{t,1},1}, {{t,2},1}, {{t,3},1}, {{t,4},0},
 1128:            {{t,5},0}, {{t,6},1}, {{t,7},1}, {{t,8},0}, {{t,9},0}] = 
 1129:         analyse_expr(T1, Cf),
 1130: 
 1131:     T2 = [<<"b = t1(2). ">>,T0],
 1132:     ?line [{{t,1},1}, {{t,2},1}, {{t,3},0}, {{t,4},1},
 1133:            {{t,5},0}, {{t,6},1}, {{t,7},0}, {{t,8},1}, {{t,9},0}] = 
 1134:         analyse_expr(T2, Cf),
 1135: 
 1136:     T3 = [<<"c = t1(3). ">>,T0],
 1137:     ?line [{{t,1},1}, {{t,2},1}, {{t,3},0}, {{t,4},1},
 1138:            {{t,5},1}, {{t,6},1}, {{t,7},0}, {{t,8},1}, {{t,9},0}] = 
 1139:         analyse_expr(T3, Cf),
 1140: 
 1141:     T4 = [<<"d = t1(4). ">>,T0],
 1142:     ?line [{{t,1},1}, {{t,2},1}, {{t,3},0}, {{t,4},0},
 1143:            {{t,5},0}, {{t,6},1}, {{t,7},0}, {{t,8},0}, {{t,9},1}] = 
 1144:         analyse_expr(T4, Cf),
 1145: 
 1146:     ?line [{{t,1},1},{{t,2},1},{{t,3},1},{{t,4},1},{{t,5},1}] =
 1147:         analyse_expr(
 1148:           <<"2 = x3(1). "
 1149:             "x3(X) ->\n"
 1150:             "    case X of \n"
 1151:             "        1 -> case X of\n"
 1152:             "                 1 -> a, Y = 2;\n"
 1153:             "                 2 -> b, Y = 3 end, Y; 2 -> Y = 4 end, Y">>, Cf),
 1154:     
 1155:     ?line [{{t,1},1},{{t,2},1},{{t,3},1},{{t,4},1}] = 
 1156:         analyse_expr(
 1157:           <<"1 = x4(1). "
 1158:             "x4(X) ->\n"
 1159:             "  case X of\n"
 1160:             "    1 -> case X of\n"
 1161:             "           1 -> Y = 1 end, case X of 1 -> Y = 1 end, Y end">>,
 1162:           Cf),
 1163: 
 1164:     T10 = <<"t1(X) ->\n"
 1165:             "if\n"
 1166:             "  X =:= 1 -> a;\n"
 1167:             "  X =:= 2 -> b; X =:= 3 -> c end, case X of \n"
 1168:             "                        1 -> a;\n"
 1169:             "                        2 -> b; 3 -> c end, case X of\n"
 1170:             "                                              1 -> a;\n"
 1171:             "                                              2 -> b; 3 -> c\n"
 1172:             "                                            end">>,
 1173:     T11 = [<<"a = t1(1). ">>,T10],
 1174:     ?line [{{t,1},1}, {{t,2},1}, {{t,3},1}, {{t,4},1},
 1175:            {{t,5},1}, {{t,6},1}, {{t,7},1}, {{t,8},0}] = 
 1176:         analyse_expr(T11, Cf),
 1177: 
 1178:     T12 = [<<"b = t1(2). ">>,T10],
 1179:     ?line [{{t,1},1}, {{t,2},1}, {{t,3},0}, {{t,4},1},
 1180:            {{t,5},0}, {{t,6},1}, {{t,7},0}, {{t,8},1}] = 
 1181:         analyse_expr(T12, Cf),
 1182: 
 1183:     T13 = [<<"c = t1(3). ">>,T10],
 1184:     ?line [{{t,1},1}, {{t,2},1}, {{t,3},0}, {{t,4},1},
 1185:            {{t,5},0}, {{t,6},1}, {{t,7},0}, {{t,8},1}] = 
 1186:         analyse_expr(T13, Cf),
 1187: 
 1188:     T20 = <<"t1(X) ->\n"
 1189:             "case X of\n"
 1190:             "        1 -> a;\n"
 1191:             "        2 -> b; 3 -> case X of\n"
 1192:             "                         1 -> a;\n"
 1193:             "                         2 -> b; 3 -> c end end, case X of\n"
 1194:             "                                             1 -> a;\n"
 1195:             "                                             2 -> b; 3 -> c\n"
 1196:             "                                         end">>,
 1197: 
 1198:     T21 = [<<"a = t1(1). ">>,T20],
 1199:     ?line [{{t,1},1}, {{t,2},1}, {{t,3},1}, {{t,4},0},
 1200:            {{t,5},0}, {{t,6},1}, {{t,7},1}, {{t,8},0}] = 
 1201:         analyse_expr(T21, Cf),
 1202: 
 1203:     T22 = [<<"b = t1(2). ">>,T20],
 1204:     ?line [{{t,1},1}, {{t,2},1}, {{t,3},0}, {{t,4},1},
 1205:            {{t,5},0}, {{t,6},1}, {{t,7},0}, {{t,8},1}] = 
 1206:         analyse_expr(T22, Cf),
 1207: 
 1208:     T23 = [<<"c = t1(3). ">>,T20],
 1209:     ?line [{{t,1},1}, {{t,2},1}, {{t,3},0}, {{t,4},1},
 1210:            {{t,5},0}, {{t,6},1}, {{t,7},0}, {{t,8},1}] = 
 1211:         analyse_expr(T23, Cf),
 1212: 
 1213:     T30 = <<
 1214:         "t1(X) ->\n"
 1215:         "case X of\n"
 1216:         " 1 -> a;\n"
 1217:         " 2 -> b; 3 -> case X of 1 -> a; 2 -> b; 3 -> c end end, case X of\n"
 1218:         "                                                 1 -> a;\n"
 1219:         "                                                 2 -> b; 3 -> c\n"
 1220:         "                                                end\n">>,
 1221: 
 1222:     T31 = [<<"a = t1(1). ">>,T30],
 1223:     ?line [{{t,1},1}, {{t,2},1}, {{t,3},1},
 1224:            {{t,4},1}, {{t,5},1}, {{t,6},0}] =
 1225:         analyse_expr(T31, Cf),
 1226: 
 1227:     T32 = [<<"b = t1(2). ">>,T30],
 1228:     ?line [{{t,1},1}, {{t,2},1}, {{t,3},0},
 1229:            {{t,4},1}, {{t,5},0}, {{t,6},1}] =
 1230:         analyse_expr(T32, Cf),
 1231: 
 1232:     T33 = [<<"c = t1(3). ">>,T30],
 1233:     ?line [{{t,1},1}, {{t,2},1}, {{t,3},0},
 1234:            {{t,4},1}, {{t,5},0}, {{t,6},1}] =
 1235:         analyse_expr(T33, Cf),
 1236: 
 1237:     %% 'try' now traverses the body as a body...
 1238:     ?line [{{t,1},1},{{t,2},1},{{t,3},1},{{t,4},0},{{t,6},1}] = 
 1239:         analyse_expr(<<"try \n"
 1240:                        "    B = 2, \n"
 1241:                        "    C = erlang:error(foo), \n"
 1242:                        "    {B,C} \n"
 1243:                        "catch _:_ -> \n"
 1244:                        "    foo \n"
 1245:                        "end">>, Cf),
 1246: 
 1247:     %% receive after:
 1248:     ?line [{{t,1},1},{{t,2},0},{{t,3},1}] = 
 1249:         analyse_expr(<<"receive \n"
 1250:                        "    X=1 -> a; \n"
 1251:                        "    X=2 -> b after begin 10 end -> X=3 end">>, Cf),
 1252:     ?line [{{t,1},1},{{t,2},0},{{t,3},1}] =
 1253:         analyse_expr(<<"receive \n"
 1254:                        "    X=1 -> a; \n"
 1255:                        "    X=2 -> b after 10 -> begin X=3 end end">>, Cf),
 1256:     ok.
 1257: 
 1258: comprehension_8188(Cf) ->
 1259:     ?line  [{{t,1},1}] = 
 1260:         analyse_expr(<<"[begin X end || X <- [1,2,3], X > 1]">>, Cf),
 1261:     ?line [{{t,1},1},{{t,2},1}] = 
 1262:         analyse_expr(<<"[begin X end || \n"
 1263:                        "    X <- [1,2,3], X > 1]">>, Cf),
 1264:     ?line [{{t,1},1},{{t,2},1},{{t,3},3}] = 
 1265:         analyse_expr(<<"[begin X end || \n "
 1266:                        "    X <- [1,2,3], \n "
 1267:                        "    X > 1]">>, Cf),
 1268:     ?line [{{t,1},1},{{t,3},1},{{t,4},3}] = 
 1269:         analyse_expr(<<"[begin X end || \n "
 1270:                        "    X <- \n "
 1271:                        "        [1,2,3], \n "
 1272:                        "    X > 1]">>, Cf),
 1273:     ?line [{{t,1},1},{{t,2},2}] =
 1274:         analyse_expr(<<"[  \n "
 1275:                        "   X || X <- [1,2,3], X > 1]">>, Cf),
 1276:     ?line [{{t,1},1},{{t,2},2},{{t,3},3}] =
 1277:         analyse_expr(<<"[ \n"
 1278:                        "  X || X <- [1,2,3], \n"
 1279:                        "  X > 1]">>, Cf),
 1280:     ?line [{{t,1},1},{{t,2},1},{{t,3},2}] =
 1281:         analyse_expr(<<"[ \n "
 1282:                        "   X || X <- [1,2,3], X > 1, \n"
 1283:                        "   X > 2]">>, Cf),
 1284: 
 1285:     ?line [{{t,1},1},
 1286:            {{t,3},2},
 1287:            {{t,5},1},
 1288:            {{t,7},1},
 1289:            {{t,8},0},
 1290:            {{t,12},3},
 1291:            {{t,15},2},
 1292:            {{t,17},2},
 1293:            {{t,18},1}] =
 1294:         analyse_expr(<<"[ \n" % 1
 1295:                        "  begin\n"
 1296:                        "      X * 2\n" % 2
 1297:                        "  end ||\n"
 1298:                        "    X <- [1,\n" % 1
 1299:                        "          case two() of\n"
 1300:                        "              2 -> 2;\n" % 1
 1301:                        "              _ -> two\n" % 0
 1302:                        "          end,\n"
 1303:                        "          3],\n"
 1304:                        "    begin\n"
 1305:                        "        math:sqrt(X) > 1.0\n" % 3
 1306:                        "    end,\n"
 1307:                        "    begin\n"
 1308:                        "        true\n" % 2
 1309:                        "    end,\n"
 1310:                        "    true]. \n" % 2
 1311:                        "  two() -> 2">>, Cf), % 1
 1312: 
 1313:     ?line [{{t,1},1},
 1314:            {{t,2},2},
 1315:            {{t,3},1},
 1316:            {{t,5},1},
 1317:            {{t,6},0},
 1318:            {{t,9},3},
 1319:            {{t,10},2},
 1320:            {{t,11},2},
 1321:            {{t,12},1}] =
 1322:         analyse_expr(<<"[ \n"
 1323:                        "      X * 2 || \n" % 2
 1324:                        "    X <- [1,\n" % 1
 1325:                        "          case two() of\n"
 1326:                        "              2 -> 2;\n" % 1
 1327:                        "              _ -> two\n" % 0
 1328:                        "          end,\n"
 1329:                        "          3],\n"
 1330:                        "    math:sqrt(X) > 1.0,\n" % 3
 1331:                        "    true,\n" % 2
 1332:                        "    true]. \n" % 2
 1333:                        "  two() -> 2">>, Cf), % 1
 1334: 
 1335:     ?line [{{t,1},1},
 1336:            {{t,2},2},
 1337:            {{t,3},1},
 1338:            {{t,4},1},
 1339:            {{t,5},0},
 1340:            {{t,8},1},
 1341:            {{t,9},0},
 1342:            {{t,12},3},
 1343:            {{t,13},2},
 1344:            {{t,14},2}] = 
 1345:         analyse_expr(<<"<< \n" % 1
 1346:                        " << (X*2) >> || \n" % 2
 1347:                        "    <<X>> <= << (case two() of\n"
 1348:                        "                     2 -> 1;\n" % 1
 1349:                        "                     _ -> 2\n" % 0
 1350:                        "                 end)/integer,\n"
 1351:                        "                (case two() of \n"
 1352:                        "                    2 -> 2;\n" % 1
 1353:                        "                    _ -> two\n" % 0
 1354:                        "                 end)/integer,\n"
 1355:                        "                3 >>, \n"
 1356:                        "    math:sqrt(X) > 1.0,\n" % 3
 1357:                        "    true >>.\n" % 2
 1358:                        "two() -> 2">>, Cf),
 1359: 
 1360:     ?line [{{t,1},1},
 1361:            {{t,2},4},
 1362:            {{t,4},1},
 1363:            {{t,6},1},
 1364:            {{t,7},0},
 1365:            {{t,10},3},
 1366:            {{t,11},2},
 1367:            {{t,12},4},
 1368:            {{t,13},1}] =
 1369:         analyse_expr(<<"<< \n" % 1
 1370:                        " << (2)\n" % 4
 1371:                        "     :(8) >> || \n"
 1372:                        "    <<X>> <= << 1,\n" % 1
 1373:                        "                (case two() of \n"
 1374:                        "                    2 -> 2;\n" % 1
 1375:                        "                    _ -> two\n" % 0
 1376:                        "                 end)/integer,\n"
 1377:                        "                3 >>, \n"
 1378:                        "    math:sqrt(X) > 1.0,\n" % 3
 1379:                        "    <<_>> <= << 1, 2 >>,\n" % 2
 1380:                        "    true >>.\n" % 4
 1381:                        "two() -> 2">>, Cf), % 1
 1382: 
 1383:     ok.
 1384: 
 1385: otp_10979_hanging_node(_Config) ->
 1386: 
 1387:     P1 = processes(),
 1388: 
 1389:     cover:stop(non_existing_node),
 1390:     cover:stop(),
 1391: 
 1392:     P2 = processes(),
 1393: 
 1394:     case P2--P1 of
 1395: 	[] ->
 1396: 	    ok;
 1397: 	New ->
 1398: 	    [io:format("New: ~p, ~p~n",[P,process_info(P)]) || P<-New],
 1399: 	    ct:fail(hanging_process)
 1400:     end,
 1401: 
 1402:     ok.
 1403: 
 1404: compile_beam_opts(doc) ->
 1405:     ["Take compiler options from beam in cover:compile_beam"];
 1406: compile_beam_opts(suite) -> [];
 1407: compile_beam_opts(Config) when is_list(Config) ->
 1408:     {ok, Cwd} = file:get_cwd(),
 1409:     ok = file:set_cwd(?config(priv_dir, Config)),
 1410:     IncDir = filename:join(?config(data_dir, Config),
 1411:                                  "included_functions"),
 1412:     File = filename:join([?config(data_dir, Config), "otp_11439", "t.erl"]),
 1413:     %% use all compiler options allowed by cover:filter_options
 1414:     %% i and d don't make sense when compiling from beam though
 1415:     {ok, t} =
 1416:         compile:file(File, [{i, IncDir},
 1417:                             {d, 'BOOL'},
 1418:                             {d, 'MACRO', macro_defined},
 1419:                             export_all,
 1420:                             debug_info,
 1421:                             return_errors]),
 1422:     Exports =
 1423:         [{func1,0},
 1424:          {macro, 0},
 1425:          {exported,0},
 1426:          {nonexported,0},
 1427:          {module_info,0},
 1428:          {module_info,1}],
 1429:     Exports = t:module_info(exports),
 1430:     {ok, t} = cover:compile_beam("t"),
 1431:     Exports = t:module_info(exports),
 1432:     cover:stop(),
 1433:     ok = file:delete("t.beam"),
 1434:     ok = file:set_cwd(Cwd),
 1435:     ok.
 1436: 
 1437: %%--Auxiliary------------------------------------------------------------
 1438: 
 1439: analyse_expr(Expr, Config) ->
 1440:     Binary = [<<"-module(t). "
 1441:                 "-export([t/0]). "
 1442:                 "t() -> ">>, Expr, <<".\n">>],
 1443:     File = cc_mod(t, Binary, Config),
 1444:     t:t(),
 1445:     {ok, Result} = cover:analyse(t, calls, line),
 1446:     ok = file:delete(File),
 1447:     Result.
 1448: 
 1449: cc_mod(M, Binary, Config) ->
 1450:     {ok, Dir} = file:get_cwd(),
 1451:     PrivDir = ?config(priv_dir, Config),
 1452:     ok = file:set_cwd(PrivDir),
 1453:     File = atom_to_list(M) ++ ".erl",
 1454:     try 
 1455:         ok = file:write_file(File, Binary),
 1456:         {ok, M} = cover:compile(File),
 1457:         filename:join(PrivDir, File)
 1458:     after file:set_cwd(Dir)
 1459:     end.
 1460: 
 1461: c_mod(M, Binary, Config) ->
 1462:     {ok, Dir} = file:get_cwd(),
 1463:     PrivDir = ?config(priv_dir, Config),
 1464:     ok = file:set_cwd(PrivDir),
 1465:     File = atom_to_list(M) ++ ".erl",
 1466:     try 
 1467:         ok = file:write_file(File, Binary),
 1468:         {ok, M} = compile:file(File, [debug_info]),
 1469:         code:purge(M),
 1470:         AbsFile = filename:rootname(File, ".erl"),
 1471:         code:load_abs(AbsFile, M),
 1472:         filename:join(PrivDir, File)
 1473:     after file:set_cwd(Dir)
 1474:     end.
 1475: 
 1476: lsfiles() ->
 1477:     {ok, CWD} = file:get_cwd(),
 1478:     lsfiles(CWD).
 1479: 
 1480: lsfiles(Dir) ->
 1481:     {ok, Files} = file:list_dir(Dir),
 1482:     Files.
 1483: 
 1484: files(Files, Ext) ->
 1485:     lists:filter(fun(File) ->
 1486: 			 case filename:extension(File) of
 1487: 			     Ext -> true;
 1488: 			     _ -> false
 1489: 			 end
 1490: 		 end,
 1491: 		 Files).
 1492: 
 1493: remove([File|Files]) ->
 1494:     ok = file:delete(File),
 1495:     remove(Files);
 1496: remove([]) ->
 1497:     ok.
 1498: 
 1499: decompile([Mod|Mods]) ->
 1500:     code:purge(Mod),
 1501:     code:delete(Mod),
 1502:     decompile(Mods);
 1503: decompile([]) ->
 1504:     ok.
 1505: 
 1506: is_unloaded(What) ->
 1507:     if
 1508: 	is_list(What) -> true;
 1509: 	What==non_existing -> true;
 1510: 	true -> false
 1511:     end.
 1512: 
 1513: check_f_calls(F1,F2) ->
 1514:     {ok,[{{f,f1,0},F1},{{f,f2,0},F2}|_]} = cover:analyse(f,calls,function).