-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
195 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
use std::time::Duration; | ||
|
||
use anyhow::Result; | ||
use xshell::{cmd, Shell}; | ||
|
||
fn main() -> Result<()> { | ||
let sh = Shell::new()?; | ||
let command = cmd!(sh, "sleep 5").timeout(Duration::from_secs(3)); | ||
|
||
// Run the command with a timeout | ||
match command.run() { | ||
Ok(_) => println!("Command completed successfully."), | ||
Err(e) => eprintln!("Command failed: {}", e), | ||
} | ||
|
||
// Run the command with a timeout and get stdout | ||
match command.read() { | ||
Ok(output) => println!("Command output: {}", output), | ||
Err(e) => eprintln!("Command failed: {}", e), | ||
} | ||
|
||
// Run the command with a timeout and get stderr | ||
match command.read_stderr() { | ||
Ok(output) => println!("Command stderr: {}", output), | ||
Err(e) => eprintln!("Command failed: {}", e), | ||
} | ||
|
||
// Run the command with a timeout and get the full output | ||
match command.output() { | ||
Ok(output) => println!("Command completed successfully.{output:?}"), | ||
Err(e) => eprintln!("Command failed: {}", e), | ||
} | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
use std::io::{self, Write}; | ||
use std::thread; | ||
use std::time::Duration; | ||
|
||
fn main() { | ||
if let Err(err) = try_main() { | ||
eprintln!("{err}"); | ||
std::process::exit(1); | ||
} | ||
} | ||
|
||
fn try_main() -> io::Result<()> { | ||
let mut sleep_seconds = 0; | ||
let mut fail = false; | ||
let mut suicide = false; | ||
|
||
let mut args = std::env::args().skip(1).peekable(); | ||
while let Some(arg) = args.peek() { | ||
match arg.as_str() { | ||
"-f" => fail = true, | ||
"-s" => suicide = true, | ||
_ => break, | ||
} | ||
args.next(); | ||
} | ||
|
||
if let Some(arg) = args.next() { | ||
sleep_seconds = arg.parse().unwrap_or_else(|_| { | ||
eprintln!("error: invalid number of seconds"); | ||
std::process::exit(1); | ||
}); | ||
} | ||
|
||
thread::sleep(Duration::from_secs(sleep_seconds)); | ||
|
||
if fail { | ||
return Err(io::ErrorKind::Other.into()); | ||
} | ||
if suicide { | ||
#[cfg(unix)] | ||
unsafe { | ||
let pid = signals::getpid(); | ||
if pid > 0 { | ||
signals::kill(pid, 9); | ||
} | ||
} | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
#[cfg(unix)] | ||
mod signals { | ||
use std::os::raw::c_int; | ||
extern "C" { | ||
pub fn kill(pid: c_int, sig: c_int) -> c_int; | ||
pub fn getpid() -> c_int; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
use crate::setup; | ||
use std::time::Duration; | ||
|
||
use xshell::cmd; | ||
|
||
#[test] | ||
fn test_run_timeout_success() { | ||
let sh = setup(); | ||
let command = cmd!(sh, "xsleep 1"); // Command that xsleeps for 1 second | ||
|
||
// Run the command with a timeout of 3 seconds | ||
let result = command.timeout(Duration::from_secs(3)).run(); | ||
assert!(result.is_ok(), "Command should complete successfully within the timeout"); | ||
} | ||
|
||
#[test] | ||
fn test_run_timeout_failure() { | ||
let sh = setup(); | ||
let command = cmd!(sh, "xsleep 5"); // Command that xsleeps for 5 seconds | ||
|
||
// Run the command with a timeout of 3 seconds | ||
let result = command.timeout(Duration::from_secs(3)).run(); | ||
assert!(result.is_err(), "Command should fail due to timeout"); | ||
} | ||
|
||
#[test] | ||
fn test_read_timeout_success() { | ||
let sh = setup(); | ||
let command = cmd!(sh, "xecho Hello, world!"); // Command that prints a message | ||
|
||
// Run the command with a timeout of 3 seconds and read stdout | ||
let result = command.timeout(Duration::from_secs(3)).read(); | ||
assert!(result.is_ok(), "Command should complete successfully within the timeout"); | ||
assert_eq!(result.unwrap(), "Hello, world!"); | ||
} | ||
|
||
#[test] | ||
fn test_read_timeout_failure() { | ||
let sh = setup(); | ||
let command = cmd!(sh, "xsleep 5"); // Command that xsleeps for 5 seconds | ||
|
||
// Run the command with a timeout of 3 seconds and read stdout | ||
let result = command.timeout(Duration::from_secs(3)).read(); | ||
assert!(result.is_err(), "Command should fail due to timeout"); | ||
} | ||
|
||
#[test] | ||
fn test_read_stderr_timeout_success() { | ||
let sh = setup(); | ||
let command = cmd!(sh, "xecho -e Error message"); // Command that prints an error message to stderr | ||
|
||
// Run the command with a timeout of 3 seconds and read stderr | ||
let result = command.timeout(Duration::from_secs(3)).read_stderr(); | ||
assert!(result.is_ok(), "Command should complete successfully within the timeout"); | ||
assert_eq!(result.unwrap(), "Error message"); | ||
} | ||
|
||
#[test] | ||
fn test_read_stderr_timeout_failure() { | ||
let sh = setup(); | ||
let command = cmd!(sh, "xsleep 5"); // Command that xsleeps for 5 seconds | ||
|
||
// Run the command with a timeout of 3 seconds and read stderr | ||
let result = command.timeout(Duration::from_secs(3)).read_stderr(); | ||
assert!(result.is_err(), "Command should fail due to timeout"); | ||
} | ||
|
||
#[test] | ||
fn test_output_timeout_success() { | ||
let sh = setup(); | ||
let command = cmd!(sh, "xecho Hello, world!"); // Command that prints a message | ||
|
||
// Run the command with a timeout of 3 seconds and get the full output | ||
let result = command.timeout(Duration::from_secs(3)).output(); | ||
assert!(result.is_ok(), "Command should complete successfully within the timeout"); | ||
let output = result.unwrap(); | ||
assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "Hello, world!"); | ||
} | ||
|
||
#[test] | ||
fn test_output_timeout_failure() { | ||
let sh = setup(); | ||
let command = cmd!(sh, "xsleep 5"); // Command that xsleeps for 5 seconds | ||
|
||
// Run the command with a timeout of 3 seconds and get the full output | ||
let result = command.timeout(Duration::from_secs(3)).output(); | ||
assert!(result.is_err(), "Command should fail due to timeout"); | ||
} |