use std::io::fs::{mod, PathExtensions};
use std::io::{mod, IoResult};
use std::os;
use std::path::{Path, BytesContainer};
use std::vec::Vec;
use std::fmt::Show;
use uuid::Uuid;
static IRON_INTEGRATION_TEST_DIR : &'static str = "iron-integration-tests";
#[deriving(PartialEq,Clone)]
struct FileBuilder {
path: Path,
body: String
}
impl FileBuilder {
pub fn new(path: Path, body: &str) -> FileBuilder {
FileBuilder { path: path, body: body.to_string() }
}
fn mk(&self) -> Result<(), String> {
try!(mkdir_recursive(&self.dirname()));
let mut file = try!(
fs::File::create(&self.path)
.with_err_msg(format!("Could not create file; path={}",
self.path.display())));
file.write_str(self.body.as_slice())
.with_err_msg(format!("Could not write to file; path={}",
self.path.display()))
}
fn dirname(&self) -> Path {
Path::new(self.path.dirname())
}
}
#[deriving(PartialEq,Clone)]
pub struct ProjectBuilder {
name: String,
root: Path,
files: Vec<FileBuilder>,
}
impl ProjectBuilder {
pub fn new(name: &str) -> ProjectBuilder {
let id = Uuid::new_v4();
debug!("path setup: root={}", root(id.clone()).display());
root(id.clone()).rm_rf().unwrap();
ProjectBuilder {
name: name.to_string(),
root: root(id).join(name),
files: vec!(),
}
}
pub fn root(&self) -> Path {
self.root.clone()
}
pub fn file<B: BytesContainer, S: Str>(mut self, path: B, body: S) -> ProjectBuilder {
self.files.push(FileBuilder::new(self.root.join(path), body.as_slice()));
self
}
pub fn build(&self) -> &ProjectBuilder {
match self.build_with_result() {
Err(e) => panic!(e),
_ => return self
}
}
pub fn build_with_result(&self) -> Result<(), String> {
for file in self.files.iter() {
try!(file.mk());
}
Ok(())
}
}
impl Drop for ProjectBuilder {
fn drop(&mut self) {
match self.root().dir_path().rm_rf() {
Ok(_) => debug!("Successfully cleaned up the test directory; path = {}", self.root().dir_path().display()),
Err(e) => debug!("Failed to cleanup the test directory; path = {}; {}", self.root().dir_path().display(), e)
}
}
}
pub fn mkdir_recursive(path: &Path) -> Result<(), String> {
fs::mkdir_recursive(path, io::USER_DIR)
.with_err_msg(format!("could not create directory; path={}",
path.display()))
}
trait ErrMsg<T> {
fn with_err_msg(self, val: String) -> Result<T, String>;
}
impl<T, E: Show> ErrMsg<T> for Result<T, E> {
fn with_err_msg(self, val: String) -> Result<T, String> {
match self {
Ok(val) => Ok(val),
Err(err) => Err(format!("{}; original={}", val, err))
}
}
}
fn root(id: Uuid) -> Path {
integration_tests_dir().join(format!("test-{}", id))
}
fn integration_tests_dir() -> Path {
os::self_exe_path().unwrap().join(IRON_INTEGRATION_TEST_DIR)
}
pub trait PathExt {
fn rm_rf(&self) -> IoResult<()>;
}
impl PathExt for Path {
fn rm_rf(&self) -> IoResult<()> {
if self.exists() {
fs::rmdir_recursive(self)
} else {
Ok(())
}
}
}