%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2018-2018. All Rights Reserved.
%%
%% 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
%%
%% 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%
%%
%%
-module(ssh_chan_behaviours_SUITE).
-include_lib("common_test/include/ct.hrl").
-include_lib("ssh/src/ssh.hrl").
-include("ssh_test_lib.hrl").
%% Note: This directive should only be used in test suites.
-compile(export_all).
%%--------------------------------------------------------------------
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
suite() ->
[{ct_hooks,[ts_install_cth]},
{timetrap,{seconds,60}}].
all() ->
[
noexist_subsystem,
undefined_subsystem,
defined_subsystem,
subsystem_client
].
%%--------------------------------------------------------------------
init_per_suite(Config) ->
?CHECK_CRYPTO(
begin
ssh:start(),
Config
end).
end_per_suite(_Config) ->
{Time,R} = timer:tc(ssh, stop, []),
ct:log("Stop ssh: ~p ms",[(100*(Time div 1000)) / 100]),
R.
init_per_testcase(_TC, Config) ->
SubSystems = [
{"bad_cb", {ssh_chan_behaviours_undefined, []}}, % A non-existing file
{"ch1", {ssh_chan_behaviours_server, [self(),true]}}
],
{Pid, Host, Port} = ssh_test_lib:std_daemon(Config, [{subsystems,SubSystems}]),
C = ssh_test_lib:std_connect(Config, Host, Port, []),
[{connref,C}, {daemon_pid,Pid}| Config].
end_per_testcase(_TC, Config) ->
{Time,_} = timer:tc(ssh, stop_daemon, [proplists:get_value(daemon_pid,Config)]),
ct:log("Stop daemon: ~p ms",[(100*(Time div 1000)) / 100]),
case flush() of
[] -> ok;
Msgs -> ct:pal("Unhandled messages:~n~p", [Msgs])
end.
-define(EXPECT(What, Bind),
Bind =
(fun() ->
receive What ->
ct:log("~p:~p ~p got ~p",[?MODULE,?LINE,self(),What]),
Bind
after 5000 ->
ct:log("~p:~p ~p Flushed:~n~p",[?MODULE,?LINE,self(),flush()]),
ct:fail("Timeout!",[])
end
end)()
).
%%--------------------------------------------------------------------
%% Test Cases --------------------------------------------------------
%%--------------------------------------------------------------------
%% Try start a subsystem whos name is not known by the server
noexist_subsystem(Config) ->
C = proplists:get_value(connref, Config),
{ok, Ch} = ssh_connection:session_channel(C, infinity),
failure = ssh_connection:subsystem(C, Ch, "noexist", infinity),
ok = ssh_connection:close(C, Ch),
?EXPECT({ssh_cm,C,{closed,Ch}},[]),
ok.
%% Try to start a subsystem with a known name, but without any callback file
undefined_subsystem(Config) ->
C = proplists:get_value(connref, Config),
{ok, Ch} = ssh_connection:session_channel(C, infinity),
failure = ssh_connection:subsystem(C, Ch, "bad_cb", infinity),
ok = ssh_connection:close(C, Ch),
?EXPECT({ssh_cm,C,{closed,Ch}},[]), % self() is instead of a proper channel handler
ok.
%% Try to start and stop a subsystem with known name and defined callback file
defined_subsystem(Config) ->
C = proplists:get_value(connref, Config),
{ok, Ch1} = ssh_connection:session_channel(C, infinity),
success = ssh_connection:subsystem(C, Ch1, "ch1", infinity),
IDsrv = ?EXPECT({{_Csrv,_Ch1srv}, {ssh_channel_up,_Ch1srv,_Csrv}}, {_Csrv,_Ch1srv}),
ok = ssh_connection:close(C, Ch1),
?EXPECT({IDsrv, {terminate,normal}}, []),
?EXPECT({ssh_cm, C, {closed,Ch1}}, []), % self() is instead of a proper channel handler
ok.
%% Try to start and stop a subsystem from a ssh_client_channel behviour
subsystem_client(Config) ->
C = proplists:get_value(connref, Config),
{ok,ChRef} = ssh_chan_behaviours_client:start_link(C),
IDclt = ?EXPECT({{C,Ch1clt}, {ssh_channel_up,Ch1clt,C}}, {C,Ch1clt}),
IDsrv = ?EXPECT({{_Csrv,Ch1srv}, {ssh_channel_up,Ch1srv,_Csrv}}, {_Csrv,Ch1srv}),
ok = ssh_chan_behaviours_client:stop(ChRef),
?EXPECT({IDclt, {terminate,normal}}, []), % From the proper channel handler
?EXPECT({IDsrv, {terminate,normal}}, []),
ok.
%%%================================================================
%%%
%%%
flush() -> lists:reverse(flush([])).
flush(Acc) ->
receive
M ->
flush([M|Acc])
after 0 ->
Acc
end.