1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2012-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%% Test suite for the systools module.
22%%
23%%	The systools module is a wrapper for a number of modules that
24%%	handle large parts of the release building functionality
25%%	(e.g. checking app files, building a tar file, building
26%%	release upgrad scripts.
27%%
28
29
30-module(systools_SUITE).
31
32-compile(export_all).
33
34%%-define(debug, true).
35
36-include_lib("common_test/include/ct.hrl").
37-define(format(S, A), ok).
38-define(datadir, ?config(data_dir, Config)).
39-define(privdir, ?config(priv_dir, Config)).
40-define(copydir, ?config(copy_dir, Config)).
41
42-include_lib("kernel/include/file.hrl").
43
44-import(lists, [foldl/3]).
45
46-define(default_timeout, ?t:minutes(20)).
47
48
49%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
50
51suite() ->
52    [{ct_hooks, [ts_install_cth]}].
53
54all() ->
55    [{group, script}, {group, tar}, {group, relup}, {group, hybrid},
56     {group, options}].
57
58groups() ->
59    [{script, [],
60      [script_options, normal_script, start_script, unicode_script, no_mod_vsn_script,
61       wildcard_script, variable_script, abnormal_script,
62       no_sasl_script, no_dot_erlang_script,
63       src_tests_script, crazy_script,
64       included_script, included_override_script,
65       included_fail_script, included_bug_script, exref_script,
66       duplicate_modules_script,
67       otp_3065_circular_dependenies, included_and_used_sort_script]},
68     {tar, [],
69      [tar_options, relname_tar, normal_tar, no_mod_vsn_tar, system_files_tar,
70       system_src_file_tar, invalid_system_files_tar, variable_tar,
71       src_tests_tar, var_tar, exref_tar, link_tar, no_sasl_tar,
72       otp_9507_path_ebin, additional_files_tar, erts_tar]},
73     {relup, [],
74      [normal_relup, restart_relup, abnormal_relup, no_sasl_relup,
75       no_appup_relup, bad_appup_relup, app_start_type_relup, regexp_relup,
76       replace_app_relup
77      ]},
78     {hybrid, [], [normal_hybrid,hybrid_no_old_sasl,hybrid_no_new_sasl]},
79     {options, [], [otp_6226_outdir,app_file_defaults]}].
80
81init_per_group(_GroupName, Config) ->
82    Config.
83
84end_per_group(_GroupName, Config) ->
85    Config.
86
87%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
88
89
90init_per_suite(Config) when is_list(Config) ->
91    %% To use in end_per_testcase
92    Path = code:get_path(),
93    {ok,Cwd} = file:get_cwd(),
94
95    %% Make of copy of the data directory.
96    DataDir = ?datadir,
97    PrivDir = ?privdir,
98    CopyDir = fname(PrivDir, "datacopy"),
99    ok = file:make_dir(CopyDir),
100    TarFile = fname(PrivDir, "datacopy.tgz"),
101    ok = file:set_cwd(DataDir),
102    ok = erl_tar:create(TarFile, ["."], [compressed]),
103    ok = erl_tar:extract(TarFile, [compressed, {cwd,CopyDir}]),
104    ok = file:delete(TarFile),
105
106    %% Compile source files in the copy directory.
107    Sources = filelib:wildcard(fname([CopyDir,'*','*','*','*','*.erl'])),
108    lists:foreach(fun compile_source/1, Sources),
109
110    [{copy_dir, CopyDir}, {cwd,Cwd}, {path,Path} | Config].
111
112compile_source(File) ->
113    %% The compiler will no longer create a Beam file
114    %% with a module name that does not match the output
115    %% file, so we must compile to a binary and write
116    %% the output file ourselves.
117    U = filename:dirname(filename:dirname(File)),
118    Base = filename:rootname(filename:basename(File)),
119    OutFile = filename:join([U,"ebin",Base++".beam"]),
120    OutFileTemp = OutFile ++ "#",
121    {ok,_,Code} = compile:file(File, [binary]),
122    ok = file:write_file(OutFileTemp, Code),
123    file:rename(OutFileTemp, OutFile).
124
125end_per_suite(Config) when is_list(Config) ->
126    rh_test_lib:clean_dir(?privdir),
127    Config.
128
129init_per_testcase(link_tar, Config) ->
130    case os:type() of
131	{unix, _} -> init_per_testcase(dummy, Config);
132	{win32, _} -> {skip, "Skip on windows"}
133    end;
134init_per_testcase(_Case, Config) ->
135    Dog = test_server:timetrap(?default_timeout),
136    [{watchdog, Dog}|Config].
137
138end_per_testcase(Case, Config) ->
139    try apply(?MODULE,Case,[cleanup,Config])
140    catch error:undef -> ok
141    end,
142    Dog=?config(watchdog, Config),
143    test_server:timetrap_cancel(Dog),
144    case {?config(path,Config),?config(cwd,Config)} of
145	{undefined,undefined} ->
146	    ok;
147	{Path,Cwd} ->
148	    true = code:set_path(Path),
149	    ok = file:set_cwd(Cwd)
150    end,
151    ok.
152
153
154
155%% Usage:
156%%    systools:make_script("RelName")
157%%                        Make a boot file from RelName.rel.
158%%                        Generates RelName.{script,boot}
159%%    systools:make_tar("RelName")
160%%                        Make a release package from RelName.rel.
161%%                        Generates RelName.tar,Z
162%%    systools:script2boot(File)
163%%                        File.script -> File.boot
164%%    systools:make_relup("Target", ["UpFromRel"...], ["DownToRel"...], Opts)
165%%			  Gather all appup scripts to the relup file
166%%
167
168
169%% make_script: Check illegal script options
170script_options(Config) when is_list(Config) ->
171    {'EXIT',{{badarg,[{path,["Path",12,"Another"]}]}, _}} =
172	(catch systools:make_script("release", [{path,["Path",12,"Another"]}])),
173    {'EXIT',{{badarg,[sillent]}, _}} =
174	(catch systools:make_script("release",
175				    [{path,["Path","Another"]},sillent])),
176    {'EXIT',{{badarg,[locall]}, _}} =
177	(catch systools:make_script("release",
178				    [{path,["Path","Another"]},locall])),
179    {'EXIT',{{badarg,[src_testsxx]}, _}} =
180	(catch systools:make_script("release",
181				    [{path,["Path"]},src_testsxx])),
182    {'EXIT',{{badarg,[{variables, {"TEST", "/home/lib"}}]}, _}} =
183	(catch systools:make_script("release",
184				    [{variables, {"TEST", "/home/lib"}}])),
185    {'EXIT',{{badarg,[{variables, [{a, b}, {"a", "b"}]}]}, _}} =
186	(catch systools:make_script("release",
187				    [{variables, [{a, b}, {"a", "b"}]}])),
188    {'EXIT',{{badarg,[exreff]}, _}} =
189	(catch systools:make_script("release",
190				    [{path,["Path","Another"]},exreff])),
191    {'EXIT',{{badarg,[{exref,["appl"]}]}, _}} =
192	(catch systools:make_script("release", [{exref,["appl"]}])),
193    {'EXIT',{{badarg,[{machine, "appl"}]}, _}} =
194	(catch systools:make_script("release", [{machine,"appl"}])),
195    ok.
196
197
198%% make_script: Check that normal case
199normal_script(Config) when is_list(Config) ->
200    {ok, OldDir} = file:get_cwd(),
201    PSAVE = code:get_path(),		% Save path
202
203    {LatestDir, LatestName} = create_script(latest,Config),
204
205    DataDir = filename:absname(?copydir),
206    LibDir = fname([DataDir, d_normal, lib]),
207    P1 = fname([LibDir, 'db-2.1', ebin]),
208    P2 = fname([LibDir, 'fe-3.1', ebin]),
209
210    true = code:add_patha(P1),
211    true = code:add_patha(P2),
212
213    ok = file:set_cwd(LatestDir),
214
215    ok = systools:make_script(filename:basename(LatestName)),
216    {ok, _} = read_script_file(LatestName),	% Check readabillity
217
218    %% Check the same but w. silent flag
219    {ok, _, []} = systools:make_script(LatestName, [silent]),
220    {ok, _, []} = systools:make_script(LatestName, [silent,warnings_as_errors]),
221
222    %% Use the local option
223    ok = systools:make_script(LatestName, [local]),
224    ok = check_script_path(LatestName),
225
226    %% use the path option
227    code:set_path(PSAVE),			% Restore path
228    %% Mess up std path:
229    true = code:add_patha(fname([LibDir, 'db-1.0', ebin])),
230    true = code:add_patha(fname([LibDir, 'fe-2.1', ebin])),
231
232    error = systools:make_script(LatestName),	%should fail
233    ok = systools:make_script(LatestName,[{path, [P1, P2]}]),
234
235    ok = file:set_cwd(OldDir),
236    code:set_path(PSAVE),			% Restore path
237    ok.
238
239%% make_script: Check that script can be named start.script
240start_script(Config) when is_list(Config) ->
241    {ok, OldDir} = file:get_cwd(),
242    PSAVE = code:get_path(),		% Save path
243
244    {LatestDir, LatestName} = create_script(latest,Config),
245
246    DataDir = filename:absname(?copydir),
247    LibDir = fname([DataDir, d_normal, lib]),
248    P1 = fname([LibDir, 'db-2.1', ebin]),
249    P2 = fname([LibDir, 'fe-3.1', ebin]),
250
251    true = code:add_patha(P1),
252    true = code:add_patha(P2),
253
254    ok = file:set_cwd(LatestDir),
255
256    ok = systools:make_script(filename:basename(LatestName), [{script_name, "start"}]),
257    {ok, _} = read_script_file("start"),	% Check readabillity
258
259    ok = file:set_cwd(OldDir),
260    code:set_path(PSAVE),			% Restore path
261    ok.
262
263%% make_script: Test make_script with unicode .app file
264unicode_script(Config) when is_list(Config) ->
265    UnicodeStr = [945,946], % alhpa beta in greek letters
266
267    {LatestDir, LatestName} = create_script({unicode,UnicodeStr},Config),
268
269    DataDir = filename:absname(?copydir),
270    UnicodeApp = fname([DataDir, "d_unicode", "lib", "ua-1.0"]),
271    TarFile = fname(?privdir, "unicode_app.tgz"),
272    {ok, Tar} = erl_tar:open(TarFile, [write, compressed]),
273    ok = erl_tar:add(Tar, UnicodeApp, "ua-1.0", [compressed]),
274    ok = erl_tar:close(Tar),
275
276    UnicodeLibDir = fname([DataDir, "d_unicode", UnicodeStr]),
277    P1 = fname([UnicodeLibDir, "ua-1.0", "ebin"]),
278
279    %% Need to do this on a separate node to make sure it has unicode
280    %% filename mode (+fnu*)
281    {ok,HostStr} = inet:gethostname(),
282    Host = list_to_atom(HostStr),
283    {ok,Node} = ct_slave:start(Host,unicode_script_node,[{erl_flags,"+fnui"}]),
284
285    ok = rpc:call(Node,erl_tar,extract,
286		  [TarFile, [{cwd,UnicodeLibDir},compressed]]),
287
288    true = rpc:call(Node,code,add_patha,[P1]),
289
290    ok = rpc:call(Node,file,set_cwd,[LatestDir]),
291
292    ok = rpc:call(Node,systools,make_script,[filename:basename(LatestName),
293					     [local]]),
294
295    {ok, Script} = rpc:call(Node,file,consult,[LatestName++".script"]),
296
297    %% For debug purpose - print script to log
298    io:format("~tp~n",[Script]),
299
300    %% check that script contains unicode strings in
301    %% 1. release version (set in ?MODULE:do_create_script)
302    [{script,{"Test release",UnicodeStr},Instr}] = Script,
303
304    %% 2. application description (set in ua.app in data dir)
305    [AppInfo] = [X || {apply,{application,load,[{application,ua,X}]}} <- Instr],
306    {description,UnicodeStr} = lists:keyfind(description,1,AppInfo),
307
308    %% 3. path (directory name where unicode_app.tgz is extracted)
309    true = lists:member({path,[P1]},Instr),
310
311    %% If all is good, delete the unicode dir to avoid lingering files
312    %% on windows.
313    rpc:call(Node,code,add_pathz,[filename:dirname(code:which(?MODULE))]),
314    rpc:call(Node,?MODULE,delete_tree,[UnicodeLibDir]),
315
316    ok.
317
318unicode_script(cleanup,Config) ->
319    _ = ct_slave:stop(unicode_script_node),
320    file:delete(fname(?privdir, "unicode_app.tgz")),
321    ok.
322
323
324%% make_script:
325%% Modules specified without version in .app file (db-3.1).
326%% Note that this is now the normal way - i.e. systools now ignores
327%% the module versions in the .app file.
328no_mod_vsn_script(Config) when is_list(Config) ->
329    {ok, OldDir} = file:get_cwd(),
330    PSAVE = code:get_path(),		% Save path
331
332    {LatestDir, LatestName} = create_script(latest_no_mod_vsn,Config),
333
334    DataDir = filename:absname(?copydir),
335    LibDir = fname([DataDir, d_normal, lib]),
336    P1 = fname([LibDir, 'db-3.1', ebin]),
337    P2 = fname([LibDir, 'fe-3.1', ebin]),
338
339    true = code:add_patha(P1),
340    true = code:add_patha(P2),
341
342    ok = file:set_cwd(LatestDir),
343
344    ok = systools:make_script(filename:basename(LatestName)),
345    {ok, _} = read_script_file(LatestName),	% Check readabillity
346
347    %% Check the same but w. silent flag
348    {ok, _, []} = systools:make_script(LatestName, [silent]),
349
350    %% Use the local option
351    ok = systools:make_script(LatestName, [local]),
352    ok = check_script_path(LatestName),
353
354    %% use the path option
355    code:set_path(PSAVE),			% Restore path
356    %% Mess up std path:
357    true = code:add_patha(fname([LibDir, 'db-1.0', ebin])),
358    true = code:add_patha(fname([LibDir, 'fe-2.1', ebin])),
359
360    error = systools:make_script(LatestName),	%should fail
361    ok = systools:make_script(LatestName,
362			      [{path, [P1, P2]}]),
363
364    ok = file:set_cwd(OldDir),
365    code:set_path(PSAVE),			% Restore path
366    ok.
367
368
369%% make_script: Check that make_script handles wildcards in path.
370wildcard_script(Config) when is_list(Config) ->
371    {ok, OldDir} = file:get_cwd(),
372
373    {LatestDir, LatestName} = create_script(latest,Config),
374
375    DataDir = filename:absname(?copydir),
376    LibDir = fname([DataDir, d_normal, lib]),
377    WildDir = fname([LibDir, '*', ebin]),
378
379    ok = file:set_cwd(LatestDir),
380
381    error = systools:make_script(filename:basename(LatestName)),
382
383    ok = systools:make_script(LatestName,
384			      [{path, [WildDir]}]),
385
386    {ok, _} = read_script_file(LatestName),	% Check readabillity
387
388    ok = file:set_cwd(OldDir),
389    ok.
390
391
392%% make_script: Add own installation dependent variable in script.
393variable_script(Config) when is_list(Config) ->
394    {ok, OldDir} = file:get_cwd(),
395
396    {LatestDir, LatestName} = create_script(latest,Config),
397
398    DataDir = filename:absname(?copydir),
399    LibDir = fname([DataDir, d_normal, lib]),
400    P = [fname([LibDir, 'db-2.1', ebin]),
401	 fname([LibDir, 'fe-3.1', ebin])],
402
403    ok = file:set_cwd(LatestDir),
404
405    ok = systools:make_script(LatestName,
406			      [{path, P},
407			       {variables, [{"TEST", LibDir}]}]),
408
409    %% Check variables
410    ok = check_var_script_file([fname(['$TEST', 'db-2.1', ebin]),
411				fname(['$TEST', 'fe-3.1', ebin])],
412			       P,
413			       LatestName),
414
415    ok = file:set_cwd(OldDir),
416    ok.
417
418%% make_script: Abnormal cases.
419abnormal_script(Config) when is_list(Config) ->
420    {ok, OldDir} = file:get_cwd(),
421
422    {LatestDir, LatestName} = create_script(latest,Config),
423
424    DataDir = filename:absname(?copydir),
425
426    ok = file:set_cwd(LatestDir),
427    LibDir = fname([DataDir, d_bad_app_vsn, lib]),
428    P = [fname([LibDir, 'db-2.1', ebin]),
429	 fname([LibDir, 'fe-3.1', ebin])],
430
431    %% Check wrong app vsn
432    error = systools:make_script(LatestName, [{path, P}]),
433    {error,
434     systools_make,
435     [{error_reading, {db, {no_valid_version,
436			    {{"should be","2.1"},
437			     {"found file", _, "2.0"}}}}}]} =
438	systools:make_script(LatestName, [silent, {path, P}]),
439
440    ok = file:set_cwd(OldDir),
441    ok.
442
443
444%% make_script: Create script without sasl appl. Check warning.
445no_sasl_script(Config) when is_list(Config) ->
446    {ok, OldDir} = file:get_cwd(),
447
448    {LatestDir, LatestName} = create_script(latest1_no_sasl,Config),
449
450    DataDir = filename:absname(?copydir),
451    LibDir = [fname([DataDir, d_normal, lib])],
452    P = [fname([LibDir, '*', ebin]),
453	 fname([DataDir, lib, kernel, ebin]),
454	 fname([DataDir, lib, stdlib, ebin]),
455	 fname([DataDir, lib, sasl, ebin])],
456
457    ok = file:set_cwd(LatestDir),
458
459    {ok, _ , [{warning,missing_sasl}]} =
460	systools:make_script(LatestName,[{path, P},silent]),
461
462    {error, systools_make, {warnings_treated_as_errors,[missing_sasl]}} =
463	systools:make_script(LatestName,[{path, P},silent,warnings_as_errors]),
464
465    {ok, _ , []} =
466	systools:make_script(LatestName,[{path, P},silent, no_warn_sasl]),
467
468    {ok, _ , []} =
469	systools:make_script(LatestName,[{path, P},silent, no_warn_sasl,
470                                         warnings_as_errors]),
471
472    ok = file:set_cwd(OldDir),
473    ok.
474
475%% make_script: Create script with no_dot_erlang. Check script contents.
476no_dot_erlang_script(Config) when is_list(Config) ->
477    {ok, OldDir} = file:get_cwd(),
478
479    {LatestDir, LatestName} = create_script(latest1_no_sasl,Config),
480
481    DataDir = filename:absname(?copydir),
482    LibDir = [fname([DataDir, d_normal, lib])],
483    P = [fname([LibDir, '*', ebin]),
484	 fname([DataDir, lib, kernel, ebin]),
485	 fname([DataDir, lib, stdlib, ebin]),
486	 fname([DataDir, lib, sasl, ebin])],
487
488    ok = file:set_cwd(LatestDir),
489
490    {ok, _ , []} =
491	systools:make_script(LatestName,[{path, P},silent, no_warn_sasl]),
492    {ok, [{_, _, LoadDotErlang}]} = read_script_file(LatestName),
493    [erlangrc] = [E || {apply, {c, E, []}} <- LoadDotErlang],
494
495    {ok, _ , []} =
496	systools:make_script(LatestName,[{path, P},silent, no_warn_sasl, no_dot_erlang]),
497    {ok, [{_, _, DoNotLoadDotErlang}]} = read_script_file(LatestName),
498    [] = [E || {apply, {c, E, []}} <- DoNotLoadDotErlang],
499
500    ok = file:set_cwd(OldDir),
501    ok.
502
503
504%% make_script: Do not check date of object file or that source code
505%% can be found.
506src_tests_script(Config) when is_list(Config) ->
507    {ok, OldDir} = file:get_cwd(),
508    PSAVE = code:get_path(),		% Save path
509
510    {LatestDir, LatestName} = create_script(latest,Config),
511    BootFile = LatestName ++ ".boot",
512
513    DataDir = filename:absname(?copydir),
514    LibDir = fname([DataDir, d_missing_src, lib]),
515    P1 = fname([LibDir, 'db-2.1', ebin]),
516    P2 = fname([LibDir, 'fe-3.1', ebin]),
517    N = [P1, P2],
518
519    ok = file:set_cwd(LatestDir),
520
521    %% Manipulate the modification date of a beam file so it seems
522    %% older than its .erl file
523    Erl = filename:join([P1,"..","src","db1.erl"]),
524    {ok, FileInfo=#file_info{mtime={{Y,M,D},T}}} = file:read_file_info(Erl),
525    Beam = filename:join(P1,"db1.beam"),
526    ok=file:write_file_info(Beam, FileInfo#file_info{mtime={{Y-1,M,D},T}}),
527
528    %% Remove a .erl file
529    Erl2 = filename:join([P1,"..","src","db2.erl"]),
530    file:delete(Erl2),
531
532    %% Then make script
533
534    %% .boot file should not exist
535    ok = file:delete(BootFile),
536    false = filelib:is_regular(BootFile),
537    %% With warnings_as_errors and src_tests option, an error should be issued
538    {error, systools_make,
539     {warnings_treated_as_errors, [{obj_out_of_date,_},
540                                   {source_not_found,_}]}} =
541	systools:make_script(LatestName, [silent, {path, N}, src_tests,
542					  warnings_as_errors]),
543    error =
544	systools:make_script(LatestName, [{path, N}, src_tests,
545					  warnings_as_errors]),
546
547    %% due to warnings_as_errors .boot file should still not exist
548    false = filelib:is_regular(BootFile),
549
550    %% Two warnings should be issued when src_tests is given
551    %% 1. old object code for db1.beam
552    %% 2. missing source code for db2.beam
553    {ok, _, [{warning,{obj_out_of_date,_}},
554	     {warning,{source_not_found,_}}]} =
555	systools:make_script(LatestName, [silent, {path, N}, src_tests]),
556
557    %% .boot file should exist now
558    true = filelib:is_regular(BootFile),
559
560    %% Without the src_tests option, no warning should be issued
561    {ok, _, []} =
562	systools:make_script(LatestName, [silent, {path, N}]),
563
564    %% Check that the old no_module_tests option (from the time when
565    %% it was default to do the src_test) is ignored
566    {ok, _, [{warning,{obj_out_of_date,_}},
567	     {warning,{source_not_found,_}}]} =
568	systools:make_script(LatestName, [silent,
569					  {path, N},
570					  no_module_tests,
571					  src_tests]),
572
573    ok = file:set_cwd(OldDir),
574    code:set_path(PSAVE),
575    ok.
576
577%% make_script: Do the crazy cases.
578crazy_script(Config) when is_list(Config) ->
579    {ok, OldDir} = file:get_cwd(),
580
581    {LatestDir, LatestName} = create_script(latest, Config),
582
583    DataDir = filename:absname(?copydir),
584    LibDir = fname([DataDir, d_normal, lib]),
585    P = [fname([LibDir, 'db-2.1', ebin]),
586	 fname([LibDir, 'fe-3.1', ebin])],
587
588    ok = file:set_cwd(LatestDir),
589
590    %% Run with bad path
591    error = systools:make_script(LatestName),
592    {error, _, [{error_reading, _}, {error_reading, _}]} =
593	systools:make_script(LatestName, [silent]),
594
595    %% Run with .rel file lacking kernel
596    {LatestDir2, LatestName2} = create_script(latest_nokernel, Config),
597    ok = file:set_cwd(LatestDir2),
598
599    error = systools:make_script(LatestName2),
600    {error, _, {missing_mandatory_app,kernel}} =
601	systools:make_script(LatestName2, [silent,{path,P}]),
602
603    %% Run with .rel file with non-permanent kernel
604    {LatestDir3, LatestName3} = create_script(latest_kernel_start_type, Config),
605    ok = file:set_cwd(LatestDir3),
606
607    error = systools:make_script(LatestName3),
608    {error, _, {mandatory_app,kernel,load}} =
609	systools:make_script(LatestName3, [silent,{path,P}]),
610
611    %% Run with .rel file with non-permanent stdlib
612    {LatestDir4, LatestName4} = create_script(latest_stdlib_start_type, Config),
613    ok = file:set_cwd(LatestDir4),
614
615    error = systools:make_script(LatestName4),
616    {error, _, {mandatory_app,stdlib,load}} =
617	systools:make_script(LatestName4, [silent,{path,P}]),
618
619    %% Run with .rel file lacking stdlib
620    {LatestDir5, LatestName5} = create_script(latest_no_stdlib, Config),
621    ok = file:set_cwd(LatestDir5),
622
623    error = systools:make_script(LatestName5),
624    {error, _, {missing_mandatory_app,stdlib}} =
625	systools:make_script(LatestName5, [silent,{path,P}]),
626
627    ok = file:set_cwd(OldDir),
628    ok.
629
630%% make_script: Check that make_script handles generation of script
631%% for applications with included applications.
632included_script(Config) when is_list(Config) ->
633    {ok, OldDir} = file:get_cwd(),
634    {LatestDir, LatestName} = create_include_files(inc1, Config),
635    ok = file:set_cwd(LatestDir),
636    ok = systools:make_script(LatestName),
637    ok = check_include_script(LatestName,
638			      [t1, t2, t3, t5, t4, t6],
639			      [t1, t3, t6]),
640    ok = file:set_cwd(OldDir),
641    ok.
642
643%% make_script: Check that make_script handles generation of script
644%% for applications with included applications which are override by
645%% the .rel file.
646included_override_script(Config) when is_list(Config) ->
647    {ok, OldDir} = file:get_cwd(),
648    {LatestDir, LatestName} = create_include_files(inc2, Config),
649    ok = file:set_cwd(LatestDir),
650    ok = systools:make_script(LatestName),
651    ok = check_include_script(LatestName,
652			      [t1, t2, t3, t4, t6, t5],
653			      [t1, t3, t6, t5]),
654
655    {_, LatestName1} = create_include_files(inc3, Config),
656    ok = systools:make_script(LatestName1),
657    ok = check_include_script(LatestName1,
658			      [t3, t5, t4, t6, t1, t2],
659			      [t3, t6, t1, t2]),
660
661    {_, LatestName2} = create_include_files(inc4, Config),
662    ok = systools:make_script(LatestName2),
663    ok = check_include_script(LatestName2,
664			      [t3, t4, t6, t5, t1, t2],
665			      [t3, t6, t5, t1, t2]),
666
667    {_, LatestName3} = create_include_files(inc5, Config),
668    ok = systools:make_script(LatestName3),
669    ok = check_include_script(LatestName3,
670			      [t3, t4, t6, t1, t2],
671			      [t3, t6, t1, t2]),
672
673    ok = file:set_cwd(OldDir),
674    ok.
675
676%% make_script: Check that make_script handles errors then generating
677%% script with included applications.
678included_fail_script(Config) when is_list(Config) ->
679    {ok, OldDir} = file:get_cwd(),
680    {LatestDir, LatestName} = create_include_files(inc6, Config),
681    ok = file:set_cwd(LatestDir),
682    {error, _, {undefined_applications,[t2]}} =
683	systools:make_script(LatestName, [silent]),
684
685    {_, LatestName1} = create_include_files(inc7, Config),
686    {error, _, {duplicate_include,[{{t5,t7,_,_},{t5,t6,_,_}}]}} =
687	systools:make_script(LatestName1, [silent]),
688
689    {_, LatestName3} = create_include_files(inc9, Config),
690    {error, _, {circular_dependencies,[{t10,_},{t8,_}]}} =
691	systools:make_script(LatestName3, [silent]),
692
693    {_, LatestName4} = create_include_files(inc10, Config),
694    {error, _, [{error_reading,{t9,{override_include,[t7]}}}]} =
695	systools:make_script(LatestName4, [silent]),
696
697    ok = file:set_cwd(OldDir),
698    ok.
699
700%% make_script: Check that make_script handles generation of script
701%% with difficult dependency for included applications.
702included_bug_script(Config) when is_list(Config) ->
703    {ok, OldDir} = file:get_cwd(),
704    {LatestDir, LatestName} = create_include_files(inc11, Config),
705    ok = file:set_cwd(LatestDir),
706    ok = systools:make_script(LatestName),
707    ok = check_include_script(LatestName,
708			      [t13, t11, t12],
709			      [t11, t12]),
710    ok = file:set_cwd(OldDir),
711    ok.
712
713
714%% make_script: Circular dependencies in systools:make_script().
715otp_3065_circular_dependenies(Config) when is_list(Config) ->
716    {ok, OldDir} = file:get_cwd(),
717    {LatestDir, LatestName} =
718	create_include_files(otp_3065_circular_dependenies, Config),
719    ok = file:set_cwd(LatestDir),
720    ok = systools:make_script(LatestName),
721    ok = check_include_script(LatestName,
722			      [aa12, chAts, chTraffic],
723			      [chTraffic]),
724    ok = file:set_cwd(OldDir),
725    ok.
726
727%% Test sorting of included applications and used applications
728included_and_used_sort_script(Config) when is_list(Config) ->
729    {ok, OldDir} = file:get_cwd(),
730    {LatestDir1, LatestName1} = create_include_files(sort_apps, Config),
731    ok = file:set_cwd(LatestDir1),
732    ok = systools:make_script(LatestName1),
733    ok = check_include_script(LatestName1,
734			      [t20,t19,t18,t17,t16,t15,t14],[t20,t19,t18,t14]),
735
736    {LatestDir2, LatestName2} = create_include_files(sort_apps_rev, Config),
737    ok = file:set_cwd(LatestDir2),
738    ok = systools:make_script(LatestName2),
739    ok = check_include_script(LatestName2,
740			      [t18,t19,t20,t15,t16,t17,t14],[t18,t19,t20,t14]),
741
742    ok = file:set_cwd(OldDir),
743    ok.
744
745
746%% make_script: Check that make_script exref option works.
747exref_script(Config) when is_list(Config) ->
748    {ok, OldDir} = file:get_cwd(),
749    PSAVE = code:get_path(),		% Save path
750
751    {LatestDir, LatestName} = create_script(latest,Config),
752
753    DataDir = filename:absname(?copydir),
754    LibDir = fname([DataDir, d_normal, lib]),
755    P = [fname([LibDir, 'db-2.1', ebin]),
756	 fname([LibDir, 'fe-3.1', ebin])],
757
758    ok = file:set_cwd(LatestDir),
759
760    {ok, _, []} = systools:make_script(LatestName, [{path,P}, silent]),
761
762    %% Complete exref
763    {ok, _, W1} =
764	systools:make_script(LatestName, [exref, {path,P}, silent]),
765    check_exref_warnings(with_db1, W1),
766    {ok, _} = read_script_file(LatestName),	% Check readabillity
767
768    %% Only exref the db application.
769    {ok, _, W2} =
770	systools:make_script(LatestName, [{exref,[db]}, {path,P}, silent]),
771    check_exref_warnings(with_db1, W2),
772    {ok, _} = read_script_file(LatestName),	% Check readabillity
773
774    %% Only exref the fe application.
775    {ok, _, W3} =
776	systools:make_script(LatestName, [{exref,[fe]}, {path,P}, silent]),
777    check_exref_warnings(without_db1, W3),
778    {ok, _} = read_script_file(LatestName),	% Check readabillity
779
780    %% exref the db and stdlib applications.
781    {ok, _, W4} =
782	systools:make_script(LatestName, [{exref,[db,stdlib]}, {path,P}, silent]),
783    check_exref_warnings(with_db1, W4),
784    {ok, _} = read_script_file(LatestName),	% Check readabillity
785    ok = file:set_cwd(OldDir),
786    code:set_path(PSAVE),			% Restore path
787    ok.
788
789check_exref_warnings(with_db1, W) ->
790    case get_exref(undef, W) of
791	{ok, [{db2,non_existing_func,0},
792	      {fe2,non_existing_func,0},
793	      {lists,non_existing_func,1}]} ->
794	    ok;
795	{ok, L} ->
796	    test_server:fail({exref_warning_undef, L});
797	_E ->
798	    test_server:fail({bad_undef,_E})
799    end;
800check_exref_warnings(without_db1, W) ->
801    case get_exref(undef, W) of
802	false ->
803	    ok;
804	{ok, L} ->
805	    test_server:fail({exref_warning_undef, L})
806    end.
807
808get_exref(undef, W)   -> filter(no_hipe(get_exref1(exref_undef, W))).
809
810filter(false) ->
811    false;
812filter({ok, W}) ->
813    {ok, filter(W)};
814filter(L) ->
815    lists:filter(fun%({hipe_consttab,_,_}) -> false;
816		     ({int,_,_}) -> false;
817		     ({i,_,_}) -> false;
818		     ({crypto,_,_}) -> false;
819		     (_) -> true
820		end,
821		 L).
822
823get_exref1(T, [{warning, {T, Value}}|_]) -> {ok, Value};
824get_exref1(T, [_|W])                     -> get_exref1(T, W);
825get_exref1(_, [])                        -> false.
826
827no_hipe(false) ->
828    false;
829no_hipe({ok, Value}) ->
830    case erlang:system_info(hipe_architecture) of
831	undefined ->
832	    Hipe = "hipe",
833	    Fun = fun({M,_,_}) -> not lists:prefix(Hipe, atom_to_list(M)) end,
834	    NewValue = lists:filter(Fun, Value),
835	    {ok, NewValue};
836	_Arch ->
837	    {ok, Value}
838    end.
839
840%% duplicate_modules_script: Check that make_script rejects two
841%% applications providing the same module.
842duplicate_modules_script(Config) when is_list(Config) ->
843    {ok, OldDir} = file:get_cwd(),
844
845    {LatestDir, LatestName} = create_script(duplicate_modules,Config),
846
847    DataDir = filename:absname(?copydir),
848
849    ok = file:set_cwd(LatestDir),
850    LibDir = fname([DataDir, d_duplicate_modules, lib]),
851    P = [fname([LibDir, 'app1-1.0', ebin]),
852	 fname([LibDir, 'app2-1.0', ebin])],
853
854    %% Check wrong app vsn
855    error = systools:make_script(LatestName, [{path, P}]),
856    {error,
857      systools_make,
858      {duplicate_modules, [
859          {{myapp,app1,_}, {myapp,app2,_}}
860        ]
861      }
862    } = systools:make_script(LatestName, [silent, {path, P}]),
863
864    ok = file:set_cwd(OldDir),
865    ok.
866
867%% tar_options: Check illegal tar options.
868tar_options(Config) when is_list(Config) ->
869    {'EXIT',{{badarg,[{path,["Path",12,"Another"]}]}, _}} =
870	(catch systools:make_tar("release", [{path,["Path",12,"Another"]}])),
871    {'EXIT',{{badarg,[sillent]}, _}} =
872	(catch systools:make_tar("release",
873				 [{path,["Path","Another"]},sillent])),
874    {'EXIT',{{badarg,[{dirs,["dirs"]}]}, _}} =
875	(catch systools:make_tar("release", [{dirs, ["dirs"]}])),
876    {'EXIT',{{badarg,[{erts, illegal}]}, _}} =
877	(catch systools:make_tar("release", [{erts, illegal}])),
878    {'EXIT',{{badarg,[src_testsxx]}, _}} =
879	(catch systools:make_tar("release",
880				 [{path,["Path"]},src_testsxx])),
881    {'EXIT',{{badarg,[{variables, [{a, b}, {"a", "b"}]}]}, _}} =
882	(catch systools:make_tar("release",
883				 [{variables, [{a, b}, {"a", "b"}]}])),
884    {'EXIT',{{badarg,[{var_tar, illegal}]}, _}} =
885	(catch systools:make_tar("release", [{var_tar, illegal}])),
886    {'EXIT',{{badarg,[exreff]}, _}} =
887	(catch systools:make_tar("release",
888				 [{path,["Path","Another"]},exreff])),
889    {'EXIT',{{badarg,[{exref,["appl"]}]}, _}} =
890	(catch systools:make_tar("release", [{exref,["appl"]}])),
891    {'EXIT',{{badarg,[{machine, "appl"}]}, _}} =
892	(catch systools:make_tar("release", [{machine,"appl"}])),
893    ok.
894
895
896%% make_tar: Check case of start.boot
897normal_tar(Config) when is_list(Config) ->
898    {ok, OldDir} = file:get_cwd(),
899
900    {LatestDir, LatestName} = create_script(latest,Config),
901
902    DataDir = filename:absname(?copydir),
903    LibDir = fname([DataDir, d_normal, lib]),
904    P = [fname([LibDir, 'db-2.1', ebin]),
905	 fname([LibDir, 'fe-3.1', ebin])],
906
907    ok = file:set_cwd(LatestDir),
908
909    {ok, _, []} = systools:make_script(LatestName, [silent, {path, P}, {script_name, "start"}]),
910    ok = systools:make_tar(LatestName, [{path, P}]),
911    ok = check_tar(fname([lib,'db-2.1',ebin,'db.app']), LatestName),
912    {ok, _, []} = systools:make_tar(LatestName, [{path, P}, silent]),
913    ok = check_tar(fname([lib,'fe-3.1',ebin,'fe.app']), LatestName),
914
915    ok = file:set_cwd(OldDir),
916    ok.
917
918%% make_tar: Check case of relname.boot
919relname_tar(Config) when is_list(Config) ->
920    {ok, OldDir} = file:get_cwd(),
921
922    {LatestDir, LatestName} = create_script(latest,Config),
923
924    DataDir = filename:absname(?copydir),
925    LibDir = fname([DataDir, d_normal, lib]),
926    P = [fname([LibDir, 'db-2.1', ebin]),
927	 fname([LibDir, 'fe-3.1', ebin])],
928
929    ok = file:set_cwd(LatestDir),
930
931    {ok, _, []} = systools:make_script(LatestName, [silent, {path, P}, {script_name, LatestName}]),
932    ok = systools:make_tar(LatestName, [{path, P}]),
933    ok = check_tar(fname([lib,'db-2.1',ebin,'db.app']), LatestName),
934    {ok, _, []} = systools:make_tar(LatestName, [{path, P}, silent]),
935    ok = check_tar(fname([lib,'fe-3.1',ebin,'fe.app']), LatestName),
936
937    ok = file:set_cwd(OldDir),
938    ok.
939
940%% make_tar: Modules specified without version in .app file (db-3.1).
941%% Note that this is now the normal way - i.e. systools now ignores
942%% the module versions in the .app file.
943no_mod_vsn_tar(Config) when is_list(Config) ->
944    {ok, OldDir} = file:get_cwd(),
945
946    {LatestDir, LatestName} = create_script(latest_no_mod_vsn,Config),
947
948    DataDir = filename:absname(?copydir),
949    LibDir = fname([DataDir, d_normal, lib]),
950    P = [fname([LibDir, 'db-3.1', ebin]),
951	 fname([LibDir, 'fe-3.1', ebin])],
952
953    ok = file:set_cwd(LatestDir),
954
955    {ok, _, []} = systools:make_script(LatestName, [silent, {path, P}]),
956    ok = systools:make_tar(LatestName, [{path, P}]),
957    ok = check_tar(fname([lib,'db-3.1',ebin,'db.app']), LatestName),
958    {ok, _, []} = systools:make_tar(LatestName, [{path, P}, silent]),
959    ok = check_tar(fname([lib,'fe-3.1',ebin,'fe.app']), LatestName),
960
961    ok = file:set_cwd(OldDir),
962    ok.
963
964
965%% make_tar: Check that relup or sys.config are included if they exist
966system_files_tar(Config) ->
967    {ok, OldDir} = file:get_cwd(),
968
969    {LatestDir, LatestName} = create_script(latest,Config),
970
971    DataDir = filename:absname(?copydir),
972    LibDir = fname([DataDir, d_normal, lib]),
973    P = [fname([LibDir, 'db-2.1', ebin]),
974	 fname([LibDir, 'fe-3.1', ebin])],
975
976    ok = file:set_cwd(LatestDir),
977
978    %% Add dummy relup and sys.config
979    ok = file:write_file("sys.config","[].\n"),
980    ok = file:write_file("relup","{\"LATEST\",[],[]}.\n"),
981
982    {ok, _, []} = systools:make_script(LatestName, [silent, {path, P}]),
983    ok = systools:make_tar(LatestName, [{path, P}]),
984    ok = check_tar(fname(["releases","LATEST","sys.config"]), LatestName),
985    ok = check_tar(fname(["releases","LATEST","relup"]), LatestName),
986    {ok, _, []} = systools:make_tar(LatestName, [{path, P}, silent]),
987    ok = check_tar(fname(["releases","LATEST","sys.config"]), LatestName),
988    ok = check_tar(fname(["releases","LATEST","relup"]), LatestName),
989
990    ok = file:set_cwd(OldDir),
991
992    ok.
993
994%% make_tar: Check that extra_files are included in the tarball
995additional_files_tar(Config) ->
996    {ok, OldDir} = file:get_cwd(),
997
998    {LatestDir, LatestName} = create_script(latest,Config),
999
1000    DataDir = filename:absname(?copydir),
1001    LibDir = fname([DataDir, d_normal, lib]),
1002    P = [fname([LibDir, 'db-2.1', ebin]),
1003	 fname([LibDir, 'fe-3.1', ebin])],
1004
1005    ok = file:set_cwd(LatestDir),
1006
1007    %% Add dummy relup and sys.config
1008    ok = file:write_file("sys.config","[].\n"),
1009    ok = file:write_file("relup","{\"LATEST\",[],[]}.\n"),
1010
1011    %% unrelated files that must be included explicitly
1012    RandomFile = "somefile",
1013    ok = file:write_file(RandomFile,"hello\n"),
1014
1015    TopLevelDir = "some_dir",
1016    TopLevelFile = filename:join(TopLevelDir, "top_level_file"),
1017
1018    filelib:ensure_dir(TopLevelFile),
1019    ok = file:write_file(TopLevelFile, "hello there\n"),
1020
1021    {ok, _, []} = systools:make_script(LatestName, [silent, {path, P}]),
1022    ok = systools:make_tar(LatestName, [{path, P}]),
1023    ok = check_tar(fname(["releases","LATEST","sys.config"]), LatestName),
1024    ok = check_tar(fname(["releases","LATEST","relup"]), LatestName),
1025    %% random file should not be in this tarball
1026    {error, _} = check_tar(fname(["releases","LATEST",RandomFile]), LatestName),
1027
1028    RandomFilePathInTar = filename:join(["releases", "LATEST", RandomFile]),
1029
1030    {ok, _, []} = systools:make_tar(LatestName,
1031                                    [{path, P}, silent,
1032                                     {extra_files, [{RandomFile, RandomFilePathInTar},
1033                                                    {TopLevelDir, TopLevelDir}]}]),
1034    ok = check_tar(fname(["releases","LATEST","sys.config"]), LatestName),
1035    ok = check_tar(fname(["releases","LATEST","relup"]), LatestName),
1036
1037    %% random file and dir should be in this tarball
1038    ok = check_tar(fname(["releases","LATEST",RandomFile]), LatestName),
1039    ok = check_tar(fname([TopLevelFile]), LatestName),
1040
1041    ok = file:set_cwd(OldDir),
1042
1043    ok.
1044
1045system_files_tar(cleanup,Config) ->
1046    Dir = ?privdir,
1047    file:delete(filename:join(Dir,"sys.config")),
1048    file:delete(filename:join(Dir,"relup")),
1049    ok.
1050
1051erts_tar(Config) ->
1052
1053    {ok, OldDir} = file:get_cwd(),
1054
1055    {LatestDir, LatestName} = create_script(current_all,Config),
1056
1057    ERTS_VSN = erlang:system_info(version),
1058    ERTS_DIR = fname(["erts-" ++ ERTS_VSN,bin]),
1059
1060    %% List of all expected executable files in erts/bin
1061    %% This list needs to be kept up to date whenever a file is
1062    %% added or removed.
1063    {Default, Ignored} =
1064        case os:type()  of
1065            {unix,_} ->
1066                {["beam.smp","dyn_erl","epmd","erl","erl_call","erl_child_setup",
1067                  "erlexec","erl.src","escript","heart","inet_gethost","run_erl",
1068                  "start","start_erl.src","start.src","to_erl"],
1069                 ["ct_run","dialyzer","erlc","typer","yielding_c_fun"]};
1070            {win32, _} ->
1071                {["beam.smp.pdb","erl.exe",
1072                  "erl.pdb","erl_log.exe","erlexec.dll","erlsrv.exe","heart.exe",
1073                  "start_erl.exe","werl.exe","beam.smp.dll",
1074                  "epmd.exe","erl.ini","erl_call.exe",
1075                  "erlexec.pdb","escript.exe","inet_gethost.exe","werl.pdb"],
1076                 ["dialyzer.exe","erlc.exe","yielding_c_fun.exe","ct_run.exe","typer.exe"]}
1077        end,
1078
1079    ErtsTarContent =
1080        fun(TarName) ->
1081                lists:sort(
1082                  [filename:basename(File)
1083                   || File <- tar_contents(TarName),
1084                      string:equal(filename:dirname(File),ERTS_DIR),
1085                      %% Filter out beam.*.smp.*
1086                      re:run(filename:basename(File), "beam\\.[^\\.]+\\.smp(\\.dll)?") == nomatch,
1087                      %% Filter out any erl_child_setup.*
1088                      re:run(filename:basename(File), "erl_child_setup\\..*") == nomatch
1089                  ])
1090        end,
1091
1092    DataDir = filename:absname(?copydir),
1093    LibDir = fname([DataDir, d_normal, lib]),
1094    P = [fname([LibDir, 'db-2.1', ebin])],
1095
1096    ok = file:set_cwd(LatestDir),
1097
1098    {ok, _, []} = systools:make_script(LatestName, [silent, {path, P}, {script_name, "start"}]),
1099    ok = systools:make_tar(LatestName, [{path, P}, {erts, code:root_dir()}]),
1100    ErtsContent = ErtsTarContent(LatestName),
1101
1102    case lists:sort(Default) of
1103        ErtsContent ->
1104            ok;
1105        Expected ->
1106            ct:pal("Content: ~p",[ErtsContent]),
1107            ct:pal("Expected: ~p",[Expected]),
1108            ct:fail("Incorrect erts bin content")
1109    end,
1110
1111    ok = systools:make_tar(LatestName, [{path, P},
1112                                        {erts, code:root_dir()},
1113                                        erts_all]),
1114    ErtsAllContent = ErtsTarContent(LatestName),
1115
1116    case lists:sort(Default ++ Ignored) of
1117        ErtsAllContent ->
1118            ok;
1119        ExpectedIgn ->
1120            ct:pal("Content: ~p",[ErtsAllContent]),
1121            ct:pal("Expected: ~p",[ExpectedIgn]),
1122            ct:fail("Incorrect erts bin content")
1123    end,
1124
1125    ok = file:set_cwd(OldDir),
1126    ok.
1127
1128
1129%% make_tar: Check that sys.config.src and not sys.config is included
1130system_src_file_tar(Config) ->
1131    {ok, OldDir} = file:get_cwd(),
1132
1133    {LatestDir, LatestName} = create_script(latest,Config),
1134
1135    DataDir = filename:absname(?copydir),
1136    LibDir = fname([DataDir, d_normal, lib]),
1137    P = [fname([LibDir, 'db-2.1', ebin]),
1138         fname([LibDir, 'fe-3.1', ebin])],
1139
1140    ok = file:set_cwd(LatestDir),
1141
1142    %% Add dummy sys.config and sys.config.src
1143    ok = file:write_file("sys.config.src","[${SOMETHING}].\n"),
1144    ok = file:write_file("sys.config","[].\n"),
1145
1146    {ok, _, _} = systools:make_script(LatestName, [silent, {path, P}]),
1147    ok = systools:make_tar(LatestName, [{path, P}]),
1148    ok = check_tar(fname(["releases","LATEST","sys.config.src"]), LatestName),
1149    {error, _} = check_tar(fname(["releases","LATEST","sys.config"]), LatestName),
1150    {ok, _, _} = systools:make_tar(LatestName, [{path, P}, silent]),
1151    ok = check_tar(fname(["releases","LATEST","sys.config.src"]), LatestName),
1152    {error, _} = check_tar(fname(["releases","LATEST","sys.config"]), LatestName),
1153
1154    ok = file:set_cwd(OldDir),
1155
1156    ok.
1157
1158system_src_file_tar(cleanup,Config) ->
1159    Dir = ?privdir,
1160    file:delete(filename:join(Dir,"sys.config")),
1161    file:delete(filename:join(Dir,"sys.config.src")),
1162    ok.
1163
1164%% make_tar: Check that make_tar fails if relup or sys.config exist
1165%% but do not have valid content
1166invalid_system_files_tar(Config) ->
1167    {ok, OldDir} = file:get_cwd(),
1168
1169    {LatestDir, LatestName} = create_script(latest,Config),
1170
1171    DataDir = filename:absname(?copydir),
1172    LibDir = fname([DataDir, d_normal, lib]),
1173    P = [fname([LibDir, 'db-2.1', ebin]),
1174	 fname([LibDir, 'fe-3.1', ebin])],
1175
1176    ok = file:set_cwd(LatestDir),
1177
1178    {ok, _, []} = systools:make_script(LatestName, [silent, {path, P}]),
1179
1180    %% Add dummy relup and sys.config - faulty sys.config
1181    ok = file:write_file("sys.config","[]\n"), %!!! syntax error - missing '.'
1182    ok = file:write_file("relup","{\"LATEST\",[],[]}.\n"),
1183
1184    error = systools:make_tar(LatestName, [{path, P}]),
1185    {error,_,{tar_error,{add,"sys.config",[{error,_}]}}} =
1186	systools:make_tar(LatestName, [{path, P}, silent]),
1187
1188    %% Add dummy relup and sys.config - faulty sys.config
1189    ok = file:write_file("sys.config","[x,y].\n"), %!!! faulty format
1190    ok = file:write_file("relup","{\"LATEST\",[],[]}.\n"),
1191
1192    error = systools:make_tar(LatestName, [{path, P}]),
1193    {error,_,{tar_error,{add,"sys.config",[invalid_format]}}} =
1194	systools:make_tar(LatestName, [{path, P}, silent]),
1195
1196    %% Add dummy relup and sys.config - faulty relup
1197    ok = file:write_file("sys.config","[]\n"),
1198    ok = file:write_file("relup","{\"LATEST\"\n"), %!!! syntax error - truncated
1199
1200    error = systools:make_tar(LatestName, [{path, P}]),
1201    {error,_,{tar_error,{add,"relup",[{error,_}]}}} =
1202	systools:make_tar(LatestName, [{path, P}, silent]),
1203
1204    %% Add dummy relup and sys.config - faulty relup
1205    ok = file:write_file("sys.config","[]\n"),
1206    ok = file:write_file("relup","[].\n"), %!!! faulty format
1207
1208    error = systools:make_tar(LatestName, [{path, P}]),
1209    {error,_,{tar_error,{add,"relup",[invalid_format]}}} =
1210	systools:make_tar(LatestName, [{path, P}, silent]),
1211
1212    ok = file:set_cwd(OldDir),
1213
1214    ok.
1215
1216invalid_system_files_tar(cleanup,Config) ->
1217    Dir = ?privdir,
1218    file:delete(filename:join(Dir,"sys.config")),
1219    file:delete(filename:join(Dir,"relup")),
1220    ok.
1221
1222
1223%% make_tar: Use variable and create separate tar (included in generated tar).
1224variable_tar(Config) when is_list(Config) ->
1225    {ok, OldDir} = file:get_cwd(),
1226
1227    {LatestDir, LatestName} = create_script(latest,Config),
1228
1229    DataDir = filename:absname(?copydir),
1230    LibDir = fname([DataDir, d_normal, lib]),
1231    P = [fname([LibDir, 'db-2.1', ebin]),
1232	 fname([LibDir, 'fe-3.1', ebin])],
1233
1234    ok = file:set_cwd(LatestDir),
1235
1236    {ok, _, []} = systools:make_script(LatestName,
1237				      [silent,
1238				       {path, P},
1239				       {variables,[{"TEST", LibDir}]}]),
1240
1241    ok = systools:make_tar(LatestName, [{path, P},
1242					{variables,[{"TEST", LibDir}]}]),
1243    ok = check_var_tar("TEST", LatestName),
1244
1245    {ok, _, []} = systools:make_tar(LatestName,
1246				   [{path, P}, silent,
1247				    {variables,[{"TEST", LibDir}]}]),
1248    ok = check_var_tar("TEST", LatestName),
1249
1250    ok = file:set_cwd(OldDir),
1251    ok.
1252
1253%% make_tar: Check that symlinks in applications are handled correctly.
1254link_tar(Config) when is_list(Config) ->
1255    {ok, OldDir} = file:get_cwd(),
1256
1257    {LatestDir, LatestName} = create_script(latest,Config),
1258
1259    DataDir = filename:absname(?copydir),
1260    LibDir = fname([DataDir, d_links, lib]),
1261    P = [fname([LibDir, 'db-2.1', ebin]),
1262	 fname([LibDir, 'fe-3.1', ebin])],
1263
1264    %% Make some links
1265    Db1Erl = fname(['db-2.1',src,'db1.erl']),
1266    NormalDb1Erl = fname([DataDir,d_normal,lib,Db1Erl]),
1267    LinkDb1Erl = fname([LibDir, Db1Erl]),
1268    ok = file:make_symlink(NormalDb1Erl, LinkDb1Erl),
1269    Db1Beam = fname(['db-2.1',ebin,'db1.beam']),
1270    NormalDb1Beam = fname([DataDir,d_normal,lib,Db1Beam]),
1271    LinkDb1Beam = fname([LibDir, Db1Beam]),
1272    ok = file:make_symlink(NormalDb1Beam, LinkDb1Beam),
1273    FeApp = fname(['fe-3.1',ebin,'fe.app']),
1274    NormalFeApp = fname([DataDir,d_normal,lib,FeApp]),
1275    LinkFeApp = fname([LibDir, FeApp]),
1276    ok = file:make_symlink(NormalFeApp, LinkFeApp),
1277
1278    %% Create the tar and check that the linked files are included as
1279    %% regular files
1280    ok = file:set_cwd(LatestDir),
1281
1282    {ok,_,[]} = systools:make_script(LatestName, [{path, P},silent]),
1283
1284    {ok, _, []} = systools:make_tar(LatestName, [{path, P}, silent]),
1285    ok = check_tar_regular(?privdir,
1286			   [fname([lib,FeApp]),
1287			    fname([lib,Db1Beam])],
1288			   LatestName),
1289
1290    {ok, _, []} = systools:make_tar(LatestName, [{path, P}, silent,
1291						 {dirs, [src]}]),
1292    ok = check_tar_regular(?privdir,
1293			   [fname([lib,FeApp]),
1294			    fname([lib,Db1Beam]),
1295			    fname([lib,Db1Erl])],
1296			   LatestName),
1297
1298    ok = file:set_cwd(OldDir),
1299    ok.
1300
1301%% make_tar: Do not check date of object file or that source code can be found.
1302src_tests_tar(Config) when is_list(Config) ->
1303    {ok, OldDir} = file:get_cwd(),
1304
1305    {LatestDir, LatestName} = create_script(latest,Config),
1306
1307    DataDir = filename:absname(?copydir),
1308    LibDir = fname([DataDir, d_missing_src, lib]),
1309    P1 = fname([LibDir, 'db-2.1', ebin]),
1310    P2 = fname([LibDir, 'fe-3.1', ebin]),
1311    P = [P1, P2],
1312
1313    ok = file:set_cwd(LatestDir),
1314
1315    %% Manipulate the modification date of a beam file so it seems
1316    %% older than the .erl file
1317    Erl = filename:join([P1,"..","src","db1.erl"]),
1318    {ok, FileInfo=#file_info{mtime={{Y,M,D},T}}} = file:read_file_info(Erl),
1319    Beam = filename:join(P1,"db1.beam"),
1320    ok = file:write_file_info(Beam, FileInfo#file_info{mtime={{Y-1,M,D},T}}),
1321
1322    %% Remove a .erl file
1323    Erl2 = filename:join([P1,"..","src","db2.erl"]),
1324    file:delete(Erl2),
1325
1326    ok = systools:make_script(LatestName, [{path, P}]),
1327
1328    %% Then make tar - two warnings should be issued when
1329    %% src_tests is given
1330    %% 1. old object code for db1.beam
1331    %% 2. missing source code for db2.beam
1332    {ok, _, [{warning,{obj_out_of_date,_}},
1333	     {warning,{source_not_found,_}}]} =
1334	systools:make_tar(LatestName, [{path, P}, silent,
1335				       {dirs, [src]},
1336				       src_tests]),
1337    ok = check_tar(fname([lib,'db-2.1',src,'db1.erl']), LatestName),
1338
1339    %% Without the src_tests option, no warning should be issued
1340    {ok, _, []} = systools:make_tar(LatestName, [{path, P}, silent,
1341						 {dirs, [src]}]),
1342    ok = check_tar(fname([lib,'db-2.1',src,'db1.erl']), LatestName),
1343
1344    %% Check that the old no_module_tests option (from the time when
1345    %% it was default to do the src_test) is ignored
1346    {ok, _, [{warning,{obj_out_of_date,_}},
1347	     {warning,{source_not_found,_}}]} =
1348	systools:make_tar(LatestName, [{path, P}, silent,
1349				       {dirs, [src]},
1350				       no_module_tests,
1351				       src_tests]),
1352    ok = check_tar(fname([lib,'db-2.1',src,'db1.erl']), LatestName),
1353
1354    ok = file:set_cwd(OldDir),
1355    ok.
1356
1357
1358%% make_tar: Check that make_tar handles generation and placement of
1359%% tar files for variables outside the main tar file.
1360%% Test the {var_tar, include | ownfile | omit} optio.
1361var_tar(Config) when is_list(Config) ->
1362    {ok, OldDir} = file:get_cwd(),
1363    PSAVE = code:get_path(),		% Save path
1364
1365    {LatestDir, LatestName} = create_script(latest,Config),
1366
1367    DataDir = filename:absname(?copydir),
1368    LibDir = fname([DataDir, d_normal, lib]),
1369    P = [fname([LibDir, 'db-2.1', ebin]),
1370	 fname([LibDir, 'fe-3.1', ebin])],
1371
1372    ok = file:set_cwd(LatestDir),
1373
1374    {ok, _, []} = systools:make_script(LatestName,
1375				      [silent,
1376				       {path, P},
1377				       {variables,[{"TEST", LibDir}]}]),
1378
1379    ok = systools:make_tar(LatestName, [{path, P},
1380					{var_tar, ownfile},
1381					{variables,[{"TEST", LibDir}]}]),
1382
1383    true = exists_tar_file("TEST"), %% Also removes the file !
1384    {error, {not_generated, _}} = check_var_tar("TEST", LatestName),
1385
1386    ok = systools:make_tar(LatestName, [{path, P},
1387					{var_tar, omit},
1388					{variables,[{"TEST", LibDir}]}]),
1389
1390    {error, {not_generated, _}} = check_var_tar("TEST", LatestName),
1391    false = exists_tar_file("TEST"),
1392
1393    ok = systools:make_tar(LatestName, [{path, P},
1394					{var_tar, include},
1395					{variables,[{"TEST", LibDir}]}]),
1396
1397    ok = check_var_tar("TEST", LatestName),
1398    false = exists_tar_file("TEST"),
1399
1400    ok = file:set_cwd(OldDir),
1401    code:set_path(PSAVE),
1402    ok.
1403
1404
1405%% make_tar: Check exref option.
1406exref_tar(Config) when is_list(Config) ->
1407    {ok, OldDir} = file:get_cwd(),
1408
1409    {LatestDir, LatestName} = create_script(latest,Config),
1410
1411    DataDir = filename:absname(?copydir),
1412    LibDir = fname([DataDir, d_normal, lib]),
1413    P = [fname([LibDir, 'db-2.1', ebin]),
1414	 fname([LibDir, 'fe-3.1', ebin])],
1415
1416    ok = file:set_cwd(LatestDir),
1417
1418    {ok, _, []} = systools:make_script(LatestName, [silent, {path, P}]),
1419
1420    %% Complete exref
1421    {ok, _, W1} =
1422	systools:make_tar(LatestName, [exref, {path, P}, silent]),
1423    check_exref_warnings(with_db1, W1),
1424    ok = check_tar(fname([lib,'db-2.1',ebin,'db.app']), LatestName),
1425
1426    %% Only exref the db application.
1427    {ok, _, W2} =
1428	systools:make_tar(LatestName, [{exref, [db]}, {path, P}, silent]),
1429    check_exref_warnings(with_db1, W2),
1430    ok = check_tar(fname([lib,'fe-3.1',ebin,'fe.app']), LatestName),
1431
1432    %% Only exref the fe application.
1433    {ok, _, W3} =
1434	systools:make_tar(LatestName, [{exref, [fe]}, {path, P}, silent]),
1435    check_exref_warnings(without_db1, W3),
1436    ok = check_tar(fname([lib,'db-2.1',ebin,'db.app']), LatestName),
1437
1438    %% exref the db and stdlib applications.
1439    {ok, _, W4} =
1440	systools:make_tar(LatestName, [{exref, [db, stdlib]},
1441				       {path, P}, silent]),
1442    check_exref_warnings(with_db1, W4),
1443    ok = check_tar(fname([lib,'fe-3.1',ebin,'fe.app']), LatestName),
1444
1445    ok = file:set_cwd(OldDir),
1446    ok.
1447
1448%% make_tar:  Create tar without sasl appl. Check warning.
1449no_sasl_tar(Config) when is_list(Config) ->
1450    {ok, OldDir} = file:get_cwd(),
1451
1452    {LatestDir, LatestName} = create_script(latest1_no_sasl,Config),
1453
1454    DataDir = filename:absname(?copydir),
1455    LibDir = fname([DataDir, d_normal, lib]),
1456    P = [fname([LibDir, '*', ebin]),
1457	 fname([DataDir, lib, kernel, ebin]),
1458	 fname([DataDir, lib, stdlib, ebin]),
1459	 fname([DataDir, lib, sasl, ebin])],
1460
1461    ok = file:set_cwd(LatestDir),
1462
1463    {ok, _, _} = systools:make_script(LatestName, [silent, {path, P}]),
1464    ok = systools:make_tar(LatestName, [{path, P}]),
1465    {ok, _, [{warning,missing_sasl}]} =
1466        systools:make_tar(LatestName, [{path, P}, silent]),
1467    {ok, _, []} =
1468        systools:make_tar(LatestName, [{path, P}, silent, no_warn_sasl]),
1469    {ok, _, []} =
1470        systools:make_tar(LatestName, [{path, P}, silent, no_warn_sasl,
1471                                       warnings_as_errors]),
1472    TarFile = LatestName ++ ".tar.gz",
1473    true = filelib:is_regular(TarFile),
1474    ok = file:delete(TarFile),
1475    {error, systools_make, {warnings_treated_as_errors,[missing_sasl]}} =
1476        systools:make_tar(LatestName, [{path, P}, silent, warnings_as_errors]),
1477    error =
1478        systools:make_tar(LatestName, [{path, P}, warnings_as_errors]),
1479    false = filelib:is_regular(TarFile),
1480
1481    ok = file:set_cwd(OldDir),
1482    ok.
1483
1484%% make_tar: OTP-9507 - make_tar failed when path given as just 'ebin'.
1485otp_9507_path_ebin(Config) when is_list(Config) ->
1486    {ok, OldDir} = file:get_cwd(),
1487
1488    {LatestDir, LatestName} = create_script(latest_small,Config),
1489
1490    DataDir = filename:absname(?copydir),
1491    LibDir = fname([DataDir, d_normal, lib]),
1492    FeDir = fname([LibDir, 'fe-3.1']),
1493
1494    ok = file:set_cwd(FeDir),
1495
1496    RelName = fname([LatestDir,LatestName]),
1497
1498    P1 = ["./ebin",
1499	  fname([DataDir, lib, kernel, ebin]),
1500	  fname([DataDir, lib, stdlib, ebin]),
1501	  fname([DataDir, lib, sasl, ebin])],
1502    {ok, _, []} = systools:make_script(RelName, [silent, {path, P1}]),
1503    ok = systools:make_tar(RelName, [{path, P1}]),
1504    Content1 = tar_contents(RelName),
1505
1506    P2 = ["ebin",
1507	  fname([DataDir, lib, kernel, ebin]),
1508	  fname([DataDir, lib, stdlib, ebin]),
1509	  fname([DataDir, lib, sasl, ebin])],
1510
1511    %% Tickets solves the following line - it used to fail with
1512    %% {function_clause,[{filename,join,[[]]},...}
1513    ok = systools:make_tar(RelName, [{path, P2}]),
1514    Content2 = tar_contents(RelName),
1515    true = (Content1 == Content2),
1516
1517    ok = file:set_cwd(OldDir),
1518
1519    ok.
1520
1521
1522%% make_relup: Check normal case
1523normal_relup(Config) when is_list(Config) ->
1524    {ok, OldDir} = file:get_cwd(),
1525
1526    {LatestDir,LatestName}   = create_script(latest0,Config),
1527    {_LatestDir1,LatestName1} = create_script(latest1,Config),
1528    {_LatestDir2,LatestName2} = create_script(latest2,Config),
1529
1530    DataDir = filename:absname(?copydir),
1531    LibDir = [fname([DataDir, d_normal, lib])],
1532    P = [fname([LibDir, '*', ebin]),
1533	 fname([DataDir, lib, kernel, ebin]),
1534	 fname([DataDir, lib, stdlib, ebin]),
1535	 fname([DataDir, lib, sasl, ebin])],
1536
1537    ok = file:set_cwd(LatestDir),
1538
1539    %% This is the ultra normal case
1540    ok = systools:make_relup(LatestName, [LatestName1], [LatestName1],
1541			     [{path, P}]),
1542    ok = check_relup([{db, "2.1"}], [{db, "1.0"}]),
1543    {ok, Relup, _, []} =
1544	systools:make_relup(LatestName, [LatestName1], [LatestName1],
1545			    [{path, P}, silent]),
1546    ok = check_relup([{db, "2.1"}], [{db, "1.0"}]),
1547
1548    %% file should not be written if warnings_as_errors is enabled.
1549    %% delete before running tests.
1550    ok = file:delete("relup"),
1551
1552    %% Check that warnings are treated as errors
1553    error =
1554	systools:make_relup(LatestName, [LatestName2], [LatestName1],
1555			    [{path, P}, warnings_as_errors]),
1556    {error, systools_relup,
1557     {warnings_treated_as_errors,[pre_R15_emulator_upgrade,
1558                                  {erts_vsn_changed, _}]}} =
1559	systools:make_relup(LatestName, [LatestName2], [LatestName1],
1560			    [{path, P}, silent, warnings_as_errors]),
1561
1562    %% relup file should not exist
1563    false = filelib:is_regular("relup"),
1564
1565    %% Check that warnings get through
1566    ok = systools:make_relup(LatestName, [LatestName2], [LatestName1],
1567			     [{path, P}]),
1568    ok = check_relup([{fe, "3.1"}, {db, "2.1"}], [{db, "1.0"}]),
1569    {ok, _, _, [pre_R15_emulator_upgrade,{erts_vsn_changed, _}]} =
1570	systools:make_relup(LatestName, [LatestName2], [LatestName1],
1571			    [{path, P}, silent]),
1572    ok = check_relup([{fe, "3.1"}, {db, "2.1"}], [{db, "1.0"}]),
1573
1574    %% relup file should exist now
1575    true = filelib:is_regular("relup"),
1576
1577    %% file should not be written if noexec option is used.
1578    %% delete before running tests.
1579    ok = file:delete("relup"),
1580    {ok,Relup,_,[]} =
1581        systools:make_relup(LatestName, [LatestName1], [LatestName1],
1582                            [{path, P}, noexec]),
1583    false = filelib:is_regular("relup"),
1584
1585    ok = file:set_cwd(OldDir),
1586    ok.
1587
1588
1589%% make_relup: Test relup which includes emulator restart.
1590restart_relup(Config) when is_list(Config) ->
1591    {ok, OldDir} = file:get_cwd(),
1592
1593    {LatestDir,LatestName}   = create_script(latest0,Config),
1594    {_LatestDir1,LatestName1} = create_script(latest1,Config),
1595    {_LatestDir0CurrErts,LatestName0CurrErts} =
1596	create_script(latest0_current_erts,Config),
1597    {_CurrentAllDir,CurrentAllName} = create_script(current_all,Config),
1598    {_CurrentAllFutErtsDir,CurrentAllFutErtsName} =
1599	create_script(current_all_future_erts,Config),
1600    {_CurrentAllFutSaslDir,CurrentAllFutSaslName} =
1601	create_script(current_all_future_sasl,Config),
1602
1603    DataDir = filename:absname(?copydir),
1604    LibDir = [fname([DataDir, d_normal, lib])],
1605    P = [fname([LibDir, '*', ebin]),
1606	 fname([DataDir, lib, kernel, ebin]),
1607	 fname([DataDir, lib, stdlib, ebin]),
1608	 fname([DataDir, lib, sasl, ebin]),
1609	 fname([DataDir, lib, 'sasl-9.9', ebin])],
1610
1611    ok = file:set_cwd(LatestDir),
1612
1613    %% OTP-2561: Check that the option 'restart_emulator' generates a
1614    %% "restart_emulator" instruction.
1615    {ok, _ , _, []} =
1616	systools:make_relup(LatestName, [LatestName1], [LatestName1],
1617			    [{path, P},restart_emulator,silent]),
1618    ok = check_relup([{db, "2.1"}], [{db, "1.0"}]),
1619    ok = check_restart_emulator(),
1620
1621
1622    %% Pre-R15 to Post-R15 upgrade
1623    {ok, _ , _, Ws} =
1624	systools:make_relup(LatestName0CurrErts,
1625			    [LatestName1],
1626			    [LatestName1],
1627			    [{path, P},silent]),
1628    ok = check_relup([{db,"2.1"}], [{db, "1.0"}]),
1629    ok = check_pre_to_post_r15_restart_emulator(),
1630    ok = check_pre_to_post_r15_warnings(Ws),
1631
1632
1633    %% Check that new sasl version generates a restart_new_emulator
1634    %% instruction
1635    {ok, _ , _, []} =
1636	systools:make_relup(CurrentAllFutSaslName,
1637			    [CurrentAllName],
1638			    [CurrentAllName],
1639			    [{path, P},silent]),
1640    ok = check_relup([{fe, "3.1"}], []),
1641    ok = check_restart_emulator_diff_coreapp(),
1642
1643
1644    %% Check that new erts version generates a restart_new_emulator
1645    %% instruction, if FromSaslVsn >= R15SaslVsn
1646    %% (One erts_vsn_changed warning for upgrade and one for downgrade)
1647    {ok, _ , _, [{erts_vsn_changed,_},{erts_vsn_changed,_}]} =
1648	systools:make_relup(CurrentAllFutErtsName,
1649			    [CurrentAllName],
1650			    [CurrentAllName],
1651			    [{path, P},silent]),
1652    ok = check_relup([{fe, "3.1"}], []),
1653    ok = check_restart_emulator_diff_coreapp(),
1654
1655
1656    %% Check that new erts version generates a restart_new_emulator
1657    %% instruction, and can be combined with restart_emulator opt.
1658    %% (One erts_vsn_changed warning for upgrade and one for downgrade)
1659    {ok, _ , _, [{erts_vsn_changed,_},{erts_vsn_changed,_}]} =
1660	systools:make_relup(CurrentAllFutErtsName,
1661			    [CurrentAllName],
1662			    [CurrentAllName],
1663			    [{path, P},restart_emulator,silent]),
1664    ok = check_relup([{fe, "3.1"}], []),
1665    ok = check_restart_emulator(),
1666    ok = check_restart_emulator_diff_coreapp(),
1667
1668    ok = file:set_cwd(OldDir),
1669    ok.
1670
1671
1672%% This test fails if wrong version numbers are seen in the relup file
1673%% or if any application is missing. This was triggered by OTP-1360.
1674check_relup(UpVsnL, DnVsnL) ->
1675    {ok, [{_V1, [{_, _, Up}], [{_, _, Dn}]}]} = file:consult(relup),
1676    [] = foldl(fun(X, Acc) ->
1677		       true = lists:member(X, Acc),
1678		       lists:delete(X, Acc) end,
1679	       UpVsnL,
1680	       [{App, Vsn} || {load_object_code,{App,Vsn,_}} <- Up]),
1681    [] = foldl(fun(X, Acc) ->
1682		       true = lists:member(X, Acc),
1683		       lists:delete(X, Acc) end,
1684	       DnVsnL,
1685	       [{App, Vsn} || {load_object_code,{App,Vsn,_}} <- Dn]),
1686    ok.
1687
1688check_relup_up_only(UpVsnL) ->
1689    {ok, [{_V1, [{_, _, Up}], []}]} = file:consult(relup),
1690    [] = foldl(fun(X, Acc) ->
1691		       true = lists:member(X, Acc),
1692		       lists:delete(X, Acc) end,
1693	       UpVsnL,
1694	       [{App, Vsn} || {load_object_code,{App,Vsn,_}} <- Up]),
1695    ok.
1696
1697check_restart_emulator() ->
1698    {ok, [{_V1, [{_, _, Up}], [{_, _, Dn}]}]} = file:consult(relup),
1699    restart_emulator = lists:last(Up),
1700    restart_emulator = lists:last(Dn),
1701    ok.
1702
1703check_restart_emulator_up_only() ->
1704    {ok, [{_V1, [{_, _, Up}], []}]} = file:consult(relup),
1705    restart_emulator = lists:last(Up),
1706    ok.
1707
1708check_restart_emulator_diff_coreapp() ->
1709    {ok, [{_V1, [{_, _, Up}], [{_, _, Dn}]}]} = file:consult(relup),
1710    [restart_new_emulator|_] = Up,
1711    restart_emulator = lists:last(Dn),
1712    ok.
1713
1714check_pre_to_post_r15_restart_emulator() ->
1715    {ok, [{_V1, [{_, _, Up}], [{_, _, Dn}]}]} = file:consult(relup),
1716    restart_new_emulator = lists:last(Up),
1717    restart_emulator = lists:last(Dn),
1718    ok.
1719
1720check_pre_to_post_r15_warnings(Ws) ->
1721    true = lists:member(pre_R15_emulator_upgrade,Ws),
1722    ok.
1723
1724%% make_relup: Check that appup files may be missing, but only if we
1725%% don't need them.
1726no_appup_relup(Config) when is_list(Config) ->
1727    {ok, OldDir} = file:get_cwd(),
1728
1729    {LatestDir,LatestName}   = create_script(latest_small,Config),
1730    {_LatestDir0,LatestName0} = create_script(latest_small0,Config),
1731    {_LatestDir1,LatestName1} = create_script(latest_small1,Config),
1732
1733    DataDir = filename:absname(?copydir),
1734
1735    ok = file:set_cwd(LatestDir),
1736
1737    %% Check that appup might be missing
1738    P1 = [fname([DataDir, d_no_appup, lib, 'fe-3.1', ebin]),
1739	  fname([DataDir, lib, kernel, ebin]),
1740	  fname([DataDir, lib, stdlib, ebin]),
1741	  fname([DataDir, lib, sasl, ebin])],
1742    ok =
1743	systools:make_relup(LatestName, [LatestName], [], [{path, P1}]),
1744    {ok,_, _, []} =
1745	systools:make_relup(LatestName, [LatestName], [],
1746			    [silent, {path, P1}]),
1747
1748    %% Check that appup might NOT be missing when we need it
1749    P2 = [fname([DataDir, d_no_appup, lib, 'fe-3.1', ebin]),
1750	  fname([DataDir, d_no_appup, lib, 'fe-2.1', ebin]),
1751	  fname([DataDir, lib, kernel, ebin]),
1752	  fname([DataDir, lib, stdlib, ebin]),
1753	  fname([DataDir, lib, sasl, ebin])],
1754    error =
1755	systools:make_relup(LatestName, [LatestName0], [], [{path, P2}]),
1756    {error,_,{file_problem, {_,{error,{open,_,_}}}}} =
1757	systools:make_relup(LatestName, [], [LatestName0],
1758			    [silent, {path, P2}]),
1759
1760    %% Check that appups missing vsn traps
1761    P3 = [fname([DataDir, d_no_appup, lib, 'fe-2.1', ebin]),
1762	  fname([DataDir, d_no_appup, lib, 'fe-500.18.7', ebin]),
1763	  fname([DataDir, lib, kernel, ebin]),
1764	  fname([DataDir, lib, stdlib, ebin]),
1765	  fname([DataDir, lib, sasl, ebin])],
1766
1767    error =
1768	systools:make_relup(LatestName0, [LatestName1], [], [{path, P3}]),
1769    {error,_,{no_relup, _, _, _}} =
1770	systools:make_relup(LatestName0, [], [LatestName1],
1771			    [silent, {path, P3}]),
1772
1773    ok = file:set_cwd(OldDir),
1774    ok.
1775
1776%% make_relup: Check that badly written appup files are detected.
1777bad_appup_relup(Config) when is_list(Config) ->
1778    {ok, OldDir} = file:get_cwd(),
1779
1780    {LatestDir,LatestName}   = create_script(latest_small,Config),
1781    {_LatestDir0,LatestName0} = create_script(latest_small0,Config),
1782
1783    DataDir = filename:absname(?copydir),
1784    N2 = [fname([DataDir, d_bad_appup, lib, 'fe-3.1', ebin]),
1785	  fname([DataDir, d_bad_appup, lib, 'fe-2.1', ebin]),
1786	  fname([DataDir, lib, kernel, ebin]),
1787	  fname([DataDir, lib, stdlib, ebin]),
1788	  fname([DataDir, lib, sasl, ebin])],
1789
1790    ok = file:set_cwd(LatestDir),
1791
1792    %% Check that bad appup is trapped
1793    error =
1794	systools:make_relup(LatestName, [LatestName0], [], [{path, N2}]),
1795    {error,_,{file_problem, {_, {error, {parse,_, _}}}}} =
1796	systools:make_relup(LatestName, [], [LatestName0],
1797			    [silent, {path, N2}]),
1798
1799    ok = file:set_cwd(OldDir),
1800    ok.
1801
1802%% make_relup: Check some abnormal cases.
1803abnormal_relup(Config) when is_list(Config) ->
1804    {ok, OldDir} = file:get_cwd(),
1805
1806    {LatestDir,LatestName}   = create_script(latest0,Config),
1807    {_LatestDir1,LatestName1} = create_script(latest1,Config),
1808
1809    %% Check wrong app vsn
1810    DataDir = filename:absname(?copydir),
1811    P = [fname([DataDir, d_bad_app_vsn, lib, 'db-2.1', ebin]),
1812	 fname([DataDir, d_bad_app_vsn, lib, 'fe-3.1', ebin]),
1813	 fname([DataDir, lib, kernel, ebin]),
1814	 fname([DataDir, lib, stdlib, ebin]),
1815	 fname([DataDir, lib, sasl, ebin])],
1816
1817    ok = file:set_cwd(LatestDir),
1818
1819    error = systools:make_relup(LatestName, [LatestName1], [LatestName1],
1820				[{path, P}]),
1821    R0 = systools:make_relup(LatestName, [LatestName1], [LatestName1],
1822			     [silent, {path, P}]),
1823    {error,systools_make,
1824     [{error_reading,{db,{no_valid_version,
1825			  {{"should be","2.1"},
1826			   {"found file", _, "2.0"}}}}}]} = R0,
1827    ok = file:set_cwd(OldDir),
1828    ok.
1829
1830
1831%% make_relup: Check relup cannot be created is sasl is not in rel file.
1832no_sasl_relup(Config) when is_list(Config) ->
1833    {ok, OldDir} = file:get_cwd(),
1834    {Dir1,Name1} = create_script(latest1_no_sasl,Config),
1835    {_Dir2,Name2} = create_script(latest1,Config),
1836
1837    DataDir = filename:absname(?copydir),
1838    LibDir = [fname([DataDir, d_normal, lib])],
1839    P = [fname([LibDir, '*', ebin]),
1840	 fname([DataDir, lib, kernel, ebin]),
1841	 fname([DataDir, lib, stdlib, ebin]),
1842	 fname([DataDir, lib, sasl, ebin])],
1843
1844    ok = file:set_cwd(Dir1),
1845
1846    error = systools:make_relup(Name2, [Name1], [Name1], [{path, P}]),
1847    R1 = systools:make_relup(Name2, [Name1], [Name1],[silent, {path, P}]),
1848    {error,systools_relup,{missing_sasl,_}} = R1,
1849
1850    error = systools:make_relup(Name1, [Name2], [Name2], [{path, P}]),
1851    R2 = systools:make_relup(Name1, [Name2], [Name2],[silent, {path, P}]),
1852    {error,systools_relup,{missing_sasl,_}} = R2,
1853
1854    ok = file:set_cwd(OldDir),
1855    ok.
1856
1857
1858%% make_relup: Check that application start type is used in relup
1859app_start_type_relup(Config) when is_list(Config) ->
1860    %% This might fail if some applications are not available, if so
1861    %% skip the test case.
1862    try create_script(latest_app_start_type2,Config) of
1863	{Dir2,Name2} ->
1864	    app_start_type_relup(Dir2,Name2,Config)
1865    catch throw:{error,Reason} ->
1866	    {skip,Reason}
1867    end.
1868
1869app_start_type_relup(Dir2,Name2,Config) ->
1870    PrivDir = ?config(priv_dir, Config),
1871    {Dir1,Name1} = create_script(latest_app_start_type1,Config),
1872
1873    Release1 = filename:join(Dir1,Name1),
1874    Release2 = filename:join(Dir2,Name2),
1875
1876    {ok, Release2Relup, systools_relup, []} = systools:make_relup(Release2, [Release1], [Release1], [{outdir, PrivDir}, silent]),
1877    {"LATEST_APP_START_TYPE2",
1878     [{"LATEST_APP_START_TYPE1",[], UpInstructions}],
1879     [{"LATEST_APP_START_TYPE1",[], DownInstructions}]} = Release2Relup,
1880    %% ?t:format("Up: ~p",[UpInstructions]),
1881    %% ?t:format("Dn: ~p",[DownInstructions]),
1882    [{load_object_code, {mnesia, _, _}},
1883     {load_object_code, {runtime_tools, _, _}},
1884     {load_object_code, {snmp, _, _}},
1885     {load_object_code, {xmerl, _, _}},
1886     point_of_no_return
1887     | UpInstructionsT] = UpInstructions,
1888    true = lists:member({apply,{application,start,[mnesia,permanent]}}, UpInstructionsT),
1889    true = lists:member({apply,{application,start,[runtime_tools,transient]}}, UpInstructionsT),
1890    true = lists:member({apply,{application,load,[snmp]}}, UpInstructionsT),
1891    false = lists:any(fun({apply,{application,_,[xmerl|_]}}) -> true; (_) -> false end, UpInstructionsT),
1892    [point_of_no_return | DownInstructionsT] = DownInstructions,
1893    true = lists:member({apply,{application,stop,[mnesia]}}, DownInstructionsT),
1894    true = lists:member({apply,{application,stop,[runtime_tools]}}, DownInstructionsT),
1895    true = lists:member({apply,{application,stop,[snmp]}}, DownInstructionsT),
1896    true = lists:member({apply,{application,stop,[xmerl]}}, DownInstructionsT),
1897    true = lists:member({apply,{application,unload,[mnesia]}}, DownInstructionsT),
1898    true = lists:member({apply,{application,unload,[runtime_tools]}}, DownInstructionsT),
1899    true = lists:member({apply,{application,unload,[snmp]}}, DownInstructionsT),
1900    true = lists:member({apply,{application,unload,[xmerl]}}, DownInstructionsT),
1901    ok.
1902
1903
1904%% make_relup: Check that regexp can be used in .appup for UpFromVsn
1905%% and DownToVsn.
1906regexp_relup(Config) ->
1907    {ok, OldDir} = file:get_cwd(),
1908
1909    {LatestDir,LatestName}   = create_script(latest_small,Config),
1910    {_LatestDir0,LatestName0} = create_script(latest_small0,Config),
1911    {_LatestDir1,LatestName1} = create_script(latest_small2,Config),
1912
1913    DataDir = filename:absname(?copydir),
1914    P = [fname([DataDir, d_regexp_appup, lib, '*', ebin]),
1915	 fname([DataDir, lib, kernel, ebin]),
1916	 fname([DataDir, lib, stdlib, ebin]),
1917	 fname([DataDir, lib, sasl, ebin])],
1918
1919    ok = file:set_cwd(LatestDir),
1920
1921    %% Upgrade fe 2.1 -> 3.1, and downgrade 2.1 -> 3.1
1922    %% Shall match the first entry if fe-3.1 appup.
1923    {ok, _, _, []} =
1924	systools:make_relup(LatestName, [LatestName0], [LatestName0],
1925			    [{path, P}, silent]),
1926    ok = check_relup([{fe, "3.1"}], [{fe, "2.1"}]),
1927
1928    %% Upgrade fe 2.1.1 -> 3.1
1929    %% Shall match the second entry in fe-3.1 appup. Have added a
1930    %% restart_emulator instruction there to distinguish it from
1931    %% the first entry...
1932    {ok, _, _, []} =
1933	systools:make_relup(LatestName, [LatestName1], [], [{path, P}, silent]),
1934    ok = check_relup_up_only([{fe, "3.1"}]),
1935    ok = check_restart_emulator_up_only(),
1936
1937    %% Attempt downgrade fe 3.1 -> 2.1.1
1938    %% Shall not match any entry!!
1939    {error,systools_relup,{no_relup,_,_,_}} =
1940	systools:make_relup(LatestName, [], [LatestName1], [{path, P}, silent]),
1941
1942    ok = file:set_cwd(OldDir),
1943
1944    ok.
1945
1946%% make_relup: Replace an application dependency with another
1947%%   The key part here is that the new application should be
1948%%   started before the old one is stopped.
1949replace_app_relup(Config) when is_list(Config) ->
1950    {ok, OldDir} = file:get_cwd(),
1951
1952    {LatestDir,LatestName}   = create_script(replace_app0,Config),
1953    {_LatestDir1,LatestName1} = create_script(replace_app1,Config),
1954
1955    DataDir = filename:absname(?copydir),
1956    LibDir = [fname([DataDir, d_replace_app, lib])],
1957    P = [fname([LibDir, '*', ebin]),
1958	 fname([DataDir, lib, kernel, ebin]),
1959	 fname([DataDir, lib, stdlib, ebin]),
1960	 fname([DataDir, lib, sasl, ebin])],
1961
1962    ok = file:set_cwd(LatestDir),
1963
1964    ok = systools:make_relup(LatestName, [LatestName1], [LatestName1],
1965			     [{path, P}]),
1966
1967    check_start_stop_order([{start,gh},{stop,fe}], [{start,fe},{stop,gh}]),
1968
1969    ok = file:set_cwd(OldDir),
1970    ok.
1971
1972
1973check_start_stop_order(UpOrder, DownOrder) ->
1974
1975    {ok, [{_V0, [{_V1, [], Up}],
1976                [{_V1, [], Down}]
1977            }]} = file:consult(relup),
1978
1979    GetAppStartStop = fun(Instr) ->
1980        [{Action,App} || {apply,{application,Action,[App|_]}} <- Instr,
1981                lists:member(Action,[start,stop])]
1982    end,
1983
1984    case GetAppStartStop(Up) of
1985        UpOrder -> ok;
1986        ActualUpOrder ->
1987          ct:fail("Incorrect upgrade order.~nExpected: ~p~nGot:~p",
1988                  [UpOrder,ActualUpOrder])
1989    end,
1990
1991    case GetAppStartStop(Down) of
1992        DownOrder -> ok;
1993        ActualDownOrder ->
1994          ct:fail("Incorrect down order.~nExpected: ~p~nGot:~p",
1995                  [DownOrder,ActualDownOrder])
1996    end,
1997
1998    ok.
1999
2000%% make_hybrid_boot: Normal case.
2001%% For upgrade of erts - create a boot file which is a hybrid between
2002%% old and new release - i.e. starts erts, kernel, stdlib, sasl from
2003%% new release, all other apps from old release.
2004normal_hybrid(Config) ->
2005    {ok, OldDir} = file:get_cwd(),
2006    {Dir1,Name1} = create_script(latest1,Config),
2007    {_Dir2,Name2} = create_script(current_all,Config),
2008
2009    DataDir = filename:absname(?copydir),
2010    LibDir = [fname([DataDir, d_normal, lib])],
2011    P = [fname([LibDir, '*', ebin]),
2012	 fname([DataDir, lib, kernel, ebin]),
2013	 fname([DataDir, lib, stdlib, ebin]),
2014	 fname([DataDir, lib, sasl, ebin])],
2015
2016    ok = file:set_cwd(Dir1),
2017
2018    {ok, _ , []} = systools:make_script(Name1,[{path, P},silent]),
2019    {ok, _ , []} = systools:make_script(Name2,[{path, P},silent]),
2020    {ok,Boot1} = file:read_file(Name1 ++ ".boot"),
2021    {ok,Boot2} = file:read_file(Name2 ++ ".boot"),
2022
2023    ok = file:set_cwd(OldDir),
2024
2025    {ok,Hybrid} = systools_make:make_hybrid_boot("tmp_vsn",Boot1,Boot2,
2026                                                 [dummy,args]),
2027
2028    {script,{"Test release","tmp_vsn"},Script} = binary_to_term(Hybrid),
2029    ct:log("~p.~n",[Script]),
2030
2031    %% Check that all paths to base apps are replaced by paths from BaseLib
2032    Boot1Str = io_lib:format("~p~n",[binary_to_term(Boot1)]),
2033    Boot2Str = io_lib:format("~p~n",[binary_to_term(Boot2)]),
2034    HybridStr = io_lib:format("~p~n",[binary_to_term(Hybrid)]),
2035    ReOpts = [global,{capture,first,list},unicode],
2036    {match,OldKernelMatch} = re:run(Boot1Str,"kernel-[0-9\.]+",ReOpts),
2037    {match,OldStdlibMatch} = re:run(Boot1Str,"stdlib-[0-9\.]+",ReOpts),
2038    {match,OldSaslMatch} = re:run(Boot1Str,"sasl-[0-9\.]+",ReOpts),
2039
2040    {match,NewKernelMatch} = re:run(Boot2Str,"kernel-[0-9\.]+",ReOpts),
2041    {match,NewStdlibMatch} = re:run(Boot2Str,"stdlib-[0-9\.]+",ReOpts),
2042    {match,NewSaslMatch} = re:run(Boot2Str,"sasl-[0-9\.]+",ReOpts),
2043
2044    {match,NewKernelMatch} = re:run(HybridStr,"kernel-[0-9\.]+",ReOpts),
2045    {match,NewStdlibMatch} = re:run(HybridStr,"stdlib-[0-9\.]+",ReOpts),
2046    {match,NewSaslMatch} = re:run(HybridStr,"sasl-[0-9\.]+",ReOpts),
2047
2048    NewKernelN = length(NewKernelMatch),
2049    NewKernelN = length(OldKernelMatch),
2050    NewStdlibN = length(NewStdlibMatch),
2051    NewStdlibN = length(OldStdlibMatch),
2052    NewSaslN = length(NewSaslMatch),
2053    NewSaslN = length(OldSaslMatch),
2054
2055    %% Check that kernelProcesses are taken from new boot script
2056    {script,_,Script2} = binary_to_term(Boot2),
2057    NewKernelProcs = [KP || KP={kernelProcess,_,_} <- Script2],
2058    NewKernelProcs = [KP || KP={kernelProcess,_,_} <- Script],
2059
2060    %% Check that application load instruction has correct versions
2061    Apps = application:loaded_applications(),
2062    {_,_,KernelVsn} = lists:keyfind(kernel,1,Apps),
2063    {_,_,StdlibVsn} = lists:keyfind(stdlib,1,Apps),
2064    {_,_,SaslVsn} = lists:keyfind(sasl,1,Apps),
2065
2066    [KernelInfo] = [I || {kernelProcess,application_controller,
2067			  {application_controller,start,
2068			   [{application,kernel,I}]}} <- Script],
2069    [StdlibInfo] = [I || {apply,
2070			  {application,load,
2071			   [{application,stdlib,I}]}} <- Script],
2072    [SaslInfo] = [I || {apply,
2073			{application,load,
2074			 [{application,sasl,I}]}} <- Script],
2075
2076    {vsn,KernelVsn} = lists:keyfind(vsn,1,KernelInfo),
2077    {vsn,StdlibVsn} = lists:keyfind(vsn,1,StdlibInfo),
2078    {vsn,SaslVsn} = lists:keyfind(vsn,1,SaslInfo),
2079
2080    %% Check that new_emulator_upgrade call is added
2081    [_,{apply,{release_handler,new_emulator_upgrade,[dummy,args]}}|_] =
2082	lists:reverse(Script),
2083
2084    %% Check that db-1.0 and fe-3.1 are used (i.e. vsns from old release)
2085    %% And that fe is in there (it exists in old rel but not in new)
2086    {match,DbMatch} = re:run(HybridStr,"db-[0-9\.]+",ReOpts),
2087    {match,[_|_]=FeMatch} = re:run(HybridStr,"fe-[0-9\.]+",ReOpts),
2088    true = lists:all(fun(["db-1.0"]) -> true;
2089			(_)  -> false
2090		     end,
2091		     DbMatch),
2092    true = lists:all(fun(["fe-3.1"]) -> true;
2093			(_)  -> false
2094		     end,
2095		     FeMatch),
2096
2097    %% Check that script has same length as old script, plus one (the
2098    %% new_emulator_upgrade apply)
2099    {_,_,Old} = binary_to_term(Boot1),
2100    OldLength = length(Old),
2101    NewLength = length(Script),
2102    NewLength = OldLength + 1,
2103
2104    ok.
2105
2106%% make_hybrid_boot: No sasl in from-release.
2107%% Check that systools_make:make_hybrid_boot fails with a meaningful
2108%% error message if the FromBoot does not include the sasl
2109%% application.
2110hybrid_no_old_sasl(Config) ->
2111    {ok, OldDir} = file:get_cwd(),
2112    {Dir1,Name1} = create_script(latest1_no_sasl,Config),
2113    {_Dir2,Name2} = create_script(current_all,Config),
2114
2115    DataDir = filename:absname(?copydir),
2116    LibDir = [fname([DataDir, d_normal, lib])],
2117    P = [fname([LibDir, '*', ebin]),
2118	 fname([DataDir, lib, kernel, ebin]),
2119	 fname([DataDir, lib, stdlib, ebin]),
2120	 fname([DataDir, lib, sasl, ebin])],
2121
2122    ok = file:set_cwd(Dir1),
2123
2124    {ok, _ , [{warning,missing_sasl}]} =
2125	systools:make_script(Name1,[{path, P},silent]),
2126    {ok, _ , []} = systools:make_script(Name2,[{path, P},silent]),
2127    {ok,Boot1} = file:read_file(Name1 ++ ".boot"),
2128    {ok,Boot2} = file:read_file(Name2 ++ ".boot"),
2129
2130    {error,{app_not_replaced,sasl}} =
2131	systools_make:make_hybrid_boot("tmp_vsn",Boot1,Boot2,[dummy,args]),
2132
2133    ok = file:set_cwd(OldDir),
2134    ok.
2135
2136
2137%% make_hybrid_boot: No sasl in to-release.
2138%% Check that systools_make:make_hybrid_boot fails with a meaningful
2139%% error message if the ToBoot does not include the sasl
2140%% application.
2141hybrid_no_new_sasl(Config) ->
2142    {ok, OldDir} = file:get_cwd(),
2143    {Dir1,Name1} = create_script(latest1,Config),
2144    {_Dir2,Name2} = create_script(current_all_no_sasl,Config),
2145
2146    DataDir = filename:absname(?copydir),
2147    LibDir = [fname([DataDir, d_normal, lib])],
2148    P = [fname([LibDir, '*', ebin]),
2149	 fname([DataDir, lib, kernel, ebin]),
2150	 fname([DataDir, lib, stdlib, ebin]),
2151	 fname([DataDir, lib, sasl, ebin])],
2152
2153    ok = file:set_cwd(Dir1),
2154
2155    {ok, _ , []} = systools:make_script(Name1,[{path, P},silent]),
2156    {ok, _ , [{warning,missing_sasl}]} =
2157	systools:make_script(Name2,[{path, P},silent]),
2158    {ok,Boot1} = file:read_file(Name1 ++ ".boot"),
2159    {ok,Boot2} = file:read_file(Name2 ++ ".boot"),
2160
2161    {error,{app_not_found,sasl}} =
2162	systools_make:make_hybrid_boot("tmp_vsn",Boot1,Boot2,[dummy,args]),
2163
2164    ok = file:set_cwd(OldDir),
2165    ok.
2166
2167
2168
2169%% options: {outdir,Dir} option
2170otp_6226_outdir(Config) when is_list(Config) ->
2171    PrivDir = ?privdir,
2172    {ok, OldDir} = file:get_cwd(),
2173
2174    {LatestDir, LatestName} = create_script(latest0,Config),
2175    {_LatestDir, LatestName1} = create_script(latest1,Config),
2176
2177    DataDir = filename:absname(?copydir),
2178    LibDir = fname([DataDir, d_normal, lib]),
2179    P = [fname([LibDir, 'db-2.1', ebin]),
2180	 fname([LibDir, 'db-1.0', ebin]),
2181	 fname([LibDir, 'fe-3.1', ebin]),
2182	 fname([DataDir, lib, kernel, ebin]),
2183	 fname([DataDir, lib, stdlib, ebin]),
2184	 fname([DataDir, lib, sasl, ebin])],
2185
2186    ok = file:set_cwd(LatestDir),
2187
2188
2189    %% Create an outdir1 directory
2190    ok = file:make_dir("outdir1"),
2191
2192    %% ==== Now test systools:make_script ====
2193    %% a) badarg
2194    {'EXIT', {{badarg,[{outdir,outdir1}]}, _}} =
2195	(catch systools:make_script(LatestName, [{outdir,outdir1},
2196						 {path,P},silent])),
2197
2198    %% b) absolute path
2199    Outdir1 = filename:join(PrivDir, "outdir1"),
2200    {ok,_,[]} = systools:make_script(LatestName, [{outdir,Outdir1},
2201						  {path,P},silent]),
2202    Script1 = filename:join(Outdir1, LatestName ++ ".script"),
2203    Boot1 = filename:join(Outdir1, LatestName ++ ".boot"),
2204    true = filelib:is_file(Script1),
2205    true = filelib:is_file(Boot1),
2206    ok = file:delete(Script1),
2207    ok = file:delete(Boot1),
2208
2209    %% c) relative path
2210    {ok,_,[]} = systools:make_script(LatestName, [{outdir,"./outdir1"},
2211						  {path,P},silent]),
2212    true = filelib:is_file(Script1),
2213    true = filelib:is_file(Boot1),
2214    ok = file:delete(Script1),
2215    ok = file:delete(Boot1),
2216
2217    %% d) absolute but incorrect path
2218    Outdir2 = filename:join(PrivDir, "outdir2"),
2219    Script2 = filename:join(Outdir2, LatestName ++ ".script"),
2220    {error,_,{open,Script2,_}} =
2221	systools:make_script(LatestName, [{outdir,Outdir2},{path,P},silent]),
2222
2223    %% e) relative but incorrect path
2224    {error,_,{open,_,_}} =
2225	systools:make_script(LatestName, [{outdir,"./outdir2"},{path,P},silent]),
2226
2227    %% f) with .rel in another directory than cwd
2228    ok = file:set_cwd(Outdir1),
2229    {ok,_,[]} = systools:make_script(filename:join(PrivDir, LatestName),
2230				     [{outdir,"."},{path,P},silent]),
2231    true = filelib:is_file(LatestName ++ ".script"),
2232    true = filelib:is_file(LatestName ++ ".boot"),
2233    ok = file:delete(LatestName ++ ".script"),
2234    ok = file:delete(LatestName ++ ".boot"),
2235    ok = file:set_cwd(LatestDir),
2236
2237    %% ==== Now test systools:make_tar =====
2238    {ok,_,[]} = systools:make_script(LatestName, [{path,P},silent]),
2239    %% a) badarg
2240    {'EXIT', {{badarg, [{outdir,outdir1}]}, _}} =
2241    	(catch systools:make_tar(LatestName,[{outdir,outdir1},{path,P},silent])),
2242
2243    %% b) absolute path
2244    {ok,_,[]} = systools:make_tar(LatestName, [{outdir,Outdir1},
2245					       {path,P},silent]),
2246    Tar1 = filename:join(Outdir1,LatestName++".tar.gz"),
2247    true = filelib:is_file(Tar1),
2248    ok = file:delete(Tar1),
2249
2250    %% c) relative path
2251    {ok,_,[]} = systools:make_tar(LatestName, [{outdir,"./outdir1"},
2252					       {path,P},silent]),
2253    true = filelib:is_file(Tar1),
2254    ok = file:delete(Tar1),
2255
2256    %% d) absolute but incorrect path
2257    Tar2 = filename:join(Outdir2,LatestName++".tar.gz"),
2258    {error,_,{tar_error,{open,Tar2,{Tar2,enoent}}}} =
2259	systools:make_tar(LatestName, [{outdir,Outdir2},{path,P},silent]),
2260
2261    %% e) relative but incorrect path
2262    {error,_,{tar_error,{open,_,_}}} =
2263	systools:make_tar(LatestName, [{outdir,"./outdir2"},{path,P},silent]),
2264
2265    %% f) with .rel in another directory than cwd
2266    ok = file:set_cwd(Outdir1),
2267    {ok,_,[]} = systools:make_tar(filename:join(PrivDir, LatestName),
2268				  [{outdir,"."},{path,P},silent]),
2269    true = filelib:is_file(Tar1),
2270    ok = file:set_cwd(LatestDir),
2271
2272    %% ===== Now test systools:make_relup =====
2273    %% a) badarg
2274    {'EXIT', {{badarg, [{outdir,outdir1}]}, _}} =
2275    	(catch systools:make_relup(LatestName,[LatestName1],[LatestName1],
2276    				   [{outdir,outdir1},
2277				    {path,P},silent])),
2278
2279    %% b) absolute path
2280    Relup = filename:join(Outdir1, "relup"),
2281    {ok,_,_,[]} = systools:make_relup(LatestName,[LatestName1],[LatestName1],
2282				      [{outdir,Outdir1},
2283				       {path,P},silent]),
2284    true = filelib:is_file(Relup),
2285    ok = file:delete(Relup),
2286
2287    %% c) relative path
2288    {ok,_,_,[]} = systools:make_relup(LatestName,[LatestName1],[LatestName1],
2289				      [{outdir,"./outdir1"},
2290				       {path,P},silent]),
2291    true = filelib:is_file(Relup),
2292    ok = file:delete(Relup),
2293
2294    %% d) absolute but incorrect path
2295    {error,_,{file_problem,{"relup",{open,enoent}}}} =
2296	systools:make_relup(LatestName,[LatestName1],[LatestName1],
2297			    [{outdir,Outdir2},{path,P},silent]),
2298
2299    %% e) relative but incorrect path
2300    {error,_,{file_problem,{"relup",{open,enoent}}}} =
2301	systools:make_relup(LatestName,[LatestName1],[LatestName1],
2302			    [{outdir,"./outdir2"},{path,P},silent]),
2303
2304    %% f) with .rel in another directory than cwd
2305    %% -- not necessary to test since relup by default is placed in
2306    %%    cwd, not in the same directory as the .rel file --
2307
2308    %% Change back to previous working directory
2309    ok = file:set_cwd(OldDir),
2310    ok.
2311
2312
2313%% Test that all default values can be used as values in the .app file
2314app_file_defaults(Config) ->
2315    PrivDir = ?config(priv_dir,Config),
2316    Name = app1,
2317    NameStr = atom_to_list(Name),
2318    Vsn = "1.0",
2319    AppSpec = app_spec(Name,#{vsn=>"1.0"}),
2320    ok = file:write_file(filename:join(PrivDir,NameStr ++ ".app"),
2321			 io_lib:format("~p.~n",[AppSpec])),
2322    {ok,_} = systools_make:read_application(NameStr,Vsn,[PrivDir],[]),
2323    ok.
2324
2325app_spec(Name,New) ->
2326    {application,Name,app_spec(New)}.
2327
2328app_spec(New) ->
2329    Default = #{description => "",
2330		id => "",
2331		vsn => "",
2332		modules => [],
2333		maxP => infinity,
2334		maxT => infinity,
2335		registered => [],
2336		included_applications => [],
2337		applications => [],
2338		env => [],
2339		mod => [],
2340		start_phases => undefined,
2341		runtime_dependencies => []},
2342    maps:to_list(maps:merge(Default,New)).
2343
2344%%%%%%
2345%%%%%% Utilities
2346%%%%%%
2347
2348check_script_path(RelName) ->
2349    {ok, [Conts]} = read_script_file(RelName),
2350    {script, {_, _}, ListOfThings} = Conts,
2351    case lists:keysearch(path, 1, ListOfThings) of
2352	{value, {path, [$$,$R,$O,$O,$T | _]}} -> %"$ROOT..."
2353	    false;
2354	_ -> ok
2355    end.
2356
2357check_var_script_file(VarDirs, NoExistDirs, RelName) ->
2358    {ok, [Conts]} = read_script_file(RelName),
2359    {script, {_, _}, ListOfThings} = Conts,
2360    AllPaths = lists:append(lists:map(fun({path, P}) -> P;
2361					 (_)         -> []
2362				      end,
2363				      ListOfThings)),
2364    case lists:filter(fun(VarDir) -> lists:member(VarDir, AllPaths) end,
2365		      VarDirs) of
2366	VarDirs ->
2367	    ok;
2368	_ ->
2369	    test_server:fail("All variable dirs not in generated script")
2370    end,
2371    case lists:filter(fun(NoExistDir) -> lists:member(NoExistDir, AllPaths) end,
2372		      NoExistDirs) of
2373	[] ->
2374	    ok;
2375	_ ->
2376	    test_server:fail("Unexpected dirs in generated script")
2377    end.
2378
2379check_include_script(RelName, ExpectedLoad, ExpectedStart) ->
2380    {ok, [Conts]} = read_script_file(RelName),
2381    {script, {_, _}, ListOfThings} = Conts,
2382
2383    %% Check that the applications are loaded in given order !
2384    ActualLoad =
2385	[App || {apply,{application,load,[{application,App,_}]}} <- ListOfThings,
2386		App=/=kernel,
2387		App=/=stdlib],
2388
2389    if ActualLoad =:= ExpectedLoad -> ok;
2390       true -> test_server:fail({bad_load_order, ActualLoad, ExpectedLoad})
2391    end,
2392
2393    %% Check that applications are started in given order !
2394    ActualStart =
2395	[App || {apply,{application,start_boot,[App|_]}} <- ListOfThings,
2396		App =/= kernel,
2397		App =/= stdlib],
2398
2399    if ActualStart =:= ExpectedStart -> ok;
2400       true -> test_server:fail({bad_start_order, ActualStart,ExpectedStart})
2401    end,
2402
2403    ok.
2404
2405read_script_file(RelName) ->
2406    file:consult(RelName ++ ".script").
2407
2408check_var_tar(Variable, RelName) ->
2409    Expected = tar_name(Variable),
2410    case check_tar(Expected,RelName) of
2411	ok ->
2412	    ok;
2413	{error, {erroneous_tar_file, _, missing, _}} ->
2414	    {error, {not_generated, Expected}}
2415    end.
2416
2417exists_tar_file(Name) ->
2418    File = tar_name(Name),
2419    case filelib:is_regular(File) of
2420	true ->
2421	    ok = file:delete(File),
2422	    true;
2423	_ ->
2424	    false
2425    end.
2426
2427%% Take a snap of the generated tar file and check if a certain
2428%% file is included.
2429%% This ensures at least that the tar file is generated.
2430check_tar(File, RelName) ->
2431    TarContents = tar_contents(RelName),
2432    case lists:member(File,TarContents) of
2433	true -> ok;
2434	_    -> {error, {erroneous_tar_file, tar_name(RelName), missing, File}}
2435    end.
2436
2437%% Check that the given files exist in the tar file, and that they are
2438%% not symlinks
2439check_tar_regular(PrivDir, Files, RelName) ->
2440    TmpDir = fname(PrivDir,tmp),
2441    ok = file:make_dir(TmpDir),
2442    ok = erl_tar:extract(tar_name(RelName),
2443			 [{files,Files},{cwd,TmpDir},compressed]),
2444    R = lists:foldl(fun(File,Acc) ->
2445			    case file:read_link_info(fname(TmpDir,File)) of
2446				{ok,#file_info{type=regular}} ->
2447				    Acc;
2448				{ok,#file_info{type=Other}} ->
2449				    [{File,Other}|Acc];
2450				_ ->
2451				    [{File,missing}|Acc]
2452			    end
2453		    end,
2454		    [],
2455		    Files),
2456    delete_tree(TmpDir),
2457    case R of
2458	[] ->
2459	    ok;
2460	NotThere ->
2461	    {error,{erroneous_tar_file,tar_name(RelName),NotThere}}
2462    end.
2463
2464delete_tree(Dir) ->
2465    case filelib:is_dir(Dir) of
2466	true ->
2467	    {ok,Files} = file:list_dir(Dir),
2468	    lists:foreach(fun(File) -> delete_tree(filename:join(Dir,File)) end,
2469			  Files),
2470	    file:del_dir(Dir);
2471	false ->
2472	    ok = file:delete(Dir)
2473    end.
2474
2475tar_contents(Name) ->
2476    {ok, Cont} = erl_tar:table(tar_name(Name), [compressed]),
2477    Cont.
2478
2479tar_name(Name) ->
2480    Name ++ ".tar.gz".
2481
2482create_script(latest,Config) ->
2483    Apps = core_apps(current) ++ [{db,"2.1"},{fe,"3.1"}],
2484    do_create_script(latest,Config,"4.4",Apps);
2485create_script(latest_no_mod_vsn,Config) ->
2486    Apps = core_apps(current) ++ [{db,"3.1"},{fe,"3.1"}],
2487    do_create_script(latest_no_mod_vsn,Config,"4.4",Apps);
2488create_script(latest0,Config) ->
2489    Apps = core_apps("1.0") ++ [{db,"2.1"},{fe,"3.1"}],
2490    do_create_script(latest0,Config,"4.4",Apps);
2491create_script(latest0_current_erts,Config) ->
2492    Apps = core_apps("1.0") ++ [{db,"2.1"},{fe,"3.1"}],
2493    do_create_script(latest0_current_erts,Config,current,Apps);
2494create_script(latest1,Config) ->
2495    Apps = core_apps("1.0") ++ [{db,"1.0"},{fe,"3.1"}],
2496    do_create_script(latest1,Config,"4.4",Apps);
2497create_script(latest1_no_sasl,Config) ->
2498    Apps = [{kernel,"1.0"},{stdlib,"1.0"},{db,"1.0"},{fe,"3.1"}],
2499    do_create_script(latest1_no_sasl,Config,"4.4",Apps);
2500create_script(latest2,Config) ->
2501    Apps = core_apps("1.0") ++ [{db,"1.0"},{fe,"2.1"}],
2502    do_create_script(latest2,Config,"4.3",Apps);
2503create_script(latest_small,Config) ->
2504    Apps = core_apps("1.0") ++ [{fe,"3.1"}],
2505    do_create_script(latest_small,Config,"4.4",Apps);
2506create_script(latest_small0,Config) ->		%Differs in fe vsn
2507    Apps = core_apps("1.0") ++ [{fe,"2.1"}],
2508    do_create_script(latest_small0,Config,"4.4",Apps);
2509create_script(latest_small1,Config) ->
2510    Apps = core_apps("1.0") ++ [{fe,"500.18.7"}],
2511    do_create_script(latest_small1,Config,"4.4",Apps);
2512create_script(latest_small2,Config) ->
2513    Apps = core_apps("1.0") ++ [{fe,"2.1.1"}],
2514    do_create_script(latest_small2,Config,"4.4",Apps);
2515create_script(latest_nokernel,Config) ->
2516    Apps = [{db,"2.1"},{fe,"3.1"}],
2517    do_create_script(latest_nokernel,Config,"4.4",Apps);
2518create_script(latest_kernel_start_type,Config) ->
2519    Apps = [{kernel,"1.0",load},{stdlib,"1.0"},{db,"2.1"},{fe,"3.1"}],
2520    do_create_script(latest_kernel_start_type,Config,"4.4",Apps);
2521create_script(latest_stdlib_start_type,Config) ->
2522    Apps = [{kernel,"1.0"},{stdlib,"1.0",load},{db,"2.1"},{fe,"3.1"}],
2523    do_create_script(latest_stdlib_start_type,Config,"4.4",Apps);
2524create_script(latest_no_stdlib,Config) ->
2525    Apps = [{kernel,"1.0"},{db,"2.1"},{fe,"3.1"}],
2526    do_create_script(latest_no_stdlib,Config,"4.4",Apps);
2527create_script(latest_app_start_type1,Config) ->
2528    Apps = core_apps(current),
2529    do_create_script(latest_app_start_type1,Config,current,Apps);
2530create_script(latest_app_start_type2,Config) ->
2531    OtherApps = [{mnesia,current,permanent},
2532		 {runtime_tools,current,transient},
2533		 {snmp,current,load},
2534		 {xmerl,current,none}],
2535    Apps = core_apps(current) ++ OtherApps,
2536    do_create_script(latest_app_start_type2,Config,current,Apps);
2537create_script(current_all_no_sasl,Config) ->
2538    Apps = [{kernel,current},{stdlib,current},{db,"2.1"},{fe,"3.1"}],
2539    do_create_script(current_all_no_sasl,Config,current,Apps);
2540create_script(current_all,Config) ->
2541    Apps = core_apps(current) ++ [{db,"2.1"}],
2542    do_create_script(current_all,Config,current,Apps);
2543create_script(current_all_future_erts,Config) ->
2544    Apps = core_apps(current) ++ [{db,"2.1"},{fe,"3.1"}],
2545    do_create_script(current_all_future_erts,Config,"99.99",Apps);
2546create_script(current_all_future_sasl,Config) ->
2547    Apps = [{kernel,current},{stdlib,current},{sasl,"9.9"},{db,"2.1"},{fe,"3.1"}],
2548    do_create_script(current_all_future_sasl,Config,current,Apps);
2549create_script({unicode,RelVsn},Config) ->
2550    Apps = core_apps(current) ++ [{ua,"1.0"}],
2551    do_create_script(unicode,RelVsn,Config,current,Apps);
2552create_script(duplicate_modules,Config) ->
2553    Apps = core_apps(current) ++ [{app1,"1.0"},{app2,"1.0"}],
2554    do_create_script(duplicate_modules,Config,current,Apps);
2555create_script(replace_app0,Config) ->
2556    Apps = core_apps(current) ++ [{db,"1.1"},{gh,"1.0"}],
2557    do_create_script(repace_app0,Config,current,Apps);
2558create_script(replace_app1,Config) ->
2559    Apps = core_apps(current) ++ [{db,"1.0"},{fe,"2.1"}],
2560    do_create_script(repace_app1,Config,current,Apps).
2561
2562
2563do_create_script(Id,Config,ErtsVsn,AppVsns) ->
2564    do_create_script(Id,string:to_upper(atom_to_list(Id)),Config,ErtsVsn,AppVsns).
2565do_create_script(Id,RelVsn,Config,ErtsVsn,AppVsns) ->
2566    PrivDir = ?privdir,
2567    Name = fname(PrivDir, Id),
2568    {ok,Fd} = file:open(Name++".rel",write),
2569    RelfileContent =
2570	{release,{"Test release", RelVsn},
2571	 {erts,erts_vsn(ErtsVsn)},
2572	 app_vsns(AppVsns)},
2573    io:format(Fd,"~p.~n",[RelfileContent]),
2574    ok = file:close(Fd),
2575    {filename:dirname(Name), filename:basename(Name)}.
2576
2577core_apps(Vsn) ->
2578    [{App,Vsn} || App <- [kernel,stdlib,sasl]].
2579
2580app_vsns(AppVsns) ->
2581    [{App,app_vsn(App,Vsn)} || {App,Vsn} <- AppVsns] ++
2582	[{App,app_vsn(App,Vsn),Type} || {App,Vsn,Type} <- AppVsns].
2583app_vsn(App,current) ->
2584    case application:load(App) of
2585	Ok when Ok==ok; Ok=={error,{already_loaded,App}} ->
2586	    {ok,Vsn} = application:get_key(App,vsn),
2587	    Vsn;
2588	Error ->
2589	    throw(Error)
2590    end;
2591app_vsn(_App,Vsn) ->
2592    Vsn.
2593
2594erts_vsn(current) -> erlang:system_info(version);
2595erts_vsn(Vsn) -> Vsn.
2596
2597
2598create_include_files(inc1, Config) ->
2599    PrivDir = ?privdir,
2600    Name = fname(PrivDir, inc1),
2601    create_apps(PrivDir),
2602
2603    Apps = application_controller:which_applications(),
2604    {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
2605    {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
2606
2607    Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
2608	" [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
2609	++ StdlibVer ++ "\"},\n"
2610	"  {t6, \"1.0\"}, {t5, \"1.0\"}, \n"
2611	"  {t4, \"1.0\"}, {t3, \"1.0\"}, {t2, \"1.0\"}, \n"
2612	"  {t1, \"1.0\"}]}.\n",
2613    file:write_file(Name ++ ".rel", list_to_binary(Rel)),
2614    {filename:dirname(Name), filename:basename(Name)};
2615
2616create_include_files(inc2, Config) ->
2617    PrivDir = ?privdir,
2618    Name = fname(PrivDir, inc2),
2619    create_apps(PrivDir),
2620
2621    Apps = application_controller:which_applications(),
2622    {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
2623    {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
2624
2625    %% t6 does not include t5 !
2626    Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
2627	" [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
2628	++ StdlibVer ++ "\"},\n"
2629	"  {t6, \"1.0\", [t4]}, {t5, \"1.0\"}, \n"
2630	"  {t4, \"1.0\"}, {t3, \"1.0\"}, {t2, \"1.0\"}, \n"
2631	"  {t1, \"1.0\"}]}.\n",
2632    file:write_file(Name ++ ".rel", list_to_binary(Rel)),
2633    {filename:dirname(Name), filename:basename(Name)};
2634
2635create_include_files(inc3, Config) ->
2636    PrivDir = ?privdir,
2637    Name = fname(PrivDir, inc3),
2638    create_apps(PrivDir),
2639
2640    Apps = application_controller:which_applications(),
2641    {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
2642    {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
2643
2644    %% t3 does not include t2 !
2645    Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
2646	" [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
2647	++ StdlibVer ++ "\"},\n"
2648	"  {t6, \"1.0\"}, {t5, \"1.0\"}, \n"
2649	"  {t4, \"1.0\"}, {t3, \"1.0\", []}, {t2, \"1.0\"}, \n"
2650	"  {t1, \"1.0\"}]}.\n",
2651    file:write_file(Name ++ ".rel", list_to_binary(Rel)),
2652    {filename:dirname(Name), filename:basename(Name)};
2653
2654create_include_files(inc4, Config) ->
2655    PrivDir = ?privdir,
2656    Name = fname(PrivDir, inc4),
2657    create_apps(PrivDir),
2658
2659    Apps = application_controller:which_applications(),
2660    {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
2661    {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
2662
2663    %% t3 does not include t2 !
2664    %% t6 does not include t5 !
2665    Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
2666	" [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
2667	++ StdlibVer ++ "\"},\n"
2668	"  {t6, \"1.0\", [t4]}, {t5, \"1.0\"}, \n"
2669	"  {t4, \"1.0\"}, {t3, \"1.0\", []}, {t2, \"1.0\"}, \n"
2670	"  {t1, \"1.0\"}]}.\n",
2671    file:write_file(Name ++ ".rel", list_to_binary(Rel)),
2672    {filename:dirname(Name), filename:basename(Name)};
2673
2674create_include_files(inc5, Config) ->
2675    PrivDir = ?privdir,
2676    Name = fname(PrivDir, inc5),
2677    create_apps(PrivDir),
2678
2679    Apps = application_controller:which_applications(),
2680    {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
2681    {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
2682
2683    %% t6 does not include t5 !
2684    %% exclude t5.
2685    Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
2686	" [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
2687	++ StdlibVer ++ "\"},\n"
2688	"  {t6, \"1.0\", [t4]}, \n"
2689	"  {t4, \"1.0\"}, {t3, \"1.0\", []}, {t2, \"1.0\"}, \n"
2690	"  {t1, \"1.0\"}]}.\n",
2691    file:write_file(Name ++ ".rel", list_to_binary(Rel)),
2692    {filename:dirname(Name), filename:basename(Name)};
2693
2694create_include_files(inc6, Config) ->
2695    PrivDir = ?privdir,
2696    Name = fname(PrivDir, inc6),
2697    create_apps(PrivDir),
2698
2699    Apps = application_controller:which_applications(),
2700    {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
2701    {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
2702
2703    %% t3 does include non existing t2 !
2704    Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
2705	" [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
2706	++ StdlibVer ++ "\"},\n"
2707	"  {t6, \"1.0\"}, {t5, \"1.0\"}, \n"
2708	"  {t4, \"1.0\"}, {t3, \"1.0\"}, \n"
2709	"  {t1, \"1.0\"}]}.\n",
2710    file:write_file(Name ++ ".rel", list_to_binary(Rel)),
2711    {filename:dirname(Name), filename:basename(Name)};
2712
2713create_include_files(inc7, Config) ->
2714    PrivDir = ?privdir,
2715    Name = fname(PrivDir, inc7),
2716    create_apps(PrivDir),
2717    create_app(t7, PrivDir),
2718
2719    Apps = application_controller:which_applications(),
2720    {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
2721    {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
2722
2723    %% t7 and t6 does include t5 !
2724    Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
2725	" [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
2726	++ StdlibVer ++ "\"},\n"
2727	"  {t7, \"1.0\"}, {t6, \"1.0\"}, {t5, \"1.0\"}, \n"
2728	"  {t4, \"1.0\"}, {t3, \"1.0\"}, {t2, \"1.0\"}, \n"
2729	"  {t1, \"1.0\"}]}.\n",
2730    file:write_file(Name ++ ".rel", list_to_binary(Rel)),
2731    {filename:dirname(Name), filename:basename(Name)};
2732
2733create_include_files(inc8, Config) ->
2734    PrivDir = ?privdir,
2735    Name = fname(PrivDir, inc8),
2736    create_circular_apps(PrivDir),
2737
2738    Apps = application_controller:which_applications(),
2739    {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
2740    {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
2741
2742    %% t8 uses t9 and t10 includes t9 !
2743    Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
2744	" [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
2745	++ StdlibVer ++ "\"},\n"
2746	"  {t8, \"1.0\"}, {t9, \"1.0\"}, {t10, \"1.0\"}]}.\n",
2747    file:write_file(Name ++ ".rel", list_to_binary(Rel)),
2748    {filename:dirname(Name), filename:basename(Name)};
2749
2750create_include_files(inc9, Config) ->
2751    PrivDir = ?privdir,
2752    Name = fname(PrivDir, inc9),
2753    create_circular_apps(PrivDir),
2754
2755    Apps = application_controller:which_applications(),
2756    {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
2757    {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
2758
2759    %% t8 uses t9, t9 uses t10 and t10 includes t8 ==> circular !!
2760    Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
2761	" [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
2762	++ StdlibVer ++ "\"},\n"
2763	"  {t8, \"1.0\"}, {t9, \"1.0\"}, {t10, \"1.0\", [t8]}]}.\n",
2764    file:write_file(Name ++ ".rel", list_to_binary(Rel)),
2765    {filename:dirname(Name), filename:basename(Name)};
2766
2767create_include_files(inc10, Config) ->
2768    PrivDir = ?privdir,
2769    Name = fname(PrivDir, inc10),
2770    create_circular_apps(PrivDir),
2771
2772    Apps = application_controller:which_applications(),
2773    {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
2774    {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
2775
2776    %% t9 tries to include not specified (in .app file) application !
2777    Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
2778	" [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
2779	++ StdlibVer ++ "\"},\n"
2780	"  {t8, \"1.0\"}, {t9, \"1.0\", [t7]}, {t10, \"1.0\"}]}.\n",
2781    file:write_file(Name ++ ".rel", list_to_binary(Rel)),
2782    {filename:dirname(Name), filename:basename(Name)};
2783
2784create_include_files(inc11, Config) ->
2785    PrivDir = ?privdir,
2786    Name = fname(PrivDir, inc11),
2787    create_apps2(PrivDir),
2788
2789    Apps = application_controller:which_applications(),
2790    {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
2791    {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
2792
2793    Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
2794	" [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
2795	++ StdlibVer ++ "\"},\n"
2796	"  {t11, \"1.0\"}, \n"
2797	"  {t12, \"1.0\"}, \n"
2798	"  {t13, \"1.0\"}]}.\n",
2799    file:write_file(Name ++ ".rel", list_to_binary(Rel)),
2800    {filename:dirname(Name), filename:basename(Name)};
2801
2802create_include_files(otp_3065_circular_dependenies, Config) ->
2803    PrivDir = ?privdir,
2804    Name = fname(PrivDir, otp_3065_circular_dependenies),
2805    create_apps_3065(PrivDir),
2806
2807    Apps = application_controller:which_applications(),
2808    {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
2809    {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
2810
2811    Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
2812	" [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
2813	++ StdlibVer ++ "\"},\n"
2814	"  {chAts, \"1.0\"}, {aa12, \"1.0\"}, \n"
2815	"  {chTraffic, \"1.0\"}]}.\n",
2816    file:write_file(Name ++ ".rel", list_to_binary(Rel)),
2817    {filename:dirname(Name), filename:basename(Name)};
2818
2819create_include_files(sort_apps, Config) ->
2820    PrivDir = ?privdir,
2821    Name = fname(PrivDir, sort_apps),
2822    create_sort_apps(PrivDir),
2823
2824    Apps = application_controller:which_applications(),
2825    {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
2826    {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
2827
2828    Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
2829	" [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
2830	++ StdlibVer ++ "\"},\n"
2831	"  {t14, \"1.0\"}, \n"
2832	"  {t20, \"1.0\"}, \n"
2833	"  {t19, \"1.0\"}, \n"
2834	"  {t18, \"1.0\"}, \n"
2835	"  {t17, \"1.0\"}, \n"
2836	"  {t16, \"1.0\"}, \n"
2837	"  {t15, \"1.0\"}]}.\n",
2838    file:write_file(Name ++ ".rel", list_to_binary(Rel)),
2839    {filename:dirname(Name), filename:basename(Name)};
2840
2841create_include_files(sort_apps_rev, Config) ->
2842    PrivDir = ?privdir,
2843    Name = fname(PrivDir, sort_apps_rev),
2844    create_sort_apps(PrivDir),
2845
2846    Apps = application_controller:which_applications(),
2847    {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
2848    {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
2849
2850    Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
2851	" [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
2852	++ StdlibVer ++ "\"},\n"
2853	"  {t14, \"1.0\"}, \n"
2854	"  {t18, \"1.0\"}, \n"
2855	"  {t19, \"1.0\"}, \n"
2856	"  {t20, \"1.0\"}, \n"
2857	"  {t15, \"1.0\"}, \n"
2858	"  {t16, \"1.0\"}, \n"
2859	"  {t17, \"1.0\"}]}.\n",
2860    file:write_file(Name ++ ".rel", list_to_binary(Rel)),
2861    {filename:dirname(Name), filename:basename(Name)}.
2862
2863
2864create_apps(Dir) ->
2865    T1 = "{application, t1,\n"
2866	" [{vsn, \"1.0\"},\n"
2867	"  {description, \"test\"},\n"
2868	"  {modules, []},\n"
2869	"  {applications, [kernel, stdlib]},\n"
2870	"  {registered, []}]}.\n",
2871    file:write_file(fname(Dir, 't1.app'), list_to_binary(T1)),
2872
2873    T2 = "{application, t2,\n"
2874	" [{vsn, \"1.0\"},\n"
2875	"  {description, \"test\"},\n"
2876	"  {modules, []},\n"
2877	"  {applications, [t1]},\n"
2878	"  {registered, []}]}.\n",
2879    file:write_file(fname(Dir, 't2.app'), list_to_binary(T2)),
2880
2881    T3 = "{application, t3,\n"
2882	" [{vsn, \"1.0\"},\n"
2883	"  {description, \"test\"},\n"
2884	"  {modules, []},\n"
2885	"  {applications, []},\n"
2886	"  {included_applications, [t2]},\n"
2887	"  {registered, []}]}.\n",
2888    file:write_file(fname(Dir, 't3.app'), list_to_binary(T3)),
2889
2890    T4 = "{application, t4,\n"
2891	" [{vsn, \"1.0\"},\n"
2892	"  {description, \"test\"},\n"
2893	"  {modules, []},\n"
2894	"  {applications, [t3]},\n"
2895	"  {included_applications, []},\n"
2896	"  {registered, []}]}.\n",
2897    file:write_file(fname(Dir, 't4.app'), list_to_binary(T4)),
2898
2899    T5 = "{application, t5,\n"
2900	" [{vsn, \"1.0\"},\n"
2901	"  {description, \"test\"},\n"
2902	"  {modules, []},\n"
2903	"  {applications, [t3]},\n"
2904	"  {included_applications, []},\n"
2905	"  {registered, []}]}.\n",
2906    file:write_file(fname(Dir, 't5.app'), list_to_binary(T5)),
2907
2908    T6 = "{application, t6,\n"
2909	" [{vsn, \"1.0\"},\n"
2910	"  {description, \"test\"},\n"
2911	"  {modules, []},\n"
2912	"  {applications, []},\n"
2913	"  {included_applications, [t4, t5]},\n"
2914	"  {registered, []}]}.\n",
2915    file:write_file(fname(Dir, 't6.app'), list_to_binary(T6)).
2916
2917create_app(t7, Dir) ->
2918    T7 = "{application, t7,\n"
2919	" [{vsn, \"1.0\"},\n"
2920	"  {description, \"test\"},\n"
2921	"  {modules, []},\n"
2922	"  {applications, []},\n"
2923	"  {included_applications, [t5]},\n"
2924	"  {registered, []}]}.\n",
2925    file:write_file(fname(Dir, 't7.app'), list_to_binary(T7)).
2926
2927create_circular_apps(Dir) ->
2928    T8 = "{application, t8,\n"
2929	" [{vsn, \"1.0\"},\n"
2930	"  {description, \"test\"},\n"
2931	"  {modules, []},\n"
2932	"  {applications, [t9]},\n"
2933	"  {included_applications, []},\n"
2934	"  {registered, []}]}.\n",
2935    file:write_file(fname(Dir, 't8.app'), list_to_binary(T8)),
2936
2937    T9 = "{application, t9,\n"
2938	" [{vsn, \"1.0\"},\n"
2939	"  {description, \"test\"},\n"
2940	"  {modules, []},\n"
2941	"  {applications, [t10]},\n"
2942	"  {included_applications, []},\n"
2943	"  {registered, []}]}.\n",
2944    file:write_file(fname(Dir, 't9.app'), list_to_binary(T9)),
2945
2946    T10 = "{application, t10,\n"
2947	" [{vsn, \"1.0\"},\n"
2948	"  {description, \"test\"},\n"
2949	"  {modules, []},\n"
2950	"  {applications, []},\n"
2951	"  {included_applications, [t8, t9]},\n"
2952	"  {registered, []}]}.\n",
2953    file:write_file(fname(Dir, 't10.app'), list_to_binary(T10)).
2954
2955create_apps2(Dir) ->
2956    T11 = "{application, t11,\n"
2957	" [{vsn, \"1.0\"},\n"
2958	"  {description, \"test\"},\n"
2959	"  {modules, []},\n"
2960	"  {applications, []},\n"
2961	"  {included_applications, [t13]},\n"
2962	"  {registered, []}]}.\n",
2963    file:write_file(fname(Dir, 't11.app'), list_to_binary(T11)),
2964
2965    T12 = "{application, t12,\n"
2966	" [{vsn, \"1.0\"},\n"
2967	"  {description, \"test\"},\n"
2968	"  {modules, []},\n"
2969	"  {applications, [t11]},\n"
2970	"  {registered, []}]}.\n",
2971    file:write_file(fname(Dir, 't12.app'), list_to_binary(T12)),
2972
2973    T13 = "{application, t13,\n"
2974	" [{vsn, \"1.0\"},\n"
2975	"  {description, \"test\"},\n"
2976	"  {modules, []},\n"
2977	"  {applications, []},\n"
2978	"  {included_applications, []},\n"
2979	"  {registered, []}]}.\n",
2980    file:write_file(fname(Dir, 't13.app'), list_to_binary(T13)).
2981
2982
2983
2984create_apps_3065(Dir) ->
2985    T11 = "{application, chTraffic,\n"
2986	" [{vsn, \"1.0\"},\n"
2987	"  {description, \"test\"},\n"
2988	"  {modules, []},\n"
2989	"  {applications, []},\n"
2990	"  {included_applications, [chAts]},\n"
2991	"  {registered, []}]}.\n",
2992    file:write_file(fname(Dir, 'chTraffic.app'), list_to_binary(T11)),
2993
2994    T12 = "{application, chAts,\n"
2995	" [{vsn, \"1.0\"},\n"
2996	"  {description, \"test\"},\n"
2997	"  {modules, []},\n"
2998	"  {applications, []},\n"
2999	"  {included_applications, [aa12]},\n"
3000	"  {registered, []}]}.\n",
3001    file:write_file(fname(Dir, 'chAts.app'), list_to_binary(T12)),
3002
3003    T13 = "{application, aa12,\n"
3004	" [{vsn, \"1.0\"},\n"
3005	"  {description, \"test\"},\n"
3006	"  {modules, []},\n"
3007	"  {applications, [chAts]},\n"
3008	"  {included_applications, []},\n"
3009	"  {registered, []}]}.\n",
3010    file:write_file(fname(Dir, 'aa12.app'), list_to_binary(T13)).
3011
3012create_sort_apps(Dir) ->
3013    T14 = "{application, t14,\n"
3014	" [{vsn, \"1.0\"},\n"
3015	"  {description, \"test\"},\n"
3016	"  {modules, []},\n"
3017	"  {applications, [t18,t20,t19]},\n"
3018	"  {included_applications, [t15,t17,t16]},\n"
3019	"  {registered, []}]}.\n",
3020    file:write_file(fname(Dir, 't14.app'), list_to_binary(T14)),
3021
3022    T15 = "{application, t15,\n"
3023	" [{vsn, \"1.0\"},\n"
3024	"  {description, \"test\"},\n"
3025	"  {modules, []},\n"
3026	"  {applications, []},\n"
3027	"  {included_applications, []},\n"
3028	"  {registered, []}]}.\n",
3029    file:write_file(fname(Dir, 't15.app'), list_to_binary(T15)),
3030
3031    T16 = "{application, t16,\n"
3032	" [{vsn, \"1.0\"},\n"
3033	"  {description, \"test\"},\n"
3034	"  {modules, []},\n"
3035	"  {applications, []},\n"
3036	"  {included_applications, []},\n"
3037	"  {registered, []}]}.\n",
3038    file:write_file(fname(Dir, 't16.app'), list_to_binary(T16)),
3039
3040    T17 = "{application, t17,\n"
3041	" [{vsn, \"1.0\"},\n"
3042	"  {description, \"test\"},\n"
3043	"  {modules, []},\n"
3044	"  {applications, []},\n"
3045	"  {included_applications, []},\n"
3046	"  {registered, []}]}.\n",
3047    file:write_file(fname(Dir, 't17.app'), list_to_binary(T17)),
3048
3049    T18 = "{application, t18,\n"
3050	" [{vsn, \"1.0\"},\n"
3051	"  {description, \"test\"},\n"
3052	"  {modules, []},\n"
3053	"  {applications, []},\n"
3054	"  {included_applications, []},\n"
3055	"  {registered, []}]}.\n",
3056    file:write_file(fname(Dir, 't18.app'), list_to_binary(T18)),
3057
3058    T19 = "{application, t19,\n"
3059	" [{vsn, \"1.0\"},\n"
3060	"  {description, \"test\"},\n"
3061	"  {modules, []},\n"
3062	"  {applications, []},\n"
3063	"  {included_applications, []},\n"
3064	"  {registered, []}]}.\n",
3065    file:write_file(fname(Dir, 't19.app'), list_to_binary(T19)),
3066
3067    T20 = "{application, t20,\n"
3068	" [{vsn, \"1.0\"},\n"
3069	"  {description, \"test\"},\n"
3070	"  {modules, []},\n"
3071	"  {applications, []},\n"
3072	"  {included_applications, []},\n"
3073	"  {registered, []}]}.\n",
3074    file:write_file(fname(Dir, 't20.app'), list_to_binary(T20)).
3075
3076fname(N) ->
3077    filename:join(N).
3078
3079fname(Dir, Basename) ->
3080    filename:join(Dir, Basename).
3081