1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2004-2018. 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
21-module(ct_rpc).
22
23%%% API
24-export([app_node/2, app_node/3, app_node/4,
25	 call/4, call/5, call/6, cast/4, cast/5]).
26
27%%%=========================================================================
28%%%  API
29%%%=========================================================================
30app_node(App, Candidates) ->
31    app_node(App, Candidates, true, []).
32
33app_node(App, Candidates, FailOnBadRPC) ->
34    app_node(App, Candidates, FailOnBadRPC, []).
35
36app_node(App, [], _, _) ->
37    ct:fail({application_not_running, App});
38
39%% Variable _Candidates is a workaround for the strange edoc behavior
40%% of creating the spec:  app_node(App, Nodes::Candidates) -> NodeName
41%% if it does not exist.
42app_node(App, _Candidates = [CandidateNode | Nodes], FailOnBadRPC, Cookie) ->
43    Cookie0 = set_the_cookie(Cookie),
44    Result = rpc:call(CandidateNode, application, which_applications, []),
45    _ = set_the_cookie(Cookie0),
46    case Result of
47	{badrpc,Reason} when FailOnBadRPC == true ->
48	    ct:fail({Reason,CandidateNode});
49	{badrpc,_} when FailOnBadRPC == false ->
50	    app_node(App, Nodes, FailOnBadRPC);
51	Apps ->
52	    case lists:keysearch(App, 1, Apps) of
53		{value, _} ->
54		    CandidateNode;
55		_ ->
56		    app_node(App, Nodes, FailOnBadRPC)
57	    end
58    end.
59
60call(Node, Module, Function, Args) ->
61    call(Node, Module, Function, Args, infinity, []).
62
63call(Node, Module, Function, Args, TimeOut) ->
64    call(Node, Module, Function, Args, TimeOut, []).
65
66call({Fun, FunArgs}, Module, Function, Args, TimeOut, Cookie) ->
67    Node = Fun(FunArgs),
68    call(Node, Module, Function, Args, TimeOut, Cookie);
69call(Node, Module, Function, Args, TimeOut, Cookie) when is_atom(Node) ->
70    Cookie0 = set_the_cookie(Cookie),
71    Result = rpc:call(Node, Module, Function, Args, TimeOut),
72    _ = set_the_cookie(Cookie0),
73    Result.
74
75cast(Node, Module, Function, Args) ->
76    cast(Node, Module, Function, Args, []).
77
78cast({Fun, FunArgs}, Module, Function, Args, Cookie) ->
79    Node = Fun(FunArgs),
80    cast(Node, Module, Function, Args, Cookie);
81cast(Node, Module, Function, Args, Cookie) when is_atom(Node) ->
82    Cookie0 = set_the_cookie(Cookie),
83    true = rpc:cast(Node, Module, Function, Args),
84    _ = set_the_cookie(Cookie0),
85    ok.
86
87
88%%%---------- Internal -----------
89
90set_the_cookie([]) ->
91    [];
92set_the_cookie(Cookie) ->
93    Cookie0 = erlang:get_cookie(),
94    erlang:set_cookie(node(),Cookie),
95    Cookie0.
96