diff options
-rw-r--r-- | test/rlx_extended_bin_SUITE.erl | 349 | ||||
-rw-r--r-- | test/rlx_test_utils.erl | 16 |
2 files changed, 365 insertions, 0 deletions
diff --git a/test/rlx_extended_bin_SUITE.erl b/test/rlx_extended_bin_SUITE.erl new file mode 100644 index 0000000..ce72437 --- /dev/null +++ b/test/rlx_extended_bin_SUITE.erl @@ -0,0 +1,349 @@ +%% -*- erlang-indent-level: 4; indent-tabs-mode: nil; fill-column: 92 -*- +%%% Copyright 2012 Erlware, LLC. All Rights Reserved. +%%% +%%% This file is provided to you under the Apache License, +%%% Version 2.0 (the "License"); you may not use this file +%%% except in compliance with the License. You may obtain +%%% a copy of the License at +%%% +%%% http://www.apache.org/licenses/LICENSE-2.0 +%%% +%%% Unless required by applicable law or agreed to in writing, +%%% software distributed under the License is distributed on an +%%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +%%% KIND, either express or implied. See the License for the +%%% specific language governing permissions and limitations +%%% under the License. +%%%------------------------------------------------------------------- +-module(rlx_extended_bin_SUITE). + +-export([suite/0, + init_per_suite/1, + end_per_suite/1, + init_per_testcase/2, + all/0, + ping/1, + attach/1, + pid/1, + restart/1, + reboot/1, + escript/1, + remote_console/1]). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("eunit/include/eunit.hrl"). +-include_lib("kernel/include/file.hrl"). + +suite() -> + [{timetrap,{seconds,30}}]. + +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + +init_per_testcase(_, Config) -> + DataDir = filename:join(proplists:get_value(priv_dir, Config), ?MODULE), + LibDir1 = filename:join([DataDir, rlx_test_utils:create_random_name("lib_dir1_")]), + ok = rlx_util:mkdir_p(LibDir1), + State = rlx_state:new([], [{lib_dirs, [LibDir1]}], [release]), + {ok, State1} = rlx_config:do(State), + [{lib1, LibDir1}, + {state, State1} | Config]. + +all() -> + [ping, attach, pid, restart, reboot, escript, + remote_console]. + +ping(Config) -> + LibDir1 = proplists:get_value(lib1, Config), + + rlx_test_utils:create_app(LibDir1, "goal_app", "0.0.1", [stdlib,kernel], []), + + ConfigFile = filename:join([LibDir1, "relx.config"]), + rlx_test_utils:write_config(ConfigFile, + [{release, {foo, "0.0.1"}, + [goal_app]}, + {lib_dirs, [filename:join(LibDir1, "*")]}, + {generate_start_script, true}, + {extended_start_script, true} + ]), + + OutputDir = filename:join([proplists:get_value(priv_dir, Config), + rlx_test_utils:create_random_name("relx-output")]), + + {ok, _State} = relx:do([{relname, foo}, + {relvsn, "0.0.1"}, + {goals, []}, + {lib_dirs, [LibDir1]}, + {log_level, 3}, + {output_dir, OutputDir}, + {config, ConfigFile}], ["release"]), + + %% now start/stop the release to make sure the extended script is working + {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo start"])), + timer:sleep(2000), + {ok, "pong"} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])), + {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo stop"])), + %% a ping should fail after stopping a node + {error, 1} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])). + +attach(Config) -> + LibDir1 = proplists:get_value(lib1, Config), + + rlx_test_utils:create_app(LibDir1, "goal_app", "0.0.1", [stdlib,kernel], []), + + ConfigFile = filename:join([LibDir1, "relx.config"]), + rlx_test_utils:write_config(ConfigFile, + [{release, {foo, "0.0.1"}, + [goal_app]}, + {lib_dirs, [filename:join(LibDir1, "*")]}, + {generate_start_script, true}, + {extended_start_script, true} + ]), + + OutputDir = filename:join([proplists:get_value(priv_dir, Config), + rlx_test_utils:create_random_name("relx-output")]), + + {ok, _State} = relx:do([{relname, foo}, + {relvsn, "0.0.1"}, + {goals, []}, + {lib_dirs, [LibDir1]}, + {log_level, 3}, + {output_dir, OutputDir}, + {config, ConfigFile}], ["release"]), + + %% now start/stop the release to make sure the extended script is working + {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo start"])), + timer:sleep(2000), + {ok, "pong"} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])), + {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo attach", "&"])), + timer:sleep(2000), + {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo stop"])), + {error, 1} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])). + +pid(Config) -> + LibDir1 = proplists:get_value(lib1, Config), + + rlx_test_utils:create_app(LibDir1, "goal_app", "0.0.1", [stdlib,kernel], []), + + ConfigFile = filename:join([LibDir1, "relx.config"]), + rlx_test_utils:write_config(ConfigFile, + [{release, {foo, "0.0.1"}, + [goal_app]}, + {lib_dirs, [filename:join(LibDir1, "*")]}, + {generate_start_script, true}, + {extended_start_script, true} + ]), + + OutputDir = filename:join([proplists:get_value(priv_dir, Config), + rlx_test_utils:create_random_name("relx-output")]), + + {ok, _State} = relx:do([{relname, foo}, + {relvsn, "0.0.1"}, + {goals, []}, + {lib_dirs, [LibDir1]}, + {log_level, 3}, + {output_dir, OutputDir}, + {config, ConfigFile}], ["release"]), + + %% check for a valid pid + {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo start"])), + timer:sleep(2000), + {ok, "pong"} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])), + {ok, _Pid} = sh(filename:join([OutputDir, "foo", "bin", "foo pid"])), + {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo stop"])), + {error, 1} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])). + +restart(Config) -> + LibDir1 = proplists:get_value(lib1, Config), + + rlx_test_utils:create_app(LibDir1, "goal_app", "0.0.1", [stdlib,kernel], []), + + ConfigFile = filename:join([LibDir1, "relx.config"]), + rlx_test_utils:write_config(ConfigFile, + [{release, {foo, "0.0.1"}, + [goal_app]}, + {lib_dirs, [filename:join(LibDir1, "*")]}, + {generate_start_script, true}, + {extended_start_script, true} + ]), + + OutputDir = filename:join([proplists:get_value(priv_dir, Config), + rlx_test_utils:create_random_name("relx-output")]), + + {ok, _State} = relx:do([{relname, foo}, + {relvsn, "0.0.1"}, + {goals, []}, + {lib_dirs, [LibDir1]}, + {log_level, 3}, + {output_dir, OutputDir}, + {config, ConfigFile}], ["release"]), + + %% a restart is a gracious operation that does not involve the + %% death of the VM, so the pid should be the same + {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo start"])), + timer:sleep(2000), + {ok, "pong"} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])), + {ok, Pid1} = sh(filename:join([OutputDir, "foo", "bin", "foo pid"])), + {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo restart"])), + timer:sleep(2000), + {ok, Pid2} = sh(filename:join([OutputDir, "foo", "bin", "foo pid"])), + {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo stop"])), + {error, 1} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])), + ?assertEqual(Pid1, Pid2). + +reboot(Config) -> + LibDir1 = proplists:get_value(lib1, Config), + + rlx_test_utils:create_app(LibDir1, "goal_app", "0.0.1", [stdlib,kernel], []), + + ConfigFile = filename:join([LibDir1, "relx.config"]), + rlx_test_utils:write_config(ConfigFile, + [{release, {foo, "0.0.1"}, + [goal_app]}, + {lib_dirs, [filename:join(LibDir1, "*")]}, + {generate_start_script, true}, + {extended_start_script, true} + ]), + + OutputDir = filename:join([proplists:get_value(priv_dir, Config), + rlx_test_utils:create_random_name("relx-output")]), + + {ok, _State} = relx:do([{relname, foo}, + {relvsn, "0.0.1"}, + {goals, []}, + {lib_dirs, [LibDir1]}, + {log_level, 3}, + {output_dir, OutputDir}, + {config, ConfigFile}], ["release"]), + + %% a reboot involves stopping the emulator, it needs to be restarted + %% though + {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo start"])), + timer:sleep(2000), + {ok, "pong"} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])), + {ok, Pid1} = sh(filename:join([OutputDir, "foo", "bin", "foo pid"])), + {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo reboot"])), + timer:sleep(2000), + {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo start"])), + timer:sleep(2000), + {ok, Pid2} = sh(filename:join([OutputDir, "foo", "bin", "foo pid"])), + {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo stop"])), + {error, 1} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])), + ?assertNotEqual(Pid1, Pid2). + +escript(Config) -> + LibDir1 = proplists:get_value(lib1, Config), + + rlx_test_utils:create_app(LibDir1, "goal_app", "0.0.1", [stdlib,kernel], []), + + ConfigFile = filename:join([LibDir1, "relx.config"]), + rlx_test_utils:write_config(ConfigFile, + [{release, {foo, "0.0.1"}, + [goal_app]}, + {lib_dirs, [filename:join(LibDir1, "*")]}, + {generate_start_script, true}, + {extended_start_script, true} + ]), + + OutputDir = filename:join([proplists:get_value(priv_dir, Config), + rlx_test_utils:create_random_name("relx-output")]), + + {ok, _State} = relx:do([{relname, foo}, + {relvsn, "0.0.1"}, + {goals, []}, + {lib_dirs, [LibDir1]}, + {log_level, 3}, + {output_dir, OutputDir}, + {config, ConfigFile}], ["release"]), + + ok = ec_file:write(filename:join([OutputDir, "foo", "script.erl"]), + [rlx_test_utils:escript_contents()]), + + %% now start/stop the release to make sure the extended script is working + {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo start"])), + timer:sleep(2000), + {ok, "pong"} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])), + [ExpectedOutput] = io_lib:format("~s", + [filename:join([OutputDir, "foo"])]), + {ok, Output} = sh(filename:join([OutputDir, "foo", "bin", "foo escript script.erl"])), + ?assertEqual(ExpectedOutput, Output). + +remote_console(Config) -> + LibDir1 = proplists:get_value(lib1, Config), + + rlx_test_utils:create_app(LibDir1, "goal_app", "0.0.1", [stdlib,kernel], []), + + ConfigFile = filename:join([LibDir1, "relx.config"]), + rlx_test_utils:write_config(ConfigFile, + [{release, {foo, "0.0.1"}, + [goal_app]}, + {lib_dirs, [filename:join(LibDir1, "*")]}, + {generate_start_script, true}, + {extended_start_script, true} + ]), + + OutputDir = filename:join([proplists:get_value(priv_dir, Config), + rlx_test_utils:create_random_name("relx-output")]), + + {ok, _State} = relx:do([{relname, foo}, + {relvsn, "0.0.1"}, + {goals, []}, + {lib_dirs, [LibDir1]}, + {log_level, 3}, + {output_dir, OutputDir}, + {config, ConfigFile}], ["release"]), + + %% now start/stop the release to make sure the extended script is working + {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo start"])), + timer:sleep(2000), + {ok, "pong"} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])), + {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo remote_console &"])), + timer:sleep(2000), + {ok, NodesStr} = sh(filename:join([OutputDir, "foo", "bin", "foo eval 'nodes(connected).'"])), + Nodes = rlx_test_utils:list_to_term(NodesStr), + ?assertEqual(1, length(Nodes)), + {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo stop"])). + +%%%=================================================================== +%%% Helper Functions +%%%=================================================================== + +sh(Command) -> + sh(Command, []). + +sh(Command, Env) -> + sh(Command, Env, get_cwd()). + +sh(Command, Env, Dir) -> + Port = open_port({spawn, lists:flatten(Command)}, + [{cd, Dir}, + {env, Env}, + exit_status, + {line, 16384}, + use_stdio, stderr_to_stdout]), + case sh_loop(Port) of + {ok, Ret} -> + {ok, Ret}; + {error, Rc} -> + {error, Rc} + end. + +sh_loop(Port) -> + sh_loop(Port, ""). + +sh_loop(Port, Acc) -> + receive + {Port, {data, {_, Line}}} -> + sh_loop(Port, Acc ++ Line); + {Port, {exit_status, 0}} -> + {ok, Acc}; + {Port, {exit_status, Rc}} -> + {error, Rc} + end. + +get_cwd() -> + {ok, Dir} = file:get_cwd(), + Dir. diff --git a/test/rlx_test_utils.erl b/test/rlx_test_utils.erl index 279a887..2e6045f 100644 --- a/test/rlx_test_utils.erl +++ b/test/rlx_test_utils.erl @@ -80,6 +80,13 @@ test_template_contents() -> "{prop1, \"{{prop1}}\"}.\n" "{prop2, {{prop2}}}.\n". +escript_contents() -> + "#!/usr/bin/env escript\n" + "\n" + "main(_Args) ->\n" + "io:format(\"~s\n\",\n" + " [os:getenv(\"RELEASE_ROOT_DIR\")]).\n". + -ifdef(rand_module). random_uniform(N) -> rand:uniform(N). @@ -88,3 +95,12 @@ random_uniform(N) -> random:seed(os:timestamp()), random:uniform(N). -endif. + +list_to_term(String) -> + {ok, T, _} = erl_scan:string(String++"."), + case erl_parse:parse_term(T) of + {ok, Term} -> + Term; + {error, Error} -> + Error + end. |