%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
%%
%% %CopyrightEnd%
%%
%%
%% Test suite for the systools module.
%%
%% The systools module is a wrapper for a number of modules that
%% handle large parts of the release building functionality
%% (e.g. checking app files, building a tar file, building
%% release upgrad scripts.
%%
-module(systools_SUITE).
%%-define(debug, true).
-include_lib("common_test/include/ct.hrl").
-define(format(S, A), ok).
-define(datadir, ?config(data_dir, Config)).
-define(privdir, ?config(priv_dir, Config)).
-define(copydir, ?config(copy_dir, Config)).
-include_lib("kernel/include/file.hrl").
-export([all/0,suite/0,groups/0,init_per_group/2,end_per_group/2]).
-export([script_options/1, normal_script/1, no_mod_vsn_script/1,
wildcard_script/1, variable_script/1, no_sasl_script/1,
abnormal_script/1, src_tests_script/1, crazy_script/1,
included_script/1, included_override_script/1,
included_fail_script/1, included_bug_script/1, exref_script/1,
otp_3065_circular_dependenies/1, included_and_used_sort_script/1]).
-export([tar_options/1, normal_tar/1, no_mod_vsn_tar/1, system_files_tar/1,
system_files_tar/2, invalid_system_files_tar/1,
invalid_system_files_tar/2, variable_tar/1,
src_tests_tar/1, var_tar/1, exref_tar/1, link_tar/1,
otp_9507_path_ebin/1]).
-export([normal_relup/1, restart_relup/1, abnormal_relup/1, no_sasl_relup/1,
no_appup_relup/1, bad_appup_relup/1, app_start_type_relup/1,
regexp_relup/1]).
-export([normal_hybrid/1,hybrid_no_old_sasl/1,hybrid_no_new_sasl/1]).
-export([otp_6226_outdir/1]).
-export([init_per_suite/1, end_per_suite/1,
init_per_testcase/2, end_per_testcase/2]).
-import(lists, [foldl/3]).
-define(default_timeout, ?t:minutes(20)).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
suite() ->
[{ct_hooks, [ts_install_cth]}].
all() ->
[{group, script}, {group, tar}, {group, relup}, {group, hybrid},
{group, options}].
groups() ->
[{script, [],
[script_options, normal_script, no_mod_vsn_script,
wildcard_script, variable_script, abnormal_script,
no_sasl_script, src_tests_script, crazy_script,
included_script, included_override_script,
included_fail_script, included_bug_script, exref_script,
otp_3065_circular_dependenies, included_and_used_sort_script]},
{tar, [],
[tar_options, normal_tar, no_mod_vsn_tar, system_files_tar,
invalid_system_files_tar, variable_tar,
src_tests_tar, var_tar, exref_tar, link_tar, otp_9507_path_ebin]},
{relup, [],
[normal_relup, restart_relup, abnormal_relup, no_sasl_relup,
no_appup_relup, bad_appup_relup, app_start_type_relup, regexp_relup
]},
{hybrid, [], [normal_hybrid,hybrid_no_old_sasl,hybrid_no_new_sasl]},
{options, [], [otp_6226_outdir]}].
init_per_group(_GroupName, Config) ->
Config.
end_per_group(_GroupName, Config) ->
Config.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
init_per_suite(Config) when is_list(Config) ->
%% Make of copy of the data directory.
DataDir = ?datadir,
PrivDir = ?privdir,
CopyDir = fname(PrivDir, "datacopy"),
TarFile = fname(PrivDir, "datacopy.tgz"),
{ok, Tar} = erl_tar:open(TarFile, [write, compressed]),
ok = erl_tar:add(Tar, DataDir, CopyDir, [compressed]),
ok = erl_tar:close(Tar),
ok = erl_tar:extract(TarFile, [compressed]),
ok = file:delete(TarFile),
%% Compile source files in the copy directory.
Sources = filelib:wildcard(fname([CopyDir,'*','*','*','*','*.erl'])),
lists:foreach(fun compile_source/1, Sources),
%% To use in end_per_testcase
Path = code:get_path(),
{ok,Cwd} = file:get_cwd(),
[{copy_dir, CopyDir}, {cwd,Cwd}, {path,Path} | Config].
compile_source(File) ->
%% The compiler will no longer create a Beam file
%% with a module name that does not match the output
%% file, so we must compile to a binary and write
%% the output file ourselves.
U = filename:dirname(filename:dirname(File)),
Base = filename:rootname(filename:basename(File)),
OutFile = filename:join([U,"ebin",Base++".beam"]),
OutFileTemp = OutFile ++ "#",
{ok,_,Code} = compile:file(File, [binary]),
ok = file:write_file(OutFileTemp, Code),
file:rename(OutFileTemp, OutFile).
end_per_suite(Conf) when is_list(Conf) ->
%% Nothing.
Conf.
init_per_testcase(link_tar, Config) ->
case os:type() of
{unix, _} -> init_per_testcase(dummy, Config);
{win32, _} -> {skip, "Skip on windows"}
end;
init_per_testcase(_Case, Config) ->
Dog = test_server:timetrap(?default_timeout),
[{watchdog, Dog}|Config].
end_per_testcase(Case, Config) ->
try apply(?MODULE,Case,[cleanup,Config])
catch error:undef -> ok
end,
Dog=?config(watchdog, Config),
test_server:timetrap_cancel(Dog),
case {?config(path,Config),?config(cwd,Config)} of
{undefined,undefined} ->
ok;
{Path,Cwd} ->
true = code:set_path(Path),
ok = file:set_cwd(Cwd)
end,
ok.
%% Usage:
%% systools:make_script("RelName")
%% Make a boot file from RelName.rel.
%% Generates RelName.{script,boot}
%% systools:make_tar("RelName")
%% Make a release package from RelName.rel.
%% Generates RelName.tar,Z
%% systools:script2boot(File)
%% File.script -> File.boot
%% systools:make_relup("Target", ["UpFromRel"...], ["DownToRel"...], Opts)
%% Gather all appup scripts to the relup file
%%
%% make_script: Check illegal script options
script_options(Config) when is_list(Config) ->
{'EXIT',{{badarg,[{path,["Path",12,"Another"]}]}, _}} =
(catch systools:make_script("release", [{path,["Path",12,"Another"]}])),
{'EXIT',{{badarg,[sillent]}, _}} =
(catch systools:make_script("release",
[{path,["Path","Another"]},sillent])),
{'EXIT',{{badarg,[locall]}, _}} =
(catch systools:make_script("release",
[{path,["Path","Another"]},locall])),
{'EXIT',{{badarg,[src_testsxx]}, _}} =
(catch systools:make_script("release",
[{path,["Path"]},src_testsxx])),
{'EXIT',{{badarg,[{variables, {"TEST", "/home/lib"}}]}, _}} =
(catch systools:make_script("release",
[{variables, {"TEST", "/home/lib"}}])),
{'EXIT',{{badarg,[{variables, [{a, b}, {"a", "b"}]}]}, _}} =
(catch systools:make_script("release",
[{variables, [{a, b}, {"a", "b"}]}])),
{'EXIT',{{badarg,[exreff]}, _}} =
(catch systools:make_script("release",
[{path,["Path","Another"]},exreff])),
{'EXIT',{{badarg,[{exref,["appl"]}]}, _}} =
(catch systools:make_script("release", [{exref,["appl"]}])),
{'EXIT',{{badarg,[{machine, "appl"}]}, _}} =
(catch systools:make_script("release", [{machine,"appl"}])),
ok.
%% make_script: Check that normal case
normal_script(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
PSAVE = code:get_path(), % Save path
{LatestDir, LatestName} = create_script(latest,Config),
DataDir = filename:absname(?copydir),
LibDir = fname([DataDir, d_normal, lib]),
P1 = fname([LibDir, 'db-2.1', ebin]),
P2 = fname([LibDir, 'fe-3.1', ebin]),
true = code:add_patha(P1),
true = code:add_patha(P2),
ok = file:set_cwd(LatestDir),
ok = systools:make_script(filename:basename(LatestName)),
{ok, _} = read_script_file(LatestName), % Check readabillity
%% Check the same but w. silent flag
{ok, _, []} = systools:make_script(LatestName, [silent]),
%% Use the local option
ok = systools:make_script(LatestName, [local]),
ok = check_script_path(LatestName),
%% use the path option
code:set_path(PSAVE), % Restore path
%% Mess up std path:
true = code:add_patha(fname([LibDir, 'db-1.0', ebin])),
true = code:add_patha(fname([LibDir, 'fe-2.1', ebin])),
error = systools:make_script(LatestName), %should fail
ok = systools:make_script(LatestName,[{path, [P1, P2]}]),
ok = file:set_cwd(OldDir),
code:set_path(PSAVE), % Restore path
ok.
%% make_script:
%% Modules specified without version in .app file (db-3.1).
%% Note that this is now the normal way - i.e. systools now ignores
%% the module versions in the .app file.
no_mod_vsn_script(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
PSAVE = code:get_path(), % Save path
{LatestDir, LatestName} = create_script(latest_no_mod_vsn,Config),
DataDir = filename:absname(?copydir),
LibDir = fname([DataDir, d_normal, lib]),
P1 = fname([LibDir, 'db-3.1', ebin]),
P2 = fname([LibDir, 'fe-3.1', ebin]),
true = code:add_patha(P1),
true = code:add_patha(P2),
ok = file:set_cwd(LatestDir),
ok = systools:make_script(filename:basename(LatestName)),
{ok, _} = read_script_file(LatestName), % Check readabillity
%% Check the same but w. silent flag
{ok, _, []} = systools:make_script(LatestName, [silent]),
%% Use the local option
ok = systools:make_script(LatestName, [local]),
ok = check_script_path(LatestName),
%% use the path option
code:set_path(PSAVE), % Restore path
%% Mess up std path:
true = code:add_patha(fname([LibDir, 'db-1.0', ebin])),
true = code:add_patha(fname([LibDir, 'fe-2.1', ebin])),
error = systools:make_script(LatestName), %should fail
ok = systools:make_script(LatestName,
[{path, [P1, P2]}]),
ok = file:set_cwd(OldDir),
code:set_path(PSAVE), % Restore path
ok.
%% make_script: Check that make_script handles wildcards in path.
wildcard_script(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
{LatestDir, LatestName} = create_script(latest,Config),
DataDir = filename:absname(?copydir),
LibDir = fname([DataDir, d_normal, lib]),
WildDir = fname([LibDir, '*', ebin]),
ok = file:set_cwd(LatestDir),
error = systools:make_script(filename:basename(LatestName)),
ok = systools:make_script(LatestName,
[{path, [WildDir]}]),
{ok, _} = read_script_file(LatestName), % Check readabillity
ok = file:set_cwd(OldDir),
ok.
%% make_script: Add own installation dependent variable in script.
variable_script(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
{LatestDir, LatestName} = create_script(latest,Config),
DataDir = filename:absname(?copydir),
LibDir = fname([DataDir, d_normal, lib]),
P = [fname([LibDir, 'db-2.1', ebin]),
fname([LibDir, 'fe-3.1', ebin])],
ok = file:set_cwd(LatestDir),
ok = systools:make_script(LatestName,
[{path, P},
{variables, [{"TEST", LibDir}]}]),
%% Check variables
ok = check_var_script_file([fname(['$TEST', 'db-2.1', ebin]),
fname(['$TEST', 'fe-3.1', ebin])],
P,
LatestName),
ok = file:set_cwd(OldDir),
ok.
%% make_script: Abnormal cases.
abnormal_script(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
{LatestDir, LatestName} = create_script(latest,Config),
DataDir = filename:absname(?copydir),
ok = file:set_cwd(LatestDir),
LibDir = fname([DataDir, d_bad_app_vsn, lib]),
P = [fname([LibDir, 'db-2.1', ebin]),
fname([LibDir, 'fe-3.1', ebin])],
%% Check wrong app vsn
error = systools:make_script(LatestName, [{path, P}]),
{error,
systools_make,
[{error_reading, {db, {no_valid_version,
{{"should be","2.1"},
{"found file", _, "2.0"}}}}}]} =
systools:make_script(LatestName, [silent, {path, P}]),
ok = file:set_cwd(OldDir),
ok.
%% make_script: Create script without sasl appl. Check warning.
no_sasl_script(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
{LatestDir, LatestName} = create_script(latest1_no_sasl,Config),
DataDir = filename:absname(?copydir),
LibDir = [fname([DataDir, d_normal, lib])],
P = [fname([LibDir, '*', ebin]),
fname([DataDir, lib, kernel, ebin]),
fname([DataDir, lib, stdlib, ebin]),
fname([DataDir, lib, sasl, ebin])],
ok = file:set_cwd(LatestDir),
{ok, _ , [{warning,missing_sasl}]} =
systools:make_script(LatestName,[{path, P},silent]),
{ok, _ , []} =
systools:make_script(LatestName,[{path, P},silent, no_warn_sasl]),
ok = file:set_cwd(OldDir),
ok.
%% make_script: Do not check date of object file or that source code
%% can be found.
src_tests_script(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
PSAVE = code:get_path(), % Save path
{LatestDir, LatestName} = create_script(latest,Config),
BootFile = LatestName ++ ".boot",
DataDir = filename:absname(?copydir),
LibDir = fname([DataDir, d_missing_src, lib]),
P1 = fname([LibDir, 'db-2.1', ebin]),
P2 = fname([LibDir, 'fe-3.1', ebin]),
N = [P1, P2],
ok = file:set_cwd(LatestDir),
%% Manipulate the modification date of a beam file so it seems
%% older than its .erl file
Erl = filename:join([P1,"..","src","db1.erl"]),
{ok, FileInfo=#file_info{mtime={{Y,M,D},T}}} = file:read_file_info(Erl),
Beam = filename:join(P1,"db1.beam"),
ok=file:write_file_info(Beam, FileInfo#file_info{mtime={{Y-1,M,D},T}}),
%% Remove a .erl file
Erl2 = filename:join([P1,"..","src","db2.erl"]),
file:delete(Erl2),
%% Then make script
%% .boot file should not exist
ok = file:delete(BootFile),
false = filelib:is_regular(BootFile),
%% With warnings_as_errors and src_tests option, an error should be issued
error =
systools:make_script(LatestName, [silent, {path, N}, src_tests,
warnings_as_errors]),
error =
systools:make_script(LatestName, [{path, N}, src_tests,
warnings_as_errors]),
%% due to warnings_as_errors .boot file should still not exist
false = filelib:is_regular(BootFile),
%% Two warnings should be issued when src_tests is given
%% 1. old object code for db1.beam
%% 2. missing source code for db2.beam
{ok, _, [{warning,{obj_out_of_date,_}},
{warning,{source_not_found,_}}]} =
systools:make_script(LatestName, [silent, {path, N}, src_tests]),
%% .boot file should exist now
true = filelib:is_regular(BootFile),
%% Without the src_tests option, no warning should be issued
{ok, _, []} =
systools:make_script(LatestName, [silent, {path, N}]),
%% Check that the old no_module_tests option (from the time when
%% it was default to do the src_test) is ignored
{ok, _, [{warning,{obj_out_of_date,_}},
{warning,{source_not_found,_}}]} =
systools:make_script(LatestName, [silent,
{path, N},
no_module_tests,
src_tests]),
ok = file:set_cwd(OldDir),
code:set_path(PSAVE),
ok.
%% make_script: Do the crazy cases.
crazy_script(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
{LatestDir, LatestName} = create_script(latest, Config),
DataDir = filename:absname(?copydir),
LibDir = fname([DataDir, d_normal, lib]),
P = [fname([LibDir, 'db-2.1', ebin]),
fname([LibDir, 'fe-3.1', ebin])],
ok = file:set_cwd(LatestDir),
%% Run with bad path
error = systools:make_script(LatestName),
{error, _, [{error_reading, _}, {error_reading, _}]} =
systools:make_script(LatestName, [silent]),
%% Run with .rel file lacking kernel
{LatestDir2, LatestName2} = create_script(latest_nokernel, Config),
ok = file:set_cwd(LatestDir2),
error = systools:make_script(LatestName2),
{error, _, {missing_mandatory_app,kernel}} =
systools:make_script(LatestName2, [silent,{path,P}]),
%% Run with .rel file with non-permanent kernel
{LatestDir3, LatestName3} = create_script(latest_kernel_start_type, Config),
ok = file:set_cwd(LatestDir3),
error = systools:make_script(LatestName3),
{error, _, {mandatory_app,kernel,load}} =
systools:make_script(LatestName3, [silent,{path,P}]),
ok = file:set_cwd(OldDir),
ok.
%% make_script: Check that make_script handles generation of script
%% for applications with included applications.
included_script(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
{LatestDir, LatestName} = create_include_files(inc1, Config),
ok = file:set_cwd(LatestDir),
ok = systools:make_script(LatestName),
ok = check_include_script(LatestName,
[t1, t2, t3, t5, t4, t6],
[t1, t3, t6]),
ok = file:set_cwd(OldDir),
ok.
%% make_script: Check that make_script handles generation of script
%% for applications with included applications which are override by
%% the .rel file.
included_override_script(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
{LatestDir, LatestName} = create_include_files(inc2, Config),
ok = file:set_cwd(LatestDir),
ok = systools:make_script(LatestName),
ok = check_include_script(LatestName,
[t1, t2, t3, t4, t6, t5],
[t1, t3, t6, t5]),
{_, LatestName1} = create_include_files(inc3, Config),
ok = systools:make_script(LatestName1),
ok = check_include_script(LatestName1,
[t3, t5, t4, t6, t1, t2],
[t3, t6, t1, t2]),
{_, LatestName2} = create_include_files(inc4, Config),
ok = systools:make_script(LatestName2),
ok = check_include_script(LatestName2,
[t3, t4, t6, t5, t1, t2],
[t3, t6, t5, t1, t2]),
{_, LatestName3} = create_include_files(inc5, Config),
ok = systools:make_script(LatestName3),
ok = check_include_script(LatestName3,
[t3, t4, t6, t1, t2],
[t3, t6, t1, t2]),
ok = file:set_cwd(OldDir),
ok.
%% make_script: Check that make_script handles errors then generating
%% script with included applications.
included_fail_script(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
{LatestDir, LatestName} = create_include_files(inc6, Config),
ok = file:set_cwd(LatestDir),
{error, _, {undefined_applications,[t2]}} =
systools:make_script(LatestName, [silent]),
{_, LatestName1} = create_include_files(inc7, Config),
{error, _, {duplicate_include,[{{t5,t7,_,_},{t5,t6,_,_}}]}} =
systools:make_script(LatestName1, [silent]),
{_, LatestName3} = create_include_files(inc9, Config),
{error, _, {circular_dependencies,[{t10,_},{t8,_}]}} =
systools:make_script(LatestName3, [silent]),
{_, LatestName4} = create_include_files(inc10, Config),
{error, _, [{error_reading,{t9,{override_include,[t7]}}}]} =
systools:make_script(LatestName4, [silent]),
ok = file:set_cwd(OldDir),
ok.
%% make_script: Check that make_script handles generation of script
%% with difficult dependency for included applications.
included_bug_script(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
{LatestDir, LatestName} = create_include_files(inc11, Config),
ok = file:set_cwd(LatestDir),
ok = systools:make_script(LatestName),
ok = check_include_script(LatestName,
[t13, t11, t12],
[t11, t12]),
ok = file:set_cwd(OldDir),
ok.
%% make_script: Circular dependencies in systools:make_script().
otp_3065_circular_dependenies(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
{LatestDir, LatestName} =
create_include_files(otp_3065_circular_dependenies, Config),
ok = file:set_cwd(LatestDir),
ok = systools:make_script(LatestName),
ok = check_include_script(LatestName,
[aa12, chAts, chTraffic],
[chTraffic]),
ok = file:set_cwd(OldDir),
ok.
%% Test sorting of included applications and used applications
included_and_used_sort_script(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
{LatestDir1, LatestName1} = create_include_files(sort_apps, Config),
ok = file:set_cwd(LatestDir1),
ok = systools:make_script(LatestName1),
ok = check_include_script(LatestName1,
[t20,t19,t18,t17,t16,t15,t14],[t20,t19,t18,t14]),
{LatestDir2, LatestName2} = create_include_files(sort_apps_rev, Config),
ok = file:set_cwd(LatestDir2),
ok = systools:make_script(LatestName2),
ok = check_include_script(LatestName2,
[t18,t19,t20,t15,t16,t17,t14],[t18,t19,t20,t14]),
ok = file:set_cwd(OldDir),
ok.
%% make_script: Check that make_script exref option works.
exref_script(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
PSAVE = code:get_path(), % Save path
{LatestDir, LatestName} = create_script(latest,Config),
DataDir = filename:absname(?copydir),
LibDir = fname([DataDir, d_normal, lib]),
P = [fname([LibDir, 'db-2.1', ebin]),
fname([LibDir, 'fe-3.1', ebin])],
ok = file:set_cwd(LatestDir),
{ok, _, _} = systools:make_script(LatestName, [{path,P}, silent]),
%% Complete exref
{ok, _, W1} =
systools:make_script(LatestName, [exref, {path,P}, silent]),
check_exref_warnings(with_db1, W1),
{ok, _} = read_script_file(LatestName), % Check readabillity
%% Only exref the db application.
{ok, _, W2} =
systools:make_script(LatestName, [{exref,[db]}, {path,P}, silent]),
check_exref_warnings(with_db1, W2),
{ok, _} = read_script_file(LatestName), % Check readabillity
%% Only exref the fe application.
{ok, _, W3} =
systools:make_script(LatestName, [{exref,[fe]}, {path,P}, silent]),
check_exref_warnings(without_db1, W3),
{ok, _} = read_script_file(LatestName), % Check readabillity
%% exref the db and stdlib applications.
{ok, _, W4} =
systools:make_script(LatestName, [{exref,[db,stdlib]}, {path,P}, silent]),
check_exref_warnings(with_db1, W4),
{ok, _} = read_script_file(LatestName), % Check readabillity
ok = file:set_cwd(OldDir),
code:set_path(PSAVE), % Restore path
ok.
check_exref_warnings(with_db1, W) ->
case get_exref(undef, W) of
{ok, [{db2,non_existing_func,0},
{fe2,non_existing_func,0},
{lists,non_existing_func,1}]} ->
ok;
{ok, L} ->
test_server:fail({exref_warning_undef, L});
_E ->
test_server:fail({bad_undef,_E})
end;
check_exref_warnings(without_db1, W) ->
case get_exref(undef, W) of
false ->
ok;
{ok, L} ->
test_server:fail({exref_warning_undef, L})
end.
get_exref(undef, W) -> filter(no_hipe(get_exref1(exref_undef, W))).
filter(false) ->
false;
filter({ok, W}) ->
{ok, filter(W)};
filter(L) ->
lists:filter(fun%({hipe_consttab,_,_}) -> false;
({int,_,_}) -> false;
({i,_,_}) -> false;
({crypto,_,_}) -> false;
(_) -> true
end,
L).
get_exref1(T, [{warning, {T, Value}}|_]) -> {ok, Value};
get_exref1(T, [_|W]) -> get_exref1(T, W);
get_exref1(_, []) -> false.
no_hipe(false) ->
false;
no_hipe({ok, Value}) ->
case erlang:system_info(hipe_architecture) of
undefined ->
Hipe = "hipe",
Fun = fun({M,_,_}) -> not lists:prefix(Hipe, atom_to_list(M)) end,
NewValue = lists:filter(Fun, Value),
{ok, NewValue};
_Arch ->
{ok, Value}
end.
%% tar_options: Check illegal tar options.
tar_options(Config) when is_list(Config) ->
{'EXIT',{{badarg,[{path,["Path",12,"Another"]}]}, _}} =
(catch systools:make_tar("release", [{path,["Path",12,"Another"]}])),
{'EXIT',{{badarg,[sillent]}, _}} =
(catch systools:make_tar("release",
[{path,["Path","Another"]},sillent])),
{'EXIT',{{badarg,[{dirs,["dirs"]}]}, _}} =
(catch systools:make_tar("release", [{dirs, ["dirs"]}])),
{'EXIT',{{badarg,[{erts, illegal}]}, _}} =
(catch systools:make_tar("release", [{erts, illegal}])),
{'EXIT',{{badarg,[src_testsxx]}, _}} =
(catch systools:make_tar("release",
[{path,["Path"]},src_testsxx])),
{'EXIT',{{badarg,[{variables, [{a, b}, {"a", "b"}]}]}, _}} =
(catch systools:make_tar("release",
[{variables, [{a, b}, {"a", "b"}]}])),
{'EXIT',{{badarg,[{var_tar, illegal}]}, _}} =
(catch systools:make_tar("release", [{var_tar, illegal}])),
{'EXIT',{{badarg,[exreff]}, _}} =
(catch systools:make_tar("release",
[{path,["Path","Another"]},exreff])),
{'EXIT',{{badarg,[{exref,["appl"]}]}, _}} =
(catch systools:make_tar("release", [{exref,["appl"]}])),
{'EXIT',{{badarg,[{machine, "appl"}]}, _}} =
(catch systools:make_tar("release", [{machine,"appl"}])),
ok.
%% make_tar: Check normal case
normal_tar(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
{LatestDir, LatestName} = create_script(latest,Config),
DataDir = filename:absname(?copydir),
LibDir = fname([DataDir, d_normal, lib]),
P = [fname([LibDir, 'db-2.1', ebin]),
fname([LibDir, 'fe-3.1', ebin])],
ok = file:set_cwd(LatestDir),
{ok, _, _} = systools:make_script(LatestName, [silent, {path, P}]),
ok = systools:make_tar(LatestName, [{path, P}]),
ok = check_tar(fname([lib,'db-2.1',ebin,'db.app']), LatestName),
{ok, _, _} = systools:make_tar(LatestName, [{path, P}, silent]),
ok = check_tar(fname([lib,'fe-3.1',ebin,'fe.app']), LatestName),
ok = file:set_cwd(OldDir),
ok.
%% make_tar: Modules specified without version in .app file (db-3.1).
%% Note that this is now the normal way - i.e. systools now ignores
%% the module versions in the .app file.
no_mod_vsn_tar(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
{LatestDir, LatestName} = create_script(latest_no_mod_vsn,Config),
DataDir = filename:absname(?copydir),
LibDir = fname([DataDir, d_normal, lib]),
P = [fname([LibDir, 'db-3.1', ebin]),
fname([LibDir, 'fe-3.1', ebin])],
ok = file:set_cwd(LatestDir),
{ok, _, _} = systools:make_script(LatestName, [silent, {path, P}]),
ok = systools:make_tar(LatestName, [{path, P}]),
ok = check_tar(fname([lib,'db-3.1',ebin,'db.app']), LatestName),
{ok, _, _} = systools:make_tar(LatestName, [{path, P}, silent]),
ok = check_tar(fname([lib,'fe-3.1',ebin,'fe.app']), LatestName),
ok = file:set_cwd(OldDir),
ok.
%% make_tar: Check that relup or sys.config are included if they exist
system_files_tar(Config) ->
{ok, OldDir} = file:get_cwd(),
{LatestDir, LatestName} = create_script(latest,Config),
DataDir = filename:absname(?copydir),
LibDir = fname([DataDir, d_normal, lib]),
P = [fname([LibDir, 'db-2.1', ebin]),
fname([LibDir, 'fe-3.1', ebin])],
ok = file:set_cwd(LatestDir),
%% Add dummy relup and sys.config
ok = file:write_file("sys.config","[].\n"),
ok = file:write_file("relup","{\"LATEST\",[],[]}.\n"),
{ok, _, _} = systools:make_script(LatestName, [silent, {path, P}]),
ok = systools:make_tar(LatestName, [{path, P}]),
ok = check_tar(fname(["releases","LATEST","sys.config"]), LatestName),
ok = check_tar(fname(["releases","LATEST","relup"]), LatestName),
{ok, _, _} = systools:make_tar(LatestName, [{path, P}, silent]),
ok = check_tar(fname(["releases","LATEST","sys.config"]), LatestName),
ok = check_tar(fname(["releases","LATEST","relup"]), LatestName),
ok = file:set_cwd(OldDir),
ok.
system_files_tar(cleanup,Config) ->
Dir = ?privdir,
file:delete(filename:join(Dir,"sys.config")),
file:delete(filename:join(Dir,"relup")),
ok.
%% make_tar: Check that make_tar fails if relup or sys.config exist
%% but do not have valid content
invalid_system_files_tar(Config) ->
{ok, OldDir} = file:get_cwd(),
{LatestDir, LatestName} = create_script(latest,Config),
DataDir = filename:absname(?copydir),
LibDir = fname([DataDir, d_normal, lib]),
P = [fname([LibDir, 'db-2.1', ebin]),
fname([LibDir, 'fe-3.1', ebin])],
ok = file:set_cwd(LatestDir),
{ok, _, _} = systools:make_script(LatestName, [silent, {path, P}]),
%% Add dummy relup and sys.config - faulty sys.config
ok = file:write_file("sys.config","[]\n"), %!!! syntax error - missing '.'
ok = file:write_file("relup","{\"LATEST\",[],[]}.\n"),
error = systools:make_tar(LatestName, [{path, P}]),
{error,_,{tar_error,{add,"sys.config",[{error,_}]}}} =
systools:make_tar(LatestName, [{path, P}, silent]),
%% Add dummy relup and sys.config - faulty sys.config
ok = file:write_file("sys.config","[x,y].\n"), %!!! faulty format
ok = file:write_file("relup","{\"LATEST\",[],[]}.\n"),
error = systools:make_tar(LatestName, [{path, P}]),
{error,_,{tar_error,{add,"sys.config",[invalid_format]}}} =
systools:make_tar(LatestName, [{path, P}, silent]),
%% Add dummy relup and sys.config - faulty relup
ok = file:write_file("sys.config","[]\n"),
ok = file:write_file("relup","{\"LATEST\"\n"), %!!! syntax error - truncated
error = systools:make_tar(LatestName, [{path, P}]),
{error,_,{tar_error,{add,"relup",[{error,_}]}}} =
systools:make_tar(LatestName, [{path, P}, silent]),
%% Add dummy relup and sys.config - faulty relup
ok = file:write_file("sys.config","[]\n"),
ok = file:write_file("relup","[].\n"), %!!! faulty format
error = systools:make_tar(LatestName, [{path, P}]),
{error,_,{tar_error,{add,"relup",[invalid_format]}}} =
systools:make_tar(LatestName, [{path, P}, silent]),
ok = file:set_cwd(OldDir),
ok.
invalid_system_files_tar(cleanup,Config) ->
Dir = ?privdir,
file:delete(filename:join(Dir,"sys.config")),
file:delete(filename:join(Dir,"relup")),
ok.
%% make_tar: Use variable and create separate tar (included in generated tar).
variable_tar(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
{LatestDir, LatestName} = create_script(latest,Config),
DataDir = filename:absname(?copydir),
LibDir = fname([DataDir, d_normal, lib]),
P = [fname([LibDir, 'db-2.1', ebin]),
fname([LibDir, 'fe-3.1', ebin])],
ok = file:set_cwd(LatestDir),
{ok, _, _} = systools:make_script(LatestName,
[silent,
{path, P},
{variables,[{"TEST", LibDir}]}]),
ok = systools:make_tar(LatestName, [{path, P},
{variables,[{"TEST", LibDir}]}]),
ok = check_var_tar("TEST", LatestName),
{ok, _, _} = systools:make_tar(LatestName,
[{path, P}, silent,
{variables,[{"TEST", LibDir}]}]),
ok = check_var_tar("TEST", LatestName),
ok = file:set_cwd(OldDir),
ok.
%% make_tar: Check that symlinks in applications are handled correctly.
link_tar(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
{LatestDir, LatestName} = create_script(latest,Config),
DataDir = filename:absname(?copydir),
LibDir = fname([DataDir, d_links, lib]),
P = [fname([LibDir, 'db-2.1', ebin]),
fname([LibDir, 'fe-3.1', ebin])],
%% Make some links
Db1Erl = fname(['db-2.1',src,'db1.erl']),
NormalDb1Erl = fname([DataDir,d_normal,lib,Db1Erl]),
LinkDb1Erl = fname([LibDir, Db1Erl]),
ok = file:make_symlink(NormalDb1Erl, LinkDb1Erl),
Db1Beam = fname(['db-2.1',ebin,'db1.beam']),
NormalDb1Beam = fname([DataDir,d_normal,lib,Db1Beam]),
LinkDb1Beam = fname([LibDir, Db1Beam]),
ok = file:make_symlink(NormalDb1Beam, LinkDb1Beam),
FeApp = fname(['fe-3.1',ebin,'fe.app']),
NormalFeApp = fname([DataDir,d_normal,lib,FeApp]),
LinkFeApp = fname([LibDir, FeApp]),
ok = file:make_symlink(NormalFeApp, LinkFeApp),
%% Create the tar and check that the linked files are included as
%% regular files
ok = file:set_cwd(LatestDir),
{ok,_,[]} = systools:make_script(LatestName, [{path, P},silent]),
{ok, _, []} = systools:make_tar(LatestName, [{path, P}, silent]),
ok = check_tar_regular(?privdir,
[fname([lib,FeApp]),
fname([lib,Db1Beam])],
LatestName),
{ok, _, []} = systools:make_tar(LatestName, [{path, P}, silent,
{dirs, [src]}]),
ok = check_tar_regular(?privdir,
[fname([lib,FeApp]),
fname([lib,Db1Beam]),
fname([lib,Db1Erl])],
LatestName),
ok = file:set_cwd(OldDir),
ok.
%% make_tar: Do not check date of object file or that source code can be found.
src_tests_tar(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
{LatestDir, LatestName} = create_script(latest,Config),
DataDir = filename:absname(?copydir),
LibDir = fname([DataDir, d_missing_src, lib]),
P1 = fname([LibDir, 'db-2.1', ebin]),
P2 = fname([LibDir, 'fe-3.1', ebin]),
P = [P1, P2],
ok = file:set_cwd(LatestDir),
%% Manipulate the modification date of a beam file so it seems
%% older than the .erl file
Erl = filename:join([P1,"..","src","db1.erl"]),
{ok, FileInfo=#file_info{mtime={{Y,M,D},T}}} = file:read_file_info(Erl),
Beam = filename:join(P1,"db1.beam"),
ok = file:write_file_info(Beam, FileInfo#file_info{mtime={{Y-1,M,D},T}}),
%% Remove a .erl file
Erl2 = filename:join([P1,"..","src","db2.erl"]),
file:delete(Erl2),
ok = systools:make_script(LatestName, [{path, P}]),
%% Then make tar - two warnings should be issued when
%% src_tests is given
%% 1. old object code for db1.beam
%% 2. missing source code for db2.beam
{ok, _, [{warning,{obj_out_of_date,_}},
{warning,{source_not_found,_}}]} =
systools:make_tar(LatestName, [{path, P}, silent,
{dirs, [src]},
src_tests]),
ok = check_tar(fname([lib,'db-2.1',src,'db1.erl']), LatestName),
%% Without the src_tests option, no warning should be issued
{ok, _, []} = systools:make_tar(LatestName, [{path, P}, silent,
{dirs, [src]}]),
ok = check_tar(fname([lib,'db-2.1',src,'db1.erl']), LatestName),
%% Check that the old no_module_tests option (from the time when
%% it was default to do the src_test) is ignored
{ok, _, [{warning,{obj_out_of_date,_}},
{warning,{source_not_found,_}}]} =
systools:make_tar(LatestName, [{path, P}, silent,
{dirs, [src]},
no_module_tests,
src_tests]),
ok = check_tar(fname([lib,'db-2.1',src,'db1.erl']), LatestName),
ok = file:set_cwd(OldDir),
ok.
%% make_tar: Check that make_tar handles generation and placement of
%% tar files for variables outside the main tar file.
%% Test the {var_tar, include | ownfile | omit} optio.
var_tar(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
PSAVE = code:get_path(), % Save path
{LatestDir, LatestName} = create_script(latest,Config),
DataDir = filename:absname(?copydir),
LibDir = fname([DataDir, d_normal, lib]),
P = [fname([LibDir, 'db-2.1', ebin]),
fname([LibDir, 'fe-3.1', ebin])],
ok = file:set_cwd(LatestDir),
{ok, _, _} = systools:make_script(LatestName,
[silent,
{path, P},
{variables,[{"TEST", LibDir}]}]),
ok = systools:make_tar(LatestName, [{path, P},
{var_tar, ownfile},
{variables,[{"TEST", LibDir}]}]),
true = exists_tar_file("TEST"), %% Also removes the file !
{error, {not_generated, _}} = check_var_tar("TEST", LatestName),
ok = systools:make_tar(LatestName, [{path, P},
{var_tar, omit},
{variables,[{"TEST", LibDir}]}]),
{error, {not_generated, _}} = check_var_tar("TEST", LatestName),
false = exists_tar_file("TEST"),
ok = systools:make_tar(LatestName, [{path, P},
{var_tar, include},
{variables,[{"TEST", LibDir}]}]),
ok = check_var_tar("TEST", LatestName),
false = exists_tar_file("TEST"),
ok = file:set_cwd(OldDir),
code:set_path(PSAVE),
ok.
%% make_tar: Check exref option.
exref_tar(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
{LatestDir, LatestName} = create_script(latest,Config),
DataDir = filename:absname(?copydir),
LibDir = fname([DataDir, d_normal, lib]),
P = [fname([LibDir, 'db-2.1', ebin]),
fname([LibDir, 'fe-3.1', ebin])],
ok = file:set_cwd(LatestDir),
{ok, _, _} = systools:make_script(LatestName, [silent, {path, P}]),
%% Complete exref
{ok, _, W1} =
systools:make_tar(LatestName, [exref, {path, P}, silent]),
check_exref_warnings(with_db1, W1),
ok = check_tar(fname([lib,'db-2.1',ebin,'db.app']), LatestName),
%% Only exref the db application.
{ok, _, W2} =
systools:make_tar(LatestName, [{exref, [db]}, {path, P}, silent]),
check_exref_warnings(with_db1, W2),
ok = check_tar(fname([lib,'fe-3.1',ebin,'fe.app']), LatestName),
%% Only exref the fe application.
{ok, _, W3} =
systools:make_tar(LatestName, [{exref, [fe]}, {path, P}, silent]),
check_exref_warnings(without_db1, W3),
ok = check_tar(fname([lib,'db-2.1',ebin,'db.app']), LatestName),
%% exref the db and stdlib applications.
{ok, _, W4} =
systools:make_tar(LatestName, [{exref, [db, stdlib]},
{path, P}, silent]),
check_exref_warnings(with_db1, W4),
ok = check_tar(fname([lib,'fe-3.1',ebin,'fe.app']), LatestName),
ok = file:set_cwd(OldDir),
ok.
%% make_tar: OTP-9507 - make_tar failed when path given as just 'ebin'.
otp_9507_path_ebin(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
{LatestDir, LatestName} = create_script(latest_small,Config),
DataDir = filename:absname(?copydir),
LibDir = fname([DataDir, d_normal, lib]),
FeDir = fname([LibDir, 'fe-3.1']),
ok = file:set_cwd(FeDir),
RelName = fname([LatestDir,LatestName]),
P1 = ["./ebin",
fname([DataDir, lib, kernel, ebin]),
fname([DataDir, lib, stdlib, ebin]),
fname([DataDir, lib, sasl, ebin])],
{ok, _, _} = systools:make_script(RelName, [silent, {path, P1}]),
ok = systools:make_tar(RelName, [{path, P1}]),
Content1 = tar_contents(RelName),
P2 = ["ebin",
fname([DataDir, lib, kernel, ebin]),
fname([DataDir, lib, stdlib, ebin]),
fname([DataDir, lib, sasl, ebin])],
%% Tickets solves the following line - it used to fail with
%% {function_clause,[{filename,join,[[]]},...}
ok = systools:make_tar(RelName, [{path, P2}]),
Content2 = tar_contents(RelName),
true = (Content1 == Content2),
ok = file:set_cwd(OldDir),
ok.
%% make_relup: Check normal case
normal_relup(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
{LatestDir,LatestName} = create_script(latest0,Config),
{_LatestDir1,LatestName1} = create_script(latest1,Config),
{_LatestDir2,LatestName2} = create_script(latest2,Config),
DataDir = filename:absname(?copydir),
LibDir = [fname([DataDir, d_normal, lib])],
P = [fname([LibDir, '*', ebin]),
fname([DataDir, lib, kernel, ebin]),
fname([DataDir, lib, stdlib, ebin]),
fname([DataDir, lib, sasl, ebin])],
ok = file:set_cwd(LatestDir),
%% This is the ultra normal case
ok = systools:make_relup(LatestName, [LatestName1], [LatestName1],
[{path, P}]),
ok = check_relup([{db, "2.1"}], [{db, "1.0"}]),
{ok, _, _, []} =
systools:make_relup(LatestName, [LatestName1], [LatestName1],
[{path, P}, silent]),
ok = check_relup([{db, "2.1"}], [{db, "1.0"}]),
%% file should not be written if warnings_as_errors is enabled.
%% delete before running tests.
ok = file:delete("relup"),
%% Check that warnings are treated as errors
error =
systools:make_relup(LatestName, [LatestName2], [LatestName1],
[{path, P}, warnings_as_errors]),
error =
systools:make_relup(LatestName, [LatestName2], [LatestName1],
[{path, P}, silent, warnings_as_errors]),
%% relup file should not exist
false = filelib:is_regular("relup"),
%% Check that warnings get through
ok = systools:make_relup(LatestName, [LatestName2], [LatestName1],
[{path, P}]),
ok = check_relup([{fe, "3.1"}, {db, "2.1"}], [{db, "1.0"}]),
{ok, _, _, [pre_R15_emulator_upgrade,{erts_vsn_changed, _}]} =
systools:make_relup(LatestName, [LatestName2], [LatestName1],
[{path, P}, silent]),
ok = check_relup([{fe, "3.1"}, {db, "2.1"}], [{db, "1.0"}]),
%% relup file should exist now
true = filelib:is_regular("relup"),
ok = file:set_cwd(OldDir),
ok.
%% make_relup: Test relup which includes emulator restart.
restart_relup(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
{LatestDir,LatestName} = create_script(latest0,Config),
{_LatestDir1,LatestName1} = create_script(latest1,Config),
{_LatestDir0CurrErts,LatestName0CurrErts} =
create_script(latest0_current_erts,Config),
{_CurrentAllDir,CurrentAllName} = create_script(current_all,Config),
{_CurrentAllFutErtsDir,CurrentAllFutErtsName} =
create_script(current_all_future_erts,Config),
{_CurrentAllFutSaslDir,CurrentAllFutSaslName} =
create_script(current_all_future_sasl,Config),
DataDir = filename:absname(?copydir),
LibDir = [fname([DataDir, d_normal, lib])],
P = [fname([LibDir, '*', ebin]),
fname([DataDir, lib, kernel, ebin]),
fname([DataDir, lib, stdlib, ebin]),
fname([DataDir, lib, sasl, ebin]),
fname([DataDir, lib, 'sasl-9.9', ebin])],
ok = file:set_cwd(LatestDir),
%% OTP-2561: Check that the option 'restart_emulator' generates a
%% "restart_emulator" instruction.
{ok, _ , _, []} =
systools:make_relup(LatestName, [LatestName1], [LatestName1],
[{path, P},restart_emulator,silent]),
ok = check_relup([{db, "2.1"}], [{db, "1.0"}]),
ok = check_restart_emulator(),
%% Pre-R15 to Post-R15 upgrade
{ok, _ , _, Ws} =
systools:make_relup(LatestName0CurrErts,
[LatestName1],
[LatestName1],
[{path, P},silent]),
ok = check_relup([{db,"2.1"}], [{db, "1.0"}]),
ok = check_pre_to_post_r15_restart_emulator(),
ok = check_pre_to_post_r15_warnings(Ws),
%% Check that new sasl version generates a restart_new_emulator
%% instruction
{ok, _ , _, []} =
systools:make_relup(CurrentAllFutSaslName,
[CurrentAllName],
[CurrentAllName],
[{path, P},silent]),
ok = check_relup([{fe, "3.1"}], []),
ok = check_restart_emulator_diff_coreapp(),
%% Check that new erts version generates a restart_new_emulator
%% instruction, if FromSaslVsn >= R15SaslVsn
%% (One erts_vsn_changed warning for upgrade and one for downgrade)
{ok, _ , _, [{erts_vsn_changed,_},{erts_vsn_changed,_}]} =
systools:make_relup(CurrentAllFutErtsName,
[CurrentAllName],
[CurrentAllName],
[{path, P},silent]),
ok = check_relup([{fe, "3.1"}], []),
ok = check_restart_emulator_diff_coreapp(),
%% Check that new erts version generates a restart_new_emulator
%% instruction, and can be combined with restart_emulator opt.
%% (One erts_vsn_changed warning for upgrade and one for downgrade)
{ok, _ , _, [{erts_vsn_changed,_},{erts_vsn_changed,_}]} =
systools:make_relup(CurrentAllFutErtsName,
[CurrentAllName],
[CurrentAllName],
[{path, P},restart_emulator,silent]),
ok = check_relup([{fe, "3.1"}], []),
ok = check_restart_emulator(),
ok = check_restart_emulator_diff_coreapp(),
ok = file:set_cwd(OldDir),
ok.
%% This test fails if wrong version numbers are seen in the relup file
%% or if any application is missing. This was triggered by OTP-1360.
check_relup(UpVsnL, DnVsnL) ->
{ok, [{_V1, [{_, _, Up}], [{_, _, Dn}]}]} = file:consult(relup),
[] = foldl(fun(X, Acc) ->
true = lists:member(X, Acc),
lists:delete(X, Acc) end,
UpVsnL,
[{App, Vsn} || {load_object_code,{App,Vsn,_}} <- Up]),
[] = foldl(fun(X, Acc) ->
true = lists:member(X, Acc),
lists:delete(X, Acc) end,
DnVsnL,
[{App, Vsn} || {load_object_code,{App,Vsn,_}} <- Dn]),
ok.
check_relup_up_only(UpVsnL) ->
{ok, [{_V1, [{_, _, Up}], []}]} = file:consult(relup),
[] = foldl(fun(X, Acc) ->
true = lists:member(X, Acc),
lists:delete(X, Acc) end,
UpVsnL,
[{App, Vsn} || {load_object_code,{App,Vsn,_}} <- Up]),
ok.
check_restart_emulator() ->
{ok, [{_V1, [{_, _, Up}], [{_, _, Dn}]}]} = file:consult(relup),
restart_emulator = lists:last(Up),
restart_emulator = lists:last(Dn),
ok.
check_restart_emulator_up_only() ->
{ok, [{_V1, [{_, _, Up}], []}]} = file:consult(relup),
restart_emulator = lists:last(Up),
ok.
check_restart_emulator_diff_coreapp() ->
{ok, [{_V1, [{_, _, Up}], [{_, _, Dn}]}]} = file:consult(relup),
[restart_new_emulator|_] = Up,
restart_emulator = lists:last(Dn),
ok.
check_pre_to_post_r15_restart_emulator() ->
{ok, [{_V1, [{_, _, Up}], [{_, _, Dn}]}]} = file:consult(relup),
restart_new_emulator = lists:last(Up),
restart_emulator = lists:last(Dn),
ok.
check_pre_to_post_r15_warnings(Ws) ->
true = lists:member(pre_R15_emulator_upgrade,Ws),
ok.
%% make_relup: Check that appup files may be missing, but only if we
%% don't need them.
no_appup_relup(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
{LatestDir,LatestName} = create_script(latest_small,Config),
{_LatestDir0,LatestName0} = create_script(latest_small0,Config),
{_LatestDir1,LatestName1} = create_script(latest_small1,Config),
DataDir = filename:absname(?copydir),
ok = file:set_cwd(LatestDir),
%% Check that appup might be missing
P1 = [fname([DataDir, d_no_appup, lib, 'fe-3.1', ebin]),
fname([DataDir, lib, kernel, ebin]),
fname([DataDir, lib, stdlib, ebin]),
fname([DataDir, lib, sasl, ebin])],
ok =
systools:make_relup(LatestName, [LatestName], [], [{path, P1}]),
{ok,_, _, []} =
systools:make_relup(LatestName, [LatestName], [],
[silent, {path, P1}]),
%% Check that appup might NOT be missing when we need it
P2 = [fname([DataDir, d_no_appup, lib, 'fe-3.1', ebin]),
fname([DataDir, d_no_appup, lib, 'fe-2.1', ebin]),
fname([DataDir, lib, kernel, ebin]),
fname([DataDir, lib, stdlib, ebin]),
fname([DataDir, lib, sasl, ebin])],
error =
systools:make_relup(LatestName, [LatestName0], [], [{path, P2}]),
{error,_,{file_problem, {_,{error,{open,_,_}}}}} =
systools:make_relup(LatestName, [], [LatestName0],
[silent, {path, P2}]),
%% Check that appups missing vsn traps
P3 = [fname([DataDir, d_no_appup, lib, 'fe-2.1', ebin]),
fname([DataDir, d_no_appup, lib, 'fe-500.18.7', ebin]),
fname([DataDir, lib, kernel, ebin]),
fname([DataDir, lib, stdlib, ebin]),
fname([DataDir, lib, sasl, ebin])],
error =
systools:make_relup(LatestName0, [LatestName1], [], [{path, P3}]),
{error,_,{no_relup, _, _, _}} =
systools:make_relup(LatestName0, [], [LatestName1],
[silent, {path, P3}]),
ok = file:set_cwd(OldDir),
ok.
%% make_relup: Check that badly written appup files are detected.
bad_appup_relup(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
{LatestDir,LatestName} = create_script(latest_small,Config),
{_LatestDir0,LatestName0} = create_script(latest_small0,Config),
DataDir = filename:absname(?copydir),
N2 = [fname([DataDir, d_bad_appup, lib, 'fe-3.1', ebin]),
fname([DataDir, d_bad_appup, lib, 'fe-2.1', ebin]),
fname([DataDir, lib, kernel, ebin]),
fname([DataDir, lib, stdlib, ebin]),
fname([DataDir, lib, sasl, ebin])],
ok = file:set_cwd(LatestDir),
%% Check that bad appup is trapped
error =
systools:make_relup(LatestName, [LatestName0], [], [{path, N2}]),
{error,_,{file_problem, {_, {error, {parse,_, _}}}}} =
systools:make_relup(LatestName, [], [LatestName0],
[silent, {path, N2}]),
ok = file:set_cwd(OldDir),
ok.
%% make_relup: Check some abnormal cases.
abnormal_relup(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
{LatestDir,LatestName} = create_script(latest0,Config),
{_LatestDir1,LatestName1} = create_script(latest1,Config),
%% Check wrong app vsn
DataDir = filename:absname(?copydir),
P = [fname([DataDir, d_bad_app_vsn, lib, 'db-2.1', ebin]),
fname([DataDir, d_bad_app_vsn, lib, 'fe-3.1', ebin]),
fname([DataDir, lib, kernel, ebin]),
fname([DataDir, lib, stdlib, ebin]),
fname([DataDir, lib, sasl, ebin])],
ok = file:set_cwd(LatestDir),
error = systools:make_relup(LatestName, [LatestName1], [LatestName1],
[{path, P}]),
R0 = systools:make_relup(LatestName, [LatestName1], [LatestName1],
[silent, {path, P}]),
{error,systools_make,
[{error_reading,{db,{no_valid_version,
{{"should be","2.1"},
{"found file", _, "2.0"}}}}}]} = R0,
ok = file:set_cwd(OldDir),
ok.
%% make_relup: Check relup can not be created is sasl is not in rel file.
no_sasl_relup(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
{Dir1,Name1} = create_script(latest1_no_sasl,Config),
{_Dir2,Name2} = create_script(latest1,Config),
DataDir = filename:absname(?copydir),
LibDir = [fname([DataDir, d_normal, lib])],
P = [fname([LibDir, '*', ebin]),
fname([DataDir, lib, kernel, ebin]),
fname([DataDir, lib, stdlib, ebin]),
fname([DataDir, lib, sasl, ebin])],
ok = file:set_cwd(Dir1),
error = systools:make_relup(Name2, [Name1], [Name1], [{path, P}]),
R1 = systools:make_relup(Name2, [Name1], [Name1],[silent, {path, P}]),
{error,systools_relup,{missing_sasl,_}} = R1,
error = systools:make_relup(Name1, [Name2], [Name2], [{path, P}]),
R2 = systools:make_relup(Name1, [Name2], [Name2],[silent, {path, P}]),
{error,systools_relup,{missing_sasl,_}} = R2,
ok = file:set_cwd(OldDir),
ok.
%% make_relup: Check that application start type is used in relup
app_start_type_relup(Config) when is_list(Config) ->
PrivDir = ?config(priv_dir, Config),
{Dir1,Name1} = create_script(latest_app_start_type1,Config),
{Dir2,Name2} = create_script(latest_app_start_type2,Config),
Release1 = filename:join(Dir1,Name1),
Release2 = filename:join(Dir2,Name2),
{ok, Release2Relup, systools_relup, []} = systools:make_relup(Release2, [Release1], [Release1], [{outdir, PrivDir}, silent]),
{"LATEST_APP_START_TYPE2",
[{"LATEST_APP_START_TYPE1",[], UpInstructions}],
[{"LATEST_APP_START_TYPE1",[], DownInstructions}]} = Release2Relup,
%% ?t:format("Up: ~p",[UpInstructions]),
%% ?t:format("Dn: ~p",[DownInstructions]),
[{load_object_code, {mnesia, _, _}},
{load_object_code, {runtime_tools, _, _}},
{load_object_code, {webtool, _, _}},
{load_object_code, {snmp, _, _}},
{load_object_code, {xmerl, _, _}},
point_of_no_return
| UpInstructionsT] = UpInstructions,
true = lists:member({apply,{application,start,[mnesia,permanent]}}, UpInstructionsT),
true = lists:member({apply,{application,start,[runtime_tools,transient]}}, UpInstructionsT),
true = lists:member({apply,{application,start,[webtool,temporary]}}, UpInstructionsT),
true = lists:member({apply,{application,load,[snmp]}}, UpInstructionsT),
false = lists:any(fun({apply,{application,_,[xmerl|_]}}) -> true; (_) -> false end, UpInstructionsT),
[point_of_no_return | DownInstructionsT] = DownInstructions,
true = lists:member({apply,{application,stop,[mnesia]}}, DownInstructionsT),
true = lists:member({apply,{application,stop,[runtime_tools]}}, DownInstructionsT),
true = lists:member({apply,{application,stop,[webtool]}}, DownInstructionsT),
true = lists:member({apply,{application,stop,[snmp]}}, DownInstructionsT),
true = lists:member({apply,{application,stop,[xmerl]}}, DownInstructionsT),
true = lists:member({apply,{application,unload,[mnesia]}}, DownInstructionsT),
true = lists:member({apply,{application,unload,[runtime_tools]}}, DownInstructionsT),
true = lists:member({apply,{application,unload,[webtool]}}, DownInstructionsT),
true = lists:member({apply,{application,unload,[snmp]}}, DownInstructionsT),
true = lists:member({apply,{application,unload,[xmerl]}}, DownInstructionsT),
ok.
%% make_relup: Check that regexp can be used in .appup for UpFromVsn
%% and DownToVsn.
regexp_relup(Config) ->
{ok, OldDir} = file:get_cwd(),
{LatestDir,LatestName} = create_script(latest_small,Config),
{_LatestDir0,LatestName0} = create_script(latest_small0,Config),
{_LatestDir1,LatestName1} = create_script(latest_small2,Config),
DataDir = filename:absname(?copydir),
P = [fname([DataDir, d_regexp_appup, lib, '*', ebin]),
fname([DataDir, lib, kernel, ebin]),
fname([DataDir, lib, stdlib, ebin]),
fname([DataDir, lib, sasl, ebin])],
ok = file:set_cwd(LatestDir),
%% Upgrade fe 2.1 -> 3.1, and downgrade 2.1 -> 3.1
%% Shall match the first entry if fe-3.1 appup.
{ok, _, _, []} =
systools:make_relup(LatestName, [LatestName0], [LatestName0],
[{path, P}, silent]),
ok = check_relup([{fe, "3.1"}], [{fe, "2.1"}]),
%% Upgrade fe 2.1.1 -> 3.1
%% Shall match the second entry in fe-3.1 appup. Have added a
%% restart_emulator instruction there to distinguish it from
%% the first entry...
{ok, _, _, []} =
systools:make_relup(LatestName, [LatestName1], [], [{path, P}, silent]),
ok = check_relup_up_only([{fe, "3.1"}]),
ok = check_restart_emulator_up_only(),
%% Attempt downgrade fe 3.1 -> 2.1.1
%% Shall not match any entry!!
{error,systools_relup,{no_relup,_,_,_}} =
systools:make_relup(LatestName, [], [LatestName1], [{path, P}, silent]),
ok = file:set_cwd(OldDir),
ok.
%% make_hybrid_boot: Normal case.
%% For upgrade of erts - create a boot file which is a hybrid between
%% old and new release - i.e. starts erts, kernel, stdlib, sasl from
%% new release, all other apps from old release.
normal_hybrid(Config) ->
{ok, OldDir} = file:get_cwd(),
{Dir1,Name1} = create_script(latest1,Config),
{_Dir2,Name2} = create_script(current_all,Config),
DataDir = filename:absname(?copydir),
LibDir = [fname([DataDir, d_normal, lib])],
P = [fname([LibDir, '*', ebin]),
fname([DataDir, lib, kernel, ebin]),
fname([DataDir, lib, stdlib, ebin]),
fname([DataDir, lib, sasl, ebin])],
ok = file:set_cwd(Dir1),
{ok, _ , []} = systools:make_script(Name1,[{path, P},silent]),
{ok, _ , []} = systools:make_script(Name2,[{path, P},silent]),
{ok,Boot1} = file:read_file(Name1 ++ ".boot"),
{ok,Boot2} = file:read_file(Name2 ++ ".boot"),
ok = file:set_cwd(OldDir),
BasePaths = {"testkernelpath","teststdlibpath","testsaslpath"},
{ok,Hybrid} = systools_make:make_hybrid_boot("tmp_vsn",Boot1,Boot2,
BasePaths, [dummy,args]),
{script,{"Test release","tmp_vsn"},Script} = binary_to_term(Hybrid),
ct:log("~p.~n",[Script]),
%% Check that all paths to base apps are replaced by paths from BaseLib
Boot1Str = io_lib:format("~p~n",[binary_to_term(Boot1)]),
HybridStr = io_lib:format("~p~n",[binary_to_term(Hybrid)]),
ReOpts = [global,{capture,first,list},unicode],
{match,OldKernelMatch} = re:run(Boot1Str,"kernel-[0-9\.]+",ReOpts),
{match,OldStdlibMatch} = re:run(Boot1Str,"stdlib-[0-9\.]+",ReOpts),
{match,OldSaslMatch} = re:run(Boot1Str,"sasl-[0-9\.]+",ReOpts),
nomatch = re:run(HybridStr,"kernel-[0-9\.]+",ReOpts),
nomatch = re:run(HybridStr,"stdlib-[0-9\.]+",ReOpts),
nomatch = re:run(HybridStr,"sasl-[0-9\.]+",ReOpts),
{match,NewKernelMatch} = re:run(HybridStr,"testkernelpath",ReOpts),
{match,NewStdlibMatch} = re:run(HybridStr,"teststdlibpath",ReOpts),
{match,NewSaslMatch} = re:run(HybridStr,"testsaslpath",ReOpts),
NewKernelN = length(NewKernelMatch),
NewKernelN = length(OldKernelMatch),
NewStdlibN = length(NewStdlibMatch),
NewStdlibN = length(OldStdlibMatch),
NewSaslN = length(NewSaslMatch),
NewSaslN = length(OldSaslMatch),
%% Check that application load instruction has correct versions
Apps = application:loaded_applications(),
{_,_,KernelVsn} = lists:keyfind(kernel,1,Apps),
{_,_,StdlibVsn} = lists:keyfind(stdlib,1,Apps),
{_,_,SaslVsn} = lists:keyfind(sasl,1,Apps),
[KernelInfo] = [I || {kernelProcess,application_controller,
{application_controller,start,
[{application,kernel,I}]}} <- Script],
[StdlibInfo] = [I || {apply,
{application,load,
[{application,stdlib,I}]}} <- Script],
[SaslInfo] = [I || {apply,
{application,load,
[{application,sasl,I}]}} <- Script],
{vsn,KernelVsn} = lists:keyfind(vsn,1,KernelInfo),
{vsn,StdlibVsn} = lists:keyfind(vsn,1,StdlibInfo),
{vsn,SaslVsn} = lists:keyfind(vsn,1,SaslInfo),
%% Check that new_emulator_upgrade call is added
[_,{apply,{release_handler,new_emulator_upgrade,[dummy,args]}}|_] =
lists:reverse(Script),
%% Check that db-1.0 and fe-3.1 are used (i.e. vsns from old release)
%% And that fe is in there (it exists in old rel but not in new)
{match,DbMatch} = re:run(HybridStr,"db-[0-9\.]+",ReOpts),
{match,[_|_]=FeMatch} = re:run(HybridStr,"fe-[0-9\.]+",ReOpts),
true = lists:all(fun(["db-1.0"]) -> true;
(_) -> false
end,
DbMatch),
true = lists:all(fun(["fe-3.1"]) -> true;
(_) -> false
end,
FeMatch),
%% Check that script has same length as old script, plus one (the
%% new_emulator_upgrade apply)
{_,_,Old} = binary_to_term(Boot1),
OldLength = length(Old),
NewLength = length(Script),
NewLength = OldLength + 1,
ok.
%% make_hybrid_boot: No sasl in from-release.
%% Check that systools_make:make_hybrid_boot fails with a meaningful
%% error message if the FromBoot does not include the sasl
%% application.
hybrid_no_old_sasl(Config) ->
{ok, OldDir} = file:get_cwd(),
{Dir1,Name1} = create_script(latest1_no_sasl,Config),
{_Dir2,Name2} = create_script(current_all,Config),
DataDir = filename:absname(?copydir),
LibDir = [fname([DataDir, d_normal, lib])],
P = [fname([LibDir, '*', ebin]),
fname([DataDir, lib, kernel, ebin]),
fname([DataDir, lib, stdlib, ebin]),
fname([DataDir, lib, sasl, ebin])],
ok = file:set_cwd(Dir1),
{ok, _ , [{warning,missing_sasl}]} =
systools:make_script(Name1,[{path, P},silent]),
{ok, _ , []} = systools:make_script(Name2,[{path, P},silent]),
{ok,Boot1} = file:read_file(Name1 ++ ".boot"),
{ok,Boot2} = file:read_file(Name2 ++ ".boot"),
BasePaths = {"testkernelpath","teststdlibpath","testsaslpath"},
{error,{app_not_replaced,sasl}} =
systools_make:make_hybrid_boot("tmp_vsn",Boot1,Boot2,
BasePaths,[dummy,args]),
ok = file:set_cwd(OldDir),
ok.
%% make_hybrid_boot: No sasl in to-release.
%% Check that systools_make:make_hybrid_boot fails with a meaningful
%% error message if the ToBoot does not include the sasl
%% application.
hybrid_no_new_sasl(Config) ->
{ok, OldDir} = file:get_cwd(),
{Dir1,Name1} = create_script(latest1,Config),
{_Dir2,Name2} = create_script(current_all_no_sasl,Config),
DataDir = filename:absname(?copydir),
LibDir = [fname([DataDir, d_normal, lib])],
P = [fname([LibDir, '*', ebin]),
fname([DataDir, lib, kernel, ebin]),
fname([DataDir, lib, stdlib, ebin]),
fname([DataDir, lib, sasl, ebin])],
ok = file:set_cwd(Dir1),
{ok, _ , []} = systools:make_script(Name1,[{path, P},silent]),
{ok, _ , [{warning,missing_sasl}]} =
systools:make_script(Name2,[{path, P},silent]),
{ok,Boot1} = file:read_file(Name1 ++ ".boot"),
{ok,Boot2} = file:read_file(Name2 ++ ".boot"),
BasePaths = {"testkernelpath","teststdlibpath","testsaslpath"},
{error,{app_not_found,sasl}} =
systools_make:make_hybrid_boot("tmp_vsn",Boot1,Boot2,
BasePaths,[dummy,args]),
ok = file:set_cwd(OldDir),
ok.
%% options: {outdir,Dir} option
otp_6226_outdir(Config) when is_list(Config) ->
PrivDir = ?privdir,
{ok, OldDir} = file:get_cwd(),
{LatestDir, LatestName} = create_script(latest0,Config),
{_LatestDir, LatestName1} = create_script(latest1,Config),
DataDir = filename:absname(?copydir),
LibDir = fname([DataDir, d_normal, lib]),
P = [fname([LibDir, 'db-2.1', ebin]),
fname([LibDir, 'db-1.0', ebin]),
fname([LibDir, 'fe-3.1', ebin]),
fname([DataDir, lib, kernel, ebin]),
fname([DataDir, lib, stdlib, ebin]),
fname([DataDir, lib, sasl, ebin])],
ok = file:set_cwd(LatestDir),
%% Create an outdir1 directory
ok = file:make_dir("outdir1"),
%% ==== Now test systools:make_script ====
%% a) badarg
{'EXIT', {{badarg,[{outdir,outdir1}]}, _}} =
(catch systools:make_script(LatestName, [{outdir,outdir1},
{path,P},silent])),
%% b) absolute path
Outdir1 = filename:join(PrivDir, "outdir1"),
{ok,_,[]} = systools:make_script(LatestName, [{outdir,Outdir1},
{path,P},silent]),
Script1 = filename:join(Outdir1, LatestName ++ ".script"),
Boot1 = filename:join(Outdir1, LatestName ++ ".boot"),
true = filelib:is_file(Script1),
true = filelib:is_file(Boot1),
ok = file:delete(Script1),
ok = file:delete(Boot1),
%% c) relative path
{ok,_,[]} = systools:make_script(LatestName, [{outdir,"./outdir1"},
{path,P},silent]),
true = filelib:is_file(Script1),
true = filelib:is_file(Boot1),
ok = file:delete(Script1),
ok = file:delete(Boot1),
%% d) absolute but incorrect path
Outdir2 = filename:join(PrivDir, "outdir2"),
Script2 = filename:join(Outdir2, LatestName ++ ".script"),
{error,_,{open,Script2,_}} =
systools:make_script(LatestName, [{outdir,Outdir2},{path,P},silent]),
%% e) relative but incorrect path
{error,_,{open,_,_}} =
systools:make_script(LatestName, [{outdir,"./outdir2"},{path,P},silent]),
%% f) with .rel in another directory than cwd
ok = file:set_cwd(Outdir1),
{ok,_,[]} = systools:make_script(filename:join(PrivDir, LatestName),
[{outdir,"."},{path,P},silent]),
true = filelib:is_file(LatestName ++ ".script"),
true = filelib:is_file(LatestName ++ ".boot"),
ok = file:delete(LatestName ++ ".script"),
ok = file:delete(LatestName ++ ".boot"),
ok = file:set_cwd(LatestDir),
%% ==== Now test systools:make_tar =====
{ok,_,[]} = systools:make_script(LatestName, [{path,P},silent]),
%% a) badarg
{'EXIT', {{badarg, [{outdir,outdir1}]}, _}} =
(catch systools:make_tar(LatestName,[{outdir,outdir1},{path,P},silent])),
%% b) absolute path
{ok,_,[]} = systools:make_tar(LatestName, [{outdir,Outdir1},
{path,P},silent]),
Tar1 = filename:join(Outdir1,LatestName++".tar.gz"),
true = filelib:is_file(Tar1),
ok = file:delete(Tar1),
%% c) relative path
{ok,_,[]} = systools:make_tar(LatestName, [{outdir,"./outdir1"},
{path,P},silent]),
true = filelib:is_file(Tar1),
ok = file:delete(Tar1),
%% d) absolute but incorrect path
Tar2 = filename:join(Outdir2,LatestName++".tar.gz"),
{error,_,{tar_error,{open,Tar2,{Tar2,enoent}}}} =
systools:make_tar(LatestName, [{outdir,Outdir2},{path,P},silent]),
%% e) relative but incorrect path
{error,_,{tar_error,{open,_,_}}} =
systools:make_tar(LatestName, [{outdir,"./outdir2"},{path,P},silent]),
%% f) with .rel in another directory than cwd
ok = file:set_cwd(Outdir1),
{ok,_,[]} = systools:make_tar(filename:join(PrivDir, LatestName),
[{outdir,"."},{path,P},silent]),
true = filelib:is_file(Tar1),
ok = file:set_cwd(LatestDir),
%% ===== Now test systools:make_relup =====
%% a) badarg
{'EXIT', {{badarg, [{outdir,outdir1}]}, _}} =
(catch systools:make_relup(LatestName,[LatestName1],[LatestName1],
[{outdir,outdir1},
{path,P},silent])),
%% b) absolute path
Relup = filename:join(Outdir1, "relup"),
{ok,_,_,[]} = systools:make_relup(LatestName,[LatestName1],[LatestName1],
[{outdir,Outdir1},
{path,P},silent]),
true = filelib:is_file(Relup),
ok = file:delete(Relup),
%% c) relative path
{ok,_,_,[]} = systools:make_relup(LatestName,[LatestName1],[LatestName1],
[{outdir,"./outdir1"},
{path,P},silent]),
true = filelib:is_file(Relup),
ok = file:delete(Relup),
%% d) absolute but incorrect path
{error,_,{file_problem,{"relup",enoent}}} =
systools:make_relup(LatestName,[LatestName1],[LatestName1],
[{outdir,Outdir2},{path,P},silent]),
%% e) relative but incorrect path
{error,_,{file_problem,{"relup",enoent}}} =
systools:make_relup(LatestName,[LatestName1],[LatestName1],
[{outdir,"./outdir2"},{path,P},silent]),
%% f) with .rel in another directory than cwd
%% -- not necessary to test since relup by default is placed in
%% cwd, not in the same directory as the .rel file --
%% Change back to previous working directory
ok = file:set_cwd(OldDir),
ok.
%%%%%%
%%%%%% Utilities
%%%%%%
check_script_path(RelName) ->
{ok, [Conts]} = read_script_file(RelName),
{script, {_, _}, ListOfThings} = Conts,
case lists:keysearch(path, 1, ListOfThings) of
{value, {path, [$$,$R,$O,$O,$T | _]}} -> %"$ROOT..."
false;
_ -> ok
end.
check_var_script_file(VarDirs, NoExistDirs, RelName) ->
{ok, [Conts]} = read_script_file(RelName),
{script, {_, _}, ListOfThings} = Conts,
AllPaths = lists:append(lists:map(fun({path, P}) -> P;
(_) -> []
end,
ListOfThings)),
case lists:filter(fun(VarDir) -> lists:member(VarDir, AllPaths) end,
VarDirs) of
VarDirs ->
ok;
_ ->
test_server:fail("All variable dirs not in generated script")
end,
case lists:filter(fun(NoExistDir) -> lists:member(NoExistDir, AllPaths) end,
NoExistDirs) of
[] ->
ok;
_ ->
test_server:fail("Unexpected dirs in generated script")
end.
check_include_script(RelName, ExpectedLoad, ExpectedStart) ->
{ok, [Conts]} = read_script_file(RelName),
{script, {_, _}, ListOfThings} = Conts,
%% Check that the applications are loaded in given order !
ActualLoad =
[App || {apply,{application,load,[{application,App,_}]}} <- ListOfThings,
App=/=kernel,
App=/=stdlib],
if ActualLoad =:= ExpectedLoad -> ok;
true -> test_server:fail({bad_load_order, ActualLoad, ExpectedLoad})
end,
%% Check that applications are started in given order !
ActualStart =
[App || {apply,{application,start_boot,[App|_]}} <- ListOfThings,
App =/= kernel,
App =/= stdlib],
if ActualStart =:= ExpectedStart -> ok;
true -> test_server:fail({bad_start_order, ActualStart,ExpectedStart})
end,
ok.
read_script_file(RelName) ->
file:consult(RelName ++ ".script").
check_var_tar(Variable, RelName) ->
Expected = tar_name(Variable),
case check_tar(Expected,RelName) of
ok ->
ok;
{error, {erroneous_tar_file, _, missing, _}} ->
{error, {not_generated, Expected}}
end.
exists_tar_file(Name) ->
File = tar_name(Name),
case filelib:is_regular(File) of
true ->
ok = file:delete(File),
true;
_ ->
false
end.
%% Take a snap of the generated tar file and check if a certain
%% file is included.
%% This ensures at least that the tar file is generated.
check_tar(File, RelName) ->
TarContents = tar_contents(RelName),
case lists:member(File,TarContents) of
true -> ok;
_ -> {error, {erroneous_tar_file, tar_name(RelName), missing, File}}
end.
%% Check that the given files exist in the tar file, and that they are
%% not symlinks
check_tar_regular(PrivDir, Files, RelName) ->
TmpDir = fname(PrivDir,tmp),
ok = file:make_dir(TmpDir),
ok = erl_tar:extract(tar_name(RelName),
[{files,Files},{cwd,TmpDir},compressed]),
R = lists:foldl(fun(File,Acc) ->
case file:read_link_info(fname(TmpDir,File)) of
{ok,#file_info{type=regular}} ->
Acc;
{ok,#file_info{type=Other}} ->
[{File,Other}|Acc];
_ ->
[{File,missing}|Acc]
end
end,
[],
Files),
delete_tree(TmpDir),
case R of
[] ->
ok;
NotThere ->
{error,{erroneous_tar_file,tar_name(RelName),NotThere}}
end.
delete_tree(Dir) ->
case filelib:is_dir(Dir) of
true ->
{ok,Files} = file:list_dir(Dir),
lists:foreach(fun(File) -> delete_tree(filename:join(Dir,File)) end,
Files),
file:del_dir(Dir);
false ->
ok = file:delete(Dir)
end.
tar_contents(Name) ->
{ok, Cont} = erl_tar:table(Name ++ ".tar.gz", [compressed]),
Cont.
tar_name(Name) ->
Name ++ ".tar.gz".
create_script(latest,Config) ->
Apps = core_apps(current) ++ [{db,"2.1"},{fe,"3.1"}],
do_create_script(latest,Config,"4.4",Apps);
create_script(latest_no_mod_vsn,Config) ->
Apps = core_apps(current) ++ [{db,"3.1"},{fe,"3.1"}],
do_create_script(latest_no_mod_vsn,Config,"4.4",Apps);
create_script(latest0,Config) ->
Apps = core_apps("1.0") ++ [{db,"2.1"},{fe,"3.1"}],
do_create_script(latest0,Config,"4.4",Apps);
create_script(latest0_current_erts,Config) ->
Apps = core_apps("1.0") ++ [{db,"2.1"},{fe,"3.1"}],
do_create_script(latest0_current_erts,Config,current,Apps);
create_script(latest1,Config) ->
Apps = core_apps("1.0") ++ [{db,"1.0"},{fe,"3.1"}],
do_create_script(latest1,Config,"4.4",Apps);
create_script(latest1_no_sasl,Config) ->
Apps = [{kernel,"1.0"},{stdlib,"1.0"},{db,"1.0"},{fe,"3.1"}],
do_create_script(latest1_no_sasl,Config,"4.4",Apps);
create_script(latest2,Config) ->
Apps = core_apps("1.0") ++ [{db,"1.0"},{fe,"2.1"}],
do_create_script(latest2,Config,"4.3",Apps);
create_script(latest_small,Config) ->
Apps = core_apps("1.0") ++ [{fe,"3.1"}],
do_create_script(latest_small,Config,"4.4",Apps);
create_script(latest_small0,Config) -> %Differs in fe vsn
Apps = core_apps("1.0") ++ [{fe,"2.1"}],
do_create_script(latest_small0,Config,"4.4",Apps);
create_script(latest_small1,Config) ->
Apps = core_apps("1.0") ++ [{fe,"500.18.7"}],
do_create_script(latest_small1,Config,"4.4",Apps);
create_script(latest_small2,Config) ->
Apps = core_apps("1.0") ++ [{fe,"2.1.1"}],
do_create_script(latest_small2,Config,"4.4",Apps);
create_script(latest_nokernel,Config) ->
Apps = [{db,"2.1"},{fe,"3.1"}],
do_create_script(latest_nokernel,Config,"4.4",Apps);
create_script(latest_kernel_start_type,Config) ->
Apps = [{kernel,"1.0",load},{db,"2.1"},{fe,"3.1"}],
do_create_script(latest_kernel_start_type,Config,"4.4",Apps);
create_script(latest_app_start_type1,Config) ->
Apps = core_apps(current),
do_create_script(latest_app_start_type1,Config,current,Apps);
create_script(latest_app_start_type2,Config) ->
OtherApps = [{mnesia,current,permanent},
{runtime_tools,current,transient},
{webtool,current,temporary},
{snmp,current,load},
{xmerl,current,none}],
Apps = core_apps(current) ++ OtherApps,
do_create_script(latest_app_start_type2,Config,current,Apps);
create_script(current_all_no_sasl,Config) ->
Apps = [{kernel,current},{stdlib,current},{db,"2.1"},{fe,"3.1"}],
do_create_script(current_all_no_sasl,Config,current,Apps);
create_script(current_all,Config) ->
Apps = core_apps(current) ++ [{db,"2.1"}],
do_create_script(current_all,Config,current,Apps);
create_script(current_all_future_erts,Config) ->
Apps = core_apps(current) ++ [{db,"2.1"},{fe,"3.1"}],
do_create_script(current_all_future_erts,Config,"99.99",Apps);
create_script(current_all_future_sasl,Config) ->
Apps = [{kernel,current},{stdlib,current},{sasl,"9.9"},{db,"2.1"},{fe,"3.1"}],
do_create_script(current_all_future_sasl,Config,current,Apps).
do_create_script(Id,Config,ErtsVsn,AppVsns) ->
PrivDir = ?privdir,
Name = fname(PrivDir, Id),
{ok,Fd} = file:open(Name++".rel",write),
RelfileContent =
{release,{"Test release", string:to_upper(atom_to_list(Id))},
{erts,erts_vsn(ErtsVsn)},
app_vsns(AppVsns)},
io:format(Fd,"~p.~n",[RelfileContent]),
ok = file:close(Fd),
{filename:dirname(Name), filename:basename(Name)}.
core_apps(Vsn) ->
[{App,Vsn} || App <- [kernel,stdlib,sasl]].
app_vsns(AppVsns) ->
[{App,app_vsn(App,Vsn)} || {App,Vsn} <- AppVsns] ++
[{App,app_vsn(App,Vsn),Type} || {App,Vsn,Type} <- AppVsns].
app_vsn(App,current) ->
application:load(App),
{ok,Vsn} = application:get_key(App,vsn),
Vsn;
app_vsn(_App,Vsn) ->
Vsn.
erts_vsn(current) -> erlang:system_info(version);
erts_vsn(Vsn) -> Vsn.
create_include_files(inc1, Config) ->
PrivDir = ?privdir,
Name = fname(PrivDir, inc1),
create_apps(PrivDir),
Apps = application_controller:which_applications(),
{value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
{value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
" [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
++ StdlibVer ++ "\"},\n"
" {t6, \"1.0\"}, {t5, \"1.0\"}, \n"
" {t4, \"1.0\"}, {t3, \"1.0\"}, {t2, \"1.0\"}, \n"
" {t1, \"1.0\"}]}.\n",
file:write_file(Name ++ ".rel", list_to_binary(Rel)),
{filename:dirname(Name), filename:basename(Name)};
create_include_files(inc2, Config) ->
PrivDir = ?privdir,
Name = fname(PrivDir, inc2),
create_apps(PrivDir),
Apps = application_controller:which_applications(),
{value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
{value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
%% t6 does not include t5 !
Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
" [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
++ StdlibVer ++ "\"},\n"
" {t6, \"1.0\", [t4]}, {t5, \"1.0\"}, \n"
" {t4, \"1.0\"}, {t3, \"1.0\"}, {t2, \"1.0\"}, \n"
" {t1, \"1.0\"}]}.\n",
file:write_file(Name ++ ".rel", list_to_binary(Rel)),
{filename:dirname(Name), filename:basename(Name)};
create_include_files(inc3, Config) ->
PrivDir = ?privdir,
Name = fname(PrivDir, inc3),
create_apps(PrivDir),
Apps = application_controller:which_applications(),
{value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
{value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
%% t3 does not include t2 !
Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
" [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
++ StdlibVer ++ "\"},\n"
" {t6, \"1.0\"}, {t5, \"1.0\"}, \n"
" {t4, \"1.0\"}, {t3, \"1.0\", []}, {t2, \"1.0\"}, \n"
" {t1, \"1.0\"}]}.\n",
file:write_file(Name ++ ".rel", list_to_binary(Rel)),
{filename:dirname(Name), filename:basename(Name)};
create_include_files(inc4, Config) ->
PrivDir = ?privdir,
Name = fname(PrivDir, inc4),
create_apps(PrivDir),
Apps = application_controller:which_applications(),
{value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
{value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
%% t3 does not include t2 !
%% t6 does not include t5 !
Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
" [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
++ StdlibVer ++ "\"},\n"
" {t6, \"1.0\", [t4]}, {t5, \"1.0\"}, \n"
" {t4, \"1.0\"}, {t3, \"1.0\", []}, {t2, \"1.0\"}, \n"
" {t1, \"1.0\"}]}.\n",
file:write_file(Name ++ ".rel", list_to_binary(Rel)),
{filename:dirname(Name), filename:basename(Name)};
create_include_files(inc5, Config) ->
PrivDir = ?privdir,
Name = fname(PrivDir, inc5),
create_apps(PrivDir),
Apps = application_controller:which_applications(),
{value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
{value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
%% t6 does not include t5 !
%% exclude t5.
Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
" [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
++ StdlibVer ++ "\"},\n"
" {t6, \"1.0\", [t4]}, \n"
" {t4, \"1.0\"}, {t3, \"1.0\", []}, {t2, \"1.0\"}, \n"
" {t1, \"1.0\"}]}.\n",
file:write_file(Name ++ ".rel", list_to_binary(Rel)),
{filename:dirname(Name), filename:basename(Name)};
create_include_files(inc6, Config) ->
PrivDir = ?privdir,
Name = fname(PrivDir, inc6),
create_apps(PrivDir),
Apps = application_controller:which_applications(),
{value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
{value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
%% t3 does include non existing t2 !
Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
" [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
++ StdlibVer ++ "\"},\n"
" {t6, \"1.0\"}, {t5, \"1.0\"}, \n"
" {t4, \"1.0\"}, {t3, \"1.0\"}, \n"
" {t1, \"1.0\"}]}.\n",
file:write_file(Name ++ ".rel", list_to_binary(Rel)),
{filename:dirname(Name), filename:basename(Name)};
create_include_files(inc7, Config) ->
PrivDir = ?privdir,
Name = fname(PrivDir, inc7),
create_apps(PrivDir),
create_app(t7, PrivDir),
Apps = application_controller:which_applications(),
{value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
{value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
%% t7 and t6 does include t5 !
Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
" [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
++ StdlibVer ++ "\"},\n"
" {t7, \"1.0\"}, {t6, \"1.0\"}, {t5, \"1.0\"}, \n"
" {t4, \"1.0\"}, {t3, \"1.0\"}, {t2, \"1.0\"}, \n"
" {t1, \"1.0\"}]}.\n",
file:write_file(Name ++ ".rel", list_to_binary(Rel)),
{filename:dirname(Name), filename:basename(Name)};
create_include_files(inc8, Config) ->
PrivDir = ?privdir,
Name = fname(PrivDir, inc8),
create_circular_apps(PrivDir),
Apps = application_controller:which_applications(),
{value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
{value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
%% t8 uses t9 and t10 includes t9 !
Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
" [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
++ StdlibVer ++ "\"},\n"
" {t8, \"1.0\"}, {t9, \"1.0\"}, {t10, \"1.0\"}]}.\n",
file:write_file(Name ++ ".rel", list_to_binary(Rel)),
{filename:dirname(Name), filename:basename(Name)};
create_include_files(inc9, Config) ->
PrivDir = ?privdir,
Name = fname(PrivDir, inc9),
create_circular_apps(PrivDir),
Apps = application_controller:which_applications(),
{value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
{value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
%% t8 uses t9, t9 uses t10 and t10 includes t8 ==> circular !!
Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
" [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
++ StdlibVer ++ "\"},\n"
" {t8, \"1.0\"}, {t9, \"1.0\"}, {t10, \"1.0\", [t8]}]}.\n",
file:write_file(Name ++ ".rel", list_to_binary(Rel)),
{filename:dirname(Name), filename:basename(Name)};
create_include_files(inc10, Config) ->
PrivDir = ?privdir,
Name = fname(PrivDir, inc10),
create_circular_apps(PrivDir),
Apps = application_controller:which_applications(),
{value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
{value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
%% t9 tries to include not specified (in .app file) application !
Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
" [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
++ StdlibVer ++ "\"},\n"
" {t8, \"1.0\"}, {t9, \"1.0\", [t7]}, {t10, \"1.0\"}]}.\n",
file:write_file(Name ++ ".rel", list_to_binary(Rel)),
{filename:dirname(Name), filename:basename(Name)};
create_include_files(inc11, Config) ->
PrivDir = ?privdir,
Name = fname(PrivDir, inc11),
create_apps2(PrivDir),
Apps = application_controller:which_applications(),
{value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
{value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
" [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
++ StdlibVer ++ "\"},\n"
" {t11, \"1.0\"}, \n"
" {t12, \"1.0\"}, \n"
" {t13, \"1.0\"}]}.\n",
file:write_file(Name ++ ".rel", list_to_binary(Rel)),
{filename:dirname(Name), filename:basename(Name)};
create_include_files(otp_3065_circular_dependenies, Config) ->
PrivDir = ?privdir,
Name = fname(PrivDir, otp_3065_circular_dependenies),
create_apps_3065(PrivDir),
Apps = application_controller:which_applications(),
{value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
{value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
" [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
++ StdlibVer ++ "\"},\n"
" {chAts, \"1.0\"}, {aa12, \"1.0\"}, \n"
" {chTraffic, \"1.0\"}]}.\n",
file:write_file(Name ++ ".rel", list_to_binary(Rel)),
{filename:dirname(Name), filename:basename(Name)};
create_include_files(sort_apps, Config) ->
PrivDir = ?privdir,
Name = fname(PrivDir, sort_apps),
create_sort_apps(PrivDir),
Apps = application_controller:which_applications(),
{value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
{value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
" [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
++ StdlibVer ++ "\"},\n"
" {t14, \"1.0\"}, \n"
" {t20, \"1.0\"}, \n"
" {t19, \"1.0\"}, \n"
" {t18, \"1.0\"}, \n"
" {t17, \"1.0\"}, \n"
" {t16, \"1.0\"}, \n"
" {t15, \"1.0\"}]}.\n",
file:write_file(Name ++ ".rel", list_to_binary(Rel)),
{filename:dirname(Name), filename:basename(Name)};
create_include_files(sort_apps_rev, Config) ->
PrivDir = ?privdir,
Name = fname(PrivDir, sort_apps_rev),
create_sort_apps(PrivDir),
Apps = application_controller:which_applications(),
{value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
{value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
" [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
++ StdlibVer ++ "\"},\n"
" {t14, \"1.0\"}, \n"
" {t18, \"1.0\"}, \n"
" {t19, \"1.0\"}, \n"
" {t20, \"1.0\"}, \n"
" {t15, \"1.0\"}, \n"
" {t16, \"1.0\"}, \n"
" {t17, \"1.0\"}]}.\n",
file:write_file(Name ++ ".rel", list_to_binary(Rel)),
{filename:dirname(Name), filename:basename(Name)}.
create_apps(Dir) ->
T1 = "{application, t1,\n"
" [{vsn, \"1.0\"},\n"
" {description, \"test\"},\n"
" {modules, []},\n"
" {applications, [kernel, stdlib]},\n"
" {registered, []}]}.\n",
file:write_file(fname(Dir, 't1.app'), list_to_binary(T1)),
T2 = "{application, t2,\n"
" [{vsn, \"1.0\"},\n"
" {description, \"test\"},\n"
" {modules, []},\n"
" {applications, [t1]},\n"
" {registered, []}]}.\n",
file:write_file(fname(Dir, 't2.app'), list_to_binary(T2)),
T3 = "{application, t3,\n"
" [{vsn, \"1.0\"},\n"
" {description, \"test\"},\n"
" {modules, []},\n"
" {applications, []},\n"
" {included_applications, [t2]},\n"
" {registered, []}]}.\n",
file:write_file(fname(Dir, 't3.app'), list_to_binary(T3)),
T4 = "{application, t4,\n"
" [{vsn, \"1.0\"},\n"
" {description, \"test\"},\n"
" {modules, []},\n"
" {applications, [t3]},\n"
" {included_applications, []},\n"
" {registered, []}]}.\n",
file:write_file(fname(Dir, 't4.app'), list_to_binary(T4)),
T5 = "{application, t5,\n"
" [{vsn, \"1.0\"},\n"
" {description, \"test\"},\n"
" {modules, []},\n"
" {applications, [t3]},\n"
" {included_applications, []},\n"
" {registered, []}]}.\n",
file:write_file(fname(Dir, 't5.app'), list_to_binary(T5)),
T6 = "{application, t6,\n"
" [{vsn, \"1.0\"},\n"
" {description, \"test\"},\n"
" {modules, []},\n"
" {applications, []},\n"
" {included_applications, [t4, t5]},\n"
" {registered, []}]}.\n",
file:write_file(fname(Dir, 't6.app'), list_to_binary(T6)).
create_app(t7, Dir) ->
T7 = "{application, t7,\n"
" [{vsn, \"1.0\"},\n"
" {description, \"test\"},\n"
" {modules, []},\n"
" {applications, []},\n"
" {included_applications, [t5]},\n"
" {registered, []}]}.\n",
file:write_file(fname(Dir, 't7.app'), list_to_binary(T7)).
create_circular_apps(Dir) ->
T8 = "{application, t8,\n"
" [{vsn, \"1.0\"},\n"
" {description, \"test\"},\n"
" {modules, []},\n"
" {applications, [t9]},\n"
" {included_applications, []},\n"
" {registered, []}]}.\n",
file:write_file(fname(Dir, 't8.app'), list_to_binary(T8)),
T9 = "{application, t9,\n"
" [{vsn, \"1.0\"},\n"
" {description, \"test\"},\n"
" {modules, []},\n"
" {applications, [t10]},\n"
" {included_applications, []},\n"
" {registered, []}]}.\n",
file:write_file(fname(Dir, 't9.app'), list_to_binary(T9)),
T10 = "{application, t10,\n"
" [{vsn, \"1.0\"},\n"
" {description, \"test\"},\n"
" {modules, []},\n"
" {applications, []},\n"
" {included_applications, [t8, t9]},\n"
" {registered, []}]}.\n",
file:write_file(fname(Dir, 't10.app'), list_to_binary(T10)).
create_apps2(Dir) ->
T11 = "{application, t11,\n"
" [{vsn, \"1.0\"},\n"
" {description, \"test\"},\n"
" {modules, []},\n"
" {applications, []},\n"
" {included_applications, [t13]},\n"
" {registered, []}]}.\n",
file:write_file(fname(Dir, 't11.app'), list_to_binary(T11)),
T12 = "{application, t12,\n"
" [{vsn, \"1.0\"},\n"
" {description, \"test\"},\n"
" {modules, []},\n"
" {applications, [t11]},\n"
" {registered, []}]}.\n",
file:write_file(fname(Dir, 't12.app'), list_to_binary(T12)),
T13 = "{application, t13,\n"
" [{vsn, \"1.0\"},\n"
" {description, \"test\"},\n"
" {modules, []},\n"
" {applications, []},\n"
" {included_applications, []},\n"
" {registered, []}]}.\n",
file:write_file(fname(Dir, 't13.app'), list_to_binary(T13)).
create_apps_3065(Dir) ->
T11 = "{application, chTraffic,\n"
" [{vsn, \"1.0\"},\n"
" {description, \"test\"},\n"
" {modules, []},\n"
" {applications, []},\n"
" {included_applications, [chAts]},\n"
" {registered, []}]}.\n",
file:write_file(fname(Dir, 'chTraffic.app'), list_to_binary(T11)),
T12 = "{application, chAts,\n"
" [{vsn, \"1.0\"},\n"
" {description, \"test\"},\n"
" {modules, []},\n"
" {applications, []},\n"
" {included_applications, [aa12]},\n"
" {registered, []}]}.\n",
file:write_file(fname(Dir, 'chAts.app'), list_to_binary(T12)),
T13 = "{application, aa12,\n"
" [{vsn, \"1.0\"},\n"
" {description, \"test\"},\n"
" {modules, []},\n"
" {applications, [chAts]},\n"
" {included_applications, []},\n"
" {registered, []}]}.\n",
file:write_file(fname(Dir, 'aa12.app'), list_to_binary(T13)).
create_sort_apps(Dir) ->
T14 = "{application, t14,\n"
" [{vsn, \"1.0\"},\n"
" {description, \"test\"},\n"
" {modules, []},\n"
" {applications, [t18,t20,t19]},\n"
" {included_applications, [t15,t17,t16]},\n"
" {registered, []}]}.\n",
file:write_file(fname(Dir, 't14.app'), list_to_binary(T14)),
T15 = "{application, t15,\n"
" [{vsn, \"1.0\"},\n"
" {description, \"test\"},\n"
" {modules, []},\n"
" {applications, []},\n"
" {included_applications, []},\n"
" {registered, []}]}.\n",
file:write_file(fname(Dir, 't15.app'), list_to_binary(T15)),
T16 = "{application, t16,\n"
" [{vsn, \"1.0\"},\n"
" {description, \"test\"},\n"
" {modules, []},\n"
" {applications, []},\n"
" {included_applications, []},\n"
" {registered, []}]}.\n",
file:write_file(fname(Dir, 't16.app'), list_to_binary(T16)),
T17 = "{application, t17,\n"
" [{vsn, \"1.0\"},\n"
" {description, \"test\"},\n"
" {modules, []},\n"
" {applications, []},\n"
" {included_applications, []},\n"
" {registered, []}]}.\n",
file:write_file(fname(Dir, 't17.app'), list_to_binary(T17)),
T18 = "{application, t18,\n"
" [{vsn, \"1.0\"},\n"
" {description, \"test\"},\n"
" {modules, []},\n"
" {applications, []},\n"
" {included_applications, []},\n"
" {registered, []}]}.\n",
file:write_file(fname(Dir, 't18.app'), list_to_binary(T18)),
T19 = "{application, t19,\n"
" [{vsn, \"1.0\"},\n"
" {description, \"test\"},\n"
" {modules, []},\n"
" {applications, []},\n"
" {included_applications, []},\n"
" {registered, []}]}.\n",
file:write_file(fname(Dir, 't19.app'), list_to_binary(T19)),
T20 = "{application, t20,\n"
" [{vsn, \"1.0\"},\n"
" {description, \"test\"},\n"
" {modules, []},\n"
" {applications, []},\n"
" {included_applications, []},\n"
" {registered, []}]}.\n",
file:write_file(fname(Dir, 't20.app'), list_to_binary(T20)).
fname(N) ->
filename:join(N).
fname(Dir, Basename) ->
filename:join(Dir, Basename).