aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/common_test/src/ct_telnet.erl56
-rw-r--r--lib/common_test/test/ct_telnet_SUITE.erl7
-rw-r--r--lib/common_test/test/ct_telnet_SUITE_data/ct_telnet_own_server_SUITE.erl146
-rw-r--r--lib/common_test/test/telnet_server.erl15
4 files changed, 205 insertions, 19 deletions
diff --git a/lib/common_test/src/ct_telnet.erl b/lib/common_test/src/ct_telnet.erl
index b748c17f30..4755d939e0 100644
--- a/lib/common_test/src/ct_telnet.erl
+++ b/lib/common_test/src/ct_telnet.erl
@@ -309,7 +309,7 @@ expect(Connection,Patterns) ->
%%% Tag = term()
%%% Opts = [Opt]
%%% Opt = {timeout,Timeout} | repeat | {repeat,N} | sequence |
-%%% {halt,HaltPatterns} | ignore_prompt
+%%% {halt,HaltPatterns} | ignore_prompt | no_prompt_check
%%% Timeout = integer()
%%% N = integer()
%%% HaltPatterns = Patterns
@@ -336,14 +336,28 @@ expect(Connection,Patterns) ->
%%% will also include the matched <code>Tag</code>. Else, only
%%% <code>RxMatch</code> is returned.</p>
%%%
-%%% <p>The function will always return when a prompt is found, unless
-%%% the <code>ignore_prompt</code> options is used.</p>
-%%%
%%% <p>The <code>timeout</code> option indicates that the function
%%% shall return if the telnet client is idle (i.e. if no data is
%%% received) for more than <code>Timeout</code> milliseconds. Default
%%% timeout is 10 seconds.</p>
%%%
+%%% <p>The function will always return when a prompt is found, unless
+%%% any of the <code>ignore_prompt</code> or
+%%% <code>no_prompt_check</code> options are used, in which case it
+%%% will return when a match is found or after a timeout.</p>
+%%%
+%%% <p>If the <code>ignore_prompt</code> option is used,
+%%% <code>ct_telnet</code> will ignore any prompt found. This option
+%%% is useful if data sent by the server could include a pattern that
+%%% would match the prompt regexp (as returned by
+%%% <code>TargedMod:get_prompt_regexp/0</code>), but which should not
+%%% cause the function to return.</p>
+%%%
+%%% <p>If the <code>no_prompt_check</code> option is used,
+%%% <code>ct_telnet</code> will not search for a prompt at all. This
+%%% is useful if, for instance, the <code>Pattern</code> itself
+%%% matches the prompt.</p>
+%%%
%%% <p>The <code>repeat</code> option indicates that the pattern(s)
%%% shall be matched multiple times. If <code>N</code> is given, the
%%% pattern(s) will be matched <code>N</code> times, and the function
@@ -728,7 +742,8 @@ teln_get_all_data(Pid,Prx,Data,Acc,LastLine) ->
haltpatterns=[],
seq=false,
repeat=false,
- found_prompt=false}).
+ found_prompt=false,
+ prompt_check=true}).
%% @hidden
%% @doc Externally the silent_teln_expect function shall only be used
@@ -754,10 +769,16 @@ silent_teln_expect(Pid,Data,Pattern,Prx,Opts) ->
%% condition is fullfilled.
%% 3b) Repeat (sequence): 2) is repeated either N times or until a
%% halt condition is fullfilled.
-teln_expect(Pid,Data,Pattern0,Prx,Opts) -> HaltPatterns = case
- get_ignore_prompt(Opts) of true -> get_haltpatterns(Opts); false
- -> [prompt | get_haltpatterns(Opts)] end,
+teln_expect(Pid,Data,Pattern0,Prx,Opts) ->
+ HaltPatterns =
+ case get_ignore_prompt(Opts) of
+ true ->
+ get_haltpatterns(Opts);
+ false ->
+ [prompt | get_haltpatterns(Opts)]
+ end,
+ PromptCheck = get_prompt_check(Opts),
Seq = get_seq(Opts),
Pattern = convert_pattern(Pattern0,Seq),
@@ -767,7 +788,8 @@ teln_expect(Pid,Data,Pattern0,Prx,Opts) -> HaltPatterns = case
prx=Prx,
timeout=Timeout,
seq=Seq,
- haltpatterns=HaltPatterns},
+ haltpatterns=HaltPatterns,
+ prompt_check=PromptCheck},
case get_repeat(Opts) of
false ->
@@ -831,7 +853,9 @@ get_haltpatterns(Opts) ->
end.
get_ignore_prompt(Opts) ->
lists:member(ignore_prompt,Opts).
-
+get_prompt_check(Opts) ->
+ not lists:member(no_prompt_check,Opts).
+
%% Repeat either single or sequence. All match results are accumulated
%% and returned when a halt condition is fulllfilled.
repeat_expect(Rest,_Pattern,Acc,#eo{repeat=0}) ->
@@ -892,6 +916,9 @@ get_data1(Pid) ->
%% lines and each line is matched against each pattern.
%% one_expect: split data chunk at prompts
+one_expect(Data,Pattern,EO) when EO#eo.prompt_check==false ->
+% io:format("Raw Data ~p Pattern ~p EO ~p ",[Data,Pattern,EO]),
+ one_expect1(Data,Pattern,[],EO#eo{found_prompt=false});
one_expect(Data,Pattern,EO) ->
case match_prompt(Data,EO#eo.prx) of
{prompt,UptoPrompt,PromptType,Rest} ->
@@ -950,6 +977,8 @@ seq_expect(Data,[],Acc,_EO) ->
{match,lists:reverse(Acc),Data};
seq_expect([],Patterns,Acc,_EO) ->
{continue,Patterns,lists:reverse(Acc),[]};
+seq_expect(Data,Patterns,Acc,EO) when EO#eo.prompt_check==false ->
+ seq_expect1(Data,Patterns,Acc,[],EO#eo{found_prompt=false});
seq_expect(Data,Patterns,Acc,EO) ->
case match_prompt(Data,EO#eo.prx) of
{prompt,UptoPrompt,PromptType,Rest} ->
@@ -1013,6 +1042,13 @@ match_lines(Data,Patterns,EO) ->
{Tag,Match} ->
{Tag,Match,[]}
end;
+ {noline,Rest} when EO#eo.prompt_check==false ->
+ case match_line(Rest,Patterns,false,EO) of
+ nomatch ->
+ {nomatch,Rest};
+ {Tag,Match} ->
+ {Tag,Match,[]}
+ end;
{noline,Rest} ->
{nomatch,Rest};
{Line,Rest} ->
diff --git a/lib/common_test/test/ct_telnet_SUITE.erl b/lib/common_test/test/ct_telnet_SUITE.erl
index c75f0f5843..a378c531f0 100644
--- a/lib/common_test/test/ct_telnet_SUITE.erl
+++ b/lib/common_test/test/ct_telnet_SUITE.erl
@@ -53,8 +53,9 @@ end_per_suite(Config) ->
ct_test_support:end_per_suite(Config).
init_per_testcase(own_server=TestCase, Config) ->
- TS = telnet_server:start([{port,1234},{users,[{?erl_telnet_server_user,
- ?erl_telnet_server_pwd}]}]),
+ TS = telnet_server:start([{port,?erl_telnet_server_port},
+ {users,[{?erl_telnet_server_user,
+ ?erl_telnet_server_pwd}]}]),
ct_test_support:init_per_testcase(TestCase, [{telnet_server,TS}|Config]);
init_per_testcase(TestCase, Config) ->
ct_test_support:init_per_testcase(TestCase, Config).
@@ -92,7 +93,7 @@ own_server(Config) ->
DataDir = ?config(data_dir, Config),
Suite = filename:join(DataDir, "ct_telnet_own_server_SUITE"),
Cfg = {unix,[{telnet,"localhost"},
- {port, 1234},
+ {port, ?erl_telnet_server_port},
{username,?erl_telnet_server_user},
{password,?erl_telnet_server_pwd},
{wait_for_linebreak, false},
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 2173c68c11..3f7c0d68bf 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
@@ -19,7 +19,18 @@ suite() -> [{require,erl_telnet_server,{unix,[telnet]}}].
all() ->
[expect,
- expect_repeat].
+ expect_repeat,
+ expect_sequence,
+ expect_error_prompt,
+ expect_error_timeout,
+ no_prompt_check,
+ no_prompt_check_repeat,
+ no_prompt_check_sequence,
+ no_prompt_check_timeout,
+ ignore_prompt,
+ ignore_prompt_repeat,
+ ignore_prompt_sequence,
+ ignore_prompt_timeout].
groups() ->
[].
@@ -30,6 +41,7 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
+%% Simple expect
expect(_) ->
{ok, Handle} = ct_telnet:open(erl_telnet_server),
ok = ct_telnet:send(Handle, "echo ayt"),
@@ -37,10 +49,136 @@ expect(_) ->
ok = ct_telnet:close(Handle),
ok.
+%% Expect with repeat option
expect_repeat(_) ->
{ok, Handle} = ct_telnet:open(erl_telnet_server),
- ok = ct_telnet:send(Handle, "repeat xy"),
- {ok,[["xy"],["xy"]],done} = ct_telnet:expect(Handle, ["xy"],
- [{repeat,2}]),
+ 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),
+ ok.
+
+%% Expect with sequence option
+expect_sequence(_) ->
+ {ok, Handle} = ct_telnet:open(erl_telnet_server),
+ ok = ct_telnet:send(Handle, "echo_ml ab cd ef"),
+ {ok,[["ab"],["cd"],["ef"]]} = ct_telnet:expect(Handle,
+ [["ab"],["cd"],["ef"]],
+ [sequence]),
+ ok = ct_telnet:close(Handle),
+ 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 = ct_telnet:send(Handle, "echo xxx> yyy"),
+ {error,{prompt,"> "}} = ct_telnet:expect(Handle, ["yyy"]),
+ ok = ct_telnet:close(Handle),
+ ok.
+
+%% 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),
+ ok = ct_telnet:send(Handle, "echo_no_prompt xxx"),
+ {error,timeout} = ct_telnet:expect(Handle, ["xxx"], [{timeout,1000}]),
+ 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 = ct_telnet:send(Handle, "echo xxx> yyy"),
+ {ok,["yyy"]} = ct_telnet:expect(Handle, ["yyy"], [ignore_prompt]),
+ ok = ct_telnet:close(Handle),
+ ok.
+
+%% expect with ignore_prompt and repeat options.
+ignore_prompt_repeat(_) ->
+ {ok, Handle} = ct_telnet:open(erl_telnet_server),
+ ok = ct_telnet:send(Handle, "echo_ml yyy> yyy>"),
+ {ok,[["yyy"],["yyy"]],done} = ct_telnet:expect(Handle, ["yyy"],
+ [{repeat,2},
+ ignore_prompt]),
+ ok = ct_telnet:close(Handle),
+ ok.
+
+%% expect with ignore_prompt and sequence options.
+ignore_prompt_sequence(_) ->
+ {ok, Handle} = ct_telnet:open(erl_telnet_server),
+ ok = ct_telnet:send(Handle, "echo_ml xxx> yyy> zzz> "),
+ {ok,[["xxx"],["yyy"],["zzz"]]} = ct_telnet:expect(Handle,
+ [["xxx"],["yyy"],["zzz"]],
+ [sequence,
+ ignore_prompt]),
+ ok = ct_telnet:close(Handle),
+ ok.
+
+%% Check that expect returns after idle timeout when ignore_prompt
+%% option is used.
+%% 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 = ct_telnet:send(Handle, "echo xxx"),
+ {error,timeout} = ct_telnet:expect(Handle, ["yyy"], [ignore_prompt,
+ {timeout,1000}]),
+ ok = ct_telnet:send(Handle, "echo xxx"), % sends prompt and newline
+ {ok,["xxx"]} = ct_telnet:expect(Handle, ["xxx"], [ignore_prompt,
+ {timeout,1000}]),
+ 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}]),
+ ok = ct_telnet:send(Handle, "echo_no_prompt xxx"), % no prompt, no newline
+ {error,timeout} = ct_telnet:expect(Handle, ["xxx"], [ignore_prompt,
+ {timeout,1000}]),
+ 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 = 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"),
+ {ok,["yyy"]} = ct_telnet:expect(Handle, ["yyy"], [no_prompt_check]),
+ ok = ct_telnet:close(Handle),
+ ok.
+
+%% no_prompt_check and repeat options
+no_prompt_check_repeat(_) ->
+ {ok, Handle} = ct_telnet:open(erl_telnet_server),
+ ok = ct_telnet:send(Handle, "echo_ml xxx xxx"),
+ {ok,[["xxx"],["xxx"]],done} = ct_telnet:expect(Handle,["xxx"],
+ [{repeat,2},
+ no_prompt_check]),
+ ok = ct_telnet:send(Handle, "echo_ml_no_prompt yyy yyy"),
+ {ok,[["yyy"],["yyy"]],done} = ct_telnet:expect(Handle,["yyy"],
+ [{repeat,2},
+ no_prompt_check]),
+ ok = ct_telnet:close(Handle),
+ ok.
+
+%% no_prompt_check and sequence options
+no_prompt_check_sequence(_) ->
+ {ok, Handle} = ct_telnet:open(erl_telnet_server),
+ ok = ct_telnet:send(Handle, "echo_ml_no_prompt ab cd ef"),
+ {ok,[["ab"],["cd"],["ef"]]} = ct_telnet:expect(Handle,
+ [["ab"],["cd"],["ef"]],
+ [sequence,
+ no_prompt_check]),
+ ok = ct_telnet:close(Handle),
+ ok.
+
+%% 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 = ct_telnet:send(Handle, "echo xxx"),
+ {error,timeout} = ct_telnet:expect(Handle, ["yyy"], [no_prompt_check,
+ {timeout,1000}]),
ok = ct_telnet:close(Handle),
ok.
diff --git a/lib/common_test/test/telnet_server.erl b/lib/common_test/test/telnet_server.erl
index 5843155eee..31884aa182 100644
--- a/lib/common_test/test/telnet_server.erl
+++ b/lib/common_test/test/telnet_server.erl
@@ -93,6 +93,7 @@ do_accept(LSock,Server) ->
end.
init_client(#state{client=Sock}=State) ->
+ dbg("Server sending: ~p~n",["login: "]),
R = case gen_tcp:send(Sock,"login: ") of
ok ->
loop(State);
@@ -164,8 +165,18 @@ do_handle_data(Data,#state{authorized={user,_}}=State) ->
do_handle_data("echo "++ Data,State) ->
send(Data++"\r\n> ",State),
{ok,State};
-do_handle_data("repeat "++ Data,State) ->
- send(Data++"\r\n"++Data++"\r\n> ",State),
+do_handle_data("echo_no_prompt "++ Data,State) ->
+ send(Data,State),
+ {ok,State};
+do_handle_data("echo_ml "++ Data,State) ->
+ Lines = string:tokens(Data," "),
+ ReturnData = string:join(Lines,"\n"),
+ send(ReturnData++"\r\n> ",State),
+ {ok,State};
+do_handle_data("echo_ml_no_prompt "++ Data,State) ->
+ Lines = string:tokens(Data," "),
+ ReturnData = string:join(Lines,"\n"),
+ send(ReturnData,State),
{ok,State};
do_handle_data([],State) ->
send("> ",State),