1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2001-2020. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20-module(cover_SUITE).
21
22-compile(export_all).
23
24-include_lib("common_test/include/ct.hrl").
25
26suite() ->
27    [{ct_hooks,[ts_install_cth]},
28     {timetrap,{minutes,5}}].
29
30all() ->
31    NoStartStop = [eif,otp_5305,otp_5418,otp_7095,otp_8273,
32                   otp_8340,otp_8188,compile_beam_opts,eep37,
33                   analyse_no_beam, line_0, compile_beam_no_file,
34                   compile_beam_missing_backend,
35                   otp_13277, otp_13289],
36    StartStop = [start, compile, analyse, misc, stop,
37                 distribution, reconnect, die_and_reconnect,
38                 dont_reconnect_after_stop, stop_node_after_disconnect,
39                 export_import, otp_5031, otp_6115,
40                 otp_8270, otp_10979_hanging_node, otp_14817,
41                 local_only, startup_race, otp_16476, cover_clauses],
42    case whereis(cover_server) of
43        undefined ->
44            [coverage,StartStop ++ NoStartStop];
45        _pid ->
46            [coverage|NoStartStop++[coverage_analysis]]
47    end.
48
49init_per_suite(Config) ->
50    [{ct_is_running_cover,whereis(cover_server) =/= undefined}|Config].
51
52end_per_suite(_Config) ->
53    ok.
54
55init_per_testcase(TC, Config) when TC =:= misc;
56                                   TC =:= compile;
57                                   TC =:= analyse;
58                                   TC =:= distribution;
59                                   TC =:= otp_5031;
60                                   TC =:= stop ->
61    case code:which(crypto) of
62        Path when is_list(Path) ->
63            init_per_testcase(dummy_tc, Config);
64        _Else ->
65            {skip, "No crypto file to test with"}
66    end;
67init_per_testcase(_TestCase, Config) ->
68    Config.
69
70end_per_testcase(TestCase, Config) ->
71    NoStop = [start,compile,analyse,misc],
72    DontStop = proplists:get_bool(ct_is_running_cover, Config) orelse
73    lists:member(TestCase, NoStop),
74    case DontStop of
75        true -> ok;
76        false -> cover:stop()
77    end,
78    ok.
79
80coverage(Config) when is_list(Config) ->
81    {ok,?MODULE} = cover:compile_beam(?MODULE),
82    ?MODULE:do_coverage(Config).
83
84do_coverage(Config) ->
85    Outdir = proplists:get_value(priv_dir, Config),
86    ExportFile = filename:join(Outdir, "export"),
87    ok = cover:export(ExportFile, ?MODULE),
88    {error,{already_started,_}} = cover:start(),
89    {error,_} = cover:compile_beam(non_existing_module),
90    _ = cover:which_nodes(),
91    _ = cover:modules(),
92    _ = cover:imported(),
93    {error,{not_cover_compiled,lists}} = cover:analyze(lists),
94
95    %% Cover escaping of '&' in HTML files.
96
97    case proplists:get_bool(ct_is_running_cover, Config) of
98        false ->
99            %% Cover server was implicitly started when this module
100            %% was cover-compiled. We must stop the cover server, but
101            %% we must ensure that this module is not on the call
102            %% stack when it is unloaded. Therefore, the call that
103            %% follows MUST be tail-recursive.
104            cover:stop();
105        true ->
106            %% Cover server was started by common_test; don't stop it.
107            ok
108    end.
109
110%% This test case will only be run when common_test is running cover.
111coverage_analysis(Config) when is_list(Config) ->
112    {ok,Analysis1} = cover:analyze(?MODULE),
113    io:format("~p\n", [Analysis1]),
114    {ok,Analysis2} = cover:analyze(?MODULE, calls),
115    io:format("~p\n", [Analysis2]),
116    {ok,_Analysis3} = cover:analyze(?MODULE, calls, line),
117
118    Outdir = proplists:get_value(priv_dir, Config),
119    Outfile = filename:join(Outdir, ?MODULE),
120
121    {ok,Outfile} = cover:analyze_to_file(?MODULE, Outfile),
122    {ok,Contents} = file:read_file(Outfile),
123    ok = file:delete(Outfile),
124    ok = io:put_chars(Contents),
125    {ok,Outfile} = cover:analyze_to_file(?MODULE, Outfile, [html]),
126    ok.
127
128start(Config) when is_list(Config) ->
129    ok = file:set_cwd(proplists:get_value(data_dir, Config)),
130
131    Files = lsfiles(),
132    remove(files(Files, ".out")),
133
134    {ok, Pid} = cover:start(),
135    {error, {already_started, Pid}} = cover:start().
136
137compile(Config) when is_list(Config) ->
138    ok = file:set_cwd(proplists:get_value(data_dir, Config)),
139
140    Result1 = cover:compile_directory(),
141    SortedResult = lists:sort(Result1),
142    {ok, CWD} = file:get_cwd(),
143    Result2 = cover:compile_directory(CWD),
144    SortedResult = lists:sort(Result2),
145    [{error,DFile},{ok,a},{ok,b},{ok,cc},{ok,f}] = SortedResult,
146    [{ok,e}] = cover:compile_directory("d1"),
147    {error,enoent} = cover:compile_directory("d2"),
148
149    [] = cover:compile([]),
150    Result21 = cover:compile([a,b,"cc.erl",d,"f"]),
151    SortedResult21 = lists:sort(Result21),
152    [{error,DFile},{ok,a},{ok,b},{ok,cc},{ok,f}] = SortedResult21,
153
154    {ok,a} = cover:compile(a),
155    {ok,b} = compile:file(b),
156    code:purge(b),
157    {module,b} = code:load_file(b),
158    {ok,d} = cover:compile("d.erl", [{d,'AGE',42}]),
159    {error,_BBFile} = cover:compile(bb),
160
161    StdlibDir = code:lib_dir(stdlib),
162    Lists = filename:join([StdlibDir, "src", "lists.erl"]),
163    {error, Lists} = cover:compile(Lists),
164
165    %% For compiling beam: using dummy files v,w,x,y and z
166    file:set_cwd("compile_beam"),
167    {ok,_} = compile:file(v,[debug_info,report]),
168    {ok,_} = compile:file(w,[debug_info,report]),
169    {ok,_} = compile:file(x),
170    {ok,_} = compile:file("d/y",[debug_info,{outdir,"d"},report]),
171    Key = "A Krypto Key",
172    CryptoWorks = crypto_works(),
173    case CryptoWorks of
174        false ->
175            {ok,_} = compile:file(crypt, [debug_info,report]),
176            {ok,crypt} = cover:compile_beam("crypt.beam");
177        true ->
178            {ok,_} = compile:file(crypt, [{debug_info_key,Key},report]),
179            {error,{encrypted_abstract_code,_}} =
180            cover:compile_beam("crypt.beam"),
181            ok = beam_lib:crypto_key_fun(simple_crypto_fun(Key)),
182            {ok,crypt} = cover:compile_beam("crypt.beam")
183    end,
184    Path = filename:join([proplists:get_value(data_dir, Config), "compile_beam", "v.erl"]),
185    {ok,v} = cover:compile_beam(v),
186    {source,Path} = lists:keyfind(source, 1, v:module_info(compile)),
187    {ok,w} = cover:compile_beam("w.beam"),
188    {error,{no_abstract_code,"./x.beam"}} = cover:compile_beam(x),
189    {error,{already_cover_compiled,no_beam_found,a}}=cover:compile_beam(a),
190    {error,non_existing} = cover:compile_beam(z),
191    [{ok,y}] = cover:compile_beam_directory("d"),
192    Result3 = lists:sort(cover:compile_beam_directory()),
193    [{error,{no_abstract_code,XBeam}},{ok,crypt},{ok,v},{ok,w}] = Result3,
194    {error,enoent} = cover:compile_beam_directory("d2"),
195
196    [] = cover:compile_beam([]),
197    Result31 = cover:compile_beam([crypt,"v.beam",w,"x"]),
198    SortedResult31 = lists:sort(Result31),
199    [{error,{no_abstract_code,XBeam}},{ok,crypt},{ok,v},{ok,w}] = SortedResult31,
200
201    decompile([v,w,y]),
202    Files = lsfiles(),
203    remove(files(Files, ".beam")).
204
205crypto_works() ->
206    try crypto:start() of
207        {error,{already_started,crypto}} -> true;
208        ok -> true
209    catch
210        error:_ ->
211            false
212    end.
213
214simple_crypto_fun(Key) ->
215    fun(init) -> ok;
216       ({debug_info, des3_cbc, crypt, _}) -> Key
217    end.
218
219analyse(Config) when is_list(Config) ->
220    ok = file:set_cwd(proplists:get_value(data_dir, Config)),
221
222    done = a:start(5),
223
224    {ok, {a,{17,2}}=ACovMod} = cover:analyse(a, coverage, module),
225    {ok, [{{a,exit_kalle,0},{1,0}},
226          {{a,loop,3},{5,1}},
227          {{a,pong,1},{1,0}},
228          {{a,start,1},{6,0}},
229          {{a,stop,1},{0,1}},
230          {{a,trycatch,1},{4,0}}]=ACovFunc} =
231    cover:analyse(a, coverage, function),
232    {ok, [{{a,exit_kalle,0,1},{1,0}},
233          {{a,loop,3,1},{3,1}},
234          {{a,loop,3,2},{2,0}},
235          {{a,pong,1,1},{1,0}},
236          {{a,start,1,1},{6,0}},
237          {{a,stop,1,1},{0,1}},
238          {{a,trycatch,1,1},{4,0}}]=ACovClause} =
239    cover:analyse(a, coverage, clause),
240    {ok, [{{a,9},{1,0}},
241          {{a,10},{1,0}},
242          {{a,11},{1,0}},
243          {{a,13},{1,0}},
244          {{a,14},{1,0}},
245          {{a,15},{1,0}},
246          {{a,21},{0,1}},
247          {{a,26},{1,0}},
248          {{a,31},{1,0}},
249          {{a,32},{1,0}},
250          {{a,34},{1,0}},
251          {{a,36},{0,1}},
252          {{a,39},{1,0}},
253          {{a,40},{1,0}},
254          {{a,44},{1,0}},
255          {{a,47},{1,0}},
256          {{a,49},{1,0}},
257          {{a,51},{1,0}},
258          {{a,55},{1,0}}]=ACovLine} = cover:analyse(a, coverage, line),
259
260    {ok, {a,15}=ACallsMod} = cover:analyse(a, calls, module),
261    {ok, [{{a,exit_kalle,0},1},
262          {{a,loop,3},6},
263          {{a,pong,1},5},
264          {{a,start,1},1},
265          {{a,stop,1},0},
266          {{a,trycatch,1},2}]=ACallsFunc} = cover:analyse(a, calls, function),
267    {ok, [{{a,exit_kalle,0,1},1},
268          {{a,loop,3,1},5},
269          {{a,loop,3,2},1},
270          {{a,pong,1,1},5},
271          {{a,start,1,1},1},
272          {{a,stop,1,1},0},
273          {{a,trycatch,1,1},2}]=ACallsClause} = cover:analyse(a, calls, clause),
274    {ok, [{{a,9},1},
275          {{a,10},1},
276          {{a,11},1},
277          {{a,13},1},
278          {{a,14},1},
279          {{a,15},1},
280          {{a,21},0},
281          {{a,26},5},
282          {{a,31},5},
283          {{a,32},5},
284          {{a,34},5},
285          {{a,36},0},
286          {{a,39},1},
287          {{a,40},1},
288          {{a,44},2},
289          {{a,47},1},
290          {{a,49},1},
291          {{a,51},2},
292          {{a,55},1}]=ACallsLine} = cover:analyse(a, calls, line),
293
294    {ok,ACovFunc} = cover:analyse(a),
295    {ok,ACovMod} = cover:analyse(a, module),
296    {ok,ACallsFunc} = cover:analyse(a, calls),
297
298    {ok, "a.COVER.out"} = cover:analyse_to_file(a),
299    {ok, "e.COVER.out"} = cover:analyse_to_file(e),
300    {ok, "a.COVER.html"} = cover:analyse_to_file(a,[html]),
301    {ok, "e.COVER.html"} = cover:analyse_to_file(e,[html]),
302
303    %% Analyse all modules
304    Modules = cover:modules(),
305    N = length(Modules),
306
307    {result,CovFunc,[]} = cover:analyse(), % default = coverage, function
308    ACovFunc = [A || {{a,_,_},_}=A<-CovFunc],
309
310    {result,CovMod,[]} = cover:analyse(coverage,module),
311    ACovMod = lists:keyfind(a,1,CovMod),
312
313    {result,CovClause,[]} = cover:analyse(coverage,clause),
314    ACovClause = [A || {{a,_,_,_},_}=A<-CovClause],
315
316    {result,CovLine,[]} = cover:analyse(coverage,line),
317    ACovLine = [A || {{a,_},_}=A<-CovLine],
318
319    {result,CallsFunc,[]} = cover:analyse(calls,function),
320    ACallsFunc = [A || {{a,_,_},_}=A<-CallsFunc],
321
322    {result,CallsMod,[]} = cover:analyse(calls,module),
323    ACallsMod = lists:keyfind(a,1,CallsMod),
324
325    {result,CallsClause,[]} = cover:analyse(calls,clause),
326    ACallsClause = [A || {{a,_,_,_},_}=A<-CallsClause],
327
328    {result,CallsLine,[]} = cover:analyse(calls,line),
329    ACallsLine = [A || {{a,_},_}=A<-CallsLine],
330
331    {result,AllToFile,[]} = cover:analyse_to_file(),
332    N = length(AllToFile),
333    true = lists:member("a.COVER.out",AllToFile),
334    {result,AllToFileHtml,[]} = cover:analyse_to_file([html]),
335    N = length(AllToFileHtml),
336    true = lists:member("a.COVER.html",AllToFileHtml),
337
338    %% Analyse list of modules
339    %% Listing all modules so we can compare result with above result
340    %% from analysing all.
341
342    {result,CovFunc1,[]} = cover:analyse(Modules), % default = coverage, function
343    true = lists:sort(CovFunc) == lists:sort(CovFunc1),
344
345    {result,CovMod1,[]} = cover:analyse(Modules,coverage,module),
346    true = lists:sort(CovMod) == lists:sort(CovMod1),
347
348    {result,CovClause1,[]} = cover:analyse(Modules,coverage,clause),
349    true = lists:sort(CovClause) == lists:sort(CovClause1),
350
351    {result,CovLine1,[]} = cover:analyse(Modules,coverage,line),
352    true = lists:sort(CovLine) == lists:sort(CovLine1),
353
354    {result,CallsFunc1,[]} = cover:analyse(Modules,calls,function),
355    true = lists:sort(CallsFunc1) == lists:sort(CallsFunc1),
356
357    {result,CallsMod1,[]} = cover:analyse(Modules,calls,module),
358    true = lists:sort(CallsMod) == lists:sort(CallsMod1),
359
360    {result,CallsClause1,[]} = cover:analyse(Modules,calls,clause),
361    true = lists:sort(CallsClause) == lists:sort(CallsClause1),
362
363    {result,CallsLine1,[]} = cover:analyse(Modules,calls,line),
364    true = lists:sort(CallsLine) == lists:sort(CallsLine1),
365
366    {result,AllToFile1,[]} = cover:analyse_to_file(Modules),
367    true = lists:sort(AllToFile) == lists:sort(AllToFile1),
368    {result,AllToFileHtml1,[]} = cover:analyse_to_file(Modules,[html]),
369    true = lists:sort(AllToFileHtml) == lists:sort(AllToFileHtml1),
370
371    %% analyse_to_file of file which is compiled from beam
372    {ok,f} = compile:file(f,[debug_info]),
373    code:purge(f),
374    {module,f} = code:load_file(f),
375    {ok,f} = cover:compile_beam(f),
376    f:f2(),
377    {ok, "f.COVER.out"} = cover:analyse_to_file(f),
378
379    %% Source code can be found via source
380    {ok,v} = compile:file("compile_beam/v",[debug_info]),
381    code:purge(v),
382    {module,v} = code:load_file(v),
383    {ok,v} = cover:compile_beam(v),
384    {ok,"v.COVER.out"} = cover:analyse_to_file(v),
385
386    %% Source code cannot be found
387    {ok,_} = file:copy("compile_beam/z.erl", "z.erl"),
388    {ok,z} = compile:file(z,[debug_info]),
389    code:purge(z),
390    {module,z} = code:load_file(z),
391    {ok,z} = cover:compile_beam(z),
392    ok = file:delete("z.erl"),
393    {error,{no_source_code_found,z}} = cover:analyse_to_file(z),
394    {result,[],[{no_source_code_found,z}]} = cover:analyse_to_file([z]),
395    code:purge(z),
396    code:delete(z),
397
398    {error,{not_cover_compiled,b}} = cover:analyse(b),
399    {error,{not_cover_compiled,g}} = cover:analyse(g),
400    {result,[],[{not_cover_compiled,b}]} = cover:analyse([b]),
401    {error,{not_cover_compiled,b}} = cover:analyse_to_file(b),
402    {error,{not_cover_compiled,g}} = cover:analyse_to_file(g),
403    {result,[],[{not_cover_compiled,g}]} = cover:analyse_to_file([g]).
404
405misc(Config) when is_list(Config) ->
406    ok = file:set_cwd(proplists:get_value(data_dir, Config)),
407
408    [a,cc,crypt,d,e,f,v] = lists:sort(cover:modules()),
409
410    {ok,cc} = compile:file(cc),
411    code:purge(cc),
412    {module,cc} = code:load_file(cc),
413    [a,crypt,d,e,f,v] = lists:sort(cover:modules()),
414
415    {file, _File} = cover:is_compiled(a),
416    false = cover:is_compiled(b),
417    false = cover:is_compiled(g),
418
419    ok = cover:reset(a),
420    {ok, {a,{0,19}}} = cover:analyse(a, module),
421    ok = cover:reset().
422
423stop(Config) when is_list(Config) ->
424    ok = file:set_cwd(proplists:get_value(data_dir, Config)),
425
426    cover_compiled = code:which(a),
427    {ok,d} = compile:file(d, [{d,'AGE',42}]),
428    code:purge(d),
429    {module,d} = code:load_file(d),
430    ok = cover:stop(),
431    Beam = code:which(a),
432    true = is_unloaded(Beam),
433
434    Files = lsfiles(),
435    remove(files(Files, ".out")),
436    remove(files(Files, ".html")),
437    remove(files(Files, ".beam")).
438
439distribution(Config) when is_list(Config) ->
440    DataDir = proplists:get_value(data_dir, Config),
441    ok = file:set_cwd(DataDir),
442
443    {ok,N1} = test_server:start_node(cover_SUITE_distribution1,slave,[]),
444    {ok,N2} = test_server:start_node(cover_SUITE_distribution2,slave,[]),
445    {ok,N3} = test_server:start_node(cover_SUITE_distribution3,slave,[]),
446    {ok,N4} = test_server:start_node(cover_SUITE_distribution4,slave,[]),
447
448    %% Check that an already compiled module is loaded on new nodes
449    {ok,f} = cover:compile(f),
450    {ok,[_,_,_,_]} = cover:start(nodes()),
451    cover_compiled = code:which(f),
452    cover_compiled = rpc:call(N1,code,which,[f]),
453    cover_compiled = rpc:call(N2,code,which,[f]),
454    cover_compiled = rpc:call(N3,code,which,[f]),
455    cover_compiled = rpc:call(N4,code,which,[f]),
456
457    %% Check that a node cannot be started twice
458    {ok,[]} = cover:start(N2),
459
460    %% Check that the current node (i.e. the main node) is not started with
461    %% start/1 and not stopped with stop/1
462    {ok,[]} = cover:start(node()),
463    ok = cover:stop(node()),
464    true = is_pid(whereis(cover_server)),
465
466    %% Check that a new compiled module is loaded on all existing nodes
467    compile:file("compile_beam/v",[debug_info]),
468    {ok,v} = cover:compile_beam(v),
469    cover_compiled = code:which(v),
470    cover_compiled = rpc:call(N1,code,which,[v]),
471    cover_compiled = rpc:call(N2,code,which,[v]),
472    cover_compiled = rpc:call(N3,code,which,[v]),
473    cover_compiled = rpc:call(N4,code,which,[v]),
474
475    %% this is lost when the node is killed
476    rpc:call(N3,f,f2,[]),
477    rpc:call(N3,erlang,halt,[]),
478
479    %% this should be visible in analyse
480    rpc:call(N1,f,f1,[]),
481
482    %% Check that data is collected from remote node when stopped
483    ok = cover:stop(N1),
484    N1Beam = rpc:call(N1,code,which,[f]),
485    true = is_unloaded(N1Beam),
486    check_f_calls(1,0),
487
488    %% Call f:f1() again on another node and check that number of calls is
489    %% accumulated.
490    f:f1(),
491    check_f_calls(2,0),
492
493    %% Check that reset works on all nodes
494    f:f1(),
495    rpc:call(N2,f,f1,[]),
496    ok = cover:reset(f),
497    check_f_calls(0,0),
498
499    %% Check that data is collected from all nodes
500    rpc:call(N2,f,f1,[]),
501    f:f2(),
502    check_f_calls(1,1),
503
504    %% Check that same data is not fetched again (i.e. that analyse does
505    %% reset on the remote node(s))
506    check_f_calls(1,1),
507
508    %% Another checn that data is not fetched twice, i.e. when flushed
509    %% then analyse should not add the same data again.
510    rpc:call(N4,f,f2,[]),
511    ok = cover:flush(N4),
512    check_f_calls(1,2),
513
514    %% Check that flush collects data so calls are not lost if node is killed
515    rpc:call(N4,f,f2,[]),
516    ok = cover:flush(N4),
517    rpc:call(N4,erlang,halt,[]),
518    check_f_calls(1,3),
519
520    %% Check that stop() unloads on all nodes
521    ok = cover:stop(),
522    timer:sleep(100), %% Give nodes time to unload on slow machines.
523    LocalBeam = code:which(f),
524    N2Beam = rpc:call(N2,code,which,[f]),
525    true = is_unloaded(LocalBeam),
526    true = is_unloaded(N2Beam),
527
528    %% Check that cover_server on remote node does not die if main node dies
529    {ok,[N1]} = cover:start(N1),
530    true = is_pid(N1Server = rpc:call(N1,erlang,whereis,[cover_server])),
531    exit(whereis(cover_server),kill),
532    timer:sleep(100),
533    N1Server = rpc:call(N1,erlang,whereis,[cover_server]),
534
535    %% Cleanup
536    Files = lsfiles(),
537    remove(files(Files, ".beam")),
538    test_server:stop_node(N1),
539    test_server:stop_node(N2).
540
541%% Test that a lost node is reconnected
542reconnect(Config) ->
543    DataDir = proplists:get_value(data_dir, Config),
544    ok = file:set_cwd(DataDir),
545
546    {ok,a} = compile:file(a),
547    {ok,b} = compile:file(b),
548    {ok,f} = compile:file(f),
549
550    {ok,N1} = test_server:start_node(cover_SUITE_reconnect,peer,
551                                     [{args," -pa " ++ DataDir},
552                                      {start_cover,false}]),
553    {ok,a} = cover:compile(a),
554    {ok,f} = cover:compile(f),
555    {ok,[N1]} = cover:start(nodes()),
556
557    %% Some calls to check later
558    rpc:call(N1,f,f1,[]),
559    cover:flush(N1),
560    rpc:call(N1,f,f1,[]),
561
562    %% This will cause first casue the N1 node to initiate a
563    %% disconnect and then call f:f2() when nodes() =:= [] on N1.
564    rpc:cast(N1,f,call_f2_when_isolated,[]),
565    timer:sleep(500), % allow some to detect disconnect and for f:f2() call
566    cover_which_nodes([]),
567
568    %% Do some add one module (b) and remove one module (a)
569    code:purge(a),
570    {module,a} = code:load_file(a),
571    {ok,b} = cover:compile(b),
572    cover_compiled = code:which(b),
573
574    cover_which_nodes([]),
575    check_f_calls(1,0), % only the first call - before the flush
576
577    %% Reconnect the node and check that b and f are cover compiled but not a
578    net_kernel:connect_node(N1),
579    timer:sleep(100),
580    [N1] = cover:which_nodes(), % we are reconnected
581    cover_compiled = rpc:call(N1,code,which,[b]),
582    cover_compiled = rpc:call(N1,code,which,[f]),
583    ABeam = rpc:call(N1,code,which,[a]),
584    false = (cover_compiled==ABeam),
585
586    %% Ensure that we have:
587    %% * one f1 call from before the flush,
588    %% * one f1 call from after the flush but before disconnect
589    %% * one f2 call when disconnected
590    check_f_calls(2,1),
591
592    cover:stop(),
593    test_server:stop_node(N1),
594    ok.
595
596%% Test that a lost node is reconnected - also if it has been dead
597die_and_reconnect(Config) ->
598    DataDir = proplists:get_value(data_dir, Config),
599    ok = file:set_cwd(DataDir),
600
601    {ok,f} = compile:file(f),
602
603    NodeName = cover_SUITE_die_and_reconnect,
604    {ok,N1} = test_server:start_node(NodeName,peer,
605                                     [{args," -pa " ++ DataDir},
606                                      {start_cover,false}]),
607    %% {ok,a} = cover:compile(a),
608    {ok,f} = cover:compile(f),
609    {ok,[N1]} = cover:start(nodes()),
610
611    %% Some calls to check later
612    rpc:call(N1,f,f1,[]),
613    cover:flush(N1),
614    rpc:call(N1,f,f1,[]),
615
616    %% Kill the node
617    rpc:call(N1,erlang,halt,[]),
618    cover_which_nodes([]),
619
620    check_f_calls(1,0), % only the first call - before the flush
621
622    %% Restart the node and check that cover reconnects
623    {ok,N1} = test_server:start_node(NodeName,peer,
624                                     [{args," -pa " ++ DataDir},
625                                      {start_cover,false}]),
626    timer:sleep(100),
627    [N1] = cover:which_nodes(), % we are reconnected
628    cover_compiled = rpc:call(N1,code,which,[f]),
629
630    %% One more call...
631    rpc:call(N1,f,f1,[]),
632
633    %% Ensure that no more calls are counted
634    check_f_calls(2,0),
635
636    cover:stop(),
637    test_server:stop_node(N1),
638    ok.
639
640%% Test that a stopped node is not marked as lost, i.e. that it is not
641%% reconnected if it is restarted (OTP-10638)
642dont_reconnect_after_stop(Config) ->
643    DataDir = proplists:get_value(data_dir, Config),
644    ok = file:set_cwd(DataDir),
645
646    {ok,f} = compile:file(f),
647
648    NodeName = cover_SUITE_dont_reconnect_after_stop,
649    {ok,N1} = test_server:start_node(NodeName,peer,
650                                     [{args," -pa " ++ DataDir},
651                                      {start_cover,false}]),
652    {ok,f} = cover:compile(f),
653    {ok,[N1]} = cover:start(nodes()),
654
655    %% A call to check later
656    rpc:call(N1,f,f1,[]),
657
658    %% Stop cover on the node, then terminate the node
659    cover:stop(N1),
660    rpc:call(N1,erlang,halt,[]),
661    cover_which_nodes([]),
662
663    check_f_calls(1,0),
664
665    %% Restart the node and check that cover does not reconnect
666    {ok,N1} = test_server:start_node(NodeName,peer,
667                                     [{args," -pa " ++ DataDir},
668                                      {start_cover,false}]),
669    timer:sleep(300),
670    cover_which_nodes([]),
671    Beam = rpc:call(N1,code,which,[f]),
672    false = (Beam==cover_compiled),
673
674    %% One more call...
675    rpc:call(N1,f,f1,[]),
676    cover:flush(N1),
677
678    %% Ensure that the last call is not counted
679    check_f_calls(1,0),
680
681    cover:stop(),
682    test_server:stop_node(N1),
683    ok.
684
685%% Test that a node which is stopped while it is marked as lost is not
686%% reconnected if it is restarted (OTP-10638)
687stop_node_after_disconnect(Config) ->
688    DataDir = proplists:get_value(data_dir, Config),
689    ok = file:set_cwd(DataDir),
690
691    {ok,f} = compile:file(f),
692
693    NodeName = cover_SUITE_stop_node_after_disconnect,
694    {ok,N1} = test_server:start_node(NodeName,peer,
695                                     [{args," -pa " ++ DataDir},
696                                      {start_cover,false}]),
697    {ok,f} = cover:compile(f),
698    {ok,[N1]} = cover:start(nodes()),
699
700    %% A call to check later
701    rpc:call(N1,f,f1,[]),
702
703    %% Flush the node, then terminate the node to make it marked as lost
704    cover:flush(N1),
705    rpc:call(N1,erlang,halt,[]),
706
707    check_f_calls(1,0),
708
709    %% Stop cover on node
710    cover:stop(N1),
711
712    %% Restart the node and check that cover does not reconnect
713    {ok,N1} = test_server:start_node(NodeName,peer,
714                                     [{args," -pa " ++ DataDir},
715                                      {start_cover,false}]),
716    timer:sleep(300),
717    cover_which_nodes([]),
718    Beam = rpc:call(N1,code,which,[f]),
719    false = (Beam==cover_compiled),
720
721    %% One more call...
722    rpc:call(N1,f,f1,[]),
723    cover:flush(N1),
724
725    %% Ensure that the last call is not counted
726    check_f_calls(1,0),
727
728    cover:stop(),
729    test_server:stop_node(N1),
730    ok.
731
732distribution_performance(Config) ->
733    PrivDir = proplists:get_value(priv_dir,Config),
734    Dir = filename:join(PrivDir,"distribution_performance"),
735    AllFiles = filename:join(Dir,"*"),
736    ok = filelib:ensure_dir(AllFiles),
737    code:add_patha(Dir),
738    M = 9,   % Generate M modules
739    F = 210, % with F functions
740    C = 10,  % and each function of C clauses
741    Mods = generate_modules(M,F,C,Dir),
742
743    %    test_server:break(""),
744
745    NodeName = cover_SUITE_distribution_performance,
746    {ok,N1} = test_server:start_node(NodeName,peer,[{start_cover,false}]),
747    %% CFun = fun() ->
748    %% 		   [{ok,_} = cover:compile_beam(Mod) || Mod <- Mods]
749    %% 	   end,
750    CFun = fun() -> cover:compile_beam(Mods) end,
751    {CT,_CA} = timer:tc(CFun),
752    %    erlang:display(_CA),
753    erlang:display({compile,CT}),
754
755    {SNT,_} = timer:tc(fun() -> {ok,[N1]} = cover:start(nodes()) end),
756    erlang:display({start_node,SNT}),
757
758    [1 = rpc:call(N1,Mod,f1,[1]) || Mod <- Mods],
759
760    %    Fun = fun() -> [cover:analyse(Mod,calls,function) || Mod<-Mods] end,
761    %    Fun = fun() -> analyse_all(Mods,calls,function) end,
762    %    Fun = fun() -> cover:analyse('_',calls,function) end,
763    Fun = fun() -> cover:analyse(Mods,calls,function) end,
764
765    %    Fun = fun() -> [begin cover:analyse_to_file(Mod,[html]) end || Mod<-Mods] end,
766    %    Fun = fun() -> analyse_all_to_file(Mods,[html]) end,
767    %    Fun = fun() -> cover:analyse_to_file(Mods,[html]) end,
768    %    Fun = fun() -> cover:analyse_to_file([html]) end,
769
770    %    Fun = fun() -> cover:reset() end,
771
772    {AT,_A} = timer:tc(Fun),
773    erlang:display({analyse,AT}),
774    %    erlang:display(lists:sort([X || X={_MFA,N} <- lists:append([L || {ok,L}<-A]), N=/=0])),
775
776    %% fprof:apply(Fun, [],[{procs,[whereis(cover_server)]}]),
777    %% fprof:profile(),
778    %% fprof:analyse(dest,[]),
779
780    {SNT2,_} = timer:tc(fun() -> test_server:stop_node(N1) end),
781    erlang:display({stop_node,SNT2}),
782
783    code:del_path(Dir),
784    Files = filelib:wildcard(AllFiles),
785    [ok = file:delete(File) || File <- Files],
786    ok = file:del_dir(Dir),
787    ok.
788
789%% Run analysis in parallel
790analyse_all(Mods,Analysis,Level) ->
791    Pids = [begin
792                Pid = spawn(fun() ->
793                                    {ok,A} = cover:analyse(Mod,Analysis,Level),
794                                    exit(A)
795                            end),
796                erlang:monitor(process,Pid),
797                Pid
798            end || Mod <- Mods],
799    get_downs(Pids,[]).
800
801analyse_all_to_file(Mods,Opts) ->
802    Pids = [begin
803                Pid = cover:async_analyse_to_file(Mod,Opts),
804                erlang:monitor(process,Pid),
805                Pid
806            end || Mod <- Mods],
807    get_downs(Pids,[]).
808
809get_downs([],Acc) ->
810    Acc;
811get_downs(Pids,Acc) ->
812    receive
813        {'DOWN', _Ref, _Type, Pid, A} ->
814            get_downs(lists:delete(Pid,Pids),[A|Acc])
815    end.
816
817generate_modules(0,_,_,_) ->
818    [];
819generate_modules(M,F,C,Dir) ->
820    ModStr = "m" ++ integer_to_list(M),
821    Mod = list_to_atom(ModStr),
822    Src = ["-module(",ModStr,").\n"
823           "-compile(export_all).\n" |
824           generate_functions(F,C)],
825    Erl = filename:join(Dir,ModStr++".erl"),
826    ok = file:write_file(Erl,Src),
827    {ok,Mod} = compile:file(Erl,[{outdir,Dir},debug_info,report]),
828    [Mod | generate_modules(M-1,F,C,Dir)].
829
830generate_functions(0,_) ->
831    [];
832generate_functions(F,C) ->
833    Func = "f" ++ integer_to_list(F),
834    [generate_clauses(C,Func) | generate_functions(F-1,C)].
835
836generate_clauses(0,_) ->
837    [];
838generate_clauses(C,Func) ->
839    CStr = integer_to_list(C),
840    Sep = if C==1 -> "."; true -> ";" end,
841    [Func,"(",CStr,") -> ",CStr,Sep,"\n" |
842     generate_clauses(C-1,Func)].
843
844
845export_import(Config) when is_list(Config) ->
846    DataDir = proplists:get_value(data_dir, Config),
847    ok = file:set_cwd(DataDir),
848    PortCount = length(erlang:ports()),
849
850    %% Export one module
851    {ok,f} = cover:compile(f),
852    f:f1(),
853    %% check that no info is written about where data comes from when no
854    %% files are imported
855    test_server:capture_start(),
856    check_f_calls(1,0),
857    [] = test_server:capture_get(),
858    test_server:capture_stop(),
859    ok = cover:export("f_exported",f),
860    check_f_calls(1,0),
861    ok = cover:stop(),
862
863    %% Check that same data exists after import and that info is written about
864    %% data comming from imported file
865    ok = cover:import("f_exported"),
866    test_server:capture_start(),
867    check_f_calls(1,0),
868    [Text1] = test_server:capture_get(),
869    "Analysis includes data from imported files"++_ = lists:flatten(Text1),
870    test_server:capture_stop(),
871
872    %% Export all modules
873    {ok,a} = cover:compile(a),
874    test_server:capture_start(),
875    ok = cover:export("all_exported"),
876    [] = test_server:capture_get(),
877    %    "Export includes data from imported files"++_ = lists:flatten(Text2),
878    test_server:capture_stop(),
879    ok = cover:stop(),
880    ok = cover:import("all_exported"),
881    check_f_calls(1,0),
882
883    %% Check that data is reset when module is compiled again, and that
884    %% warning is written when data is deleted for imported module.
885    test_server:capture_start(),
886    {ok,f} = cover:compile(f),
887    timer:sleep(10), % capture needs some time
888    [Text3] = test_server:capture_get(),
889    "WARNING: Deleting data for module f imported from" ++ _ = lists:flatten(Text3),
890    test_server:capture_stop(),
891    check_f_calls(0,0),
892
893    %% Check that data is summed up when first compiled and then imported
894    %% The module which has been compiled (f) is loaded from the file
895    %% all_exported again (since it has been reset during cover compiling),
896    %% but the other module (a) is not loaded since it is already loaded
897    f:f1(),
898    f:f2(),
899    ok = cover:import("f_exported"),
900    test_server:capture_start(),
901    ok = cover:import("all_exported"),
902    [Text4] = test_server:capture_get(), % a is not loaded again
903    "WARNING: Module a already imported from " ++ _ = lists:flatten(Text4),
904    test_server:capture_stop(),
905    check_f_calls(3,1),
906
907    %% Check that warning is written when same file is imported twice,
908    %% and that data is not imported again
909    test_server:capture_start(),
910    ok = cover:import("all_exported"),
911    [Text5,Text6] = test_server:capture_get(),
912    "WARNING: Module f already imported from " ++ _ = lists:flatten(Text5),
913    "WARNING: Module a already imported from " ++ _ = lists:flatten(Text6),
914    test_server:capture_stop(),
915    check_f_calls(3,1),
916
917    %% Check that reset removes all data and that the file which has been
918    %% reset can be imported again with no warning
919    cover:reset(f),
920    check_f_calls(0,0),
921    test_server:capture_start(),
922    ok = cover:import("all_exported"),
923    [Text7] = test_server:capture_get(), % warning only on mod a
924    "WARNING: Module a already imported from " ++ _ = lists:flatten(Text7),
925    test_server:capture_stop(),
926    check_f_calls(1,0),
927
928    %% same as above - only reset all
929    cover:reset(),
930    check_f_calls(0,0),
931    test_server:capture_start(),
932    ok = cover:import("all_exported"),
933    [] = test_server:capture_get(), % no warnings
934    test_server:capture_stop(),
935    check_f_calls(1,0),
936
937    %% Check no raw files are left open
938    PortCount = length(erlang:ports()),
939
940    %% Cleanup
941    ok = cover:stop(),
942    Files = lsfiles(),
943    remove(["f_exported","all_exported"|files(Files, ".beam")]).
944
945
946otp_5031(Config) when is_list(Config) ->
947    ct:timetrap({seconds, 10}),
948
949    {ok,N1} = test_server:start_node(cover_SUITE_otp_5031,slave,[]),
950    {ok,[N1]} = cover:start(N1),
951    {error,not_main_node} = rpc:call(N1,cover,modules,[]),
952    cover:stop(),
953    test_server:stop_node(N1),
954    ok.
955
956%% Test the \'Exclude Included Functions\' functionality
957eif(Config) when is_list(Config) ->
958    ok = file:set_cwd(filename:join(proplists:get_value(data_dir, Config),
959                                    "included_functions")),
960    {ok, cover_inc} = compile:file(cover_inc,[debug_info]),
961    {ok, cover_inc} = cover:compile_beam(cover_inc),
962
963    %% This function will cause an included function to be executed.
964    %% The analysis should only show the lines that actually exist
965    %% in cover_inc.beam - not the ones from the included file.
966    cover_inc:func(),
967    {ok, [_, _]} = cover:analyse(cover_inc, line),
968    ok.
969
970otp_5305(Config) when is_list(Config) ->
971    ok = file:set_cwd(proplists:get_value(priv_dir, Config)),
972
973    File = "t.erl",
974    Test = <<"-module(t).
975              -export([t/0]).
976              -include_lib(\"stdlib/include/ms_transform.hrl\").
977              t() ->
978                  ets:fun2ms(fun(X) -> X end).
979             ">>,
980    ok = file:write_file(File, Test),
981    {ok, t} = cover:compile(File),
982    ok = file:delete(File),
983    ok.
984
985otp_5418(Config) when is_list(Config) ->
986    ok = file:set_cwd(proplists:get_value(priv_dir, Config)),
987
988    File = "t.erl",
989    Test = <<"-module(t).
990             ">>,
991    ok = file:write_file(File, Test),
992    {ok, t} = cover:compile(File),
993    {ok,{t,{0,0}}} = cover:analyse(t, module),
994    ok = file:delete(File),
995    ok.
996
997otp_6115(Config) when is_list(Config) ->
998    {ok, CWD} = file:get_cwd(),
999    Dir = filename:join(proplists:get_value(data_dir, Config), otp_6115),
1000    ok = file:set_cwd(Dir),
1001    {ok, f1} = compile:file(f1, [debug_info]),
1002    {ok, f2} = compile:file(f2, [debug_info]),
1003
1004    %% Cover compile f1, but not f2
1005    {ok, f1} = cover:compile(f1),
1006
1007    %% This test used to ensure that a process containing a
1008    %% fun refering to cover compiled code was killed.
1009    %% check_process_code may however ignore funs as of ERTS
1010    %% version 8.1. The test has therefore been rewritten to
1011    %% check that a process with a direct reference (in this
1012    %% case a return address) to the code is killed.
1013    %%
1014    %% If f1 is cover compiled, a process P is started with a
1015    %% direct reference to the f1, and cover:stop() is called,
1016    %% then P should be killed.
1017    %% This is because of the return address to the cover
1018    %% compiled code which should be *unloaded* when cover:stop() is
1019    %% called -- running cover compiled code when there is no cover
1020    %% server and thus no ets tables to bump counters in, makes no
1021    %% sense.
1022    Pid = spawn(fun () -> f1:non_tail_call_f2_wait() end),
1023
1024    %% Now stop cover
1025    cover:stop(),
1026
1027    %% Ensure that f1 is loaded (and not cover compiled), and that
1028    %% both Pid is dead.
1029    case code:which(f1) of
1030        Beam when is_list(Beam) ->
1031            ok;
1032        Other ->
1033            ct:fail({"f1 is not reloaded", Other})
1034    end,
1035    case process_info(Pid) of
1036        undefined ->
1037            ok;
1038        _PI ->
1039            RefToOldP = erlang:check_process_code(Pid, f1),
1040            ct:fail({"Pid still alive", RefToOldP})
1041    end,
1042
1043    file:set_cwd(CWD),
1044    ok.
1045
1046%% andalso/orelse
1047otp_7095(Config) when is_list(Config) ->
1048    ok = file:set_cwd(proplists:get_value(priv_dir, Config)),
1049
1050    File = "t.erl",
1051    Test = <<"-module(t).
1052              -export([t/0]).
1053              t() ->
1054                  t1(),
1055                  t2(),
1056                  t3(),
1057                  t4(),
1058                  t5(),
1059                  put(t6, 0),
1060                  0  = t6(),
1061                  1 = erase(t6),
1062                  t7(),
1063                  put(t8, 0),
1064                  {'EXIT',{{badarg,0},_}} = (catch t8()),
1065                  1 = erase(t8),
1066                  t9(),
1067                  ok.
1068
1069              t1() ->
1070                  false        % 20
1071                    andalso
1072                  true.        % 22
1073
1074              t2() ->
1075                  true         % 25
1076                    andalso
1077                  true.        % 27
1078
1079              t3() ->
1080                  false        % 30
1081                    orelse
1082                  true.        % 32
1083
1084              t4() ->
1085                  true         % 35
1086                    orelse
1087                  true.        % 37
1088
1089              t5() ->
1090                  true         % 40
1091                    andalso
1092                  true         % 42
1093                    andalso
1094                  false.       % 44
1095
1096              t6() ->
1097                  true andalso % 47
1098                  add_one(t6). % 48
1099
1100              t7() ->
1101                  true         % 51
1102                    andalso
1103                  false        % 53
1104                    andalso
1105                  not_ok.      % 55
1106
1107              t8() ->
1108                  true         % 58
1109                    andalso
1110                  true         % 60
1111                    andalso
1112                  add_one(t8)  % 62
1113                    andalso
1114                  false.       % 64
1115
1116              t9() ->
1117                  if           % 67
1118                      true ->
1119                          true % 69
1120                            andalso
1121                          false % 71
1122                  end
1123                    orelse
1124                  case ok of   % 74
1125                      true ->
1126                          a;   % 76
1127                      _ ->
1128                          true % 78
1129                  end.
1130
1131              add_one(T) ->
1132                  put(T, get(T) + 1). % 82
1133             ">>,
1134    ok = file:write_file(File, Test),
1135    {ok, t} = cover:compile(File),
1136    ok = t:t(),
1137    {ok,[{{t,4},1},{{t,5},1},{{t,6},1},{{t,7},1},{{t,8},1},{{t,9},1},
1138         {{t,10},1},{{t,11},1},{{t,12},1},{{t,13},1},{{t,14},1},
1139         {{t,15},1},{{t,16},1},{{t,17},1},
1140         {{t,20},1},{{t,22},0},
1141         {{t,25},1},{{t,27},1},
1142         {{t,30},1},{{t,32},1},
1143         {{t,35},1},{{t,37},0},
1144         {{t,40},1},{{t,42},1},{{t,44},1},
1145         {{t,47},1},{{t,48},1},
1146         {{t,51},1},{{t,53},1},{{t,55},0},
1147         {{t,58},1},{{t,60},1},{{t,62},1},{{t,64},0},
1148         {{t,67},1},{{t,69},1},{{t,71},1},{{t,74},1},
1149         {{t,76},0},{{t,78},1},
1150         {{t,82},2}]} = cover:analyse(t, calls, line),
1151    ok = file:delete(File),
1152    ok.
1153
1154
1155%% OTP-8270. Bug.
1156otp_8270(Config) when is_list(Config) ->
1157    DataDir = proplists:get_value(data_dir, Config),
1158    ok = file:set_cwd(DataDir),
1159
1160    PrivDir = proplists:get_value(priv_dir, Config),
1161
1162    As = [{args," -pa " ++ PrivDir}],
1163    {ok,N1} = test_server:start_node(cover_n1,slave,As),
1164    {ok,N2} = test_server:start_node(cover_n2,slave,As),
1165    {ok,N3} = test_server:start_node(cover_n3,slave,As),
1166
1167    timer:sleep(500),
1168    {ok,[_,_,_]} = cover:start(nodes()),
1169
1170    Test = <<"-module(m).\n"
1171             "-compile(export_all).\n"
1172             "t() -> t(0).\n"
1173             "l() ->\n"
1174             "   catch ets:tab2list(cover_internal_data_table).\n"
1175             "t(Sz) ->\n"
1176             "   case ets:info(cover_internal_data_table, size) of\n"
1177             "       Sz ->\n"
1178             "           m:t(Sz); % Not a local call! Newly loaded code is entered.\n"
1179             "       NSz ->\n"
1180             "           % error_logger:info_msg(\"~p: ~p ~p change~n L1 ~p~n\", \n"
1181             "           % [node(), Sz, NSz, l()]),\n"
1182             "           m:t(NSz)\n"
1183             "   end.\n">>,
1184    _File = c_mod(m, Test, Config),
1185    Fun = fun m:t/0,
1186    Pid1 = spawn(Fun),
1187    Pid2 = spawn(N1, Fun),
1188    Pid3 = spawn(N2, Fun),
1189    Pid4 = spawn(N3, Fun),
1190
1191    {ok, m} = cover:compile_beam(m),
1192
1193    timer:sleep(1000),
1194
1195    Info = erlang:process_info(Pid1),
1196    N1_info = rpc:call(N1, erlang, process_info, [Pid2]),
1197    N2_info = rpc:call(N2, erlang, process_info, [Pid3]),
1198    N3_info = rpc:call(N3, erlang, process_info, [Pid4]),
1199
1200    true = is_list(Info),
1201    {N1,true} = {N1,is_list(N1_info)},
1202    {N2,true} = {N2,is_list(N2_info)},
1203    {N3,true} = {N3,is_list(N3_info)},
1204
1205    exit(Pid1,kill),
1206    test_server:stop_node(N1),
1207    test_server:stop_node(N2),
1208    test_server:stop_node(N3),
1209    ok.
1210
1211%% OTP-8273. Bug.
1212otp_8273(Config) when is_list(Config) ->
1213    Test = <<"-module(t).
1214              -export([t/0]).
1215              t() ->
1216                  foo = true andalso foo,
1217                  bar = false orelse bar,
1218                  ok.
1219             ">>,
1220    File = cc_mod(t, Test, Config),
1221    ok = t:t(),
1222    ok = file:delete(File),
1223
1224    ok.
1225
1226%% OTP-8340. Bug.
1227otp_8340(Config) when is_list(Config) ->
1228    [{{t,1},1},{{t,2},1},{{t,4},1}] =
1229    analyse_expr(<<"<< \n"
1230                   " <<3:2, \n"
1231                   "   SeqId:62>> \n"
1232                   "      || SeqId <- [64] >>">>, Config),
1233    ok.
1234
1235%% Clauses on the same line.
1236otp_8188(Config) when is_list(Config) ->
1237    %% This example covers the bug report:
1238    Test = <<"-module(t).
1239              -export([test/1]).
1240
1241              -define(FOOBAR(X),
1242                      case X of
1243                          ok -> true;
1244                          _ -> false
1245                      end).
1246
1247              test(X)->
1248                  _Res =
1249                  ?FOOBAR(X).
1250             ">>,
1251    File = cc_mod(t, Test, Config),
1252    false = t:test(nok),
1253    {ok,[{{t,11},1},{{t,12},1}]} = cover:analyse(t, calls, line),
1254    ok = file:delete(File),
1255
1256    %% Bit string comprehensions are now traversed;
1257    %% the handling of list comprehensions has been improved:
1258    comprehension_8188(Config),
1259
1260    %% Variants of the reported bug:
1261    bug_8188(Config),
1262    ok.
1263
1264bug_8188(Cf) ->
1265    [{{t,1},1},{{t,2},1},{{t,3},1}] =
1266    analyse_expr(<<"A = 3,\n" % 1
1267                   "    case A of\n" % 1
1268                   "        2 -> two; 3 -> three end, A + 2">>,  % 1
1269                 Cf),
1270
1271    [{{t,1},1},
1272     {{t,2},0},
1273     {{t,3},1},
1274     {{t,4},1},
1275     {{t,5},1},
1276     {{t,6},0},
1277     {{t,7},1},
1278     {{t,9},2}] =
1279    analyse_expr(<<"case two() of\n" % 1
1280                   "     1 -> 2;\n" % 0
1281                   "    _  -> begin 3 end\n" % 1
1282                   "              +\n" % 1
1283                   "          begin 4 end end, case two() of\n" % 1
1284                   "                               1 -> a;\n" % 0
1285                   "                               2 -> b; 3 -> c\n" % 1
1286                   "                           end.\n"
1287                   "two() -> 2">>, Cf), % 2
1288
1289    [{{t,1},1}, {{t,2},1}, {{t,3},1},
1290     {{t,4},1}, {{t,5},1}, {{t,6},0}] =
1291    analyse_expr(<<"    self() ! 1,\n"
1292                   "    receive \n"
1293                   "        X=1 -> a;\n"
1294                   "        X=2 -> b end, case X of \n"
1295                   "                          1 -> a;\n"
1296                   "                          2 -> b\n"
1297                   "                      end">>, Cf),
1298
1299    T0 = <<"t1(X) ->\n "
1300           "case X of\n"
1301           "  1 -> A=a,B=A,B; % bump Li\n"
1302           "  2 -> b; 3 -> case X of % 2 -> b shall bump Li\n"
1303           "                  3 -> a; % bump Li\n"
1304           "                  2 -> b end; 4 -> d end, case X of  % Li\n"
1305           "                                            1 -> a;\n"
1306           "                                            2 -> b; 3 -> c;\n"
1307           "                                            4 -> d\n"
1308           "                                          end">>,
1309
1310    T1 = [<<"a = t1(1). ">>,T0],
1311    [{{t,1},1}, {{t,2},1}, {{t,3},1}, {{t,4},0},
1312     {{t,5},0}, {{t,6},1}, {{t,7},1}, {{t,8},0}, {{t,9},0}] =
1313      analyse_expr(T1, Cf),
1314
1315    T2 = [<<"b = t1(2). ">>,T0],
1316    [{{t,1},1}, {{t,2},1}, {{t,3},0}, {{t,4},1},
1317     {{t,5},0}, {{t,6},1}, {{t,7},0}, {{t,8},1}, {{t,9},0}] =
1318      analyse_expr(T2, Cf),
1319
1320    T3 = [<<"c = t1(3). ">>,T0],
1321    [{{t,1},1}, {{t,2},1}, {{t,3},0}, {{t,4},1},
1322     {{t,5},1}, {{t,6},1}, {{t,7},0}, {{t,8},1}, {{t,9},0}] =
1323      analyse_expr(T3, Cf),
1324
1325    T4 = [<<"d = t1(4). ">>,T0],
1326    [{{t,1},1}, {{t,2},1}, {{t,3},0}, {{t,4},0},
1327     {{t,5},0}, {{t,6},1}, {{t,7},0}, {{t,8},0}, {{t,9},1}] =
1328      analyse_expr(T4, Cf),
1329
1330    [{{t,1},1},{{t,2},1},{{t,3},1},{{t,4},1},{{t,5},1}] =
1331      analyse_expr(
1332        <<"2 = x3(1). "
1333          "x3(X) ->\n"
1334          "    case X of \n"
1335          "        1 -> case X of\n"
1336          "                 1 -> a, Y = 2;\n"
1337          "                 2 -> b, Y = 3 end, Y; 2 -> Y = 4 end, Y">>, Cf),
1338
1339    [{{t,1},1},{{t,2},1},{{t,3},1},{{t,4},1}] =
1340    analyse_expr(
1341      <<"1 = x4(1). "
1342        "x4(X) ->\n"
1343        "  case X of\n"
1344        "    1 -> case X of\n"
1345        "           1 -> Y = 1 end, case X of 1 -> Y = 1 end, Y end">>,
1346      Cf),
1347
1348    T10 = <<"t1(X) ->\n"
1349            "if\n"
1350            "  X =:= 1 -> a;\n"
1351            "  X =:= 2 -> b; X =:= 3 -> c end, case X of \n"
1352            "                        1 -> a;\n"
1353            "                        2 -> b; 3 -> c end, case X of\n"
1354            "                                              1 -> a;\n"
1355            "                                              2 -> b; 3 -> c\n"
1356            "                                            end">>,
1357    T11 = [<<"a = t1(1). ">>,T10],
1358    [{{t,1},1}, {{t,2},1}, {{t,3},1}, {{t,4},1},
1359     {{t,5},1}, {{t,6},1}, {{t,7},1}, {{t,8},0}] = analyse_expr(T11, Cf),
1360
1361    T12 = [<<"b = t1(2). ">>,T10],
1362    [{{t,1},1}, {{t,2},1}, {{t,3},0}, {{t,4},1},
1363     {{t,5},0}, {{t,6},1}, {{t,7},0}, {{t,8},1}] = analyse_expr(T12, Cf),
1364
1365    T13 = [<<"c = t1(3). ">>,T10],
1366    [{{t,1},1}, {{t,2},1}, {{t,3},0}, {{t,4},1},
1367     {{t,5},0}, {{t,6},1}, {{t,7},0}, {{t,8},1}] = analyse_expr(T13, Cf),
1368
1369    T20 = <<"t1(X) ->\n"
1370            "case X of\n"
1371            "        1 -> a;\n"
1372            "        2 -> b; 3 -> case X of\n"
1373            "                         1 -> a;\n"
1374            "                         2 -> b; 3 -> c end end, case X of\n"
1375            "                                             1 -> a;\n"
1376            "                                             2 -> b; 3 -> c\n"
1377            "                                         end">>,
1378
1379    T21 = [<<"a = t1(1). ">>,T20],
1380    [{{t,1},1}, {{t,2},1}, {{t,3},1}, {{t,4},0},
1381     {{t,5},0}, {{t,6},1}, {{t,7},1}, {{t,8},0}] = analyse_expr(T21, Cf),
1382
1383    T22 = [<<"b = t1(2). ">>,T20],
1384    [{{t,1},1}, {{t,2},1}, {{t,3},0}, {{t,4},1},
1385     {{t,5},0}, {{t,6},1}, {{t,7},0}, {{t,8},1}] = analyse_expr(T22, Cf),
1386
1387    T23 = [<<"c = t1(3). ">>,T20],
1388    [{{t,1},1}, {{t,2},1}, {{t,3},0}, {{t,4},1},
1389     {{t,5},0}, {{t,6},1}, {{t,7},0}, {{t,8},1}] = analyse_expr(T23, Cf),
1390
1391    T30 = <<
1392            "t1(X) ->\n"
1393            "case X of\n"
1394            " 1 -> a;\n"
1395            " 2 -> b; 3 -> case X of 1 -> a; 2 -> b; 3 -> c end end, case X of\n"
1396            "                                                 1 -> a;\n"
1397            "                                                 2 -> b; 3 -> c\n"
1398            "                                                end\n">>,
1399
1400    T31 = [<<"a = t1(1). ">>,T30],
1401    [{{t,1},1}, {{t,2},1}, {{t,3},1},
1402     {{t,4},1}, {{t,5},1}, {{t,6},0}] = analyse_expr(T31, Cf),
1403
1404    T32 = [<<"b = t1(2). ">>,T30],
1405    [{{t,1},1}, {{t,2},1}, {{t,3},0},
1406     {{t,4},1}, {{t,5},0}, {{t,6},1}] = analyse_expr(T32, Cf),
1407
1408    T33 = [<<"c = t1(3). ">>,T30],
1409    [{{t,1},1}, {{t,2},1}, {{t,3},0},
1410     {{t,4},1}, {{t,5},0}, {{t,6},1}] = analyse_expr(T33, Cf),
1411
1412    %% 'try' now traverses the body as a body...
1413    [{{t,1},1},{{t,2},1},{{t,3},1},{{t,4},0},{{t,6},1}] =
1414    analyse_expr(<<"try \n"
1415                   "    B = 2, \n"
1416                   "    C = erlang:error(foo), \n"
1417                   "    {B,C} \n"
1418                   "catch _:_ -> \n"
1419                   "    foo \n"
1420                   "end">>, Cf),
1421
1422    %% receive after:
1423    [{{t,1},1},{{t,2},0},{{t,3},1}] =
1424    analyse_expr(<<"receive \n"
1425                   "    X=1 -> a; \n"
1426                   "    X=2 -> b after begin 10 end -> X=3 end">>, Cf),
1427    [{{t,1},1},{{t,2},0},{{t,3},1}] =
1428    analyse_expr(<<"receive \n"
1429                   "    X=1 -> a; \n"
1430                   "    X=2 -> b after 10 -> begin X=3 end end">>, Cf),
1431    ok.
1432
1433comprehension_8188(Cf) ->
1434    [{{t,1},1}] = analyse_expr(<<"[begin X end || X <- [1,2,3], X > 1]">>, Cf),
1435    [{{t,1},1},{{t,2},1}] = analyse_expr(<<"[begin X end || \n"
1436                                           "    X <- [1,2,3], X > 1]">>, Cf),
1437    [{{t,1},1},{{t,2},1},{{t,3},3}] = analyse_expr(<<"[begin X end || \n "
1438                                                     "    X <- [1,2,3], \n "
1439                                                     "    X > 1]">>, Cf),
1440    [{{t,1},1},{{t,3},1},{{t,4},3}] = analyse_expr(<<"[begin X end || \n "
1441                                                     "    X <- \n "
1442                                                     "        [1,2,3], \n "
1443                                                     "    X > 1]">>, Cf),
1444    [{{t,1},1},{{t,2},2}] = analyse_expr(<<"[  \n "
1445                                           "   X || X <- [1,2,3], X > 1]">>, Cf),
1446    [{{t,1},1},{{t,2},2},{{t,3},3}] = analyse_expr(<<"[ \n"
1447                                                     "  X || X <- [1,2,3], \n"
1448                                                     "  X > 1]">>, Cf),
1449    [{{t,1},1},{{t,2},1},{{t,3},2}] = analyse_expr(<<"[ \n "
1450                                                     "   X || X <- [1,2,3], X > 1, \n"
1451                                                     "   X > 2]">>, Cf),
1452
1453    [{{t,1},1},
1454     {{t,3},2},
1455     {{t,5},1},
1456     {{t,7},1},
1457     {{t,8},0},
1458     {{t,12},3},
1459     {{t,15},2},
1460     {{t,17},2},
1461     {{t,18},1}] = analyse_expr(<<"[ \n" % 1
1462                                  "  begin\n"
1463                                  "      X * 2\n" % 2
1464                                  "  end ||\n"
1465                                  "    X <- [1,\n" % 1
1466                                  "          case two() of\n"
1467                                  "              2 -> 2;\n" % 1
1468                                  "              _ -> two\n" % 0
1469                                  "          end,\n"
1470                                  "          3],\n"
1471                                  "    begin\n"
1472                                  "        math:sqrt(X) > 1.0\n" % 3
1473                                  "    end,\n"
1474                                  "    begin\n"
1475                                  "        true\n" % 2
1476                                  "    end,\n"
1477                                  "    true]. \n" % 2
1478                                  "  two() -> 2">>, Cf), % 1
1479
1480    [{{t,1},1},
1481     {{t,2},2},
1482     {{t,3},1},
1483     {{t,5},1},
1484     {{t,6},0},
1485     {{t,9},3},
1486     {{t,10},2},
1487     {{t,11},2},
1488     {{t,12},1}] = analyse_expr(<<"[ \n"
1489                                  "      X * 2 || \n" % 2
1490                                  "    X <- [1,\n" % 1
1491                                  "          case two() of\n"
1492                                  "              2 -> 2;\n" % 1
1493                                  "              _ -> two\n" % 0
1494                                  "          end,\n"
1495                                  "          3],\n"
1496                                  "    math:sqrt(X) > 1.0,\n" % 3
1497                                  "    true,\n" % 2
1498                                  "    true]. \n" % 2
1499                                  "  two() -> 2">>, Cf), % 1
1500
1501    [{{t,1},1},
1502     {{t,2},2},
1503     {{t,3},1},
1504     {{t,4},1},
1505     {{t,5},0},
1506     {{t,8},1},
1507     {{t,9},0},
1508     {{t,12},3},
1509     {{t,13},2},
1510     {{t,14},2}] = analyse_expr(<<"<< \n" % 1
1511                                  " << (X*2) >> || \n" % 2
1512                                  "    <<X>> <= << (case two() of\n"
1513                                  "                     2 -> 1;\n" % 1
1514                                  "                     _ -> 2\n" % 0
1515                                  "                 end)/integer,\n"
1516                                  "                (case two() of \n"
1517                                  "                    2 -> 2;\n" % 1
1518                                  "                    _ -> two\n" % 0
1519                                  "                 end)/integer,\n"
1520                                  "                3 >>, \n"
1521                                  "    math:sqrt(X) > 1.0,\n" % 3
1522                                  "    true >>.\n" % 2
1523                                  "two() -> 2">>, Cf),
1524    [{{t,1},1},
1525     {{t,2},4},
1526     {{t,4},1},
1527     {{t,6},1},
1528     {{t,7},0},
1529     {{t,10},3},
1530     {{t,11},2},
1531     {{t,12},4},
1532     {{t,13},1}] = analyse_expr(<<"<< \n" % 1
1533                                  " << (2)\n" % 4
1534                                  "     :(8) >> || \n"
1535                                  "    <<X>> <= << 1,\n" % 1
1536                                  "                (case two() of \n"
1537                                  "                    2 -> 2;\n" % 1
1538                                  "                    _ -> two\n" % 0
1539                                  "                 end)/integer,\n"
1540                                  "                3 >>, \n"
1541                                  "    math:sqrt(X) > 1.0,\n" % 3
1542                                  "    <<_>> <= << 1, 2 >>,\n" % 2
1543                                  "    true >>.\n" % 4
1544                                  "two() -> 2">>, Cf), % 1
1545    ok.
1546
1547eep37(Config) when is_list(Config) ->
1548    [{{t,1},1},{{t,2},1},{{t,4},6},{{t,6},1},{{t,8},1}] =
1549    analyse_expr(<<"begin\n" % 1
1550                   "    F =\n" % 1
1551                   "        fun Fact(N) when N > 0 ->\n"
1552                   "                N * Fact(N - 1);\n" % 6
1553                   "            Fact(0) ->\n"
1554                   "                1\n" % 1
1555                   "        end,\n"
1556                   "    F(6)\n" % 1
1557                   "end\n">>,
1558                 Config),
1559    ok.
1560
1561otp_10979_hanging_node(_Config) ->
1562
1563    P1 = processes(),
1564
1565    cover:stop(non_existing_node),
1566    cover:stop(),
1567
1568    P2 = processes(),
1569
1570    case P2--P1 of
1571        [] ->
1572            ok;
1573        New ->
1574            [io:format("New: ~p, ~p~n",[P,process_info(P)]) || P<-New],
1575            ct:fail(hanging_process)
1576    end,
1577
1578    ok.
1579
1580otp_14817(Config) when is_list(Config) ->
1581    Test = <<"-module(otp_14817).
1582              -export([a/0, b/0, c/0, d/0]).
1583              a() -> ok. b() -> ok. c() -> ok.
1584              d() -> ok.
1585             ">>,
1586    File = cc_mod(otp_14817, Test, Config),
1587    ok = otp_14817:a(),
1588    ok = otp_14817:b(),
1589    ok = otp_14817:c(),
1590    ok = otp_14817:d(),
1591    {ok,[{{otp_14817,3},1},
1592         {{otp_14817,3},1},
1593         {{otp_14817,3},1},
1594         {{otp_14817,4},1}]} =
1595        cover:analyse(otp_14817, calls, line),
1596    {ok, CovOut} = cover:analyse_to_file(otp_14817),
1597    {ok, Bin} = file:read_file(CovOut),
1598    <<"3..|",_/binary>> = string:find(Bin, "3..|"),
1599    <<"1..|",_/binary>> = string:find(Bin, "1..|"),
1600    ok = file:delete(File),
1601    ok = file:delete(CovOut),
1602    ok.
1603
1604%% Tests a bug where cover failed for an export named clauses
1605cover_clauses(Config) when is_list(Config) ->
1606    Test = <<"-module(cover_clauses).
1607              -export([clauses/0]).
1608              clauses() -> ok.
1609             ">>,
1610    File = cc_mod(cover_clauses, Test, Config),
1611    ok.
1612
1613%% Take compiler options from beam in cover:compile_beam
1614compile_beam_opts(Config) when is_list(Config) ->
1615    {ok, Cwd} = file:get_cwd(),
1616    ok = file:set_cwd(proplists:get_value(priv_dir, Config)),
1617    IncDir = filename:join(proplists:get_value(data_dir, Config),
1618                           "included_functions"),
1619    File = filename:join([proplists:get_value(data_dir, Config), "otp_11439", "t.erl"]),
1620    %% use all compiler options allowed by cover:filter_options
1621    %% i and d don't make sense when compiling from beam though
1622    {ok, t} =
1623    compile:file(File, [{i, IncDir},
1624                        {d, 'BOOL'},
1625                        {d, 'MACRO', macro_defined},
1626                        export_all,
1627                        debug_info,
1628                        return_errors]),
1629    code:purge(t),
1630    code:delete(t),
1631    Exports =
1632    [{func1,0},
1633     {macro, 0},
1634     {exported,0},
1635     {nonexported,0},
1636     {module_info,0},
1637     {module_info,1}],
1638    Exports = t:module_info(exports),
1639    {ok, t} = cover:compile_beam("t"),
1640    Exports = t:module_info(exports),
1641    ok = file:delete("t.beam"),
1642    ok = file:set_cwd(Cwd),
1643    ok.
1644
1645%% Don't crash if beam is not available
1646analyse_no_beam(Config) when is_list(Config) ->
1647    {ok, Cwd} = file:get_cwd(),
1648    ok = file:set_cwd(proplists:get_value(data_dir, Config)),
1649
1650    code:purge(t),
1651    code:delete(t),
1652
1653    {ok,_} = file:copy("compile_beam/t.erl", "t.erl"),
1654    {ok,t} = compile:file(t, [debug_info]),
1655    {module,t} = code:load_file(t),
1656    {ok,t} = cover:compile_beam(t),
1657    t:f(),
1658    ok = cover:export("t.coverdata"),
1659
1660    code:purge(t),
1661    code:delete(t),
1662
1663    %% this is just so that cover realises (without stopping)
1664    %% that this module is not cover compiled any more
1665    {error, {not_cover_compiled,t}} = cover:analyse(t),
1666
1667    %% source and beam not available any more
1668    ok = file:delete("t.erl"),
1669    ok = file:delete("t.beam"),
1670
1671    ok = cover:import("t.coverdata"),
1672
1673    {error,{no_source_code_found,t}} = cover:analyse_to_file(t),
1674    {result,[],[{no_source_code_found,t}]} = cover:analyse_to_file([t]),
1675
1676    ok = file:delete("t.coverdata"),
1677    ok = file:set_cwd(Cwd),
1678    ok.
1679
1680%% When including eunit.hrl, a parse transform adds the function
1681%% test/0 to line 0 in your module. A bug in OTP-18.0 caused
1682%% cover:analyse_to_file/1 to fail to insert cover data in the output
1683%% file in this situation. The test below tests that this bug is
1684%% corrected.
1685line_0(Config) ->
1686    ok = file:set_cwd(filename:join(proplists:get_value(data_dir, Config),
1687                                    "include_eunit_hrl")),
1688    {ok, cover_inc_eunit} = compile:file(cover_inc_eunit,[debug_info]),
1689    {ok, cover_inc_eunit} = cover:compile_beam(cover_inc_eunit),
1690    {ok, CovOut} = cover:analyse_to_file(cover_inc_eunit),
1691
1692    {ok,Bin} = file:read_file(CovOut),
1693    Match = <<"0..|      ok.\n">>,  % "0.." is missing when bug is there
1694    S = byte_size(Bin)-byte_size(Match),
1695    <<_:S/binary,Match/binary>> = Bin,
1696    ok.
1697
1698
1699%% OTP-13200: Return error instead of crashing when trying to compile
1700%% a beam which has no 'file' attribute.
1701compile_beam_no_file(Config) ->
1702    PrivDir = proplists:get_value(priv_dir,Config),
1703    Dir = filename:join(PrivDir,"compile_beam_no_file"),
1704    ok = filelib:ensure_dir(filename:join(Dir,"*")),
1705    code:add_patha(Dir),
1706    Str = lists:concat(
1707            ["-module(nofile).\n"
1708             "-compile(export_all).\n"
1709             "foo() -> ok.\n"]),
1710    TT = do_scan(Str),
1711    Forms = [ begin {ok,Y} = erl_parse:parse_form(X),Y end || X <- TT ],
1712    {ok,_,Bin} = compile:forms(Forms,[debug_info]),
1713    BeamFile = filename:join(Dir,"nofile.beam"),
1714    ok = file:write_file(BeamFile,Bin),
1715    {error,{no_file_attribute,BeamFile}} = cover:compile_beam(nofile),
1716    [{error,{no_file_attribute,BeamFile}}] = cover:compile_beam_directory(Dir),
1717    ok.
1718
1719%% GH-4353: Don't crash when the backend for generating the abstract code
1720%% is missing.
1721compile_beam_missing_backend(Config) ->
1722    PrivDir = proplists:get_value(priv_dir, Config),
1723    Dir = filename:join(PrivDir, ?FUNCTION_NAME),
1724    ok = filelib:ensure_dir(filename:join(Dir, "*")),
1725    code:add_patha(Dir),
1726    Str = lists:append(
1727            ["-module(no_backend).\n"
1728             "-compile(export_all).\n"
1729             "foo() -> ok.\n"]),
1730    TT = do_scan(Str),
1731    Forms = [ begin {ok,Y} = erl_parse:parse_form(X),Y end || X <- TT ],
1732    {ok,_,Bin} = compile:forms(Forms, [debug_info]),
1733
1734    %% Create a debug_info chunk with a non-existing backend.
1735    {ok,no_backend,All0} = beam_lib:all_chunks(Bin),
1736    FakeBackend = definitely__not__an__existing__backend,
1737    FakeDebugInfo = {debug_info_v1,FakeBackend,nothing_here},
1738    All = lists:keyreplace("Dbgi", 1, All0, {"Dbgi", term_to_binary(FakeDebugInfo)}),
1739    {ok,NewBeam} = beam_lib:build_module(All),
1740    BeamFile = filename:join(Dir, "no_backend.beam"),
1741    ok = file:write_file(BeamFile, NewBeam),
1742
1743    {error,{{missing_backend,FakeBackend},BeamFile}} = cover:compile_beam(no_backend),
1744    [{error,{{missing_backend,FakeBackend},BeamFile}}] = cover:compile_beam_directory(Dir),
1745
1746    ok.
1747
1748do_scan([]) ->
1749    [];
1750do_scan(Str) ->
1751    {done,{ok,T,_},C} = erl_scan:tokens([],Str,0),
1752    [ T | do_scan(C) ].
1753
1754
1755%% PR 856. Fix a bc bug.
1756otp_13277(Config) ->
1757    Test = <<"-module(t).
1758              -export([t/0]).
1759
1760              pad(A, L) ->
1761                  P = << <<\"#\">> || _ <- lists:seq(1, L) >>,
1762                  <<A/binary, P/binary>>.
1763
1764              t() ->
1765                  pad(<<\"hi\">>, 2).
1766             ">>,
1767    File = cc_mod(t, Test, Config),
1768    <<"hi##">> = t:t(),
1769    ok = file:delete(File),
1770    ok.
1771
1772%% Test general expressions in a binary comprehension.
1773otp_13289(Config) ->
1774    Test = <<"-module(t).
1775              -export([t/0]).
1776
1777              t() ->
1778                  << (id(<<I>>)) || I <- [1,2,3] >>.
1779
1780              id(I) -> I.
1781             ">>,
1782    File = cc_mod(t, Test, Config),
1783    <<1,2,3>> = t:t(),
1784    ok = file:delete(File),
1785    ok.
1786
1787local_only(Config) ->
1788    ok = file:set_cwd(proplists:get_value(data_dir, Config)),
1789
1790    %% Trying restricting to local nodes too late.
1791    cover:start(),
1792    {ok,a} = cover:compile(a),
1793    [a] = cover:modules(),
1794    {error,too_late} = cover:local_only(),
1795    cover:stop(),
1796
1797    %% Now test local only mode.
1798    cover:start(),
1799    ok = cover:local_only(),
1800    [] = cover:modules(),
1801    {ok,a} = cover:compile(a),
1802    [a] = cover:modules(),
1803    done = a:start(5),
1804    {ok, {a,{17,2}}} = cover:analyse(a, coverage, module),
1805    {ok, [{{a,exit_kalle,0},{1,0}},
1806          {{a,loop,3},{5,1}},
1807          {{a,pong,1},{1,0}},
1808          {{a,start,1},{6,0}},
1809          {{a,stop,1},{0,1}},
1810          {{a,trycatch,1},{4,0}}]} =
1811        cover:analyse(a, coverage, function),
1812
1813    %% Make sure that it is not possible to run cover on
1814    %% slave nodes.
1815    {ok,Name} = test_server:start_node(?FUNCTION_NAME, slave, []),
1816    {error,local_only} = cover:start([Name]),
1817    test_server:stop_node(Name),
1818    ok.
1819
1820%% ERL-943; We should not crash on startup when multiple servers race to
1821%% register the server name.
1822startup_race(Config) when is_list(Config) ->
1823    PidRefs = [spawn_monitor(fun() ->
1824                                     case cover:start() of
1825                                         {error, {already_started, _Pid}} ->
1826                                             ok;
1827                                         {ok, _Pid} ->
1828                                             ok
1829                                     end
1830                             end) || _<- lists:seq(1,8)],
1831    startup_race_1(PidRefs).
1832
1833startup_race_1([{Pid, Ref} | PidRefs]) ->
1834    receive
1835        {'DOWN', Ref, process, Pid, normal} ->
1836            startup_race_1(PidRefs);
1837        {'DOWN', Ref, process, Pid, _Other} ->
1838            ct:fail("Cover server crashed on startup.")
1839    after 5000 ->
1840            ct:fail("Timed out.")
1841    end;
1842startup_race_1([]) ->
1843    cover:stop(),
1844    ok.
1845
1846otp_16476(Config) when is_list(Config) ->
1847    Mod = obvious_booleans,
1848    Dir = filename:join(proplists:get_value(data_dir, Config),
1849                        ?FUNCTION_NAME),
1850    ok = file:set_cwd(Dir),
1851    {ok, Mod} = compile:file(Mod, [debug_info]),
1852    {ok, Mod} = cover:compile(Mod),
1853    ok = Mod:Mod(),
1854    ok = cover:stop(),
1855    ok.
1856
1857%%--Auxiliary------------------------------------------------------------
1858
1859analyse_expr(Expr, Config) ->
1860    Binary = [<<"-module(t). "
1861                "-export([t/0]). "
1862                "t() -> ">>, Expr, <<".\n">>],
1863    File = cc_mod(t, Binary, Config),
1864    t:t(),
1865    {ok, Result} = cover:analyse(t, calls, line),
1866    ok = file:delete(File),
1867    Result.
1868
1869cc_mod(M, Binary, Config) ->
1870    {ok, Dir} = file:get_cwd(),
1871    PrivDir = proplists:get_value(priv_dir, Config),
1872    ok = file:set_cwd(PrivDir),
1873    File = atom_to_list(M) ++ ".erl",
1874    try
1875        ok = file:write_file(File, Binary),
1876        {ok, M} = cover:compile(File),
1877        filename:join(PrivDir, File)
1878    after file:set_cwd(Dir)
1879    end.
1880
1881c_mod(M, Binary, Config) ->
1882    {ok, Dir} = file:get_cwd(),
1883    PrivDir = proplists:get_value(priv_dir, Config),
1884    ok = file:set_cwd(PrivDir),
1885    File = atom_to_list(M) ++ ".erl",
1886    try
1887        ok = file:write_file(File, Binary),
1888        {ok, M} = compile:file(File, [debug_info]),
1889        code:purge(M),
1890        AbsFile = filename:rootname(File, ".erl"),
1891        code:load_abs(AbsFile, M),
1892        filename:join(PrivDir, File)
1893    after file:set_cwd(Dir)
1894    end.
1895
1896lsfiles() ->
1897    {ok, CWD} = file:get_cwd(),
1898    lsfiles(CWD).
1899
1900lsfiles(Dir) ->
1901    {ok, Files} = file:list_dir(Dir),
1902    Files.
1903
1904files(Files, Ext) ->
1905    lists:filter(fun(File) ->
1906                         case filename:extension(File) of
1907                             Ext -> true;
1908                             _ -> false
1909                         end
1910                 end,
1911                 Files).
1912
1913remove([File|Files]) ->
1914    ok = file:delete(File),
1915    remove(Files);
1916remove([]) ->
1917    ok.
1918
1919decompile([Mod|Mods]) ->
1920    code:purge(Mod),
1921    code:delete(Mod),
1922    decompile(Mods);
1923decompile([]) ->
1924    ok.
1925
1926is_unloaded(What) ->
1927    if
1928        is_list(What) -> true;
1929        What==non_existing -> true;
1930        true -> false
1931    end.
1932
1933check_f_calls(F1,F2) ->
1934    {ok,A} = cover:analyse(f,calls,function),
1935    {_,F1} = lists:keyfind({f,f1,0},1,A),
1936    {_,F2} = lists:keyfind({f,f2,0},1,A).
1937
1938cover_which_nodes(Expected) ->
1939    case cover:which_nodes() of
1940        Expected ->
1941            ok;
1942        Other ->
1943            {Time,ok} = timer:tc(fun Retry() ->
1944                                         case cover:which_nodes() of
1945                                             Expected -> ok;
1946                                             _ ->
1947                                                 timer:sleep(100),
1948                                                 Retry()
1949                                         end
1950    end),
1951            io:format("~p ms before cover:which_nodes() returned ~p",
1952                      [Time,Expected]),
1953            Expected = Other
1954    end.
1955