GithubHelp home page GithubHelp logo

rexpect's People

Contributors

badhrink avatar bors[bot] avatar dependabot[bot] avatar didier-wenzek avatar gz avatar khuey avatar kosayoda avatar matthiasbeyer avatar memoryruins avatar pbartyik avatar petreeftime avatar phaer avatar philippkeller avatar scottconrad avatar souze avatar thomasantony avatar typr124 avatar zhiburt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rexpect's Issues

try_read panic

Try to read a utf-8 character, program panic.
How to fix this problem?

panicked at 'byte index 1 is not a char boundary; it is inside 'é' (bytes 0..2) of `éª�æ�¶ ...

stack backtrace:
0: backtrace::backtrace::libunwind::trace
at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.44/src/backtrace/libunwind.rs:86
1: backtrace::backtrace::trace_unsynchronized
at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.44/src/backtrace/mod.rs:66
2: std::sys_common::backtrace::_print_fmt
at src/libstd/sys_common/backtrace.rs:78
3: <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt
at src/libstd/sys_common/backtrace.rs:59
4: core::fmt::write
at src/libcore/fmt/mod.rs:1063
5: std::io::Write::write_fmt
at /rustc/4fb7144ed159f94491249e86d5bbd033b5d60550/src/libstd/io/mod.rs:1426
6: std::io::impls::<impl std::io::Write for alloc::boxed::Box>::write_fmt
at src/libstd/io/impls.rs:156
7: std::sys_common::backtrace::_print
at src/libstd/sys_common/backtrace.rs:62
8: std::sys_common::backtrace::print
at src/libstd/sys_common/backtrace.rs:49
9: std::panicking::default_hook::{{closure}}
at src/libstd/panicking.rs:204
10: std::panicking::default_hook
at src/libstd/panicking.rs:221
11: std::panicking::rust_panic_with_hook
at src/libstd/panicking.rs:470
12: rust_begin_unwind
at src/libstd/panicking.rs:378
13: core::panicking::panic_fmt
at src/libcore/panicking.rs:85
14: core::str::slice_error_fail
at src/libcore/str/mod.rs:0
15: core::str::traits::<impl core::slice::SliceIndex for core::ops::range::Range>::index::{{closure}}
at /rustc/4fb7144ed159f94491249e86d5bbd033b5d60550/src/libcore/str/mod.rs:1919
16: core::option::Option::unwrap_or_else
at /rustc/4fb7144ed159f94491249e86d5bbd033b5d60550/src/libcore/option.rs:428
17: core::str::traits::<impl core::slice::SliceIndex for core::ops::range::Range>::index
at /rustc/4fb7144ed159f94491249e86d5bbd033b5d60550/src/libcore/str/mod.rs:1919
18: core::str::traits::<impl core::ops::index::Index for str>::index
at /rustc/4fb7144ed159f94491249e86d5bbd033b5d60550/src/libcore/str/mod.rs:1780
19: <alloc::string::String as core::ops::index::Index<core::ops::range::Range>>::index
at /rustc/4fb7144ed159f94491249e86d5bbd033b5d60550/src/liballoc/string.rs:1999
20: alloc::string::String::drain
at /rustc/4fb7144ed159f94491249e86d5bbd033b5d60550/src/liballoc/string.rs:1551
21: rexpect::reader::NBReader::try_read
at /home/zhangyongcheng/.cargo/registry/src/mirrors.tuna.tsinghua.edu.cn-df7c3c540f42cdbd/rexpect-0.4.0/src/reader.rs:265
22: rexpect::session::StreamSession::try_read
at /home/zhangyongcheng/.cargo/registry/src/mirrors.tuna.tsinghua.edu.cn-df7c3c540f42cdbd/rexpect-0.4.0/src/session.rs:98

rexpect 0.3 ready ?

Hi @philippkeller
In README.md, the example is referring to rexpect 0.3.0 while the version on crates.io is only upto 0.2.0.

I tried to test out the examples in README.md using 0.2.0 but failed with following message.

[me@fedora01 src]$cargo build
   Compiling cmd1 v0.1.0 (file:///home/tjyang/cmd1)
error[E0061]: this function takes 1 parameter but 2 parameters were supplied
 --> src/main.rs:8:7
  |
8 |     p.execute("ping 8.8.8.8", "bytes of data")?;
  |       ^^^^^^^ expected 1 parameter

error[E0061]: this function takes 1 parameter but 2 parameters were supplied
  --> src/main.rs:12:7
   |
12 |     p.execute("bg", "ping 8.8.8.8")?;
   |       ^^^^^^^ expected 1 parameter

error[E0061]: this function takes 1 parameter but 2 parameters were supplied
  --> src/main.rs:17:7
   |
17 |     p.execute("fg", "ping 8.8.8.8")?;
   |       ^^^^^^^ expected 1 parameter

error: aborting due to 3 previous errors

error: Could not compile `cmd1`.

To learn more, run the command again with --verbose.
[me@fedora01 src]$

get the index of element that was matched by exp_any

find fn returns a tuple with the unread buffer and the matched string by needle. The question is if it could also return the position of the expression used in ReadUntil::Any(vec)? Right now I'm looping through the passed expressions and checking which one matches the returned matched string.

Think "did I match username or password prompt, what to send back to the process".

Replace error-chain with thiserror

I would like to replace the (seemingly abandoned) error-chain dependency with the maintained thiserror.

Does anyone object? @petreeftime?

rexpect has a lot of unwrap()/expect() calls in the codebase, which I would like to review after moving to thiserror (and hopefully fix, of course).

bash_read.rs: use rexpect::error::Error; --> could not find `error` in `rexpect`

I am learning rexpect via *.rs in examples dir.

  • With following Cargo.toml and needed directory layout, I was able to run command like "cargo run --bin bash_read" to see if it works.

[me@ipa01 examples]$ cat Cargo.toml
[package]
name = "rexpect-examples"
version = "0.1.0"
authors = ["rexpect authors"]
description = "Cargo.toml to compile rexpect examples in batch"
license = "MIT"
homepage = "https://github.com/rust-cli/rexpect"
readme = "README.md"
categories = ["command-line-utilities" ]
keywords = ["rexpect", "rust", "bash"]

[dependencies]
rexpect = "0.4.0"
[me@ipa01 examples]$

[me@ipa01 examples]$ tree -L 23
.
├── Cargo.lock
├── Cargo.toml
└── src
└── bin
└── bash_read.rs

2 directories, 3 files
[me@ipa01 examples]$

  • Output of "cargo run --bin bash_read" command

[me@ipa01 examples]$ cargo run --bin bash_read
Compiling memchr v2.5.0
Compiling libc v0.2.135
Compiling cc v1.0.73
Compiling gimli v0.26.2
Compiling version_check v0.9.4
Compiling adler v1.0.2
Compiling cfg-if v1.0.0
Compiling nix v0.14.1
Compiling rustc-demangle v0.1.21
Compiling fastrand v1.8.0
Compiling remove_dir_all v0.5.3
Compiling regex-syntax v0.6.27
Compiling void v1.0.2
Compiling cfg-if v0.1.10
Compiling bitflags v1.3.2
Compiling miniz_oxide v0.5.4
Compiling error-chain v0.12.4
Compiling backtrace v0.3.66
Compiling object v0.29.0
Compiling aho-corasick v0.7.19
Compiling addr2line v0.17.0
Compiling tempfile v3.3.0
Compiling regex v1.6.0
Compiling rexpect v0.4.0
Compiling rexpect-examples v0.1.0 (/home/me/github/rexpect/contrib/examples)
error[E0432]: unresolved import rexpect::error
--> src/bin/bash_read.rs:2:14
|
2 | use rexpect::error::Error;
| ^^^^^ could not find error in rexpect

For more information about this error, try rustc --explain E0432.
error: could not compile rexpect-examples due to previous error
[me@ipa01 examples]$

  • src/bin/bash_read.rs is unchanged examples/bash_read.rs.

better support for embedded targets, ssh

spawn_bash assumes you're spawning a new terminal on the same machine running rexpect. I use pexpect to write integration tests for embedded targets and pxssh is really useful. Having the fairly robust ssh login stuff for starters, but also not assuming the login shell is necessarily bash while still providing reliable synchronization and resetting the prompt (i.e. set PS1 but don't try to load .profile or anything)

Binary support?

Some binary data cannot be represented in an &str, so functions that take &[u8] are necessary. Unless I misunderstand or am using the wrong tool.

Use case is programing Marvell ARMADA 3700 over serial port.

spawn() does not return Error when trying to start an invalid program

Expected Behaviour:

Trying to launch an invalid program (file does not exist, is not executable etc.) should return an error.

use rexpect::spawn;

let mut spawned = spawn("invalidprogram", None);
println!("[{}] spawned is Error: {}", std::process::id(), spawned.is_err());

should print something like

[19989] spawned is Error: true

Actual behaviour:

spawn returns an Ok(PtySession)

Further testing shows:

let mut program = spawned.unwrap();  // does not fail, because it is an Ok(PtySession)
let output = program.exp_eof();  // capturing the full output of the PtySession
println!("{:?}", output);

outputs

Ok("[20011] spawned is Error: true\r\nthread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Nix(ENOENT)', src/main.rs:9:31\r\nnote: run with `RUST_BACKTRACE=1` environment variable to display a backtrace\r\n")

So it seems that it does actually fail but does not propagate the Error to the parent.

Send signals to underlying process?

I notice you can send a control character like <ctrl-c> for keyboard interrupt, or <ctrl-d> for EOF. Is there any way to send a signal like SIGTERM or SIGHUP (perhaps using a nix::sys::signal::Signal) to the underlying process?

An alternative might be adding a method to the PtySession which gives you a mutable reference to the underlying PtyProcess so you can call signal() and friends directly on that.

RFC: Create another dir to host Cargo.toml file and directory layout to test/learn examples

Hi @matthiasbeyer

As a rexpect beginner, I had to create my own dir structure and file to really run/test/learn rexpect crate.

  • Can this be part of rexpect src tree ?
[me@ipa01 rexpect]$ pwd
/home/me/github/rexpect
[me@ipa01 rexpect]$ tree contrib -L 4
contrib
└── examples
    ├── Cargo.toml
    └── src
        └── bin
            ├── bash_read.rs
            ├── bash.rs
            ├── exit_code.rs
            ├── ftp.rs
            ├── repl.rs
            └── tcp.rs

3 directories, 7 files
[me@ipa01 rexpect]$

Migrate away from Error-Chain

Error-Chain seems to be unmaintained or rather not developed any further. Furthermore most people start adopting failure,anyhow and eyre for new errors in applications, which require Sync on errors to allow easier multithreading. Currently error-chain can't and won't have sync errors, requiring some special handling for errors of this library. Thus I recommend migrating to thiserror.

See also rust-lang-deprecated/error-chain#240 and wisespace-io/pwned-rs#4 for more info and an attached PR for how one can change this.

This is more or less in support of #29

Unicode output does not roundtrip

When I put the unicode character "∀" into cat, the output doesn't roundtrip:

Input:
∀
226 136 128 
Output:
��
195 162 194 136 194 128 

Code:

use rexpect::spawn;
use rexpect::error::*;

fn display(s: &str)
{
	println!("{}", s);
	for b in s.as_bytes()
	{
		print!("{} ", b);
	}
	println!("");
}
fn repl() -> Result<(), Error>
{
	let mut p = spawn("cat", Some(1000))?;

	let ex: String = "∀".to_string();
	p.send_line(&ex)?;
	let line = p.read_line()?;

	println!("Input:");
	display(&ex);
	println!("Output:");
	display(&line);
	Ok(())
}
fn main()
{
	repl().unwrap_or_else(|e| panic!("ftp job failed with {}", e));
}

Need help on converting a bash script into rexpect

Hi @philippkeller

  • And this is the command and logs from realm join command
#realm join -v --computer-ou="ou=servers,dc=test,dc=com" test.com -U admin_ad
 * Resolving: _ldap._tcp.test.com
 * Performing LDAP DSE lookup on: 100.76.1.18
 * Performing LDAP DSE lookup on: 100.76.1.19
 * Performing LDAP DSE lookup on: 100.64.0.65
 * Successfully discovered: test.com
Password for admin_ad: admin_ad_password
  • This is one-liner bash script I used to join a centos 7 to MS AD domain.
realm join -v --computer-ou="ou=ma,ou=servers,dc=test,dc=com" test.com -U admin_ad << MYPASSWD
admin_ad_password
MYPASSWD
  • And this is using rexpect 0.3
//Run this code with cargo
// Join test.com AD domain on CentOS 7 with SSSD enabled.
//  Following is the response from realm command
//!  realm join -v --computer-ou="ou=unit1,ou=servers,dc=test,dc=com" test.com -U admin_ad
//!  * Resolving: _ldap._tcp.test.com
//!  * Performing LDAP DSE lookup on: 100.76.1.18
//!  * Performing LDAP DSE lookup on: 100.76.1.19
//!  * Performing LDAP DSE lookup on: 100.58.0.65
//!  * Successfully discovered: test.com
//! Password for admin_ad:

extern crate rexpect;

use rexpect::spawn;
use rexpect::errors::*;

fn  join() -> Result<()> {
    let mut p = spawn("realm join -v --computer-ou=\"ou=ma,ou=servers,dc=test,dc=com\" test.com -U admin_ad", Some(30_000))?;
    p.exp_regex("^Password for .*: ")?;
    p.send_line("admin_ad_password")?;
    p.exp_eof()?;
    Ok(())
}


fn main() {
    join().unwrap_or_else(|e| panic!("Failed to joing test.com AD domain {}", e));
}
  • The error
    Is there a way to skip first 5 lines from realm command output ?
>target/debug/joinad
thread 'main ' panicked at 'Failed to joing test.com AD domain EOF (End of File): Expected Regex: "^Password for .*: " but got EOF after reading " * Resolving: _ldap._tcp.test.com
  • I inserted "p.wait_for_prompt()?;" before " p.exp_regex" but I got compilation error saying no wait_for_promp method for ptysession ...

Allow specifying terminal size

Hi, this is a follow-up for #17. Basically I would like to be able to set the terminal size for the spawned process.

My use case is as follows: I'm using rexpect to create integration tests for my full-screen TUI app (like vim), where I launch the program, send some keystrokes to it, and check that the printed characters are as expected. The layout of my app will depend on the terminal size, and for example some elements are not drawn at all if the size is zero. Currently I can't test my app properly without setting the terminal size.

Currently, my program actually crashes with a zero-size terminal, which I should probably handle, but I am still unable to test the screen contents.

(As another sidenote, this issue didn't come up before because crossterm (the library I'm using for the TUI) used to check if the size from /dev/tty (set by rexpect) is zero, and if it was, it used tput to query the terminal size instead. However, after an update, this check was removed and it returns a zero-size terminal now, which breaks my tests.)

Capturing stderr

Hi, I'm trying to write integration tests for an interactive CLI application (full-screen, like vim). Basically in my test, I want to run the main app binary, send some keystrokes to it, and then check the stdout and stderr. rexpect seems like a good fit, and it works for stdout, but I can't seem to find a way to read the stderr. Is there a way to read it?

Update on crates.io

There were quite a few changes since version v0.4.0, it would be a good idea to push a new version out to crates.io.

Are there any guidelines for rust-cli organization on how it's best to do this, for example changelog format, steps, etc?

Sporadically failing CI testcases

We have some sporadically failing testcases, which blocks CI.
Has been discussed in #101 among other PRs. But I'm opening an issue to keep the discussion in one place.

I'm able to reliably reproduce the failure on my machine like so:

I=1; while cargo nextest run test_read_line; do I=$(($I+1)); echo "PASS $I"; done; echo "FAIL $I"
    Starting 1 tests across 1 binaries (19 skipped)
        FAIL [   0.207s] rexpect session::tests::test_read_line

--- STDOUT:              rexpect session::tests::test_read_line ---

running 1 test
test session::tests::test_read_line ... FAILED

failures:

failures:
    session::tests::test_read_line

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 19 filtered out; finished in 0.21s


--- STDERR:              rexpect session::tests::test_read_line ---
thread 'session::tests::test_read_line' panicked at 'assertion failed: `(left == right)`
  left: `"hans"`,
 right: `"hanshans"`', src/session.rs:437:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

   Canceling due to test failure: 0 tests still running
------------
     Summary [   0.207s] 1 tests run: 0 passed, 1 failed, 19 skipped
        FAIL [   0.207s] rexpect session::tests::test_read_line
error: test run failed
FAIL 270

It failed after 270 runs of the test. I'm running Ubuntu 20.

Help with maintainance?

@philippkeller It seems like this project is not being actively maintained anymore. Would you like help with maintenance or would you prefer that this was forked an maintained by someone else?

rexpect::spawn with empty program parameter

    #[test]
    fn test_empty_spawn() {
        let p = spawn("", Some(1000));
        assert!(p.is_ok());
    }

Currently such spawn will produce a correct PtySession but any work with it it's obviously not a good idea.
I wonder if the spawn function have to check the input if it's empty and return the error in such case.
If it's I may provide a PR :)

I am not sure what is a relatively good step here. So create an issue rather than PR :)

Rare inconsistent result.

While testing gluon with rexpect, there has been one inconsistent test, specicially the hello_world test. It may be a problem of how I used the api or a rare bug with the repl. Rexpect has worked consistently with every other test that's been thrown at it.

There are a few different variations tried in here, including the original without expecting anything after the first sent import line, expecting a regex, and using execute -- gluon-lang/gluon#478.

It would be great to get your eyes on this if you spot anything I'm missing while using rexpect :)

Any kind of community communication?

Should we add some sort of zulip/discord/slack for this package? Adding a channel in an existing forum would be the easiest, anything else feels a bit overkill I think.

execute 'ls -l' to stdout

Excuse me, how can I execute 'ls -l' to output a directory list after logging into the server via ssh? I managed to execute 'ls -l' successfully, but I'm confused when trying to print out the directory structure. Am I missing any related methods?

Performance differences between spawn() and spawn_bash()

Hello, this is perhaps not an issue, but I've been experimenting with the crate and notice the following behavior:

If I get a PtyReplSession with spawn_bash(Some(timeout)), and then use p.execute(command, ready), the time it takes for this to successfully return is directly related to timeout regardless of the time it actually takes command to reach ready. The higher the timeout, the longer it takes (but it returns Ok), and viceversa (though at a certain point, very small timeouts will fail to find ready).

If I get a PtySession with spawn(command, Some(timeout)), and then use p.exp_string(ready), the time it takes for this to successfully return is independent of timeout. I can change timeout as much as I want (as long as I don't make it too small), and the time to successfully return will remain constant. If ready is not found, the timeout works as expected.

I wouldn't expect the execution time of command to change when running in a PtySession vs a PtyReplSession. Could you explain why this happens? Is it a bug or am I missing something?

Example code with PtyReplSession:

let mut bash_session = spawn_bash(Some(10000))
.expect("session failed");

bash_session.execute("hostname", "mypc")
.expect("command failed");

Example code with PtySession:

let mut session = spawn("hostname", Some(10000))
.expect("session failed");

session.exp_string("mypc")
.expect("command failed");

Here are some test results:

Test: PtyReplSession with 2,000ms timeout:

running 1 test
test pruebas_rexpect::with_pty_repl_session_timeout_2000 ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 2.42s

Test: PtyReplSession with 10,000ms timeout:

running 1 test
test pruebas_rexpect::with_pty_repl_session_timeout_10000 ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 10.45s

Test: PtySession with 2,000ms timeout:

running 1 test
test pruebas_rexpect::with_pty_session_timeout_2000 ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.19s

Test: PtySession with 10,000ms timeout:

running 1 test
test pruebas_rexpect::with_pty_session_timeout_10000 ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.16s

Windows Support

I am interested in adding Windows support for this crate. Would you be willing to accept a PR if I can get this working?

Specifically, I want to look into adding Windows support via PseudoTerminal. Doing so will likely require some additions to this crate, including depending on winapi and some other platform-specific code for Windows builds.

I don't intend on changing the API, as I like the simplicity, and would try not to change the internals much. That said, I haven't looked closely at this codebase yet so I don't really know what will be required.

If this is something you see as possible, I can start working on it. It could take me a couple weeks (or more) to get something working.

Timeout behavior is not the same as pexpect

pexpect will eventually raise a timeout:

If nothing matches an expected pattern then expect() will eventually raise a TIMEOUT exception. The default time is 30 seconds, but you can change this by passing a timeout argument to expect():

It looks like rexpect does not timeout but hangs forever.

A new release?

I'd like to use the functionality from #103, but it seems that it's not released on crates.io yet. I would appreciate a new release, are there plans for it to happen? Thanks!

(I'll just use the Git version for now.)

Testing rexpect app

It would be nice if we could provide an easy way to test rexpect apps. Maybe something like this?

fn main() -> Result<(), Error> {
    let mut p = rexpect::spawn("cat", Some(300))?;

    use_cat(&mut p)?;
    Ok(())
}

fn use_cat(p: &mut PtySession) -> Result<(), Error> {
    p.send_line("I'm a cat")?;
    p.exp_string("I'm a cat\r\n")?;
    Ok(())
}

mod test {
    use super::*;

    #[test]
    fn option1() -> Result<(), Error> {
        use_cat(
            rexpect::testing::FakePtySession()
                .recv("I'm a cat")
                .send("I'm a cat"),
        )?;
        Ok(())
    }

    fn option2() -> Result<(), Error> {
        let mut p = rexpect::testing::FakePtySession();
        std::thread::spawn(|| use_cat(p));
        p.recv("I'm a cat");
        p.send("I'm a cat");
        Ok(())
    }
}

Or any suggestions for a better interface? I think option2 looks nicer in the test case, but I think option1 is overall better, since it doesn't require spinning up a new thread, and needing to sync between the two.
I'm not sure how we could get nice error messages with either approach, but I'm working on option1 at the moment and will see how it turns out.

I haven't seen any crates providing special testing-utilities, is it normally not done? Should we have it behind a feature-flag?

Implementation wise, it looks like we would have to store Box<impl PtyProcess> in PtySession and Box<impl Write> in StreamSession. So that we can keep PtySession without template arguments. This would break the API, but I don't think it should be a problem?

replwrap style run function

It would also be nice to borrow from replwrap and have a method to fold these three lines into one:

    p.send_line("hostname")?;
    let hostname = p.read_line()?;
    p.wait_for_prompt()?; // go sure `hostname` is really done

becomes something like

    let output = p.run("hostname")?;

other things that would help missing from pexpect that I've had to add for run(): take multiple commands to pass a script that you read from the host filesystem either as a vec or by splitting on newlines, sanitizing carriage returns, stripping out colour

Mechanism to access buffer after an expectation

A common pattern I've done in pexpect is something like the following:

proc = pexpect.spawnu("foo")
proc.setecho(False)
proc.sendline("some input")
proc.expect("> ")
print(proc.before)

The proc.before part allows me to access the result of the input. Is there currently an equivalent in rexpect?

Moving repository to CLI-WG org?

Hi!

In the last meetup of the CLI WG it came up that we want to make this crate to the CLI WG org.

The benefits that we would get from that would be the increased bus factor. I know we have three or four people that currently maintain this crate, and we wouldn't even increase that number any further when moving to the CLI WG org, but we would get the option of the WG having access to the repository settings and if it happens that we (the current maintainers) are all unresponsive, the WG can install new maintainers.

Please lets have a discussion about that.

@petreeftime suggested that after the maintainership thing got cleared up, we can talk about moving to a more permanent place (#43 (comment)) ... and that's what I'm trying here now! 😆
@souze is also a maintainer IIRC and of course
@philippkeller has the final say as the owner of the repository!

Copying child process output

pexpect has child.logfile* APIs to log child process output to a file-like destination.
I looked around the docs but I didn't seem to find anything similar for rexpect.

Is there any chance this could be supported?

Question: How pty behaives with empty command.

I was tinkering pty/tty stuff and still not clearly understand how it works :). And you're @philippkeller the most right person who I could address this question. Example below.

Currently this test will pass.
But why?

Why we get this echoed strings?

I've tested the flags.local_flags &= !termios::LocalFlags::ECHO works fine.

Thanks in advance.

    #[test]
    /// Open cat, write string, read back string twice, send Ctrl^C and check that cat exited
    fn test_no_cmd() {
        // wrapping into closure so I can use ?
        || -> std::io::Result<()> {
            let process = PtyProcess::new(Command::new("")).expect("could not execute cat");
            let f = process.get_file_handle();
            let mut writer = LineWriter::new(&f);
            let mut reader = BufReader::new(&f);
            writer.write_all(b"hello cat\n")?;
            let mut buf = String::new();
            reader.read_line(&mut buf)?;
            assert_eq!(buf, "hello cat\r\n");

            Ok(())
        }()
        .unwrap_or_else(|e| panic!("test_cat failed: {}", e));
    }

PtySession::expect_eof never finishes with current nightly build

I've traced down the source of a faulty execution in a application that I contribute to the PtySession::expect_eof never finishing execution on Rut's currently nightly build.

I have a little example that can reproduce the problem:

// On Cargo.toml
// [dependencies]
// rexpect = "0.4"

fn main() {
    let mut p = rexpect::spawn("echo 'working as expected'", Some(10000)).unwrap();
    println!("{}", p.exp_eof().unwrap());
}

When I run this on nightly the timeout is reached, and if no timeout is set the execution just hangs indefinitely. On stable it just works as expected.

Here's my rust and cargo version for the nightly build:

$ rustc --version --verbose
rustc 1.56.0-nightly (30a0a9b69 2021-08-17)
binary: rustc
commit-hash: 30a0a9b694cde95cbab863f7ef4d554f0f46b606
commit-date: 2021-08-17
host: x86_64-unknown-linux-gnu
release: 1.56.0-nightly
LLVM version: 12.0.1

$ cargo --version --verbose
cargo 1.56.0-nightly (b51439fd8 2021-08-09)
release: 1.56.0
commit-hash: b51439fd8b505d4800a257acfecf3c69f81e35cf
commit-date: 2021-08-09

Would appreciate if you guys could make it compatible with nightly again as it is what I use during development. In the mean time I'll be pining down my nightly to the last working release.

License

Currently, a LICENSE file is not in the repository. It would be great to add one to match the MIT license in rexpect's Cargo.toml, as well as reference at the bottom of the readme.

test_read_line fails randomly

I was unable to reproduce the issue on my own. So far the only time it showed up is in https://github.com/philippkeller/rexpect/actions/runs/3060626462/jobs/4939368842, for PR #47.

I've reviewed the code involved in this test, but there was nothing obvious that could lead to such an issue. What I expected was that there's some sort of race condition where Session::read_line starts reading before the \n is available, and so it ends up reading the string once, stopping because it can't match and then reading again, but NBReader looks like it would correctly accumulate characters into the buffer and the whole operation is retried until the match is found in the buffer.

---- session::tests::test_read_line stdout ----
thread 'session::tests::test_read_line' panicked at 'assertion failed: `(left == right)`
  left: `"hans"`,
 right: `"hanshans"`', src/session.rs:438:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.