Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move to new io/path/fs/net API #13

Merged
merged 1 commit into from
Mar 8, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 13 additions & 19 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![deny(missing_docs)]
#![deny(warnings)]
#![feature(core, io, env, path)]
#![feature(core, io, path, std_misc, net, path_ext)]

//! A set of constructors for mocking Iron objects.

Expand All @@ -26,14 +26,15 @@ pub mod mock {

use hyper::http::HttpReader;

use std::old_io::net::ip::ToSocketAddr;
use std::io::Read;
use std::net::SocketAddr;

/// Create a new mock Request with the given method, url, and data.
pub fn new<'a, R>(method: method::Method, path: Url,
data: &'a mut R) -> Request<'a>
where R: Reader {
let reader = HttpReader::EofReader(data as &'a mut Reader);
let addr = "127.0.0.1:3000".to_socket_addr().unwrap();
where R: Read {
let reader = HttpReader::EofReader(data as &'a mut Read);
let addr: SocketAddr = "127.0.0.1:3000".parse().unwrap();

let mut headers = Headers::new();
let host = Url::parse("http://127.0.0.1:3000").unwrap()
Expand Down Expand Up @@ -66,24 +67,17 @@ mod test {
use super::super::mock::request;
use iron::method;
use iron::Url;
use std::io::{Read,Cursor};

#[test] fn test_new() {
let req = request::new(method::Get, "localhost:3000");
#[test] fn test_request() {
let ref mut data = Cursor::new("Hello Google!".as_bytes());
let mut req = request::new(method::Get, Url::parse("http://localhost:3000").unwrap(), data);
assert_eq!(req.method, method::Get);
assert_eq!(format!("{}", req.url).as_slice(), "http://localhost:3000/");
}

#[test] fn test_at() {
let req = request::at(method::Post, Url::parse("http://www.google.com/").unwrap());
assert_eq!(req.method, method::Post);
assert_eq!(format!("{}", req.url).as_slice(), "http://www.google.com:80/");
}

#[test] fn test_at_with() {
let req = request::at_with(method::Put, Url::parse("http://www.google.com/").unwrap(), "Hello Google!");
assert_eq!(req.method, method::Put);
assert_eq!(format!("{}", req.url).as_slice(), "http://www.google.com:80/");
assert_eq!(req.body.as_slice(), b"Hello Google!");
let mut body_buf = Vec::new();
req.body.read_to_end(&mut body_buf).ok().unwrap();
assert_eq!(&*body_buf, b"Hello Google!");
}
}
}
Expand Down
59 changes: 33 additions & 26 deletions src/project_builder.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
use std::old_io::fs::{self, PathExtensions};
use std::old_io::IoResult;
use std::old_io as io;
use std::fs;
use std::fs::PathExt;
use std::io::{self, Write};
use std::env;
use std::old_path::{Path, BytesContainer};
use std::path::{Path, PathBuf, AsPath};
use std::fmt::Debug;
use uuid::Uuid;
use std::ffi::IntoBytes;
use std::sync::{StaticMutex, MUTEX_INIT};

static IRON_INTEGRATION_TEST_DIR : &'static str = "iron-integration-tests";
static FILE_OP_LOCK: StaticMutex = MUTEX_INIT;

#[derive(Debug, PartialEq, Clone)]
struct FileBuilder {
path: Path,
path: PathBuf,
body: Vec<u8>
}

impl FileBuilder {
/// creates new instance of ProjectBuilder
pub fn new(path: Path, body: &[u8]) -> FileBuilder {
FileBuilder { path: path, body: body.to_vec() }
/// creates new instance of FileBuilder
pub fn new<P: AsPath, B: IntoBytes>(path: P, body: B) -> FileBuilder {
FileBuilder { path: path.as_path().to_path_buf(), body: body.into_bytes() }
}

fn mk(&self) -> Result<(), String> {
Expand All @@ -33,8 +36,9 @@ impl FileBuilder {
self.path.display()))
}

fn dirname(&self) -> Path {
Path::new(self.path.dirname())
// FIXME: Panics if there's no parent
fn dirname(&self) -> &Path {
&self.path.parent().expect("parent directory")
}
}

Expand All @@ -46,7 +50,7 @@ impl FileBuilder {
#[derive(Debug, PartialEq, Clone)]
pub struct ProjectBuilder {
name: String,
root: Path,
root: PathBuf,
files: Vec<FileBuilder>,
}

Expand All @@ -73,9 +77,9 @@ impl ProjectBuilder {
}

/// Add a new file to the temporary directory with the given contents.
pub fn file<B, C>(mut self, path: B, body: C) -> ProjectBuilder
where B: BytesContainer, C: BytesContainer {
self.files.push(FileBuilder::new(self.root.join(path), body.container_as_bytes()));
pub fn file<P, B>(mut self, path: P, body: B) -> ProjectBuilder
where P: AsPath, B: IntoBytes {
self.files.push(FileBuilder::new(self.root.join(&path), body));
self
}

Expand All @@ -96,16 +100,18 @@ impl ProjectBuilder {

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)
match self.root().parent().map(BuilderPathExt::rm_rf) {
Some(Ok(_)) => debug!("Successfully cleaned up the test directory; path = {:?}", self.root().parent().unwrap()),
Some(Err(e)) => debug!("Failed to cleanup the test directory; path = {:?}; {}", self.root().parent().unwrap(), e),
None => debug!("Failed to cleanup the test directory; no parent")
}
}
}

// Recursively creates the directory with all subdirectories
fn mkdir_recursive(path: &Path) -> Result<(), String> {
fs::mkdir_recursive(path, io::USER_DIR)
let _l = FILE_OP_LOCK.lock().unwrap();
fs::create_dir_all(path)
.with_err_msg(format!("could not create directory; path={}",
path.display()))
}
Expand All @@ -128,27 +134,28 @@ impl<T, E: Debug> ErrMsg<T> for Result<T, E> {

// Current test root path.
// Will be located in target/iron-integration-tests/test-<uuid>
fn root(id: Uuid) -> Path {
integration_tests_dir().join(format!("test-{}", id))
fn root(id: Uuid) -> PathBuf {
integration_tests_dir().join(&format!("test-{}", id))
}

fn integration_tests_dir() -> Path {
fn integration_tests_dir() -> PathBuf {
env::current_exe()
.map(|mut p| { p.pop(); p.join(IRON_INTEGRATION_TEST_DIR) })
.unwrap()
}


/// Convenience methods on Path
pub trait PathExt {
pub trait BuilderPathExt {
/// Deletes directory in Path recursively
fn rm_rf(&self) -> IoResult<()>;
fn rm_rf(&self) -> io::Result<()>;
}

impl PathExt for Path {
fn rm_rf(&self) -> IoResult<()> {
impl BuilderPathExt for Path {
fn rm_rf(&self) -> io::Result<()> {
let _l = FILE_OP_LOCK.lock().unwrap();
if self.exists() {
fs::rmdir_recursive(self)
fs::remove_dir_all(self)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there be locking for this operation as well? Can concurrent mkdir_recursive and this cause issues?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While it doesn't matter for the tests from iron/static (they only remove their very own directy) I think we should look rm as well. Just in case.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like a plan. Make the change and I'll give a final pass (everything else LGTM though).

} else {
Ok(())
}
Expand Down