File 3172-Test-data-integrity-after-send_timeout-resume.patch of Package erlang

From deae5c45a756aa657b7bb0c0d8aa19ee2e3a8e77 Mon Sep 17 00:00:00 2001
From: Raimo Niskanen <raimo@erlang.org>
Date: Wed, 5 Jan 2022 15:04:13 +0100
Subject: [PATCH 2/2] Test data integrity after send_timeout resume

---
 lib/kernel/test/gen_tcp_misc_SUITE.erl | 159 ++++++++++++++++++++++++-
 1 file changed, 154 insertions(+), 5 deletions(-)

diff --git a/lib/kernel/test/gen_tcp_misc_SUITE.erl b/lib/kernel/test/gen_tcp_misc_SUITE.erl
index 2c2725ad30..5ebf68220d 100644
--- a/lib/kernel/test/gen_tcp_misc_SUITE.erl
+++ b/lib/kernel/test/gen_tcp_misc_SUITE.erl
@@ -1,7 +1,7 @@
 %%
 %% %CopyrightBegin%
 %%
-%% Copyright Ericsson AB 1998-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2022. 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.
@@ -54,6 +54,7 @@
 	 killing_acceptor/1,killing_multi_acceptors/1,killing_multi_acceptors2/1,
 	 several_accepts_in_one_go/1, accept_system_limit/1,
 	 active_once_closed/1, send_timeout/1, send_timeout_active/1,
+         send_timeout_resume/1,
          otp_7731/1, zombie_sockets/1, otp_7816/1, otp_8102/1,
          wrapping_oct/0, wrapping_oct/1, otp_9389/1, otp_13939/1,
          otp_12242/1, delay_send_error/1, bidirectional_traffic/1]).
@@ -139,7 +140,7 @@ accept_cases() ->
      accept_timeouts_in_order7, accept_timeouts_mixed,
      killing_acceptor, killing_multi_acceptors,
      killing_multi_acceptors2, several_accepts_in_one_go, accept_system_limit,
-     active_once_closed, send_timeout, send_timeout_active, otp_7731,
+     active_once_closed, send_timeout, send_timeout_active, send_timeout_resume, otp_7731,
      wrapping_oct,
      zombie_sockets, otp_7816, otp_8102, otp_9389,
      otp_12242, delay_send_error, bidirectional_traffic].
@@ -4422,7 +4423,153 @@ timeout_sink_loop(Action, N) ->
                 Other]),
 	    {Other, N2}
     end.
-     
+
+
+
+send_timeout_resume(Config) when is_list(Config) ->
+    ct:timetrap(?SECS(16)),
+    ?TC_TRY(
+       send_timeout_resume,
+       fun () -> do_send_timeout_resume(Config) end).
+
+do_send_timeout_resume(Config) ->
+    Dir = filename:dirname(code:which(?MODULE)),
+    {ok,RNode} =
+        test_server:start_node(
+          ?UNIQ_NODE_NAME, slave, [{args,"-pa " ++ Dir}]),
+    try
+        do_send_timeout_resume(Config, RNode, 12)
+    after
+        test_server:stop_node(RNode)
+    end.
+
+do_send_timeout_resume(Config, RNode, BlockPow) ->
+    N = 8,
+    BlockSize = 1 bsl BlockPow,
+    1 = rand:uniform(1),
+    Seed = rand:export_seed(),
+    ListenOpts =
+        [inet,
+         {backlog, 2},
+         {active, false},
+         binary,
+         {sndbuf, BlockSize},
+         {recbuf, BlockSize},
+         {buffer, BlockSize bsl 1}],
+    ConnectOpts =
+        [inet,
+         {send_timeout, 0},
+         {active, false},
+         binary,
+         {high_watermark, BlockSize},
+         {low_watermark, BlockSize bsr 1},
+         {sndbuf, BlockSize},
+         {recbuf, BlockSize},
+         {buffer, BlockSize bsl 1}],
+    Client = self(),
+    Tag = make_ref(),
+    {Server, Mref} =
+        spawn_opt(
+          RNode,
+          fun () ->
+                  send_timeout_resume_srv(
+                    Config, Seed, Client, Tag, ListenOpts)
+          end, [monitor, link]),
+    ?P("Client=~p Server=~p Tag=~p~n", [Client, Server, Tag]),
+    receive {Tag, P} -> ok end,
+    ?P("connecting to ~p~n", [P]),
+    {ok, C} = ?CONNECT(Config, localhost, P, ConnectOpts),
+    try
+        Timeouts = do_send_timeout_resume_send(C, BlockSize, 0, N),
+        receive
+            {'DOWN', Mref, _, _, Result} ->
+                ?P("N=~p BlockSize=~p Timeouts=~p Result=~p~n",
+                   [N, BlockSize, Timeouts, Result]),
+                case Result of
+                    {ok, Count} ->
+                        Count = N * BlockSize,
+                        true = N < Timeouts,
+                        ok;
+                    _ ->
+                        ct:fail(Result)
+                end
+        end
+    after
+        gen_tcp:close(C)
+    end.
+
+do_send_timeout_resume_send(S, _BlockSize, Timeouts, 0) ->
+    ok = gen_tcp:close(S),
+    Timeouts;
+do_send_timeout_resume_send(S, BlockSize, Timeouts, N) ->
+    Bin = random_data(BlockSize),
+    Timeouts_1 = do_send_timeout_resume_send(S, Bin, Timeouts),
+    do_send_timeout_resume_send(S, BlockSize, Timeouts_1, N - 1).
+
+do_send_timeout_resume_send(S, Bin, Timeouts) ->
+    case gen_tcp:send(S, Bin) of
+        ok ->
+            Timeouts;
+        {error, Reason} ->
+            case Reason of
+                timeout ->
+                    receive after 100 -> ok end,
+                    do_send_timeout_resume_send(S, <<>>, Timeouts + 1);
+                {timeout, RestData} ->
+                    receive after 100 -> ok end,
+                    do_send_timeout_resume_send(S, RestData, Timeouts + 1);
+                _ ->
+                    error({Reason, Timeouts})
+            end
+    end.
+
+random_data(0) ->
+    <<>>;
+random_data(Size) ->
+    <<(rand:uniform(256) - 1), (random_data(Size - 1))/binary>>.
+
+compare_data(<<>>, Count) ->
+    Count;
+compare_data(<<Byte, Bin/binary>>, Count) ->
+    case rand:uniform(256) - 1 of
+        Byte ->
+            compare_data(Bin, Count + 1);
+        _ ->
+            error({diff, Count})
+    end.
+
+send_timeout_resume_srv(Config, Seed, Client, Tag, ListenOpts) ->
+    rand:seed(Seed),
+    {ok, L} = ?LISTEN(Config, 0, ListenOpts),
+    Count =
+        try
+            {ok, P} = inet:port(L),
+            Client ! {Tag, P},
+            {ok, A} = gen_tcp:accept(L, 2000),
+            ?P("accept success ~p~n", [A]),
+            receive after 2000 -> ok end,
+            try send_timeout_resume_srv(A, 0)
+            after
+                gen_tcp:close(A)
+            end
+        after
+            gen_tcp:close(L)
+        end,
+    exit({ok, Count}).
+
+send_timeout_resume_srv(S, Count) ->
+    case gen_tcp:recv(S, 0) of
+        {ok, Data} ->
+            Count_1 = compare_data(Data, Count),
+            send_timeout_resume_srv(S, Count_1);
+        {error, closed} ->
+            Count;
+        {error, Reason} ->
+            error({Reason, Count})
+    end.
+
+
+
 has_superfluous_schedulers() ->
     case {erlang:system_info(schedulers),
 	  erlang:system_info(logical_processors)} of
@@ -5094,7 +5241,9 @@ delay_send_error(Config) ->
     ?P("close accepted socket"),
     ok = gen_tcp:close(A),
     ?P("close connected socket"),
-    ok = gen_tcp:close(C).
+    ok = gen_tcp:close(C),
+    ok = gen_tcp:close(S),
+    ok = gen_tcp:close(L).
 
 
 delay_send_error2(Sock) ->
-- 
2.34.1

openSUSE Build Service is sponsored by