aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorSiri Hansen <[email protected]>2013-05-15 12:09:36 +0200
committerSiri Hansen <[email protected]>2013-05-17 11:47:26 +0200
commit55d975b3a1266d50b5a55004a004d0f244d5a17b (patch)
tree5f82e8d4e9478f409616f72b5ae3718c2e446044 /lib
parent61641a3e1d86014ce6e6a27ab27faac7ec461d70 (diff)
downloadotp-55d975b3a1266d50b5a55004a004d0f244d5a17b.tar.gz
otp-55d975b3a1266d50b5a55004a004d0f244d5a17b.tar.bz2
otp-55d975b3a1266d50b5a55004a004d0f244d5a17b.zip
[common_test] Add new option 'no_prompt_check' to ct_telnet:expect/3.
If this option is used, ct_telnet will not search for a prompt before attempting to match the given pattern. This is useful if, for instance, the Pattern itself matches the prompt or if the telnet session starts interactive programs which do not display the normal prompt.
Diffstat (limited to 'lib')
-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),