use crate::{
artifact::hash_file,
tool::{AdmittedTool, ExecutionContext, OutputLimits, ToolSpec},
};
use std::{
ffi::OsString,
fs,
path::{Path, PathBuf},
sync::{
Mutex, MutexGuard,
atomic::{AtomicU64, Ordering},
},
time::Duration,
};
static PROCESS_FIXTURES: Mutex<()> = Mutex::new(());
static SEQUENCE: AtomicU64 = AtomicU64::new(0);
pub const LIMITS: OutputLimits = OutputLimits {
stdout_bytes: 256 * 1024,
stderr_bytes: 256 * 1024,
timeout: Duration::from_secs(5),
};
pub const VERSION: &str = "test-host-tool version 1";
pub struct Fixture {
pub root: PathBuf,
_guard: MutexGuard<'static, ()>,
}
impl Fixture {
pub fn new() -> Self {
let guard = PROCESS_FIXTURES
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
let root = std::env::temp_dir().join(format!(
"ic-host-tools-test-{}-{}",
std::process::id(),
SEQUENCE.fetch_add(1, Ordering::Relaxed)
));
fs::create_dir(&root).unwrap();
Self {
root: root.canonicalize().unwrap(),
_guard: guard,
}
}
pub fn context<'a>(&'a self, environment: &'a [(OsString, OsString)]) -> ExecutionContext<'a> {
ExecutionContext {
current_dir: &self.root,
environment,
}
}
pub fn tool(&self) -> AdmittedTool {
admit(&tool_path(), &self.context(&[]), VERSION).unwrap()
}
pub fn source(&self) -> PathBuf {
let source = self.root.join("source.wasm");
fs::write(&source, b"\0asm\x01\0\0\0").unwrap();
source
}
}
impl Drop for Fixture {
fn drop(&mut self) {
let _ = fs::remove_dir_all(&self.root);
}
}
pub fn tool_path() -> PathBuf {
Path::new(concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/fixtures/tool.sh"
))
.canonicalize()
.unwrap()
}
pub fn admit(
path: &Path,
context: &ExecutionContext<'_>,
version: &str,
) -> Result<AdmittedTool, crate::tool::ToolError> {
let identity = hash_file(path, 1024 * 1024).unwrap();
AdmittedTool::admit(
&ToolSpec {
executable: path,
sha256: identity.sha256,
executable_bytes: 1024 * 1024,
version_arguments: &[OsString::from("--version")],
version_identity: version,
},
context,
LIMITS,
)
}