aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssh/test/ssh_basic_SUITE.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssh/test/ssh_basic_SUITE.erl')
-rw-r--r--lib/ssh/test/ssh_basic_SUITE.erl994
1 files changed, 327 insertions, 667 deletions
diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl
index fa7b426545..51431da48e 100644
--- a/lib/ssh/test/ssh_basic_SUITE.erl
+++ b/lib/ssh/test/ssh_basic_SUITE.erl
@@ -3,16 +3,17 @@
%%
%% Copyright Ericsson AB 2008-2015. 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/.
+%% Licensed 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
%%
-%% 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.
+%% 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.
%%
%% %CopyrightEnd%
%%
@@ -23,9 +24,44 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/inet.hrl").
+-include_lib("kernel/include/file.hrl").
%% Note: This directive should only be used in test suites.
--compile(export_all).
+%%-compile(export_all).
+
+%%% Test cases
+-export([
+ app_test/1,
+ appup_test/1,
+ cli/1,
+ close/1,
+ daemon_already_started/1,
+ double_close/1,
+ exec/1,
+ exec_compressed/1,
+ idle_time/1,
+ inet6_option/1,
+ inet_option/1,
+ internal_error/1,
+ known_hosts/1,
+ misc_ssh_options/1,
+ openssh_zlib_basic_test/1,
+ packet_size_zero/1,
+ pass_phrase/1,
+ peername_sockname/1,
+ send/1,
+ shell/1,
+ shell_no_unicode/1,
+ shell_unicode_string/1,
+ ssh_info_print/1
+ ]).
+
+%%% Common test callbacks
+-export([suite/0, all/0, groups/0,
+ init_per_suite/1, end_per_suite/1,
+ init_per_group/2, end_per_group/2,
+ init_per_testcase/2, end_per_testcase/2
+ ]).
-define(NEWLINE, <<"\r\n">>).
@@ -45,22 +81,9 @@ all() ->
{group, rsa_pass_key},
{group, internal_error},
daemon_already_started,
- server_password_option,
- server_userpassword_option,
double_close,
- ssh_connect_timeout,
- ssh_connect_arg4_timeout,
packet_size_zero,
- ssh_daemon_minimal_remote_max_packet_size_option,
- ssh_msg_debug_fun_option_client,
- ssh_msg_debug_fun_option_server,
- id_string_no_opt_client,
- id_string_own_string_client,
- id_string_random_client,
- id_string_no_opt_server,
- id_string_own_string_server,
- id_string_random_server,
- {group, hardening_tests}
+ ssh_info_print
].
groups() ->
@@ -68,28 +91,22 @@ groups() ->
{rsa_key, [], basic_tests()},
{dsa_pass_key, [], [pass_phrase]},
{rsa_pass_key, [], [pass_phrase]},
- {internal_error, [], [internal_error]},
- {hardening_tests, [], [ssh_connect_nonegtimeout_connected_parallel,
- ssh_connect_nonegtimeout_connected_sequential,
- ssh_connect_negtimeout_parallel,
- ssh_connect_negtimeout_sequential,
- max_sessions_ssh_connect_parallel,
- max_sessions_ssh_connect_sequential,
- max_sessions_sftp_start_channel_parallel,
- max_sessions_sftp_start_channel_sequential
- ]}
+ {internal_error, [], [internal_error]}
].
basic_tests() ->
[send, close, peername_sockname,
- exec, exec_compressed, shell, cli, known_hosts,
- idle_time, rekey, openssh_zlib_basic_test,
- misc_ssh_options, inet_option].
+ exec, exec_compressed,
+ shell, shell_no_unicode, shell_unicode_string,
+ cli, known_hosts,
+ idle_time, openssh_zlib_basic_test,
+ misc_ssh_options, inet_option, inet6_option].
%%--------------------------------------------------------------------
init_per_suite(Config) ->
+ catch crypto:stop(),
case catch crypto:start() of
ok ->
Config;
@@ -128,6 +145,48 @@ init_per_group(internal_error, Config) ->
ssh_test_lib:setup_dsa(DataDir, PrivDir),
file:delete(filename:join(PrivDir, "system/ssh_host_dsa_key")),
Config;
+init_per_group(dir_options, Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ %% Make unreadable dir:
+ Dir_unreadable = filename:join(PrivDir, "unread"),
+ ok = file:make_dir(Dir_unreadable),
+ {ok,F1} = file:read_file_info(Dir_unreadable),
+ ok = file:write_file_info(Dir_unreadable,
+ F1#file_info{mode = F1#file_info.mode band (bnot 8#00444)}),
+ %% Make readable file:
+ File_readable = filename:join(PrivDir, "file"),
+ ok = file:write_file(File_readable, <<>>),
+
+ %% Check:
+ case {file:read_file_info(Dir_unreadable),
+ file:read_file_info(File_readable)} of
+ {{ok, Id=#file_info{type=directory, access=Md}},
+ {ok, If=#file_info{type=regular, access=Mf}}} ->
+ AccessOK =
+ case {Md, Mf} of
+ {read, _} -> false;
+ {read_write, _} -> false;
+ {_, read} -> true;
+ {_, read_write} -> true;
+ _ -> false
+ end,
+
+ case AccessOK of
+ true ->
+ %% Save:
+ [{unreadable_dir, Dir_unreadable},
+ {readable_file, File_readable}
+ | Config];
+ false ->
+ ct:log("File#file_info : ~p~n"
+ "Dir#file_info : ~p",[If,Id]),
+ {skip, "File or dir mode settings failed"}
+ end;
+
+ NotDirFile ->
+ ct:log("{Dir,File} -> ~p",[NotDirFile]),
+ {skip, "File/Dir creation failed"}
+ end;
init_per_group(_, Config) ->
Config.
@@ -157,6 +216,25 @@ end_per_group(internal_error, Config) ->
end_per_group(_, Config) ->
Config.
%%--------------------------------------------------------------------
+init_per_testcase(TC, Config) when TC==shell_no_unicode ;
+ TC==shell_unicode_string ->
+ PrivDir = ?config(priv_dir, Config),
+ UserDir = ?config(priv_dir, Config),
+ SysDir = ?config(data_dir, Config),
+ ssh:start(),
+ Sftpd = {_Pid, _Host, Port} =
+ ssh_test_lib:daemon([{system_dir, SysDir},
+ {user_dir, PrivDir},
+ {user_passwords, [{"foo", "bar"}]}]),
+ ct:sleep(500),
+ IO = ssh_test_lib:start_io_server(),
+ Shell = ssh_test_lib:start_shell(Port, IO, UserDir,
+ [{silently_accept_hosts, true},
+ {user,"foo"},{password,"bar"}]),
+ ct:log("IO=~p, Shell=~p, self()=~p",[IO,Shell,self()]),
+ ct:log("file:native_name_encoding() = ~p,~nio:getopts() = ~p",
+ [file:native_name_encoding(),io:getopts()]),
+ wait_for_erlang_first_line([{io,IO}, {shell,Shell}, {sftpd, Sftpd} | Config]);
init_per_testcase(_TestCase, Config) ->
ssh:start(),
Config.
@@ -166,6 +244,15 @@ end_per_testcase(TestCase, Config) when TestCase == server_password_option;
UserDir = filename:join(?config(priv_dir, Config), nopubkey),
ssh_test_lib:del_dirs(UserDir),
end_per_testcase(Config);
+end_per_testcase(TC, Config) when TC==shell_no_unicode ;
+ TC==shell_unicode_string ->
+ case ?config(sftpd, Config) of
+ {Pid, _, _} ->
+ ssh:stop_daemon(Pid),
+ ssh:stop();
+ _ ->
+ ssh:stop()
+ end;
end_per_testcase(_TestCase, Config) ->
end_per_testcase(Config).
end_per_testcase(_Config) ->
@@ -175,21 +262,18 @@ end_per_testcase(_Config) ->
%%--------------------------------------------------------------------
%% Test Cases --------------------------------------------------------
%%--------------------------------------------------------------------
-app_test() ->
- [{doc, "App lication consistency test."}].
+%%% Application consistency test.
app_test(Config) when is_list(Config) ->
?t:app_test(ssh),
ok.
%%--------------------------------------------------------------------
-appup_test() ->
- [{doc, "Appup file consistency test."}].
+%%% Appup file consistency test.
appup_test(Config) when is_list(Config) ->
ok = ?t:appup_test(ssh).
%%--------------------------------------------------------------------
-misc_ssh_options() ->
- [{doc, "Test that we can set some misc options not tested elsewhere, "
- "some options not yet present are not decided if we should support or "
- "if they need thier own test case."}].
+%%% Test that we can set some misc options not tested elsewhere
+%%% some options not yet present are not decided if we should support or
+%%% if they need thier own test case.
misc_ssh_options(Config) when is_list(Config) ->
SystemDir = filename:join(?config(priv_dir, Config), system),
UserDir = ?config(priv_dir, Config),
@@ -203,8 +287,7 @@ misc_ssh_options(Config) when is_list(Config) ->
basic_test([{client_opts, CMiscOpt1}, {server_opts, SMiscOpt1}]).
%%--------------------------------------------------------------------
-inet_option() ->
- [{doc, "Test configuring IPv4"}].
+%%% Test configuring IPv4
inet_option(Config) when is_list(Config) ->
SystemDir = filename:join(?config(priv_dir, Config), system),
UserDir = ?config(priv_dir, Config),
@@ -220,8 +303,7 @@ inet_option(Config) when is_list(Config) ->
{server_opts, [{inet, inet} | ServerOpts]}]).
%%--------------------------------------------------------------------
-inet6_option() ->
- [{doc, "Test configuring IPv6"}].
+%%% Test configuring IPv6
inet6_option(Config) when is_list(Config) ->
SystemDir = filename:join(?config(priv_dir, Config), system),
UserDir = ?config(priv_dir, Config),
@@ -237,8 +319,7 @@ inet6_option(Config) when is_list(Config) ->
{server_opts, [{inet, inet6} | ServerOpts]}]).
%%--------------------------------------------------------------------
-exec() ->
- [{doc, "Test api function ssh_connection:exec"}].
+%%% Test api function ssh_connection:exec
exec(Config) when is_list(Config) ->
process_flag(trap_exit, true),
SystemDir = filename:join(?config(priv_dir, Config), system),
@@ -279,15 +360,14 @@ exec(Config) when is_list(Config) ->
ssh:stop_daemon(Pid).
%%--------------------------------------------------------------------
-exec_compressed() ->
- [{doc, "Test that compression option works"}].
+%%% Test that compression option works
exec_compressed(Config) when is_list(Config) ->
process_flag(trap_exit, true),
SystemDir = filename:join(?config(priv_dir, Config), system),
UserDir = ?config(priv_dir, Config),
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},{user_dir, UserDir},
- {compression, zlib},
+ {preferred_algorithms,[{compression, [zlib]}]},
{failfun, fun ssh_test_lib:failfun/2}]),
ConnectionRef =
@@ -308,8 +388,7 @@ exec_compressed(Config) when is_list(Config) ->
ssh:stop_daemon(Pid).
%%--------------------------------------------------------------------
-idle_time() ->
- [{doc, "Idle timeout test"}].
+%%% Idle timeout test
idle_time(Config) ->
SystemDir = filename:join(?config(priv_dir, Config), system),
UserDir = ?config(priv_dir, Config),
@@ -329,31 +408,9 @@ idle_time(Config) ->
{error, closed} = ssh_connection:session_channel(ConnectionRef, 1000)
end,
ssh:stop_daemon(Pid).
-%%--------------------------------------------------------------------
-rekey() ->
- [{doc, "Idle timeout test"}].
-rekey(Config) ->
- SystemDir = filename:join(?config(priv_dir, Config), system),
- UserDir = ?config(priv_dir, Config),
- {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
- {user_dir, UserDir},
- {failfun, fun ssh_test_lib:failfun/2},
- {rekey_limit, 0}]),
- ConnectionRef =
- ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
- {user_dir, UserDir},
- {user_interaction, false},
- {rekey_limit, 0}]),
- receive
- after 200000 ->
- %%By this time rekeying would have been done
- ssh:close(ConnectionRef),
- ssh:stop_daemon(Pid)
- end.
%%--------------------------------------------------------------------
-shell() ->
- [{doc, "Test that ssh:shell/2 works"}].
+%%% Test that ssh:shell/2 works
shell(Config) when is_list(Config) ->
process_flag(trap_exit, true),
SystemDir = filename:join(?config(priv_dir, Config), system),
@@ -369,13 +426,11 @@ shell(Config) when is_list(Config) ->
{'EXIT', _, _} ->
ct:fail(no_ssh_connection);
ErlShellStart ->
- ct:pal("Erlang shell start: ~p~n", [ErlShellStart]),
+ ct:log("Erlang shell start: ~p~n", [ErlShellStart]),
do_shell(IO, Shell)
end.
%%--------------------------------------------------------------------
-cli() ->
- [{doc, ""}].
cli(Config) when is_list(Config) ->
process_flag(trap_exit, true),
SystemDir = filename:join(?config(priv_dir, Config), system),
@@ -409,9 +464,8 @@ cli(Config) when is_list(Config) ->
end.
%%--------------------------------------------------------------------
-daemon_already_started() ->
- [{doc, "Test that get correct error message if you try to start a daemon",
- "on an adress that already runs a daemon see also seq10667"}].
+%%% Test that get correct error message if you try to start a daemon
+%%% on an adress that already runs a daemon see also seq10667
daemon_already_started(Config) when is_list(Config) ->
SystemDir = ?config(data_dir, Config),
UserDir = ?config(priv_dir, Config),
@@ -426,166 +480,7 @@ daemon_already_started(Config) when is_list(Config) ->
ssh:stop_daemon(Pid).
%%--------------------------------------------------------------------
-server_password_option() ->
- [{doc, "validate to server that uses the 'password' option"}].
-server_password_option(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
- UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
- file:make_dir(UserDir),
- SysDir = ?config(data_dir, Config),
- {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
- {user_dir, UserDir},
- {password, "morot"}]),
-
- ConnectionRef =
- ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
- {user, "foo"},
- {password, "morot"},
- {user_interaction, false},
- {user_dir, UserDir}]),
-
- Reason = "Unable to connect using the available authentication methods",
-
- {error, Reason} =
- ssh:connect(Host, Port, [{silently_accept_hosts, true},
- {user, "vego"},
- {password, "foo"},
- {user_interaction, false},
- {user_dir, UserDir}]),
-
- ct:pal("Test of wrong password: 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(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
- UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
- file:make_dir(UserDir),
- SysDir = ?config(data_dir, Config),
- {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
- {user_dir, PrivDir},
- {user_passwords, [{"vego", "morot"}]}]),
-
- ConnectionRef =
- ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
- {user, "vego"},
- {password, "morot"},
- {user_interaction, false},
- {user_dir, UserDir}]),
- ssh:close(ConnectionRef),
-
- Reason = "Unable to connect using the available authentication methods",
-
- {error, Reason} =
- 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}]),
- ssh:stop_daemon(Pid).
-
-%%--------------------------------------------------------------------
-ssh_msg_debug_fun_option_client() ->
- [{doc, "validate client that uses the 'ssh_msg_debug_fun' option"}].
-ssh_msg_debug_fun_option_client(Config) ->
- PrivDir = ?config(priv_dir, Config),
- UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
- file:make_dir(UserDir),
- SysDir = ?config(data_dir, Config),
-
- {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
- {user_dir, UserDir},
- {password, "morot"},
- {failfun, fun ssh_test_lib:failfun/2}]),
- Parent = self(),
- DbgFun = fun(ConnRef,Displ,Msg,Lang) -> Parent ! {msg_dbg,{ConnRef,Displ,Msg,Lang}} end,
-
- ConnectionRef =
- ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
- {user, "foo"},
- {password, "morot"},
- {user_dir, UserDir},
- {user_interaction, false},
- {ssh_msg_debug_fun,DbgFun}]),
- %% Beware, implementation knowledge:
- gen_fsm:send_all_state_event(ConnectionRef,{ssh_msg_debug,false,<<"Hello">>,<<>>}),
- receive
- {msg_dbg,X={ConnectionRef,false,<<"Hello">>,<<>>}} ->
- ct:log("Got expected dbg msg ~p",[X]),
- ssh:stop_daemon(Pid);
- {msg_dbg,X={_,false,<<"Hello">>,<<>>}} ->
- ct:log("Got dbg msg but bad ConnectionRef (~p expected) ~p",[ConnectionRef,X]),
- ssh:stop_daemon(Pid),
- {fail, "Bad ConnectionRef received"};
- {msg_dbg,X} ->
- ct:log("Got bad dbg msg ~p",[X]),
- ssh:stop_daemon(Pid),
- {fail,"Bad msg received"}
- after 1000 ->
- ssh:stop_daemon(Pid),
- {fail,timeout}
- end.
-
-%%--------------------------------------------------------------------
-ssh_msg_debug_fun_option_server() ->
- [{doc, "validate client that uses the 'ssh_msg_debug_fun' option"}].
-ssh_msg_debug_fun_option_server(Config) ->
- PrivDir = ?config(priv_dir, Config),
- UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
- file:make_dir(UserDir),
- SysDir = ?config(data_dir, Config),
-
- Parent = self(),
- DbgFun = fun(ConnRef,Displ,Msg,Lang) -> Parent ! {msg_dbg,{ConnRef,Displ,Msg,Lang}} end,
- ConnFun = fun(_,_,_) -> Parent ! {connection_pid,self()} end,
-
- {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
- {user_dir, UserDir},
- {password, "morot"},
- {failfun, fun ssh_test_lib:failfun/2},
- {connectfun, ConnFun},
- {ssh_msg_debug_fun, DbgFun}]),
- _ConnectionRef =
- ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
- {user, "foo"},
- {password, "morot"},
- {user_dir, UserDir},
- {user_interaction, false}]),
- receive
- {connection_pid,Server} ->
- %% Beware, implementation knowledge:
- gen_fsm:send_all_state_event(Server,{ssh_msg_debug,false,<<"Hello">>,<<>>}),
- receive
- {msg_dbg,X={_,false,<<"Hello">>,<<>>}} ->
- ct:log("Got expected dbg msg ~p",[X]),
- ssh:stop_daemon(Pid);
- {msg_dbg,X} ->
- ct:log("Got bad dbg msg ~p",[X]),
- ssh:stop_daemon(Pid),
- {fail,"Bad msg received"}
- after 3000 ->
- ssh:stop_daemon(Pid),
- {fail,timeout2}
- end
- after 3000 ->
- ssh:stop_daemon(Pid),
- {fail,timeout1}
- end.
-
-%%--------------------------------------------------------------------
-known_hosts() ->
- [{doc, "check that known_hosts is updated correctly"}].
+%%% check that known_hosts is updated correctly
known_hosts(Config) when is_list(Config) ->
SystemDir = ?config(data_dir, Config),
PrivDir = ?config(priv_dir, Config),
@@ -611,8 +506,7 @@ known_hosts(Config) when is_list(Config) ->
ssh:stop_daemon(Pid).
%%--------------------------------------------------------------------
-pass_phrase() ->
- [{doc, "Test that we can use keyes protected by pass phrases"}].
+%%% Test that we can use keyes protected by pass phrases
pass_phrase(Config) when is_list(Config) ->
process_flag(trap_exit, true),
SystemDir = filename:join(?config(priv_dir, Config), system),
@@ -630,28 +524,26 @@ pass_phrase(Config) when is_list(Config) ->
{ok, _ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity),
ssh:stop_daemon(Pid).
-%%--------------------------------------------------------------------
-internal_error() ->
- [{doc,"Test that client does not hang if disconnects due to internal error"}].
+%%--------------------------------------------------------------------
+%%% Test that client does not hang if disconnects due to internal error
internal_error(Config) when is_list(Config) ->
process_flag(trap_exit, true),
SystemDir = filename:join(?config(priv_dir, Config), system),
UserDir = ?config(priv_dir, Config),
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
- {user_dir, UserDir},
- {failfun, fun ssh_test_lib:failfun/2}]),
+ {user_dir, UserDir},
+ {failfun, fun ssh_test_lib:failfun/2}]),
{error, Error} =
- ssh:connect(Host, Port, [{silently_accept_hosts, true},
- {user_dir, UserDir},
- {user_interaction, false}]),
+ ssh:connect(Host, Port, [{silently_accept_hosts, true},
+ {user_dir, UserDir},
+ {user_interaction, false}]),
check_error(Error),
ssh:stop_daemon(Pid).
%%--------------------------------------------------------------------
-send() ->
- [{doc, "Test ssh_connection:send/3"}].
+%%% Test ssh_connection:send/3
send(Config) when is_list(Config) ->
process_flag(trap_exit, true),
SystemDir = filename:join(?config(priv_dir, Config), system),
@@ -671,8 +563,7 @@ send(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
-peername_sockname() ->
- [{doc, "Test ssh:connection_info([peername, sockname])"}].
+%%% Test ssh:connection_info([peername, sockname])
peername_sockname(Config) when is_list(Config) ->
process_flag(trap_exit, true),
SystemDir = filename:join(?config(priv_dir, Config), system),
@@ -694,13 +585,13 @@ peername_sockname(Config) when is_list(Config) ->
ssh:connection_info(ConnectionRef, [peer]),
[{sockname, {HostSockClient,PortSockClient} = ClientSock}] =
ssh:connection_info(ConnectionRef, [sockname]),
- ct:pal("Client: ~p ~p", [ClientPeer, ClientSock]),
+ ct:log("Client: ~p ~p", [ClientPeer, ClientSock]),
receive
{ssh_cm, ConnectionRef, {data, ChannelId, _, Response}} ->
{PeerNameSrv,SockNameSrv} = binary_to_term(Response),
{HostPeerSrv,PortPeerSrv} = PeerNameSrv,
{HostSockSrv,PortSockSrv} = SockNameSrv,
- ct:pal("Server: ~p ~p", [PeerNameSrv, SockNameSrv]),
+ ct:log("Server: ~p ~p", [PeerNameSrv, SockNameSrv]),
host_equal(HostPeerSrv, HostSockClient),
PortPeerSrv = PortSockClient,
host_equal(HostSockSrv, HostPeerClient),
@@ -722,8 +613,7 @@ ips(Name) when is_list(Name) ->
%%--------------------------------------------------------------------
-close() ->
- [{doc, "Client receives close when server closes"}].
+%%% Client receives close when server closes
close(Config) when is_list(Config) ->
process_flag(trap_exit, true),
SystemDir = filename:join(?config(priv_dir, Config), system),
@@ -747,8 +637,7 @@ close(Config) when is_list(Config) ->
end.
%%--------------------------------------------------------------------
-double_close() ->
- [{doc, "Simulate that we try to close an already closed connection"}].
+%%% Simulate that we try to close an already closed connection
double_close(Config) when is_list(Config) ->
SystemDir = ?config(data_dir, Config),
PrivDir = ?config(priv_dir, Config),
@@ -769,92 +658,6 @@ double_close(Config) when is_list(Config) ->
ok = ssh:close(CM).
%%--------------------------------------------------------------------
-ssh_connect_timeout() ->
- [{doc, "Test connect_timeout option in ssh:connect/4"}].
-ssh_connect_timeout(_Config) ->
- ConnTimeout = 2000,
- {error,{faked_transport,connect,TimeoutToTransport}} =
- ssh:connect("localhost", 12345,
- [{transport,{tcp,?MODULE,tcp_closed}},
- {connect_timeout,ConnTimeout}],
- 1000),
- case TimeoutToTransport of
- ConnTimeout -> ok;
- Other ->
- ct:log("connect_timeout is ~p but transport received ~p",[ConnTimeout,Other]),
- {fail,"ssh:connect/4 wrong connect_timeout received in transport"}
- end.
-
-%% Help for the test above
-connect(_Host, _Port, _Opts, Timeout) ->
- {error, {faked_transport,connect,Timeout}}.
-
-
-%%--------------------------------------------------------------------
-ssh_connect_arg4_timeout() ->
- [{doc, "Test fourth argument in ssh:connect/4"}].
-ssh_connect_arg4_timeout(_Config) ->
- Timeout = 1000,
- Parent = self(),
- %% start the server
- Server = spawn(fun() ->
- {ok,Sl} = gen_tcp:listen(0,[]),
- {ok,{_,Port}} = inet:sockname(Sl),
- Parent ! {port,self(),Port},
- Rsa = gen_tcp:accept(Sl),
- ct:log("Server gen_tcp:accept got ~p",[Rsa]),
- receive after 2*Timeout -> ok end %% let client timeout first
- end),
-
- %% Get listening port
- Port = receive
- {port,Server,ServerPort} -> ServerPort
- end,
-
- %% try to connect with a timeout, but "supervise" it
- Client = spawn(fun() ->
- T0 = now(),
- Rc = ssh:connect("localhost",Port,[],Timeout),
- ct:log("Client ssh:connect got ~p",[Rc]),
- Parent ! {done,self(),Rc,T0}
- end),
-
- %% Wait for client reaction on the connection try:
- receive
- {done, Client, {error,timeout}, T0} ->
- Msp = ms_passed(T0, now()),
- exit(Server,hasta_la_vista___baby),
- Low = 0.9*Timeout,
- High = 1.1*Timeout,
- ct:log("Timeout limits: ~.4f - ~.4f ms, timeout "
- "was ~.4f ms, expected ~p ms",[Low,High,Msp,Timeout]),
- %%ct:log("Timeout limits: ~p--~p, my timeout was ~p, expected ~p",[Low,High,Msp0,Timeout]),
- if
- Low<Msp, Msp<High -> ok;
- true -> {fail, "timeout not within limits"}
- end;
-
- {done, Client, {error,Other}, _T0} ->
- ct:log("Error message \"~p\" from the client is unexpected.",[{error,Other}]),
- {fail, "Unexpected error message"};
-
- {done, Client, {ok,_Ref}, _T0} ->
- {fail,"ssh-connected ???"}
- after
- 5000 ->
- exit(Server,hasta_la_vista___baby),
- exit(Client,hasta_la_vista___baby),
- {fail, "Didn't timeout"}
- end.
-
-%% Help function
-%% N2-N1
-ms_passed(N1={_,_,M1}, N2={_,_,M2}) ->
- {0,{0,Min,Sec}} = calendar:time_difference(calendar:now_to_local_time(N1),
- calendar:now_to_local_time(N2)),
- 1000 * (Min*60 + Sec + (M2-M1)/1000000).
-
-%%--------------------------------------------------------------------
packet_size_zero(Config) ->
SystemDir = ?config(data_dir, Config),
PrivDir = ?config(priv_dir, Config),
@@ -879,317 +682,128 @@ packet_size_zero(Config) ->
receive
{ssh_cm,Conn,{data,Chan,_Type,_Msg1}} = M ->
- ct:pal("Got ~p",[M]),
+ ct:log("Got ~p",[M]),
ct:fail(doesnt_obey_max_packet_size_0)
after 5000 ->
ok
end.
%%--------------------------------------------------------------------
-ssh_daemon_minimal_remote_max_packet_size_option(Config) ->
- SystemDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
- UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
- file:make_dir(UserDir),
-
- {Server, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
- {user_dir, UserDir},
- {user_passwords, [{"vego", "morot"}]},
- {failfun, fun ssh_test_lib:failfun/2},
- {minimal_remote_max_packet_size, 14}]),
- Conn =
- ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
- {user_dir, UserDir},
- {user_interaction, false},
- {user, "vego"},
- {password, "morot"}]),
-
- %% Try the limits of the minimal_remote_max_packet_size:
- {ok, _ChannelId} = ssh_connection:session_channel(Conn, 100, 14, infinity),
- {open_error,_,"Maximum packet size below 14 not supported",_} =
- ssh_connection:session_channel(Conn, 100, 13, infinity),
-
- ssh:close(Conn),
- ssh:stop_daemon(Server).
-
-%%--------------------------------------------------------------------
-id_string_no_opt_client(Config) ->
- {Server, Host, Port} = fake_daemon(Config),
- {error,_} = ssh:connect(Host, Port, []),
- receive
- {id,Server,"SSH-2.0-Erlang/"++Vsn} ->
- true = expected_ssh_vsn(Vsn);
- {id,Server,Other} ->
- ct:fail("Unexpected id: ~s.",[Other])
- end.
-
-%%--------------------------------------------------------------------
-id_string_own_string_client(Config) ->
- {Server, Host, Port} = fake_daemon(Config),
- {error,_} = ssh:connect(Host, Port, [{id_string,"Pelle"}]),
- receive
- {id,Server,"SSH-2.0-Pelle\r\n"} ->
- ok;
- {id,Server,Other} ->
- ct:fail("Unexpected id: ~s.",[Other])
- end.
-
-%%--------------------------------------------------------------------
-id_string_random_client(Config) ->
- {Server, Host, Port} = fake_daemon(Config),
- {error,_} = ssh:connect(Host, Port, [{id_string,random}]),
- receive
- {id,Server,Id="SSH-2.0-Erlang"++_} ->
- ct:fail("Unexpected id: ~s.",[Id]);
- {id,Server,Rnd="SSH-2.0-"++_} ->
- ct:log("Got ~s.",[Rnd]);
- {id,Server,Id} ->
- ct:fail("Unexpected id: ~s.",[Id])
- end.
-
-%%--------------------------------------------------------------------
-id_string_no_opt_server(Config) ->
- {_Server, Host, Port} = std_daemon(Config, []),
- {ok,S1}=gen_tcp:connect(Host,Port,[{active,false}]),
- {ok,"SSH-2.0-Erlang/"++Vsn} = gen_tcp:recv(S1, 0, 2000),
- true = expected_ssh_vsn(Vsn).
-
-%%--------------------------------------------------------------------
-id_string_own_string_server(Config) ->
- {_Server, Host, Port} = std_daemon(Config, [{id_string,"Olle"}]),
- {ok,S1}=gen_tcp:connect(Host,Port,[{active,false}]),
- {ok,"SSH-2.0-Olle\r\n"} = gen_tcp:recv(S1, 0, 2000).
-
-%%--------------------------------------------------------------------
-id_string_random_server(Config) ->
- {_Server, Host, Port} = std_daemon(Config, [{id_string,random}]),
- {ok,S1}=gen_tcp:connect(Host,Port,[{active,false}]),
- {ok,"SSH-2.0-"++Rnd} = gen_tcp:recv(S1, 0, 2000),
- case Rnd of
- "Erlang"++_ -> ct:log("Id=~p",[Rnd]),
- {fail,got_default_id};
- "Olle\r\n" -> {fail,got_previous_tests_value};
- _ -> ct:log("Got ~s.",[Rnd])
- end.
-
+shell_no_unicode(Config) ->
+ new_do_shell(?config(io,Config),
+ [new_prompt,
+ {type,"io:format(\"hej ~p~n\",[42])."},
+ {expect,"hej 42"}
+ ]).
+
%%--------------------------------------------------------------------
-ssh_connect_negtimeout_parallel(Config) -> ssh_connect_negtimeout(Config,true).
-ssh_connect_negtimeout_sequential(Config) -> ssh_connect_negtimeout(Config,false).
-
-ssh_connect_negtimeout(Config, Parallel) ->
- process_flag(trap_exit, true),
- SystemDir = filename:join(?config(priv_dir, Config), system),
- UserDir = ?config(priv_dir, Config),
- NegTimeOut = 2000, % ms
- ct:log("Parallel: ~p",[Parallel]),
-
- {_Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},{user_dir, UserDir},
- {parallel_login, Parallel},
- {negotiation_timeout, NegTimeOut},
- {failfun, fun ssh_test_lib:failfun/2}]),
-
- {ok,Socket} = gen_tcp:connect(Host, Port, []),
- ct:pal("And now sleeping 1.2*NegTimeOut (~p ms)...", [round(1.2 * NegTimeOut)]),
- receive after round(1.2 * NegTimeOut) -> ok end,
-
- case inet:sockname(Socket) of
- {ok,_} -> ct:fail("Socket not closed");
- {error,_} -> ok
- end.
+shell_unicode_string(Config) ->
+ new_do_shell(?config(io,Config),
+ [new_prompt,
+ {type,"io:format(\"こにちわ~ts~n\",[\"四二\"])."},
+ {expect,"こにちわ四二"},
+ {expect,"ok"}
+ ]).
%%--------------------------------------------------------------------
-ssh_connect_nonegtimeout_connected_parallel() ->
- [{doc, "Test that ssh connection does not timeout if the connection is established (parallel)"}].
-ssh_connect_nonegtimeout_connected_parallel(Config) ->
- ssh_connect_nonegtimeout_connected(Config, true).
-
-ssh_connect_nonegtimeout_connected_sequential() ->
- [{doc, "Test that ssh connection does not timeout if the connection is established (non-parallel)"}].
-ssh_connect_nonegtimeout_connected_sequential(Config) ->
- ssh_connect_nonegtimeout_connected(Config, false).
-
-
-ssh_connect_nonegtimeout_connected(Config, Parallel) ->
- process_flag(trap_exit, true),
- SystemDir = filename:join(?config(priv_dir, Config), system),
- UserDir = ?config(priv_dir, Config),
- NegTimeOut = 20000, % ms
- ct:log("Parallel: ~p",[Parallel]),
-
- {_Pid, _Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},{user_dir, UserDir},
- {parallel_login, Parallel},
- {negotiation_timeout, NegTimeOut},
- {failfun, fun ssh_test_lib:failfun/2}]),
- ct:pal("~p Listen ~p:~p",[_Pid,_Host,Port]),
- ct:sleep(500),
-
- IO = ssh_test_lib:start_io_server(),
- Shell = ssh_test_lib:start_shell(Port, IO, UserDir),
- receive
- Error = {'EXIT', _, _} ->
- ct:pal("~p",[Error]),
- ct:fail(no_ssh_connection);
- ErlShellStart ->
- ct:pal("---Erlang shell start: ~p~n", [ErlShellStart]),
- one_shell_op(IO, NegTimeOut),
- one_shell_op(IO, NegTimeOut),
- ct:pal("And now sleeping 1.2*NegTimeOut (~p ms)...", [round(1.2 * NegTimeOut)]),
- receive after round(1.2 * NegTimeOut) -> ok end,
- one_shell_op(IO, NegTimeOut)
- end,
- exit(Shell, kill).
-
-
-one_shell_op(IO, TimeOut) ->
- ct:pal("One shell op: Waiting for prompter"),
- receive
- ErlPrompt0 -> ct:log("Erlang prompt: ~p~n", [ErlPrompt0])
- after TimeOut -> ct:fail("Timeout waiting for promter")
- end,
-
- IO ! {input, self(), "2*3*7.\r\n"},
- receive
- Echo0 -> ct:log("Echo: ~p ~n", [Echo0])
- after TimeOut -> ct:fail("Timeout waiting for echo")
- end,
-
- receive
- ?NEWLINE -> ct:log("NEWLINE received", [])
- after TimeOut ->
- receive Any1 -> ct:log("Bad NEWLINE: ~p",[Any1])
- after 0 -> ct:fail("Timeout waiting for NEWLINE")
- end
- end,
-
- receive
- Result0 -> ct:log("Result: ~p~n", [Result0])
- after TimeOut -> ct:fail("Timeout waiting for result")
- end.
-
-%%--------------------------------------------------------------------
-
-openssh_zlib_basic_test() ->
- [{doc, "Test basic connection with openssh_zlib"}].
+%%% Test basic connection with openssh_zlib
openssh_zlib_basic_test(Config) ->
SystemDir = filename:join(?config(priv_dir, Config), system),
UserDir = ?config(priv_dir, Config),
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
{user_dir, UserDir},
+ {preferred_algorithms,[{compression, ['[email protected]']}]},
{failfun, fun ssh_test_lib:failfun/2}]),
ConnectionRef =
ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
{user_dir, UserDir},
{user_interaction, false},
- {compression, openssh_zlib}]),
+ {preferred_algorithms,[{compression, ['[email protected]',
+ none]}]}
+ ]),
ok = ssh:close(ConnectionRef),
ssh:stop_daemon(Pid).
%%--------------------------------------------------------------------
+ssh_info_print(Config) ->
+ %% Just check that ssh_print:info() crashes
+ PrivDir = ?config(priv_dir, Config),
+ PrintFile = filename:join(PrivDir,info),
+ UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
+ file:make_dir(UserDir),
+ SysDir = ?config(data_dir, Config),
-max_sessions_ssh_connect_parallel(Config) ->
- max_sessions(Config, true, connect_fun(ssh__connect,Config)).
-max_sessions_ssh_connect_sequential(Config) ->
- max_sessions(Config, false, connect_fun(ssh__connect,Config)).
-
-max_sessions_sftp_start_channel_parallel(Config) ->
- max_sessions(Config, true, connect_fun(ssh_sftp__start_channel, Config)).
-max_sessions_sftp_start_channel_sequential(Config) ->
- max_sessions(Config, false, connect_fun(ssh_sftp__start_channel, Config)).
-
-
-%%%---- helpers:
-connect_fun(ssh__connect, Config) ->
- fun(Host,Port) ->
- ssh_test_lib:connect(Host, Port,
- [{silently_accept_hosts, true},
- {user_dir, ?config(priv_dir,Config)},
- {user_interaction, false},
- {user, "carni"},
- {password, "meat"}
- ])
- %% ssh_test_lib returns R when ssh:connect returns {ok,R}
- end;
-connect_fun(ssh_sftp__start_channel, _Config) ->
- fun(Host,Port) ->
- {ok,_Pid,ConnRef} =
- ssh_sftp:start_channel(Host, Port,
- [{silently_accept_hosts, true},
- {user, "carni"},
- {password, "meat"}
- ]),
- ConnRef
- end.
+ Parent = self(),
+ UnexpFun = fun(Msg,_Peer) ->
+ Parent ! {unexpected,Msg,self()},
+ skip
+ end,
+ ConnFun = fun(_,_,_) -> Parent ! {connect,self()} end,
+
+ {DaemonRef, Host, Port} =
+ ssh_test_lib:daemon([{system_dir, SysDir},
+ {user_dir, UserDir},
+ {password, "morot"},
+ {unexpectedfun, UnexpFun},
+ {connectfun, ConnFun},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+ ClientConnRef1 =
+ ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ {user, "foo"},
+ {password, "morot"},
+ {user_dir, UserDir},
+ {unexpectedfun, UnexpFun},
+ {user_interaction, false}]),
+ ClientConnRef2 =
+ ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ {user, "foo"},
+ {password, "morot"},
+ {user_dir, UserDir},
+ {unexpectedfun, UnexpFun},
+ {user_interaction, false}]),
+ receive
+ {connect,DaemonConnRef} ->
+ ct:log("DaemonRef=~p, DaemonConnRef=~p, ClientConnRefs=~p",[DaemonRef, DaemonConnRef,
+ [ClientConnRef1,ClientConnRef2]
+ ])
+ after 2000 ->
+ ok
+ end,
+ {ok,D} = file:open(PrintFile, write),
+ ssh_info:print(D),
+ ok = file:close(D),
-max_sessions(Config, ParallelLogin, Connect0) when is_function(Connect0,2) ->
- Connect = fun(Host,Port) ->
- R = Connect0(Host,Port),
- ct:pal("Connect(~p,~p) -> ~p",[Host,Port,R]),
- R
- end,
- SystemDir = filename:join(?config(priv_dir, Config), system),
- UserDir = ?config(priv_dir, Config),
- MaxSessions = 5,
- {Pid, Host, Port} = ssh_test_lib:daemon([
- {system_dir, SystemDir},
- {user_dir, UserDir},
- {user_passwords, [{"carni", "meat"}]},
- {parallel_login, ParallelLogin},
- {max_sessions, MaxSessions}
- ]),
- ct:pal("~p Listen ~p:~p for max ~p sessions",[Pid,Host,Port,MaxSessions]),
- try [Connect(Host,Port) || _ <- lists:seq(1,MaxSessions)]
- of
- Connections ->
- %% Step 1 ok: could set up max_sessions connections
- ct:log("Connections up: ~p",[Connections]),
- [_|_] = Connections,
-
- %% Now try one more than alowed:
- ct:pal("Info Report might come here...",[]),
- try Connect(Host,Port)
- of
- _ConnectionRef1 ->
- ssh:stop_daemon(Pid),
- {fail,"Too many connections accepted"}
- catch
- error:{badmatch,{error,"Connection closed"}} ->
- %% Step 2 ok: could not set up max_sessions+1 connections
- %% This is expected
- %% Now stop one connection and try to open one more
- ok = ssh:close(hd(Connections)),
- try Connect(Host,Port)
- of
- _ConnectionRef1 ->
- %% Step 3 ok: could set up one more connection after killing one
- %% Thats good.
- ssh:stop_daemon(Pid),
- ok
- catch
- error:{badmatch,{error,"Connection closed"}} ->
- %% Bad indeed. Could not set up one more connection even after killing
- %% one existing. Very bad.
- ssh:stop_daemon(Pid),
- {fail,"Does not decrease # active sessions"}
- end
- end
- catch
- error:{badmatch,{error,"Connection closed"}} ->
- ssh:stop_daemon(Pid),
- {fail,"Too few connections accepted"}
+ {ok,Bin} = file:read_file(PrintFile),
+ ct:log("~s",[Bin]),
+
+ receive
+ {unexpected, Msg, Pid} ->
+ ct:log("~p got unexpected msg ~p",[Pid,Msg]),
+ ct:log("process_info(~p) = ~n~p",[Pid,process_info(Pid)]),
+ ok = ssh:close(ClientConnRef1),
+ ok = ssh:close(ClientConnRef2),
+ ok = ssh:stop_daemon(DaemonRef),
+ {fail,"unexpected msg"}
+ after 1000 ->
+ ok = ssh:close(ClientConnRef1),
+ ok = ssh:close(ClientConnRef2),
+ ok = ssh:stop_daemon(DaemonRef)
end.
+
%%--------------------------------------------------------------------
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
-
%% Due to timing the error message may or may not be delivered to
%% the "tcp-application" before the socket closed message is recived
check_error("Invalid state") ->
ok;
check_error("Connection closed") ->
ok;
+check_error("Selection of key exchange algorithm failed") ->
+ ok;
check_error(Error) ->
ct:fail(Error).
@@ -1205,12 +819,12 @@ basic_test(Config) ->
do_shell(IO, Shell) ->
receive
ErlPrompt0 ->
- ct:pal("Erlang prompt: ~p~n", [ErlPrompt0])
+ ct:log("Erlang prompt: ~p~n", [ErlPrompt0])
end,
IO ! {input, self(), "1+1.\r\n"},
receive
Echo0 ->
- ct:pal("Echo: ~p ~n", [Echo0])
+ ct:log("Echo: ~p ~n", [Echo0])
end,
receive
?NEWLINE ->
@@ -1218,7 +832,7 @@ do_shell(IO, Shell) ->
end,
receive
Result0 = <<"2">> ->
- ct:pal("Result: ~p~n", [Result0])
+ ct:log("Result: ~p~n", [Result0])
end,
receive
?NEWLINE ->
@@ -1226,7 +840,7 @@ do_shell(IO, Shell) ->
end,
receive
ErlPrompt1 ->
- ct:pal("Erlang prompt: ~p~n", [ErlPrompt1])
+ ct:log("Erlang prompt: ~p~n", [ErlPrompt1])
end,
exit(Shell, kill).
%%Does not seem to work in the testserver!
@@ -1237,7 +851,7 @@ do_shell(IO, Shell) ->
%% end,
%% receive
%% Echo1 ->
- %% ct:pal("Echo: ~p ~n", [Echo1])
+ %% ct:log("Echo: ~p ~n", [Echo1])
%% end,
%% receive
%% ?NEWLINE ->
@@ -1245,7 +859,7 @@ do_shell(IO, Shell) ->
%% end,
%% receive
%% Result1 ->
- %% ct:pal("Result: ~p~n", [Result1])
+ %% ct:log("Result: ~p~n", [Result1])
%% end,
%% receive
%% {'EXIT', Shell, killed} ->
@@ -1253,44 +867,90 @@ do_shell(IO, Shell) ->
%% end.
-std_daemon(Config, ExtraOpts) ->
- SystemDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
- UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
- file:make_dir(UserDir),
- {_Server, _Host, _Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
- {user_dir, UserDir},
- {failfun, fun ssh_test_lib:failfun/2} | ExtraOpts]).
-
-expected_ssh_vsn(Str) ->
- try
- {ok,L} = application:get_all_key(ssh),
- proplists:get_value(vsn,L,"")++"\r\n"
- of
- Str -> true;
- "\r\n" -> true;
- _ -> false
- catch
- _:_ -> true %% ssh not started so we dont't know
+%%--------------------------------------------------------------------
+wait_for_erlang_first_line(Config) ->
+ receive
+ {'EXIT', _, _} ->
+ {fail,no_ssh_connection};
+ <<"Eshell ",_/binary>> = _ErlShellStart ->
+ ct:log("Erlang shell start: ~p~n", [_ErlShellStart]),
+ Config;
+ Other ->
+ ct:log("Unexpected answer from ssh server: ~p",[Other]),
+ {fail,unexpected_answer}
+ after 10000 ->
+ ct:log("No answer from ssh-server"),
+ {fail,timeout}
end.
-
-
-fake_daemon(_Config) ->
- Parent = self(),
- %% start the server
- Server = spawn(fun() ->
- {ok,Sl} = gen_tcp:listen(0,[]),
- {ok,{Host,Port}} = inet:sockname(Sl),
- Parent ! {sockname,self(),Host,Port},
- Rsa = gen_tcp:accept(Sl),
- ct:log("Server gen_tcp:accept got ~p",[Rsa]),
- {ok,S} = Rsa,
- receive
- {tcp, S, Id} -> Parent ! {id,self(),Id}
- end
- end),
- %% Get listening host and port
+
+
+
+new_do_shell(IO, List) -> new_do_shell(IO, 0, List).
+
+new_do_shell(IO, N, [new_prompt|More]) ->
+ new_do_shell(IO, N+1, More);
+
+new_do_shell(IO, N, Ops=[{Order,Arg}|More]) ->
+ Pfx = prompt_prefix(),
+ PfxSize = size(Pfx),
receive
- {sockname,Server,ServerHost,ServerPort} -> {Server, ServerHost, ServerPort}
+ _X = <<"\r\n">> ->
+ ct:log("Skip newline ~p",[_X]),
+ new_do_shell(IO, N, Ops);
+
+ <<Pfx:PfxSize/binary,P1,"> ">> when (P1-$0)==N ->
+ new_do_shell_prompt(IO, N, Order, Arg, More);
+
+ <<Pfx:PfxSize/binary,P1,P2,"> ">> when (P1-$0)*10 + (P2-$0) == N ->
+ new_do_shell_prompt(IO, N, Order, Arg, More);
+
+ <<Pfx:PfxSize/binary,P1,P2,P3,"> ">> when (P1-$0)*100 + (P2-$0)*10 + (P3-$0) == N ->
+ new_do_shell_prompt(IO, N, Order, Arg, More);
+
+ Err when element(1,Err)==error ->
+ ct:fail("new_do_shell error: ~p~n",[Err]);
+
+ RecBin when Order==expect ; Order==expect_echo ->
+ ct:log("received ~p",[RecBin]),
+ RecStr = string:strip(unicode:characters_to_list(RecBin)),
+ ExpStr = string:strip(Arg),
+ case lists:prefix(ExpStr, RecStr) of
+ true when Order==expect ->
+ ct:log("Matched ~ts",[RecStr]),
+ new_do_shell(IO, N, More);
+ true when Order==expect_echo ->
+ ct:log("Matched echo ~ts",[RecStr]),
+ new_do_shell(IO, N, More);
+ false ->
+ ct:fail("*** Expected ~p, but got ~p",[string:strip(ExpStr),RecStr])
+ end
+ after 30000 ->
+ ct:log("Meassage queue of ~p:~n~p",
+ [self(), erlang:process_info(self(), messages)]),
+ case Order of
+ expect -> ct:fail("timeout, expected ~p",[string:strip(Arg)]);
+ type -> ct:fail("timeout, no prompt")
+ end
+ end;
+
+new_do_shell(_, _, []) ->
+ ok.
+
+prompt_prefix() ->
+ case node() of
+ nonode@nohost -> <<>>;
+ Node -> list_to_binary(
+ lists:concat(["(",Node,")"]))
end.
+
+new_do_shell_prompt(IO, N, type, Str, More) ->
+ ct:log("Matched prompt ~p to trigger sending of next line to server",[N]),
+ IO ! {input, self(), Str++"\r\n"},
+ ct:log("Promt '~p> ', Sent ~ts",[N,Str++"\r\n"]),
+ new_do_shell(IO, N, [{expect_echo,Str}|More]); % expect echo of the sent line
+new_do_shell_prompt(IO, N, Op, Str, More) ->
+ ct:log("Matched prompt ~p",[N]),
+ new_do_shell(IO, N, [{Op,Str}|More]).
+
+%%--------------------------------------------------------------------