diff options
Diffstat (limited to 'lib/inets/test/ftp_SUITE.erl')
-rw-r--r-- | lib/inets/test/ftp_SUITE.erl | 482 |
1 files changed, 334 insertions, 148 deletions
diff --git a/lib/inets/test/ftp_SUITE.erl b/lib/inets/test/ftp_SUITE.erl index cc40377ebf..08295d4e3c 100644 --- a/lib/inets/test/ftp_SUITE.erl +++ b/lib/inets/test/ftp_SUITE.erl @@ -42,8 +42,10 @@ -define(BAD_USER, "baduser"). -define(BAD_DIR, "baddirectory"). -go() -> ct:run_test([{suite,"ftp_SUITE"}, {logdir,"LOG"}]). -gos() -> ct:run_test([{suite,"ftp_SUITE"}, {group,ftps_passive}, {logdir,"LOG"}]). +-record(progress, { + current = 0, + total + }). %%-------------------------------------------------------------------- %% Common Test interface functions ----------------------------------- @@ -90,7 +92,14 @@ ftp_tests()-> recv_chunk, type, quote, - ip_v6_disabled + ip_v6_disabled, + progress_report_send, + progress_report_recv, + not_owner, + unexpected_call, + unexpected_cast, + unexpected_bang, + clean_shutdown ]. %%-------------------------------------------------------------------- @@ -117,9 +126,9 @@ ftp_tests()-> -define(default_ftp_servers, [{"vsftpd", fun(__CONF__) -> - DataDir = ?config(data_dir,__CONF__), + DataDir = proplists:get_value(data_dir,__CONF__), ConfFile = filename:join(DataDir, "vsftpd.conf"), - PrivDir = ?config(priv_dir,__CONF__), + PrivDir = proplists:get_value(priv_dir,__CONF__), AnonRoot = PrivDir, Cmd = ["vsftpd "++filename:join(DataDir,"vsftpd.conf"), " -oftpd_banner=erlang_otp_testing", @@ -145,7 +154,7 @@ ftp_tests()-> fun(_StartResult) -> os:cmd("kill `ps ax | grep erlang_otp_testing | awk '/vsftpd/{print $1}'`") end, fun(__CONF__) -> - AnonRoot = ?config(priv_dir,__CONF__), + AnonRoot = proplists:get_value(priv_dir,__CONF__), [{id2ftp, fun(Id) -> filename:join(AnonRoot,Id) end}, {id2ftp_result,fun(Id) -> filename:join(AnonRoot,Id) end} | __CONF__] end, @@ -161,9 +170,9 @@ init_per_suite(Config) -> false -> {skip, "No ftp server found"}; {ok,Data} -> - TstDir = filename:join(?config(priv_dir,Config), "test"), + TstDir = filename:join(proplists:get_value(priv_dir,Config), "test"), file:make_dir(TstDir), - make_cert_files(dsa, rsa, "server-", ?config(data_dir,Config)), + make_cert_files(dsa, rsa, "server-", proplists:get_value(data_dir,Config)), start_ftpd([{test_dir,TstDir}, {ftpd_data,Data} | Config]) @@ -181,8 +190,16 @@ init_per_group(_Group, Config) -> Config. end_per_group(_Group, Config) -> Config. %%-------------------------------------------------------------------- -init_per_testcase(Case, Config0) -> - Group = proplists:get_value(name,?config(tc_group_properties,Config0)), + +init_per_testcase(Case, Config) when (Case =:= progress_report_send) orelse + (Case =:= progress_report_recv) -> + common_init_per_testcase(Case, [{progress, {?MODULE, progress, #progress{}}} | Config]); + +init_per_testcase(Case, Config) -> + common_init_per_testcase(Case, Config). + +common_init_per_testcase(Case, Config0) -> + Group = proplists:get_value(name,proplists:get_value(tc_group_properties,Config0)), try ?MODULE:Case(doc) of Msg -> ct:comment(Msg) catch @@ -203,9 +220,9 @@ init_per_testcase(Case, Config0) -> user -> Config; bad_user -> Config; _ -> - Pid = ?config(ftp,Config), + Pid = proplists:get_value(ftp,Config), ok = ftp:user(Pid, ?FTP_USER, ?FTP_PASS(atom_to_list(Group)++"-"++atom_to_list(Case)) ), - ok = ftp:cd(Pid, ?config(priv_dir,Config)), + ok = ftp:cd(Pid, proplists:get_value(priv_dir,Config)), Config end. @@ -213,10 +230,10 @@ init_per_testcase(Case, Config0) -> end_per_testcase(user, _Config) -> ok; end_per_testcase(bad_user, _Config) -> ok; end_per_testcase(_Case, Config) -> - case ?config(tc_status,Config) of + case proplists:get_value(tc_status,Config) of ok -> ok; _ -> - try ftp:latest_ctrl_response(?config(ftp,Config)) + try ftp:latest_ctrl_response(proplists:get_value(ftp,Config)) of {ok,S} -> ct:log("***~n*** Latest ctrl channel response:~n*** ~p~n***",[S]) catch @@ -228,38 +245,43 @@ end_per_testcase(_Case, Config) -> %%-------------------------------------------------------------------- %% Test Cases -------------------------------------------------------- %%-------------------------------------------------------------------- -user(doc) -> ["Open an ftp connection to a host, and logon as anonymous ftp, then logoff"]; +user() -> [ + {doc, "Open an ftp connection to a host, and logon as anonymous ftp," + " then logoff"}]. user(Config) -> - Pid = ?config(ftp, Config), + Pid = proplists:get_value(ftp, Config), ok = ftp:user(Pid, ?FTP_USER, ?FTP_PASS("")),% logon ok = ftp:close(Pid), % logoff {error,eclosed} = ftp:pwd(Pid), % check logoff result ok. %%------------------------------------------------------------------------- -bad_user(doc) -> ["Open an ftp connection to a host, and logon with bad user."]; +bad_user() -> + [{doc, "Open an ftp connection to a host, and logon with bad user."}]. bad_user(Config) -> - Pid = ?config(ftp, Config), + Pid = proplists:get_value(ftp, Config), {error, euser} = ftp:user(Pid, ?BAD_USER, ?FTP_PASS("")), ok. %%------------------------------------------------------------------------- -pwd(doc) -> ["Test ftp:pwd/1 & ftp:lpwd/1"]; +pwd() -> + [{doc, "Test ftp:pwd/1 & ftp:lpwd/1"}]. pwd(Config0) -> Config = set_state([reset], Config0), - Pid = ?config(ftp, Config), + Pid = proplists:get_value(ftp, Config), {ok, PWD} = ftp:pwd(Pid), {ok, PathLpwd} = ftp:lpwd(Pid), PWD = id2ftp_result("", Config), PathLpwd = id2ftp_result("", Config). %%------------------------------------------------------------------------- -cd(doc) -> ["Open an ftp connection, log on as anonymous ftp, and cd to a" - "directory and to a non-existent directory."]; +cd() -> + ["Open an ftp connection, log on as anonymous ftp, and cd to a" + "directory and to a non-existent directory."]. cd(Config0) -> Dir = "test", Config = set_state([reset,{mkdir,Dir}], Config0), - Pid = ?config(ftp, Config), + Pid = proplists:get_value(ftp, Config), ok = ftp:cd(Pid, id2ftp(Dir,Config)), {ok, PWD} = ftp:pwd(Pid), ExpectedPWD = id2ftp_result(Dir, Config), @@ -267,12 +289,12 @@ cd(Config0) -> {error, epath} = ftp:cd(Pid, ?BAD_DIR). %%------------------------------------------------------------------------- -lcd(doc) -> - ["Test api function ftp:lcd/2"]; +lcd() -> + [{doc, "Test api function ftp:lcd/2"}]. lcd(Config0) -> Dir = "test", Config = set_state([reset,{mkdir,Dir}], Config0), - Pid = ?config(ftp, Config), + Pid = proplists:get_value(ftp, Config), ok = ftp:lcd(Pid, id2ftp(Dir,Config)), {ok, PWD} = ftp:lpwd(Pid), ExpectedPWD = id2ftp_result(Dir, Config), @@ -280,19 +302,20 @@ lcd(Config0) -> {error, epath} = ftp:lcd(Pid, ?BAD_DIR). %%------------------------------------------------------------------------- -ls(doc) -> ["Open an ftp connection; ls the current directory, and the " - "\"test\" directory. We assume that ls never fails, since " - "it's output is meant to be read by humans. "]; +ls() -> + [{doc, "Open an ftp connection; ls the current directory, and the " + "\"test\" directory. We assume that ls never fails, since " + "it's output is meant to be read by humans. "}]. ls(Config0) -> Config = set_state([reset,{mkdir,"test"}], Config0), - Pid = ?config(ftp, Config), + Pid = proplists:get_value(ftp, Config), {ok, _R1} = ftp:ls(Pid), {ok, _R2} = ftp:ls(Pid, id2ftp("test",Config)), %% neither nlist nor ls operates on a directory %% they operate on a pathname, which *can* be a %% directory, but can also be a filename or a group %% of files (including wildcards). - case ?config(wildcard_support, Config) of + case proplists:get_value(wildcard_support, Config) of true -> {ok, _R3} = ftp:ls(Pid, id2ftp("te*",Config)); _ -> @@ -300,20 +323,21 @@ ls(Config0) -> end. %%------------------------------------------------------------------------- -nlist(doc) -> ["Open an ftp connection; nlist the current directory, and the " +nlist() -> + [{doc,"Open an ftp connection; nlist the current directory, and the " "\"test\" directory. Nlist does not behave consistenly over " "operating systems. On some it is an error to have an empty " - "directory."]; + "directory."}]. nlist(Config0) -> Config = set_state([reset,{mkdir,"test"}], Config0), - Pid = ?config(ftp, Config), + Pid = proplists:get_value(ftp, Config), {ok, _R1} = ftp:nlist(Pid), {ok, _R2} = ftp:nlist(Pid, id2ftp("test",Config)), %% neither nlist nor ls operates on a directory %% they operate on a pathname, which *can* be a %% directory, but can also be a filename or a group %% of files (including wildcards). - case ?config(wildcard_support, Config) of + case proplists:get_value(wildcard_support, Config) of true -> {ok, _R3} = ftp:nlist(Pid, id2ftp("te*",Config)); _ -> @@ -321,13 +345,14 @@ nlist(Config0) -> end. %%------------------------------------------------------------------------- -rename(doc) -> ["Rename a file."]; +rename() -> + [{doc, "Rename a file."}]. rename(Config0) -> Contents = <<"ftp_SUITE test ...">>, OldFile = "old.txt", NewFile = "new.txt", Config = set_state([reset,{mkfile,OldFile,Contents}], Config0), - Pid = ?config(ftp, Config), + Pid = proplists:get_value(ftp, Config), ok = ftp:rename(Pid, id2ftp(OldFile,Config), @@ -338,13 +363,14 @@ rename(Config0) -> %%------------------------------------------------------------------------- -send(doc) -> ["Transfer a file with ftp using send/2."]; +send() -> + [{doc, "Transfer a file with ftp using send/2."}]. send(Config0) -> Contents = <<"ftp_SUITE test ...">>, SrcDir = "data", File = "file.txt", Config = set_state([reset,{mkfile,[SrcDir,File],Contents}], Config0), - Pid = ?config(ftp, Config), + Pid = proplists:get_value(ftp, Config), chk_no_file([File],Config), chk_file([SrcDir,File],Contents,Config), @@ -356,14 +382,15 @@ chk_file([SrcDir,File],Contents,Config), chk_file(File, Contents, Config). %%------------------------------------------------------------------------- -send_3(doc) -> ["Transfer a file with ftp using send/3."]; +send_3() -> + [{doc, "Transfer a file with ftp using send/3."}]. send_3(Config0) -> Contents = <<"ftp_SUITE test ...">>, Dir = "incoming", File = "file.txt", RemoteFile = "remfile.txt", Config = set_state([reset,{mkfile,File,Contents},{mkdir,Dir}], Config0), - Pid = ?config(ftp, Config), + Pid = proplists:get_value(ftp, Config), ok = ftp:cd(Pid, id2ftp(Dir,Config)), ok = ftp:lcd(Pid, id2ftp("",Config)), @@ -372,23 +399,25 @@ send_3(Config0) -> chk_file([Dir,RemoteFile], Contents, Config). %%------------------------------------------------------------------------- -send_bin(doc) -> ["Send a binary."]; +send_bin() -> + [{doc, "Send a binary."}]. send_bin(Config0) -> BinContents = <<"ftp_SUITE test ...">>, File = "file.txt", Config = set_state([reset], Config0), - Pid = ?config(ftp, Config), + Pid = proplists:get_value(ftp, Config), {error, enotbinary} = ftp:send_bin(Pid, "some string", id2ftp(File,Config)), ok = ftp:send_bin(Pid, BinContents, id2ftp(File,Config)), chk_file(File, BinContents, Config). %%------------------------------------------------------------------------- -send_chunk(doc) -> ["Send a binary using chunks."]; +send_chunk() -> + [{doc, "Send a binary using chunks."}]. send_chunk(Config0) -> Contents = <<"ftp_SUITE test ...">>, File = "file.txt", Config = set_state([reset,{mkdir,"incoming"}], Config0), - Pid = ?config(ftp, Config), + Pid = proplists:get_value(ftp, Config), ok = ftp:send_chunk_start(Pid, id2ftp(File,Config)), {error, echunk} = ftp:cd(Pid, "incoming"), @@ -399,63 +428,69 @@ send_chunk(Config0) -> chk_file(File, <<Contents/binary,Contents/binary>>, Config). %%------------------------------------------------------------------------- -delete(doc) -> ["Delete a file."]; +delete() -> + [{doc, "Delete a file."}]. delete(Config0) -> Contents = <<"ftp_SUITE test ...">>, File = "file.txt", Config = set_state([reset,{mkfile,File,Contents}], Config0), - Pid = ?config(ftp, Config), + Pid = proplists:get_value(ftp, Config), ok = ftp:delete(Pid, id2ftp(File,Config)), chk_no_file([File], Config). %%------------------------------------------------------------------------- -mkdir(doc) -> ["Make a remote directory."]; +mkdir() -> + [{doc, "Make a remote directory."}]. mkdir(Config0) -> NewDir = "new_dir", Config = set_state([reset], Config0), - Pid = ?config(ftp, Config), + Pid = proplists:get_value(ftp, Config), ok = ftp:mkdir(Pid, id2ftp(NewDir,Config)), chk_dir([NewDir], Config). %%------------------------------------------------------------------------- -rmdir(doc) -> ["Remove a directory."]; +rmdir() -> + [{doc, "Remove a directory."}]. rmdir(Config0) -> Dir = "dir", Config = set_state([reset,{mkdir,Dir}], Config0), - Pid = ?config(ftp, Config), + Pid = proplists:get_value(ftp, Config), ok = ftp:rmdir(Pid, id2ftp(Dir,Config)), chk_no_dir([Dir], Config). %%------------------------------------------------------------------------- -append(doc) -> ["Append a local file twice to a remote file"]; +append() -> + [{doc, "Append a local file twice to a remote file"}]. append(Config0) -> SrcFile = "f_src.txt", DstFile = "f_dst.txt", Contents = <<"ftp_SUITE test ...">>, Config = set_state([reset,{mkfile,SrcFile,Contents}], Config0), - Pid = ?config(ftp, Config), + Pid = proplists:get_value(ftp, Config), ok = ftp:append(Pid, id2ftp(SrcFile,Config), id2ftp(DstFile,Config)), ok = ftp:append(Pid, id2ftp(SrcFile,Config), id2ftp(DstFile,Config)), chk_file(DstFile, <<Contents/binary,Contents/binary>>, Config). %%------------------------------------------------------------------------- -append_bin(doc) -> ["Append a local file twice to a remote file using append_bin"]; +append_bin() -> + [{doc, "Append a local file twice to a remote file using append_bin"}]. append_bin(Config0) -> DstFile = "f_dst.txt", Contents = <<"ftp_SUITE test ...">>, Config = set_state([reset], Config0), - Pid = ?config(ftp, Config), + Pid = proplists:get_value(ftp, Config), ok = ftp:append_bin(Pid, Contents, id2ftp(DstFile,Config)), ok = ftp:append_bin(Pid, Contents, id2ftp(DstFile,Config)), chk_file(DstFile, <<Contents/binary,Contents/binary>>, Config). %%------------------------------------------------------------------------- -append_chunk(doc) -> ["Append chunks."]; +append_chunk() -> + [{doc, "Append chunks."}]. append_chunk(Config0) -> File = "f_dst.txt", Contents = [<<"ER">>,<<"LE">>,<<"RL">>], Config = set_state([reset], Config0), - Pid = ?config(ftp, Config), + Pid = proplists:get_value(ftp, Config), ok = ftp:append_chunk_start(Pid, id2ftp(File,Config)), {error, enotbinary} = ftp:append_chunk(Pid, binary_to_list(lists:nth(1,Contents))), ok = ftp:append_chunk(Pid,lists:nth(1,Contents)), @@ -465,53 +500,58 @@ append_chunk(Config0) -> chk_file(File, <<"ERLERL">>, Config). %%------------------------------------------------------------------------- -recv(doc) -> ["Receive a file using recv/2"]; +recv() -> + [{doc, "Receive a file using recv/2"}]. recv(Config0) -> File = "f_dst.txt", SrcDir = "a_dir", Contents = <<"ftp_SUITE test ...">>, Config = set_state([reset, {mkfile,[SrcDir,File],Contents}], Config0), - Pid = ?config(ftp, Config), + Pid = proplists:get_value(ftp, Config), ok = ftp:cd(Pid, id2ftp(SrcDir,Config)), ok = ftp:lcd(Pid, id2ftp("",Config)), ok = ftp:recv(Pid, File), chk_file(File, Contents, Config). %%------------------------------------------------------------------------- -recv_3(doc) -> ["Receive a file using recv/3"]; +recv_3() -> + [{doc,"Receive a file using recv/3"}]. recv_3(Config0) -> DstFile = "f_src.txt", SrcFile = "f_dst.txt", Contents = <<"ftp_SUITE test ...">>, Config = set_state([reset, {mkfile,SrcFile,Contents}], Config0), - Pid = ?config(ftp, Config), + Pid = proplists:get_value(ftp, Config), ok = ftp:cd(Pid, id2ftp("",Config)), ok = ftp:recv(Pid, SrcFile, id2abs(DstFile,Config)), chk_file(DstFile, Contents, Config). %%------------------------------------------------------------------------- -recv_bin(doc) -> ["Receive a file as a binary."]; +recv_bin() -> + [{doc, "Receive a file as a binary."}]. recv_bin(Config0) -> File = "f_dst.txt", Contents = <<"ftp_SUITE test ...">>, Config = set_state([reset, {mkfile,File,Contents}], Config0), - Pid = ?config(ftp, Config), + Pid = proplists:get_value(ftp, Config), {ok,Received} = ftp:recv_bin(Pid, id2ftp(File,Config)), find_diff(Received, Contents). %%------------------------------------------------------------------------- -recv_chunk(doc) -> ["Receive a file using chunk-wise."]; +recv_chunk() -> + [{doc, "Receive a file using chunk-wise."}]. recv_chunk(Config0) -> File = "big_file.txt", Contents = list_to_binary( lists:duplicate(1000, lists:seq(0,255)) ), Config = set_state([reset, {mkfile,File,Contents}], Config0), - Pid = ?config(ftp, Config), + Pid = proplists:get_value(ftp, Config), {{error, "ftp:recv_chunk_start/2 not called"},_} = recv_chunk(Pid, <<>>), ok = ftp:recv_chunk_start(Pid, id2ftp(File,Config)), {ok, ReceivedContents, _Ncunks} = recv_chunk(Pid, <<>>), find_diff(ReceivedContents, Contents). -recv_chunk(Pid, Acc) -> recv_chunk(Pid, Acc, 0). +recv_chunk(Pid, Acc) -> + recv_chunk(Pid, Acc, 0). recv_chunk(Pid, Acc, N) -> case ftp:recv_chunk(Pid) of @@ -521,18 +561,18 @@ recv_chunk(Pid, Acc, N) -> end. %%------------------------------------------------------------------------- -type(doc) -> ["Test that we can change btween ASCCI and binary transfer mode"]; +type() -> + [{doc,"Test that we can change btween ASCCI and binary transfer mode"}]. type(Config) -> - Pid = ?config(ftp, Config), + Pid = proplists:get_value(ftp, Config), ok = ftp:type(Pid, ascii), ok = ftp:type(Pid, binary), ok = ftp:type(Pid, ascii), {error, etype} = ftp:type(Pid, foobar). %%------------------------------------------------------------------------- -quote(doc) -> [""]; quote(Config) -> - Pid = ?config(ftp, Config), + Pid = proplists:get_value(ftp, Config), ["257 \""++_Rest] = ftp:quote(Pid, "pwd"), %% 257 [_| _] = ftp:quote(Pid, "help"), %% This negativ test causes some ftp servers to hang. This test @@ -541,48 +581,6 @@ quote(Config) -> %% = ftp:quote(Pid, "list"), ok. - -%%------------------------------------------------------------------------- -ip_v6_disabled(doc) -> ["Test ipv4 command PORT"]; -ip_v6_disabled(_Config) -> - %%% FIXME!!!! What is this??? - ok.%% send(Config). - -%%------------------------------------------------------------------------- -%% big_one(doc) -> -%% ["Create a local file and transfer it to the remote host into the " -%% "the \"incoming\" directory, remove " -%% "the local file. Then open a new connection; cd to \"incoming\", " -%% "lcd to the private directory; receive the file; delete the " -%% "remote file; close connection; check that received file is in " -%% "the correct directory; cleanup." ]; -%% big_one(Config) -> -%% Pid = ?config(ftp, Config), -%% do_recv(Pid, Config). - -%% do_recv(Pid, Config) -> -%% PrivDir = ?config(priv_dir, Config), -%% File = ?config(file, Config), -%% Newfile = ?config(new_file, Config), -%% AbsFile = filename:absname(File, PrivDir), -%% Contents = "ftp_SUITE:recv test ...", -%% ok = file:write_file(AbsFile, list_to_binary(Contents)), -%% ok = ftp:cd(Pid, "incoming"), -%% ftp:delete(Pid, File), % reset -%% ftp:lcd(Pid, PrivDir), -%% ok = ftp:send(Pid, File), -%% ok = file:delete(AbsFile), % cleanup -%% test_server:sleep(100), -%% ok = ftp:lcd(Pid, PrivDir), -%% ok = ftp:recv(Pid, File), -%% {ok, Files} = file:list_dir(PrivDir), -%% true = lists:member(File, Files), -%% ok = file:delete(AbsFile), % cleanup -%% ok = ftp:recv(Pid, File, Newfile), -%% ok = ftp:delete(Pid, File), % cleanup -%% ok. - - %%-------------------------------------------------------------------- %% Internal functions ----------------------------------------------- %%-------------------------------------------------------------------- @@ -676,13 +674,114 @@ chk_no_dir(PathList, Config) -> ct:fail("Unexpected error for ~p: ~p",[Path,Error]) end. +%%------------------------------------------------------------------------- +progress_report_send() -> + [{doc, "Test the option progress for ftp:send/[2,3]"}]. +progress_report_send(Config) when is_list(Config) -> + ReportPid = + spawn_link(?MODULE, progress_report_receiver_init, [self(), 1]), + send(Config), + receive + {ReportPid, ok} -> + ok + end. +%%------------------------------------------------------------------------- +progress_report_recv() -> + [{doc, "Test the option progress for ftp:recv/[2,3]"}]. +progress_report_recv(Config) when is_list(Config) -> + ReportPid = + spawn_link(?MODULE, progress_report_receiver_init, [self(), 3]), + recv(Config), + receive + {ReportPid, ok} -> + ok + end. + +%%------------------------------------------------------------------------- + +not_owner() -> + [{doc, "Test what happens if a process that not owns the connection tries " + "to use it"}]. +not_owner(Config) when is_list(Config) -> + Pid = proplists:get_value(ftp, Config), + OtherPid = spawn_link(?MODULE, not_owner, [Pid, self()]), + + receive + {OtherPid, ok} -> + {ok, _} = ftp:pwd(Pid) + end. + + +%%------------------------------------------------------------------------- + + +unexpected_call()-> + [{doc, "Test that behaviour of the ftp process if the api is abused"}]. +unexpected_call(Config) when is_list(Config) -> + Flag = process_flag(trap_exit, true), + Pid = proplists:get_value(ftp, Config), + + %% Serious programming fault, connetion will be shut down + case (catch gen_server:call(Pid, {self(), foobar, 10}, infinity)) of + {error, {connection_terminated, 'API_violation'}} -> + ok; + Unexpected1 -> + exit({unexpected_result, Unexpected1}) + end, + ct:sleep(500), + undefined = process_info(Pid, status), + process_flag(trap_exit, Flag). +%%------------------------------------------------------------------------- + +unexpected_cast()-> + [{doc, "Test that behaviour of the ftp process if the api is abused"}]. +unexpected_cast(Config) when is_list(Config) -> + Flag = process_flag(trap_exit, true), + Pid = proplists:get_value(ftp, Config), + %% Serious programming fault, connetion will be shut down + gen_server:cast(Pid, {self(), foobar, 10}), + ct:sleep(500), + undefined = process_info(Pid, status), + process_flag(trap_exit, Flag). +%%------------------------------------------------------------------------- + +unexpected_bang()-> + [{doc, "Test that connection ignores unexpected bang"}]. +unexpected_bang(Config) when is_list(Config) -> + Flag = process_flag(trap_exit, true), + Pid = proplists:get_value(ftp, Config), + %% Could be an innocent misstake the connection lives. + Pid ! foobar, + ct:sleep(500), + {status, _} = process_info(Pid, status), + process_flag(trap_exit, Flag). + +%%------------------------------------------------------------------------- + +clean_shutdown() -> + [{doc, "Test that owning process that exits with reason " + "'shutdown' does not cause an error message. OTP 6035"}]. + +clean_shutdown(Config) -> + PrivDir = proplists:get_value(priv_dir, Config), + LogFile = filename:join([PrivDir,"ticket_6035.log"]), + Host = proplists:get_value(ftpd_host,Config), + try + Pid = spawn(?MODULE, open_wait_6035, [Host, self()]), + error_logger:logfile({open, LogFile}), + true = kill_ftp_proc_6035(Pid, LogFile), + error_logger:logfile(close) + catch + throw:{error, not_found} -> + {skip, "No available FTP servers"} + end. %%-------------------------------------------------------------------- +%% Internal functions %%-------------------------------------------------------------------- -%% find a suitable ftpd -%% + find_executable(Config) -> - FTPservers = case ?config(ftpservers,Config) of + FTPservers = case proplists:get_value(ftpservers,Config) of undefined -> ?default_ftp_servers; L -> L end, @@ -694,11 +793,9 @@ find_executable(Config) -> not_available({Name,_StartCmd,_ChkUp,_StopCommand,_ConfigUpd,_Host,_Port}) -> os:find_executable(Name) == false. -%%-------------------------------------------------------------------- -%% start/stop of ftpd -%% + start_ftpd(Config) -> - {Name,StartCmd,_ChkUp,_StopCommand,ConfigRewrite,Host,Port} = ?config(ftpd_data, Config), + {Name,StartCmd,_ChkUp,_StopCommand,ConfigRewrite,Host,Port} = proplists:get_value(ftpd_data, Config), case StartCmd(Config) of {ok,StartResult} -> [{ftpd_host,Host}, @@ -709,38 +806,31 @@ start_ftpd(Config) -> end. stop_ftpd(Config) -> - {_Name,_StartCmd,_ChkUp,StopCommand,_ConfigUpd,_Host,_Port} = ?config(ftpd_data, Config), - StopCommand(?config(ftpd_start_result,Config)). + {_Name,_StartCmd,_ChkUp,StopCommand,_ConfigUpd,_Host,_Port} = proplists:get_value(ftpd_data, Config), + StopCommand(proplists:get_value(ftpd_start_result,Config)). ps_ftpd(Config) -> - {_Name,_StartCmd,ChkUp,_StopCommand,_ConfigUpd,_Host,_Port} = ?config(ftpd_data, Config), - ct:log( ChkUp(?config(ftpd_start_result,Config)) ). + {_Name,_StartCmd,ChkUp,_StopCommand,_ConfigUpd,_Host,_Port} = proplists:get_value(ftpd_data, Config), + ct:log( ChkUp(proplists:get_value(ftpd_start_result,Config)) ). ftpd_running(Config) -> - {_Name,_StartCmd,ChkUp,_StopCommand,_ConfigUpd,_Host,_Port} = ?config(ftpd_data, Config), - ChkUp(?config(ftpd_start_result,Config)). + {_Name,_StartCmd,ChkUp,_StopCommand,_ConfigUpd,_Host,_Port} = proplists:get_value(ftpd_data, Config), + ChkUp(proplists:get_value(ftpd_start_result,Config)). -%%-------------------------------------------------------------------- -%% start/stop of ftpc -%% ftp__open(Config, Options) -> - Host = ?config(ftpd_host,Config), - Port = ?config(ftpd_port,Config), + Host = proplists:get_value(ftpd_host,Config), + Port = proplists:get_value(ftpd_port,Config), ct:log("Host=~p, Port=~p",[Host,Port]), {ok,Pid} = ftp:open(Host, [{port,Port} | Options]), [{ftp,Pid}|Config]. ftp__close(Config) -> - ok = ftp:close(?config(ftp,Config)), + ok = ftp:close(proplists:get_value(ftp,Config)), Config. -%%-------------------------------------------------------------------- -%% split(Cs) -> string:tokens(Cs, "\r\n"). -%%-------------------------------------------------------------------- -%% find_diff(Bin1, Bin2) -> case find_diff(Bin1, Bin2, 1) of {error, {diff,Pos,RC,LC}} -> @@ -753,15 +843,14 @@ find_diff(Bin1, Bin2) -> find_diff(A, A, _) -> true; find_diff(<<H,T1/binary>>, <<H,T2/binary>>, Pos) -> find_diff(T1, T2, Pos+1); find_diff(RC, LC, Pos) -> {error, {diff, Pos, RC, LC}}. -%%-------------------------------------------------------------------- -%% + set_state(Ops, Config) when is_list(Ops) -> lists:foldl(fun set_state/2, Config, Ops); set_state(reset, Config) -> rm('*', id2abs("",Config)), - PrivDir = ?config(priv_dir,Config), + PrivDir = proplists:get_value(priv_dir,Config), file:set_cwd(PrivDir), - ftp:lcd(?config(ftp,Config),PrivDir), + ftp:lcd(proplists:get_value(ftp,Config),PrivDir), set_state({mkdir,""},Config); set_state({mkdir,Id}, Config) -> Abs = id2abs(Id, Config), @@ -787,7 +876,6 @@ mk_path(F, Pfx) -> AbsName end. - rm('*', Pfx) -> {ok,Fs} = file:list_dir(Pfx), lists:foreach(fun(F) -> rm(F, Pfx) end, Fs); @@ -805,17 +893,115 @@ rm(F, Pfx) -> ok end. -%%-------------------------------------------------------------------- -%% +not_owner(FtpPid, Pid) -> + {error, not_connection_owner} = ftp:pwd(FtpPid), + ftp:close(FtpPid), + ct:sleep(100), + Pid ! {self(), ok}. -id2abs(Id, Conf) -> filename:join(?config(priv_dir,Conf),ids(Id)). -id2ftp(Id, Conf) -> (?config(id2ftp,Conf))(ids(Id)). -id2ftp_result(Id, Conf) -> (?config(id2ftp_result,Conf))(ids(Id)). +id2abs(Id, Conf) -> filename:join(proplists:get_value(priv_dir,Conf),ids(Id)). +id2ftp(Id, Conf) -> (proplists:get_value(id2ftp,Conf))(ids(Id)). +id2ftp_result(Id, Conf) -> (proplists:get_value(id2ftp_result,Conf))(ids(Id)). ids([[_|_]|_]=Ids) -> filename:join(Ids); ids(Id) -> Id. -is_expected_absName(Id, File, Conf) -> File = (?config(id2abs,Conf))(Id). -is_expected_ftpInName(Id, File, Conf) -> File = (?config(id2ftp,Conf))(Id). -is_expected_ftpOutName(Id, File, Conf) -> File = (?config(id2ftp_result,Conf))(Id). +is_expected_absName(Id, File, Conf) -> File = (proplists:get_value(id2abs,Conf))(Id). +is_expected_ftpInName(Id, File, Conf) -> File = (proplists:get_value(id2ftp,Conf))(Id). +is_expected_ftpOutName(Id, File, Conf) -> File = (proplists:get_value(id2ftp_result,Conf))(Id). + + +progress(#progress{} = Progress , _File, {file_size, Total}) -> + progress_report_receiver ! start, + Progress#progress{total = Total}; + +progress(#progress{total = Total, current = Current} + = Progress, _File, {transfer_size, 0}) -> + progress_report_receiver ! finish, + case Total of + unknown -> + ok; + Current -> + ok; + _ -> + ct:fail({error, {progress, {total, Total}, + {current, Current}}}) + end, + Progress; +progress(#progress{current = Current} = Progress, _File, + {transfer_size, Size}) -> + progress_report_receiver ! update, + Progress#progress{current = Current + Size}. + +progress_report_receiver_init(Pid, N) -> + register(progress_report_receiver, self()), + receive + start -> + ok + end, + progress_report_receiver_loop(Pid, N-1). + +progress_report_receiver_loop(Pid, N) -> + receive + update -> + progress_report_receiver_loop(Pid, N); + finish when N =:= 0 -> + Pid ! {self(), ok}; + finish -> + Pid ! {self(), ok}, + receive + start -> + ok + end, + progress_report_receiver_loop(Pid, N-1) + end. + +kill_ftp_proc_6035(Pid, LogFile) -> + receive + open -> + exit(Pid, shutdown), + kill_ftp_proc_6035(Pid, LogFile); + {open_failed, Reason} -> + exit({skip, {failed_openening_server_connection, Reason}}) + after + 5000 -> + is_error_report_6035(LogFile) + end. + +open_wait_6035({_Tag, FtpServer}, From) -> + case ftp:open(FtpServer, [{timeout, timer:seconds(15)}]) of + {ok, Pid} -> + _LoginResult = ftp:user(Pid,"anonymous","kldjf"), + From ! open, + receive + dummy -> + ok + after + 10000 -> + ok + end, + ok; + {error, Reason} -> + From ! {open_failed, {Reason, FtpServer}}, + ok + end. + +is_error_report_6035(LogFile) -> + Res = + case file:read_file(LogFile) of + {ok, Bin} -> + Txt = binary_to_list(Bin), + read_log_6035(Txt); + _ -> + false + end, + %% file:delete(LogFile), + Res. + +read_log_6035("=ERROR REPORT===="++_Rest) -> + true; +read_log_6035([_|T]) -> + read_log_6035(T); +read_log_6035([]) -> + false. |