Skip to content
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

Workflows #20

Merged
merged 31 commits into from
Feb 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
470e1ff
Add test workflow.
tmpfs Feb 24, 2024
b610d64
Update macos runner.
tmpfs Feb 24, 2024
140e0f9
Enable echo for tests.
tmpfs Feb 24, 2024
f38700c
Remove exit from fixtures.
tmpfs Feb 24, 2024
d1e0775
Disable fail-fast for now.
tmpfs Feb 24, 2024
471b9cc
Tidy error module, update workflow env.
tmpfs Feb 24, 2024
bba441f
Check sh version.
tmpfs Feb 24, 2024
a593138
Use explicit bash for default command.
tmpfs Feb 24, 2024
fe8f58f
Update workflow.
tmpfs Feb 24, 2024
bc3012d
Fix const.
tmpfs Feb 24, 2024
e41b5ed
Clippy fixes, debug windows failure.
tmpfs Feb 24, 2024
04fc1b0
Debug powershell command.
tmpfs Feb 24, 2024
d8e5dd1
Check python in workflow.
tmpfs Feb 24, 2024
17061a1
Fix carriage return in test.
tmpfs Feb 24, 2024
50629de
Try to pause in expect_str().
tmpfs Feb 24, 2024
f47ea17
Pause after spawning powershell.
tmpfs Feb 24, 2024
515f303
Update test.
tmpfs Feb 24, 2024
795cc7e
Debug windows CI failures.
tmpfs Feb 24, 2024
e8fa975
Include Duration in error variant.
tmpfs Feb 24, 2024
530a291
Ignore failing windows tests for now.
tmpfs Feb 24, 2024
78a2937
Try with pwsh.
tmpfs Feb 24, 2024
c72b03b
Debug failing windows tests.
tmpfs Feb 24, 2024
011cb01
Revert to pwsh, disable tests.
tmpfs Feb 24, 2024
c1023a3
Do not filter test runner.
tmpfs Feb 24, 2024
908c579
Tweak workflow.
tmpfs Feb 24, 2024
e89b27c
Merge branch 'main' into workflows
tmpfs Feb 24, 2024
88940ff
Try conpty test spec.
tmpfs Feb 24, 2024
c161ed6
Try set_echo true.
tmpfs Feb 24, 2024
88ed98e
Debug conpty test.
tmpfs Feb 24, 2024
f7d7940
Try explicit set_echo() false.
tmpfs Feb 24, 2024
58f94f4
Disable windows in matrix for now.
tmpfs Feb 24, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Tests

on:
#workflow_call:
pull_request:

env:
RUST_BACKTRACE: full
ANTICIPATE_ECHO: true

jobs:
check:
name: Run test
runs-on: ${{ matrix.os }}
strategy:
fail-fast: true
matrix:
include:
- os: ubuntu-latest
#- os: windows-latest
- os: macos-latest
steps:
- uses: actions/checkout@v4
- name: ⚡ Cache
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}

- name: Run tests
run: |
cargo test --all -- --nocapture
18 changes: 3 additions & 15 deletions core/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
use std::error;
use std::fmt;
use std::fmt::Display;
use std::io;

use thiserror::Error;
use std::time::Duration;

/// Error type for the library.
#[derive(Debug, Error)]
Expand All @@ -15,8 +11,8 @@ pub enum Error {
#[error("failed to parse regex")]
RegexParsing,
/// An timeout was reached while waiting in expect call.
#[error("reached the timeout for an expectation")]
ExpectTimeout,
#[error("reached the timeout for an expectation ({0:?})")]
ExpectTimeout(Duration),
/// Unhandled EOF error.
#[error("unhandled EOF")]
Eof,
Expand All @@ -28,11 +24,3 @@ pub enum Error {
#[error(transparent)]
Conpty(#[from] conpty::error::Error),
}

pub(crate) fn to_io_error<E: Display>(
message: &'static str,
) -> impl FnOnce(E) -> io::Error {
move |e: E| {
io::Error::new(io::ErrorKind::Other, format!("{}; {}", message, e))
}
}
4 changes: 2 additions & 2 deletions core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![warn(missing_docs)]
#![forbid(unsafe_code)]
//! Control a pseudo-terminal similar to `expect(1)`,
//! fork of [expectrl](https://docs.rs/expectrl) with
//! Control a pseudo-terminal similar to `expect(1)`,
//! fork of [expectrl](https://docs.rs/expectrl) with
//! minimal dependencies and features.

mod captures;
Expand Down
14 changes: 3 additions & 11 deletions core/src/process/unix.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//! This module contains a Unix implementation of [crate::process::Process].

use super::{Healthcheck, NonBlocking, Process};
use crate::error::to_io_error;
use ptyprocess::{stream::Stream, PtyProcess};

use std::{
Expand Down Expand Up @@ -37,27 +36,20 @@ impl Process for UnixProcess {
}

fn spawn_command(command: Self::Command) -> Result<Self> {
let proc = PtyProcess::spawn(command)
.map_err(to_io_error("Failed to spawn a command"))?;

let proc = PtyProcess::spawn(command)?;
Ok(Self { proc })
}

fn open_stream(&mut self) -> Result<Self::Stream> {
let stream = self
.proc
.get_pty_stream()
.map_err(to_io_error("Failed to create a stream"))?;
let stream = self.proc.get_pty_stream()?;
let stream = PtyStream::new(stream);
Ok(stream)
}
}

impl Healthcheck for UnixProcess {
fn is_alive(&mut self) -> Result<bool> {
self.proc
.is_alive()
.map_err(to_io_error("Failed to call pty.is_alive()"))
Ok(self.proc.is_alive()?)
}
}

Expand Down
9 changes: 5 additions & 4 deletions core/src/process/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,14 @@ impl ProcessTrait for WinProcess {
type Stream = ProcessStream;

fn spawn<S: AsRef<str>>(cmd: S) -> Result<Self> {
Ok(spawn(cmd.as_ref())
.map(|proc| WinProcess { proc })?)
Ok(spawn(cmd.as_ref()).map(|proc| WinProcess { proc })?)
}

fn spawn_command(command: Self::Command) -> Result<Self> {
Ok(conpty::Process::spawn(command)
.map(|proc| WinProcess { proc })?)
Ok(
conpty::Process::spawn(command)
.map(|proc| WinProcess { proc })?,
)
}

fn open_stream(&mut self) -> Result<Self::Stream> {
Expand Down
2 changes: 1 addition & 1 deletion core/src/repl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use crate::{
error::Error,
log::{NoopLogWriter, LogWriter},
log::{LogWriter, NoopLogWriter},
spawn, Captures, Expect, Needle, Session,
};
use std::ops::{Deref, DerefMut};
Expand Down
16 changes: 2 additions & 14 deletions core/src/session/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ impl<O: LogWriter, P, S: Read + NonBlocking> Session<O, P, S> {

if let Some(timeout) = self.expect_timeout {
if start.elapsed() > timeout {
return Err(Error::ExpectTimeout);
return Err(Error::ExpectTimeout(timeout));
}
}
}
Expand Down Expand Up @@ -230,7 +230,7 @@ impl<O: LogWriter, P, S: Read + NonBlocking> Session<O, P, S> {

if let Some(timeout) = self.expect_timeout {
if start.elapsed() > timeout {
return Err(Error::ExpectTimeout);
return Err(Error::ExpectTimeout(timeout));
}
}
}
Expand Down Expand Up @@ -440,10 +440,6 @@ struct TryStream<S> {
}

impl<S> TryStream<S> {
fn into_inner(self) -> S {
self.stream.inner.into_inner().inner
}

fn as_ref(&self) -> &S {
&self.stream.inner.get_ref().inner
}
Expand All @@ -460,17 +456,9 @@ impl<S: Read> TryStream<S> {
stream: ControlledReader::new(stream),
})
}

fn flush_in_buffer(&mut self) {
self.stream.flush_in_buffer();
}
}

impl<S> TryStream<S> {
fn keep_in_buffer(&mut self, v: &[u8]) {
self.stream.keep_in_buffer(v);
}

fn get_available(&mut self) -> &[u8] {
self.stream.get_available()
}
Expand Down
9 changes: 9 additions & 0 deletions core/tests/conpty.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#[test]
#[cfg(windows)]
fn conpty_echo() {
let mut proc = conpty::spawn("echo Hello World").unwrap();
let mut reader = proc.output().unwrap();
let mut buf = [0; 1024];
reader.read(&mut buf).unwrap();
assert!(String::from_utf8_lossy(&buf).contains("Hello World"));
}
13 changes: 7 additions & 6 deletions core/tests/expect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ fn expect_str() {
#[test]
fn expect_str() {
let mut session =
spawn(r#"powershell -c "python ./tests/actions/cat/main.py""#).unwrap();
session.send_line("Hello World\n\r").unwrap();
spawn(r#"pwsh -c "python ./tests/actions/cat/main.py""#)
.unwrap();
session.send_line("Hello World").unwrap();
session.expect("Hello World").unwrap();
}

Expand Down Expand Up @@ -45,10 +46,10 @@ fn expect_regex_lazy() {
#[test]
fn expect_regex() {
let mut session =
spawn("python ./tests/actions/echo/main.py Hello World").unwrap();
spawn("echo 'Hello World'").unwrap();
let m = session.expect(Regex("lo.*")).unwrap();
assert_eq!(m.matches().count(), 1);
assert_eq!(m.get(0).unwrap(), b"lo World\r");
assert_eq!(m.get(0).unwrap(), b"lo World'\r");
}

#[cfg(unix)]
Expand Down Expand Up @@ -134,7 +135,7 @@ fn expect_eof_timeout() {
let mut p = spawn("sleep 3").expect("cannot run sleep 3");
p.set_expect_timeout(Some(Duration::from_millis(100)));
match p.expect(Eof) {
Err(anticipate::Error::ExpectTimeout) => {}
Err(anticipate::Error::ExpectTimeout(_)) => {}
r => panic!("reached a timeout {r:?}"),
}
}
Expand All @@ -145,7 +146,7 @@ fn expect_eof_timeout() {
let mut p = spawn("sleep 3").expect("cannot run sleep 3");
p.set_expect_timeout(Some(Duration::from_millis(100)));
match p.expect(Eof) {
Err(anticipate::Error::ExpectTimeout) => {}
Err(anticipate::Error::ExpectTimeout(_)) => {}
r => panic!("should raise TimeOut {:?}", r),
}
}
8 changes: 4 additions & 4 deletions core/tests/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ fn send_controll() {
#[cfg(windows)]
fn send_controll() {
let mut proc =
DefaultSession::spawn(Command::new("powershell -C ping localhost"))
DefaultSession::spawn(Command::new("pwsh -C ping localhost"))
.unwrap();

// give powershell a bit time
Expand Down Expand Up @@ -129,7 +129,7 @@ fn try_read_by_byte() {
// it shows that on windows ECHO is turned on.
// Mustn't it be turned down?

let mut proc = DefaultSession::spawn(Command::new("powershell")).unwrap();
let mut proc = DefaultSession::spawn(Command::new("pwsh")).unwrap();
_p_send_line(
&mut proc,
"while (1) { read-host | set r; if (!$r) { break }}",
Expand Down Expand Up @@ -188,7 +188,7 @@ fn blocking_read_after_non_blocking() {
#[test]
#[cfg(windows)]
fn blocking_read_after_non_blocking() {
let mut proc = DefaultSession::spawn(Command::new("powershell")).unwrap();
let mut proc = DefaultSession::spawn(Command::new("pwsh")).unwrap();
_p_send_line(
&mut proc,
"while (1) { read-host | set r; if (!$r) { break }}",
Expand Down Expand Up @@ -241,7 +241,7 @@ fn try_read() {
#[test]
#[cfg(windows)]
fn try_read() {
let mut proc = DefaultSession::spawn(Command::new("powershell")).unwrap();
let mut proc = DefaultSession::spawn(Command::new("pwsh")).unwrap();
thread::sleep(Duration::from_millis(300));
_p_send_line(
&mut proc,
Expand Down
26 changes: 13 additions & 13 deletions runner/src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{
resolve_path, Error, Instruction, Instructions, Result, ScriptParser,
};
use anticipate::{
log::{NoopLogWriter, LogWriter, PrefixLogWriter, StandardLogWriter},
log::{LogWriter, NoopLogWriter, PrefixLogWriter, StandardLogWriter},
repl::ReplSession,
spawn_with_options, ControlCode, Expect, Regex, Session,
};
Expand All @@ -20,7 +20,12 @@ use tracing::{span, Level};
use unicode_segmentation::UnicodeSegmentation;

const PROMPT: &str = "➜ ";
#[cfg(unix)]
const COMMAND: &str = "bash -noprofile -norc";
#[cfg(windows)]
const COMMAND: &str = "pwsh -NoProfile -NonInteractive -NoLogo";

/// Source for probability distribution.
struct Source<T>(T);

impl<T: rand::RngCore> source::Source for Source<T> {
Expand Down Expand Up @@ -52,10 +57,7 @@ impl Default for CinemaOptions {
delay: 75,
type_pragma: false,
deviation: 15.0,
#[cfg(unix)]
shell: "sh -noprofile -norc".to_string(),
#[cfg(windows)]
shell: "powershell".to_string(),
shell: COMMAND.to_string(),
cols: 80,
rows: 24,
}
Expand Down Expand Up @@ -85,15 +87,12 @@ pub struct InterpreterOptions {
impl Default for InterpreterOptions {
fn default() -> Self {
Self {
#[cfg(unix)]
command: "sh -noprofile -norc".to_owned(),
#[cfg(windows)]
command: "powershell".to_string(),
command: COMMAND.to_owned(),
prompt: None,
timeout: Some(5000),
timeout: Some(10000),
cinema: None,
id: None,
echo: false,
echo: std::env::var("ANTICIPATE_ECHO").ok().is_some(),
format: false,
print_comments: false,
}
Expand All @@ -109,7 +108,7 @@ impl InterpreterOptions {
print_comments: bool,
) -> Self {
Self {
command: "sh -noprofile -norc".to_owned(),
command: COMMAND.to_owned(),
prompt: None,
timeout: Some(timeout),
cinema: None,
Expand Down Expand Up @@ -291,7 +290,8 @@ impl ScriptFile {
spawn_with_options(cmd, None, timeout)?;
start(pty, prompt, options, pragma, instructions)?;
} else if options.echo && !options.format {
let pty = spawn_with_options(cmd, Some(StandardLogWriter), timeout)?;
let pty =
spawn_with_options(cmd, Some(StandardLogWriter), timeout)?;
start(pty, prompt, options, pragma, instructions)?;
} else if options.echo && options.format {
let pty =
Expand Down
1 change: 0 additions & 1 deletion tests/fixtures/echo.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
echo "hello world"
#$ expect hello world
exit
1 change: 0 additions & 1 deletion tests/fixtures/escaped-newline.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
echo \
"hello world"
#$ expect hello world
exit