aboutsummaryrefslogblamecommitdiffstats
path: root/lib/ssh/test/ssh_upgrade_SUITE.erl
blob: 861c7ab3dd1f0b882d99c85c178be53157c6ed77 (plain) (tree)













































































































































































































                                                                                                                     
%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2014-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/.2
%%
%% 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_upgrade_SUITE).

%% Note: This directive should only be used in test suites.
-compile(export_all).

-include_lib("common_test/include/ct.hrl").

-record(state, {
	  config,
	  root_dir,
	  server,
	  client,
	  connection,
	  soft
	 }).


%%%================================================================
%%%
%%% CommonTest callbacks
%%% 
all() -> 
    [
     minor_upgrade,
     major_upgrade
    ].

init_per_suite(Config0) ->
    catch crypto:stop(),
    try {crypto:start(), erlang:system_info({wordsize, internal}) == 
                 	     erlang:system_info({wordsize, external})} of
	{ok, true} ->
	    case ct_release_test:init(Config0) of
		{skip, Reason} ->
		    {skip, Reason};
		Config ->
		    ssh:start(),
		    Config
	    end;
	{ok, false} ->
	    {skip, "Test server will not handle halfwordemulator correctly. Skip as halfwordemulator is deprecated"} 
    catch _:_ ->
	    {skip, "Crypto did not start"}
    end.

end_per_suite(Config) ->
    ct_release_test:cleanup(Config),
    ssh:stop(),
    crypto:stop(),
    UserDir = ?config(priv_dir, Config),
    ssh_test_lib:clean_rsa(UserDir).

init_per_testcase(_TestCase, Config) ->
    Config.
end_per_testcase(_TestCase, Config) ->
    Config.

%%%================================================================
%%%
%%% Test cases
%%% 
major_upgrade(Config) when is_list(Config) ->
    ct_release_test:upgrade(ssh, major,{?MODULE, #state{config = Config}}, Config).

minor_upgrade(Config) when is_list(Config) ->
    ct_release_test:upgrade(ssh, minor,{?MODULE, #state{config = Config}}, Config).

%%%================================================================
%%%
%%% ct_release_test callbacks
%%% 

%%%----------------------------------------------------------------
%%% Initialyze system before upgrade test starts.
%%% Called by ct_release_test:upgrade/4
upgrade_init(CTData, State) -> 
    {ok, AppUp={_, _, Up, _Down}} = ct_release_test:get_appup(CTData, ssh),
    ct:pal("AppUp: ~p", [AppUp]),
    ct:pal("Up: ~p", [Up]),
    case Soft = is_soft(Up) of
	%% It is symmetrical, if upgrade is soft so is downgrade  
	true ->
	    setup_server_client(State#state{soft = Soft});
	false ->
	    State#state{soft = Soft}
    end.

%%%----------------------------------------------------------------
%%% Check that upgrade was successful
%%% Called by ct_release_test:upgrade/4
upgrade_upgraded(_, #state{soft=false} = State) ->
    test_hard(State, "upgrade");

upgrade_upgraded(_, State) -> 
    test_soft(State, "upgrade1").

%%%----------------------------------------------------------------
%%% Check that downgrade was successful.
%%% Called by ct_release_test:upgrade/4
upgrade_downgraded(_, #state{soft=false} = State) -> 
    test_hard(State, "downgrade");

upgrade_downgraded(_, #state{soft=true} = State) -> 
    test_soft(State, "downgrade1").
 
%%%================================================================
%%%
%%% Private functions
%%% 

is_soft([{restart_application, ssh}]) -> 
    false;
is_soft(_) ->
    true.


test_hard(State0, FileName) ->
    ct:pal("test_hard State0=~p, FileName=~p",[State0, FileName]),
    State = setup_server_client(State0),
    test_connection(FileName, random_contents(), State).

test_soft(State0, FileName) ->
    ct:pal("test_soft State0=~p, FileName=~p",[State0, FileName]),
    State = test_connection(FileName, random_contents(), State0),
    setup_server_client( close(State) ).


setup_server_client(#state{config=Config} = State) ->
    DataDir = ?config(data_dir, Config),
    PrivDir = ?config(priv_dir, Config),
	    
    FtpRootDir = filename:join(PrivDir, "ftp_root"),
    catch file:make_dir(FtpRootDir),
	
    SFTP = ssh_sftpd:subsystem_spec([{root,FtpRootDir},{cwd,FtpRootDir}]),

    {Server,Host,Port} = ssh_test_lib:daemon([{system_dir,DataDir},
					      {user_passwords,[{"hej","hopp"}]},
					      {subsystems,[SFTP]}]),
    
    {ok, ChannelPid, Connection} = 
	ssh_sftp:start_channel(Host, Port, [{user_interaction,false},
					    {silently_accept_hosts,true},
					    {user_dir,DataDir},
					    {user,"hej"},
					    {password,"hopp"}]),
    State#state{server = Server,
		client = ChannelPid,
		connection = Connection}.


test_connection(FileName, FileContents,
		#state{client = ChannelPid,
		       root_dir = FtpRootDir} = State) ->
    ct:pal("test_connection Writing with ssh_sftp:write_file",[]),
    case ssh_sftp:write_file(ChannelPid, FileName, FileContents) of
	ok ->
	    case ssh_sftp:read_file(ChannelPid, FileName) of
		{ok,FileContents} ->
			    State;
		{ok,Unexpected} ->
		    ct:fail("Expected ~p but got ~p from sftp:read_file(~p,..) in RootDir ~p",
			    [FileContents,Unexpected,FileName,FtpRootDir]
			   );
		Other ->
		    ct:fail("ssh_sftp:read_file(~p,~p) -> ~p~n" 
			    "ssh_sftp:list_dir(~p,\".\") -> ~p", 
			    [ChannelPid,FileName,Other,
			     ChannelPid, catch ssh_sftp:list_dir(ChannelPid, ".")])
	    end;

	Other ->
	    ct:fail("ssh_sftp:write_file(~p,~p,~p) -> ~p",[ChannelPid,FileName,FileContents,Other])
    end.


close(#state{server = Server,
	     connection = Connection} = State) ->
    ssh:close(Connection),
    ssh:stop_daemon(Server),
    State#state{server = undefined,
		client = undefined,
		connection = undefined}.


random_contents() -> list_to_binary( random_chars(3) ).

random_chars(N) -> [crypto:rand_uniform($a,$z) || _<-lists:duplicate(N,x)].