@@ -359,21 +359,22 @@ analyze_coverage(_, _) ->
359
359
360
360
prepare (Props ) ->
361
361
Nodes = get_mongoose_nodes (Props ),
362
- maybe_compile_cover (Nodes ).
362
+ maybe_compile_cover (Nodes ),
363
+ block_nodes (Props ).
363
364
364
365
maybe_compile_cover ([]) ->
365
366
io :format (" cover: skip cover compilation~n " , []),
366
367
ok ;
367
- maybe_compile_cover (Nodes ) ->
368
+ maybe_compile_cover ([ CoverNode | _ ] = Nodes ) ->
368
369
io :format (" cover: compiling modules for nodes ~p~n " , [Nodes ]),
369
370
import_code_paths (hd (Nodes )),
370
371
371
- cover : start ( Nodes ),
372
+ cover_start ( CoverNode , Nodes ),
372
373
Dir = call (hd (Nodes ), code , lib_dir , [mongooseim , ebin ]),
373
374
374
375
% % Time is in microseconds
375
376
{Time , Compiled } = timer :tc (fun () ->
376
- Results = cover : compile_beam_directory ( Dir ),
377
+ Results = cover_compile_dir ( CoverNode , Dir ),
377
378
Ok = [X || X = {ok , _ } <- Results ],
378
379
NotOk = Results -- Ok ,
379
380
#{ok => length (Ok ), failed => NotOk }
@@ -385,26 +386,26 @@ maybe_compile_cover(Nodes) ->
385
386
ok .
386
387
387
388
analyze (Props , CoverOpts ) ->
389
+ unblock_nodes (Props ),
388
390
io :format (" Coverage analyzing~n " ),
389
391
Nodes = get_mongoose_nodes (Props ),
390
392
analyze (Props , CoverOpts , Nodes ).
391
393
392
394
analyze (_Props , _CoverOpts , []) ->
393
395
ok ;
394
- analyze (_Props , CoverOpts , Nodes ) ->
395
- deduplicate_cover_server_console_prints (),
396
+ analyze (_Props , CoverOpts , [CoverNode |_ ] = Nodes ) ->
396
397
% % Import small tests cover
397
398
Files = filelib :wildcard (repo_dir () ++ " /_build/**/cover/*.coverdata" ),
398
399
io :format (" Files: ~p " , [Files ]),
399
400
report_time (" Import cover data into run_common_test node" , fun () ->
400
- [cover : import ( File ) || File <- Files ]
401
+ [cover_import ( CoverNode , File ) || File <- Files ]
401
402
end ),
402
403
report_time (" Export merged cover data" , fun () ->
403
- cover : export ( " /tmp/mongoose_combined.coverdata" )
404
+ cover_export ( CoverNode , " /tmp/mongoose_combined.coverdata" )
404
405
end ),
405
406
case os :getenv (" GITHUB_RUN_ID" ) of
406
407
false ->
407
- make_html (modules_to_analyze (CoverOpts ));
408
+ make_html (CoverNode , modules_to_analyze (CoverNode , CoverOpts ));
408
409
_ ->
409
410
ok
410
411
end ,
@@ -414,11 +415,11 @@ analyze(_Props, CoverOpts, Nodes) ->
414
415
ok ;
415
416
_ ->
416
417
report_time (" Stopping cover on MongooseIM nodes" , fun () ->
417
- cover : stop ([ node ()| Nodes ] )
418
+ cover_stop ( CoverNode , Nodes )
418
419
end )
419
420
end .
420
421
421
- make_html (Modules ) ->
422
+ make_html (CoverNode , Modules ) ->
422
423
{ok , Root } = file :get_cwd (),
423
424
SortScript = Root ++ " /priv/sorttable.js" ,
424
425
os :cmd (" cp " ++ SortScript ++ " " ++ ? CT_REPORT ),
@@ -437,11 +438,11 @@ make_html(Modules) ->
437
438
FileName = lists :flatten (io_lib :format (" ~s .COVER.html" ,[Module ])),
438
439
439
440
% % We assume that import_code_paths/1 was called earlier
440
- case cover : analyse ( Module , module ) of
441
+ case cover_analyse ( CoverNode , Module ) of
441
442
{ok , {Module , {C , NC }}} ->
442
443
file :write (File , row (atom_to_list (Module ), C , NC , percent (C ,NC )," coverage/" ++ FileName )),
443
444
FilePathC = filename :join ([CoverageDir , FileName ]),
444
- catch cover : analyse_to_file ( Module , FilePathC , [ html ] ),
445
+ cover_analyse_to_html_file ( CoverNode , Module , FilePathC ),
445
446
{CAcc + C , NCAcc + NC };
446
447
Reason ->
447
448
error_logger :error_msg (" issue=cover_analyse_failed module=~p reason=~p " ,
@@ -503,9 +504,9 @@ module_list(undefined) ->
503
504
module_list (ModuleList ) ->
504
505
[ list_to_atom (L ) || L <- string :tokens (ModuleList , " , " ) ].
505
506
506
- modules_to_analyze (true ) ->
507
- lists :usort (cover : imported_modules () ++ cover : modules ( ));
508
- modules_to_analyze (ModuleList ) when is_list (ModuleList ) ->
507
+ modules_to_analyze (CoverNode , true ) ->
508
+ lists :usort (cover_all_modules ( CoverNode ));
509
+ modules_to_analyze (_CoverNode , ModuleList ) when is_list (ModuleList ) ->
509
510
ModuleList .
510
511
511
512
add ({X1 , X2 , X3 , X4 },
@@ -581,6 +582,9 @@ host_param(Name, {_, Params}) ->
581
582
{Name , Param } = lists :keyfind (Name , 1 , Params ),
582
583
Param .
583
584
585
+ host_param (Name , {_ , Params }, Default ) ->
586
+ proplists :get_value (Name , Params , Default ).
587
+
584
588
report_time (Description , Fun ) ->
585
589
report_progress (" ~n Executing ~ts~n " , [Description ]),
586
590
Start = os :timestamp (),
@@ -630,16 +634,6 @@ handle_file_error(_FileName, Other) ->
630
634
631
635
% % ------------------------------------------------------------------
632
636
633
- % % cover_server process is using io:format too much.
634
- % % This code removes duplicate io:formats.
635
- % %
636
- % % Example of a message we want to write only once:
637
- % % "Analysis includes data from imported files" from cover.erl in Erlang/R19
638
- deduplicate_cover_server_console_prints () ->
639
- % % Set a new group leader for cover_server
640
- CoverPid = whereis (cover_server ),
641
- dedup_proxy_group_leader :start_proxy_group_leader_for (CoverPid ).
642
-
643
637
ct_run_dirs () ->
644
638
filelib :wildcard (" ct_report/ct_run*" ).
645
639
@@ -721,3 +715,91 @@ assert_preset_present(Preset, PresetConfs) ->
721
715
error_logger :error_msg (" Preset not found ~p~n " , [Preset ]),
722
716
error ({preset_not_found , Preset })
723
717
end .
718
+
719
+ assert_list (X ) when is_list (X ) -> X .
720
+
721
+ % % We use mim1 as a main node.
722
+ % % Only the main node supports meck
723
+ % % (other nodes should not use meck for the cover compiled modules).
724
+ cover_start (CoverNode , Nodes ) ->
725
+ {ok , _ } = cover_call (CoverNode , start , [Nodes ]),
726
+ CoverNode = cover_call (CoverNode , get_main_node , []),
727
+ ok .
728
+
729
+ cover_stop (CoverNode , Nodes ) ->
730
+ cover_call (CoverNode , stop , [Nodes ]).
731
+
732
+ cover_all_modules (CoverNode ) ->
733
+ List1 = assert_list (cover_call (CoverNode , imported_modules , [])),
734
+ List2 = assert_list (cover_call (CoverNode , modules , [])),
735
+ List1 ++ List2 .
736
+
737
+ cover_analyse_to_html_file (CoverNode , Module , FilePathC ) ->
738
+ catch cover_call (CoverNode , analyse_to_file , [Module , FilePathC , [html ]]).
739
+
740
+ cover_analyse (CoverNode , Module ) ->
741
+ cover_call (CoverNode , analyse , [Module , module ]).
742
+
743
+ cover_export (CoverNode , ToFile ) ->
744
+ cover_call (CoverNode , export , [ToFile ]).
745
+
746
+ cover_import (CoverNode , FromFile ) ->
747
+ cover_call (CoverNode , import , [FromFile ]).
748
+
749
+ cover_compile_dir (CoverNode , Dir ) ->
750
+ cover_call (CoverNode , compile_beam_directory , [Dir ]).
751
+
752
+ cover_call (CoverNode , Fun , Args ) ->
753
+ rpc :call (CoverNode , cover , Fun , Args ).
754
+
755
+ block_nodes (Props ) ->
756
+ [block_node (Node , BlockNode , Props ) || {Node , BlockNode } <- block_nodes_specs (Props )],
757
+ ok .
758
+
759
+ unblock_nodes (Props ) ->
760
+ [unblock_node (Node , BlockNode , Props ) || {Node , BlockNode } <- block_nodes_specs (Props )],
761
+ ok .
762
+
763
+ % % Reads `blocks_hosts' parameter for the host from `test.config'.
764
+ % % Returns a list of blocks to do like `[{mim, fed}]'.
765
+ block_nodes_specs (Props ) ->
766
+ EnabledHosts = [ H || H <- get_all_hosts (Props ), is_test_host_enabled (host_name (H )) ],
767
+ [{host_name (H ), BlockName }
768
+ || H <- EnabledHosts , BlockName <- host_param (blocks_hosts , H , []),
769
+ is_test_host_enabled (BlockName )].
770
+
771
+ host_name_to_node (Name , Props ) ->
772
+ Hosts = get_all_hosts (Props ),
773
+ Host = proplists :get_value (Name , Hosts , []),
774
+ case proplists :get_value (node , Host ) of
775
+ undefined ->
776
+ error ({host_name_to_node_failed , Name , Props });
777
+ Node ->
778
+ Node
779
+ end .
780
+
781
+ % % Do not allow node Name to talk to node BlockName
782
+ block_node (Name , BlockName , Props ) ->
783
+ Node = host_name_to_node (Name , Props ),
784
+ BlockNode = host_name_to_node (BlockName , Props ),
785
+ rpc_call (Node , erlang , set_cookie , [BlockNode , make_bad_cookie (Name , BlockNode )]),
786
+ rpc_call (Node , erlang , disconnect_node , [BlockNode ]),
787
+ Cond = fun () -> lists :member (BlockNode , rpc_call (Node , erlang , nodes , [])) end ,
788
+ mongoose_helper :wait_until (Cond , false ).
789
+
790
+ unblock_node (Name , BlockName , Props ) ->
791
+ Node = host_name_to_node (Name , Props ),
792
+ BlockNode = host_name_to_node (BlockName , Props ),
793
+ DefCookie = rpc_call (Node , erlang , get_cookie , []),
794
+ rpc_call (Node , erlang , set_cookie , [BlockNode , DefCookie ]).
795
+
796
+ make_bad_cookie (Name , BlockName ) ->
797
+ list_to_atom (atom_to_list (Name ) ++ " _blocks_" ++ atom_to_list (BlockName )).
798
+
799
+ rpc_call (Node , M , F , Args ) ->
800
+ case rpc :call (Node , M , F , Args ) of
801
+ {badrpc , Reason } ->
802
+ error ({rpc_call_failed , Reason , Node , {M , F , Args }});
803
+ Res ->
804
+ Res
805
+ end .
0 commit comments