From 129370d9015831b7b5059686de39b25a5be5f502 Mon Sep 17 00:00:00 2001
From: Peter Andersson <peppe@erlang.org>
Date: Mon, 14 Apr 2014 15:53:35 +0200
Subject: Fix problem with substring in large message getting incorrectly
 reversed

OTP-11871
---
 lib/common_test/src/ct_telnet.erl                  |  7 ++--
 .../ct_telnet_own_server_SUITE.erl                 | 42 ++++++++++++++++++++--
 lib/common_test/test/telnet_server.erl             |  8 +++++
 3 files changed, 51 insertions(+), 6 deletions(-)

(limited to 'lib')

diff --git a/lib/common_test/src/ct_telnet.erl b/lib/common_test/src/ct_telnet.erl
index c9dc2338cd..44e910eb81 100644
--- a/lib/common_test/src/ct_telnet.erl
+++ b/lib/common_test/src/ct_telnet.erl
@@ -869,14 +869,13 @@ teln_cmd(Pid,Cmd,Prx,Timeout) ->
     teln_receive_until_prompt(Pid,Prx,Timeout).
 
 teln_get_all_data(Pid,Prx,Data,Acc,LastLine) ->
-    case check_for_prompt(Prx,lists:reverse(LastLine) ++ Data) of
+    case check_for_prompt(Prx,LastLine++Data) of
 	{prompt,Lines,_PromptType,Rest} ->
 	    teln_get_all_data(Pid,Prx,Rest,[Lines|Acc],[]);
 	{noprompt,Lines,LastLine1} ->
 	    case ct_telnet_client:get_data(Pid) of
 		{ok,[]} ->
-		    {ok,lists:reverse(lists:append([Lines|Acc])),
-		     lists:reverse(LastLine1)};
+		    {ok,lists:reverse(lists:append([Lines|Acc])),LastLine1};
 		{ok,Data1} ->
 		    teln_get_all_data(Pid,Prx,Data1,[Lines|Acc],LastLine1)
 	    end
@@ -1334,7 +1333,7 @@ teln_receive_until_prompt(Pid,Prx,Timeout) ->
 
 teln_receive_until_prompt(Pid,Prx,Acc,LastLine) ->
     {ok,Data} = ct_telnet_client:get_data(Pid),
-    case check_for_prompt(Prx,LastLine ++ Data) of
+    case check_for_prompt(Prx,LastLine++Data) of
 	{prompt,Lines,PromptType,Rest} ->
 	    Return = lists:reverse(lists:append([Lines|Acc])),
 	   {ok,Return,PromptType,Rest};
diff --git a/lib/common_test/test/ct_telnet_SUITE_data/ct_telnet_own_server_SUITE.erl b/lib/common_test/test/ct_telnet_SUITE_data/ct_telnet_own_server_SUITE.erl
index 0ee0525216..c0f79d0f10 100644
--- a/lib/common_test/test/ct_telnet_SUITE_data/ct_telnet_own_server_SUITE.erl
+++ b/lib/common_test/test/ct_telnet_SUITE_data/ct_telnet_own_server_SUITE.erl
@@ -16,7 +16,8 @@ suite() ->
     ].
 
 all() ->
-    [expect,
+    [
+     expect,
      expect_repeat,
      expect_sequence,
      expect_error_prompt,
@@ -31,8 +32,10 @@ all() ->
      ignore_prompt_repeat,
      ignore_prompt_sequence,
      ignore_prompt_timeout,
+     large_string,
      server_speaks,
-     server_disconnects].
+     server_disconnects
+    ].
 
 groups() ->
     [].
@@ -214,6 +217,41 @@ no_prompt_check_timeout(_) ->
     ok = ct_telnet:close(Handle),
     ok.
 
+%% Check that it's possible to receive multiple chunks of data sent from
+%% the server with one get_data call
+large_string(_) ->
+    {ok, Handle} = ct_telnet:open(telnet_server_conn1),
+    String = "abcd efgh ijkl mnop qrst uvwx yz ",
+    BigString = lists:flatmap(fun(S) -> S end,
+			      [String || _ <- lists:seq(1,10)]),
+    VerifyStr = [C || C <- BigString, C/=$ ],
+
+    {ok,Data} = ct_telnet:cmd(Handle, "echo_sep "++BigString),
+    ct:log("[CMD] Received ~w chars: ~s", [length(lists:flatten(Data)),Data]),
+    VerifyStr = [C || C <- lists:flatten(Data), C/=$ , C/=$\r, C/=$\n, C/=$>],
+
+    %% Test #1: With a long sleep value, all data gets gets buffered and
+    %% ct_telnet can receive it with one single request to ct_telnet_client.
+    %% Test #2: With a short sleep value, ct_telnet needs multiple calls to
+    %% ct_telnet_client to collect the data. This iterative operation should
+    %% yield the same result as the single request case.
+
+    ok = ct_telnet:send(Handle, "echo_sep "++BigString),
+    timer:sleep(1000),
+    {ok,Data1} = ct_telnet:get_data(Handle),
+    ct:log("[GET DATA #1] Received ~w chars: ~s",
+	   [length(lists:flatten(Data1)),Data1]),
+    VerifyStr = [C || C <- lists:flatten(Data1), C/=$ , C/=$\r, C/=$\n, C/=$>],
+
+    ok = ct_telnet:send(Handle, "echo_sep "++BigString),
+    timer:sleep(50),
+    {ok,Data2} = ct_telnet:get_data(Handle),
+    ct:log("[GET DATA #2] Received ~w chars: ~s", [length(lists:flatten(Data2)),Data2]),
+    VerifyStr = [C || C <- lists:flatten(Data2), C/=$ , C/=$\r, C/=$\n, C/=$>],
+
+    ok = ct_telnet:close(Handle),
+    ok.
+
 %% The server says things. Manually check that it gets printed correctly
 %% in the general IO log.
 server_speaks(_) ->
diff --git a/lib/common_test/test/telnet_server.erl b/lib/common_test/test/telnet_server.erl
index ae56787819..1d341d6106 100644
--- a/lib/common_test/test/telnet_server.erl
+++ b/lib/common_test/test/telnet_server.erl
@@ -198,6 +198,14 @@ do_handle_data(Data,#state{authorized={user,_}}=State) ->
 do_handle_data("echo " ++ Data,State) ->
     send(Data++"\r\n> ",State),
     {ok,State};
+do_handle_data("echo_sep " ++ Data,State) ->
+    Msgs = string:tokens(Data," "),
+    lists:foreach(fun(Msg) ->
+			  send(Msg,State),
+			  timer:sleep(10)
+		  end, Msgs),
+    send("\r\n> ",State),
+    {ok,State};
 do_handle_data("echo_no_prompt " ++ Data,State) ->
     send(Data,State),
     {ok,State};
-- 
cgit v1.2.3