1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 1997-2016. 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(orber_SUITE).
22-include_lib("common_test/include/ct.hrl").
23
24-define(default_timeout, test_server:minutes(15)).
25-define(application, orber).
26
27% Test server specific exports
28-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
29	 init_per_group/2,end_per_group/2]).
30-export([init_per_testcase/2, end_per_testcase/2]).
31
32% Test cases must be exported.
33-export([app_test/1, undefined_functions/1, install_load_order/1,
34	 install_local_content/1,
35         otp_9887/1]).
36
37%% Exporting error handler callbacks for use in otp_9887
38-export([init/1, handle_event/2]).
39
40%%
41%% all/1
42%%
43suite() -> [{ct_hooks,[ts_install_cth]}].
44
45all() ->
46    [app_test, undefined_functions, install_load_order,
47     install_local_content,
48     otp_9887].
49
50groups() ->
51    [].
52
53init_per_suite(Config) ->
54    Config.
55
56end_per_suite(_Config) ->
57    ok.
58
59init_per_group(_GroupName, Config) ->
60    Config.
61
62end_per_group(_GroupName, Config) ->
63    Config.
64
65
66init_per_testcase(_Case, Config) ->
67    Dog=test_server:timetrap(?default_timeout),
68    [{watchdog, Dog}|Config].
69
70end_per_testcase(_Case, Config) ->
71    Dog=proplists:get_value(watchdog, Config),
72    test_server:timetrap_cancel(Dog),
73    ok.
74
75%
76% Test cases starts here.
77%
78app_test(_Config) ->
79    ok=test_server:app_test(orber),
80    ok.
81
82otp_9887(_Config) ->
83    orber:jump_stop(),
84    application:set_env(orber, orber_debug_level, 10),
85    orber:jump_start([]),
86
87    mnesia:create_table(orber_light_ifr, []),
88
89    error_logger:add_report_handler(?MODULE,[self()]),
90    catch orber_ifr:get_module(foo, bar),
91
92    receive
93	{stolen,Reason} ->
94            {error,_Pid1, {_Pid2, _ErrorString, ArgumentList}} = Reason,
95            5 = length(ArgumentList)
96    after 500 ->
97            test_server:fail("OTP_9887 TIMED OUT")
98    end,
99
100    orber:jump_stop(),
101    ok.
102
103%% Install Orber using the load_order option.
104install_load_order(_Config) ->
105    orber:jump_stop(),
106    case catch install_load_order2() of
107	ok ->
108	    orber:jump_stop();
109	What ->
110	    orber:jump_stop(),
111	    exit(What)
112    end.
113
114install_load_order2() ->
115    application:load(orber),
116    mnesia:start(),
117    corba:orb_init([{iiop_port, 0}]),
118    orber:install([node()], [{ifr_storage_type, ram_copies},
119			     {load_order, 10}]),
120    orber:start(),
121    [H|_] = orber:get_tables(),
122    10 = mnesia:table_info(H, load_order),
123    ok.
124
125%% Install Orber using the local_content option.
126install_local_content(_Config) ->
127    orber:jump_stop(),
128    case catch install_local_content2() of
129	ok ->
130	    orber:jump_stop();
131	What ->
132	    orber:jump_stop(),
133	    exit(What)
134    end.
135
136install_local_content2() ->
137    application:load(orber),
138    mnesia:start(),
139    corba:orb_init([{iiop_port, 0}]),
140    orber:install([node()], [{ifr_storage_type, ram_copies},
141			     {local_content, true}]),
142    orber:start(),
143    [H|_] = orber:get_tables(),
144    true = mnesia:table_info(H, local_content),
145    ok.
146
147
148
149%% Check for undefined functions
150undefined_functions(_Config) ->
151    App            = orber,
152    Root           = code:root_dir(),
153    LibDir         = code:lib_dir(App),
154    EbinDir        = filename:join([LibDir,"ebin"]),
155    AppFilePath    = filename:join([LibDir,"ebin", "orber.app"]),
156    {ok, [{application,orber,AppFile}]} = file:consult(AppFilePath),
157    io:format("Using ~p~n~p~n", [AppFilePath, AppFile]),
158    Mods           = key1search(modules, AppFile),
159    XRefTestName   = undef_funcs_make_name(App, xref_test_name),
160    {ok, XRef}     = xref:start(XRefTestName),
161    ok             = xref:set_default(XRef,
162                                      [{verbose,false},{warnings,false}]),
163    XRefName       = undef_funcs_make_name(App, xref_name),
164    {ok, XRefName} = xref:add_release(XRef, Root, {name,XRefName}),
165    {ok, App}      = xref:replace_application(XRef, App, EbinDir),
166    {ok, Undefs}   = xref:analyze(XRef, undefined_function_calls),
167    xref:stop(XRef),
168    analyze_undefined_function_calls(Undefs, Mods, []).
169
170analyze_undefined_function_calls([], _, []) ->
171    ok;
172analyze_undefined_function_calls([], _, AppUndefs) ->
173    exit({suite_failed, {undefined_function_calls, AppUndefs}});
174analyze_undefined_function_calls([{{Mod, _F, _A}, _C} = AppUndef|Undefs],
175                                 AppModules, AppUndefs) ->
176    %% Check that this module is our's
177    case lists:member(Mod,AppModules) of
178        true ->
179            {Calling,Called} = AppUndef,
180            {Mod1,Func1,Ar1} = Calling,
181            {Mod2,Func2,Ar2} = Called,
182            io:format("undefined function call: "
183                      "~n   ~w:~w/~w calls ~w:~w/~w~n",
184                      [Mod1,Func1,Ar1,Mod2,Func2,Ar2]),
185            analyze_undefined_function_calls(Undefs, AppModules,
186                                             [AppUndef|AppUndefs]);
187        false ->
188            io:format("dropping ~p~n", [Mod]),
189            analyze_undefined_function_calls(Undefs, AppModules, AppUndefs)
190    end.
191
192%% This function is used simply to avoid cut-and-paste errors later...
193undef_funcs_make_name(App, PostFix) ->
194    list_to_atom(atom_to_list(App) ++ "_" ++ atom_to_list(PostFix)).
195
196key1search(Key, L) ->
197    case lists:keysearch(Key, 1, L) of
198        false ->
199            fail({not_found, Key, L});
200        {value, {Key, Value}} ->
201            Value
202    end.
203
204fail(Reason) ->
205    exit({suite_failed, Reason}).
206
207%% Error handler
208
209init([Proc]) -> {ok,Proc}.
210
211handle_event(Event, Proc) ->
212    Proc ! {stolen,Event},
213    {ok,Proc}.
214