aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssh/test/ssh_basic_SUITE.erl
diff options
context:
space:
mode:
authorBjörn-Egil Dahlberg <[email protected]>2010-11-26 14:55:41 +0100
committerNiclas Eklund <[email protected]>2011-05-19 14:38:11 +0200
commitd6e981e751b4565773204d7eb394ca445d63e771 (patch)
tree261d56b65f7a9d1255f3d5471213cac34e03e485 /lib/ssh/test/ssh_basic_SUITE.erl
parent2a3bb0347d691703cc1eb9b1fd6f29f489ff4e3a (diff)
downloadotp-d6e981e751b4565773204d7eb394ca445d63e771.tar.gz
otp-d6e981e751b4565773204d7eb394ca445d63e771.tar.bz2
otp-d6e981e751b4565773204d7eb394ca445d63e771.zip
Add test suite for ssh
Diffstat (limited to 'lib/ssh/test/ssh_basic_SUITE.erl')
-rw-r--r--lib/ssh/test/ssh_basic_SUITE.erl395
1 files changed, 395 insertions, 0 deletions
diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl
new file mode 100644
index 0000000000..d5eb5367e6
--- /dev/null
+++ b/lib/ssh/test/ssh_basic_SUITE.erl
@@ -0,0 +1,395 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(ssh_basic_SUITE).
+
+-include("test_server.hrl").
+-include("test_server_line.hrl").
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-define(NEWLINE, <<"\r\n">>).
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config) -> Config
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Description: Initialization before the whole suite
+%%
+%% Note: This function is free to add any key/value pairs to the Config
+%% variable, but should NOT alter/remove any existing entries.
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ crypto:start(),
+ Dir = ?config(priv_dir, Config),
+ ssh_test_lib:save_known_hosts(Dir),
+ {ok, _} = ssh_test_lib:get_id_keys(Dir),
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config) -> _
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Description: Cleanup after the whole suite
+%%--------------------------------------------------------------------
+end_per_suite(Config) ->
+ Dir = ?config(priv_dir, Config),
+ crypto:stop(),
+ ssh_test_lib:remove_id_keys(Dir),
+ ssh_test_lib:restore_known_hosts(Dir),
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config) -> Config
+%% Case - atom()
+%% Name of the test case that is about to be run.
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%%
+%% Description: Initialization before each test case
+%%
+%% Note: This function is free to add any key/value pairs to the Config
+%% variable, but should NOT alter/remove any existing entries.
+%% Description: Initialization before each test case
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ rename_known_hosts(backup),
+ ssh:start(),
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config) -> _
+%% Case - atom()
+%% Name of the test case that is about to be run.
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Description: Cleanup after each test case
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ssh:stop(),
+ rename_known_hosts(restore),
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: all(Clause) -> TestCases
+%% Clause - atom() - suite | doc
+%% TestCases - [Case]
+%% Case - atom()
+%% Name of a test case.
+%% Description: Returns a list of all test cases in this test suite
+%%--------------------------------------------------------------------
+all(doc) ->
+ ["Test ssh API"];
+
+all(suite) ->
+ [exec, exec_compressed, shell, daemon_allready_started,
+ server_password_option, server_userpassword_option, known_hosts].
+
+%% Test cases starts here.
+%%--------------------------------------------------------------------
+
+exec(doc) ->
+ ["Test api function ssh_connection:exec"];
+
+exec(suite) ->
+ [];
+
+exec(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ SystemDir = ?config(data_dir, Config),
+ Host = ssh_test_lib:hostname(),
+ Port = ssh_test_lib:inet_port(),
+ {ok, Pid} = ssh:daemon(Port, [{system_dir, SystemDir},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+ {ok, ConnectionRef} =
+ ssh:connect(Host, Port, [{silently_accept_hosts, true},
+ {user_interaction, false}]),
+ {ok, ChannelId0} = ssh_connection:session_channel(ConnectionRef, infinity),
+ success = ssh_connection:exec(ConnectionRef, ChannelId0,
+ "1+1.", infinity),
+ Data0 = {ssh_cm, ConnectionRef, {data, ChannelId0, 0, <<"2\n">>}},
+ case ssh_test_lib:receive_exec_result(Data0) of
+ expected ->
+ ok;
+ Other0 ->
+ test_server:fail(Other0)
+ end,
+ ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId0),
+
+ %% Test that it is possible to start a new channel and
+ %% run an other exec on the same connection.
+ {ok, ChannelId1} = ssh_connection:session_channel(ConnectionRef, infinity),
+ success = ssh_connection:exec(ConnectionRef, ChannelId1,
+ "2+2.", infinity),
+ Data1 = {ssh_cm, ConnectionRef, {data, ChannelId1, 0, <<"4\n">>}},
+ case ssh_test_lib:receive_exec_result(Data1) of
+ expected ->
+ ok;
+ Other1 ->
+ test_server:fail(Other1)
+ end,
+ ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId1),
+ ssh:stop_daemon(Pid).
+
+%%--------------------------------------------------------------------
+exec_compressed(doc) ->
+ ["Test that compression option works"];
+
+exec_compressed(suite) ->
+ [];
+
+exec_compressed(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ SystemDir = ?config(data_dir, Config),
+ Host = ssh_test_lib:hostname(),
+ Port = ssh_test_lib:inet_port(),
+ {ok, Pid} = ssh:daemon(Port, [{system_dir, SystemDir},
+ {compression, zlib},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+
+ {ok, ConnectionRef} =
+ ssh:connect(Host, Port, [{silently_accept_hosts, true},
+ {user_interaction, false}]),
+ {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity),
+ success = ssh_connection:exec(ConnectionRef, ChannelId,
+ "1+1.", infinity),
+ Data = {ssh_cm, ConnectionRef, {data, ChannelId, 0, <<"2\n">>}},
+ case ssh_test_lib:receive_exec_result(Data) of
+ expected ->
+ ok;
+ Other ->
+ test_server:fail(Other)
+ end,
+ ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId),
+ ssh:stop_daemon(Pid).
+
+%%--------------------------------------------------------------------
+
+shell(doc) ->
+ ["Test that ssh:shell/2 works"];
+
+shell(suite) ->
+ [];
+
+shell(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ SystemDir = ?config(data_dir, Config),
+ Port = ssh_test_lib:inet_port(),
+ {ok, _Pid} = ssh:daemon(Port, [{system_dir, SystemDir},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+ test_server:sleep(500),
+
+ IO = ssh_test_lib:start_io_server(),
+ Shell = ssh_test_lib:start_shell(Port, IO),
+ receive
+ ErlShellStart ->
+ test_server:format("Erlang shell start: ~p~n", [ErlShellStart])
+ end,
+ receive
+ ErlPrompt0 ->
+ test_server:format("Erlang prompt: ~p~n", [ErlPrompt0])
+ end,
+ IO ! {input, self(), "1+1.\r\n"},
+ receive
+ Echo0 ->
+ test_server:format("Echo: ~p ~n", [Echo0])
+ end,
+ receive
+ ?NEWLINE ->
+ ok
+ end,
+ receive
+ Result0 = <<"2">> ->
+ test_server:format("Result: ~p~n", [Result0])
+ end,
+ receive
+ ?NEWLINE ->
+ ok
+ end,
+ receive
+ ErlPrompt1 ->
+ test_server:format("Erlang prompt: ~p~n", [ErlPrompt1])
+ end,
+ exit(Shell, kill),
+ %% Does not seem to work in the testserver!
+ %% IO ! {input, self(), "q().\r\n"},
+ %% receive
+ %% ?NEWLINE ->
+ %% ok
+ %% end,
+ %% receive
+ %% Echo1 ->
+ %% test_server:format("Echo: ~p ~n", [Echo1])
+ %% end,
+ %% receive
+ %% ?NEWLINE ->
+ %% ok
+ %% end,
+ %% receive
+ %% Result1 ->
+ %% test_server:format("Result: ~p~n", [Result1])
+ %% end,
+ receive
+ {'EXIT', Shell, killed} ->
+ ok
+ end.
+
+%%--------------------------------------------------------------------
+daemon_allready_started(doc) ->
+ ["Test that get correct error message if you try to start a daemon",
+ "on an adress that allready runs a daemon see also seq10667" ];
+
+daemon_allready_started(suite) ->
+ [];
+
+daemon_allready_started(Config) when is_list(Config) ->
+ SystemDir = ?config(data_dir, Config),
+ Port = ssh_test_lib:inet_port(),
+ {ok, Pid} = ssh:daemon(Port, [{system_dir, SystemDir},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+ {error, eaddrinuse} = ssh:daemon(Port, [{system_dir, SystemDir},
+ {failfun,
+ fun ssh_test_lib:failfun/2}]),
+ ssh:stop_daemon(Pid).
+
+%%--------------------------------------------------------------------
+server_password_option(doc) ->
+ ["validate to server that uses the 'password' option"];
+server_password_option(suite) ->
+ [];
+server_password_option(Config) when is_list(Config) ->
+ UserDir = ?config(data_dir, Config), % to make sure we don't use
+ SysDir = ?config(data_dir, Config), % public-key-auth
+ Port = ssh_test_lib:inet_port(),
+ {ok, Pid} =
+ ssh:daemon(Port, [{system_dir, SysDir},
+ {password, "morot"}]),
+ Host = ssh_test_lib:hostname(),
+
+ {ok, ConnectionRef} =
+ ssh:connect(Host, Port, [{silently_accept_hosts, true},
+ {user, "foo"},
+ {password, "morot"},
+ {user_interaction, false},
+ {user_dir, UserDir}]),
+ {error, Reason} =
+ ssh:connect(Host, Port, [{silently_accept_hosts, true},
+ {user, "vego"},
+ {password, "foo"},
+ {user_interaction, false},
+ {user_dir, UserDir}]),
+
+ test_server:format("Test of wrong pasword: Error msg: ~p ~n", [Reason]),
+
+ ssh:close(ConnectionRef),
+ ssh:stop_daemon(Pid).
+
+%%--------------------------------------------------------------------
+
+server_userpassword_option(doc) ->
+ ["validate to server that uses the 'password' option"];
+server_userpassword_option(suite) ->
+ [];
+server_userpassword_option(Config) when is_list(Config) ->
+ UserDir = ?config(data_dir, Config), % to make sure we don't use
+ SysDir = ?config(data_dir, Config), % public-key-auth
+ Port = ssh_test_lib:inet_port(),
+ {ok, Pid} =
+ ssh:daemon(Port, [{system_dir, SysDir},
+ {user_passwords, [{"vego", "morot"}]}]),
+ Host = ssh_test_lib:hostname(),
+
+ {ok, ConnectionRef} =
+ ssh:connect(Host, Port, [{silently_accept_hosts, true},
+ {user, "vego"},
+ {password, "morot"},
+ {user_interaction, false},
+ {user_dir, UserDir}]),
+ ssh:close(ConnectionRef),
+
+ {error, Reason0} =
+ ssh:connect(Host, Port, [{silently_accept_hosts, true},
+ {user, "foo"},
+ {password, "morot"},
+ {user_interaction, false},
+ {user_dir, UserDir}]),
+
+ test_server:format("Test of user foo that does not exist. "
+ "Error msg: ~p ~n", [Reason0]),
+
+ {error, Reason1} =
+ ssh:connect(Host, Port, [{silently_accept_hosts, true},
+ {user, "vego"},
+ {password, "foo"},
+ {user_interaction, false},
+ {user_dir, UserDir}]),
+ test_server:format("Test of wrong Pasword. "
+ "Error msg: ~p ~n", [Reason1]),
+
+ ssh:stop_daemon(Pid).
+
+%%--------------------------------------------------------------------
+known_hosts(doc) ->
+ ["check that known_hosts is updated correctly"];
+known_hosts(suite) ->
+ [];
+known_hosts(Config) when is_list(Config) ->
+ SystemDir = ?config(data_dir, Config),
+ UserDir = ?config(priv_dir, Config),
+ Port = ssh_test_lib:inet_port(),
+
+ {ok, Pid} = ssh:daemon(Port, [{system_dir, SystemDir},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+
+ KnownHosts = filename:join(UserDir, "known_hosts"),
+ file:delete(KnownHosts),
+ {error, enoent} = file:read_file(KnownHosts),
+ Host = ssh_test_lib:hostname(),
+ {ok, ConnectionRef} =
+ ssh:connect(Host, Port, [{user_dir, UserDir},
+ {user_interaction, false},
+ silently_accept_hosts]),
+ {ok, _Channel} = ssh_connection:session_channel(ConnectionRef, infinity),
+ ok = ssh:close(ConnectionRef),
+ {ok, Binary} = file:read_file(KnownHosts),
+ Lines = string:tokens(binary_to_list(Binary), "\n"),
+ [Line] = Lines,
+ {ok, Hostname} = inet:gethostname(),
+ [HostAndIp, Alg, _KeyData] = string:tokens(Line, " "),
+ [Hostname, _Ip] = string:tokens(HostAndIp, ","),
+ "ssh-" ++ _ = Alg,
+ ssh:stop_daemon(Pid).
+
+%%--------------------------------------------------------------------
+%% Internal functions
+%%--------------------------------------------------------------------
+
+rename_known_hosts(BR) ->
+ KnownHosts = ssh_file:file_name(user, "known_hosts", []),
+ B = KnownHosts ++ "xxx",
+ case BR of
+ backup ->
+ file:rename(KnownHosts, B);
+ restore ->
+ file:delete(KnownHosts),
+ file:rename(B, KnownHosts)
+ end.