aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--test/rlx_extended_bin_SUITE.erl349
-rw-r--r--test/rlx_test_utils.erl16
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.