feat: add rust-script
This commit is contained in:
121
external/rust-script/tests/util/mod.rs
vendored
Normal file
121
external/rust-script/tests/util/mod.rs
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
use std::sync::Mutex;
|
||||
|
||||
macro_rules! rust_script {
|
||||
(
|
||||
#[env($($env_k:ident=$env_v:expr),* $(,)*)]
|
||||
$($args:expr),* $(,)*
|
||||
) => {
|
||||
{
|
||||
extern crate tempfile;
|
||||
use std::process::Command;
|
||||
|
||||
let cargo_lock = crate::util::CARGO_MUTEX.lock().expect("Could not acquire Cargo mutex");
|
||||
|
||||
let cmd_str;
|
||||
let out = {
|
||||
let target_dir = ::std::env::var("CARGO_TARGET_DIR")
|
||||
.unwrap_or_else(|_| String::from("target"));
|
||||
let mut cmd = Command::new(format!("{}/debug/rust-script", target_dir));
|
||||
$(
|
||||
cmd.arg($args);
|
||||
)*
|
||||
|
||||
cmd.env_remove("CARGO_TARGET_DIR");
|
||||
$(cmd.env(stringify!($env_k), $env_v);)*
|
||||
|
||||
cmd_str = format!("{:?}", cmd);
|
||||
|
||||
cmd.output()
|
||||
.map(crate::util::Output::from)
|
||||
};
|
||||
|
||||
if let Ok(out) = out.as_ref() {
|
||||
println!("rust-script cmd: {}", cmd_str);
|
||||
println!("rust-script stdout:");
|
||||
println!("-----");
|
||||
println!("{}", out.stdout);
|
||||
println!("-----");
|
||||
println!("rust-script stderr:");
|
||||
println!("-----");
|
||||
println!("{}", out.stderr);
|
||||
println!("-----");
|
||||
}
|
||||
|
||||
drop(cargo_lock);
|
||||
|
||||
out
|
||||
}
|
||||
};
|
||||
|
||||
($($args:expr),* $(,)*) => {
|
||||
rust_script!(#[env()] $($args),*)
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! with_output_marker {
|
||||
(prelude $p:expr; $e:expr) => {
|
||||
format!(concat!($p, "{}", $e), crate::util::OUTPUT_MARKER_CODE)
|
||||
};
|
||||
|
||||
($e:expr) => {
|
||||
format!(concat!("{}", $e), crate::util::OUTPUT_MARKER_CODE)
|
||||
};
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
#[doc(hidden)]
|
||||
pub static ref CARGO_MUTEX: Mutex<()> = Mutex::new(());
|
||||
}
|
||||
|
||||
pub const OUTPUT_MARKER: &str = "--output--";
|
||||
pub const OUTPUT_MARKER_CODE: &str = "println!(\"--output--\");";
|
||||
|
||||
pub struct Output {
|
||||
pub status: ::std::process::ExitStatus,
|
||||
pub stdout: String,
|
||||
pub stderr: String,
|
||||
}
|
||||
|
||||
impl Output {
|
||||
pub fn stdout_output(&self) -> &str {
|
||||
assert!(self.success());
|
||||
for marker in self.stdout.matches(OUTPUT_MARKER) {
|
||||
let i = subslice_offset(&self.stdout, marker).expect("couldn't find marker in output");
|
||||
let before_cp = self.stdout[..i].chars().rev().next().unwrap_or('\n');
|
||||
if !(before_cp == '\r' || before_cp == '\n') {
|
||||
continue;
|
||||
}
|
||||
let after = &self.stdout[i + OUTPUT_MARKER.len()..];
|
||||
let after_cp = after.chars().next().expect("couldn't find cp after marker");
|
||||
if !(after_cp == '\r' || after_cp == '\n') {
|
||||
continue;
|
||||
}
|
||||
return after;
|
||||
}
|
||||
panic!("could not find `{}` in script output", OUTPUT_MARKER);
|
||||
}
|
||||
|
||||
pub fn success(&self) -> bool {
|
||||
self.status.success()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<::std::process::Output> for Output {
|
||||
fn from(v: ::std::process::Output) -> Self {
|
||||
Self {
|
||||
status: v.status,
|
||||
stdout: String::from_utf8(v.stdout).unwrap(),
|
||||
stderr: String::from_utf8(v.stderr).unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn subslice_offset(outer: &str, inner: &str) -> Option<usize> {
|
||||
let outer_beg = outer.as_ptr() as usize;
|
||||
let inner = inner.as_ptr() as usize;
|
||||
if inner < outer_beg || inner > outer_beg.wrapping_add(outer.len()) {
|
||||
None
|
||||
} else {
|
||||
Some(inner.wrapping_sub(outer_beg))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user