use std::cell::RefCell;
use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicUsize, Ordering};
static COMPILETEST_INTEGRATION_TEST_DIR: &str = "cit";
thread_local! {
static TEST_ID: RefCell<Option<usize>> = RefCell::new(None);
}
lazy_static::lazy_static! {
pub static ref GLOBAL_ROOT: PathBuf = {
let mut path = env::current_exe().unwrap();
path.pop(); path.pop(); path.pop();
path.push(COMPILETEST_INTEGRATION_TEST_DIR);
path.mkdir_p();
path
};
}
pub fn testsuite(mode: &str) -> TestsuiteBuilder {
let builder = TestsuiteBuilder::new(mode);
builder.build();
builder
}
pub struct TestsuiteBuilder {
pub root: PathBuf,
}
impl TestsuiteBuilder {
pub fn new(mode: &str) -> Self {
static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
TEST_ID.with(|n| *n.borrow_mut() = Some(id));
let root = GLOBAL_ROOT
.join(format!("id{}", TEST_ID.with(|n| n.borrow().unwrap())))
.join(mode);
root.mkdir_p();
Self { root }
}
pub fn mk_file(&self, path: &str, body: &str) {
self.root.mkdir_p();
fs::write(self.root.join(&path), &body)
.unwrap_or_else(|e| panic!("could not create file {}: {}", path, e));
}
pub fn file_contents(&self, name: &str) -> String {
fs::read_to_string(self.root.join(name)).expect("Unable to read file")
}
fn build(&self) {
self.rm_root();
self.root.mkdir_p();
}
fn rm_root(&self) {
self.root.rm_rf();
}
}
pub trait PathExt {
fn rm_rf(&self);
fn mkdir_p(&self);
}
impl PathExt for Path {
fn rm_rf(&self) {
if self.is_dir() {
if let Err(e) = fs::remove_dir_all(self) {
panic!("failed to remove {:?}: {:?}", self, e)
}
} else {
if let Err(e) = fs::remove_file(self) {
panic!("failed to remove {:?}: {:?}", self, e)
}
}
}
fn mkdir_p(&self) {
fs::create_dir_all(self)
.unwrap_or_else(|e| panic!("failed to mkdir_p {}: {}", self.display(), e))
}
}