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