-
Notifications
You must be signed in to change notification settings - Fork 269
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add Wait to wait for expected output #257
Conversation
I've been experimenting with this and it's a useful feature, thanks for creating this! I've noticed though that it would benefit from a timeout option in the event the expected pattern isn't encountered? |
@rbergmanaf Yeah, I could see using that; should it be optional or required? If optional, should it have a default? It seems odd to have something hang forever by default. Something short, like 3 seconds, and then you can manually raise it for long commands. If the default is shorter, then it's more likely a user will put their value in for longer-running commands -- the last thing we want is a script that takes a long time failing halfway through because the user didn't realize there was a 30-second timeout or something. MatchLine <regex> [timeout] I considered using Alternatively, since it is a waiting command, we could just make it mandatory. |
I don't feel strongly, but do like the idea of a short default. |
I agree on the time out being a great option, I agree on the default of 3 seconds as well having the user manually bump it if they know it will be longer. Additionally, I would probably have this renamed to
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great! I'm really excited about this feature, just a bit concerned about the naming. I don't know if MatchLine
and MatchScreen
are the best names.
I also think waiting for the prompt i.e. MatchLine "^>"
will be a very popular incantation of the command. I wonder if it's worth having a Wait
command that simply Sleep
s until the prompt shows up.
token.go
Outdated
} | ||
return string(t) | ||
} | ||
|
||
func toCamel(s string) string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this extraction ❤️
|
||
// CurrentLine returns the current line from the buffer. | ||
func (v *VHS) CurrentLine() (string, error) { | ||
buf, err := v.Page.Eval("() => term.buffer.active.getLine(term.buffer.active.cursorY+term.buffer.active.viewportY).translateToString().trimEnd()") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, this is great! 👌
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great! I'm really excited about this feature, just a bit concerned about the naming. I don't know if MatchLine
and MatchScreen
are the best names.
I also think waiting for the prompt i.e. MatchLine "^>"
will be a very popular incantation of the command. I wonder if it's worth having a Wait
command that simply Sleep
s until the prompt shows up.
A simplified command like |
I like how I think As for the common case of waiting for prompts, we could potentially do a |
I would propose something like the following: Wait[+Context][@timeout] [regex]
Wait # simply wait for the prompt to appear (default timeout of 5 seconds)
Wait@3m # wait for a maximum of 3 minutes for the prompt to appear
Wait /hello/ # wait for hello to appear
Wait+Screen /hello/ # wait for hello to appear on the screen.
Wait+Line /hello/ # wait for hello to appear on the line.
Wait+Screen@1m /hello/ What are your thoughts? I think this syntax is nicer since it limits the commands but I'm very open to having different API that is potentially nicer? |
Context is a nice idea, is that used elsewhere or would this be a new syntax? As for defaulting, I think we should set the defaults for our "wait for prompt" use case. Set WaitPattern />$/ # default wait pattern
Set WaitTimeout 5s # default wait timeout
Wait # can be used in most cases to wait for the next prompt
Wait+Line # identical to the above
Wait@1m # for longer-running commands
Wait /custom-pattern/
Wait+Screen /dialog title/ # match anywhere on the screen |
Yup, sounds good!
This Ctrl+L
Alt+Enter In terms of implementation, the |
Okay, that all sounds reasonable, and thanks for the insight on context. The last bit to clarify is regex parsing -- we can probably piggyback on Does all sound good? |
The new REGEX token sounds great! |
Excellent, I'll switch this PR to a draft until I'm able to get those changes pushed up for review |
Hey @fenio, sorry for the delayed response. To test out this branch you would do something like:
and then run
|
@maaslalani thanks for sharing info how to build it but it fails this way with:
|
@maaslalani I just had to set WaitTimeout to 30s cause with default it was not enough. I LOVE IT ;) |
It's just 8s shorter but (not sure why) size dropped from around 1,05MB to 350kB which is significant amount. Please merge it as I already updated my tape files ;) |
Yeah the 5s wait timeout also caught me off guard. I think it should probably be either 15 or 30 seconds by default. |
Definitely. If someone tries to find something that will allow to work with commands that finish in unpredictable time then it's probably way more than 5 seconds ;) |
I updated the default to 15s for now, though I'm happy to adjust it if it should be higher. I expect use cases to vary a lot, so I'm not sure of the best value. |
So how about merge? What are the blockers for it? |
Maybe documentation should be updated too? |
FWIW, I also cloned astercactapus:match branch and ran the following tape (found earlier in this thread) - it worked perfectly: # Where should we write the GIF?
Output demo.gif
Set Shell fish
# Set up a 1200x600 terminal with 46px font.
Set FontSize 25
Set Width 1500
Set Height 1000
Set BorderRadius 10
Type "secator x httpx testphp.vulnweb.com"
Sleep 500ms
Enter
Wait |
I just tried running this locally and ran into this error (slightly modified the test script to run traceroute instead)
I ran a different tape, got a similar error:
|
Hey I was really curious about this feature, any update? |
Alright, so let's get this one done. I think we're there in terms of API and it should just be a matter of vetting the execution. Thanks for your patience with this one, everyone. |
…sts and actually run them in race mode (#560) Since we rely a lot on sleeping on the integration tests, due to the fact we can't yet go with charmbracelet/vhs#257, we need to be able to tune this value depending on the context we're running the tests. In general sanitizers slows down the runtime quite a bit (especially the thread one), so make possible to use dynamic sleep times values depending on variables that we adjust depending on the context we're running in. Tests can now slowed up/down using `AUTHD_TESTS_SLEEP_MULTIPLIER` variable too (this can be used for helping local testing too, e.g. personally I can reliably run the tests faster in my machine - with no failures - using `AUTHD_TESTS_SLEEP_MULTIPLIER=0.3`; but also it helps to quickly "fix" slower machines). Tune the tape files so that we don't miss some changing contents (as in the MFA/QrCode tests) and make the example broker to be a bit lazier. Then, I noticed that we were not actually running the integration tests in `-race` mode, so fix this. Indeed this implies slower tests, but at least now we're fully checking for races both the daemon and the client. This worked fine in various builds both in my fork and in a private repo fork I did where the builders are way slower than the public ones. UDENG-4793
Co-authored-by: Christian Rocha <[email protected]>
code-wise this lgtm! thanks everyone for the effort in this! ❤️ that said, one thing is that waiting on a line will not always work, e.g.
This might fail because at the time the line was check it was already just the prompt ( I guess there's no way around it though... But I thought this would work:
and i still got
maybe we should get the last line that isn't the prompt? |
@caarlos0
Solutions for your examples:
Both of these should also work over serial or SSH sessions. While potentially confusing, the current behavior serves the intended purpose of detecting when execution has finished (as best as possible). Alternatives like line-by-line processing of the buffer could introduce instability with large outputs since we can only scan what fits in the buffer (e.g., logs, large files), so we'll need to make a tradeoff somewhere on complexity/behavior. Determining if we're checking the same line twice would also be challenging, especially because the buffer can scroll as new lines are fed in. Conversely, tools like expect (which inspired this idea) can be deterministic and behave as you're expecting (no pun intended); however, that's only possible because they operate directly on a stream (i.e., a child process). Our options here are limited by operating through a "looking glass" to |
right, yeah, that makes sense! cool, so, IMO, we can merge this. @meowgorithm any additional remarks? |
LGTM. Let’s get it done. |
thanks everyone! <3 |
We were relying on sleeping when running integration tests tapes, but this is quite unreliable because: - Depends on the speed of the machine running the tests - Using generous sleeping times implies slower tests (this saves around 10m on CI tests...) So, use `Wait` commands from VHS charmbracelet/vhs#257 to only send input once the UI has the expected contents. Added some `Wait+$Extensions` to make regular expressions easier to maintain, and reducing complexity of the tape files. Fix some potential races that I've found while testing this. Based on #641 UDENG-4964
This PR adds two new commands:
MatchLine
that takes a regular expression and waits until the current line matchesMatchScreen
that takes a regular expression and waits until the "screen" matchesThe purpose is to allow waiting for things like network or serial devices that might have more variable delays while using VHS.
MatchLine
exampleMatchScreen
exampleAdditional Info
string(s[0]) + strings.ToLower(s[1:])
places were changed to atoCamel
helper with unit test (fixes issue withMUTLI_WORD
commands formatting).Buffer()
method was added to*VHS
to allow getting the current buffer as text (screen).CurrentLine()
method was added to*VHS
to allow getting the current line as text.SaveOutput()
was updated to use the shared method (largely the same code as before)