4
%% Copyright Ericsson AB 2009. All Rights Reserved.
6
%% The contents of this file are subject to the Erlang Public License,
7
%% Version 1.1, (the "License"); you may not use this file except in
8
%% compliance with the License. You should have received a copy of the
9
%% Erlang Public License along with this software. If not, it can be
10
%% retrieved online at http://www.erlang.org/.
12
%% Software distributed under the License is distributed on an "AS IS"
13
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
14
%% the License for the specific language governing rights and limitations
19
-module(reltool_server_SUITE).
21
-export([all/0, init_per_suite/1, end_per_suite/1,
22
init_per_testcase/2, fin_per_testcase/2, end_per_testcase/2]).
26
-include("reltool_test_lib.hrl").
28
-define(NODE_NAME, '__RELTOOL__TEMPORARY_TEST__NODE__').
30
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
31
%% Initialization functions.
33
init_per_suite(Config) ->
34
reltool_test_lib:init_per_suite(Config).
36
end_per_suite(Config) ->
37
reltool_test_lib:end_per_suite(Config).
39
init_per_testcase(Func,Config) ->
40
reltool_test_lib:init_per_testcase(Func,Config).
41
end_per_testcase(Func,Config) ->
42
reltool_test_lib:end_per_testcase(Func,Config).
43
fin_per_testcase(Func,Config) -> %% For test_server
44
reltool_test_lib:end_per_testcase(Func,Config).
46
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
47
%% SUITE specification
65
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
66
%% Start a server process and check that it does not crash
68
start_server(TestInfo) when is_atom(TestInfo) ->
69
reltool_test_lib:tc_info(TestInfo);
70
start_server(_Config) ->
71
{ok, Pid} = ?msym({ok, _}, reltool:start_server([])),
72
Libs = lists:sort(erl_libs()),
76
_ -> {sys, [{lib_dirs, Libs}]}
78
?m({ok, StrippedDefault}, reltool:get_config(Pid)),
79
?m(ok, reltool:stop(Pid)),
82
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
83
%% Start a server process and check that it does not crash
85
set_config(TestInfo) when is_atom(TestInfo) ->
86
reltool_test_lib:tc_info(TestInfo);
87
set_config(_Config) ->
88
Libs = lists:sort(erl_libs()),
94
{root_dir, code:root_dir()},
97
{ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Default}])),
101
_ -> {sys, [{lib_dirs, Libs}]}
103
?m({ok, StrippedDefault}, reltool:get_config(Pid)),
105
?m(ok, reltool:stop(Pid)),
108
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
111
create_release(TestInfo) when is_atom(TestInfo) ->
112
reltool_test_lib:tc_info(TestInfo);
113
create_release(_Config) ->
114
%% Configure the server
115
RelName = "Just testing...",
122
{rel, RelName, RelVsn, [kernel, stdlib]}
125
ErtsVsn = erlang:system_info(version),
126
Apps = application:loaded_applications(),
127
{value, {_, _, KernelVsn}} = lists:keysearch(kernel, 1, Apps),
128
{value, {_, _, StdlibVsn}} = lists:keysearch(stdlib, 1, Apps),
129
Rel = {release, {RelName, RelVsn},
131
[{kernel, KernelVsn},
132
{stdlib, StdlibVsn}]},
133
?m({ok, Rel}, reltool:get_rel([{config, Config}], RelName)),
136
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
137
%% Generate boot scripts
139
create_script(TestInfo) when is_atom(TestInfo) ->
140
reltool_test_lib:tc_info(TestInfo);
141
create_script(_Config) ->
142
%% Configure the server
143
RelName = "Just testing",
150
{rel, RelName, RelVsn, [stdlib, kernel]}
152
{ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Config}])),
154
%% Generate release file
155
ErtsVsn = erlang:system_info(version),
156
Apps = application:loaded_applications(),
157
{value, {_, _, KernelVsn}} = lists:keysearch(kernel, 1, Apps),
158
{value, {_, _, StdlibVsn}} = lists:keysearch(stdlib, 1, Apps),
162
[{stdlib, StdlibVsn}, {kernel, KernelVsn}]},
163
?m({ok, Rel}, reltool:get_rel(Pid, RelName)),
164
RelFile = RelName ++ ".rel",
165
?m(ok, file:write_file(RelFile, io_lib:format("~p.\n", [Rel]))),
167
%% Generate script file
168
?m(ok, systools:make_script(RelName, [])),
169
ScriptFile = RelName ++ ".script",
170
{ok, [OrigScript]} = ?msym({ok, [_]}, file:consult(ScriptFile)),
171
{ok, Script} = ?msym({ok, _}, reltool:get_script(Pid, RelName)),
172
%% OrigScript2 = sort_script(OrigScript),
173
%% Script2 = sort_script(Script),
174
%% ?m(OrigScript2, Script2),
176
?m(equal, diff_script(OrigScript, Script)),
179
?m(ok, reltool:stop(Pid)),
182
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
183
%% Generate target system
185
create_target(TestInfo) when is_atom(TestInfo) ->
186
reltool_test_lib:tc_info(TestInfo);
187
create_target(_Config) ->
188
%% Configure the server
189
RelName1 = "Just testing",
190
RelName2 = "Just testing with SASL",
195
{root_dir, code:root_dir()},
197
{boot_rel, RelName2},
198
{rel, RelName1, RelVsn, [stdlib, kernel]},
199
{rel, RelName2, RelVsn, [sasl, stdlib, kernel]},
200
{app, sasl, [{incl_cond, include}]}
203
%% Generate target file
204
TargetDir = "reltool_target_dir_development",
205
?m(ok, reltool_utils:recursive_delete(TargetDir)),
206
?m(ok, file:make_dir(TargetDir)),
207
?m(ok, reltool:create_target([{config, Config}], TargetDir)),
209
Erl = filename:join([TargetDir, "bin", "erl"]),
210
{ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)),
211
?msym(ok, stop_node(Node)),
215
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
216
%% Generate embedded target system
218
create_embedded(TestInfo) when is_atom(TestInfo) ->
219
reltool_test_lib:tc_info(TestInfo);
220
create_embedded(_Config) ->
221
%% Configure the server
222
RelName1 = "Just testing",
223
RelName2 = "Just testing with SASL",
230
{boot_rel, RelName2},
231
{rel, RelName1, RelVsn, [stdlib, kernel]},
232
{rel, RelName2, RelVsn, [sasl, stdlib, kernel]},
233
{app, sasl, [{incl_cond, include}]}
236
%% Generate target file
237
TargetDir = "reltool_target_dir_embedded",
238
?m(ok, reltool_utils:recursive_delete(TargetDir)),
239
?m(ok, file:make_dir(TargetDir)),
240
?m(ok, reltool:create_target([{config, Config}], TargetDir)),
242
Erl = filename:join([TargetDir, "bin", "erl"]),
243
{ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)),
244
?msym(ok, stop_node(Node)),
248
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
249
%% Generate standalone system
251
create_standalone(TestInfo) when is_atom(TestInfo) ->
252
reltool_test_lib:tc_info(TestInfo);
253
create_standalone(_Config) ->
254
%% Configure the server
255
ExDir = code:lib_dir(reltool, examples),
256
EscriptName = "display_args",
257
Escript = filename:join([ExDir, EscriptName]),
262
{escript, Escript, [{incl_cond, include}]},
263
{profile, standalone}
266
%% Generate target file
267
TargetDir = "reltool_target_dir_standalone",
268
?m(ok, reltool_utils:recursive_delete(TargetDir)),
269
?m(ok, file:make_dir(TargetDir)),
270
?m(ok, reltool:create_target([{config, Config}], TargetDir)),
272
BinDir = filename:join([TargetDir, "bin"]),
273
Erl = filename:join([BinDir, "erl"]),
274
{ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)),
275
RootDir = ?ignore(rpc:call(Node, code, root_dir, [])),
276
?msym(ok, stop_node(Node)),
278
Expected = iolist_to_binary(["Root dir: ", RootDir, "\n"
279
"Script args: [\"-arg1\",\"arg2\",\"arg3\"]\n",
282
io:format("Expected: ~s\n", [Expected]),
283
?m(Expected, run(BinDir, EscriptName ++ " -arg1 arg2 arg3")),
287
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
288
%% Generate old type of target system
290
create_old_target(TestInfo) when is_atom(TestInfo) ->
291
reltool_test_lib:tc_info(TestInfo);
292
create_old_target(_Config) ->
293
%% Configure the server
294
RelName1 = "Just testing",
295
RelName2 = "Just testing with SASL",
301
{boot_rel, RelName2},
302
{rel, RelName1, RelVsn, [stdlib, kernel]},
303
{rel, RelName2, RelVsn, [sasl, stdlib, kernel]},
304
{relocatable, false}, % Implies explicit old style installation
305
{app, sasl, [{incl_cond, include}]}
308
%% Generate target file
309
TargetDir = "reltool_target_dir_old",
310
?m(ok, reltool_utils:recursive_delete(TargetDir)),
311
?m(ok, file:make_dir(TargetDir)),
312
?m(ok, reltool:create_target([{config, Config}], TargetDir)),
314
%% io:format("Will fail on Windows (should patch erl.ini)\n", []),
315
?m(ok, reltool:install(RelName2, TargetDir)),
317
Erl = filename:join([TargetDir, "bin", "erl"]),
318
{ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)),
319
?msym(ok, stop_node(Node)),
323
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
327
case os:getenv("ERL_LIBS") of
329
LibStr -> string:tokens(LibStr, ":;")
332
diff_script(Script, Script) ->
334
diff_script({script, Rel, Commands1}, {script, Rel, Commands2}) ->
335
diff_cmds(Commands1, Commands2);
336
diff_script({script, Rel1, _}, {script, Rel2, _}) ->
337
{error, {Rel1, Rel2}}.
339
diff_cmds([Cmd | Commands1], [Cmd | Commands2]) ->
340
diff_cmds(Commands1, Commands2);
341
diff_cmds([Cmd1 | _Commands1], [Cmd2 | _Commands2]) ->
342
{diff, {expected, Cmd1}, {actual, Cmd2}};
346
os_cmd(Cmd) when is_list(Cmd) ->
347
%% Call the plain os:cmd with an echo command appended to print command status
348
%% io:format("os:cmd(~p).\n", [Cmd]),
349
case os:cmd(Cmd++";echo \"#$?\"") of
350
%% There is (as far as I can tell) only one thing that will match this
351
%% and that is too silly to ever be used, but...
355
%% Find the position of the status code wich is last in the string
357
case string:rchr(Return, $#) of
359
%% This happens only if the sh command pipe is somehow interrupted
364
Result = string:left(Return,Position - 1),
365
Status = string:substr(Return,Position + 1, length(Return) - Position - 1),
366
{list_to_integer(Status), Result}
370
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
373
start_node(Name, ErlPath) ->
374
FullName = full_node_name(Name),
375
CmdLine = mk_node_cmdline(Name, ErlPath),
376
io:format("Starting node ~p: ~s~n", [FullName, CmdLine]),
377
case open_port({spawn, CmdLine}, []) of
378
Port when is_port(Port) ->
380
erlang:port_close(Port),
381
case ping_node(FullName, 50) of
382
ok -> {ok, FullName};
383
Other -> exit({failed_to_start_node, FullName, Other})
386
exit({failed_to_start_node, FullName, Error})
390
monitor_node(Node, true),
391
spawn(Node, fun () -> halt() end),
392
receive {nodedown, Node} -> ok end.
394
mk_node_cmdline(Name) ->
395
Prog = case catch init:get_argument(progname) of
397
_ -> exit(no_progname_argument_found)
399
mk_node_cmdline(Name, Prog).
401
mk_node_cmdline(Name, Prog) ->
402
Static = "-detached -noinput",
403
Pa = filename:dirname(code:which(?MODULE)),
404
NameSw = case net_kernel:longnames() of
407
_ -> exit(not_distributed_node)
409
{ok, Pwd} = file:get_cwd(),
410
NameStr = atom_to_list(Name),
413
++ NameSw ++ " " ++ NameStr ++ " "
414
++ "-pa " ++ Pa ++ " "
415
++ "-env ERL_CRASH_DUMP " ++ Pwd ++ "/erl_crash_dump." ++ NameStr ++ " "
416
++ "-setcookie " ++ atom_to_list(erlang:get_cookie()).
418
full_node_name(PreName) ->
419
HostSuffix = lists:dropwhile(fun ($@) -> false; (_) -> true end,
420
atom_to_list(node())),
421
list_to_atom(atom_to_list(PreName) ++ HostSuffix).
423
ping_node(_Node, 0) ->
425
ping_node(Node, N) when is_integer(N), N > 0 ->
426
case catch net_adm:ping(Node) of
428
wait_for_process(Node, code_server, 50);
434
wait_for_process(_Node, Name, 0) ->
436
wait_for_process(Node, Name, N) when is_integer(N), N > 0 ->
437
case rpc:call(Node, erlang, whereis, [Name]) of
440
wait_for_process(Node, Name, N-1);
441
{badrpc, _} = Reason ->
442
erlang:error({Reason, Node});
443
Pid when is_pid(Pid) ->
447
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
451
Cmd = case os:type() of
452
{win32,_} -> filename:nativename(Dir) ++ "\\" ++ Cmd0;
457
run(Dir, Opts, Cmd0) ->
458
Cmd = case os:type() of
459
{win32,_} -> Opts ++ " " ++ filename:nativename(Dir) ++ "\\" ++ Cmd0;
460
_ -> Opts ++ " " ++ Dir ++ "/" ++ Cmd0
465
io:format("Run: ~p\n", [Cmd]),
466
Env = [{"PATH",Dir++":"++os:getenv("PATH")}],
467
Port = open_port({spawn,Cmd}, [exit_status,eof,in,{env,Env}]),
468
Res = get_data(Port, []),
470
{Port,{exit_status,ExitCode}} ->
471
iolist_to_binary([Res,"ExitCode:"++integer_to_list(ExitCode)])
474
get_data(Port, SoFar) ->
476
{Port,{data,Bytes}} ->
477
get_data(Port, [SoFar|Bytes]);
479
erlang:port_close(Port),
483
expected_output([data_dir|T], Data) ->
484
Slash = case os:type() of
488
[filename:nativename(Data)++Slash|expected_output(T, Data)];
489
expected_output([H|T], Data) ->
490
[H|expected_output(T, Data)];
491
expected_output([], _) ->
493
expected_output(Bin, _) when is_binary(Bin) ->