Skip to content

Commit

Permalink
Experimental: Add pattern_mode command and config parameter
Browse files Browse the repository at this point in the history
The setting affects which data that are matched agains fail and
success patterns.

    [pattern_mode]
    [pattern_mode all]
    [pattern_mode skip]

    --pattern_mode=all
    --pattern_mode=skip
  • Loading branch information
Håkan Mattsson committed Aug 23, 2023
1 parent fd9b38a commit f3b8efa
Show file tree
Hide file tree
Showing 11 changed files with 131 additions and 2 deletions.
10 changes: 10 additions & 0 deletions doc/config_params.md.src
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,16 @@ tries to match it against any [regular expression][]s. It defaults
to `0`. If you want to experiment with it, `100` milliseconds
(1/10 second) can be a resonable value.

**--pattern\_mode PatternMode**
EXPERIMENTAL FEATURE!!! May be changed or removed in a future release.

Changes the default behavior of fail and success patterns. This can
be overridden separately for each shell with the \[pattern\_mode
PatternMode\] command. Valid settings are `all` and `skip`. The
default is `all`.

See the command `\[pattern\_mode PatternMode\]` for details.

**--risky\_threshold RiskyThreshold**
An experimental timeout setting.
By default Lux warns for risky timers, i.e. timers that are close
Expand Down
24 changes: 24 additions & 0 deletions doc/script_syntax.md.src
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ explicitly is expecting some output. That is when a command like `?`,
cannot produce more output, for example when a shell exits or when
there are no more commands to evaluate.

See also the configuration parameter `--pattern_mode` and the command
`[pattern_mode]`.

**+**
**+Regexp**
Sets the success pattern for a shell to a regular expression (see
Expand All @@ -124,6 +127,9 @@ explicitly is expecting some output. That is when a command like `?`,
cannot produce more output, for example when a shell exits or when
there are no more commands to evaluate.

See also the configuration parameter `--pattern_mode` and the command
`[pattern_mode]`.

**@**
**@Regexp**
Sets a loop break pattern for a shell to a regular expression (see
Expand Down Expand Up @@ -443,3 +449,21 @@ parameters. Some config parameters can have multiple values, such as
`skip` and `require`. See their respective descriptions. See also the
configuration parameter `--config_dir` about the location of the
architecture specific files.

**\[pattern\_mode\]**
**\[pattern\_mode PatternMode\]**
EXPERIMENTAL FEATURE!!! May be changed or removed in a future release.

Changes the behavior of fail and success patterns in a shell. By
default these patterns are matched against everything found in the
output streams (`stdout`, `stderr`). This means that they are both
matched against the characters actually are matching (in a `?`, `??`
or `???` commands) as well as the characters that are skipped (not
explicitely matched). This default behavior can also be achieved by
setting `PatternMode` to `all` for the shell.

By setting `PatternMode` to `skip` instead, only the skipped (not
explicitely matched) are matched against the fail and success
patterns.

See also the configuration parameter `--pattern_mode`.
1 change: 1 addition & 0 deletions emacs/lux-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
"mode"
"multiplier"
"newshell"
"pattern_mode"
"poll_timeout"
"post_case"
"progress"
Expand Down
3 changes: 3 additions & 0 deletions src/lux.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
health :: alive | zombie,
vars :: [string()], % ["name=val"]
match_timeout :: infinity | non_neg_integer(),
pattern_mode :: all | skip,
fail_pattern :: undefined | binary(),
success_pattern :: undefined | binary()}).

Expand Down Expand Up @@ -198,6 +199,7 @@
poll_timeout = 0 :: non_neg_integer(), % Should be 100
default_timeout = 10*?ONE_SEC :: non_neg_integer() | infinity,
cleanup_timeout = 100*?ONE_SEC :: non_neg_integer() | infinity,
default_pattern_mode = all :: all | skip,
risky_threshold = ?DEFAULT_RISKY_THRESHOLD :: float() | infinity,
sloppy_threshold = ?DEFAULT_SLOPPY_THRESHOLD :: float() | infinity,
newshell = false :: boolean(),
Expand Down Expand Up @@ -323,6 +325,7 @@
flush_timeout :: non_neg_integer(),
poll_timeout :: non_neg_integer(),
match_timeout :: non_neg_integer() | infinity,
pattern_mode :: all | skip,
timer_ref :: undefined | #timer_ref{},
timer_started_at :: undefined | erlang:timestamp(),
wakeup_ref :: undefined | #timer_ref{},
Expand Down
5 changes: 5 additions & 0 deletions src/lux_args.erl
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ specs() ->
{"--poll_timeout", 100, {integer, -1, infinity},mandatory},
{"--timeout", 10*1000, {integer, 0, infinity}, mandatory},
{"--cleanup_timeout", 100*1000, {integer, 0, infinity}, mandatory},
{"--pattern_mode", all , {enum, pattern_mode}, mandatory},
{"--risky_threshold", 0.85, {float, 0.0, infinity}, mandatory},
{"--sloppy_threshold", 0.000000001, {float, 0.0, infinity}, mandatory},
{"--newshell" , false, boolean, none},
Expand Down Expand Up @@ -109,6 +110,8 @@ enum(history_cases) ->
[latest, any];
enum(wrapper_mode) ->
[silent, debug, trace];
enum(pattern_mode) ->
[all, skip];
enum(prio) ->
[enable, success, skip, warning, fail, error, disable];
enum(html) ->
Expand Down Expand Up @@ -240,6 +243,7 @@ translate_opts([
{"--poll_timeout", PollTimeout},
{"--timeout", ExpectTimeout},
{"--cleanup_timeout", CleanupTimeout},
{"--pattern_mode", PatternMode},
{"--risky_threshold", RiskyThreshold},
{"--sloppy_threshold", SloppyThreshold},
{"--newshell", NewShell},
Expand Down Expand Up @@ -274,6 +278,7 @@ translate_opts([
{poll_timeout, PollTimeout},
{timeout, ExpectTimeout},
{cleanup_timeout, CleanupTimeout},
{pattern_mode, PatternMode},
{risky_threshold, RiskyThreshold},
{sloppy_threshold, SloppyThreshold},
{newshell, NewShell},
Expand Down
3 changes: 3 additions & 0 deletions src/lux_case.erl
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,8 @@ config_type(Name) ->
cleanup_timeout ->
{ok, #istate.cleanup_timeout, [{integer, 0, infinity},
{atom, [infinity]}]};
pattern_mode ->
{ok, #istate.default_pattern_mode, [{atom, [all, skip]}]};
risky_threshold ->
{ok, #istate.risky_threshold, [{float, 0.0, infinity}]};
sloppy_threshold ->
Expand Down Expand Up @@ -852,6 +854,7 @@ user_config_keys() ->
poll_timeout,
timeout,
cleanup_timeout,
pattern_mode,
risky_threshold,
sloppy_threshold,
newshell,
Expand Down
21 changes: 21 additions & 0 deletions src/lux_interpret.erl
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,24 @@ dispatch_cmd(I,
I2
end
end;
change_pattern_mode ->
PatternMode =
case Arg of
default ->
I#istate.default_pattern_mode;
PatternModeStr ->
case safe_expand_vars(I, PatternModeStr) of
{ok, "all"} ->
all;
{ok, "skip"} ->
skip;
{no_such_var, BadName} ->
no_such_var(I, Cmd, Cmd#cmd.lineno, BadName)
end
end,
Cmd2 = Cmd#cmd{arg = PatternMode},
ShellPos = #shell.pattern_mode,
change_shell_var(I, ShellPos, PatternMode, Cmd2);
doc ->
DisplayDoc =
fun({Level, Doc}) ->
Expand Down Expand Up @@ -1677,6 +1695,7 @@ expand_vars(#istate{active_shell = Shell,
case Shell of
#shell{vars = LocalVars,
match_timeout = Millis,
pattern_mode = PatternMode,
fail_pattern = FailPattern,
success_pattern = SuccessPattern} ->
Secs =
Expand All @@ -1688,6 +1707,8 @@ expand_vars(#istate{active_shell = Shell,
[
lists:flatten("LUX_TIMEOUT=",
?FF("~p", [Secs])),
lists:flatten("LUX_PATTERN_MODE=",
?FF("~p", [PatternMode])),
lists:flatten("LUX_FAIL_PATTERN=",
?FF("~s", [opt_binary(FailPattern)])),
lists:flatten("LUX_SUCCESS_PATTERN=",
Expand Down
4 changes: 4 additions & 0 deletions src/lux_parse.erl
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,10 @@ parse_meta_token(P, Fd, Cmd, Meta, LineNo) ->
{P, Cmd#cmd{type = change_timeout, arg = Time}};
"timeout " ++ Time ->
{P, Cmd#cmd{type = change_timeout, arg = Time}};
"pattern_mode" ->
{P, Cmd#cmd{type = change_pattern_mode, arg = default}};
"pattern_mode " ++ PatternMode ->
{P, Cmd#cmd{type = change_pattern_mode, arg = PatternMode}};
"sleep " ++ Time ->
{P, Cmd#cmd{type = sleep, arg = Time}};
"progress " ++ String ->
Expand Down
14 changes: 12 additions & 2 deletions src/lux_shell.erl
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ start_monitor(I, Cmd, Name, ExtraLogs) ->
flush_timeout = I#istate.flush_timeout,
poll_timeout = I#istate.poll_timeout,
match_timeout = I#istate.default_timeout,
pattern_mode = I#istate.default_pattern_mode,
risky_threshold = I#istate.risky_threshold,
sloppy_threshold = I#istate.sloppy_threshold,
shell_wrapper = I#istate.shell_wrapper,
Expand All @@ -58,7 +59,8 @@ start_monitor(I, Cmd, Name, ExtraLogs) ->
ref = Ref,
health = alive,
vars = NewVarVals ++ I#istate.global_vars,
match_timeout = C#cstate.match_timeout},
match_timeout = C#cstate.match_timeout,
pattern_mode = C#cstate.pattern_mode},
I2 = I#istate{active_shell = Shell,
active_name = Name},
{ok, I2#istate{logs = I2#istate.logs ++ [Logs]}};
Expand Down Expand Up @@ -457,6 +459,7 @@ assert_eval(_C, #cmd{type = Type}, _From)
Type =:= break;
Type =:= progress;
Type =:= change_timeout;
Type =:= change_pattern_mode;
Type =:= no_cleanup;
Type =:= cleanup;
Type =:= post_case ->
Expand Down Expand Up @@ -628,6 +631,9 @@ shell_eval(#cstate{name = Name} = C0,
end,
C#cstate{match_timeout = Millis,
warnings = NewWarnings};
change_pattern_mode ->
PatternMode = Arg,
C#cstate{pattern_mode = PatternMode};
no_cleanup ->
cleanup(C, Type);
cleanup ->
Expand Down Expand Up @@ -1115,7 +1121,11 @@ split_single_match(C, Matches, Actual, Context, AltSkip) ->
end
end,
SubBins = lists:map(Extract, SubMatches),
SkipMatch = <<Skip/binary, Match/binary>>,
SkipMatch =
case C#cstate.pattern_mode of
all -> <<Skip/binary, Match/binary>>;
skip -> Skip
end,
{SkipMatch, Rest, SubBins, LogFun}.

split_total(Actual, Matches, AltSkip) ->
Expand Down
47 changes: 47 additions & 0 deletions test/fast-fail.lux
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
[shell test]
[timeout 30]

[progress EXPECT SUCCESS]
!echo "aaa<PROMPT>bbb<PROMPT>GOOD<PROMPT>ccc<PROMPT>" > tmp.txt
?SH-PROMPT:
[invoke match]

[progress EXPECT FAST FAIL]
!echo "aaa<PROMPT>bbb<PROMPT>BAD<PROMPT>ccc<PROMPT>" > tmp.txt
?SH-PROMPT:
[invoke match]

[macro match]
# When <PROMPT> is seen we know that the output is ready to be
# matched. If something unexpected is seen before the <PROMPT>
# instead we know it is wrong and then we want to fail fast. This
# setup requires [pattern_mode skip].

[my old_mode=${LUX_PATTERN_MODE}]
[my old_fail=${LUX_FAIL_PATTERN}]

[pattern_mode skip]
-<PROMPT>

!cat tmp.txt
"""?
aaa<PROMPT>
"""
"""?
bbb<PROMPT>
"""
"""?
GOOD<PROMPT>
"""
"""?
ccc<PROMPT>
"""
-${old_fail}
[pattern_mode ${old_mode}]

?SH-PROMPT:
[endmacro]

[cleanup]
!rm -f tmp.txt
?SH-PROMPT:
1 change: 1 addition & 0 deletions vim/syntax/lux.vim
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ syn match luxVarArg /\(\$\)\@1<!\$[a-zA-Z0-9_]\+/ contained
syn keyword luxKeyword config include contained nextgroup=luxArgs skipwhite
syn keyword luxKeyword shell contained nextgroup=luxArgs skipwhite
syn keyword luxKeyword newshell contained nextgroup=luxArgs skipwhite
syn keyword luxKeyword pattern_mode contained nextgroup=luxArgs skipwhite
syn keyword luxKeyword timeout contained
\ nextgroup=luxNumArg,luxVarArg,luxMetaEnd skipwhite
syn keyword luxKeyword sleep contained nextgroup=luxNumArg,luxVarArg skipwhite
Expand Down

0 comments on commit f3b8efa

Please sign in to comment.