diff --git a/doc/config_params.md.src b/doc/config_params.md.src index f92c93c4..e24b090d 100644 --- a/doc/config_params.md.src +++ b/doc/config_params.md.src @@ -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 diff --git a/doc/script_syntax.md.src b/doc/script_syntax.md.src index 4debf54e..8cc73c46 100644 --- a/doc/script_syntax.md.src +++ b/doc/script_syntax.md.src @@ -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 @@ -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 @@ -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`. diff --git a/emacs/lux-mode.el b/emacs/lux-mode.el index 66a2426b..c5e82c25 100644 --- a/emacs/lux-mode.el +++ b/emacs/lux-mode.el @@ -75,6 +75,7 @@ "mode" "multiplier" "newshell" + "pattern_mode" "poll_timeout" "post_case" "progress" diff --git a/src/lux.hrl b/src/lux.hrl index 701a0b01..c63f7d36 100644 --- a/src/lux.hrl +++ b/src/lux.hrl @@ -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()}). @@ -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(), @@ -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{}, diff --git a/src/lux_args.erl b/src/lux_args.erl index 67b48ff7..520e3259 100644 --- a/src/lux_args.erl +++ b/src/lux_args.erl @@ -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}, @@ -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) -> @@ -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}, @@ -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}, diff --git a/src/lux_case.erl b/src/lux_case.erl index c27c9c53..43a8cc52 100644 --- a/src/lux_case.erl +++ b/src/lux_case.erl @@ -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 -> @@ -852,6 +854,7 @@ user_config_keys() -> poll_timeout, timeout, cleanup_timeout, + pattern_mode, risky_threshold, sloppy_threshold, newshell, diff --git a/src/lux_interpret.erl b/src/lux_interpret.erl index d82c2442..3e57a9bd 100644 --- a/src/lux_interpret.erl +++ b/src/lux_interpret.erl @@ -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}) -> @@ -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 = @@ -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=", diff --git a/src/lux_parse.erl b/src/lux_parse.erl index 95972638..7911074a 100644 --- a/src/lux_parse.erl +++ b/src/lux_parse.erl @@ -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 -> diff --git a/src/lux_shell.erl b/src/lux_shell.erl index d0cf00fc..81ccbf39 100644 --- a/src/lux_shell.erl +++ b/src/lux_shell.erl @@ -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, @@ -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]}}; @@ -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 -> @@ -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 -> @@ -1115,7 +1121,11 @@ split_single_match(C, Matches, Actual, Context, AltSkip) -> end end, SubBins = lists:map(Extract, SubMatches), - SkipMatch = <>, + SkipMatch = + case C#cstate.pattern_mode of + all -> <>; + skip -> Skip + end, {SkipMatch, Rest, SubBins, LogFun}. split_total(Actual, Matches, AltSkip) -> diff --git a/test/fast-fail.lux b/test/fast-fail.lux new file mode 100644 index 00000000..042ff055 --- /dev/null +++ b/test/fast-fail.lux @@ -0,0 +1,47 @@ +[shell test] + [timeout 30] + + [progress EXPECT SUCCESS] + !echo "aaabbbGOODccc" > tmp.txt + ?SH-PROMPT: + [invoke match] + + [progress EXPECT FAST FAIL] + !echo "aaabbbBADccc" > tmp.txt + ?SH-PROMPT: + [invoke match] + +[macro match] + # When is seen we know that the output is ready to be + # matched. If something unexpected is seen before the + # 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] + - + + !cat tmp.txt + """? + aaa + """ + """? + bbb + """ + """? + GOOD + """ + """? + ccc + """ + -${old_fail} + [pattern_mode ${old_mode}] + + ?SH-PROMPT: +[endmacro] + +[cleanup] + !rm -f tmp.txt + ?SH-PROMPT: diff --git a/vim/syntax/lux.vim b/vim/syntax/lux.vim index ba3c0383..3b54580c 100644 --- a/vim/syntax/lux.vim +++ b/vim/syntax/lux.vim @@ -31,6 +31,7 @@ syn match luxVarArg /\(\$\)\@1