1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
|
//! Provides a simple way to set up compiletest sample testsuites used in testing.
//!
//! Inspired by cargo's `cargo-test-support` crate:
//! https://github.com/rust-lang/cargo/tree/master/crates/cargo-test-support
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(); // chop off exe name
path.pop(); // chop off 'deps' part
path.pop(); // chop off 'debug'
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 }
}
/// Creates a new file to be used for the integration test
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));
}
/// Returns the contents of the file
pub fn file_contents(&self, name: &str) -> String {
fs::read_to_string(self.root.join(name)).expect("Unable to read file")
}
// Sets up a new testsuite root directory
fn build(&self) {
// Cleanup before we run the next test
self.rm_root();
// Create the new directory
self.root.mkdir_p();
}
/// Deletes the root directory and all its contents
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))
}
}
|