diff options
Diffstat (limited to 'lib/kernel/test')
-rw-r--r-- | lib/kernel/test/Makefile | 3 | ||||
-rw-r--r-- | lib/kernel/test/file_SUITE.erl | 4 | ||||
-rw-r--r-- | lib/kernel/test/gen_sctp_SUITE.erl | 4 | ||||
-rw-r--r-- | lib/kernel/test/gen_tcp_api_SUITE.erl | 10 | ||||
-rw-r--r-- | lib/kernel/test/gen_tcp_echo_SUITE.erl | 11 | ||||
-rw-r--r-- | lib/kernel/test/gen_tcp_misc_SUITE.erl | 71 | ||||
-rw-r--r-- | lib/kernel/test/inet_SUITE.erl | 8 | ||||
-rw-r--r-- | lib/kernel/test/inet_res_SUITE.erl | 6 | ||||
-rwxr-xr-x | lib/kernel/test/inet_res_SUITE_data/run-named | 2 | ||||
-rw-r--r-- | lib/kernel/test/os_SUITE.erl | 18 | ||||
-rw-r--r-- | lib/kernel/test/prim_file_SUITE.erl | 108 | ||||
-rw-r--r-- | lib/kernel/test/sendfile_SUITE.erl | 355 | ||||
-rw-r--r-- | lib/kernel/test/wrap_log_reader_SUITE.erl | 2 |
13 files changed, 572 insertions, 30 deletions
diff --git a/lib/kernel/test/Makefile b/lib/kernel/test/Makefile index 82bc3fc6d1..5dcaad3f5e 100644 --- a/lib/kernel/test/Makefile +++ b/lib/kernel/test/Makefile @@ -74,7 +74,8 @@ MODULES= \ wrap_log_reader_SUITE \ cleanup \ zlib_SUITE \ - loose_node + loose_node \ + sendfile_SUITE APP_FILES = \ appinc.app \ diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl index 77fc7e73f9..85346762ac 100644 --- a/lib/kernel/test/file_SUITE.erl +++ b/lib/kernel/test/file_SUITE.erl @@ -3144,12 +3144,12 @@ ipread_int(Dir, ModeList) -> {fun (Bin) when is_binary(Bin) -> Bin; (List) when is_list(List) -> list_to_binary(List) end, - {erlang, size}}; + fun erlang:byte_size/1}; false -> {fun (Bin) when is_binary(Bin) -> binary_to_list(Bin); (List) when is_list(List) -> List end, - {erlang, length}} + fun erlang:length/1} end, ?line Pos = 4711, ?line Data = Conv("THE QUICK BROWN FOX JUMPS OVER A LAZY DOG"), diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl index 300152ddce..8f490b6643 100644 --- a/lib/kernel/test/gen_sctp_SUITE.erl +++ b/lib/kernel/test/gen_sctp_SUITE.erl @@ -48,7 +48,9 @@ init_per_suite(_Config) -> {ok,Socket} -> gen_sctp:close(Socket), []; - {error,eprotonosupport} -> + {error,Error} + when Error =:= eprotonosupport; + Error =:= esocktnosupport -> {skip,"SCTP not supported on this machine"} end. diff --git a/lib/kernel/test/gen_tcp_api_SUITE.erl b/lib/kernel/test/gen_tcp_api_SUITE.erl index cbaec2d6dd..a7af00c12a 100644 --- a/lib/kernel/test/gen_tcp_api_SUITE.erl +++ b/lib/kernel/test/gen_tcp_api_SUITE.erl @@ -22,7 +22,7 @@ %% are not tested here, because they are tested indirectly in this and %% and other test suites. --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -include_lib("kernel/include/inet.hrl"). -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, @@ -46,6 +46,8 @@ groups() -> {t_connect, [], [t_connect_timeout, t_connect_bad]}, {t_recv, [], [t_recv_timeout, t_recv_eof]}]. + + init_per_suite(Config) -> Config. @@ -55,9 +57,8 @@ end_per_suite(_Config) -> init_per_group(_GroupName, Config) -> Config. -end_per_group(_GroupName, Config) -> - Config. - +end_per_group(_,_Config) -> + ok. init_per_testcase(_Func, Config) -> Dog = test_server:timetrap(test_server:seconds(60)), @@ -237,7 +238,6 @@ implicit_inet6(S, Addr) -> ?line ok = gen_tcp:close(S1). - %%% Utilities %% Calls M:F/length(A), which should return a timeout error, and complete diff --git a/lib/kernel/test/gen_tcp_echo_SUITE.erl b/lib/kernel/test/gen_tcp_echo_SUITE.erl index fffaaf4c45..5bbaeb02ad 100644 --- a/lib/kernel/test/gen_tcp_echo_SUITE.erl +++ b/lib/kernel/test/gen_tcp_echo_SUITE.erl @@ -167,8 +167,12 @@ echo_test_1(SockOpts, EchoFun, Config0) -> [{type, {cdr, little}}|Config]), ?line case lists:keymember(packet_size, 1, SockOpts) of false -> - ?line echo_packet([{packet, line}|SockOpts], - EchoFun, Config); + % This is cheating, we should test that packet_size + % also works for line and http. + echo_packet([{packet, line}|SockOpts], EchoFun, Config), + echo_packet([{packet, http}|SockOpts], EchoFun, Config), + echo_packet([{packet, http_bin}|SockOpts], EchoFun, Config); + true -> ok end, ?line echo_packet([{packet, tpkt}|SockOpts], EchoFun, Config), @@ -183,9 +187,6 @@ echo_test_1(SockOpts, EchoFun, Config0) -> [{type, {asn1, short, LongTag}}|Config]), ?line echo_packet([{packet, asn1}|SockOpts], EchoFun, [{type, {asn1, long, LongTag}}|Config]), - - ?line echo_packet([{packet, http}|SockOpts], EchoFun, Config), - ?line echo_packet([{packet, http_bin}|SockOpts], EchoFun, Config), ok. echo_packet(SockOpts, EchoFun, Opts) -> diff --git a/lib/kernel/test/gen_tcp_misc_SUITE.erl b/lib/kernel/test/gen_tcp_misc_SUITE.erl index b1ef8826d5..3da4b07c05 100644 --- a/lib/kernel/test/gen_tcp_misc_SUITE.erl +++ b/lib/kernel/test/gen_tcp_misc_SUITE.erl @@ -40,7 +40,8 @@ accept_timeouts_in_order3/1,accept_timeouts_mixed/1, killing_acceptor/1,killing_multi_acceptors/1,killing_multi_acceptors2/1, several_accepts_in_one_go/1,active_once_closed/1, send_timeout/1, send_timeout_active/1, - otp_7731/1, zombie_sockets/1, otp_7816/1, otp_8102/1]). + otp_7731/1, zombie_sockets/1, otp_7816/1, otp_8102/1, + otp_9389/1]). %% Internal exports. -export([sender/3, not_owner/1, passive_sockets_server/2, priority_server/1, @@ -72,7 +73,7 @@ all() -> killing_acceptor, killing_multi_acceptors, killing_multi_acceptors2, several_accepts_in_one_go, active_once_closed, send_timeout, send_timeout_active, otp_7731, - zombie_sockets, otp_7816, otp_8102]. + zombie_sockets, otp_7816, otp_8102, otp_9389]. groups() -> []. @@ -1030,6 +1031,7 @@ busy_send_loop(Server, Client, N) -> {Server,send} -> ?line busy_send_2(Server, Client, N+1) after 10000 -> + %% If this happens, see busy_send_srv ?t:fail({timeout,{server,not_send,flush([])}}) end end. @@ -1049,7 +1051,9 @@ busy_send_2(Server, Client, _N) -> busy_send_srv(L, Master, Msg) -> %% Server - %% + %% Sometimes this accept does not return, do not really know why + %% but is causes the timeout error in busy_send_loop to be + %% triggered. Only happens on OS X Leopard?!? {ok,Socket} = gen_tcp:accept(L), busy_send_srv_loop(Socket, Master, Msg). @@ -2479,4 +2483,63 @@ otp_8102_do(LSocket, PortNum, {Bin,PType}) -> io:format("Got error msg, ok.\n",[]), gen_tcp:close(SSocket), gen_tcp:close(RSocket). - + +otp_9389(doc) -> ["Verify packet_size handles long HTTP header lines"]; +otp_9389(suite) -> []; +otp_9389(Config) when is_list(Config) -> + ?line {ok, LS} = gen_tcp:listen(0, []), + ?line {ok, {_, PortNum}} = inet:sockname(LS), + io:format("Listening on ~w with port number ~p\n", [LS, PortNum]), + OrigLinkHdr = "/" ++ string:chars($S, 8192), + _Server = spawn_link( + fun() -> + ?line {ok, S} = gen_tcp:accept(LS), + ?line ok = inet:setopts(S, [{packet_size, 16384}]), + ?line ok = otp_9389_loop(S, OrigLinkHdr), + ?line ok = gen_tcp:close(S) + end), + ?line {ok, S} = gen_tcp:connect("localhost", PortNum, + [binary, {active, false}]), + Req = "GET / HTTP/1.1\r\n" + ++ "Host: localhost\r\n" + ++ "Link: " ++ OrigLinkHdr ++ "\r\n\r\n", + ?line ok = gen_tcp:send(S, Req), + ?line ok = inet:setopts(S, [{packet, http}]), + ?line {ok, {http_response, {1,1}, 200, "OK"}} = gen_tcp:recv(S, 0), + ?line ok = inet:setopts(S, [{packet, httph}, {packet_size, 16384}]), + ?line {ok, {http_header, _, 'Content-Length', _, "0"}} = gen_tcp:recv(S, 0), + ?line {ok, {http_header, _, "Link", _, LinkHdr}} = gen_tcp:recv(S, 0), + ?line true = (LinkHdr == OrigLinkHdr), + ok = gen_tcp:close(S), + ok = gen_tcp:close(LS), + ok. + +otp_9389_loop(S, OrigLinkHdr) -> + ?line ok = inet:setopts(S, [{active,once},{packet,http}]), + receive + {http, S, {http_request, 'GET', _, _}} -> + ?line ok = otp_9389_loop(S, OrigLinkHdr, undefined) + after + 3000 -> + ?line error({timeout,request_line}) + end. +otp_9389_loop(S, OrigLinkHdr, ok) -> + ?line Resp = "HTTP/1.1 200 OK\r\nContent-length: 0\r\n" ++ + "Link: " ++ OrigLinkHdr ++ "\r\n\r\n", + ?line ok = gen_tcp:send(S, Resp); +otp_9389_loop(S, OrigLinkHdr, State) -> + ?line ok = inet:setopts(S, [{active,once}, {packet,httph}]), + receive + {http, S, http_eoh} -> + ?line otp_9389_loop(S, OrigLinkHdr, ok); + {http, S, {http_header, _, "Link", _, LinkHdr}} -> + ?line LinkHdr = OrigLinkHdr, + ?line otp_9389_loop(S, OrigLinkHdr, State); + {http, S, {http_header, _, _Hdr, _, _Val}} -> + ?line otp_9389_loop(S, OrigLinkHdr, State); + {http, S, {http_error, Err}} -> + ?line error({error, Err}) + after + 3000 -> + ?line error({timeout,header}) + end. diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl index aaa20b7398..7241b093d0 100644 --- a/lib/kernel/test/inet_SUITE.erl +++ b/lib/kernel/test/inet_SUITE.erl @@ -97,8 +97,12 @@ t_gethostbyaddr() -> required(v4). t_gethostbyaddr(doc) -> "Test the inet:gethostbyaddr/1 function."; t_gethostbyaddr(Config) when is_list(Config) -> - ?line {Name,FullName,IPStr,IP,Aliases,_,_} = + ?line {Name,FullName,IPStr,{A,B,C,D}=IP,Aliases,_,_} = ct:get_config(test_host_ipv4_only), + ?line Rname = integer_to_list(D) ++ "." ++ + integer_to_list(C) ++ "." ++ + integer_to_list(B) ++ "." ++ + integer_to_list(A) ++ ".in-addr.arpa", ?line {ok,HEnt} = inet:gethostbyaddr(IPStr), ?line {ok,HEnt} = inet:gethostbyaddr(IP), ?line {error,Error} = inet:gethostbyaddr(Name), @@ -116,7 +120,7 @@ t_gethostbyaddr(Config) when is_list(Config) -> ok; _ -> ?line check_elems([{HEnt#hostent.h_name,[Name,FullName]}, - {HEnt#hostent.h_aliases,[[],Aliases]}]) + {HEnt#hostent.h_aliases,[[],Aliases,[Rname]]}]) end, ?line {_DName, _DFullName, DIPStr, DIP, _, _, _} = diff --git a/lib/kernel/test/inet_res_SUITE.erl b/lib/kernel/test/inet_res_SUITE.erl index 15b0ed5718..f3ba28e4f9 100644 --- a/lib/kernel/test/inet_res_SUITE.erl +++ b/lib/kernel/test/inet_res_SUITE.erl @@ -88,7 +88,7 @@ init_per_testcase(Func, Config) -> inet_db:ins_alt_ns(IP, Port); _ -> ok end, - Dog = test_server:timetrap(test_server:seconds(10)), + Dog = test_server:timetrap(test_server:seconds(20)), [{nameserver,NsSpec},{res_lookup,Lookup},{watchdog,Dog}|Config] catch SkipReason -> @@ -303,7 +303,7 @@ basic(Config) when is_list(Config) -> {ok,Msg2} = inet_dns:decode(Bin2), %% %% lookup - [IP] = inet_res:lookup(Name, in, a, [{nameservers,[NS]}]), + [IP] = inet_res:lookup(Name, in, a, [{nameservers,[NS]},verbose]), %% %% gethostbyname {ok,#hostent{h_addr_list=[IP]}} = inet_res:gethostbyname(Name), @@ -410,7 +410,7 @@ edns0(Config) when is_list(Config) -> false = inet_db:res_option(edns), % ASSERT true = inet_db:res_option(udp_payload_size) >= 1280, % ASSERT %% These will fall back to TCP - MXs = lists:sort(inet_res:lookup(Domain, in, mx, [{nameservers,[NS]}])), + MXs = lists:sort(inet_res:lookup(Domain, in, mx, [{nameservers,[NS]},verbose])), %% {ok,#hostent{h_addr_list=As}} = inet_res:getbyname(Domain++".", mx), MXs = lists:sort(As), diff --git a/lib/kernel/test/inet_res_SUITE_data/run-named b/lib/kernel/test/inet_res_SUITE_data/run-named index 39e7b1d5aa..eeca680ab5 100755 --- a/lib/kernel/test/inet_res_SUITE_data/run-named +++ b/lib/kernel/test/inet_res_SUITE_data/run-named @@ -163,7 +163,7 @@ echo "Command: $NAMED $NAMED_FG -c $CONF_FILE" NAMED_PID=$! trap "kill -TERM $NAMED_PID >/dev/null 2>&1; wait $NAMED_PID >/dev/null 2>&1" \ 0 1 2 3 15 -sleep 2 # Give name server time to load its zone files +sleep 5 # Give name server time to load its zone files if [ -f "$EXIT_FILE" ]; then ERROR="`cat "$EXIT_FILE"`" (exit "$ERROR")& error "$NAMED returned $ERROR on start" diff --git a/lib/kernel/test/os_SUITE.erl b/lib/kernel/test/os_SUITE.erl index b08b12c978..ae3410d13f 100644 --- a/lib/kernel/test/os_SUITE.erl +++ b/lib/kernel/test/os_SUITE.erl @@ -117,9 +117,21 @@ space_in_name(Config) when is_list(Config) -> ?line ok = file:change_mode(Echo, 8#777), % Make it executable on Unix. %% Run the echo program. - - ?line comp("", os:cmd("\"" ++ Echo ++ "\"")), - ?line comp("a::b::c", os:cmd("\"" ++ Echo ++ "\" a b c")), + %% Quoting on windows depends on if the full path of the executable + %% contains special characters. Paths when running common_tests always + %% include @, why Windows would always fail if we do not double the + %% quotes (this is the behaviour of cmd.exe, not Erlang's idea). + Quote = case os:type() of + {win32,_} -> + case (Echo -- "&<>()@^|") =:= Echo of + true -> "\""; + false -> "\"\"" + end; + _ -> + "\"" + end, + ?line comp("", os:cmd(Quote ++ Echo ++ Quote)), + ?line comp("a::b::c", os:cmd(Quote ++ Echo ++ Quote ++ " a b c")), ?t:sleep(5), ?line [] = receive_all(), ok. diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl index 00eda6292f..ccf26ee034 100644 --- a/lib/kernel/test/prim_file_SUITE.erl +++ b/lib/kernel/test/prim_file_SUITE.erl @@ -32,7 +32,10 @@ file_info_basic_directory_a/1, file_info_basic_directory_b/1, file_info_bad_a/1, file_info_bad_b/1, file_info_times_a/1, file_info_times_b/1, - file_write_file_info_a/1, file_write_file_info_b/1]). + file_write_file_info_a/1, file_write_file_info_b/1, + file_read_file_info_opts/1, file_write_file_info_opts/1, + file_write_read_file_info_opts/1 + ]). -export([rename_a/1, rename_b/1, access/1, truncate/1, datasync/1, sync/1, read_write/1, pread_write/1, append/1, exclusive/1]). @@ -90,7 +93,10 @@ groups() -> file_info_basic_directory_a, file_info_basic_directory_b, file_info_bad_a, file_info_bad_b, file_info_times_a, file_info_times_b, - file_write_file_info_a, file_write_file_info_b]}, + file_write_file_info_a, file_write_file_info_b, + file_read_file_info_opts, file_write_file_info_opts, + file_write_read_file_info_opts + ]}, {errors, [], [e_delete, e_rename, e_make_dir, e_del_dir]}, {compression, [], @@ -1074,6 +1080,104 @@ file_write_file_info(Config, Handle, Suffix) -> ?line test_server:timetrap_cancel(Dog), ok. +%% Test the write_file_info/3 function. + +file_write_file_info_opts(suite) -> []; +file_write_file_info_opts(doc) -> []; +file_write_file_info_opts(Config) when is_list(Config) -> + {ok, Handle} = ?PRIM_FILE:start(), + Dog = test_server:timetrap(test_server:seconds(10)), + RootDir = get_good_directory(Config), + test_server:format("RootDir = ~p", [RootDir]), + + Name = filename:join(RootDir, atom_to_list(?MODULE) ++"_write_file_info_opts"), + ok = ?PRIM_FILE:write_file(Name, "hello_opts"), + + lists:foreach(fun + ({FI, Opts}) -> + ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, FI, Opts]) + end, [ + {#file_info{ mode=8#600, atime = Time, mtime = Time, ctime = Time}, Opts} || + Opts <- [[{time, posix}]], + Time <- [ 0,1,-1,100,-100,1000,-1000,10000,-10000 ] + ]), + + % REM: determine date range dependent on time_t = Uint32 | Sint32 | Sint64 + % Determine time_t on os:type()? + lists:foreach(fun + ({FI, Opts}) -> + ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, FI, Opts]) + end, [ + {#file_info{ mode=8#400, atime = Time, mtime = Time, ctime = Time}, Opts} || + Opts <- [[{time, universal}],[{time, local}]], + Time <- [ + {{1970,1,1},{0,0,0}}, + {{1970,1,1},{0,0,1}}, + {{1969,12,31},{23,59,59}}, + {{1908,2,3},{23,59,59}}, + {{2012,2,3},{23,59,59}}, + {{2037,2,3},{23,59,59}}, + erlang:localtime() + ]]), + ok = ?PRIM_FILE:stop(Handle), + test_server:timetrap_cancel(Dog), + ok. + +file_read_file_info_opts(suite) -> []; +file_read_file_info_opts(doc) -> []; +file_read_file_info_opts(Config) when is_list(Config) -> + {ok, Handle} = ?PRIM_FILE:start(), + Dog = test_server:timetrap(test_server:seconds(10)), + RootDir = get_good_directory(Config), + test_server:format("RootDir = ~p", [RootDir]), + + Name = filename:join(RootDir, atom_to_list(?MODULE) ++"_read_file_info_opts"), + ok = ?PRIM_FILE:write_file(Name, "hello_opts"), + + lists:foreach(fun + (Opts) -> + {ok,_} = ?PRIM_FILE_call(read_file_info, Handle, [Name, Opts]) + end, [[{time, Type}] || Type <- [local, universal, posix]]), + ok = ?PRIM_FILE:stop(Handle), + test_server:timetrap_cancel(Dog), + ok. + +%% Test the write and read back *_file_info/3 functions. + +file_write_read_file_info_opts(suite) -> []; +file_write_read_file_info_opts(doc) -> []; +file_write_read_file_info_opts(Config) when is_list(Config) -> + {ok, Handle} = ?PRIM_FILE:start(), + Dog = test_server:timetrap(test_server:seconds(10)), + RootDir = get_good_directory(Config), + test_server:format("RootDir = ~p", [RootDir]), + + Name = filename:join(RootDir, atom_to_list(?MODULE) ++"_read_write_file_info_opts"), + ok = ?PRIM_FILE:write_file(Name, "hello_opts2"), + + ok = file_write_read_file_info_opts(Handle, Name, {{1989, 04, 28}, {19,30,22}}, [{time, local}]), + ok = file_write_read_file_info_opts(Handle, Name, {{1989, 04, 28}, {19,30,22}}, [{time, universal}]), + ok = file_write_read_file_info_opts(Handle, Name, {{1930, 04, 28}, {19,30,22}}, [{time, local}]), + ok = file_write_read_file_info_opts(Handle, Name, {{1930, 04, 28}, {19,30,22}}, [{time, universal}]), + ok = file_write_read_file_info_opts(Handle, Name, 1, [{time, posix}]), + ok = file_write_read_file_info_opts(Handle, Name, -1, [{time, posix}]), + ok = file_write_read_file_info_opts(Handle, Name, 300000, [{time, posix}]), + ok = file_write_read_file_info_opts(Handle, Name, -300000, [{time, posix}]), + ok = file_write_read_file_info_opts(Handle, Name, 0, [{time, posix}]), + + ok = ?PRIM_FILE:stop(Handle), + test_server:timetrap_cancel(Dog), + ok. + +file_write_read_file_info_opts(Handle, Name, Mtime, Opts) -> + {ok, FI} = ?PRIM_FILE_call(read_file_info, Handle, [Name, Opts]), + FI2 = FI#file_info{ mtime = Mtime }, + ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, FI2, Opts]), + {ok, FI2} = ?PRIM_FILE_call(read_file_info, Handle, [Name, Opts]), + ok. + + + %% Returns a directory on a file system that has correct file times. get_good_directory(Config) -> diff --git a/lib/kernel/test/sendfile_SUITE.erl b/lib/kernel/test/sendfile_SUITE.erl new file mode 100644 index 0000000000..6d0848ee05 --- /dev/null +++ b/lib/kernel/test/sendfile_SUITE.erl @@ -0,0 +1,355 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2011-2011. 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(sendfile_SUITE). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("kernel/include/file.hrl"). + +-compile(export_all). + +all() -> + [t_sendfile_small + ,t_sendfile_big + ,t_sendfile_partial + ,t_sendfile_offset + ,t_sendfile_sendafter + ,t_sendfile_recvafter + ,t_sendfile_sendduring + ,t_sendfile_recvduring + ,t_sendfile_closeduring + ,t_sendfile_crashduring + ]. + +init_per_suite(Config) -> + Priv = ?config(priv_dir, Config), + SFilename = filename:join(Priv, "sendfile_small.html"), + {ok, DS} = file:open(SFilename,[write,raw]), + file:write(DS,"yo baby yo"), + file:sync(DS), + file:close(DS), + BFilename = filename:join(Priv, "sendfile_big.html"), + {ok, DB} = file:open(BFilename,[write,raw]), + [file:write(DB,[<<0:(10*8*1024*1024)>>]) || _I <- lists:seq(1,51)], + file:sync(DB), + file:close(DB), + [{small_file, SFilename}, + {file_opts,[raw,binary]}, + {big_file, BFilename}|Config]. + +end_per_suite(Config) -> + file:delete(proplists:get_value(big_file, Config)). + +init_per_testcase(TC,Config) when TC == t_sendfile_recvduring; + TC == t_sendfile_sendduring -> + Filename = proplists:get_value(small_file, Config), + + Send = fun(Sock) -> + {_Size, Data} = sendfile_file_info(Filename), + {ok,D} = file:open(Filename, [raw,binary,read]), + prim_file:sendfile(D, Sock, 0, 0, 0, + [],[],false,false,false), + Data + end, + + %% Check if sendfile is supported on this platform + case catch sendfile_send(Send) of + ok -> + Config; + Error -> + ct:log("Error: ~p",[Error]), + {skip,"Not supported"} + end; +init_per_testcase(_Tc,Config) -> + Config. + + +t_sendfile_small(Config) when is_list(Config) -> + Filename = proplists:get_value(small_file, Config), + + Send = fun(Sock) -> + {Size, Data} = sendfile_file_info(Filename), + {ok, Size} = file:sendfile(Filename, Sock), + Data + end, + + ok = sendfile_send(Send). + +t_sendfile_big(Config) when is_list(Config) -> + Filename = proplists:get_value(big_file, Config), + + Send = fun(Sock) -> + {ok, #file_info{size = Size}} = + file:read_file_info(Filename), + {ok, Size} = file:sendfile(Filename, Sock), + Size + end, + + ok = sendfile_send({127,0,0,1}, Send, 0). + +t_sendfile_partial(Config) -> + Filename = proplists:get_value(small_file, Config), + FileOpts = proplists:get_value(file_opts, Config, []), + + SendSingle = fun(Sock) -> + {_Size, <<Data:5/binary,_/binary>>} = + sendfile_file_info(Filename), + {ok,D} = file:open(Filename,[read|FileOpts]), + {ok,5} = file:sendfile(D,Sock,0,5,[]), + file:close(D), + Data + end, + ok = sendfile_send(SendSingle), + + {_Size, <<FData:5/binary,SData:3/binary,_/binary>>} = + sendfile_file_info(Filename), + {ok,D} = file:open(Filename,[read|FileOpts]), + {ok, <<FData/binary>>} = file:read(D,5), + FSend = fun(Sock) -> + {ok,5} = file:sendfile(D,Sock,0,5,[]), + FData + end, + + ok = sendfile_send(FSend), + + SSend = fun(Sock) -> + {ok,3} = file:sendfile(D,Sock,5,3,[]), + SData + end, + + ok = sendfile_send(SSend), + + {ok, <<SData/binary>>} = file:read(D,3), + + file:close(D). + +t_sendfile_offset(Config) -> + Filename = proplists:get_value(small_file, Config), + FileOpts = proplists:get_value(file_opts, Config, []), + + Send = fun(Sock) -> + {_Size, <<_:5/binary,Data:3/binary,_/binary>> = AllData} = + sendfile_file_info(Filename), + {ok,D} = file:open(Filename,[read|FileOpts]), + {ok,3} = file:sendfile(D,Sock,5,3,[]), + {ok, AllData} = file:read(D,100), + file:close(D), + Data + end, + ok = sendfile_send(Send). + + +t_sendfile_sendafter(Config) -> + Filename = proplists:get_value(small_file, Config), + + Send = fun(Sock) -> + {Size, Data} = sendfile_file_info(Filename), + {ok, Size} = file:sendfile(Filename, Sock), + ok = gen_tcp:send(Sock, <<2>>), + <<Data/binary,2>> + end, + + ok = sendfile_send(Send). + +t_sendfile_recvafter(Config) -> + Filename = proplists:get_value(small_file, Config), + + Send = fun(Sock) -> + {Size, Data} = sendfile_file_info(Filename), + {ok, Size} = file:sendfile(Filename, Sock), + ok = gen_tcp:send(Sock, <<1>>), + {ok,<<1>>} = gen_tcp:recv(Sock, 1), + <<Data/binary,1>> + end, + + ok = sendfile_send(Send). + +t_sendfile_sendduring(Config) -> + Filename = proplists:get_value(big_file, Config), + + Send = fun(Sock) -> + {ok, #file_info{size = Size}} = + file:read_file_info(Filename), + spawn_link(fun() -> + timer:sleep(50), + ok = gen_tcp:send(Sock, <<2>>) + end), + {ok, Size} = file:sendfile(Filename, Sock), + Size+1 + end, + + ok = sendfile_send({127,0,0,1}, Send, 0). + +t_sendfile_recvduring(Config) -> + Filename = proplists:get_value(big_file, Config), + + Send = fun(Sock) -> + {ok, #file_info{size = Size}} = + file:read_file_info(Filename), + spawn_link(fun() -> + timer:sleep(50), + ok = gen_tcp:send(Sock, <<1>>), + {ok,<<1>>} = gen_tcp:recv(Sock, 1) + end), + {ok, Size} = file:sendfile(Filename, Sock), + timer:sleep(1000), + Size+1 + end, + + ok = sendfile_send({127,0,0,1}, Send, 0). + +t_sendfile_closeduring(Config) -> + Filename = proplists:get_value(big_file, Config), + + Send = fun(Sock,SFServPid) -> + spawn_link(fun() -> + timer:sleep(50), + SFServPid ! stop + end), + case erlang:system_info(thread_pool_size) of + 0 -> + {error, closed} = file:sendfile(Filename, Sock); + _Else -> + %% This can return how much has been sent or + %% {error,closed} depending on OS. + %% How much is sent impossible to know as + %% the socket was closed mid sendfile + case file:sendfile(Filename, Sock) of + {error, closed} -> + ok; + {ok, Size} when is_integer(Size) -> + ok + end + end, + -1 + end, + + ok = sendfile_send({127,0,0,1}, Send, 0). + +t_sendfile_crashduring(Config) -> + Filename = proplists:get_value(big_file, Config), + + error_logger:add_report_handler(?MODULE,[self()]), + + Send = fun(Sock) -> + spawn_link(fun() -> + timer:sleep(50), + exit(die) + end), + {error, closed} = file:sendfile(Filename, Sock), + -1 + end, + process_flag(trap_exit,true), + spawn_link(fun() -> + ok = sendfile_send({127,0,0,1}, Send, 0) + end), + receive + {stolen,Reason} -> + process_flag(trap_exit,false), + ct:fail(Reason) + after 200 -> + receive + {'EXIT',_,Reason} -> + process_flag(trap_exit,false), + die = Reason + end + end. + +%% Generic sendfile server code +sendfile_send(Send) -> + sendfile_send({127,0,0,1},Send). +sendfile_send(Host, Send) -> + sendfile_send(Host, Send, []). +sendfile_send(Host, Send, Orig) -> + SFServer = spawn_link(?MODULE, sendfile_server, [self(), Orig]), + receive + {server, Port} -> + {ok, Sock} = gen_tcp:connect(Host, Port, + [binary,{packet,0}, + {active,false}]), + Data = case proplists:get_value(arity,erlang:fun_info(Send)) of + 1 -> + Send(Sock); + 2 -> + Send(Sock, SFServer) + end, + ok = gen_tcp:close(Sock), + receive + {ok, Bin} -> + Data = Bin, + ok + end + end. + +sendfile_server(ClientPid, Orig) -> + {ok, LSock} = gen_tcp:listen(0, [binary, {packet, 0}, + {active, true}, + {reuseaddr, true}]), + {ok, Port} = inet:port(LSock), + ClientPid ! {server, Port}, + {ok, Sock} = gen_tcp:accept(LSock), + {ok, Bin} = sendfile_do_recv(Sock, Orig), + ClientPid ! {ok, Bin}, + gen_tcp:send(Sock, <<1>>). + +-define(SENDFILE_TIMEOUT, 10000). +sendfile_do_recv(Sock, Bs) -> + receive + stop when Bs /= 0,is_integer(Bs) -> + gen_tcp:close(Sock), + {ok, -1}; + {tcp, Sock, B} -> + case binary:match(B,<<1>>) of + nomatch when is_list(Bs) -> + sendfile_do_recv(Sock, [B|Bs]); + nomatch when is_integer(Bs) -> + sendfile_do_recv(Sock, byte_size(B) + Bs); + _ when is_list(Bs) -> + ct:log("Stopped due to a 1"), + {ok, iolist_to_binary(lists:reverse([B|Bs]))}; + _ when is_integer(Bs) -> + ct:log("Stopped due to a 1"), + {ok, byte_size(B) + Bs} + end; + {tcp_closed, Sock} when is_list(Bs) -> + ct:log("Stopped due to close"), + {ok, iolist_to_binary(lists:reverse(Bs))}; + {tcp_closed, Sock} when is_integer(Bs) -> + ct:log("Stopped due to close"), + {ok, Bs} + after ?SENDFILE_TIMEOUT -> + ct:log("Sendfile timeout"), + timeout + end. + +sendfile_file_info(File) -> + {ok, #file_info{size = Size}} = file:read_file_info(File), + {ok, Data} = file:read_file(File), + {Size, Data}. + + +%% Error handler + +init([Proc]) -> {ok,Proc}. + +handle_event({error,noproc,{emulator,Format,Args}}, Proc) -> + Proc ! {stolen,lists:flatten(io_lib:format(Format,Args))}, + {ok,Proc}; +handle_event(_, Proc) -> + {ok,Proc}. diff --git a/lib/kernel/test/wrap_log_reader_SUITE.erl b/lib/kernel/test/wrap_log_reader_SUITE.erl index ffc8def626..96dc3e6d33 100644 --- a/lib/kernel/test/wrap_log_reader_SUITE.erl +++ b/lib/kernel/test/wrap_log_reader_SUITE.erl @@ -561,4 +561,4 @@ rec(M, Where) -> end. pps() -> - {erlang:ports(), lists:filter({erlang, is_process_alive}, processes())}. + {erlang:ports(), lists:filter(fun erlang:is_process_alive/1, processes())}. |