aboutsummaryrefslogtreecommitdiffstats
path: root/lib/inets/test
diff options
context:
space:
mode:
authorPéter Dimitrov <[email protected]>2018-03-20 11:26:01 +0100
committerPéter Dimitrov <[email protected]>2018-03-28 10:19:38 +0200
commit09ccfa2a6a8f8df55c7d808f5ad26324ac1e81b6 (patch)
treedb6e9a1172ee8bb761041e352b6dc637fd765d28 /lib/inets/test
parent3c41882115f2cd9bfda8318925b4352cd1ec06b7 (diff)
downloadotp-09ccfa2a6a8f8df55c7d808f5ad26324ac1e81b6.tar.gz
otp-09ccfa2a6a8f8df55c7d808f5ad26324ac1e81b6.tar.bz2
otp-09ccfa2a6a8f8df55c7d808f5ad26324ac1e81b6.zip
inets,tftp: Break out TFTP from inets
- Create directory structure - Move code, tests, documentation from inets - Add inets_tftp_wrapper - Add tftp app to run-dialyzer script Change-Id: I6a142ae66cecb9a1821cbf9ea6a45f66a836763d
Diffstat (limited to 'lib/inets/test')
-rw-r--r--lib/inets/test/Makefile15
-rw-r--r--lib/inets/test/inets_SUITE.erl38
-rw-r--r--lib/inets/test/inets_socketwrap_SUITE.erl34
-rw-r--r--lib/inets/test/inets_sup_SUITE.erl24
-rw-r--r--lib/inets/test/tftp_SUITE.erl949
-rw-r--r--lib/inets/test/tftp_test_lib.erl308
-rw-r--r--lib/inets/test/tftp_test_lib.hrl44
7 files changed, 7 insertions, 1405 deletions
diff --git a/lib/inets/test/Makefile b/lib/inets/test/Makefile
index 4dab4e14c6..0e33b72095 100644
--- a/lib/inets/test/Makefile
+++ b/lib/inets/test/Makefile
@@ -138,8 +138,6 @@ MODULES = \
httpd_test_lib \
inets_sup_SUITE \
inets_SUITE \
- tftp_test_lib \
- tftp_SUITE \
uri_SUITE \
inets_socketwrap_SUITE
@@ -149,8 +147,7 @@ EBIN = .
HRL_FILES = inets_test_lib.hrl \
inets_internal.hrl \
httpc_internal.hrl \
- http_internal.hrl \
- tftp_test_lib.hrl
+ http_internal.hrl
ERL_FILES = $(MODULES:%=%.erl)
@@ -165,8 +162,7 @@ INETS_FILES = inets.config $(INETS_SPECS)
# SUB_SUITES = \
# inets_sup_suite \
# inets_httpd_suite \
-# inets_httpc_suite \
-# inets_tftp_suite
+# inets_httpc_suite
INETS_DATADIRS = inets_SUITE_data inets_socketwrap_SUITE_data
@@ -299,10 +295,3 @@ info:
@echo "INETS_PRIV_DIR = $(INETS_PRIV_DIR)"
@echo "INETS_ROOT = $(INETS_ROOT)"
@echo "INETS_FLAGS = $(INETS_FLAGS)"
-
-tftp:
- erlc $(ERL_COMPILE_FLAGS) tftp_test_lib.erl tftp_SUITE.erl && erl -pa ../../inets/ebin -s tftp_SUITE t -s erlang halt
-
-tftp_work:
- echo "tftp_test_lib:t([{tftp_SUITE, all}])."
- erlc $(ERL_COMPILE_FLAGS) tftp_test_lib.erl tftp_SUITE.erl && erl -pa ../../inets/ebin
diff --git a/lib/inets/test/inets_SUITE.erl b/lib/inets/test/inets_SUITE.erl
index 12db2479d2..07ce594a1d 100644
--- a/lib/inets/test/inets_SUITE.erl
+++ b/lib/inets/test/inets_SUITE.erl
@@ -41,8 +41,7 @@ groups() ->
[{services_test, [],
[start_inets,
start_httpc,
- start_httpd,
- start_tftpd
+ start_httpd
]},
{app_test, [], [app, appup]}].
@@ -297,41 +296,6 @@ start_httpd(Config) when is_list(Config) ->
%%-------------------------------------------------------------------------
-start_tftpd() ->
- [{doc, "Start/stop of tfpd service"}].
-start_tftpd(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- ok = inets:start(),
- {ok, Pid0} = inets:start(tftpd, [{host, "localhost"}, {port, 0}]),
- Pids0 = [ServicePid || {_, ServicePid} <- inets:services()],
- true = lists:member(Pid0, Pids0),
- [_|_] = inets:services_info(),
- inets:stop(tftpd, Pid0),
- ct:sleep(100),
- Pids1 = [ServicePid || {_, ServicePid} <- inets:services()],
- false = lists:member(Pid0, Pids1),
- {ok, Pid1} =
- inets:start(tftpd, [{host, "localhost"}, {port, 0}], stand_alone),
- Pids2 = [ServicePid || {_, ServicePid} <- inets:services()],
- false = lists:member(Pid1, Pids2),
- ok = inets:stop(stand_alone, Pid1),
- receive
- {'EXIT', Pid1, shutdown} ->
- ok
- after 100 ->
- ct:fail(stand_alone_not_shutdown)
- end,
- ok = inets:stop(),
- application:load(inets),
- application:set_env(inets, services, [{tftpd,[{host, "localhost"},
- {port, 0}]}]),
- ok = inets:start(),
- (?NUM_DEFAULT_SERVICES + 1) = length(inets:services()),
- application:unset_env(inets, services),
- ok = inets:stop().
-
-%%-------------------------------------------------------------------------
-
httpd_reload() ->
[{doc, "Reload httpd configuration without restarting service"}].
httpd_reload(Config) when is_list(Config) ->
diff --git a/lib/inets/test/inets_socketwrap_SUITE.erl b/lib/inets/test/inets_socketwrap_SUITE.erl
index 7ea7e08ed1..fc87c595a9 100644
--- a/lib/inets/test/inets_socketwrap_SUITE.erl
+++ b/lib/inets/test/inets_socketwrap_SUITE.erl
@@ -30,7 +30,7 @@ suite() ->
[{ct_hooks,[ts_install_cth]}].
all() ->
- [start_httpd_fd, start_tftpd_fd].
+ [start_httpd_fd].
init_per_suite(Config) ->
case os:type() of
@@ -90,37 +90,7 @@ start_httpd_fd(Config) when is_list(Config) ->
ct:fail(open_port_failed)
end
end.
-%%-------------------------------------------------------------------------
-start_tftpd_fd() ->
- [{doc, "Start/stop of tfpd service with socket wrapper"}].
-start_tftpd_fd(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- case setup_node_info(node()) of
- {skip, _} = Skip ->
- Skip;
- {Node, NodeArg} ->
- InetPort = inets_test_lib:inet_port(node()),
- ct:pal("Node: ~p~n", [Node]),
- Wrapper = filename:join(DataDir, "setuid_socket_wrap"),
- Cmd = Wrapper ++
- " -s -tftpd_69,0:" ++ integer_to_list(InetPort)
- ++ " -p " ++ os:find_executable("erl") ++
- " -- " ++ NodeArg,
- ct:pal("cmd: ~p~n", [Cmd]),
- case open_port({spawn, Cmd}, [stderr_to_stdout]) of
- Port when is_port(Port) ->
- wait_node_up(Node, 10),
- ct:pal("~p", [rpc:call(Node, init, get_argument, [tftpd_69])]),
- ok = rpc:call(Node, inets, start, []),
- {ok, Pid} = rpc:call(Node, inets, start,
- [tftpd,[{host, "localhost"}]]),
- {ok, Info} = rpc:call(Node, tftp, info, [Pid]),
- {value,{port, InetPort}} = lists:keysearch(port, 1, Info),
- rpc:call(Node, erlang, halt, []);
- _ ->
- ct:fail(open_port_failed)
- end
- end.
+
%%-------------------------------------------------------------------------
%% Internal functions
%%-------------------------------------------------------------------------
diff --git a/lib/inets/test/inets_sup_SUITE.erl b/lib/inets/test/inets_sup_SUITE.erl
index d36d4dc53e..727e91e987 100644
--- a/lib/inets/test/inets_sup_SUITE.erl
+++ b/lib/inets/test/inets_sup_SUITE.erl
@@ -32,8 +32,7 @@ suite() ->
].
all() ->
- [default_tree, tftpd_worker,
- httpd_config, httpd_subtree, httpd_subtree_profile,
+ [default_tree, httpd_config, httpd_subtree, httpd_subtree_profile,
httpc_subtree].
groups() ->
@@ -147,13 +146,11 @@ default_tree() ->
"in the default case."}].
default_tree(Config) when is_list(Config) ->
TopSupChildren = supervisor:which_children(inets_sup),
- 3 = length(TopSupChildren),
+ 2 = length(TopSupChildren),
{value, {httpd_sup, _, supervisor,[httpd_sup]}} =
lists:keysearch(httpd_sup, 1, TopSupChildren),
{value, {httpc_sup, _,supervisor,[httpc_sup]}} =
lists:keysearch(httpc_sup, 1, TopSupChildren),
- {value, {tftp_sup,_,supervisor,[tftp_sup]}} =
- lists:keysearch(tftp_sup, 1, TopSupChildren),
HttpcSupChildren = supervisor:which_children(httpc_sup),
{value, {httpc_profile_sup,_, supervisor, [httpc_profile_sup]}} =
@@ -168,24 +165,7 @@ default_tree(Config) when is_list(Config) ->
= supervisor:which_children(httpc_profile_sup),
[] = supervisor:which_children(httpc_handler_sup),
-
- [] = supervisor:which_children(tftp_sup),
-
- ok.
-tftpd_worker() ->
- [{doc, "Makes sure the tftp sub tree is correct."}].
-tftpd_worker(Config) when is_list(Config) ->
- [] = supervisor:which_children(tftp_sup),
- {ok, Pid0} = inets:start(tftpd, [{host, inets_test_lib:hostname()},
- {port, 0}]),
- {ok, _Pid1} = inets:start(tftpd, [{host, inets_test_lib:hostname()},
- {port, 0}], stand_alone),
-
- [{_,Pid0, worker, _}] = supervisor:which_children(tftp_sup),
- inets:stop(tftpd, Pid0),
- ct:sleep(5000),
- [] = supervisor:which_children(tftp_sup),
ok.
httpd_config() ->
diff --git a/lib/inets/test/tftp_SUITE.erl b/lib/inets/test/tftp_SUITE.erl
deleted file mode 100644
index 09049e36af..0000000000
--- a/lib/inets/test/tftp_SUITE.erl
+++ /dev/null
@@ -1,949 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2006-2016. 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(tftp_SUITE).
-
--compile(export_all).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Includes and defines
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
--include("tftp_test_lib.hrl").
-
--define(START_DAEMON(PortX, OptionsX),
- fun(Port, Options) ->
- {ok, Pid} = ?VERIFY({ok, _Pid}, tftp:start([{port, Port} | Options])),
- if
- Port == 0 ->
- {ok, ActualOptions} = ?IGNORE(tftp:info(Pid)),
- {value, {port, ActualPort}} =
- lists:keysearch(port, 1, ActualOptions),
- {ActualPort, Pid};
- true ->
- {Port, Pid}
- end
- end(PortX, OptionsX)).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% API
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-t() ->
- tftp_test_lib:t([{?MODULE, all}]).
-
-t(Cases) ->
- tftp_test_lib:t(Cases, default_config()).
-
-t(Cases, Config) ->
- tftp_test_lib:t(Cases, Config).
-
-default_config() ->
- [].
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Test server callbacks
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-init_per_testcase(Case, Config) ->
- tftp_test_lib:init_per_testcase(Case, Config).
-
-end_per_testcase(Case, Config) when is_list(Config) ->
- tftp_test_lib:end_per_testcase(Case, Config).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Top test case
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [simple, extra, reuse_connection, resend_client,
- resend_server, large_file].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Simple
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-simple(doc) ->
- ["Start the daemon and perform simple a read and write."];
-simple(suite) ->
- [];
-simple(Config) when is_list(Config) ->
- ?VERIFY(ok, application:start(inets)),
-
- {Port, DaemonPid} = ?IGNORE(?START_DAEMON(0, [{debug, brief}])),
-
- %% Read fail
- RemoteFilename = "tftp_temporary_remote_test_file.txt",
- LocalFilename = "tftp_temporary_local_test_file.txt",
- Blob = list_to_binary(lists:duplicate(2000, $1)),
- %% Blob = <<"Some file contents\n">>,
- Size = size(Blob),
- ?IGNORE(file:delete(RemoteFilename)),
- ?VERIFY({error, {client_open, enoent, _}},
- tftp:read_file(RemoteFilename, binary, [{port, Port}])),
-
- %% Write and read
- ?VERIFY({ok, Size}, tftp:write_file(RemoteFilename, Blob, [{port, Port}])),
- ?VERIFY({ok, Blob}, tftp:read_file(RemoteFilename, binary, [{port, Port}])),
- ?IGNORE(file:delete(LocalFilename)),
- ?VERIFY({ok, Size}, tftp:read_file(RemoteFilename, LocalFilename, [{port, Port}])),
-
- %% Cleanup
- unlink(DaemonPid),
- exit(DaemonPid, kill),
- ?VERIFY(ok, file:delete(LocalFilename)),
- ?VERIFY(ok, file:delete(RemoteFilename)),
- ?VERIFY(ok, application:stop(inets)),
- ok.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Extra
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-extra(doc) ->
- ["Verify new stuff for IS 1.2."];
-extra(suite) ->
- [];
-extra(Config) when is_list(Config) ->
- ?VERIFY({'EXIT', {badarg,{fake_key, fake_flag}}},
- tftp:start([{port, 0}, {fake_key, fake_flag}])),
-
- {Port, DaemonPid} = ?IGNORE(?START_DAEMON(0, [{debug, brief}])),
-
- RemoteFilename = "tftp_extra_temporary_remote_test_file.txt",
- LocalFilename = "tftp_extra_temporary_local_test_file.txt",
- Blob = <<"Some file contents\n">>,
- Size = size(Blob),
- Host = "127.0.0.1",
- Peer = {inet, Host, Port},
- Generic =
- [
- {state, []},
- {prepare, fun extra_prepare/6},
- {open, fun extra_open/6},
- {read, fun extra_read/1},
- {write, fun extra_write/2},
- {abort, fun extra_abort/3 }
- ],
- Options = [{host, Host},
- {port, Port},
- %%{ debug,all},
- {callback, {".*", tftp_test_lib, Generic}}],
- ?VERIFY(ok, file:write_file(LocalFilename, Blob)),
- ?VERIFY({ok, [{count, Size}, Peer]},
- tftp:write_file(RemoteFilename, LocalFilename, Options)),
- ?VERIFY(ok, file:delete(LocalFilename)),
-
- ?VERIFY({ok,[{bin, Blob}, Peer]},
- tftp:read_file(RemoteFilename, LocalFilename, Options)),
-
- %% Cleanup
- unlink(DaemonPid),
- exit(DaemonPid, kill),
- ?VERIFY(ok, file:delete(LocalFilename)),
- ?VERIFY(ok, file:delete(RemoteFilename)),
- ok.
-
--record(extra_state, {file, blksize, count, acc, peer}).
-
-%%-------------------------------------------------------------------
-%% Prepare
-%%-------------------------------------------------------------------
-
-extra_prepare(Peer, Access, LocalFilename, Mode, SuggestedOptions, []) ->
- %% Client side
- BlkSize = list_to_integer(tftp_test_lib:lookup_option("blksize", "512", SuggestedOptions)),
- State = #extra_state{blksize = BlkSize, peer = Peer},
- extra_open(Peer, Access, LocalFilename, Mode, SuggestedOptions, State),
- {ok, SuggestedOptions, State};
-extra_prepare(_Peer, _Access, _Bin, _Mode, _SuggestedOptions, _Initial) ->
- {error, {undef, "Illegal callback options."}}.
-
-%%-------------------------------------------------------------------
-%% Open
-%%-------------------------------------------------------------------
-
-extra_open(Peer, Access, LocalFilename, Mode, SuggestedOptions, []) ->
- %% Server side
- case extra_prepare(Peer, Access, LocalFilename, Mode, SuggestedOptions, []) of
- {ok, AcceptedOptions, []} ->
- BlkSize = list_to_integer(tftp_test_lib:lookup_option("blksize", "512", AcceptedOptions)),
- State = #extra_state{blksize = BlkSize, peer = Peer},
- extra_open(Peer, Access, LocalFilename, Mode, AcceptedOptions, State);
- {error, {Code, Text}} ->
- {error, {Code, Text}}
- end;
-extra_open(_Peer, Access, LocalFilename, _Mode, NegotiatedOptions, #extra_state{} = State) ->
- {File, Acc} =
- case Access of
- read ->
- if
- is_binary(LocalFilename) ->
- {undefined, LocalFilename};
- is_list(LocalFilename) ->
- {ok, Bin} = file:read_file(LocalFilename),
- {LocalFilename, Bin}
- end;
- write ->
- {LocalFilename, []}
- end,
- %% Both sides
- State2 = State#extra_state{file = File, acc = Acc, count = 0},
- {ok, NegotiatedOptions, State2}.
-
-%%-------------------------------------------------------------------
-%% Read
-%%-------------------------------------------------------------------
-
-extra_read(#extra_state{acc = Bin} = State) when is_binary(Bin) ->
- BlkSize = State#extra_state.blksize,
- Count = State#extra_state.count + size(Bin),
- if
- size(Bin) >= BlkSize ->
- <<Block:BlkSize/binary, Bin2/binary>> = Bin,
- State2 = State#extra_state{acc = Bin2, count = Count},
- {more, Block, State2};
- size(Bin) < BlkSize ->
- Res = [{count, Count}, State#extra_state.peer],
- {last, Bin, Res}
- end.
-
-%%-------------------------------------------------------------------
-%% Write
-%%-------------------------------------------------------------------
-
-extra_write(Bin, #extra_state{acc = List} = State) when is_binary(Bin), is_list(List) ->
- Size = size(Bin),
- BlkSize = State#extra_state.blksize,
- if
- Size == BlkSize ->
- {more, State#extra_state{acc = [Bin | List]}};
- Size < BlkSize ->
- Bin2 = list_to_binary(lists:reverse([Bin | List])),
- Res = [{bin, Bin2}, State#extra_state.peer],
- file:write_file(State#extra_state.file, Bin2),
- {last, Res}
- end.
-
-%%-------------------------------------------------------------------
-%% Abort
-%%-------------------------------------------------------------------
-
-extra_abort(_Code, _Text, #extra_state{}) ->
- ok.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Re-send client
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-resend_client(doc) ->
- ["Verify that the server behaves correctly when the client re-sends packets."];
-resend_client(suite) ->
- [];
-resend_client(Config) when is_list(Config) ->
- Host = {127, 0, 0, 1},
- {Port, DaemonPid} = ?IGNORE(?START_DAEMON(0, [{debug, all}])),
-
- ?VERIFY(ok, resend_read_client(Host, Port, 10)),
- ?VERIFY(ok, resend_read_client(Host, Port, 512)),
- ?VERIFY(ok, resend_read_client(Host, Port, 1025)),
-
- ?VERIFY(ok, resend_write_client(Host, Port, 10)),
- ?VERIFY(ok, resend_write_client(Host, Port, 512)),
- ?VERIFY(ok, resend_write_client(Host, Port, 1025)),
-
- %% Cleanup
- unlink(DaemonPid),
- exit(DaemonPid, kill),
- ok.
-
-resend_read_client(Host, Port, BlkSize) ->
- RemoteFilename = "tftp_resend_read_client.tmp",
- Block1 = lists:duplicate(BlkSize, $1),
- Block2 = lists:duplicate(BlkSize, $2),
- Block3 = lists:duplicate(BlkSize, $3),
- Block4 = lists:duplicate(BlkSize, $4),
- Block5 = lists:duplicate(BlkSize, $5),
- Blocks = [Block1, Block2, Block3, Block4, Block5],
- Blob = list_to_binary(Blocks),
- ?VERIFY(ok, file:write_file(RemoteFilename, Blob)),
-
- Timeout = timer:seconds(3),
- ?VERIFY(timeout, recv(0)),
-
- %% Open socket
- {ok, Socket} = ?VERIFY({ok, _}, gen_udp:open(0, [binary, {reuseaddr, true}, {active, true}])),
-
- ReadList = [0, 1, RemoteFilename, 0, "octet", 0],
- Data1Bin = list_to_binary([0, 3, 0, 1 | Block1]),
- NewPort =
- if
- BlkSize =:= 512 ->
- %% Send READ
- ReadBin = list_to_binary(ReadList),
- ?VERIFY(ok, gen_udp:send(Socket, Host, Port, ReadBin)),
-
- %% Sleep a while in order to provoke the server to re-send the packet
- timer:sleep(Timeout + timer:seconds(1)),
-
- %% Recv DATA #1 (the packet that the server think that we have lost)
- {udp, _, _, NewPort0, _} = ?VERIFY({udp, Socket, Host, _, Data1Bin}, recv(Timeout)),
- NewPort0;
- true ->
- %% Send READ
- BlkSizeList = integer_to_list(BlkSize),
- Options = ["blksize", 0, BlkSizeList, 0],
- ReadBin = list_to_binary([ReadList | Options]),
- ?VERIFY(ok, gen_udp:send(Socket, Host, Port, ReadBin)),
-
- %% Recv OACK
- OptionAckBin = list_to_binary([0, 6 | Options]),
- {udp, _, _, NewPort0, _} = ?VERIFY({udp, Socket, Host, _, OptionAckBin}, recv(Timeout)),
-
- %% Send ACK #0
- Ack0Bin = <<0, 4, 0, 0>>,
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort0, Ack0Bin)),
-
- %% Send ACK #0 AGAIN (pretend that we timed out)
- timer:sleep(timer:seconds(1)),
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort0, Ack0Bin)),
-
- %% Recv DATA #1 (the packet that the server think that we have lost)
- ?VERIFY({udp, Socket, Host, NewPort0, Data1Bin}, recv(Timeout)),
- NewPort0
- end,
-
- %% Recv DATA #1 AGAIN (the re-sent package)
- ?VERIFY({udp, Socket, Host, NewPort, Data1Bin}, recv(Timeout)),
-
- %% Send ACK #1
- Ack1Bin = <<0, 4, 0, 1>>,
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack1Bin)),
-
- %% Recv DATA #2
- Data2Bin = list_to_binary([0, 3, 0, 2 | Block2]),
- ?VERIFY({udp, Socket, Host, NewPort, Data2Bin}, recv(Timeout)),
-
- %% Send ACK #2
- Ack2Bin = <<0, 4, 0, 2>>,
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack2Bin)),
-
- %% Recv DATA #3
- Data3Bin = list_to_binary([0, 3, 0, 3 | Block3]),
- ?VERIFY({udp, Socket, Host, NewPort, Data3Bin}, recv(Timeout)),
-
- %% Send ACK #3
- Ack3Bin = <<0, 4, 0, 3>>,
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack3Bin)),
-
- %% Send ACK #3 AGAIN (pretend that we timed out)
- timer:sleep(timer:seconds(1)),
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack3Bin)),
-
- %% Recv DATA #4 (the packet that the server think that we have lost)
- Data4Bin = list_to_binary([0, 3, 0, 4 | Block4]),
- ?VERIFY({udp, Socket, Host, NewPort, Data4Bin}, recv(Timeout)),
-
- %% Recv DATA #4 AGAIN (the re-sent package)
- ?VERIFY({udp, Socket, Host, NewPort, Data4Bin}, recv(Timeout)),
-
- %% Send ACK #2 which is out of range
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack2Bin)),
-
- %% Send ACK #4
- Ack4Bin = <<0, 4, 0, 4>>,
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack4Bin)),
-
- %% Recv DATA #5
- Data5Bin = list_to_binary([0, 3, 0, 5 | Block5]),
- ?VERIFY({udp, Socket, Host, NewPort, Data5Bin}, recv(Timeout)),
-
- %% Send ACK #5
- Ack5Bin = <<0, 4, 0, 5>>,
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack5Bin)),
-
- %% Close socket
- ?VERIFY(ok, gen_udp:close(Socket)),
-
- ?VERIFY(timeout, recv(Timeout)),
- ?VERIFY(ok, file:delete(RemoteFilename)),
- ok.
-
-resend_write_client(Host, Port, BlkSize) ->
- RemoteFilename = "tftp_resend_write_client.tmp",
- Block1 = lists:duplicate(BlkSize, $1),
- Block2 = lists:duplicate(BlkSize, $2),
- Block3 = lists:duplicate(BlkSize, $3),
- Block4 = lists:duplicate(BlkSize, $4),
- Block5 = lists:duplicate(BlkSize, $5),
- Blocks = [Block1, Block2, Block3, Block4, Block5],
- Blob = list_to_binary(Blocks),
- ?IGNORE(file:delete(RemoteFilename)),
- ?VERIFY({error, enoent}, file:read_file(RemoteFilename)),
-
- Timeout = timer:seconds(3),
- ?VERIFY(timeout, recv(0)),
-
- %% Open socket
- {ok, Socket} = ?VERIFY({ok, _}, gen_udp:open(0, [binary, {reuseaddr, true}, {active, true}])),
-
- WriteList = [0, 2, RemoteFilename, 0, "octet", 0],
- NewPort =
- if
- BlkSize =:= 512 ->
- %% Send WRITE
- WriteBin = list_to_binary(WriteList),
- ?VERIFY(ok, gen_udp:send(Socket, Host, Port, WriteBin)),
-
- %% Sleep a while in order to provoke the server to re-send the packet
- timer:sleep(Timeout + timer:seconds(1)),
-
- %% Recv ACK #0 (the packet that the server think that we have lost)
- Ack0Bin = <<0, 4, 0, 0>>,
- ?VERIFY({udp, Socket, Host, _, Ack0Bin}, recv(Timeout)),
-
- %% Recv ACK #0 AGAIN (the re-sent package)
- {udp, _, _, NewPort0, _} = ?VERIFY({udp, Socket, Host, _, Ack0Bin}, recv(Timeout)),
- NewPort0;
- true ->
- %% Send WRITE
- BlkSizeList = integer_to_list(BlkSize),
- WriteBin = list_to_binary([WriteList, "blksize", 0, BlkSizeList, 0]),
- ?VERIFY(ok, gen_udp:send(Socket, Host, Port, WriteBin)),
-
- %% Sleep a while in order to provoke the server to re-send the packet
- timer:sleep(timer:seconds(1)),
-
- %% Recv OACK (the packet that the server think that we have lost)
- OptionAckBin = list_to_binary([0, 6, "blksize",0, BlkSizeList, 0]),
- ?VERIFY({udp, Socket, Host, _, OptionAckBin}, recv(Timeout)),
-
- %% Recv OACK AGAIN (the re-sent package)
- {udp, _, _, NewPort0, _} = ?VERIFY({udp, Socket, Host, _, OptionAckBin}, recv(Timeout)),
- NewPort0
- end,
-
- %% Send DATA #1
- Data1Bin = list_to_binary([0, 3, 0, 1 | Block1]),
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Data1Bin)),
-
- %% Recv ACK #1
- Ack1Bin = <<0, 4, 0, 1>>,
- ?VERIFY({udp, Socket, Host, NewPort, Ack1Bin}, recv(Timeout)),
-
- %% Send DATA #2
- Data2Bin = list_to_binary([0, 3, 0, 2 | Block2]),
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Data2Bin)),
-
- %% Recv ACK #2
- Ack2Bin = <<0, 4, 0, 2>>,
- ?VERIFY({udp, Socket, Host, NewPort, Ack2Bin}, recv(Timeout)),
-
- %% Send DATA #3
- Data3Bin = list_to_binary([0, 3, 0, 3 | Block3]),
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Data3Bin)),
-
- %% Recv ACK #3
- Ack3Bin = <<0, 4, 0, 3>>,
- ?VERIFY({udp, Socket, Host, NewPort, Ack3Bin}, recv(Timeout)),
-
- %% Send DATA #3 AGAIN (pretend that we timed out)
- timer:sleep(timer:seconds(1)),
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Data3Bin)),
-
- %% Recv ACK #3 AGAIN (the packet that the server think that we have lost)
- ?VERIFY({udp, Socket, Host, NewPort, Ack3Bin}, recv(Timeout)),
-
- %% Send DATA #2 which is out of range
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Data2Bin)),
-
- %% Send DATA #4
- Data4Bin = list_to_binary([0, 3, 0, 4 | Block4]),
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Data4Bin)),
-
- %% Recv ACK #4
- Ack4Bin = <<0, 4, 0, 4>>,
- ?VERIFY({udp, Socket, Host, NewPort, Ack4Bin}, recv(Timeout)),
-
- %% Send DATA #5
- Data5Bin = list_to_binary([0, 3, 0, 5 | Block5]),
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Data5Bin)),
-
- %% Recv ACK #5
- Ack5Bin = <<0, 4, 0, 5>>,
- ?VERIFY({udp, Socket, Host, NewPort, Ack5Bin}, recv(Timeout)),
-
- %% Close socket
- ?VERIFY(ok, gen_udp:close(Socket)),
-
- ?VERIFY(timeout, recv(Timeout)),
- ?VERIFY({ok, Blob}, file:read_file(RemoteFilename)),
- ?VERIFY(ok, file:delete(RemoteFilename)),
- ok.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Re-send server
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-resend_server(doc) ->
- ["Verify that the server behaves correctly when the server re-sends packets."];
-resend_server(suite) ->
- [];
-resend_server(Config) when is_list(Config) ->
- Host = {127, 0, 0, 1},
-
- ?VERIFY(ok, resend_read_server(Host, 10)),
- ?VERIFY(ok, resend_read_server(Host, 512)),
- ?VERIFY(ok, resend_read_server(Host, 1025)),
-
- ?VERIFY(ok, resend_write_server(Host, 10)),
- ?VERIFY(ok, resend_write_server(Host, 512)),
- ?VERIFY(ok, resend_write_server(Host, 1025)),
- ok.
-
-resend_read_server(Host, BlkSize) ->
- RemoteFilename = "tftp_resend_read_server.tmp",
- Block1 = lists:duplicate(BlkSize, $1),
- Block2 = lists:duplicate(BlkSize, $2),
- Block3 = lists:duplicate(BlkSize, $3),
- Block4 = lists:duplicate(BlkSize, $4),
- Block5 = lists:duplicate(BlkSize, $5),
- Block6 = [],
- Blocks = [Block1, Block2, Block3, Block4, Block5, Block6],
- Blob = list_to_binary(Blocks),
-
- Timeout = timer:seconds(3),
- ?VERIFY(timeout, recv(0)),
-
- %% Open daemon socket
- {ok, DaemonSocket} = ?VERIFY({ok, _}, gen_udp:open(0, [binary, {reuseaddr, true}, {active, true}])),
- {ok, DaemonPort} = ?IGNORE(inet:port(DaemonSocket)),
-
- %% Open server socket
- {ok, ServerSocket} = ?VERIFY({ok, _}, gen_udp:open(0, [binary, {reuseaddr, true}, {active, true}])),
- ?IGNORE(inet:port(ServerSocket)),
-
- %% Prepare client process
- ReplyTo = self(),
- ClientFun =
- fun(Extra) ->
- Options = [{port, DaemonPort}, {debug, brief}] ++ Extra,
- Res = ?VERIFY({ok, Blob}, tftp:read_file(RemoteFilename, binary, Options)),
- ReplyTo ! {self(), {tftp_client_reply, Res}},
- exit(normal)
- end,
-
- ReadList = [0, 1, RemoteFilename, 0, "octet", 0],
- Data1Bin = list_to_binary([0, 3, 0, 1 | Block1]),
- Ack1Bin = <<0, 4, 0, 1>>,
- {ClientPort, ClientPid} =
- if
- BlkSize =:= 512 ->
- %% Start client process
- ClientPid0 = spawn_link(fun() -> ClientFun([]) end),
-
- %% Recv READ
- ReadBin = list_to_binary(ReadList),
- {udp, _, _, ClientPort0, _} = ?VERIFY({udp, DaemonSocket, Host, _, ReadBin}, recv(Timeout)),
-
- %% Send DATA #1
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort0, Data1Bin)),
-
- %% Sleep a while in order to provoke the client to re-send the packet
- timer:sleep(Timeout + timer:seconds(1)),
-
- %% Recv ACK #1 (the packet that the server think that we have lost)
- ?VERIFY({udp, ServerSocket, Host, ClientPort0, Ack1Bin}, recv(Timeout)),
-
- %% Recv ACK #1 AGAIN (the re-sent package)
- ?VERIFY({udp, ServerSocket, Host, _, Ack1Bin}, recv(Timeout)),
- {ClientPort0, ClientPid0};
- true ->
- %% Start client process
- BlkSizeList = integer_to_list(BlkSize),
- ClientPid0 = spawn_link(fun() -> ClientFun([{"blksize", BlkSizeList}]) end),
-
- %% Recv READ
- Options = ["blksize", 0, BlkSizeList, 0],
- ReadBin = list_to_binary([ReadList | Options]),
- {udp, _, _, ClientPort0, _} = ?VERIFY({udp, DaemonSocket, Host, _, ReadBin}, recv(Timeout)),
-
- %% Send OACK
- BlkSizeList = integer_to_list(BlkSize),
- OptionAckBin = list_to_binary([0, 6, "blksize",0, BlkSizeList, 0]),
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort0, OptionAckBin)),
-
- %% Sleep a while in order to provoke the client to re-send the packet
- timer:sleep(Timeout + timer:seconds(1)),
-
- %% Recv ACK #0 (the packet that the server think that we have lost)
- Ack0Bin = <<0, 4, 0, 0>>,
- ?VERIFY({udp, ServerSocket, Host, ClientPort0, Ack0Bin}, recv(Timeout)),
-
- %% Recv ACK #0 AGAIN (the re-sent package)
- ?VERIFY({udp, ServerSocket, Host, ClientPort0, Ack0Bin}, recv(Timeout)),
-
- %% Send DATA #1
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort0, Data1Bin)),
-
- %% Recv ACK #1
- ?VERIFY({udp, ServerSocket, Host, _, Ack1Bin}, recv(Timeout)),
- {ClientPort0, ClientPid0}
- end,
-
- %% Send DATA #2
- Data2Bin = list_to_binary([0, 3, 0, 2 | Block2]),
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Data2Bin)),
-
- %% Recv ACK #2
- Ack2Bin = <<0, 4, 0, 2>>,
- ?VERIFY({udp, ServerSocket, Host, ClientPort, Ack2Bin}, recv(Timeout)),
-
- %% Send DATA #3
- Data3Bin = list_to_binary([0, 3, 0, 3 | Block3]),
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Data3Bin)),
-
- %% Recv ACK #3
- Ack3Bin = <<0, 4, 0, 3>>,
- ?VERIFY({udp, ServerSocket, Host, ClientPort, Ack3Bin}, recv(Timeout)),
-
- %% Send DATA #3 AGAIN (pretend that we timed out)
- timer:sleep(timer:seconds(1)),
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Data3Bin)),
-
- %% Recv ACK #3 AGAIN (the packet that the server think that we have lost)
- ?VERIFY({udp, ServerSocket, Host, ClientPort, Ack3Bin}, recv(Timeout)),
-
- %% Send DATA #4
- Data4Bin = list_to_binary([0, 3, 0, 4 | Block4]),
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Data4Bin)),
-
- %% Recv ACK #4
- Ack4Bin = <<0, 4, 0, 4>>,
- ?VERIFY({udp, ServerSocket, Host, ClientPort, Ack4Bin}, recv(Timeout)),
-
- %% Send DATA #3 which is out of range
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Data3Bin)),
-
- %% Send DATA #5
- Data5Bin = list_to_binary([0, 3, 0, 5 | Block5]),
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Data5Bin)),
-
- %% Recv ACK #5
- Ack5Bin = <<0, 4, 0, 5>>,
- ?VERIFY({udp, ServerSocket, Host, ClientPort, Ack5Bin}, recv(Timeout)),
-
- %% Send DATA #6
- Data6Bin = list_to_binary([0, 3, 0, 6 | Block6]),
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Data6Bin)),
-
- %% Close daemon and server sockets
- ?VERIFY(ok, gen_udp:close(ServerSocket)),
- ?VERIFY(ok, gen_udp:close(DaemonSocket)),
-
- ?VERIFY({ClientPid, {tftp_client_reply, {ok, Blob}}}, recv(Timeout)),
-
- ?VERIFY(timeout, recv(Timeout)),
- ok.
-
-resend_write_server(Host, BlkSize) ->
- RemoteFilename = "tftp_resend_write_server.tmp",
- Block1 = lists:duplicate(BlkSize, $1),
- Block2 = lists:duplicate(BlkSize, $2),
- Block3 = lists:duplicate(BlkSize, $3),
- Block4 = lists:duplicate(BlkSize, $4),
- Block5 = lists:duplicate(BlkSize, $5),
- Block6 = [],
- Blocks = [Block1, Block2, Block3, Block4, Block5, Block6],
- Blob = list_to_binary(Blocks),
- Size = size(Blob),
-
- Timeout = timer:seconds(3),
- ?VERIFY(timeout, recv(0)),
-
- %% Open daemon socket
- {ok, DaemonSocket} = ?VERIFY({ok, _}, gen_udp:open(0, [binary, {reuseaddr, true}, {active, true}])),
- {ok, DaemonPort} = ?IGNORE(inet:port(DaemonSocket)),
-
- %% Open server socket
- {ok, ServerSocket} = ?VERIFY({ok, _}, gen_udp:open(0, [binary, {reuseaddr, true}, {active, true}])),
- ?IGNORE(inet:port(ServerSocket)),
-
- %% Prepare client process
- ReplyTo = self(),
- ClientFun =
- fun(Extra) ->
- Options = [{port, DaemonPort}, {debug, brief}] ++ Extra,
- Res = ?VERIFY({ok, Size}, tftp:write_file(RemoteFilename, Blob, Options)),
- ReplyTo ! {self(), {tftp_client_reply, Res}},
- exit(normal)
- end,
-
- WriteList = [0, 2, RemoteFilename, 0, "octet", 0],
- Data1Bin = list_to_binary([0, 3, 0, 1 | Block1]),
- {ClientPort, ClientPid} =
- if
- BlkSize =:= 512 ->
- %% Start client process
- ClientPid0 = spawn_link(fun() -> ClientFun([]) end),
-
- %% Recv WRITE
- WriteBin = list_to_binary(WriteList),
- io:format("WriteBin ~p\n", [WriteBin]),
- {udp, _, _, ClientPort0, _} = ?VERIFY({udp, DaemonSocket, Host, _, WriteBin}, recv(Timeout)),
-
- %% Send ACK #1
- Ack0Bin = <<0, 4, 0, 0>>,
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort0, Ack0Bin)),
-
- %% Sleep a while in order to provoke the client to re-send the packet
- timer:sleep(Timeout + timer:seconds(1)),
-
- %% Recv DATA #1 (the packet that the server think that we have lost)
- ?VERIFY({udp, ServerSocket, Host, ClientPort0, Data1Bin}, recv(Timeout)),
-
- %% Recv DATA #1 AGAIN (the re-sent package)
- ?VERIFY({udp, ServerSocket, Host, _, Data1Bin}, recv(Timeout)),
- {ClientPort0, ClientPid0};
- true ->
- %% Start client process
- BlkSizeList = integer_to_list(BlkSize),
- ClientPid0 = spawn_link(fun() -> ClientFun([{"blksize", BlkSizeList}]) end),
-
- %% Recv WRITE
- Options = ["blksize", 0, BlkSizeList, 0],
- WriteBin = list_to_binary([WriteList | Options]),
- {udp, _, _, ClientPort0, _} = ?VERIFY({udp, DaemonSocket, Host, _, WriteBin}, recv(Timeout)),
-
- %% Send OACK
- BlkSizeList = integer_to_list(BlkSize),
- OptionAckBin = list_to_binary([0, 6, "blksize",0, BlkSizeList, 0]),
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort0, OptionAckBin)),
-
- %% Sleep a while in order to provoke the client to re-send the packet
- timer:sleep(Timeout + timer:seconds(1)),
-
- %% Recv DATA #1 (the packet that the server think that we have lost)
- ?VERIFY({udp, ServerSocket, Host, ClientPort0, Data1Bin}, recv(Timeout)),
-
- %% Recv DATA #1 AGAIN (the re-sent package)
- ?VERIFY({udp, ServerSocket, Host, ClientPort0, Data1Bin}, recv(Timeout)),
- {ClientPort0, ClientPid0}
- end,
-
- %% Send ACK #1
- Ack1Bin = <<0, 4, 0, 1>>,
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Ack1Bin)),
-
- %% Recv DATA #2
- Data2Bin = list_to_binary([0, 3, 0, 2 | Block2]),
- ?VERIFY({udp, ServerSocket, Host, ClientPort, Data2Bin}, recv(Timeout)),
-
- %% Send ACK #2
- Ack2Bin = <<0, 4, 0, 2>>,
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Ack2Bin)),
-
- %% Recv DATA #3
- Data3Bin = list_to_binary([0, 3, 0, 3 | Block3]),
- ?VERIFY({udp, ServerSocket, Host, ClientPort, Data3Bin}, recv(Timeout)),
-
- %% Send ACK #3
- Ack3Bin = <<0, 4, 0, 3>>,
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Ack3Bin)),
-
- %% Send ACK #3 AGAIN (pretend that we timed out)
- timer:sleep(timer:seconds(1)),
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Ack3Bin)),
-
- %% Recv DATA #4 (the packet that the server think that we have lost)
- Data4Bin = list_to_binary([0, 3, 0, 4 | Block4]),
- ?VERIFY({udp, ServerSocket, Host, ClientPort, Data4Bin}, recv(Timeout)),
-
- %% Recv DATA #4 AGAIN (the re-sent package)
- ?VERIFY({udp, ServerSocket, Host, ClientPort, Data4Bin}, recv(Timeout)),
-
- %% Send ACK #4
- Ack4Bin = <<0, 4, 0, 4>>,
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Ack4Bin)),
-
- %% Recv DATA #5
- Data5Bin = list_to_binary([0, 3, 0, 5 | Block5]),
- ?VERIFY({udp, ServerSocket, Host, ClientPort, Data5Bin}, recv(Timeout)),
-
- %% Send ACK #3 which is out of range
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Ack3Bin)),
-
- %% Send ACK #5
- Ack5Bin = <<0, 4, 0, 5>>,
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Ack5Bin)),
-
- %% Recv DATA #6
- Data6Bin = list_to_binary([0, 3, 0, 6 | Block6]),
- ?VERIFY({udp, ServerSocket, Host, ClientPort, Data6Bin}, recv(Timeout)),
-
- %% Send ACK #6
- Ack6Bin = <<0, 4, 0, 6>>,
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Ack6Bin)),
-
- %% Close daemon and server sockets
- ?VERIFY(ok, gen_udp:close(ServerSocket)),
- ?VERIFY(ok, gen_udp:close(DaemonSocket)),
-
- ?VERIFY({ClientPid, {tftp_client_reply, {ok, Size}}}, recv(Timeout)),
-
- ?VERIFY(timeout, recv(Timeout)),
- ok.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-reuse_connection(doc) ->
- ["Verify that the server can reuse an ongiong connection when same client resends request."];
-reuse_connection(suite) ->
- [];
-reuse_connection(Config) when is_list(Config) ->
- Host = {127, 0, 0, 1},
- {Port, DaemonPid} = ?IGNORE(?START_DAEMON(0, [{debug, all}])),
-
- RemoteFilename = "reuse_connection.tmp",
- BlkSize = 512,
- Block1 = lists:duplicate(BlkSize, $1),
- Block2 = lists:duplicate(BlkSize div 2, $2),
- Blocks = [Block1, Block2],
- Blob = list_to_binary(Blocks),
- ?VERIFY(ok, file:write_file(RemoteFilename, Blob)),
-
- Seconds = 3,
- Timeout = timer:seconds(Seconds),
- ?VERIFY(timeout, recv(0)),
-
- %% Open socket
- {ok, Socket} = ?VERIFY({ok, _}, gen_udp:open(0, [binary, {reuseaddr, true}, {active, true}])),
-
- ReadList = [0, 1, RemoteFilename, 0, "octet", 0],
- Data1Bin = list_to_binary([0, 3, 0, 1 | Block1]),
-
- %% Send READ
- TimeoutList = integer_to_list(Seconds),
- Options = ["timeout", 0, TimeoutList, 0],
- ReadBin = list_to_binary([ReadList | Options]),
- ?VERIFY(ok, gen_udp:send(Socket, Host, Port, ReadBin)),
-
- %% Send yet another READ for same file
- ?VERIFY(ok, gen_udp:send(Socket, Host, Port, ReadBin)),
-
- %% Recv OACK
- OptionAckBin = list_to_binary([0, 6 | Options]),
- {udp, _, _, NewPort, _} = ?VERIFY({udp, Socket, Host, _, OptionAckBin}, recv(Timeout)),
-
- %% Send ACK #0
- Ack0Bin = <<0, 4, 0, 0>>,
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack0Bin)),
-
- %% Recv DATA #1
- ?VERIFY({udp, Socket, Host, NewPort, Data1Bin}, recv(Timeout)),
-
- %% Send ACK #1
- Ack1Bin = <<0, 4, 0, 1>>,
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack1Bin)),
-
- %% Recv DATA #2
- Data2Bin = list_to_binary([0, 3, 0, 2 | Block2]),
- ?VERIFY({udp, Socket, Host, NewPort, Data2Bin}, recv(Timeout)),
-
- %% Send ACK #2
- Ack2Bin = <<0, 4, 0, 2>>,
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack2Bin)),
-
- %% Close socket
- ?VERIFY(ok, gen_udp:close(Socket)),
-
- ?VERIFY(timeout, recv(Timeout)),
- ?VERIFY(ok, file:delete(RemoteFilename)),
-
- %% Cleanup
- unlink(DaemonPid),
- exit(DaemonPid, kill),
- ok.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Large file: transfer > 65535 blocks
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-large_file(doc) ->
- ["Start the daemon and test transfer of files greater than 32M."];
-large_file(suite) ->
- [];
-large_file(Config) when is_list(Config) ->
- ?VERIFY(ok, application:start(inets)),
-
- {Port, DaemonPid} = ?IGNORE(?START_DAEMON(0, [{debug, brief}])),
-
- %% Read fail
- RemoteFilename = "tftp_temporary_large_file_remote_test_file.txt",
- LocalFilename = "tftp_temporary_large_file_local_test_file.txt",
-
- {ok, FH} = file:open(LocalFilename, [write,exclusive]),
- {ok, Size} = file:position(FH, {eof, 2*512*65535}),
- ok = file:truncate(FH),
- ?IGNORE(file:close(FH)),
-
- %% Write and read
- ?VERIFY({ok, Size}, tftp:write_file(RemoteFilename, LocalFilename, [{port, Port}])),
- ?IGNORE(file:delete(LocalFilename)),
- ?VERIFY({ok, Size}, tftp:read_file(RemoteFilename, LocalFilename, [{port, Port}])),
-
- %% Cleanup
- unlink(DaemonPid),
- exit(DaemonPid, kill),
- ?VERIFY(ok, file:delete(LocalFilename)),
- ?VERIFY(ok, file:delete(RemoteFilename)),
- ?VERIFY(ok, application:stop(inets)),
- ok.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Goodies
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-recv(Timeout) ->
- receive
- Msg ->
- Msg
- after Timeout ->
- timeout
- end.
diff --git a/lib/inets/test/tftp_test_lib.erl b/lib/inets/test/tftp_test_lib.erl
deleted file mode 100644
index f07795324f..0000000000
--- a/lib/inets/test/tftp_test_lib.erl
+++ /dev/null
@@ -1,308 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2007-2016. 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(tftp_test_lib).
-
--compile(export_all).
-
--include("tftp_test_lib.hrl").
-
-%%
-%% -----
-%%
-
-init_per_testcase(_Case, Config) when is_list(Config) ->
- io:format("\n ", []),
- ?IGNORE(application:stop(inets)),
- Config.
-
-end_per_testcase(_Case, Config) when is_list(Config) ->
- ?IGNORE(application:stop(inets)),
- Config.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Infrastructure for test suite
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-error(Actual, Mod, Line) ->
- (catch global:send(tftp_global_logger, {failed, Mod, Line})),
- log("<ERROR> Bad result: ~p\n", [Actual], Mod, Line),
- Label = lists:concat([Mod, "(", Line, ") unexpected result"]),
- et:report_event(60, Mod, Mod, Label,
- [{line, Mod, Line}, {error, Actual}]),
- case global:whereis_name(tftp_test_case_sup) of
- undefined ->
- ignore;
- Pid ->
- Fail = #'REASON'{mod = Mod, line = Line, desc = Actual},
- Pid ! {fail, self(), Fail}
- end,
- Actual.
-
-log(Format, Args, Mod, Line) ->
- case global:whereis_name(tftp_global_logger) of
- undefined ->
- io:format(user, "~p(~p): " ++ Format,
- [Mod, Line] ++ Args);
- Pid ->
- io:format(Pid, "~p(~p): " ++ Format,
- [Mod, Line] ++ Args)
- end.
-
-default_config() ->
- [].
-
-t() ->
- t([{?MODULE, all}]).
-
-t(Cases) ->
- t(Cases, default_config()).
-
-t(Cases, Config) ->
- process_flag(trap_exit, true),
- Res = lists:flatten(do_test(Cases, Config)),
- io:format("Res: ~p\n", [Res]),
- display_result(Res),
- Res.
-
-do_test({Mod, Fun}, Config) when is_atom(Mod), is_atom(Fun) ->
- case catch apply(Mod, Fun, [suite]) of
- [] ->
- io:format("Eval: ~p:", [{Mod, Fun}]),
- Res = eval(Mod, Fun, Config),
- {R, _, _} = Res,
- io:format(" ~p\n", [R]),
- Res;
-
- Cases when is_list(Cases) ->
- io:format("Expand: ~p ...\n", [{Mod, Fun}]),
- Map = fun(Case) when is_atom(Case)-> {Mod, Case};
- (Case) -> Case
- end,
- do_test(lists:map(Map, Cases), Config);
-
- {req, _, {conf, Init, Cases, Finish}} ->
- case (catch apply(Mod, Init, [Config])) of
- Conf when is_list(Conf) ->
- io:format("Expand: ~p ...\n", [{Mod, Fun}]),
- Map = fun(Case) when is_atom(Case)-> {Mod, Case};
- (Case) -> Case
- end,
- Res = do_test(lists:map(Map, Cases), Conf),
- (catch apply(Mod, Finish, [Conf])),
- Res;
-
- {'EXIT', {skipped, Reason}} ->
- io:format(" => skipping: ~p\n", [Reason]),
- [{skipped, {Mod, Fun}, Reason}];
-
- Error ->
- io:format(" => failed: ~p\n", [Error]),
- [{failed, {Mod, Fun}, Error}]
- end;
-
- {'EXIT', {undef, _}} ->
- io:format("Undefined: ~p\n", [{Mod, Fun}]),
- [{nyi, {Mod, Fun}, ok}];
-
- Error ->
- io:format("Ignoring: ~p: ~p\n", [{Mod, Fun}, Error]),
- [{failed, {Mod, Fun}, Error}]
- end;
-do_test(Mod, Config) when is_atom(Mod) ->
- Res = do_test({Mod, all}, Config),
- Res;
-do_test(Cases, Config) when is_list(Cases) ->
- [do_test(Case, Config) || Case <- Cases];
-do_test(Bad, _Config) ->
- [{badarg, Bad, ok}].
-
-eval(Mod, Fun, Config) ->
- TestCase = {?MODULE, Mod, Fun},
- Label = lists:concat(["TEST CASE: ", Fun]),
- et:report_event(40, ?MODULE, Mod, Label ++ " started",
- [TestCase, Config]),
- global:register_name(tftp_test_case_sup, self()),
- Flag = process_flag(trap_exit, true),
- Config2 = Mod:init_per_testcase(Fun, Config),
- Pid = spawn_link(?MODULE, do_eval, [self(), Mod, Fun, Config2]),
- R = wait_for_evaluator(Pid, Mod, Fun, Config2, []),
- Mod:end_per_testcase(Fun, Config2),
- global:unregister_name(tftp_test_case_sup),
- process_flag(trap_exit, Flag),
- R.
-
-wait_for_evaluator(Pid, Mod, Fun, Config, Errors) ->
- TestCase = {?MODULE, Mod, Fun},
- Label = lists:concat(["TEST CASE: ", Fun]),
- receive
- {done, Pid, ok} when Errors == [] ->
- et:report_event(40, Mod, ?MODULE, Label ++ " ok",
- [TestCase, Config]),
- {ok, {Mod, Fun}, Errors};
- {done, Pid, {ok, _}} when Errors == [] ->
- et:report_event(40, Mod, ?MODULE, Label ++ " ok",
- [TestCase, Config]),
- {ok, {Mod, Fun}, Errors};
- {done, Pid, Fail} ->
- et:report_event(20, Mod, ?MODULE, Label ++ " failed",
- [TestCase, Config, {return, Fail}, Errors]),
- {failed, {Mod,Fun}, Fail};
- {'EXIT', Pid, {skipped, Reason}} ->
- et:report_event(20, Mod, ?MODULE, Label ++ " skipped",
- [TestCase, Config, {skipped, Reason}]),
- {skipped, {Mod, Fun}, Errors};
- {'EXIT', Pid, Reason} ->
- et:report_event(20, Mod, ?MODULE, Label ++ " crashed",
- [TestCase, Config, {'EXIT', Reason}]),
- {crashed, {Mod, Fun}, [{'EXIT', Reason} | Errors]};
- {fail, Pid, Reason} ->
- wait_for_evaluator(Pid, Mod, Fun, Config, Errors ++ [Reason])
- end.
-
-do_eval(ReplyTo, Mod, Fun, Config) ->
- case (catch apply(Mod, Fun, [Config])) of
- {'EXIT', {skipped, Reason}} ->
- ReplyTo ! {'EXIT', self(), {skipped, Reason}};
- Other ->
- ReplyTo ! {done, self(), Other}
- end,
- unlink(ReplyTo),
- exit(shutdown).
-
-display_result([]) ->
- io:format("OK\n", []);
-display_result(Res) when is_list(Res) ->
- Ok = [MF || {ok, MF, _} <- Res],
- Nyi = [MF || {nyi, MF, _} <- Res],
- Skipped = [{MF, Reason} || {skipped, MF, Reason} <- Res],
- Failed = [{MF, Reason} || {failed, MF, Reason} <- Res],
- Crashed = [{MF, Reason} || {crashed, MF, Reason} <- Res],
- display_summary(Ok, Nyi, Skipped, Failed, Crashed),
- display_skipped(Skipped),
- display_failed(Failed),
- display_crashed(Crashed).
-
-display_summary(Ok, Nyi, Skipped, Failed, Crashed) ->
- io:format("\nTest case summary:\n", []),
- display_summary(Ok, "successful"),
- display_summary(Nyi, "not yet implemented"),
- display_summary(Skipped, "skipped"),
- display_summary(Failed, "failed"),
- display_summary(Crashed, "crashed"),
- io:format("\n", []).
-
-display_summary(Res, Info) ->
- io:format(" ~w test cases ~s\n", [length(Res), Info]).
-
-display_skipped([]) ->
- ok;
-display_skipped(Skipped) ->
- io:format("Skipped test cases:\n", []),
- F = fun({MF, Reason}) -> io:format(" ~p => ~p\n", [MF, Reason]) end,
- lists:foreach(F, Skipped),
- io:format("\n", []).
-
-
-display_failed([]) ->
- ok;
-display_failed(Failed) ->
- io:format("Failed test cases:\n", []),
- F = fun({MF, Reason}) -> io:format(" ~p => ~p\n", [MF, Reason]) end,
- lists:foreach(F, Failed),
- io:format("\n", []).
-
-display_crashed([]) ->
- ok;
-display_crashed(Crashed) ->
- io:format("Crashed test cases:\n", []),
- F = fun({MF, Reason}) -> io:format(" ~p => ~p\n", [MF, Reason]) end,
- lists:foreach(F, Crashed),
- io:format("\n", []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% generic callback
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
--record(generic_state, {state, prepare, open, read, write, abort}).
-
-prepare(Peer, Access, LocalFilename, Mode, SuggestedOptions, Initial) when is_list(Initial) ->
- State = lookup_option(state, mandatory, Initial),
- Prepare = lookup_option(prepare, mandatory, Initial),
- Open = lookup_option(open, mandatory, Initial),
- Read = lookup_option(read, mandatory, Initial),
- Write = lookup_option(write, mandatory, Initial),
- Abort = lookup_option(abort, mandatory, Initial),
- case Prepare(Peer, Access, LocalFilename, Mode, SuggestedOptions, State) of
- {ok, AcceptedOptions, NewState} ->
- {ok,
- AcceptedOptions,
- #generic_state{state = NewState,
- prepare = Prepare,
- open = Open,
- read = Read,
- write = Write,
- abort = Abort}};
- Other ->
- Other
- end.
-
-open(Peer, Access, LocalFilename, Mode, SuggestedOptions, Initial) when is_list(Initial) ->
- case prepare(Peer, Access, LocalFilename, Mode, SuggestedOptions, Initial) of
- {ok, SuggestedOptions2, GenericState} ->
- open(Peer, Access, LocalFilename, Mode, SuggestedOptions2, GenericState);
- Other ->
- Other
- end;
-open(Peer, Access, LocalFilename, Mode, SuggestedOptions, #generic_state{state = State, open = Open} = GenericState) ->
- case Open(Peer, Access, LocalFilename, Mode, SuggestedOptions, State) of
- {ok, SuggestedOptions2, NewState} ->
- {ok, SuggestedOptions2, GenericState#generic_state{state = NewState}};
- Other ->
- Other
- end.
-
-read(#generic_state{state = State, read = Read} = GenericState) ->
- case Read(State) of
- {more, DataBlock, NewState} ->
- {more, DataBlock, GenericState#generic_state{state = NewState}};
- Other ->
- Other
- end.
-
-write(DataBlock, #generic_state{state = State, write = Write} = GenericState) ->
- case Write(DataBlock, State) of
- {more, NewState} ->
- {more, GenericState#generic_state{state = NewState}};
- Other ->
- Other
- end.
-
-abort(Code, Text, #generic_state{state = State, abort = Abort}) ->
- Abort(Code, Text, State).
-
-lookup_option(Key, Default, Options) ->
- case lists:keysearch(Key, 1, Options) of
- {value, {_, Val}} ->
- Val;
- false ->
- Default
- end.
-
diff --git a/lib/inets/test/tftp_test_lib.hrl b/lib/inets/test/tftp_test_lib.hrl
deleted file mode 100644
index e7a5a37d2c..0000000000
--- a/lib/inets/test/tftp_test_lib.hrl
+++ /dev/null
@@ -1,44 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2007-2016. 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%
-%%
-
--record('REASON', {mod, line, desc}).
-
--define(LOG(Format, Args),
- tftp_test_lib:log(Format, Args, ?MODULE, ?LINE)).
-
--define(ERROR(Reason),
- tftp_test_lib:error(Reason, ?MODULE, ?LINE)).
-
--define(VERIFY(Expected, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- Expected -> ?LOG("Ok, ~p\n", [AcTuAlReS]);
- _ -> ?ERROR(AcTuAlReS)
- end,
- AcTuAlReS
- end()).
-
--define(IGNORE(Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- ?LOG("Ok, ~p\n", [AcTuAlReS]),
- AcTuAlReS
- end()).