conradkleinespel / rpassword

Cross platform Rust library to read a password in the terminal (Linux, BSD, OSX, Windows, WASM).
Apache License 2.0
244 stars 38 forks source link

Move unit tests to Github actions #54

Closed conradkleinespel closed 3 years ago

conradkleinespel commented 3 years ago

This will allow doing things like:

pub struct ReaderManager<'a, R: BufRead> {
    inner: &'a mut Box<R>,
}

impl<'a, R: BufRead> ReaderManager<'a, R> {
    pub fn new(inner: &'a mut Box<R>) -> ReaderManager<'a, R> {
        ReaderManager { inner }
    }

    pub fn read_line(&mut self) -> IoResult<String> {
        let mut s = String::new();
        self.inner.read_line(&mut s)?;
        Ok(s)
    }

    pub fn read_password(&mut self) -> IoResult<String> {
        hide_tty_input_during_callback(libc::STDIN_FILENO, || -> IoResult<String> {
            read_password_with_reader(Some(self.inner))
        })
    }
}

This means you can use any BufRead you want, including an existing StdinLock and still hide input if you need. Super useful if you want to swap out your input reader with a Cursor in unit tests.

conradkleinespel commented 3 years ago

@dvermd I was playing around with your mock improvements recently, trying to unit test rooster with Rust instead of shell scripts

I ran into this issue where I have an existing StdinLock and so I can't use read_password_with_reader(None). It uses read_password_from_stdin which tries to stdin.lock() also. Only one lock at a time is possible.

The above solution works well for my use case: I can use the exact same code in tests and in the final binary.

How have you been using read_password_with_reader? Any code I can look at for inspiration?

dvermd commented 3 years ago

How have you been using read_password_with_reader? Any code I can look at for inspiration?

The only branch I managed to find that is still available somewhere is https://git.duniter.org/nodes/rust/duniter-rs/-/merge_requests/275 It doesn't use read_password_with_reader anymore. This project used "plugin" and there might be a GUI someday thus a higher order trait was created to abstract all user interaction. It's this trait that got Mocked for testing not the BufRead itself.

conradkleinespel commented 3 years ago

Thanks @dvermd ! That's helpful. It seems that read_password_with_reader is a bit difficult to use in practice. Because my way is similar to what you're linking: I'm mocking a struct that calls IO functions, not the IO functions themselves. Maybe that's the easiest way after all.