1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2008-2019. 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%%
22%%----------------------------------------------------------------------
23%% Purpose: Test various aspects of the flex scanner handling
24%%
25%% Test:    ts:run(megaco, megaco_flex_SUITE, [batch]).
26%%
27%%----------------------------------------------------------------------
28
29-module(megaco_flex_SUITE).
30
31-include("megaco_test_lib.hrl").
32
33-export([
34         suite/0, all/0, groups/0,
35	 init_per_suite/1,    end_per_suite/1,
36         init_per_group/2,    end_per_group/2,
37	 init_per_testcase/2, end_per_testcase/2,
38
39	 plain/1,
40	 port_exit/1,
41	 garbage_in/1
42
43	]).
44
45
46%%======================================================================
47%% Common Test interface functions
48%%======================================================================
49
50suite() ->
51    [{ct_hooks, [ts_install_cth]}].
52
53all() ->
54    [
55     plain,
56     port_exit,
57     garbage_in
58    ].
59
60
61groups() ->
62    [].
63
64
65
66%%
67%% -----
68%%
69
70init_per_suite(suite) ->
71    [];
72init_per_suite(doc) ->
73    [];
74init_per_suite(Config0) when is_list(Config0) ->
75
76    ?ANNOUNCE_SUITE_INIT(),
77
78    p("init_per_suite -> entry with"
79      "~n      Config: ~p"
80      "~n      Nodes:  ~p", [Config0, erlang:nodes()]),
81
82    case ?LIB:init_per_suite(Config0) of
83        {skip, _} = SKIP ->
84            SKIP;
85
86        Config1 when is_list(Config1) ->
87
88            case megaco_flex_scanner:is_enabled() of
89                true ->
90
91                    %% We need a (local) monitor on this node also
92                    megaco_test_sys_monitor:start(),
93
94                    p("init_per_suite -> end when"
95                      "~n      Config: ~p"
96                      "~n      Nodes:  ~p", [Config1, erlang:nodes()]),
97
98                    Config1;
99                false ->
100                    ?SKIP(flex_scanner_not_enabled)
101            end
102    end.
103
104end_per_suite(suite) -> [];
105end_per_suite(doc) -> [];
106end_per_suite(Config0) when is_list(Config0) ->
107
108    p("end_per_suite -> entry with"
109      "~n      Config: ~p"
110      "~n      Nodes:  ~p", [Config0, erlang:nodes()]),
111
112    megaco_test_sys_monitor:stop(),
113    Config1 = ?LIB:end_per_suite(Config0),
114
115    p("end_per_suite -> end when"
116      "~n      Nodes:  ~p", [erlang:nodes()]),
117
118    Config1.
119
120
121%%
122%% -----
123%%
124
125init_per_group(_GroupName, Config) ->
126    Config.
127
128end_per_group(_GroupName, Config) ->
129    Config.
130
131
132%%
133%% -----
134%%
135
136init_per_testcase(Case, Config) ->
137
138    p("init_per_testcase -> entry with"
139      "~n   Config: ~p"
140      "~n   Nodes:  ~p", [Config, erlang:nodes()]),
141
142    megaco_test_global_sys_monitor:reset_events(),
143
144    megaco_test_lib:init_per_testcase(Case, Config).
145
146end_per_testcase(Case, Config) ->
147
148    p("end_per_testcase -> entry with"
149      "~n   Config: ~p"
150      "~n   Nodes:  ~p", [Config, erlang:nodes()]),
151
152    p("system events during test: "
153      "~n   ~p", [megaco_test_global_sys_monitor:events()]),
154
155    megaco_test_lib:end_per_testcase(Case, Config).
156
157
158
159%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
160
161plain(suite) ->
162    [];
163plain(doc) ->
164    ["This is to simply test that it is possible to start and stop the "
165     "flex handler."];
166plain(Config) when is_list(Config) ->
167    put(tc, plain),
168    p("begin"),
169    process_flag(trap_exit, true),
170    p("start the flex handler"),
171    {ok, Pid, _PortInfo} = flex_scanner_handler_start(),
172    p("stop handler"),
173    flex_scanner_handler_stop(Pid),
174    p("end"),
175    ok.
176
177
178%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
179
180port_exit(suite) ->
181    [];
182port_exit(doc) ->
183    ["Test that the handler detects and handles an exiting port."];
184port_exit(Config) when is_list(Config) ->
185    put(tc, port_exit),
186    p("begin"),
187    process_flag(trap_exit, true),
188
189    p("start the flex handler"),
190    {ok, Pid, {flex, PortOrPorts}} = flex_scanner_handler_start(),
191    Port = case PortOrPorts of
192	       P when is_port(P) ->
193		   P;
194	       Ports when is_tuple(Ports) ->
195		   %% It does not matter which of the ports we choose
196		   element(1, PortOrPorts);
197	       Ports when is_list(Ports) ->
198		   %% It does not matter which of the ports we choose
199		   hd(Ports)
200	   end,
201
202    p("simulate crash"),
203    exit(Port, simulated_crash),
204
205    p("await handler exit"),
206    receive
207	{'EXIT', Pid, _} ->
208	    p("end"),
209	    ok
210    after 5000 ->
211	    p("timeout - stop handler"),
212	    flex_scanner_handler_stop(Pid),
213	    p("end after timeout"),
214	    {error, timeout}
215    end.
216
217
218%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
219
220garbage_in(suite) ->
221    [];
222garbage_in(doc) ->
223    ["Send in various unexpected messages and requeststo the handler "
224     "to see that it does die on us. "];
225garbage_in(Config) when is_list(Config) ->
226    put(tc, garbage_in),
227    p("begin"),
228    process_flag(trap_exit, true),
229
230    p("start the flex handler"),
231    {ok, Pid, _PortInfo} = flex_scanner_handler_start(),
232
233    p("make an invalid call"),
234    {error, _} = gen_server:call(Pid, garbage_request),
235    p("make an invalid cast"),
236    gen_server:cast(Pid, garbage_msg),
237    p("send an unknown message"),
238    Pid ! garbage_info,
239
240    p("wait for any garbage response"),
241    receive
242	Any ->
243	    p("end with unexpected message: ~p", [Any]),
244	    {error, {unexpected_msg, Any}}
245    after 1000 ->
246	    p("end with nothing received - stop handler"),
247	    flex_scanner_handler_stop(Pid),
248	    ok
249    end.
250
251
252
253%% ------- Misc functions --------
254
255flex_scanner_handler_start() ->
256    case megaco_flex_scanner_handler:start_link() of
257	{error, {failed_starting_scanner, {error, {load_driver, _}}}} ->
258	    p("failed loading driver"),
259	    ?SKIP(could_not_load_driver);
260	{error, {failed_starting_scanner, {load_driver, _}}} ->
261	    p("failed loading driver"),
262	    ?SKIP(could_not_load_driver);
263	{error, {failed_starting_scanner, {load_driver, _}, _}} ->
264	    p("failed loading driver"),
265	    ?SKIP(could_not_load_driver);
266	Else ->
267	    p("driver load result: ~p", [Else]),
268	    Else
269    end.
270
271flex_scanner_handler_stop(Pid) ->
272    megaco_flex_scanner_handler:stop(Pid).
273
274
275%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
276
277p(F) ->
278    p(F, []).
279
280p(F, A) ->
281    case get(tc) of
282        undefined ->
283            io:format("*** [~s] ~p ***"
284                      "~n" ++ F ++ "~n", [?FTS(), self() | A]);
285        TC ->
286            io:format("*** [~s] ~p ~w ***"
287                      "~n   " ++ F ++ "~n",
288                      [?FTS(), self(), TC | A])
289    end.
290
291