1: %% -*- coding: utf-8 -*- 2: %% 3: %% %CopyrightBegin% 4: %% 5: %% Copyright Ericsson AB 2009-2013. All Rights Reserved. 6: %% 7: %% The contents of this file are subject to the Erlang Public License, 8: %% Version 1.1, (the "License"); you may not use this file except in 9: %% compliance with the License. You should have received a copy of the 10: %% Erlang Public License along with this software. If not, it can be 11: %% retrieved online at http://www.erlang.org/. 12: %% 13: %% Software distributed under the License is distributed on an "AS IS" 14: %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 15: %% the License for the specific language governing rights and limitations 16: %% under the License. 17: %% 18: %% %CopyrightEnd% 19: 20: -module(reltool_server_SUITE). 21: 22: -export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, 23: init_per_suite/1, end_per_suite/1, 24: init_per_testcase/2, end_per_testcase/2]). 25: 26: -compile(export_all). 27: 28: -include_lib("reltool/src/reltool.hrl"). 29: -include("reltool_test_lib.hrl"). 30: -include_lib("common_test/include/ct.hrl"). 31: -include_lib("kernel/include/file.hrl"). 32: 33: -define(NODE_NAME, '__RELTOOL__TEMPORARY_TEST__NODE__'). 34: -define(WORK_DIR, "reltool_work_dir"). 35: 36: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 37: %% Initialization functions. 38: 39: init_per_suite(Config) -> 40: {ok,Cwd} = file:get_cwd(), 41: ?ignore(file:make_dir(?WORK_DIR)), 42: [{cwd,Cwd}|reltool_test_lib:init_per_suite(Config)]. 43: 44: end_per_suite(Config) -> 45: reltool_test_lib:end_per_suite(Config). 46: 47: init_per_testcase(Func,Config) -> 48: Node = full_node_name(?NODE_NAME), 49: case net_adm:ping(Node) of 50: pong -> stop_node(Node); 51: pang -> ok 52: end, 53: reltool_test_lib:init_per_testcase(Func,Config). 54: end_per_testcase(Func,Config) -> 55: ok = file:set_cwd(filename:join(?config(cwd,Config),?WORK_DIR)), 56: {ok,All} = file:list_dir("."), 57: Files = [F || F <- All, false == lists:prefix("save.",F)], 58: case ?config(tc_status,Config) of 59: ok -> 60: ok; 61: _Fail -> 62: SaveDir = "save."++atom_to_list(Func), 63: ok = file:make_dir(SaveDir), 64: save_test_result(Files,SaveDir) 65: end, 66: rm_files(Files), 67: ok = file:set_cwd(?config(cwd,Config)), 68: reltool_test_lib:end_per_testcase(Func,Config). 69: 70: 71: save_test_result(Files,DestDir) -> 72: Tar = "copy.tar", 73: ok = erl_tar:create(Tar, Files), 74: ok = erl_tar:extract(Tar, [{cwd,DestDir}]), 75: ok = file:delete(Tar), 76: ok. 77: 78: rm_files([F | Fs]) -> 79: case file:read_file_info(F) of 80: {ok,#file_info{type=directory}} -> 81: rm_dir(F); 82: {ok,_Regular} -> 83: ok = file:delete(F) 84: end, 85: rm_files(Fs); 86: rm_files([]) -> 87: ok. 88: 89: rm_dir(Dir) -> 90: {ok,Files} = file:list_dir(Dir), 91: rm_files([filename:join(Dir, F) || F <- Files]), 92: ok = file:del_dir(Dir). 93: 94: 95: 96: 97: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 98: %% SUITE specification 99: 100: suite() -> [{ct_hooks,[ts_install_cth]}]. 101: 102: all() -> 103: [start_server, 104: set_config, 105: get_config, 106: create_release, 107: create_release_sort, 108: create_script, 109: create_script_sort, 110: create_target, 111: create_target_unicode, 112: create_embedded, 113: create_standalone, 114: create_standalone_beam, 115: create_standalone_app, 116: create_standalone_app_clash, 117: create_multiple_standalone, 118: create_old_target, 119: create_slim, 120: eval_target_spec, 121: otp_9135, 122: otp_9229_dupl_mod_exclude_app, 123: otp_9229_dupl_mod_exclude_mod, 124: dupl_mod_in_app_file, 125: include_non_existing_app, 126: exclude_non_existing_app, 127: get_apps, 128: get_mod, 129: get_sys, 130: set_app_and_undo, 131: set_apps_and_undo, 132: set_apps_inlined, 133: set_sys_and_undo, 134: load_config_and_undo, 135: load_config_fail, 136: load_config_escript_path, 137: load_config_same_escript_source, 138: load_config_same_escript_beam, 139: load_config_add_escript, 140: reset_config_and_undo, 141: gen_rel_files, 142: save_config, 143: dependencies, 144: mod_incl_cond_derived, 145: use_selected_vsn, 146: use_selected_vsn_relative_path, 147: non_standard_vsn_id]. 148: 149: groups() -> 150: []. 151: 152: init_per_group(_GroupName, Config) -> 153: Config. 154: 155: end_per_group(_GroupName, Config) -> 156: Config. 157: 158: 159: %% The test cases 160: 161: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 162: %% A dummy break test case which is NOT in all(), but can be run 163: %% directly from the command line with ct_run. It just does a 164: %% test_server:break()... 165: break(_Config) -> 166: test_server:break(""), 167: ok. 168: 169: 170: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 171: %% Start a server process and check that it does not crash 172: 173: start_server(_Config) -> 174: {ok, Pid} = ?msym({ok, _}, reltool:start_server([])), 175: Libs = lists:sort(erl_libs()), 176: StrippedDefault = 177: case Libs of 178: [] -> {sys, []}; 179: _ -> {sys, [{lib_dirs, Libs}]} 180: end, 181: ?m({ok, StrippedDefault}, reltool:get_config(Pid)), 182: ?m(ok, reltool:stop(Pid)), 183: ok. 184: 185: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 186: %% Start a server process and check that it does not crash 187: 188: set_config(_Config) -> 189: Libs = lists:sort(erl_libs()), 190: Default = 191: {sys, 192: [ 193: {mod_cond, all}, 194: {incl_cond, derived}, 195: {root_dir, code:root_dir()}, 196: {lib_dirs, Libs} 197: ]}, 198: {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Default}])), 199: StrippedDefault = 200: case Libs of 201: [] -> {sys, []}; 202: _ -> {sys, [{lib_dirs, Libs}]} 203: end, 204: ?m({ok, StrippedDefault}, reltool:get_config(Pid)), 205: 206: ?m(ok, reltool:stop(Pid)), 207: ok. 208: 209: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 210: %% Check that get_config returns the expected derivates and defaults 211: %% as specified 212: get_config(_Config) -> 213: 214: KVsn = latest(kernel), 215: StdVsn = latest(stdlib), 216: SaslVsn = latest(sasl), 217: 218: LibDir = code:lib_dir(), 219: KLibDir = filename:join(LibDir,"kernel-"++KVsn), 220: StdLibDir = filename:join(LibDir,"stdlib-"++StdVsn), 221: SaslLibDir = filename:join(LibDir,"sasl-"++SaslVsn), 222: 223: Sys = {sys,[{incl_cond, exclude}, 224: {app,kernel,[{incl_cond,include}]}, 225: {app,sasl,[{incl_cond,include},{vsn,SaslVsn}]}, 226: {app,stdlib,[{incl_cond,include},{lib_dir,StdLibDir}]}]}, 227: {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])), 228: ?m({ok, Sys}, reltool:get_config(Pid)), 229: ?m({ok, Sys}, reltool:get_config(Pid,false,false)), 230: 231: %% Include derived info 232: ?msym({ok,{sys,[{incl_cond, exclude}, 233: {erts,[]}, 234: {app,kernel,[{incl_cond,include},{mod,_,[]}|_]}, 235: {app,sasl,[{incl_cond,include},{vsn,SaslVsn},{mod,_,[]}|_]}, 236: {app,stdlib,[{incl_cond,include},{lib_dir,StdLibDir}, 237: {mod,_,[]}|_]}]}}, 238: reltool:get_config(Pid,false,true)), 239: 240: %% Include defaults 241: ?msym({ok,{sys,[{root_dir,_}, 242: {lib_dirs,_}, 243: {mod_cond,all}, 244: {incl_cond,exclude}, 245: {app,kernel,[{incl_cond,include},{vsn,undefined}, 246: {lib_dir,undefined}]}, 247: {app,sasl,[{incl_cond,include},{vsn,SaslVsn}, 248: {lib_dir,undefined}]}, 249: {app,stdlib,[{incl_cond,include},{vsn,undefined}, 250: {lib_dir,StdLibDir}]}, 251: {boot_rel,"start_clean"}, 252: {rel,"start_clean","1.0",[]}, 253: {rel,"start_sasl","1.0",[sasl]}, 254: {emu_name,"beam"}, 255: {relocatable,true}, 256: {profile,development}, 257: {incl_sys_filters,[".*"]}, 258: {excl_sys_filters,[]}, 259: {incl_app_filters,[".*"]}, 260: {excl_app_filters,[]}, 261: {incl_archive_filters,[".*"]}, 262: {excl_archive_filters,["^include$","^priv$"]}, 263: {archive_opts,[]}, 264: {rel_app_type,permanent}, 265: {app_file,keep}, 266: {debug_info,keep}]}}, 267: reltool:get_config(Pid,true,false)), 268: 269: %% Include both defaults and derived info 270: ?msym({ok,{sys,[{root_dir,_}, 271: {lib_dirs,_}, 272: {mod_cond,all}, 273: {incl_cond,exclude}, 274: {erts,[]}, 275: {app,kernel,[{incl_cond,include},{vsn,KVsn}, 276: {lib_dir,KLibDir},{mod,_,[]}|_]}, 277: {app,sasl,[{incl_cond,include},{vsn,SaslVsn}, 278: {lib_dir,SaslLibDir},{mod,_,[]}|_]}, 279: {app,stdlib,[{incl_cond,include},{vsn,StdVsn}, 280: {lib_dir,StdLibDir},{mod,_,[]}|_]}, 281: {boot_rel,"start_clean"}, 282: {rel,"start_clean","1.0",[]}, 283: {rel,"start_sasl","1.0",[sasl]}, 284: {emu_name,"beam"}, 285: {relocatable,true}, 286: {profile,development}, 287: {incl_sys_filters,[".*"]}, 288: {excl_sys_filters,[]}, 289: {incl_app_filters,[".*"]}, 290: {excl_app_filters,[]}, 291: {incl_archive_filters,[".*"]}, 292: {excl_archive_filters,["^include$","^priv$"]}, 293: {archive_opts,[]}, 294: {rel_app_type,permanent}, 295: {app_file,keep}, 296: {debug_info,keep}]}}, 297: reltool:get_config(Pid,true,true)), 298: 299: ?m(ok, reltool:stop(Pid)), 300: ok. 301: 302: 303: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 304: %% OTP-9135, test that app_file option can be set to all | keep | strip 305: 306: otp_9135(_Config) -> 307: Libs = lists:sort(erl_libs()), 308: StrippedDefaultSys = 309: case Libs of 310: [] -> []; 311: _ -> {lib_dirs, Libs} 312: end, 313: 314: Config1 = {sys,[{app_file, keep}]}, % this is the default 315: {ok, Pid1} = ?msym({ok, _}, reltool:start_server([{config, Config1}])), 316: ?m({ok, {sys,StrippedDefaultSys}}, reltool:get_config(Pid1)), 317: ?m(ok, reltool:stop(Pid1)), 318: 319: Config2 = {sys,[{app_file, strip}]}, 320: {ok, Pid2} = ?msym({ok, _}, reltool:start_server([{config, Config2}])), 321: ExpectedConfig2 = StrippedDefaultSys++[{app_file,strip}], 322: ?m({ok, {sys,ExpectedConfig2}}, reltool:get_config(Pid2)), 323: ?m(ok, reltool:stop(Pid2)), 324: 325: Config3 = {sys,[{app_file, all}]}, 326: {ok, Pid3} = ?msym({ok, _}, reltool:start_server([{config, Config3}])), 327: ExpectedConfig3 = StrippedDefaultSys++[{app_file,all}], 328: ?m({ok, {sys,ExpectedConfig3}}, reltool:get_config(Pid3)), 329: ?m(ok, reltool:stop(Pid3)), 330: ok. 331: 332: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 333: %% Generate releases 334: 335: create_release(_Config) -> 336: %% Configure the server 337: RelName = "Just testing...", 338: RelVsn = "1.0", 339: Config = 340: {sys, 341: [ 342: {lib_dirs, []}, 343: {boot_rel, RelName}, 344: {rel, RelName, RelVsn, [kernel, stdlib]} 345: ]}, 346: %% Generate release 347: ErtsVsn = erlang:system_info(version), 348: Apps = application:loaded_applications(), 349: {value, {_, _, KernelVsn}} = lists:keysearch(kernel, 1, Apps), 350: {value, {_, _, StdlibVsn}} = lists:keysearch(stdlib, 1, Apps), 351: Rel = {release, {RelName, RelVsn}, 352: {erts, ErtsVsn}, 353: [{kernel, KernelVsn}, {stdlib, StdlibVsn}]}, 354: ?m({ok, Rel}, reltool:get_rel([{config, Config}], RelName)), 355: ok. 356: 357: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 358: %% Generate releases and make sure order of applications specified in 359: %% 'rel' parameter is preserved and that included applications are 360: %% started before the including application. 361: %% Circular dependencies shall also be detected and cause error. 362: 363: create_release_sort(Config) -> 364: DataDir = ?config(data_dir,Config), 365: %% Configure the server 366: RelName1 = "MnesiaFirst", 367: RelName2 = "SaslFirst", 368: RelName3 = "Include-both", 369: RelName4 = "Include-only-app", 370: RelName5 = "Include-only-rel", 371: RelName6 = "Auto-add-missing-apps", 372: RelName7 = "Circular", 373: RelName8 = "Include-rel-alter-order", 374: RelName9 = "Include-none-overwrite", 375: RelName10= "Uses-order-as-rel", 376: RelName11= "Auto-add-dont-overwrite-load", 377: RelVsn = "1.0", 378: %% Application z (.app file): 379: %% includes [tools, mnesia] 380: %% uses [kernel, stdlib, sasl, inets] 381: Sys = 382: {sys, 383: [ 384: {lib_dirs, [filename:join(DataDir,"sort_apps")]}, 385: {boot_rel, RelName1}, 386: {rel, RelName1, RelVsn, [stdlib, kernel, mnesia, sasl]}, 387: {rel, RelName2, RelVsn, [stdlib, kernel, sasl, mnesia]}, 388: {rel, RelName3, RelVsn, [stdlib, kernel, {z,[tools]}, tools, mnesia]}, 389: {rel, RelName4, RelVsn, [stdlib, kernel, z, mnesia, tools]}, 390: {rel, RelName5, RelVsn, [stdlib, kernel, {sasl,[tools]}]}, 391: {rel, RelName6, RelVsn, [z]}, 392: {rel, RelName7, RelVsn, [stdlib, kernel, mnesia, y, sasl, x]}, 393: {rel, RelName8, RelVsn, [stdlib, kernel, {z,[mnesia,tools]}]}, 394: {rel, RelName9, RelVsn, [stdlib, kernel, {z,[]}]}, 395: {rel, RelName10, RelVsn, [stdlib, kernel, {z,[]}, inets, sasl]}, 396: {rel, RelName11, RelVsn, [stdlib, kernel, z, {inets, load}]}, 397: {incl_cond,exclude}, 398: {mod_cond,app}, 399: {app,kernel,[{incl_cond,include}]}, 400: {app,stdlib,[{incl_cond,include}]}, 401: {app,mnesia,[{incl_cond,include}]}, 402: {app,sasl,[{incl_cond,include}]}, 403: {app,inets,[{incl_cond,include}]}, 404: {app,x,[{incl_cond,include}]}, 405: {app,y,[{incl_cond,include}]}, 406: {app,z,[{incl_cond,include}]}, 407: {app,tools,[{mod_cond,app},{incl_cond,include}]} 408: ]}, 409: %% Generate release 410: 411: ?msym({ok, {release, {RelName1, RelVsn}, 412: {erts, _}, 413: [{kernel, _}, 414: {stdlib, _}, 415: {mnesia, _}, 416: {sasl, _}]}}, 417: reltool:get_rel([{config, Sys}], RelName1)), 418: 419: ?msym({ok, {release, {RelName2, RelVsn}, 420: {erts, _}, 421: [{kernel, _}, 422: {stdlib, _}, 423: {sasl, _}, 424: {mnesia, _}]}}, 425: reltool:get_rel([{config, Sys}], RelName2)), 426: 427: ?msym({ok, {release, {RelName3, RelVsn}, 428: {erts, _}, 429: [{kernel, _}, 430: {stdlib, _}, 431: {sasl, _}, 432: {inets, _}, 433: {tools, _}, 434: {z, _, [tools]}, 435: {mnesia, _}]}}, 436: reltool:get_rel([{config, Sys}], RelName3)), 437: 438: ?msym({ok, {release, {RelName4, RelVsn}, 439: {erts, _}, 440: [{kernel, _}, 441: {stdlib, _}, 442: {sasl, _}, 443: {inets, _}, 444: {mnesia, _}, 445: {tools, _}, 446: {z, _}]}}, 447: reltool:get_rel([{config, Sys}], RelName4)), 448: 449: ?m({error,"sasl: These applications are used by release " 450: "Include-only-rel but are missing as included_applications " 451: "in the app file: [tools]"}, 452: reltool:get_rel([{config, Sys}], RelName5)), 453: 454: ?msym({ok, {release, {RelName6, RelVsn}, 455: {erts, _}, 456: [{kernel, _}, 457: {stdlib, _}, 458: {sasl, _}, 459: {inets, _}, 460: {tools, _}, 461: {mnesia, _}, 462: {z, _}]}}, 463: reltool:get_rel([{config, Sys}], RelName6)), 464: 465: ?m({error,"Circular dependencies: [x,y]"}, 466: reltool:get_rel([{config, Sys}], RelName7)), 467: 468: ?msym({ok, {release, {RelName8, RelVsn}, 469: {erts, _}, 470: [{kernel, _}, 471: {stdlib, _}, 472: {sasl, _}, 473: {inets, _}, 474: {mnesia, _}, 475: {tools, _}, 476: {z, _, [mnesia,tools]}]}}, 477: reltool:get_rel([{config, Sys}], RelName8)), 478: 479: ?msym({ok,{release,{RelName9,RelVsn}, 480: {erts,_}, 481: [{kernel,_}, 482: {stdlib,_}, 483: {sasl, _}, 484: {inets, _}, 485: {z,_,[]}]}}, 486: reltool:get_rel([{config, Sys}], RelName9)), 487: 488: ?msym({ok,{release,{RelName10,RelVsn}, 489: {erts,_}, 490: [{kernel,_}, 491: {stdlib,_}, 492: {inets, _}, 493: {sasl, _}, 494: {z,_,[]}]}}, 495: reltool:get_rel([{config, Sys}], RelName10)), 496: 497: ?msym({ok,{release,{RelName11,RelVsn}, 498: {erts,_}, 499: [{kernel,_}, 500: {stdlib,_}, 501: {sasl, _}, 502: {inets, _, load}, 503: {tools, _}, 504: {mnesia, _}, 505: {z,_}]}}, 506: reltool:get_rel([{config, Sys}], RelName11)), 507: 508: ok. 509: 510: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 511: %% Generate boot scripts 512: 513: create_script(_Config) -> 514: %% Configure the server 515: RelName = "Just testing", 516: RelVsn = "1.0", 517: Config = 518: {sys, 519: [ 520: {lib_dirs, []}, 521: {boot_rel, RelName}, 522: {rel, RelName, RelVsn, [stdlib, kernel]} 523: ]}, 524: {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Config}])), 525: 526: %% Generate release file 527: ErtsVsn = erlang:system_info(version), 528: Apps = application:loaded_applications(), 529: {value, {_, _, KernelVsn}} = lists:keysearch(kernel, 1, Apps), 530: {value, {_, _, StdlibVsn}} = lists:keysearch(stdlib, 1, Apps), 531: Rel = {release, 532: {RelName, RelVsn}, 533: {erts, ErtsVsn}, 534: [{kernel, KernelVsn}, {stdlib, StdlibVsn}]}, 535: ?m({ok, Rel}, reltool:get_rel(Pid, RelName)), 536: ?m(ok, file:write_file(filename:join([?WORK_DIR, RelName ++ ".rel"]), 537: io_lib:format("~p.\n", [Rel]))), 538: 539: %% Generate script file 540: {ok, Cwd} = file:get_cwd(), 541: ?m(ok, file:set_cwd(?WORK_DIR)), 542: ?m(ok, systools:make_script(RelName, [])), 543: {ok, [OrigScript]} = ?msym({ok, [_]}, file:consult(RelName ++ ".script")), 544: ?m(ok, file:set_cwd(Cwd)), 545: {ok, Script} = ?msym({ok, _}, reltool:get_script(Pid, RelName)), 546: %% OrigScript2 = sort_script(OrigScript), 547: %% Script2 = sort_script(Script), 548: %% ?m(OrigScript2, Script2), 549: 550: ?m(equal, diff_script(OrigScript, Script)), 551: 552: %% Stop server 553: ?m(ok, reltool:stop(Pid)), 554: ok. 555: 556: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 557: %% Test creation of .script with different sorting of applications and 558: %% included applications. 559: %% Test that result is equal to what systools produces 560: create_script_sort(Config) -> 561: DataDir = ?config(data_dir,Config), 562: %% Configure the server 563: RelName1 = "MnesiaFirst", 564: RelName2 = "SaslFirst", 565: RelName3 = "Include-both", 566: RelName4 = "Include-only-app", 567: RelName5 = "Include-only-rel", 568: RelName6 = "Auto-add-missing-apps", 569: RelName7 = "Circular", 570: RelName8 = "Include-rel-alter-order", 571: RelName9 = "Include-none-overwrite", 572: RelName10= "Uses-order-as-rel", 573: RelVsn = "1.0", 574: LibDir = filename:join(DataDir,"sort_apps"), 575: %% Application z (.app file): 576: %% includes [tools, mnesia] 577: %% uses [kernel, stdlib, sasl, inets] 578: Sys = 579: {sys, 580: [ 581: {lib_dirs, [LibDir]}, 582: {boot_rel, RelName1}, 583: {rel, RelName1, RelVsn, [stdlib, kernel, mnesia, sasl]}, 584: {rel, RelName2, RelVsn, [stdlib, kernel, sasl, mnesia]}, 585: {rel, RelName3, RelVsn, [stdlib, kernel, {z,[tools]}, tools, mnesia]}, 586: {rel, RelName4, RelVsn, [stdlib, kernel, z, mnesia, tools]}, 587: {rel, RelName5, RelVsn, [stdlib, kernel, {sasl,[tools]}]}, 588: {rel, RelName6, RelVsn, [z]}, 589: {rel, RelName7, RelVsn, [stdlib, kernel, mnesia, y, sasl, x]}, 590: {rel, RelName8, RelVsn, [stdlib, kernel, {z,[mnesia,tools]}]}, 591: {rel, RelName9, RelVsn, [stdlib, kernel, {z,[]}]}, 592: {rel, RelName10, RelVsn, [stdlib, kernel, {z,[]}, inets, sasl]}, 593: {incl_cond,exclude}, 594: {mod_cond,app}, 595: {app,kernel,[{incl_cond,include}]}, 596: {app,stdlib,[{incl_cond,include}]}, 597: {app,mnesia,[{incl_cond,include}]}, 598: {app,sasl,[{incl_cond,include}]}, 599: {app,inets,[{incl_cond,include}]}, 600: {app,x,[{incl_cond,include}]}, 601: {app,y,[{incl_cond,include}]}, 602: {app,z,[{incl_cond,include}]}, 603: {app,tools,[{mod_cond,app},{incl_cond,include}]} 604: ]}, 605: 606: {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])), 607: 608: %% Generate release files 609: application:load(sasl), 610: application:load(inets), 611: application:load(mnesia), 612: application:load(tools), 613: {ok,KernelVsn} = application:get_key(kernel,vsn), 614: {ok,StdlibVsn} = application:get_key(stdlib,vsn), 615: {ok,SaslVsn} = application:get_key(sasl,vsn), 616: {ok,InetsVsn} = application:get_key(inets,vsn), 617: {ok,MnesiaVsn} = application:get_key(mnesia,vsn), 618: {ok,ToolsVsn} = application:get_key(tools,vsn), 619: ErtsVsn = erlang:system_info(version), 620: 621: Rel1 = {release, {RelName1,RelVsn}, {erts,ErtsVsn}, 622: [{kernel,KernelVsn}, 623: {stdlib,StdlibVsn}, 624: {mnesia,MnesiaVsn}, 625: {sasl,SaslVsn}]}, 626: FullName1 = filename:join(?WORK_DIR,RelName1), 627: ?m(ok, file:write_file(FullName1 ++ ".rel", io_lib:format("~p.\n", [Rel1]))), 628: Rel2 = {release, {RelName2,RelVsn}, {erts,ErtsVsn}, 629: [{kernel,KernelVsn}, 630: {stdlib,StdlibVsn}, 631: {sasl,SaslVsn}, 632: {mnesia,MnesiaVsn}]}, 633: FullName2 = filename:join(?WORK_DIR,RelName2), 634: ?m(ok, file:write_file(FullName2 ++ ".rel", io_lib:format("~p.\n", [Rel2]))), 635: Rel3 = {release, {RelName3,RelVsn}, {erts,ErtsVsn}, 636: [{kernel,KernelVsn}, 637: {stdlib,StdlibVsn}, 638: {z,"1.0",[tools]}, 639: {tools,ToolsVsn}, 640: {mnesia,MnesiaVsn}, 641: {sasl,SaslVsn}, 642: {inets,InetsVsn}]}, 643: FullName3 = filename:join(?WORK_DIR,RelName3), 644: ?m(ok, file:write_file(FullName3 ++ ".rel", io_lib:format("~p.\n", [Rel3]))), 645: Rel4 = {release, {RelName4,RelVsn}, {erts,ErtsVsn}, 646: [{kernel,KernelVsn}, 647: {stdlib,StdlibVsn}, 648: {z,"1.0"}, 649: {mnesia,MnesiaVsn}, 650: {tools,ToolsVsn}, 651: {sasl,SaslVsn}, 652: {inets,InetsVsn}]}, 653: FullName4 = filename:join(?WORK_DIR,RelName4), 654: ?m(ok, file:write_file(FullName4 ++ ".rel", io_lib:format("~p.\n", [Rel4]))), 655: Rel5 = {release, {RelName5,RelVsn}, {erts,ErtsVsn}, 656: [{kernel,KernelVsn}, 657: {stdlib,StdlibVsn}, 658: {sasl,SaslVsn,[tools]}, 659: {tools,ToolsVsn}]}, 660: FullName5 = filename:join(?WORK_DIR,RelName5), 661: ?m(ok, file:write_file(FullName5 ++ ".rel", io_lib:format("~p.\n", [Rel5]))), 662: Rel6 = {release, {RelName6,RelVsn}, {erts,ErtsVsn}, 663: [{kernel,KernelVsn}, 664: {stdlib,StdlibVsn}, 665: {sasl,SaslVsn}, 666: {inets,InetsVsn}, 667: {tools,ToolsVsn}, 668: {mnesia,MnesiaVsn}, 669: {z,"1.0"}]}, 670: FullName6 = filename:join(?WORK_DIR,RelName6), 671: ?m(ok, file:write_file(FullName6 ++ ".rel", io_lib:format("~p.\n", [Rel6]))), 672: Rel7 = {release, {RelName7,RelVsn}, {erts,ErtsVsn}, 673: [{kernel,KernelVsn}, 674: {stdlib,StdlibVsn}, 675: {mnesia,MnesiaVsn}, 676: {y,"1.0"}, 677: {sasl,SaslVsn}, 678: {x,"1.0"}]}, 679: FullName7 = filename:join(?WORK_DIR,RelName7), 680: ?m(ok, file:write_file(FullName7 ++ ".rel", io_lib:format("~p.\n", [Rel7]))), 681: Rel8 = {release, {RelName8,RelVsn}, {erts,ErtsVsn}, 682: [{kernel,KernelVsn}, 683: {stdlib,StdlibVsn}, 684: {z,"1.0",[mnesia,tools]}, 685: {sasl,SaslVsn}, 686: {inets,InetsVsn}, 687: {mnesia,MnesiaVsn}, 688: {tools,ToolsVsn}]}, 689: FullName8 = filename:join(?WORK_DIR,RelName8), 690: ?m(ok, file:write_file(FullName8 ++ ".rel", io_lib:format("~p.\n", [Rel8]))), 691: Rel9 = {release, {RelName9,RelVsn}, {erts,ErtsVsn}, 692: [{kernel,KernelVsn}, 693: {stdlib,StdlibVsn}, 694: {z,"1.0",[]}, 695: {sasl,SaslVsn}, 696: {inets,InetsVsn}]}, 697: FullName9 = filename:join(?WORK_DIR,RelName9), 698: ?m(ok, file:write_file(FullName9 ++ ".rel", io_lib:format("~p.\n", [Rel9]))), 699: Rel10 = {release, {RelName10,RelVsn}, {erts,ErtsVsn}, 700: [{kernel,KernelVsn}, 701: {stdlib,StdlibVsn}, 702: {z,"1.0",[]}, 703: {inets,InetsVsn}, 704: {sasl,SaslVsn}]}, 705: FullName10 = filename:join(?WORK_DIR,RelName10), 706: ?m(ok, file:write_file(FullName10 ++ ".rel", io_lib:format("~p.\n", [Rel10]))), 707: 708: %% Generate script files with systools and reltool and compare 709: ZPath = filename:join([LibDir,"*",ebin]), 710: 711: ?msym({ok,_,_}, systools_make_script(FullName1,ZPath)), 712: {ok, [SystoolsScript1]} = ?msym({ok,[_]}, file:consult(FullName1++".script")), 713: {ok, Script1} = ?msym({ok, _}, reltool:get_script(Pid, RelName1)), 714: ?m(equal, diff_script(SystoolsScript1, Script1)), 715: 716: ?msym({ok,_,_}, systools_make_script(FullName2,ZPath)), 717: {ok, [SystoolsScript2]} = ?msym({ok,[_]}, file:consult(FullName2++".script")), 718: {ok, Script2} = ?msym({ok, _}, reltool:get_script(Pid, RelName2)), 719: ?m(equal, diff_script(SystoolsScript2, Script2)), 720: 721: ?msym({ok,_,_}, systools_make_script(FullName3,ZPath)), 722: {ok, [SystoolsScript3]} = ?msym({ok,[_]}, file:consult(FullName3++".script")), 723: {ok, Script3} = ?msym({ok, _}, reltool:get_script(Pid, RelName3)), 724: ?m(equal, diff_script(SystoolsScript3, Script3)), 725: 726: ?msym({ok,_,_}, systools_make_script(FullName4,ZPath)), 727: {ok, [SystoolsScript4]} = ?msym({ok,[_]}, file:consult(FullName4++".script")), 728: {ok, Script4} = ?msym({ok, _}, reltool:get_script(Pid, RelName4)), 729: ?m(equal, diff_script(SystoolsScript4, Script4)), 730: 731: ?msym({error,_,[{error_reading,{sasl,{override_include,_}}}]}, 732: systools_make_script(FullName5,ZPath)), 733: ?m({error,"sasl: These applications are used by release " 734: "Include-only-rel but are missing as included_applications " 735: "in the app file: [tools]"}, 736: reltool:get_script(Pid, RelName5)), 737: 738: ?msym({ok,_,_}, systools_make_script(FullName6,ZPath)), 739: {ok, [SystoolsScript6]} = ?msym({ok,[_]}, file:consult(FullName6++".script")), 740: {ok, Script6} = ?msym({ok, _}, reltool:get_script(Pid, RelName6)), 741: ?m(equal, diff_script(SystoolsScript6, Script6)), 742: 743: ?msym({error,_,{circular_dependencies,_}}, 744: systools_make_script(FullName7,ZPath)), 745: ?m({error,"Circular dependencies: [x,y]"}, 746: reltool:get_script(Pid, RelName7)), 747: 748: ?msym({ok,_,_}, systools_make_script(FullName8,ZPath)), 749: {ok, [SystoolsScript8]} = ?msym({ok,[_]}, file:consult(FullName8++".script")), 750: {ok, Script8} = ?msym({ok, _}, reltool:get_script(Pid, RelName8)), 751: ?m(equal, diff_script(SystoolsScript8, Script8)), 752: 753: ?msym({ok,_,_}, systools_make_script(FullName9,ZPath)), 754: {ok, [SystoolsScript9]} = ?msym({ok,[_]}, file:consult(FullName9++".script")), 755: {ok, Script9} = ?msym({ok, _}, reltool:get_script(Pid, RelName9)), 756: ?m(equal, diff_script(SystoolsScript9, Script9)), 757: 758: ?msym({ok,_,_}, systools_make_script(FullName10,ZPath)), 759: {ok, [SystoolsScript10]} = ?msym({ok,[_]}, file:consult(FullName10++".script")), 760: {ok, Script10} = ?msym({ok, _}, reltool:get_script(Pid, RelName10)), 761: ?m(equal, diff_script(SystoolsScript10, Script10)), 762: 763: %% Stop server 764: ?m(ok, reltool:stop(Pid)), 765: ok. 766: 767: 768: systools_make_script(Name,Path) -> 769: systools:make_script(Name,[{path,[Path]},{outdir,?WORK_DIR},silent]). 770: 771: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 772: %% Generate target system 773: 774: create_target(_Config) -> 775: %% Configure the server 776: RelName1 = "Just testing", 777: RelName2 = "Just testing with SASL", 778: RelVsn = "1.0", 779: Config = 780: {sys, 781: [ 782: {root_dir, code:root_dir()}, 783: {lib_dirs, []}, 784: {boot_rel, RelName2}, 785: {rel, RelName1, RelVsn, [stdlib, kernel]}, 786: {rel, RelName2, RelVsn, [sasl, stdlib, kernel]}, 787: {app, sasl, [{incl_cond, include}]} 788: ]}, 789: 790: %% Generate target file 791: TargetDir = filename:join([?WORK_DIR, "target_development"]), 792: ?m(ok, reltool_utils:recursive_delete(TargetDir)), 793: ?m(ok, file:make_dir(TargetDir)), 794: ?log("SPEC: ~p\n", [reltool:get_target_spec([{config, Config}])]), 795: ok = ?m(ok, reltool:create_target([{config, Config}], TargetDir)), 796: 797: Erl = filename:join([TargetDir, "bin", "erl"]), 798: {ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)), 799: ?msym(ok, stop_node(Node)), 800: 801: ok. 802: 803: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 804: %% Generate target system 805: 806: create_target_unicode(Config) -> 807: DataDir = ?config(data_dir,Config), 808: 809: %% If file name translation mode is unicode, then use unicode 810: %% characters release name (which will be used as file name for 811: %% .rel, .script and .boot) 812: RelNamePrefix = 813: case file:native_name_encoding() of 814: utf8 -> 815: "Unicode test αβ"; 816: latin1 -> 817: "Unicode test" 818: end, 819: 820: %% Configure the server 821: RelName1 = RelNamePrefix, 822: RelName2 = RelNamePrefix ++ " with SASL", 823: RelVsn = "1.0", 824: Sys = 825: {sys, 826: [ 827: {root_dir, code:root_dir()}, 828: {lib_dirs, [filename:join(DataDir,"unicode")]}, 829: {app_file, all}, 830: {incl_cond,exclude}, 831: {boot_rel, RelName2}, 832: {rel, RelName1, RelVsn, [stdlib, kernel, ua]}, 833: {rel, RelName2, RelVsn, [sasl, stdlib, kernel, ua]}, 834: {app, kernel, [{incl_cond, include}]}, 835: {app, stdlib, [{incl_cond, include}]}, 836: {app, sasl, [{incl_cond, include}]}, 837: {app, ua, [{incl_cond, include}]} 838: ]}, 839: 840: %% Generate target file 841: TargetDir = filename:join([?WORK_DIR, "target_unicode"]), 842: ?m(ok, reltool_utils:recursive_delete(TargetDir)), 843: ?m(ok, file:make_dir(TargetDir)), 844: ?log("SPEC: ~p\n", [reltool:get_target_spec([{config, Sys}])]), 845: ok = ?m(ok, reltool:create_target([{config, Sys}], TargetDir)), 846: 847: %% Start a node 848: Erl = filename:join([TargetDir, "bin", "erl"]), 849: {ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)), 850: 851: 852: %% The ua application has a unicode string as description - check 853: %% that it is translated correctly. 854: wait_for_app(Node,ua,50), 855: Apps = rpc:call(Node,application,which_applications,[]), 856: ?m({ua,"Application for testing unicode in reltool - αβ","1.0"}, 857: lists:keyfind(ua,1,Apps)), 858: 859: %% Check that the release name is correct (really only 860: %% insteresting if file name translation mode is utf8) 861: [{RelName,_,_,_}] = 862: ?msym([{_,_,_,_}],rpc:call(Node,release_handler,which_releases,[])), 863: ?m(true,lists:prefix(RelNamePrefix,RelName)), 864: 865: ?msym(ok, stop_node(Node)), 866: 867: ok. 868: 869: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 870: %% Generate embedded target system 871: 872: create_embedded(_Config) -> 873: %% Configure the server 874: RelName1 = "Just testing", 875: RelName2 = "Just testing with SASL", 876: RelVsn = "1.0", 877: Config = 878: {sys, 879: [ 880: {lib_dirs, []}, 881: {profile, embedded}, 882: {boot_rel, RelName2}, 883: {rel, RelName1, RelVsn, [stdlib, kernel]}, 884: {rel, RelName2, RelVsn, [sasl, stdlib, kernel]}, 885: {app, sasl, [{incl_cond, include}]} 886: ]}, 887: 888: %% Generate target file 889: TargetDir = filename:join([?WORK_DIR, "target_embedded"]), 890: ?m(ok, reltool_utils:recursive_delete(TargetDir)), 891: ?m(ok, file:make_dir(TargetDir)), 892: ok = ?m(ok, reltool:create_target([{config, Config}], TargetDir)), 893: 894: Erl = filename:join([TargetDir, "bin", "erl"]), 895: {ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)), 896: ?msym(ok, stop_node(Node)), 897: 898: ok. 899: 900: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 901: %% Generate standalone system 902: 903: create_standalone(_Config) -> 904: %% Configure the server 905: ExDir = code:lib_dir(reltool, examples), 906: EscriptName = "display_args", 907: Escript = filename:join([ExDir, EscriptName]), 908: Config = 909: {sys, 910: [ 911: {lib_dirs, []}, 912: {escript, Escript, [{incl_cond, include}]}, 913: {profile, standalone} 914: ]}, 915: 916: %% Generate target file 917: TargetDir = filename:join([?WORK_DIR, "target_standalone"]), 918: ?m(ok, reltool_utils:recursive_delete(TargetDir)), 919: ?m(ok, file:make_dir(TargetDir)), 920: ok = ?m(ok, reltool:create_target([{config, Config}], TargetDir)), 921: 922: %% Start the target system and fetch root dir 923: BinDir = filename:join([TargetDir, "bin"]), 924: Erl = filename:join([BinDir, "erl"]), 925: {ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)), 926: RootDir = ?ignore(rpc:call(Node, code, root_dir, [])), 927: ?msym(ok, stop_node(Node)), 928: 929: %% Execute escript 930: Expected = s2b(["Root dir: ", RootDir, "\n" 931: "Script args: [\"-arg1\",\"arg2\",\"arg3\"]\n", 932: "Emuarg: [\"emuvalue\"]\n", 933: "ExitCode:0"]), 934: io:format("Expected: ~ts\n", [Expected]), 935: ?m(Expected, run(BinDir, EscriptName, "-arg1 arg2 arg3")), 936: 937: ok. 938: 939: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 940: %% Generate standalone system with inlined beam file 941: 942: create_standalone_beam(Config) -> 943: %% Read beam file 944: DataDir = ?config(data_dir,Config), 945: BeamFile = filename:join([DataDir,escript,"someapp-1.0",ebin,"mymod.beam"]), 946: {ok,BeamBin} = file:read_file(BeamFile), 947: 948: %% Create the escript 949: EscriptName = "mymod.escript", 950: Escript = filename:join(?WORK_DIR,EscriptName), 951: ok = escript:create(Escript,[shebang,{beam,BeamBin}]), 952: ok = file:change_mode(Escript,8#00744), 953: 954: %% Configure the server 955: Sys = 956: {sys, 957: [ 958: {lib_dirs, []}, 959: {escript, Escript, [{incl_cond, include}]}, 960: {profile, standalone} 961: ]}, 962: 963: %% Generate target file 964: TargetDir = filename:join([?WORK_DIR, "target_standalone_beam"]), 965: ?m(ok, reltool_utils:recursive_delete(TargetDir)), 966: ?m(ok, file:make_dir(TargetDir)), 967: ok = ?m(ok, reltool:create_target([{config, Sys}], TargetDir)), 968: 969: %% Start the target system and fetch root dir 970: BinDir = filename:join([TargetDir, "bin"]), 971: Erl = filename:join([BinDir, "erl"]), 972: {ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)), 973: RootDir = ?ignore(rpc:call(Node, code, root_dir, [])), 974: ?msym(ok, stop_node(Node)), 975: 976: %% Execute escript 977: Expected = s2b(["Module: mymod\n" 978: "Root dir: ", RootDir, "\n" 979: "Script args: [\"-arg1\",\"arg2\",\"arg3\"]\n", 980: "ExitCode:0"]), 981: io:format("Expected: ~ts\n", [Expected]), 982: ?m(Expected, run(BinDir, EscriptName, "-arg1 arg2 arg3")), 983: 984: ok. 985: 986: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 987: %% Generate standalone system with inlined archived application 988: 989: create_standalone_app(Config) -> 990: %% Create archive 991: DataDir = ?config(data_dir,Config), 992: EscriptDir = filename:join(DataDir,escript), 993: {ok,{_Archive,Bin}} = zip:create("someapp-1.0.ez",["someapp-1.0"], 994: [memory, 995: {cwd,EscriptDir}, 996: {compress,all}, 997: {uncompress,[".beam",".app"]}]), 998: 999: %% Create the escript 1000: EscriptName = "someapp.escript", 1001: Escript = filename:join(?WORK_DIR,EscriptName), 1002: ok = escript:create(Escript,[shebang, 1003: {emu_args,"-escript main mymod"}, 1004: {archive,Bin}]), 1005: ok = file:change_mode(Escript,8#00744), 1006: 1007: %% Configure the server 1008: Sys = 1009: {sys, 1010: [ 1011: {lib_dirs, []}, 1012: {escript, Escript, [{incl_cond, include}]}, 1013: {profile, standalone} 1014: ]}, 1015: 1016: %% Generate target file 1017: TargetDir = filename:join([?WORK_DIR, "target_standalone_app"]), 1018: ?m(ok, reltool_utils:recursive_delete(TargetDir)), 1019: ?m(ok, file:make_dir(TargetDir)), 1020: ok = ?m(ok, reltool:create_target([{config, Sys}], TargetDir)), 1021: 1022: %% Start the target system and fetch root dir 1023: BinDir = filename:join([TargetDir, "bin"]), 1024: Erl = filename:join([BinDir, "erl"]), 1025: {ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)), 1026: RootDir = ?ignore(rpc:call(Node, code, root_dir, [])), 1027: ?msym(ok, stop_node(Node)), 1028: 1029: %% Execute escript 1030: Expected = s2b(["Module: mymod\n" 1031: "Root dir: ", RootDir, "\n" 1032: "Script args: [\"-arg1\",\"arg2\",\"arg3\"]\n", 1033: "ExitCode:0"]), 1034: io:format("Expected: ~ts\n", [Expected]), 1035: ?m(Expected, run(BinDir, EscriptName, "-arg1 arg2 arg3")), 1036: 1037: ok. 1038: 1039: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1040: %% Generate standalone system with inlined archived application 1041: %% Check that the inlined app can not be explicitly configured 1042: 1043: create_standalone_app_clash(Config) -> 1044: %% Create archive 1045: DataDir = ?config(data_dir,Config), 1046: EscriptDir = filename:join(DataDir,escript), 1047: {ok,{_Archive,Bin}} = zip:create("someapp-1.0.ez",["someapp-1.0"], 1048: [memory, 1049: {cwd,EscriptDir}, 1050: {compress,all}, 1051: {uncompress,[".beam",".app"]}]), 1052: 1053: %% Create the escript 1054: EscriptName = "someapp.escript", 1055: Escript = filename:join(?WORK_DIR,EscriptName), 1056: ok = escript:create(Escript,[shebang, 1057: {emu_args,"-escript main mymod"}, 1058: {archive,Bin}]), 1059: ok = file:change_mode(Escript,8#00744), 1060: 1061: %% Configure the server 1062: Sys = 1063: {sys, 1064: [ 1065: {lib_dirs, []}, 1066: {escript, Escript, [{incl_cond, include}]}, 1067: {profile, standalone}, 1068: {app, someapp, [{incl_cond,include}]} 1069: ]}, 1070: 1071: ?msym({error,"someapp: Application name clash. Escript "++_}, 1072: reltool:start_server([{config,Sys}])), 1073: ok. 1074: 1075: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1076: %% Generate standalone system with multiple escripts 1077: 1078: create_multiple_standalone(Config) -> 1079: %% First escript 1080: ExDir = code:lib_dir(reltool, examples), 1081: EscriptName1 = "display_args", 1082: Escript1 = filename:join([ExDir, EscriptName1]), 1083: 1084: %% Second escript 1085: DataDir = ?config(data_dir,Config), 1086: BeamFile = filename:join([DataDir,escript,"someapp-1.0",ebin,"mymod.beam"]), 1087: {ok,BeamBin} = file:read_file(BeamFile), 1088: EscriptName2 = "mymod.escript", 1089: Escript2 = filename:join(?WORK_DIR,EscriptName2), 1090: ok = escript:create(Escript2,[shebang,{beam,BeamBin}]), 1091: ok = file:change_mode(Escript2,8#00744), 1092: 1093: %% Configure server 1094: Sys = 1095: {sys, 1096: [ 1097: {lib_dirs, []}, 1098: {escript, Escript1, [{incl_cond, include}]}, 1099: {escript, Escript2, [{incl_cond, include}]}, 1100: {profile, standalone} 1101: ]}, 1102: 1103: %% Generate target system 1104: TargetDir = filename:join([?WORK_DIR, "target_multiple_standalone"]), 1105: ?m(ok, reltool_utils:recursive_delete(TargetDir)), 1106: ?m(ok, file:make_dir(TargetDir)), 1107: ok = ?m(ok, reltool:create_target([{config,Sys}], TargetDir)), 1108: 1109: %% Start the target system and fetch root dir 1110: BinDir = filename:join([TargetDir, "bin"]), 1111: Erl = filename:join([BinDir, "erl"]), 1112: {ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)), 1113: RootDir = ?ignore(rpc:call(Node, code, root_dir, [])), 1114: ?msym(ok, stop_node(Node)), 1115: 1116: %% Execute escript1 1117: Expected1 = s2b(["Root dir: ", RootDir, "\n" 1118: "Script args: [\"-arg1\",\"arg2\",\"arg3\"]\n", 1119: "Emuarg: [\"emuvalue\"]\n", 1120: "ExitCode:0"]), 1121: io:format("Expected1: ~ts\n", [Expected1]), 1122: ?m(Expected1, run(BinDir, EscriptName1, "-arg1 arg2 arg3")), 1123: 1124: 1125: %% Execute escript2 1126: Expected2 = s2b(["Module: mymod\n" 1127: "Root dir: ", RootDir, "\n" 1128: "Script args: [\"-arg1\",\"arg2\",\"arg3\"]\n", 1129: "ExitCode:0"]), 1130: io:format("Expected2: ~ts\n", [Expected2]), 1131: ?m(Expected2, run(BinDir, EscriptName2, "-arg1 arg2 arg3")), 1132: 1133: ok. 1134: 1135: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1136: %% Generate old type of target system 1137: create_old_target(_Config) -> 1138: 1139: %% Configure the server 1140: RelName1 = "Just testing", 1141: RelName2 = "Just testing with SASL", 1142: RelVsn = "1.0", 1143: Config = 1144: {sys, 1145: [ 1146: {lib_dirs, []}, 1147: {boot_rel, RelName2}, 1148: {rel, RelName1, RelVsn, [stdlib, kernel]}, 1149: {rel, RelName2, RelVsn, [sasl, stdlib, kernel]}, 1150: {relocatable, false}, % Implies explicit old style installation 1151: {app, sasl, [{incl_cond, include}]} 1152: ]}, 1153: 1154: %% Generate target file 1155: TargetDir = filename:join([?WORK_DIR, "target_old_style"]), 1156: ?m(ok, reltool_utils:recursive_delete(TargetDir)), 1157: ?m(ok, file:make_dir(TargetDir)), 1158: ok = ?m(ok, reltool:create_target([{config, Config}], TargetDir)), 1159: 1160: ok = ?m(ok, reltool:install(RelName2, TargetDir)), 1161: 1162: Erl = filename:join([TargetDir, "bin", "erl"]), 1163: {ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)), 1164: ?msym(ok, stop_node(Node)), 1165: 1166: ok. 1167: 1168: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1169: %% Generate target system 1170: 1171: create_slim(Config) -> 1172: %% Configure the server 1173: RelName = "slim", 1174: RelVsn = "1.0", 1175: 1176: DataDir = ?config(data_dir,Config), 1177: LibDir = filename:join(DataDir,"slim"), 1178: 1179: Sys = 1180: {sys, 1181: [ 1182: {root_dir, code:root_dir()}, 1183: {lib_dirs, []}, 1184: {boot_rel, RelName}, 1185: {rel, RelName, RelVsn, [sasl, stdlib, kernel, a]}, 1186: {app, sasl, [{incl_cond, include}]}, 1187: {app, a, [{incl_cond, include}, 1188: {lib_dir,filename:join(LibDir,"a-1.0")}]}, 1189: {excl_lib,otp_root} 1190: ]}, 1191: 1192: %% Generate target file 1193: TargetDir = filename:absname(filename:join([?WORK_DIR, "target_slim"])), 1194: ?m(ok, reltool_utils:recursive_delete(TargetDir)), 1195: ?m(ok, file:make_dir(TargetDir)), 1196: ?log("SPEC: ~p\n", [reltool:get_target_spec([{config, Sys}])]), 1197: ok = ?m(ok, reltool:create_target([{config, Sys}], TargetDir)), 1198: 1199: TargetLibDir = filename:join(TargetDir,"lib"), 1200: TargetRelDir = filename:join(TargetDir,"releases"), 1201: TargetRelVsnDir = filename:join(TargetRelDir,RelVsn), 1202: 1203: {ok,["a-1.0.ez"]} = file:list_dir(TargetLibDir), 1204: 1205: RootDir = code:root_dir(), 1206: Erl = filename:join([RootDir, "bin", "erl"]), 1207: EscapedQuote = 1208: case os:type() of 1209: {win32,_} -> "\\\""; 1210: _ -> "\"" 1211: end, 1212: Args = ["-boot_var", "RELTOOL_EXT_LIB", TargetLibDir, 1213: "-boot", filename:join(TargetRelVsnDir,RelName), 1214: "-sasl", "releases_dir", EscapedQuote++TargetRelDir++EscapedQuote], 1215: {ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl, Args)), 1216: ?msym(RootDir, rpc:call(Node, code, root_dir, [])), 1217: wait_for_app(Node,sasl,50), 1218: ?msym([{RelName,RelVsn,_,permanent}], 1219: rpc:call(Node,release_handler,which_releases,[])), 1220: ?msym(ok, stop_node(Node)), 1221: 1222: ok. 1223: 1224: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1225: %% Generate target system with eval_target_spec/3 1226: 1227: eval_target_spec(_Config) -> 1228: %% Configure the server 1229: RelName1 = "Just testing", 1230: RelName2 = "Just testing with SASL", 1231: RelVsn = "1.0", 1232: Config = 1233: {sys, 1234: [ 1235: {root_dir, code:root_dir()}, 1236: {lib_dirs, []}, 1237: {boot_rel, RelName2}, 1238: {rel, RelName1, RelVsn, [stdlib, kernel]}, 1239: {rel, RelName2, RelVsn, [sasl, stdlib, kernel]}, 1240: {app, sasl, [{incl_cond, include}]} 1241: ]}, 1242: 1243: %% Generate target file 1244: TargetDir = filename:join([?WORK_DIR, "eval_target_spec"]), 1245: ?m(ok, reltool_utils:recursive_delete(TargetDir)), 1246: ?m(ok, file:make_dir(TargetDir)), 1247: {ok, Spec} = ?msym({ok,_}, reltool:get_target_spec([{config, Config}])), 1248: ok = ?m(ok, reltool:eval_target_spec(Spec, code:root_dir(), TargetDir)), 1249: 1250: Erl = filename:join([TargetDir, "bin", "erl"]), 1251: {ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)), 1252: ?msym(ok, stop_node(Node)), 1253: 1254: ok. 1255: 1256: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1257: %% OTP-9229 - handle duplicated module names, i.e. same module name 1258: %% exists in two applications. 1259: 1260: %% Include on app, exclude the other 1261: otp_9229_dupl_mod_exclude_app(Config) -> 1262: DataDir = ?config(data_dir,Config), 1263: LibDir = filename:join(DataDir,"otp_9229"), 1264: 1265: %% Configure the server 1266: ExclApp = 1267: {sys, 1268: [ 1269: {root_dir, code:root_dir()}, 1270: {lib_dirs, [LibDir]}, 1271: {incl_cond,exclude}, 1272: {app,x,[{incl_cond,include}]}, 1273: {app,y,[{incl_cond,exclude}]}, 1274: {app,kernel,[{incl_cond,include}]}, 1275: {app,stdlib,[{incl_cond,include}]}, 1276: {app,sasl,[{incl_cond,include}]} 1277: ]}, 1278: 1279: %% Generate target file 1280: TargetDir = filename:join([?WORK_DIR, "target_dupl_mod_excl_app"]), 1281: ?m(ok, reltool_utils:recursive_delete(TargetDir)), 1282: ?m(ok, file:make_dir(TargetDir)), 1283: ?log("SPEC: ~p\n", [reltool:get_target_spec([{config, ExclApp}])]), 1284: ?m({ok,["Module mylib exists in applications x and y. Using module from application x."]}, reltool:get_status([{config, ExclApp}])), 1285: ok = ?m(ok, reltool:create_target([{config, ExclApp}], TargetDir)), 1286: 1287: Erl = filename:join([TargetDir, "bin", "erl"]), 1288: {ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)), 1289: 1290: AbsTargetDir = filename:absname(TargetDir), 1291: XArchive = "x-1.0.ez", 1292: AbsXArchive = filename:join([AbsTargetDir,lib,XArchive]), 1293: XEbin = ["ebin","x-1.0",XArchive], 1294: YArchive = "y-1.0.ez", 1295: AbsYArchive = filename:join([AbsTargetDir,lib,YArchive]), 1296: 1297: ?m(true, filelib:is_file(AbsXArchive)), 1298: ?m(XEbin, mod_path(Node,x)), 1299: ?m(XEbin, mod_path(Node,mylib)), 1300: ?m(false, filelib:is_file(AbsYArchive)), 1301: ?m(non_existing, mod_path(Node,y)), 1302: 1303: ?msym(ok, stop_node(Node)), 1304: 1305: ok. 1306: 1307: %% Include both apps, but exclude common module from one app 1308: otp_9229_dupl_mod_exclude_mod(Config) -> 1309: DataDir = ?config(data_dir,Config), 1310: LibDir = filename:join(DataDir,"otp_9229"), 1311: 1312: %% Configure the server 1313: ExclMod = 1314: {sys, 1315: [ 1316: {root_dir, code:root_dir()}, 1317: {lib_dirs, [LibDir]}, 1318: {incl_cond,exclude}, 1319: {app,x,[{incl_cond,include}]}, 1320: {app,y,[{incl_cond,include},{mod, mylib,[{incl_cond,exclude}]}]}, 1321: {app,kernel,[{incl_cond,include}]}, 1322: {app,stdlib,[{incl_cond,include}]}, 1323: {app,sasl,[{incl_cond,include}]} 1324: ]}, 1325: 1326: %% Generate target file 1327: TargetDir = filename:join([?WORK_DIR, "target_dupl_mod_excl_mod"]), 1328: ?m(ok, reltool_utils:recursive_delete(TargetDir)), 1329: ?m(ok, file:make_dir(TargetDir)), 1330: ?log("SPEC: ~p\n", [reltool:get_target_spec([{config, ExclMod}])]), 1331: ?m({ok,["Module mylib exists in applications x and y. Using module from application x."]}, reltool:get_status([{config, ExclMod}])), 1332: ok = ?m(ok, reltool:create_target([{config, ExclMod}], TargetDir)), 1333: 1334: Erl = filename:join([TargetDir, "bin", "erl"]), 1335: {ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)), 1336: 1337: AbsTargetDir = filename:absname(TargetDir), 1338: XArchive = "x-1.0.ez", 1339: AbsXArchive = filename:join([AbsTargetDir,lib,XArchive]), 1340: XEbin = ["ebin","x-1.0",XArchive], 1341: YArchive = "y-1.0.ez", 1342: AbsYArchive = filename:join([AbsTargetDir,lib,YArchive]), 1343: YEbin = ["ebin","y-1.0",YArchive], 1344: 1345: ?m(true, filelib:is_file(AbsXArchive)), 1346: ?m(XEbin, mod_path(Node,x)), 1347: ?m(XEbin, mod_path(Node,mylib)), 1348: ?m(true, filelib:is_file(AbsYArchive)), 1349: ?m(YEbin, mod_path(Node,y)), 1350: 1351: %% Remove path to XEbin and check that mylib is not located in YEbin 1352: Mylib = rpc:call(Node,code,which,[mylib]), 1353: rpc:call(Node,code,del_path,[filename:dirname(Mylib)]), 1354: ?m(non_existing, mod_path(Node,mylib)), 1355: 1356: ?msym(ok, stop_node(Node)), 1357: 1358: ok. 1359: 1360: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1361: %% Test that if a module is duplicated in a .app file, then a warning 1362: %% is produced, but target can still be created. 1363: dupl_mod_in_app_file(Config) -> 1364: DataDir = ?config(data_dir,Config), 1365: LibDir = filename:join(DataDir,"dupl_mod"), 1366: 1367: %% Configure the server 1368: Sys = 1369: {sys, 1370: [ 1371: {lib_dirs, [LibDir]}, 1372: {incl_cond,exclude}, 1373: {app,a,[{incl_cond,include}]}, 1374: {app,kernel,[{incl_cond,include}]}, 1375: {app,stdlib,[{incl_cond,include}]}, 1376: {app,sasl,[{incl_cond,include}]} 1377: ]}, 1378: 1379: %% Generate target file 1380: TargetDir = filename:join([?WORK_DIR, "target_dupl_mod_in_app_file"]), 1381: ?m(ok, reltool_utils:recursive_delete(TargetDir)), 1382: ?m(ok, file:make_dir(TargetDir)), 1383: ?log("SPEC: ~p\n", [reltool:get_target_spec([{config, Sys}])]), 1384: ?m({ok,["Module a duplicated in app file for application a."]}, 1385: reltool:get_status([{config, Sys}])), 1386: 1387: %%! test that only one module installed (in spec) 1388: 1389: ok. 1390: 1391: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1392: %% Test that a reasonable error message is returned if an application 1393: %% is missing 1394: include_non_existing_app(_Config) -> 1395: %% Configure the server 1396: Sys = 1397: {sys, 1398: [ 1399: {incl_cond,exclude}, 1400: {app,foobar,[{incl_cond,include}]}, 1401: {app,kernel,[{incl_cond,include}]}, 1402: {app,stdlib,[{incl_cond,include}]}, 1403: {app,sasl,[{incl_cond,include}]} 1404: ]}, 1405: 1406: %% Generate target file 1407: TargetDir = filename:join([?WORK_DIR, "target_include_non_existing_app"]), 1408: ?m(ok, reltool_utils:recursive_delete(TargetDir)), 1409: ?m(ok, file:make_dir(TargetDir)), 1410: ?log("SPEC: ~p\n", [reltool:get_target_spec([{config, Sys}])]), 1411: ?m({error,"foobar: Missing application directory."}, 1412: reltool:get_status([{config, Sys}])), 1413: 1414: ok. 1415: 1416: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1417: %% Test that if a missing application is explicitly excluded a warning 1418: %% should be issued. 1419: exclude_non_existing_app(_Config) -> 1420: %% Configure the server 1421: Sys = 1422: {sys, 1423: [ 1424: {incl_cond,exclude}, 1425: {app,foobar,[{incl_cond,exclude}]}, 1426: {app,kernel,[{incl_cond,include}]}, 1427: {app,stdlib,[{incl_cond,include}]}, 1428: {app,sasl,[{incl_cond,include}]} 1429: ]}, 1430: 1431: %% Generate target file 1432: TargetDir = filename:join([?WORK_DIR, "target_exclude_non_existing_app"]), 1433: ?m(ok, reltool_utils:recursive_delete(TargetDir)), 1434: ?m(ok, file:make_dir(TargetDir)), 1435: ?log("SPEC: ~p\n", [reltool:get_target_spec([{config, Sys}])]), 1436: ?m({ok,["foobar: Missing application directory."]}, 1437: reltool:get_status([{config, Sys}])), 1438: 1439: ok. 1440: 1441: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1442: %% Test the interface used by the GUI: 1443: %% get_app 1444: %% get_apps 1445: %% set_app 1446: %% set_apps 1447: %% load_config 1448: %% reset_config 1449: %% 1450: %% Also, for each operation which manipulates the config, test 1451: %% get_status and undo_config. 1452: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1453: get_apps(_Config) -> 1454: Sys = {sys,[{app,kernel,[{incl_cond,include}]}, 1455: {app,sasl,[{incl_cond,include}]}, 1456: {app,stdlib,[{incl_cond,include}]}, 1457: {app,tools,[{incl_cond,derived}]}, 1458: {app,runtime_tools,[{incl_cond,exclude}]}]}, 1459: {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])), 1460: 1461: {ok,Sasl} = ?msym({ok,#app{name=sasl}}, reltool_server:get_app(Pid,sasl)), 1462: {ok,[#app{name=kernel}, 1463: #app{name=sasl}=Sasl, 1464: #app{name=stdlib}] = White} = 1465: ?msym({ok,_}, reltool_server:get_apps(Pid,whitelist)), 1466: {ok,[#app{name=runtime_tools}] = Black} = 1467: ?msym({ok,_}, reltool_server:get_apps(Pid,blacklist)), 1468: 1469: {ok,Derived} = ?msym({ok,_}, reltool_server:get_apps(Pid,derived)), 1470: true = lists:keymember(tools,#app.name,Derived), 1471: 1472: {ok,Source} = ?msym({ok,_}, reltool_server:get_apps(Pid,source)), 1473: true = lists:keymember(common_test,#app.name,Source), 1474: 1475: %% Check that the four lists are disjoint 1476: Number = length(White) + length(Black) + length(Derived) + length(Source), 1477: WN = lists:usort([N || #app{name=N} <- White]), 1478: BN = lists:usort([N || #app{name=N} <- Black]), 1479: DN = lists:usort([N || #app{name=N} <- Derived]), 1480: SN = lists:usort([N || #app{name=N} <- Source]), 1481: AllN = lists:umerge([WN,BN,DN,SN]), 1482: ?m(Number,length(AllN)), 1483: 1484: ?m(ok, reltool:stop(Pid)), 1485: ok. 1486: 1487: 1488: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1489: get_mod(_Config) -> 1490: Sys = {sys,[{app,kernel,[{incl_cond,include}]}, 1491: {app,sasl,[{incl_cond,include}]}, 1492: {app,stdlib,[{incl_cond,include}]}, 1493: {app,tools,[{incl_cond,derived}]}, 1494: {app,runtime_tools,[{incl_cond,exclude}]}]}, 1495: {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])), 1496: 1497: %% Read app and get a module from the #app record 1498: {ok,Tools} = ?msym({ok,#app{name=tools}}, reltool_server:get_app(Pid,tools)), 1499: Cover = lists:keyfind(cover,#mod.name,Tools#app.mods), 1500: 1501: %% get_mod - and check that it is equal to the one in #app.mods 1502: ?m({ok,Cover}, reltool_server:get_mod(Pid,cover)), 1503: 1504: ?m(ok, reltool:stop(Pid)), 1505: ok. 1506: 1507: 1508: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1509: get_sys(_Config) -> 1510: Sys = {sys,[{app,kernel,[{incl_cond,include}]}, 1511: {app,sasl,[{incl_cond,include}]}, 1512: {app,stdlib,[{incl_cond,include}]}, 1513: {app,tools,[{incl_cond,derived}]}, 1514: {app,runtime_tools,[{incl_cond,exclude}]}]}, 1515: {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])), 1516: 1517: RootDir = code:root_dir(), 1518: ?msym({ok,#sys{root_dir=RootDir,apps=undefined}},reltool_server:get_sys(Pid)), 1519: 1520: ?m(ok, reltool:stop(Pid)), 1521: ok. 1522: 1523: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1524: set_app_and_undo(Config) -> 1525: Sys = {sys,[{lib_dirs,[filename:join(datadir(Config),"faulty_app_file")]}, 1526: {incl_cond, exclude}, 1527: {app,a,[{incl_cond,include}]}, 1528: {app,kernel,[{incl_cond,include}]}, 1529: {app,sasl,[{incl_cond,include}]}, 1530: {app,stdlib,[{incl_cond,include}]}, 1531: {app,tools,[{incl_cond,include}]}]}, 1532: {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])), 1533: ?m({ok, Sys}, reltool:get_config(Pid)), 1534: ?msym({ok,["a: Cannot parse app file"++_]},reltool_server:get_status(Pid)), 1535: 1536: %% Get app and mod 1537: {ok,Tools} = ?msym({ok,_}, reltool_server:get_app(Pid,tools)), 1538: {ok,Cover} = ?msym({ok,#mod{name=cover, is_included=true}}, 1539: reltool_server:get_mod(Pid,cover)), 1540: 1541: %% Exclude one module with set_app 1542: ExclCover = Cover#mod{incl_cond=exclude}, 1543: Mods = Tools#app.mods, 1544: Tools1 = Tools#app{mods = lists:keyreplace(cover,#mod.name,Mods,ExclCover)}, 1545: {ok,ToolsNoCover,["a: Cannot parse app file"++_|_]} = 1546: ?msym({ok,_,["a: Cannot parse app file"++_|_]}, 1547: reltool_server:set_app(Pid,Tools1)), 1548: ?msym({ok,["a: Cannot parse app file"++_]}, reltool_server:get_status(Pid)), 1549: 1550: %% Check that the module is no longer included 1551: ?m({ok,ToolsNoCover}, reltool_server:get_app(Pid,tools)), 1552: {ok,NoIncludeCover} = ?msym({ok,#mod{name=cover, is_included=false}}, 1553: reltool_server:get_mod(Pid,cover)), 1554: 1555: %% Undo 1556: ?m(ok, reltool_server:undo_config(Pid)), 1557: ?m({ok,Tools}, reltool_server:get_app(Pid,tools)), 1558: ?m({ok,Cover}, reltool_server:get_mod(Pid,cover)), 1559: ?msym({ok,["a: Cannot parse app file"++_]}, reltool_server:get_status(Pid)), 1560: 1561: %% Undo again, to check that it toggles 1562: ?msym(ok, reltool_server:undo_config(Pid)), 1563: ?m({ok,ToolsNoCover}, reltool_server:get_app(Pid,tools)), 1564: ?m({ok,NoIncludeCover}, reltool_server:get_mod(Pid,cover)), 1565: ?msym({ok,["a: Cannot parse app file"++_]}, reltool_server:get_status(Pid)), 1566: 1567: ?m(ok, reltool:stop(Pid)), 1568: ok. 1569: 1570: 1571: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1572: set_apps_and_undo(Config) -> 1573: Sys = {sys,[{lib_dirs,[filename:join(datadir(Config),"faulty_app_file")]}, 1574: {incl_cond, exclude}, 1575: {app,kernel,[{incl_cond,include}]}, 1576: {app,sasl,[{incl_cond,include}]}, 1577: {app,stdlib,[{incl_cond,include}]}, 1578: {app,tools,[{incl_cond,include}]}]}, 1579: {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])), 1580: ?m({ok, Sys}, reltool:get_config(Pid)), 1581: ?msym({ok,["a: Cannot parse app file"++_]},reltool_server:get_status(Pid)), 1582: 1583: %% Get app and mod 1584: {ok,Tools} = ?msym({ok,_}, reltool_server:get_app(Pid,tools)), 1585: ?m(true, Tools#app.is_pre_included), 1586: ?m(true, Tools#app.is_included), 1587: {ok,Cover} = ?msym({ok,#mod{name=cover, is_included=true}}, 1588: reltool_server:get_mod(Pid,cover)), 1589: 1590: %% Exclude one application with set_apps 1591: ExclTools = Tools#app{incl_cond=exclude}, 1592: ?msym({ok,["a: Cannot parse app file"++_]}, 1593: reltool_server:set_apps(Pid,[ExclTools])), 1594: ?msym({ok,["a: Cannot parse app file"++_]}, reltool_server:get_status(Pid)), 1595: 1596: %% Check that the app and its modules (one of them) are no longer included 1597: {ok,NoTools} = ?msym({ok,_}, reltool_server:get_app(Pid,tools)), 1598: ?m(false, NoTools#app.is_pre_included), 1599: ?m(false, NoTools#app.is_included), 1600: {ok,NoIncludeCover} = ?msym({ok,#mod{name=cover, is_included=false}}, 1601: reltool_server:get_mod(Pid,cover)), 1602: 1603: %% Undo 1604: ?m(ok, reltool_server:undo_config(Pid)), 1605: ?m({ok,Tools}, reltool_server:get_app(Pid,tools)), 1606: ?m({ok,Cover}, reltool_server:get_mod(Pid,cover)), 1607: ?msym({ok,["a: Cannot parse app file"++_]},reltool_server:get_status(Pid)), 1608: 1609: %% Undo again, to check that it toggles 1610: ?m(ok, reltool_server:undo_config(Pid)), 1611: ?m({ok,NoTools}, reltool_server:get_app(Pid,tools)), 1612: ?m({ok,NoIncludeCover}, reltool_server:get_mod(Pid,cover)), 1613: ?msym({ok,["a: Cannot parse app file"++_]}, reltool_server:get_status(Pid)), 1614: 1615: ?m(ok, reltool:stop(Pid)), 1616: ok. 1617: 1618: 1619: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1620: %% Test that escript can be configured, but not its inlined applications 1621: set_apps_inlined(Config) -> 1622: %% Create archive 1623: DataDir = ?config(data_dir,Config), 1624: EscriptDir = filename:join(DataDir,escript), 1625: {ok,{_Archive,Bin}} = zip:create("someapp-1.0.ez",["someapp-1.0"], 1626: [memory, 1627: {cwd,EscriptDir}, 1628: {compress,all}, 1629: {uncompress,[".beam",".app"]}]), 1630: 1631: %% Create the escript 1632: EscriptName = "someapp.escript", 1633: Escript = filename:join(?WORK_DIR,EscriptName), 1634: ok = escript:create(Escript,[shebang, 1635: {emu_args,"-escript main mymod"}, 1636: {archive,Bin}]), 1637: ok = file:change_mode(Escript,8#00744), 1638: 1639: %% Configure the server 1640: Sys = {sys,[{incl_cond, exclude}, 1641: {escript,Escript,[]}, 1642: {app,kernel,[{incl_cond,include}]}, 1643: {app,sasl,[{incl_cond,include}]}, 1644: {app,stdlib,[{incl_cond,include}]}]}, 1645: {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])), 1646: ?msym({ok,[]},reltool_server:get_status(Pid)), 1647: 1648: %% Get app and mod 1649: {ok,EApp} = ?msym({ok,_}, reltool_server:get_app(Pid,'*escript* someapp')), 1650: {ok,Someapp} = ?msym({ok,_}, reltool_server:get_app(Pid,someapp)), 1651: ?m(undefined, EApp#app.incl_cond), 1652: ?m(undefined, Someapp#app.incl_cond), 1653: ?m(false, Someapp#app.is_included), 1654: ?m(false, Someapp#app.is_pre_included), 1655: 1656: %% Include escript 1657: EApp1 = EApp#app{incl_cond=include}, 1658: ?m({ok,[]}, reltool_server:set_apps(Pid,[EApp1])), 1659: ExpectedEApp = EApp1#app{is_included=true,is_pre_included=true}, 1660: ?m({ok,ExpectedEApp}, reltool_server:get_app(Pid,'*escript* someapp')), 1661: {ok,Someapp1} = ?msym({ok,_}, reltool_server:get_app(Pid,someapp)), 1662: ?m(include, Someapp1#app.incl_cond), 1663: ?m(true, Someapp1#app.is_included), 1664: ?m(true, Someapp1#app.is_pre_included), 1665: 1666: %% Check that inlined app can not be configured 1667: Someapp2 = Someapp1#app{incl_cond=exclude}, 1668: ?msym({error, 1669: "Application someapp is inlined in '*escript* someapp'. " 1670: "Can not change configuration for an inlined application."}, 1671: reltool_server:set_apps(Pid,[Someapp2])), 1672: ?m({ok,Someapp1}, reltool_server:get_app(Pid,someapp)), 1673: 1674: %% Exclude escript 1675: {ok,EApp2} = ?msym({ok,_}, reltool_server:get_app(Pid,'*escript* someapp')), 1676: EApp3 = EApp2#app{incl_cond=exclude}, 1677: ?m({ok,[]}, reltool_server:set_apps(Pid,[EApp3])), 1678: ExpectedEApp3 = EApp3#app{is_included=false,is_pre_included=false}, 1679: ?m({ok,ExpectedEApp3}, reltool_server:get_app(Pid,'*escript* someapp')), 1680: {ok,Someapp3} = ?msym({ok,_}, reltool_server:get_app(Pid,someapp)), 1681: ?m(exclude, Someapp3#app.incl_cond), 1682: ?m(false, Someapp3#app.is_included), 1683: ?m(false, Someapp3#app.is_pre_included), 1684: 1685: ?m(ok, reltool:stop(Pid)), 1686: ok. 1687: 1688: 1689: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1690: set_sys_and_undo(Config) -> 1691: Sys1 = {sys,[{incl_cond, exclude}, 1692: {app,kernel,[{incl_cond,include}]}, 1693: {app,sasl,[{incl_cond,include}]}, 1694: {app,stdlib,[{incl_cond,include}]}, 1695: {app,tools,[{incl_cond,include}]}]}, 1696: {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys1}])), 1697: ?m({ok,[]}, reltool_server:get_status(Pid)), 1698: 1699: %% Read sys record 1700: {ok, SysRec} = reltool_server:get_sys(Pid), 1701: 1702: %% Set lib dirs by call to set_sys 1703: NewLib = filename:join(datadir(Config),"faulty_app_file"), 1704: NewLibDirs = [NewLib | SysRec#sys.lib_dirs], 1705: NewSysRec = SysRec#sys{lib_dirs=NewLibDirs}, 1706: ?msym({ok,["a: Cannot parse app file"++_]}, 1707: reltool_server:set_sys(Pid, NewSysRec)), 1708: ?m({ok,NewSysRec}, reltool_server:get_sys(Pid)), 1709: ?msym({ok,["a: Cannot parse app file"++_]},reltool_server:get_status(Pid)), 1710: 1711: %% Undo 1712: ?m(ok, reltool_server:undo_config(Pid)), 1713: ?m({ok,SysRec}, reltool_server:get_sys(Pid)), 1714: ?m({ok,[]}, reltool_server:get_status(Pid)), 1715: 1716: %% Undo again, to check that it toggles 1717: ?m(ok,reltool_server:undo_config(Pid)), 1718: ?m({ok,NewSysRec}, reltool_server:get_sys(Pid)), 1719: ?msym({ok,["a: Cannot parse app file"++_]},reltool_server:get_status(Pid)), 1720: 1721: ?m(ok, reltool:stop(Pid)), 1722: ok. 1723: 1724: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1725: load_config_and_undo(Config) -> 1726: Sys1 = {sys,[{incl_cond, exclude}, 1727: {app,kernel,[{incl_cond,include}]}, 1728: {app,sasl,[{incl_cond,include}]}, 1729: {app,stdlib,[{incl_cond,include}]}, 1730: {app,tools,[{incl_cond,include}]}]}, 1731: {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys1}])), 1732: ?m({ok, Sys1}, reltool:get_config(Pid)), 1733: ?m({ok,[]}, reltool_server:get_status(Pid)), 1734: 1735: %% Get app and mod 1736: {ok,Tools1} = ?msym({ok,_}, reltool_server:get_app(Pid,tools)), 1737: ?m(true, Tools1#app.is_pre_included), 1738: ?m(true, Tools1#app.is_included), 1739: {ok,Cover1} = ?msym({ok,#mod{name=cover, 1740: is_included=true, 1741: is_pre_included=true}}, 1742: reltool_server:get_mod(Pid,cover)), 1743: 1744: %% Change tools from include to derived by loading new config 1745: Sys2 = {sys,[{lib_dirs,[filename:join(datadir(Config),"faulty_app_file")]}, 1746: {app,a,[{incl_cond,include}]}, 1747: {app,kernel,[{incl_cond,include}]}, 1748: {app,sasl,[{incl_cond,include}]}, 1749: {app,stdlib,[{incl_cond,include}]}, 1750: {app,tools,[{incl_cond,derived}]}]}, 1751: ?msym({ok,["a: Cannot parse app file"++_]}, 1752: reltool_server:load_config(Pid,Sys2)), 1753: %%% OTP-0702, 15) ?m({ok, Sys2}, reltool:get_config(Pid)), 1754: %%% Note that {incl_cond,exclude} is removed compared to Sys1 - 1755: %%% config is merged, not overwritten - is this correct??? 1756: ?msym({ok,["a: Cannot parse app file"++_]},reltool_server:get_status(Pid)), 1757: 1758: %% Check that tools is included (since it is used by sasl) but not 1759: %% pre-included (neither included or excluded => undefined) 1760: {ok,Tools2} = ?msym({ok,_}, reltool_server:get_app(Pid,tools)), 1761: ?m(undefined, Tools2#app.is_pre_included), 1762: ?m(true, Tools2#app.is_included), 1763: {ok,Cover2} = ?msym({ok,#mod{name=cover, 1764: is_included=true, 1765: is_pre_included=undefined}}, 1766: reltool_server:get_mod(Pid,cover)), 1767: 1768: %% Undo 1769: ?m(ok, reltool_server:undo_config(Pid)), 1770: ?m({ok,Tools1}, reltool_server:get_app(Pid,tools)), 1771: ?m({ok,Cover1}, reltool_server:get_mod(Pid,cover)), 1772: ?m({ok,[]}, reltool_server:get_status(Pid)), 1773: 1774: %% Undo again, to check that it toggles 1775: ?m(ok, reltool_server:undo_config(Pid)), 1776: ?m({ok,Tools2}, reltool_server:get_app(Pid,tools)), 1777: ?m({ok,Cover2}, reltool_server:get_mod(Pid,cover)), 1778: ?msym({ok,["a: Cannot parse app file"++_]},reltool_server:get_status(Pid)), 1779: 1780: ?m(ok, reltool:stop(Pid)), 1781: ok. 1782: 1783: 1784: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1785: %% Test that load_config is properly rolled back if it fails 1786: load_config_fail(_Config) -> 1787: Sys1 = {sys,[{incl_cond, exclude}, 1788: {app,kernel,[{incl_cond,include}]}, 1789: {app,sasl,[{incl_cond,include}]}, 1790: {app,stdlib,[{incl_cond,include}]}, 1791: {app,tools,[{incl_cond,include}]}]}, 1792: {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys1}])), 1793: ?m({ok, Sys1}, reltool:get_config(Pid)), 1794: ?m({ok,[]}, reltool_server:get_status(Pid)), 1795: 1796: %% Get app and mod 1797: {ok,Tools} = ?msym({ok,_}, reltool_server:get_app(Pid,tools)), 1798: 1799: %% Try to load a config with a faulty rel statement (includes a 1800: %% non-existing application) 1801: Sys2 = {sys,[{incl_cond, exclude}, 1802: {boot_rel, "faulty_rel"}, 1803: {rel, "faulty_rel", "1.0", [kernel, sasl, stdlib, xxx]}, 1804: {app,kernel,[{incl_cond,include}]}, 1805: {app,sasl,[{incl_cond,include}]}, 1806: {app,stdlib,[{incl_cond,include}]}]}, 1807: ?msym({error,"Release \"faulty_rel\" uses non existing application xxx"}, 1808: reltool_server:load_config(Pid,Sys2)), 1809: 1810: %% Check that a rollback is done to the old configuration 1811: ?m({ok, Sys1}, reltool:get_config(Pid,false,false)), 1812: 1813: %% and that tools is not changed (i.e. that the new configuration 1814: %% is not applied) 1815: ?m({ok,Tools}, reltool_server:get_app(Pid,tools)), 1816: 1817: ?m(ok, reltool:stop(Pid)), 1818: ok. 1819: 1820: 1821: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1822: %% Load config with escript 1823: 1824: load_config_escript_path(Config) -> 1825: %% Create escript 1826: DataDir = ?config(data_dir,Config), 1827: BeamFile = filename:join([DataDir,escript,"someapp-1.0",ebin,"mymod.beam"]), 1828: {ok,BeamBin} = file:read_file(BeamFile), 1829: EscriptName = "mymod.escript", 1830: Escript = filename:join(?WORK_DIR,EscriptName), 1831: ok = escript:create(Escript,[shebang,{beam,BeamBin}]), 1832: ok = file:change_mode(Escript,8#00744), 1833: 1834: %% Start reltool_server with one escript in configuration 1835: EscriptSys = 1836: {sys, 1837: [ 1838: {lib_dirs, []}, 1839: {escript, Escript, [{incl_cond, include}]}, 1840: {profile, standalone} 1841: ]}, 1842: 1843: {ok, Pid1} = ?msym({ok, _}, reltool:start_server([{config, EscriptSys}])), 1844: {ok,[#app{name='*escript* mymod'}=A]} = 1845: ?msym({ok,[_]}, reltool_server:get_apps(Pid1,whitelist)), 1846: ?m(ok, reltool:stop(Pid1)), 1847: 1848: 1849: %% Do same again, but now start reltool first with simple config, 1850: %% then add escript by loading new configuration and check that 1851: %% #app is the same 1852: SimpleSys = 1853: {sys, 1854: [ 1855: {lib_dirs, []} 1856: ]}, 1857: 1858: {ok, Pid2} = ?msym({ok, _}, reltool:start_server([{config, SimpleSys}])), 1859: ?m({ok,[]}, reltool_server:get_apps(Pid2,whitelist)), 1860: ?m({ok,[]}, reltool_server:load_config(Pid2,EscriptSys)), 1861: ?m({ok,[A]}, reltool_server:get_apps(Pid2,whitelist)), 1862: 1863: ?m(ok, reltool:stop(Pid2)), 1864: 1865: ok. 1866: 1867: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1868: %% Load config with same (source) escript twice and check that the 1869: %% application information is not changed. 1870: 1871: load_config_same_escript_source(_Config) -> 1872: %% Create escript 1873: ExDir = code:lib_dir(reltool, examples), 1874: EscriptName = "display_args", 1875: Escript = filename:join([ExDir, EscriptName]), 1876: 1877: %% Start reltool_server with one escript in configuration 1878: Sys = 1879: {sys, 1880: [ 1881: {lib_dirs, []}, 1882: {escript, Escript, [{incl_cond, include}]}, 1883: {profile, standalone} 1884: ]}, 1885: 1886: {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])), 1887: % {ok,[#app{name='*escript* display_args'}]} = 1888: ?msym({ok,[#app{name='*escript* display_args',mods=[_]}]}, 1889: reltool_server:get_apps(Pid,whitelist)), 1890: 1891: %% Load the same config again, then check that app is not changed 1892: ?m({ok,[]}, reltool_server:load_config(Pid,Sys)), 1893: ?msym({ok,[#app{name='*escript* display_args',mods=[_]}]}, 1894: reltool_server:get_apps(Pid,whitelist)), 1895: 1896: ?m(ok, reltool:stop(Pid)), 1897: 1898: ok. 1899: 1900: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1901: %% Load config with same (beam) escript twice and check that the 1902: %% application information is not changed. 1903: 1904: load_config_same_escript_beam(Config) -> 1905: %% Create escript 1906: DataDir = ?config(data_dir,Config), 1907: BeamFile = filename:join([DataDir,escript,"someapp-1.0",ebin,"mymod.beam"]), 1908: {ok,BeamBin} = file:read_file(BeamFile), 1909: EscriptName = "mymod.escript", 1910: Escript = filename:join(?WORK_DIR,EscriptName), 1911: ok = escript:create(Escript,[shebang,{beam,BeamBin}]), 1912: ok = file:change_mode(Escript,8#00744), 1913: 1914: %% Start reltool_server with one escript in configuration 1915: Sys = 1916: {sys, 1917: [ 1918: {lib_dirs, []}, 1919: {escript, Escript, [{incl_cond, include}]}, 1920: {profile, standalone} 1921: ]}, 1922: 1923: {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])), 1924: {ok,[#app{name='*escript* mymod'}=A]} = 1925: ?msym({ok,[_]}, reltool_server:get_apps(Pid,whitelist)), 1926: 1927: %% Load the same config again, then check that app is not changed 1928: ?m({ok,[]}, reltool_server:load_config(Pid,Sys)), 1929: ?m({ok,[A]}, reltool_server:get_apps(Pid,whitelist)), 1930: 1931: ?m(ok, reltool:stop(Pid)), 1932: 1933: ok. 1934: 1935: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1936: %% Load config with escript 1937: 1938: load_config_add_escript(Config) -> 1939: %% First escript 1940: ExDir = code:lib_dir(reltool, examples), 1941: EscriptName1 = "display_args", 1942: Escript1 = filename:join([ExDir, EscriptName1]), 1943: 1944: %% Second escript 1945: DataDir = ?config(data_dir,Config), 1946: BeamFile = filename:join([DataDir,escript,"someapp-1.0",ebin,"mymod.beam"]), 1947: {ok,BeamBin} = file:read_file(BeamFile), 1948: EscriptName2 = "mymod.escript", 1949: Escript2 = filename:join(?WORK_DIR,EscriptName2), 1950: ok = escript:create(Escript2,[shebang,{beam,BeamBin}]), 1951: ok = file:change_mode(Escript2,8#00744), 1952: 1953: %% Start reltool_server with one escript in configuration 1954: Sys1 = 1955: {sys, 1956: [ 1957: {lib_dirs, []}, 1958: {escript, Escript2, [{incl_cond, include}]}, 1959: {profile, standalone} 1960: ]}, 1961: 1962: {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys1}])), 1963: 1964: %% Add second escript by loading new configuration 1965: Sys2 = 1966: {sys, 1967: [ 1968: {lib_dirs, []}, 1969: {escript, Escript1, [{incl_cond, include}]}, 1970: {escript, Escript2, [{incl_cond, include}]}, 1971: {profile, standalone} 1972: ]}, 1973: 1974: {ok,[]} = ?m({ok,[]}, reltool_server:load_config(Pid,Sys2)), 1975: {ok,[#app{name='*escript* display_args'}, 1976: #app{name='*escript* mymod'}]} = 1977: ?msym({ok,[_,_]}, reltool_server:get_apps(Pid,whitelist)), 1978: 1979: ?m(ok, reltool:stop(Pid)), 1980: 1981: ok. 1982: 1983: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1984: reset_config_and_undo(Config) -> 1985: Sys1 = {sys,[{lib_dirs,[filename:join(datadir(Config),"faulty_app_file")]}, 1986: {incl_cond, exclude}, 1987: {app,a,[{incl_cond,include}]}, 1988: {app,kernel,[{incl_cond,include}]}, 1989: {app,sasl,[{incl_cond,include}]}, 1990: {app,stdlib,[{incl_cond,include}]}, 1991: {app,tools,[{incl_cond,include}]}]}, 1992: {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys1}])), 1993: ?m({ok, Sys1}, reltool:get_config(Pid)), 1994: ?msym({ok,["a: Cannot parse app file"++_]},reltool_server:get_status(Pid)), 1995: 1996: %% Get app and mod 1997: {ok,Tools1} = ?msym({ok,_}, reltool_server:get_app(Pid,tools)), 1998: ?m(true, Tools1#app.is_pre_included), 1999: ?m(true, Tools1#app.is_included), 2000: {ok,Cover1} = ?msym({ok,#mod{name=cover, 2001: is_included=true, 2002: is_pre_included=true}}, 2003: reltool_server:get_mod(Pid,cover)), 2004: 2005: %% Exclude tools by loading new config 2006: Sys2 = {sys,[{incl_cond, exclude}, 2007: {app,kernel,[{incl_cond,include}]}, 2008: {app,sasl,[{incl_cond,include}]}, 2009: {app,stdlib,[{incl_cond,include}]}, 2010: {app,tools,[{incl_cond,exclude}]}]}, 2011: ?m({ok,[]}, reltool_server:load_config(Pid,Sys2)), 2012: ?m({ok,[]}, reltool_server:get_status(Pid)), 2013: 2014: %% Check that tools is excluded 2015: {ok,Tools2} = ?msym({ok,_}, reltool_server:get_app(Pid,tools)), 2016: ?m(false, Tools2#app.is_pre_included), 2017: ?m(false, Tools2#app.is_included), 2018: {ok,Cover2} = ?msym({ok,#mod{name=cover, 2019: is_included=false, 2020: is_pre_included=false}}, 2021: reltool_server:get_mod(Pid,cover)), 2022: 2023: %% Reset 2024: ?msym({ok,["a: Cannot parse app file"++_]},reltool_server:reset_config(Pid)), 2025: ?m({ok,Tools1}, reltool_server:get_app(Pid,tools)), 2026: ?m({ok,Cover1}, reltool_server:get_mod(Pid,cover)), 2027: ?msym({ok,["a: Cannot parse app file"++_]},reltool_server:get_status(Pid)), 2028: 2029: %% Undo 2030: ?m(ok, reltool_server:undo_config(Pid)), 2031: ?m({ok,Tools2}, reltool_server:get_app(Pid,tools)), 2032: ?m({ok,Cover2}, reltool_server:get_mod(Pid,cover)), 2033: ?m({ok,[]}, reltool_server:get_status(Pid)), 2034: 2035: %% Undo again, to check that it toggles 2036: ?m(ok, reltool_server:undo_config(Pid)), 2037: ?m({ok,Tools1}, reltool_server:get_app(Pid,tools)), 2038: ?m({ok,Cover1}, reltool_server:get_mod(Pid,cover)), 2039: ?msym({ok,["a: Cannot parse app file"++_]},reltool_server:get_status(Pid)), 2040: 2041: ?m(ok, reltool:stop(Pid)), 2042: ok. 2043: 2044: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2045: gen_rel_files(_Config) -> 2046: %% Configure the server 2047: RelName = "gen_fel_files_test", 2048: RelVsn = "1.0", 2049: Sys = 2050: {sys, 2051: [ 2052: {lib_dirs, []}, 2053: {boot_rel, RelName}, 2054: {rel, RelName, RelVsn, [kernel, stdlib]} 2055: ]}, 2056: {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])), 2057: 2058: %% Generate .rel, .script and .boot 2059: Dir = filename:join(?WORK_DIR,"gen_rel_files"), 2060: ok = file:make_dir(Dir), 2061: ?m({ok,[]}, reltool_server:gen_rel_files(Pid,Dir)), 2062: 2063: Script = RelName ++ ".script", 2064: Rel = RelName ++ ".rel", 2065: Boot = RelName ++ ".boot", 2066: {ok,Files} = ?msym({ok,_}, file:list_dir(Dir)), 2067: [Boot,Rel,Script] = lists:sort(Files), 2068: 2069: %% Check that contents is reasonable 2070: {ok,[S]} = ?msym({ok,[{script,_,_}]},file:consult(filename:join(Dir,Script))), 2071: ?msym({ok,[{release,_,_,_}]}, file:consult(filename:join(Dir,Rel))), 2072: {ok,Bin} = ?msym({ok,_}, file:read_file(filename:join(Dir,Boot))), 2073: ?m(S,binary_to_term(Bin)), 2074: 2075: ?m(ok, reltool:stop(Pid)), 2076: ok. 2077: 2078: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2079: save_config(Config) -> 2080: PrivDir = ?config(priv_dir,Config), 2081: Sys = {sys,[{incl_cond, exclude}, 2082: {app,kernel,[{incl_cond,include}]}, 2083: {app,sasl,[{incl_cond,include}]}, 2084: {app,stdlib,[{incl_cond,include}]}]}, 2085: {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])), 2086: ?m({ok, Sys}, reltool:get_config(Pid)), 2087: 2088: Simple = filename:join(PrivDir,"save_simple.reltool"), 2089: ?m(ok, reltool_server:save_config(Pid,Simple,false,false)), 2090: ?m({ok,[Sys]}, file:consult(Simple)), 2091: 2092: Derivates = filename:join(PrivDir,"save_derivates.reltool"), 2093: ?m(ok, reltool_server:save_config(Pid,Derivates,false,true)), 2094: ?msym({ok,[{sys,[{incl_cond, exclude}, 2095: {erts,[]}, 2096: {app,kernel,[{incl_cond,include},{mod,_,[]}|_]}, 2097: {app,sasl,[{incl_cond,include},{mod,_,[]}|_]}, 2098: {app,stdlib,[{incl_cond,include},{mod,_,[]}|_]}]}]}, 2099: file:consult(Derivates)), 2100: 2101: Defaults = filename:join(PrivDir,"save_defaults.reltool"), 2102: ?m(ok, reltool_server:save_config(Pid,Defaults,true,false)), 2103: ?msym({ok,[{sys,[{root_dir,_}, 2104: {lib_dirs,_}, 2105: {mod_cond,all}, 2106: {incl_cond,exclude}, 2107: {app,kernel,[{incl_cond,include},{vsn,undefined}, 2108: {lib_dir,undefined}]}, 2109: {app,sasl,[{incl_cond,include},{vsn,undefined}, 2110: {lib_dir,undefined}]}, 2111: {app,stdlib,[{incl_cond,include},{vsn,undefined}, 2112: {lib_dir,undefined}]}, 2113: {boot_rel,"start_clean"}, 2114: {rel,"start_clean","1.0",[]}, 2115: {rel,"start_sasl","1.0",[sasl]}, 2116: {emu_name,"beam"}, 2117: {relocatable,true}, 2118: {profile,development}, 2119: {incl_sys_filters,[".*"]}, 2120: {excl_sys_filters,[]}, 2121: {incl_app_filters,[".*"]}, 2122: {excl_app_filters,[]}, 2123: {incl_archive_filters,[".*"]}, 2124: {excl_archive_filters,["^include$","^priv$"]}, 2125: {archive_opts,[]}, 2126: {rel_app_type,permanent}, 2127: {app_file,keep}, 2128: {debug_info,keep}]}]}, 2129: file:consult(Defaults)), 2130: 2131: KVsn = latest(kernel), 2132: StdVsn = latest(stdlib), 2133: SaslVsn = latest(sasl), 2134: 2135: LibDir = code:lib_dir(), 2136: KLibDir = filename:join(LibDir,"kernel-"++KVsn), 2137: StdLibDir = filename:join(LibDir,"stdlib-"++StdVsn), 2138: SaslLibDir = filename:join(LibDir,"sasl-"++SaslVsn), 2139: 2140: All = filename:join(PrivDir,"save_all.reltool"), 2141: ?m(ok, reltool_server:save_config(Pid,All,true,true)), 2142: ?msym({ok,[{sys,[{root_dir,_}, 2143: {lib_dirs,_}, 2144: {mod_cond,all}, 2145: {incl_cond,exclude}, 2146: {erts,[]}, 2147: {app,kernel,[{incl_cond,include},{vsn,KVsn}, 2148: {lib_dir,KLibDir},{mod,_,[]}|_]}, 2149: {app,sasl,[{incl_cond,include},{vsn,SaslVsn}, 2150: {lib_dir,SaslLibDir},{mod,_,[]}|_]}, 2151: {app,stdlib,[{incl_cond,include},{vsn,StdVsn}, 2152: {lib_dir,StdLibDir},{mod,_,[]}|_]}, 2153: {boot_rel,"start_clean"}, 2154: {rel,"start_clean","1.0",[]}, 2155: {rel,"start_sasl","1.0",[sasl]}, 2156: {emu_name,"beam"}, 2157: {relocatable,true}, 2158: {profile,development}, 2159: {incl_sys_filters,[".*"]}, 2160: {excl_sys_filters,[]}, 2161: {incl_app_filters,[".*"]}, 2162: {excl_app_filters,[]}, 2163: {incl_archive_filters,[".*"]}, 2164: {excl_archive_filters,["^include$","^priv$"]}, 2165: {archive_opts,[]}, 2166: {rel_app_type,permanent}, 2167: {app_file,keep}, 2168: {debug_info,keep}]}]}, 2169: file:consult(All)), 2170: 2171: ?m(ok, reltool:stop(Pid)), 2172: ok. 2173: 2174: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2175: %% Test calculation of dependencies 2176: %% The following test applications are used 2177: %% 2178: %% x-1.0: x1.erl x2.erl x3.erl 2179: %% \ / (x2 calls y1, x3 calls y2) 2180: %% y-1.0: y0.erl y1.erl y2.erl 2181: %% \ (y1 calls z1) 2182: %% z-1.0 z1.erl 2183: %% 2184: %% Test includes x and derives y and z. 2185: %% 2186: dependencies(Config) -> 2187: %% Default: all modules included => y and z are included (derived) 2188: Sys = {sys,[{lib_dirs,[filename:join(datadir(Config),"dependencies")]}, 2189: {incl_cond, exclude}, 2190: {app,kernel,[{incl_cond,include}]}, 2191: {app,sasl,[{incl_cond,include}]}, 2192: {app,stdlib,[{incl_cond,include}]}, 2193: {app,x,[{incl_cond,include}]}, 2194: {app,y,[{incl_cond,derived}]}, 2195: {app,z,[{incl_cond,derived}]}]}, 2196: {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])), 2197: 2198: ?msym({ok,[#app{name=kernel}, 2199: #app{name=sasl}, 2200: #app{name=stdlib}, 2201: #app{name=x,uses_apps=[y]}]}, 2202: reltool_server:get_apps(Pid,whitelist)), 2203: {ok, Der} = ?msym({ok,_}, 2204: reltool_server:get_apps(Pid,derived)), 2205: ?msym([#app{name=y,uses_apps=[z]}, 2206: #app{name=z}], 2207: rm_missing_app(Der)), 2208: ?msym({ok,[]}, 2209: reltool_server:get_apps(Pid,source)), 2210: 2211: %% Excluding x2 => y still included since y2 is used by x3 2212: %% z still included since z1 is used by y1 2213: Sys2 = {sys,[{lib_dirs,[filename:join(datadir(Config),"dependencies")]}, 2214: {incl_cond, exclude}, 2215: {app,kernel,[{incl_cond,include}]}, 2216: {app,sasl,[{incl_cond,include}]}, 2217: {app,stdlib,[{incl_cond,include}]}, 2218: {app,x,[{incl_cond,include},{mod,x2,[{incl_cond,exclude}]}]}, 2219: {app,y,[{incl_cond,derived}]}, 2220: {app,z,[{incl_cond,derived}]}]}, 2221: ?m({ok,[]}, reltool_server:load_config(Pid,Sys2)), 2222: ?msym({ok,[#app{name=kernel}, 2223: #app{name=sasl}, 2224: #app{name=stdlib}, 2225: #app{name=x,uses_apps=[y]}]}, 2226: reltool_server:get_apps(Pid,whitelist)), 2227: {ok, Der2} = ?msym({ok,_}, 2228: reltool_server:get_apps(Pid,derived)), 2229: ?msym([#app{name=y,uses_apps=[z]}, 2230: #app{name=z}], 2231: rm_missing_app(Der2)), 2232: ?msym({ok,[]}, 2233: reltool_server:get_apps(Pid,source)), 2234: 2235: %% Excluding x3 => y still included since y1 is used by x2 2236: %% z still included since z1 is used by y1 2237: Sys3 = {sys,[{lib_dirs,[filename:join(datadir(Config),"dependencies")]}, 2238: {incl_cond, exclude}, 2239: {app,kernel,[{incl_cond,include}]}, 2240: {app,sasl,[{incl_cond,include}]}, 2241: {app,stdlib,[{incl_cond,include}]}, 2242: {app,x,[{incl_cond,include},{mod,x3,[{incl_cond,exclude}]}]}, 2243: {app,y,[{incl_cond,derived}]}, 2244: {app,z,[{incl_cond,derived}]}]}, 2245: ?m({ok,[]}, reltool_server:load_config(Pid,Sys3)), 2246: ?msym({ok,[#app{name=kernel}, 2247: #app{name=sasl}, 2248: #app{name=stdlib}, 2249: #app{name=x,uses_apps=[y]}]}, 2250: reltool_server:get_apps(Pid,whitelist)), 2251: {ok, Der3} = ?msym({ok,_}, 2252: reltool_server:get_apps(Pid,derived)), 2253: ?msym([#app{name=y,uses_apps=[z]}, 2254: #app{name=z}], 2255: rm_missing_app(Der3)), 2256: ?msym({ok,[]}, 2257: reltool_server:get_apps(Pid,source)), 2258: 2259: %% Excluding x2 and x3 => y and z excluded 2260: Sys4 = {sys,[{lib_dirs,[filename:join(datadir(Config),"dependencies")]}, 2261: {incl_cond, exclude}, 2262: {app,kernel,[{incl_cond,include}]}, 2263: {app,sasl,[{incl_cond,include}]}, 2264: {app,stdlib,[{incl_cond,include}]}, 2265: {app,x,[{incl_cond,include}, 2266: {mod,x2,[{incl_cond,exclude}]}, 2267: {mod,x3,[{incl_cond,exclude}]}]}, 2268: {app,y,[{incl_cond,derived}]}, 2269: {app,z,[{incl_cond,derived}]}]}, 2270: ?m({ok,[]}, reltool_server:load_config(Pid,Sys4)), 2271: ?msym({ok,[#app{name=kernel}, 2272: #app{name=sasl}, 2273: #app{name=stdlib}, 2274: #app{name=x,uses_apps=[]}]}, 2275: reltool_server:get_apps(Pid,whitelist)), 2276: {ok, Der4} = ?msym({ok,_}, 2277: reltool_server:get_apps(Pid,derived)), 2278: ?msym([], rm_missing_app(Der4)), 2279: ?msym({ok,[#app{name=y}, 2280: #app{name=z}]}, 2281: reltool_server:get_apps(Pid,source)), 2282: 2283: %% Excluding y1 => y still included since y2 is used by x3 2284: %% z excluded since not used by any other than y1 2285: Sys5 = {sys,[{lib_dirs,[filename:join(datadir(Config),"dependencies")]}, 2286: {incl_cond, exclude}, 2287: {app,kernel,[{incl_cond,include}]}, 2288: {app,sasl,[{incl_cond,include}]}, 2289: {app,stdlib,[{incl_cond,include}]}, 2290: {app,x,[{incl_cond,include}]}, 2291: {app,y,[{incl_cond,derived}, 2292: {mod,y1,[{incl_cond,exclude}]}]}, 2293: {app,z,[{incl_cond,derived}]}]}, 2294: ?m({ok,[]}, reltool_server:load_config(Pid,Sys5)), 2295: ?msym({ok,[#app{name=kernel}, 2296: #app{name=sasl}, 2297: #app{name=stdlib}, 2298: #app{name=x,uses_apps=[y]}]}, 2299: reltool_server:get_apps(Pid,whitelist)), 2300: {ok, Der5} = ?msym({ok,_}, 2301: reltool_server:get_apps(Pid,derived)), 2302: ?msym([#app{name=y,uses_apps=[]}], rm_missing_app(Der5)), 2303: ?msym({ok,[#app{name=z}]}, 2304: reltool_server:get_apps(Pid,source)), 2305: 2306: ?m(ok, reltool:stop(Pid)), 2307: ok. 2308: 2309: 2310: %% Test that incl_cond on mod level overwrites mod_cond on app level 2311: %% Uses same test applications as dependencies/1 above 2312: mod_incl_cond_derived(Config) -> 2313: %% In app y: mod_cond=none means no module shall be included 2314: %% but mod_cond is overwritten by incl_cond on mod level 2315: Sys = {sys,[{lib_dirs,[filename:join(datadir(Config),"dependencies")]}, 2316: {incl_cond, exclude}, 2317: {app,kernel,[{incl_cond,include}]}, 2318: {app,sasl,[{incl_cond,include}]}, 2319: {app,stdlib,[{incl_cond,include}]}, 2320: {app,x,[{incl_cond,include}]}, 2321: {app,y,[{incl_cond,include}, 2322: {mod_cond,none}, 2323: {mod,y0,[{incl_cond,derived}]}, 2324: {mod,y2,[{incl_cond,derived}]}]}]}, 2325: {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])), 2326: 2327: ?msym({ok,[#app{name=kernel}, 2328: #app{name=sasl}, 2329: #app{name=stdlib}, 2330: #app{name=x,uses_apps=[y]}, 2331: #app{name=y,uses_apps=[]}]}, 2332: reltool_server:get_apps(Pid,whitelist)), 2333: {ok, Der} = ?msym({ok,_},reltool_server:get_apps(Pid,derived)), 2334: ?msym([], rm_missing_app(Der)), 2335: ?msym({ok,[]}, reltool_server:get_apps(Pid,source)), 2336: 2337: %% 1. check that y0 is not included since it has 2338: %% incl_cond=derived, but is not used by any other module. 2339: ?msym({ok,#mod{is_included=undefined}}, reltool_server:get_mod(Pid,y0)), 2340: 2341: %% 2. check that y1 is excluded since it has undefined incl_cond 2342: %% on mod level, so mod_cond on app level shall be used. 2343: ?msym({ok,#mod{is_included=false}}, reltool_server:get_mod(Pid,y1)), 2344: 2345: %% 3. check that y2 is included since it has incl_cond=derived and 2346: %% is used by x3. 2347: ?msym({ok,#mod{is_included=true}}, reltool_server:get_mod(Pid,y2)), 2348: 2349: ok. 2350: 2351: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2352: use_selected_vsn(Config) -> 2353: LibDir1 = filename:join(datadir(Config),"use_selected_vsn"), 2354: B1Dir = filename:join(LibDir1,"b-1.0"), 2355: B3Dir = filename:join(LibDir1,"b-3.0"), 2356: 2357: LibDir2 = filename:join(LibDir1,"lib2"), 2358: B2Dir = filename:join(LibDir2,"b-2.0"), 2359: 2360: %%----------------------------------------------------------------- 2361: %% Pre-selected vsn of app b 2362: Sys1 = {sys,[{lib_dirs,[LibDir1]}, 2363: {incl_cond, exclude}, 2364: {app,kernel,[{incl_cond,include}]}, 2365: {app,sasl,[{incl_cond,include}]}, 2366: {app,stdlib,[{incl_cond,include}]}, 2367: {app,b,[{incl_cond,include},{vsn,"1.0"}]}]}, 2368: {ok, Pid1} = ?msym({ok, _}, reltool:start_server([{config, Sys1}])), 2369: {ok,B11} = ?msym({ok,#app{vsn="1.0",active_dir=B1Dir}}, 2370: reltool_server:get_app(Pid1,b)), 2371: 2372: %% Change from a pre-selected vsn to use a specific dir 2373: ?msym({ok, #app{vsn ="3.0", active_dir = B3Dir}, []}, 2374: reltool_server:set_app(Pid1, 2375: B11#app{active_dir = B3Dir, 2376: use_selected_vsn = dir, 2377: label = undefined, 2378: vsn = undefined, 2379: info = undefined})), 2380: ?m(ok, reltool:stop(Pid1)), 2381: 2382: 2383: %%----------------------------------------------------------------- 2384: %% Pre-selected vsn of app b 2385: Sys2 = {sys,[{lib_dirs,[LibDir1]}, 2386: {incl_cond, exclude}, 2387: {app,kernel,[{incl_cond,include}]}, 2388: {app,sasl,[{incl_cond,include}]}, 2389: {app,stdlib,[{incl_cond,include}]}, 2390: {app,b,[{incl_cond,include},{vsn,"1.0"}]}]}, 2391: {ok, Pid2} = ?msym({ok, _}, reltool:start_server([{config, Sys2}])), 2392: {ok,B21} = ?msym({ok,#app{vsn="1.0",active_dir=B1Dir}}, 2393: reltool_server:get_app(Pid2,b)), 2394: 2395: %% Change from a pre-selected vsn to use latest 2396: ?msym({ok, #app{vsn ="3.0", active_dir = B3Dir}, []}, 2397: reltool_server:set_app(Pid2, 2398: B21#app{use_selected_vsn=undefined, 2399: label = undefined, 2400: vsn = undefined, 2401: info = undefined})), 2402: ?m(ok, reltool:stop(Pid2)), 2403: 2404: 2405: %%----------------------------------------------------------------- 2406: %% Pre-selected directory for app b 2407: Sys3 = {sys,[{lib_dirs,[LibDir1]}, 2408: {incl_cond, exclude}, 2409: {app,kernel,[{incl_cond,include}]}, 2410: {app,sasl,[{incl_cond,include}]}, 2411: {app,stdlib,[{incl_cond,include}]}, 2412: {app,b,[{incl_cond,include},{lib_dir,B2Dir}]}]}, 2413: {ok, Pid3} = ?msym({ok, _}, reltool:start_server([{config, Sys3}])), 2414: % test_server:break("Pid3 = list_to_pid(\""++pid_to_list(Pid3)++"\")."), 2415: {ok,B31} = ?msym({ok,#app{vsn="2.0",active_dir=B2Dir}}, 2416: reltool_server:get_app(Pid3,b)), 2417: %% Change from a pre-selected dir to use latest 2418: {ok,B32,_} = ?msym({ok, #app{vsn ="3.0", active_dir = B3Dir}, []}, 2419: reltool_server:set_app(Pid3, 2420: B31#app{use_selected_vsn=undefined, 2421: label = undefined, 2422: vsn = undefined, 2423: info = undefined})), 2424: %% Change back to use selected dir 2425: {ok,B33,_} = ?msym({ok, #app{vsn ="3.0", active_dir = B3Dir}, []}, 2426: reltool_server:set_app(Pid3, 2427: B32#app{use_selected_vsn = dir})), 2428: %% use dir 1 2429: {ok,B34,_} = ?msym({ok, #app{vsn ="1.0", active_dir = B1Dir}, []}, 2430: reltool_server:set_app(Pid3, 2431: B33#app{active_dir = B1Dir, 2432: label = undefined, 2433: vsn = undefined, 2434: info = undefined})), 2435: %% use dir 2 2436: {ok,B35,_} = ?msym({ok, #app{vsn ="2.0", active_dir = B2Dir}, []}, 2437: reltool_server:set_app(Pid3, 2438: B34#app{active_dir = B2Dir, 2439: label = undefined, 2440: vsn = undefined, 2441: info = undefined})), 2442: %% use dir 3 2443: ?msym({ok, #app{vsn ="3.0", active_dir = B3Dir}, []}, 2444: reltool_server:set_app(Pid3, 2445: B35#app{active_dir = B3Dir, 2446: label = undefined, 2447: vsn = undefined, 2448: info = undefined})), 2449: ?m(ok, reltool:stop(Pid3)), 2450: ok. 2451: 2452: 2453: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2454: use_selected_vsn_relative_path(Config) -> 2455: LibDir = filename:join([datadir(Config),"use_selected_vsn","b-1.0"]), 2456: RelDir = filename:join(LibDir,"rel"), 2457: 2458: {ok,Cwd} = file:get_cwd(), 2459: ok = file:set_cwd(RelDir), 2460: 2461: Sys = {sys,[{incl_cond, exclude}, 2462: {app,kernel,[{incl_cond,include}]}, 2463: {app,sasl,[{incl_cond,include}]}, 2464: {app,stdlib,[{incl_cond,include}]}, 2465: {app,b,[{incl_cond,include},{lib_dir,".."}]}]}, 2466: {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])), 2467: 2468: ?msym({ok,#app{vsn="1.0",active_dir=LibDir}},reltool_server:get_app(Pid,b)), 2469: 2470: ?m(ok, reltool:stop(Pid)), 2471: 2472: ok = file:set_cwd(Cwd), 2473: ok. 2474: 2475: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2476: %% Test that reltool recognizes an application with its real name even 2477: %% though it uses non standard format for its version number (in the 2478: %% directory name) 2479: non_standard_vsn_id(Config) -> 2480: LibDir = filename:join(datadir(Config),"non_standard_vsn_id"), 2481: B1Dir = filename:join(LibDir,"b-first"), 2482: B2Dir = filename:join(LibDir,"b-second"), 2483: 2484: %%----------------------------------------------------------------- 2485: %% Default vsn of app b 2486: Sys1 = {sys,[{lib_dirs,[LibDir]}, 2487: {incl_cond, exclude}, 2488: {app,kernel,[{incl_cond,include}]}, 2489: {app,sasl,[{incl_cond,include}]}, 2490: {app,stdlib,[{incl_cond,include}]}, 2491: {app,b,[{incl_cond,include}]}]}, 2492: {ok, Pid1} = ?msym({ok, _}, reltool:start_server([{config, Sys1}])), 2493: ?msym({ok,#app{vsn="first",active_dir=B1Dir,sorted_dirs=[B1Dir,B2Dir]}}, 2494: reltool_server:get_app(Pid1,b)), 2495: 2496: %%----------------------------------------------------------------- 2497: %% Pre-selected vsn of app b 2498: Sys2 = {sys,[{lib_dirs,[LibDir]}, 2499: {incl_cond, exclude}, 2500: {app,kernel,[{incl_cond,include}]}, 2501: {app,sasl,[{incl_cond,include}]}, 2502: {app,stdlib,[{incl_cond,include}]}, 2503: {app,b,[{incl_cond,include},{vsn,"second"}]}]}, 2504: {ok, Pid2} = ?msym({ok, _}, reltool:start_server([{config, Sys2}])), 2505: ?msym({ok,#app{vsn="second",active_dir=B2Dir,sorted_dirs=[B1Dir,B2Dir]}}, 2506: reltool_server:get_app(Pid2,b)), 2507: ok. 2508: 2509: 2510: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2511: %% Library functions 2512: 2513: erl_libs() -> 2514: case os:getenv("ERL_LIBS") of 2515: false -> []; 2516: LibStr -> string:tokens(LibStr, ":;") 2517: end. 2518: 2519: datadir(Config) -> 2520: %% Removes the trailing slash... 2521: filename:nativename(?config(data_dir,Config)). 2522: 2523: latest(App) -> 2524: AppStr = atom_to_list(App), 2525: AppDirs = filelib:wildcard(filename:join(code:lib_dir(),AppStr++"-*")), 2526: [LatestAppDir|_] = lists:reverse(AppDirs), 2527: [_,Vsn] = string:tokens(filename:basename(LatestAppDir),"-"), 2528: Vsn. 2529: 2530: rm_missing_app(Apps) -> 2531: lists:keydelete(?MISSING_APP_NAME,#app.name,Apps). 2532: 2533: diff_script(Script, Script) -> 2534: equal; 2535: diff_script({script, Rel, Commands1}, {script, Rel, Commands2}) -> 2536: diff_cmds(Commands1, Commands2); 2537: diff_script({script, Rel1, _}, {script, Rel2, _}) -> 2538: {error, {Rel1, Rel2}}. 2539: 2540: diff_cmds([Cmd | Commands1], [Cmd | Commands2]) -> 2541: diff_cmds(Commands1, Commands2); 2542: diff_cmds([Cmd1 | _Commands1], [Cmd2 | _Commands2]) -> 2543: {diff, {expected, Cmd1}, {actual, Cmd2}}; 2544: diff_cmds([], []) -> 2545: equal. 2546: 2547: os_cmd(Cmd) when is_list(Cmd) -> 2548: %% Call the plain os:cmd with an echo command appended to print command status 2549: %% io:format("os:cmd(~p).\n", [Cmd]), 2550: case os:cmd(Cmd++";echo \"#$?\"") of 2551: %% There is (as far as I can tell) only one thing that will match this 2552: %% and that is too silly to ever be used, but... 2553: []-> 2554: {99, []}; 2555: Return-> 2556: %% Find the position of the status code wich is last in the string 2557: %% prepended with # 2558: case string:rchr(Return, $#) of 2559: 2560: %% This happens only if the sh command pipe is somehow interrupted 2561: 0-> 2562: {98, Return}; 2563: 2564: Position-> 2565: Result = string:left(Return,Position - 1), 2566: Status = string:substr(Return,Position + 1, length(Return) - Position - 1), 2567: {list_to_integer(Status), Result} 2568: end 2569: end. 2570: 2571: %% Returns the location (directory) of the given module. Split, 2572: %% reverted and relative to the lib dir. 2573: mod_path(Node,Mod) -> 2574: case rpc:call(Node,code,which,[Mod]) of 2575: Path when is_list(Path) -> 2576: lists:takewhile( 2577: fun("lib") -> false; 2578: (_) -> true 2579: end, 2580: lists:reverse(filename:split(filename:dirname(Path)))); 2581: Other -> 2582: Other 2583: end. 2584: 2585: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2586: %% Node handling 2587: 2588: start_node(Name, ErlPath) -> 2589: start_node(Name, ErlPath, []). 2590: start_node(Name, ErlPath, Args0) -> 2591: FullName = full_node_name(Name), 2592: Args = mk_node_args(Name, Args0), 2593: io:format("Starting node ~p: ~ts~n", 2594: [FullName, lists:flatten([[X," "] || X <- [ErlPath|Args]])]), 2595: %io:format("open_port({spawn_executable, ~p}, [{args,~p}])~n",[ErlPath,Args]), 2596: case open_port({spawn_executable, ErlPath}, [{args,Args}]) of 2597: Port when is_port(Port) -> 2598: %% no need to close port since node is detached (see 2599: %% mk_node_args) so port will be closed anyway. 2600: case ping_node(FullName, 50) of 2601: ok -> {ok, FullName}; 2602: Other -> exit({failed_to_start_node, FullName, Other}) 2603: end; 2604: Error -> 2605: exit({failed_to_start_node, FullName, Error}) 2606: end. 2607: 2608: stop_node(Node) -> 2609: rpc:call(Node,erlang,halt,[]), 2610: wait_for_node_down(Node,50). 2611: 2612: wait_for_node_down(Node,0) -> 2613: test_server:fail({cant_terminate_node,Node}); 2614: wait_for_node_down(Node,N) -> 2615: case net_adm:ping(Node) of 2616: pong -> 2617: timer:sleep(1000), 2618: wait_for_node_down(Node,N-1); 2619: pang -> 2620: ok 2621: end. 2622: 2623: mk_node_args(Name, Args) -> 2624: Pa = filename:dirname(code:which(?MODULE)), 2625: NameSw = case net_kernel:longnames() of 2626: false -> "-sname"; 2627: true -> "-name"; 2628: _ -> exit(not_distributed_node) 2629: end, 2630: {ok, Pwd} = file:get_cwd(), 2631: NameStr = atom_to_list(Name), 2632: ["-detached", 2633: NameSw, NameStr, 2634: "-pa", Pa, 2635: "-env", "ERL_CRASH_DUMP", Pwd ++ "/erl_crash_dump." ++ NameStr, 2636: "-setcookie", atom_to_list(erlang:get_cookie()) 2637: | Args]. 2638: 2639: full_node_name(PreName) -> 2640: HostSuffix = lists:dropwhile(fun ($@) -> false; (_) -> true end, 2641: atom_to_list(node())), 2642: list_to_atom(atom_to_list(PreName) ++ HostSuffix). 2643: 2644: ping_node(_Node, 0) -> 2645: {error, net_adm}; 2646: ping_node(Node, N) when is_integer(N), N > 0 -> 2647: case catch net_adm:ping(Node) of 2648: pong -> 2649: wait_for_process(Node, code_server, 50); 2650: _ -> 2651: timer:sleep(1000), 2652: ping_node(Node, N-1) 2653: end. 2654: 2655: wait_for_process(_Node, Name, 0) -> 2656: {error, Name}; 2657: wait_for_process(Node, Name, N) when is_integer(N), N > 0 -> 2658: case rpc:call(Node, erlang, whereis, [Name]) of 2659: undefined -> 2660: timer:sleep(1000), 2661: wait_for_process(Node, Name, N-1); 2662: {badrpc, _} = Reason -> 2663: erlang:error({Reason, Node}); 2664: Pid when is_pid(Pid) -> 2665: ok 2666: end. 2667: 2668: wait_for_app(_Node, Name, 0) -> 2669: {error, Name}; 2670: wait_for_app(Node, Name, N) when is_integer(N), N > 0 -> 2671: case rpc:call(Node,application,which_applications,[]) of 2672: {badrpc,Reason} -> 2673: test_server:fail({failed_to_get_applications,Reason}); 2674: Apps -> 2675: case lists:member(Name,Apps) of 2676: false -> 2677: timer:sleep(1000), 2678: wait_for_app(Node, Name, N-1); 2679: true -> 2680: ok 2681: end 2682: end. 2683: 2684: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2685: %% Run escript 2686: 2687: run(Dir, Script, Args) -> 2688: Cmd0 = filename:rootname(Script) ++ " " ++ Args, 2689: Cmd = case os:type() of 2690: {win32,_} -> filename:nativename(Dir) ++ "\\" ++ Cmd0; 2691: _ -> Cmd0 2692: end, 2693: do_run(Dir, Cmd). 2694: 2695: run(Dir, Opts, Script, Args) -> 2696: Cmd0 = filename:rootname(Script) ++ " " ++ Args, 2697: Cmd = case os:type() of 2698: {win32,_} -> Opts ++ " " ++ filename:nativename(Dir) ++ "\\" ++ Cmd0; 2699: _ -> Opts ++ " " ++ Dir ++ "/" ++ Cmd0 2700: end, 2701: do_run(Dir, Cmd). 2702: 2703: do_run(Dir, Cmd) -> 2704: io:format("Run: ~p\n", [Cmd]), 2705: Env = [{"PATH",Dir++":"++os:getenv("PATH")}, 2706: {"ERL_FLAGS",""}, % Make sure no flags are set that can override 2707: {"ERL_ZFLAGS",""}], % any of the flags set in the escript. 2708: Port = open_port({spawn,Cmd}, [exit_status,eof,in,{env,Env}]), 2709: Res = get_data(Port, []), 2710: receive 2711: {Port,{exit_status,ExitCode}} -> 2712: s2b([Res,"ExitCode:"++integer_to_list(ExitCode)]) 2713: end. 2714: 2715: get_data(Port, SoFar) -> 2716: receive 2717: {Port,{data,Bytes}} -> 2718: get_data(Port, [SoFar|Bytes]); 2719: {Port,eof} -> 2720: erlang:port_close(Port), 2721: SoFar 2722: end. 2723: 2724: expected_output([data_dir|T], Data) -> 2725: Slash = case os:type() of 2726: {win32,_} -> "\\"; 2727: _ -> "/" 2728: end, 2729: [filename:nativename(Data)++Slash|expected_output(T, Data)]; 2730: expected_output([H|T], Data) -> 2731: [H|expected_output(T, Data)]; 2732: expected_output([], _) -> 2733: []; 2734: expected_output(Bin, _) when is_binary(Bin) -> 2735: Bin. 2736: 2737: %% Convert the given list to a binary with the same encoding as the 2738: %% file name translation mode 2739: s2b(List) -> 2740: Enc = file:native_name_encoding(), 2741: unicode:characters_to_binary(List,Enc,Enc).