diff options
Diffstat (limited to 'lib/common_test/test/ct_telnet_SUITE_data/ct_telnet_own_server_SUITE.erl')
-rw-r--r-- | lib/common_test/test/ct_telnet_SUITE_data/ct_telnet_own_server_SUITE.erl | 262 |
1 files changed, 231 insertions, 31 deletions
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 3f7c0d68bf..9dc9095f47 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 @@ -4,25 +4,48 @@ -include_lib("common_test/include/ct.hrl"). +%% telnet control characters +-define(SE, 240). +-define(NOP, 241). +-define(DM, 242). +-define(BRK, 243). +-define(IP, 244). +-define(AO, 245). +-define(AYT, 246). +-define(EC, 247). +-define(EL, 248). +-define(GA, 249). +-define(SB, 250). +-define(WILL, 251). +-define(WONT, 252). +-define(DO, 253). +-define(DONT, 254). +-define(IAC, 255). + +-define(SHORT_TIME,2000). + %%-------------------------------------------------------------------- %% TEST SERVER CALLBACK FUNCTIONS %%-------------------------------------------------------------------- -init_per_suite(Config) -> - Config. - -end_per_suite(_Config) -> - ok. - - -suite() -> [{require,erl_telnet_server,{unix,[telnet]}}]. +suite() -> + [ + {require,telnet_server_conn1,{unix,[telnet]}}, + {require,ct_conn_log}, + {ct_hooks, [{cth_conn_log,[]}]} + ]. all() -> - [expect, + [ + expect, expect_repeat, expect_sequence, + expect_wait_until_prompt, expect_error_prompt, - expect_error_timeout, + expect_error_timeout1, + expect_error_timeout2, + expect_error_timeout3, + total_timeout_less_than_idle, no_prompt_check, no_prompt_check_repeat, no_prompt_check_sequence, @@ -30,11 +53,25 @@ all() -> ignore_prompt, ignore_prompt_repeat, ignore_prompt_sequence, - ignore_prompt_timeout]. + ignore_prompt_timeout, + large_string, + server_speaks, + server_disconnects, + newline_ayt, + newline_break + ]. groups() -> []. +init_per_suite(Config) -> + ct:pal("Will use these log hook options: ~p", + [ct:get_config(ct_conn_log,[])]), + Config. + +end_per_suite(_Config) -> + ok. + init_per_group(_GroupName, Config) -> Config. @@ -43,7 +80,9 @@ end_per_group(_GroupName, Config) -> %% Simple expect expect(_) -> - {ok, Handle} = ct_telnet:open(erl_telnet_server), + {ok, Handle} = ct_telnet:open(telnet_server_conn1), + ok = ct_telnet:send(Handle, "echo ayt"), + {ok,["ayt"]} = ct_telnet:expect(Handle, "ayt"), ok = ct_telnet:send(Handle, "echo ayt"), {ok,["ayt"]} = ct_telnet:expect(Handle, ["ayt"]), ok = ct_telnet:close(Handle), @@ -51,7 +90,7 @@ expect(_) -> %% Expect with repeat option expect_repeat(_) -> - {ok, Handle} = ct_telnet:open(erl_telnet_server), + {ok, Handle} = ct_telnet:open(telnet_server_conn1), ok = ct_telnet:send(Handle, "echo_ml xy xy"), {ok,[["xy"],["xy"]],done} = ct_telnet:expect(Handle, ["xy"],[{repeat,2}]), ok = ct_telnet:close(Handle), @@ -59,7 +98,7 @@ expect_repeat(_) -> %% Expect with sequence option expect_sequence(_) -> - {ok, Handle} = ct_telnet:open(erl_telnet_server), + {ok, Handle} = ct_telnet:open(telnet_server_conn1), ok = ct_telnet:send(Handle, "echo_ml ab cd ef"), {ok,[["ab"],["cd"],["ef"]]} = ct_telnet:expect(Handle, [["ab"],["cd"],["ef"]], @@ -67,10 +106,25 @@ expect_sequence(_) -> ok = ct_telnet:close(Handle), ok. +%% Check that expect can wait for delayed prompt +expect_wait_until_prompt(_) -> + {ok, Handle} = ct_telnet:open(telnet_server_conn1), + Timeouts = [{idle_timeout,5000},{total_timeout,7000}], + + ok = ct_telnet:send(Handle, "echo_delayed_prompt 3000 xxx"), + {ok,["xxx"]} = + ct_telnet:expect(Handle, "xxx", + [wait_for_prompt|Timeouts]), + ok = ct_telnet:send(Handle, "echo_delayed_prompt 3000 yyy zzz"), + {ok,[["yyy"],["zzz"]]} = + ct_telnet:expect(Handle, ["yyy","zzz"], + [{wait_for_prompt,"> "}|Timeouts]), + ok. + %% Check that expect returns when a prompt is found, even if pattern %% is not matched. expect_error_prompt(_) -> - {ok, Handle} = ct_telnet:open(erl_telnet_server), + {ok, Handle} = ct_telnet:open(telnet_server_conn1), ok = ct_telnet:send(Handle, "echo xxx> yyy"), {error,{prompt,"> "}} = ct_telnet:expect(Handle, ["yyy"]), ok = ct_telnet:close(Handle), @@ -79,17 +133,61 @@ expect_error_prompt(_) -> %% Check that expect returns after idle timeout, and even if the %% expected pattern is received - as long as not newline or prompt is %% received it will not match. -expect_error_timeout(_) -> - {ok, Handle} = ct_telnet:open(erl_telnet_server), +expect_error_timeout1(_) -> + {ok, Handle} = ct_telnet:open(telnet_server_conn1), + ok = ct_telnet:send(Handle, "echo_no_prompt xxx"), + {error,timeout} = ct_telnet:expect(Handle, ["xxx"], [{timeout,?SHORT_TIME}]), + ok = ct_telnet:close(Handle), + ok. + +expect_error_timeout2(_) -> + {ok, Handle} = ct_telnet:open(telnet_server_conn1), + ok = ct_telnet:send(Handle, "echo_no_prompt xxx"), + {error,timeout} = ct_telnet:expect(Handle, ["xxx"], [{idle_timeout,1000}, + {total_timeout,infinity}]), + ok = ct_telnet:close(Handle), + ok. + +%% Check that if server loops and pattern not matching, the operation +%% can be aborted +expect_error_timeout3(_) -> + {ok, Handle} = ct_telnet:open(telnet_server_conn1), + ok = ct_telnet:send(Handle, "echo_loop 5000 xxx"), + + T0 = now(), + {error,timeout} = ct_telnet:expect(Handle, ["yyy"], + [{idle_timeout,infinity}, + {total_timeout,2001}]), + Diff = trunc(timer:now_diff(now(),T0)/1000), + {_,true} = {Diff, (Diff >= 2000) and (Diff =< 4000)}, + + ok = ct_telnet:send(Handle, "echo ayt"), + {ok,["ayt"]} = ct_telnet:expect(Handle, ["ayt"]), + ok = ct_telnet:close(Handle), + ok. + +%% OTP-12335: If total_timeout < idle_timeout, expect will never timeout +%% until after idle_timeout, which is incorrect. +total_timeout_less_than_idle(_) -> + {ok, Handle} = ct_telnet:open(telnet_server_conn1), ok = ct_telnet:send(Handle, "echo_no_prompt xxx"), - {error,timeout} = ct_telnet:expect(Handle, ["xxx"], [{timeout,1000}]), + + T0 = now(), + {error,timeout} = ct_telnet:expect(Handle, ["yyy"], + [{idle_timeout,5000}, + {total_timeout,2001}]), + Diff = trunc(timer:now_diff(now(),T0)/1000), + {_,true} = {Diff, (Diff >= 2000) and (Diff =< 4000)}, + + ok = ct_telnet:send(Handle, "echo ayt"), + {ok,["ayt"]} = ct_telnet:expect(Handle, ["ayt"]), ok = ct_telnet:close(Handle), ok. %% expect with ignore_prompt option should not return even if a prompt %% is found. The pattern after the prompt (here "> ") can be matched. ignore_prompt(_) -> - {ok, Handle} = ct_telnet:open(erl_telnet_server), + {ok, Handle} = ct_telnet:open(telnet_server_conn1), ok = ct_telnet:send(Handle, "echo xxx> yyy"), {ok,["yyy"]} = ct_telnet:expect(Handle, ["yyy"], [ignore_prompt]), ok = ct_telnet:close(Handle), @@ -97,7 +195,7 @@ ignore_prompt(_) -> %% expect with ignore_prompt and repeat options. ignore_prompt_repeat(_) -> - {ok, Handle} = ct_telnet:open(erl_telnet_server), + {ok, Handle} = ct_telnet:open(telnet_server_conn1), ok = ct_telnet:send(Handle, "echo_ml yyy> yyy>"), {ok,[["yyy"],["yyy"]],done} = ct_telnet:expect(Handle, ["yyy"], [{repeat,2}, @@ -107,7 +205,7 @@ ignore_prompt_repeat(_) -> %% expect with ignore_prompt and sequence options. ignore_prompt_sequence(_) -> - {ok, Handle} = ct_telnet:open(erl_telnet_server), + {ok, Handle} = ct_telnet:open(telnet_server_conn1), ok = ct_telnet:send(Handle, "echo_ml xxx> yyy> zzz> "), {ok,[["xxx"],["yyy"],["zzz"]]} = ct_telnet:expect(Handle, [["xxx"],["yyy"],["zzz"]], @@ -121,26 +219,26 @@ ignore_prompt_sequence(_) -> %% As for expect without the ignore_prompt option, it a newline or a %% prompt is required in order for the pattern to match. ignore_prompt_timeout(_) -> - {ok, Handle} = ct_telnet:open(erl_telnet_server), + {ok, Handle} = ct_telnet:open(telnet_server_conn1), ok = ct_telnet:send(Handle, "echo xxx"), {error,timeout} = ct_telnet:expect(Handle, ["yyy"], [ignore_prompt, - {timeout,1000}]), + {timeout,?SHORT_TIME}]), ok = ct_telnet:send(Handle, "echo xxx"), % sends prompt and newline {ok,["xxx"]} = ct_telnet:expect(Handle, ["xxx"], [ignore_prompt, - {timeout,1000}]), + {timeout,?SHORT_TIME}]), ok = ct_telnet:send(Handle, "echo_no_prompt xxx\n"), % no prompt, but newline {ok,["xxx"]} = ct_telnet:expect(Handle, ["xxx"], [ignore_prompt, - {timeout,1000}]), + {timeout,?SHORT_TIME}]), ok = ct_telnet:send(Handle, "echo_no_prompt xxx"), % no prompt, no newline {error,timeout} = ct_telnet:expect(Handle, ["xxx"], [ignore_prompt, - {timeout,1000}]), + {timeout,?SHORT_TIME}]), ok = ct_telnet:close(Handle), ok. %% no_prompt_check option shall match pattern both when prompt is sent %% and when it is not. no_prompt_check(_) -> - {ok, Handle} = ct_telnet:open(erl_telnet_server), + {ok, Handle} = ct_telnet:open(telnet_server_conn1), ok = ct_telnet:send(Handle, "echo xxx"), {ok,["xxx"]} = ct_telnet:expect(Handle, ["xxx"], [no_prompt_check]), ok = ct_telnet:send(Handle, "echo_no_prompt yyy"), @@ -150,7 +248,7 @@ no_prompt_check(_) -> %% no_prompt_check and repeat options no_prompt_check_repeat(_) -> - {ok, Handle} = ct_telnet:open(erl_telnet_server), + {ok, Handle} = ct_telnet:open(telnet_server_conn1), ok = ct_telnet:send(Handle, "echo_ml xxx xxx"), {ok,[["xxx"],["xxx"]],done} = ct_telnet:expect(Handle,["xxx"], [{repeat,2}, @@ -164,7 +262,7 @@ no_prompt_check_repeat(_) -> %% no_prompt_check and sequence options no_prompt_check_sequence(_) -> - {ok, Handle} = ct_telnet:open(erl_telnet_server), + {ok, Handle} = ct_telnet:open(telnet_server_conn1), ok = ct_telnet:send(Handle, "echo_ml_no_prompt ab cd ef"), {ok,[["ab"],["cd"],["ef"]]} = ct_telnet:expect(Handle, [["ab"],["cd"],["ef"]], @@ -176,9 +274,111 @@ no_prompt_check_sequence(_) -> %% Check that expect returns after idle timeout when no_prompt_check %% option is used. no_prompt_check_timeout(_) -> - {ok, Handle} = ct_telnet:open(erl_telnet_server), + {ok, Handle} = ct_telnet:open(telnet_server_conn1), ok = ct_telnet:send(Handle, "echo xxx"), {error,timeout} = ct_telnet:expect(Handle, ["yyy"], [no_prompt_check, - {timeout,1000}]), + {timeout,?SHORT_TIME}]), + 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), + ct: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), + ct: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. +%% +%% In this test case we simulate data sent spontaneously from the +%% server. We use ct_telnet_client:send_data instead of ct_telnet:send +%% to avoid flushing of buffers in the client, and we use +%% echo_no_prompt since the server would normally not send a prompt in +%% this case. +server_speaks(_) -> + {ok, Handle} = ct_telnet:open(telnet_server_conn1), + + Backdoor = ct_gen_conn:get_conn_pid(Handle), + ok = ct_telnet_client:send_data(Backdoor, + "echo_no_prompt This is the first message"), + ok = ct_telnet_client:send_data(Backdoor, + "echo_no_prompt This is the second message"), + %% Let ct_telnet_client get an idle timeout. This should print the + %% two messages to the log. Note that the buffers are not flushed here! + ct:sleep(15000), + ok = ct_telnet_client:send_data(Backdoor, + "echo_no_prompt This is the third message"), + {ok,_} = ct_telnet:expect(Handle, ["first.*second.*third"], + [no_prompt_check, sequence]), + {error,timeout} = ct_telnet:expect(Handle, ["the"], [no_prompt_check, + {timeout,?SHORT_TIME}]), + ok = ct_telnet_client:send_data(Backdoor, + "echo_no_prompt This is the fourth message"), + %% give the server time to respond + ct:sleep(2000), + %% closing the connection should print last message in log + ok = ct_telnet:close(Handle), + ok. + +%% Let the server close the connection. Make sure buffered data gets printed +%% to the general IO log. +server_disconnects(_) -> + {ok, Handle} = ct_telnet:open(telnet_server_conn1), + ok = ct_telnet:send(Handle, "disconnect_after 1500"), + %% wait until the get_data operation (triggered by send/2) times out + %% before sending the msg + ct:sleep(500), + ok = ct_telnet:send(Handle, "echo_no_prompt This is the message"), + %% when the server closes the connection, the last message should be + %% printed in the log + ct:sleep(3000), + _ = ct_telnet:close(Handle), + ok. + +%% Test option {newline,false} to send telnet command sequence. +newline_ayt(_) -> + {ok, Handle} = ct_telnet:open(telnet_server_conn1), + ok = ct_telnet:send(Handle, [?IAC,?AYT], [{newline,false}]), + {ok,["yes"]} = ct_telnet:expect(Handle, ["yes"]), + ok = ct_telnet:close(Handle), + ok. + +%% Test option {newline,false} to send telnet command sequence. +newline_break(_) -> + {ok, Handle} = ct_telnet:open(telnet_server_conn1), + ok = ct_telnet:send(Handle, [?IAC,?BRK], [{newline,false}]), + %% '#' is the prompt in break mode + {ok,["# "]} = ct_telnet:expect(Handle, ["# "], [no_prompt_check]), + {ok,R} = ct_telnet:cmd(Handle, "q", [{newline,false}]), + "> " = lists:flatten(R), ok = ct_telnet:close(Handle), ok. |