From 8179e41007922c059b8f9441f563edf694b8b315 Mon Sep 17 00:00:00 2001
From: Siri Hansen
Date: Fri, 12 Oct 2012 15:49:22 +0200
Subject: [cover] Add support for test_server
OTP-10523
* Added cover:flush(Nodes), which will fetch data from remote nodes
without stopping cover on those nodes.
* Added cover:get_main_node(), which returns the node name of the main
node. This is used by test_server to avoid {error,not_main_node}
when a slave starts another slave (e.g. in test_server's own tests).
---
lib/tools/doc/src/cover.xml | 15 ++++++++++++++-
lib/tools/src/cover.erl | 31 +++++++++++++++++++++++++++++--
lib/tools/test/cover_SUITE.erl | 17 ++++++++++++++++-
3 files changed, 59 insertions(+), 4 deletions(-)
diff --git a/lib/tools/doc/src/cover.xml b/lib/tools/doc/src/cover.xml
index 683acc025d..be0fd5bd47 100644
--- a/lib/tools/doc/src/cover.xml
+++ b/lib/tools/doc/src/cover.xml
@@ -5,7 +5,7 @@
2001
- 2011
+ 2012
Ericsson AB, All Rights Reserved
@@ -104,6 +104,8 @@
remove nodes. The same Cover compiled code will be loaded on each
node, and analysis will collect and sum up coverage data results
from all nodes.
+ To only collect data from remote nodes without stopping
+ cover on those nodes, use cover:flush/1
@@ -477,6 +479,17 @@
remote nodes is fetched and stored on the main node.
+
+ flush(Nodes) -> ok | {error,not_main_node}
+ Collect cover data from remote nodes.
+
+ Nodes = [atom()]
+
+
+ Fetch data from the Cover database on the remote nodes and
+ stored on the main node.
+
+
diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl
index e21bd1b88c..fb65206938 100644
--- a/lib/tools/src/cover.erl
+++ b/lib/tools/src/cover.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -81,8 +81,9 @@
export/1, export/2, import/1,
modules/0, imported/0, imported_modules/0, which_nodes/0, is_compiled/1,
reset/1, reset/0,
+ flush/1,
stop/0, stop/1]).
--export([remote_start/1]).
+-export([remote_start/1,get_main_node/0]).
%-export([bump/5]).
-export([transform/4]). % for test purposes
@@ -497,6 +498,19 @@ stop(Node) when is_atom(Node) ->
stop(Nodes) ->
call({stop,remove_myself(Nodes,[])}).
+%% flush(Nodes) -> ok | {error,not_main_node}
+%% Nodes = [Node] | Node
+%% Node = atom()
+%% Error = {not_cover_compiled,Module}
+flush(Node) when is_atom(Node) ->
+ flush([Node]);
+flush(Nodes) ->
+ call({flush,remove_myself(Nodes,[])}).
+
+%% Used by test_server only. Not documented.
+get_main_node() ->
+ call(get_main_node).
+
%% bump(Module, Function, Arity, Clause, Line)
%% Module = Function = atom()
%% Arity = Clause = Line = integer()
@@ -710,6 +724,11 @@ main_process_loop(State) ->
State1 = State#main_state{nodes=State#main_state.nodes--Nodes},
main_process_loop(State1);
+ {From, {flush,Nodes}} ->
+ remote_collect('_',Nodes,false),
+ reply(From, ok),
+ main_process_loop(State);
+
{From, stop} ->
lists:foreach(
fun(Node) ->
@@ -796,6 +815,10 @@ main_process_loop(State) ->
State1 = State#main_state{nodes=State#main_state.nodes--[node(Pid)]},
main_process_loop(State1);
+ {From, get_main_node} ->
+ reply(From, node()),
+ main_process_loop(State);
+
get_status ->
io:format("~p~n",[State]),
main_process_loop(State)
@@ -852,6 +875,10 @@ remote_process_loop(State) ->
unregister(?SERVER),
remote_reply(State#remote_state.main_node, ok);
+ {From, get_main_node} ->
+ reply(From, State#remote_state.main_node),
+ remote_process_loop(State);
+
get_status ->
io:format("~p~n",[State]),
remote_process_loop(State);
diff --git a/lib/tools/test/cover_SUITE.erl b/lib/tools/test/cover_SUITE.erl
index c2c708d806..950c4ddbcb 100644
--- a/lib/tools/test/cover_SUITE.erl
+++ b/lib/tools/test/cover_SUITE.erl
@@ -326,14 +326,16 @@ distribution(Config) when is_list(Config) ->
?line {ok,N1} = ?t:start_node(cover_SUITE_distribution1,slave,[]),
?line {ok,N2} = ?t:start_node(cover_SUITE_distribution2,slave,[]),
?line {ok,N3} = ?t:start_node(cover_SUITE_distribution3,slave,[]),
+ ?line {ok,N4} = ?t:start_node(cover_SUITE_distribution4,slave,[]),
%% Check that an already compiled module is loaded on new nodes
?line {ok,f} = cover:compile(f),
- ?line {ok,[_,_,_]} = cover:start(nodes()),
+ ?line {ok,[_,_,_,_]} = cover:start(nodes()),
?line cover_compiled = code:which(f),
?line cover_compiled = rpc:call(N1,code,which,[f]),
?line cover_compiled = rpc:call(N2,code,which,[f]),
?line cover_compiled = rpc:call(N3,code,which,[f]),
+ ?line cover_compiled = rpc:call(N4,code,which,[f]),
%% Check that a node cannot be started twice
?line {ok,[]} = cover:start(N2),
@@ -351,6 +353,7 @@ distribution(Config) when is_list(Config) ->
?line cover_compiled = rpc:call(N1,code,which,[v]),
?line cover_compiled = rpc:call(N2,code,which,[v]),
?line cover_compiled = rpc:call(N3,code,which,[v]),
+ ?line cover_compiled = rpc:call(N4,code,which,[v]),
%% this is lost when the node is killed
?line rpc:call(N3,f,f2,[]),
@@ -385,6 +388,18 @@ distribution(Config) when is_list(Config) ->
%% reset on the remote node(s))
?line check_f_calls(1,1),
+ %% Another checn that data is not fetched twice, i.e. when flushed
+ %% then analyse should not add the same data again.
+ ?line rpc:call(N4,f,f2,[]),
+ ?line ok = cover:flush(N4),
+ ?line check_f_calls(1,2),
+
+ %% Check that flush collects data so calls are not lost if node is killed
+ ?line rpc:call(N4,f,f2,[]),
+ ?line ok = cover:flush(N4),
+ ?line rpc:call(N4,erlang,halt,[]),
+ ?line check_f_calls(1,3),
+
%% Check that stop() unloads on all nodes
?line ok = cover:stop(),
?line timer:sleep(100), %% Give nodes time to unload on slow machines.
--
cgit v1.2.3