mirror of https://github.com/rust-lang/cargo
Initial stab at integration tests
At the same time, we started adding a generic error handling concept to Cargo. The idea is that every Result gets converted to a CargoError, which includes all the information that Cargo needs to print out a friendly human error message and exit gracefully.
This commit is contained in:
parent
4e236c8558
commit
d1ec90b3d8
24
Makefile
24
Makefile
|
@ -7,7 +7,8 @@ BINS = cargo-compile \
|
|||
cargo-rustc \
|
||||
cargo-verify-project
|
||||
|
||||
SRC = $(wildcard src/*.rs)
|
||||
SRC = $(shell find src -name '*.rs')
|
||||
|
||||
DEPS = -L libs/hammer.rs/target -L libs/rust-toml/lib
|
||||
TOML = libs/rust-toml/lib/$(shell rustc --crate-file-name libs/rust-toml/src/toml/lib.rs)
|
||||
HAMMER = libs/hammer.rs/target/$(shell rustc --crate-type=lib --crate-file-name libs/hammer.rs/src/hammer.rs)
|
||||
|
@ -25,14 +26,14 @@ $(HAMMER): $(wildcard libs/hammer.rs/src/*.rs)
|
|||
$(TOML): $(wildcard libs/rust-toml/src/toml/*.rs)
|
||||
cd libs/rust-toml && make
|
||||
|
||||
$(HAMCREST): $(wildcard libs/hamcrest-rust/src/*.rs)
|
||||
$(HAMCREST): $(wildcard libs/hamcrest-rust/src/hamcrest/*.rs)
|
||||
cd libs/hamcrest-rust && make
|
||||
|
||||
# === Cargo
|
||||
|
||||
$(LIBCARGO): $(SRC)
|
||||
mkdir -p target
|
||||
$(RUSTC) $(RUSTC_FLAGS) --out-dir target src/cargo.rs
|
||||
$(RUSTC) $(RUSTC_FLAGS) --out-dir target src/cargo/mod.rs
|
||||
touch $(LIBCARGO)
|
||||
|
||||
libcargo: $(LIBCARGO)
|
||||
|
@ -42,8 +43,18 @@ libcargo: $(LIBCARGO)
|
|||
$(BIN_TARGETS): target/%: src/bin/%.rs $(HAMMER) $(TOML) $(LIBCARGO)
|
||||
$(RUSTC) $(RUSTC_FLAGS) $(DEPS) -Ltarget --out-dir target $<
|
||||
|
||||
test:
|
||||
echo "testing"
|
||||
# === Tests
|
||||
|
||||
TEST_SRC = $(wildcard tests/*.rs)
|
||||
TEST_DEPS = $(DEPS) -L libs/hamcrest-rust/target
|
||||
|
||||
target/tests: $(BIN_TARGETS) $(HAMCREST) $(TEST_SRC)
|
||||
$(RUSTC) --test --crate-type=lib $(TEST_DEPS) -Ltarget --out-dir target tests/tests.rs
|
||||
|
||||
test-integration: target/tests
|
||||
CARGO_BIN_PATH=$(PWD)/target/ $<
|
||||
|
||||
test: test-integration
|
||||
|
||||
clean:
|
||||
rm -rf target
|
||||
|
@ -54,7 +65,8 @@ distclean: clean
|
|||
cd libs/rust-toml && make clean
|
||||
|
||||
# Setup phony tasks
|
||||
.PHONY: all clean distclean test libcargo
|
||||
.PHONY: all clean distclean test test-integration libcargo
|
||||
|
||||
# Disable unnecessary built-in rules
|
||||
.SUFFIXES:
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 95f531ad8c726a832f28d171bde2860c77ec7619
|
||||
Subproject commit 39f00624492fd648631041eadf1301a08cd2a482
|
|
@ -1 +1 @@
|
|||
Subproject commit 894fdd9db6c50b9a70d1fc7d4e49c76e86921016
|
||||
Subproject commit 1389ceb42b2ae04dac40c8b2d4af8fe21823ecbc
|
|
@ -1,4 +1,5 @@
|
|||
#[crate_id="cargo-compile"];
|
||||
#[allow(deprecated_owned_vector)];
|
||||
|
||||
extern crate serialize;
|
||||
extern crate hammer;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#[crate_id="cargo-read-manifest"];
|
||||
#[allow(deprecated_owned_vector)];
|
||||
|
||||
extern crate cargo;
|
||||
extern crate hammer;
|
||||
|
@ -9,7 +10,7 @@ use hammer::{FlagDecoder,FlagConfig,FlagConfiguration};
|
|||
use serialize::{Decoder,Decodable};
|
||||
use serialize::json::Encoder;
|
||||
use toml::from_toml;
|
||||
use cargo::{Manifest,LibTarget,ExecTarget,Project};
|
||||
use cargo::{Manifest,LibTarget,ExecTarget,Project,CargoResult,CargoError,ToCargoError};
|
||||
use std::path::Path;
|
||||
|
||||
#[deriving(Decodable,Encodable,Eq,Clone,Ord)]
|
||||
|
@ -41,21 +42,32 @@ impl FlagConfig for ReadManifestFlags {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
match execute() {
|
||||
Err(e) => {
|
||||
println!("{}", e.message);
|
||||
// TODO: Exit with error code
|
||||
},
|
||||
_ => return
|
||||
}
|
||||
}
|
||||
|
||||
fn execute() -> CargoResult<()> {
|
||||
let mut decoder = FlagDecoder::new::<ReadManifestFlags>(std::os::args().tail());
|
||||
let flags: ReadManifestFlags = Decodable::decode(&mut decoder);
|
||||
|
||||
if decoder.error.is_some() {
|
||||
fail!("Error: {}", decoder.error.unwrap());
|
||||
return Err(CargoError::new(decoder.error.unwrap(), 1));
|
||||
}
|
||||
|
||||
let root = toml::parse_from_file(flags.manifest_path).unwrap();
|
||||
let manifest_path = flags.manifest_path;
|
||||
let root = try!(toml::parse_from_file(manifest_path.clone()).to_cargo_error(format!("Couldn't parse Toml file: {}", manifest_path), 1));
|
||||
|
||||
let toml_manifest = from_toml::<SerializedManifest>(root.clone());
|
||||
|
||||
let (lib, bin) = normalize(&toml_manifest.lib, &toml_manifest.bin);
|
||||
|
||||
let manifest = Manifest{
|
||||
root: Path::new(flags.manifest_path).dirname_str().unwrap().to_owned(),
|
||||
root: try!(Path::new(manifest_path.clone()).dirname_str().to_cargo_error(format!("Could not get dirname from {}", manifest_path), 1)).to_owned(),
|
||||
project: toml_manifest.project,
|
||||
lib: lib,
|
||||
bin: bin
|
||||
|
@ -64,6 +76,8 @@ fn main() {
|
|||
let encoded: ~str = Encoder::str_encode(&manifest);
|
||||
|
||||
println!("{}", encoded);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn normalize(lib: &Option<~[SerializedLibTarget]>, bin: &Option<~[SerializedExecTarget]>) -> (~[LibTarget], ~[ExecTarget]) {
|
||||
|
@ -98,7 +112,7 @@ fn normalize(lib: &Option<~[SerializedLibTarget]>, bin: &Option<~[SerializedExec
|
|||
let b = b_ref.clone();
|
||||
let mut path = b.path.clone();
|
||||
if path.is_none() {
|
||||
path = Some(format!("src/bin/{}.rs", b.name.clone()));
|
||||
path = Some(format!("src/{}.rs", b.name.clone()));
|
||||
}
|
||||
ExecTarget{ path: path.unwrap(), name: b.name }
|
||||
});
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#[crate_id="cargo-rustc"];
|
||||
#[allow(deprecated_owned_vector)];
|
||||
|
||||
extern crate toml;
|
||||
extern crate serialize;
|
||||
|
@ -10,7 +11,7 @@ use std::io::process::{Process,ProcessConfig,InheritFd};
|
|||
use serialize::json;
|
||||
use serialize::Decodable;
|
||||
use std::path::Path;
|
||||
use cargo::Manifest;
|
||||
use cargo::{Manifest,CargoResult,CargoError,ToCargoError};
|
||||
|
||||
/**
|
||||
cargo-rustc -- ...args
|
||||
|
@ -19,23 +20,40 @@ use cargo::Manifest;
|
|||
*/
|
||||
|
||||
fn main() {
|
||||
let mut reader = io::stdin();
|
||||
let input = reader.read_to_str().unwrap();
|
||||
match execute() {
|
||||
Err(e) => {
|
||||
write!(&mut std::io::stderr(), "{}", e.message);
|
||||
// TODO: Exit with error code
|
||||
},
|
||||
_ => return
|
||||
}
|
||||
}
|
||||
|
||||
let json = json::from_str(input).unwrap();
|
||||
fn execute() -> CargoResult<()> {
|
||||
let mut reader = io::stdin();
|
||||
let input = try!(reader.read_to_str().to_cargo_error(~"Cannot read stdin to a string", 1));
|
||||
|
||||
let json = try!(json::from_str(input).to_cargo_error(format!("Cannot parse json: {}", input), 1));
|
||||
let mut decoder = json::Decoder::new(json);
|
||||
let manifest: Manifest = Decodable::decode(&mut decoder);
|
||||
|
||||
let Manifest{ root, lib, .. } = manifest;
|
||||
let Manifest{ root, lib, bin, .. } = manifest;
|
||||
|
||||
let (crate_type, out_dir) = if lib.len() > 0 {
|
||||
( ~"lib", lib[0].path )
|
||||
} else if bin.len() > 0 {
|
||||
( ~"bin", bin[0].path )
|
||||
} else {
|
||||
return Err(CargoError::new(~"bad manifest, no lib or bin specified", 1));
|
||||
};
|
||||
|
||||
let root = Path::new(root);
|
||||
let out_dir = lib[0].path;
|
||||
let target = join(&root, ~"target");
|
||||
|
||||
let args = [
|
||||
join(&root, out_dir),
|
||||
~"--out-dir", target,
|
||||
~"--crate-type", ~"lib"
|
||||
~"--crate-type", crate_type
|
||||
];
|
||||
|
||||
match io::fs::mkdir_recursive(&root.join("target"), io::UserRWX) {
|
||||
|
@ -51,15 +69,25 @@ fn main() {
|
|||
config.program = "rustc";
|
||||
config.args = args.as_slice();
|
||||
|
||||
let mut p = Process::configure(config).unwrap();
|
||||
let mut p = try!(Process::configure(config).to_cargo_error(format!("Could not start process: rustc {}", args.as_slice()), 1));
|
||||
|
||||
let status = p.wait();
|
||||
|
||||
if status != std::io::process::ExitStatus(0) {
|
||||
fail!("Failed to execute")
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn join(path: &Path, part: ~str) -> ~str {
|
||||
path.join(part).as_str().unwrap().to_owned()
|
||||
format!("{}", path.join(part).display())
|
||||
}
|
||||
|
||||
fn vec_idx<T>(v: ~[T], idx: uint) -> Option<T> {
|
||||
if idx < v.len() {
|
||||
Some(v[idx])
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#[crate_id="cargo-verify-project"];
|
||||
#[allow(deprecated_owned_vector)];
|
||||
|
||||
extern crate toml;
|
||||
extern crate getopts;
|
||||
|
|
34
src/cargo.rs
34
src/cargo.rs
|
@ -1,34 +0,0 @@
|
|||
#[crate_type="rlib"];
|
||||
|
||||
extern crate serialize;
|
||||
use serialize::{Decoder};
|
||||
|
||||
#[deriving(Decodable,Encodable,Eq,Clone,Ord)]
|
||||
pub struct Manifest {
|
||||
project: ~Project,
|
||||
root: ~str,
|
||||
lib: ~[LibTarget],
|
||||
bin: ~[ExecTarget]
|
||||
}
|
||||
|
||||
#[deriving(Decodable,Encodable,Eq,Clone,Ord)]
|
||||
pub struct ExecTarget {
|
||||
name: ~str,
|
||||
path: ~str
|
||||
}
|
||||
|
||||
#[deriving(Decodable,Encodable,Eq,Clone,Ord)]
|
||||
pub struct LibTarget {
|
||||
name: ~str,
|
||||
path: ~str
|
||||
}
|
||||
|
||||
//pub type LibTarget = Target;
|
||||
//pub type ExecTarget = Target;
|
||||
|
||||
#[deriving(Decodable,Encodable,Eq,Clone,Ord)]
|
||||
pub struct Project {
|
||||
name: ~str,
|
||||
version: ~str,
|
||||
authors: ~[~str]
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
#[crate_id="cargo"];
|
||||
#[crate_type="rlib"];
|
||||
|
||||
#[allow(deprecated_owned_vector)];
|
||||
|
||||
extern crate serialize;
|
||||
use serialize::{Decoder};
|
||||
use std::fmt;
|
||||
use std::fmt::{Show,Formatter};
|
||||
|
||||
pub mod util;
|
||||
|
||||
#[deriving(Decodable,Encodable,Eq,Clone,Ord)]
|
||||
pub struct Manifest {
|
||||
project: ~Project,
|
||||
root: ~str,
|
||||
lib: ~[LibTarget],
|
||||
bin: ~[ExecTarget]
|
||||
}
|
||||
|
||||
#[deriving(Decodable,Encodable,Eq,Clone,Ord)]
|
||||
pub struct ExecTarget {
|
||||
name: ~str,
|
||||
path: ~str
|
||||
}
|
||||
|
||||
#[deriving(Decodable,Encodable,Eq,Clone,Ord)]
|
||||
pub struct LibTarget {
|
||||
name: ~str,
|
||||
path: ~str
|
||||
}
|
||||
|
||||
//pub type LibTarget = Target;
|
||||
//pub type ExecTarget = Target;
|
||||
|
||||
#[deriving(Decodable,Encodable,Eq,Clone,Ord)]
|
||||
pub struct Project {
|
||||
name: ~str,
|
||||
version: ~str,
|
||||
authors: ~[~str]
|
||||
}
|
||||
|
||||
pub type CargoResult<T> = Result<T, CargoError>;
|
||||
|
||||
pub struct CargoError {
|
||||
message: ~str,
|
||||
exit_code: uint
|
||||
}
|
||||
|
||||
impl CargoError {
|
||||
pub fn new(message: ~str, exit_code: uint) -> CargoError {
|
||||
CargoError { message: message, exit_code: exit_code }
|
||||
}
|
||||
}
|
||||
|
||||
impl Show for CargoError {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f.buf, "{}", self.message)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ToCargoError<T> {
|
||||
fn to_cargo_error(self, message: ~str, exit_code: uint) -> Result<T, CargoError>;
|
||||
}
|
||||
|
||||
impl<T,U> ToCargoError<T> for Result<T,U> {
|
||||
fn to_cargo_error(self, message: ~str, exit_code: uint) -> Result<T, CargoError> {
|
||||
match self {
|
||||
Err(_) => Err(CargoError{ message: message, exit_code: exit_code }),
|
||||
Ok(val) => Ok(val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ToCargoError<T> for Option<T> {
|
||||
fn to_cargo_error(self, message: ~str, exit_code: uint) -> CargoResult<T> {
|
||||
match self {
|
||||
None => Err(CargoError{ message: message, exit_code: exit_code }),
|
||||
Some(val) => Ok(val)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
pub use self::process_builder::process;
|
||||
pub mod process_builder;
|
|
@ -0,0 +1,63 @@
|
|||
use std;
|
||||
use std::os;
|
||||
use std::path::Path;
|
||||
use std::io::IoResult;
|
||||
use std::io::process::{Process,ProcessConfig,ProcessOutput};
|
||||
use ToCargoError;
|
||||
use CargoResult;
|
||||
|
||||
pub struct ProcessBuilder {
|
||||
program: ~str,
|
||||
args: ~[~str],
|
||||
path: ~[~str],
|
||||
cwd: Path
|
||||
}
|
||||
|
||||
// TODO: Upstream a Windows/Posix branch to Rust proper
|
||||
static PATH_SEP : &'static str = ":";
|
||||
|
||||
impl ProcessBuilder {
|
||||
pub fn args(mut self, arguments: &[~str]) -> ProcessBuilder {
|
||||
self.args = arguments.to_owned();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn extra_path(mut self, path: &str) -> ProcessBuilder {
|
||||
self.path.push(path.to_owned());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn cwd(mut self, path: Path) -> ProcessBuilder {
|
||||
self.cwd = path;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn exec_with_output(self) -> CargoResult<ProcessOutput> {
|
||||
let mut config = ProcessConfig::new();
|
||||
|
||||
println!("cwd: {}", self.cwd.display());
|
||||
|
||||
config.program = self.program.as_slice();
|
||||
config.args = self.args.as_slice();
|
||||
config.cwd = Some(&self.cwd);
|
||||
|
||||
let os_path = try!(os::getenv("PATH").to_cargo_error(~"Could not find the PATH environment variable", 1));
|
||||
let path = os_path + PATH_SEP + self.path.connect(PATH_SEP);
|
||||
|
||||
let path = [(~"PATH", path)];
|
||||
config.env = Some(path.as_slice());
|
||||
|
||||
println!("{:?}", config);
|
||||
|
||||
Process::configure(config).map(|mut ok| ok.wait_with_output()).to_cargo_error(~"Could not spawn process", 1)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn process(cmd: &str) -> ProcessBuilder {
|
||||
ProcessBuilder {
|
||||
program: cmd.to_owned(),
|
||||
args: ~[],
|
||||
path: ~[],
|
||||
cwd: os::getcwd()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
// use std::io::fs::{mkdir_recursive,rmdir_recursive};
|
||||
use std::io::fs;
|
||||
use std::os::tmpdir;
|
||||
use std::path::{Path};
|
||||
|
||||
static CARGO_INTEGRATION_TEST_DIR : &'static str = "cargo-integration-tests";
|
||||
static MKDIR_PERM : u32 = 0o755;
|
||||
|
||||
#[deriving(Eq,Clone)]
|
||||
struct FileBuilder {
|
||||
path: Path,
|
||||
body: ~str
|
||||
}
|
||||
|
||||
impl FileBuilder {
|
||||
pub fn new(path: Path, body: &str) -> FileBuilder {
|
||||
FileBuilder { path: path, body: body.to_owned() }
|
||||
}
|
||||
|
||||
fn mk(&self) -> Result<(), ~str> {
|
||||
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(Eq,Clone)]
|
||||
struct ProjectBuilder {
|
||||
name: ~str,
|
||||
root: Path,
|
||||
files: ~[FileBuilder]
|
||||
}
|
||||
|
||||
impl ProjectBuilder {
|
||||
pub fn new(name: &str, root: Path) -> ProjectBuilder {
|
||||
ProjectBuilder {
|
||||
name: name.to_owned(),
|
||||
root: root,
|
||||
files: ~[]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn root(&self) -> Path {
|
||||
self.root.clone()
|
||||
}
|
||||
|
||||
pub fn file(mut self, path: &str, body: &str) -> ProjectBuilder {
|
||||
self.files.push(FileBuilder::new(self.root.join(path), body));
|
||||
self
|
||||
}
|
||||
|
||||
// TODO: return something different than a ProjectBuilder
|
||||
pub fn build(self) -> ProjectBuilder {
|
||||
match self.build_with_result() {
|
||||
Err(e) => fail!(e),
|
||||
_ => return self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_with_result(&self) -> Result<(), ~str> {
|
||||
// First, clean the directory if it already exists
|
||||
try!(self.rm_root());
|
||||
|
||||
// Create the empty directory
|
||||
try!(mkdir_recursive(&self.root));
|
||||
|
||||
for file in self.files.iter() {
|
||||
try!(file.mk());
|
||||
}
|
||||
|
||||
println!("{}", self.root.display());
|
||||
println!("{:?}", self);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn rm_root(&self) -> Result<(), ~str> {
|
||||
if self.root.exists() {
|
||||
rmdir_recursive(&self.root)
|
||||
}
|
||||
else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generates a project layout
|
||||
pub fn project(name: &str) -> ProjectBuilder {
|
||||
ProjectBuilder::new(name, tmpdir().join(CARGO_INTEGRATION_TEST_DIR))
|
||||
}
|
||||
|
||||
// === Helpers ===
|
||||
|
||||
pub fn mkdir_recursive(path: &Path) -> Result<(), ~str> {
|
||||
fs::mkdir_recursive(path, MKDIR_PERM)
|
||||
.with_err_msg(format!("could not create directory; path={}", path.display()))
|
||||
}
|
||||
|
||||
pub fn rmdir_recursive(path: &Path) -> Result<(), ~str> {
|
||||
fs::rmdir_recursive(path)
|
||||
.with_err_msg(format!("could not rm directory; path={}", path.display()))
|
||||
}
|
||||
|
||||
trait ErrMsg<T> {
|
||||
fn with_err_msg(self, val: ~str) -> Result<T, ~str>;
|
||||
}
|
||||
|
||||
impl<T, E> ErrMsg<T> for Result<T, E> {
|
||||
fn with_err_msg(self, val: ~str) -> Result<T, ~str> {
|
||||
match self {
|
||||
Ok(val) => Ok(val),
|
||||
Err(_) => Err(val)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
use std;
|
||||
use support::project;
|
||||
use hamcrest::{SelfDescribing,Description,Matcher,assert_that};
|
||||
use cargo;
|
||||
|
||||
#[deriving(Clone,Eq)]
|
||||
pub struct ExistingFile;
|
||||
|
||||
impl SelfDescribing for ExistingFile {
|
||||
fn describe_to(&self, desc: &mut Description) {
|
||||
desc.append_text("an existing file");
|
||||
}
|
||||
}
|
||||
|
||||
impl Matcher<Path> for ExistingFile {
|
||||
fn matches(&self, actual: &Path) -> bool {
|
||||
actual.exists()
|
||||
}
|
||||
|
||||
fn describe_mismatch(&self, actual: &Path, desc: &mut Description) {
|
||||
desc.append_text(format!("`{}` was missing", actual.display()));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn existing_file() -> ExistingFile {
|
||||
ExistingFile
|
||||
}
|
||||
|
||||
fn setup() {
|
||||
|
||||
}
|
||||
|
||||
test!(cargo_compile_with_explicit_manifest_path {
|
||||
let p = project("foo")
|
||||
.file("Cargo.toml", r#"
|
||||
[project]
|
||||
|
||||
name = "foo"
|
||||
version = "0.5.0"
|
||||
authors = ["wycats@example.com"]
|
||||
|
||||
[[bin]]
|
||||
|
||||
name = "foo"
|
||||
"#)
|
||||
.file("src/foo.rs", r#"
|
||||
fn main() {
|
||||
println!("i am foo");
|
||||
}"#)
|
||||
.build();
|
||||
|
||||
let output = cargo::util::process("cargo-compile")
|
||||
.args([~"--manifest-path", ~"Cargo.toml"])
|
||||
.extra_path(target_path())
|
||||
.cwd(p.root())
|
||||
.exec_with_output();
|
||||
|
||||
match output {
|
||||
Ok(out) => {
|
||||
println!("out:\n{}\n", std::str::from_utf8(out.output));
|
||||
println!("err:\n{}\n", std::str::from_utf8(out.error));
|
||||
},
|
||||
Err(e) => println!("err: {}", e)
|
||||
}
|
||||
|
||||
assert_that(p.root().join("target/foo/bar"), existing_file());
|
||||
assert!(p.root().join("target/foo").exists(), "the executable exists");
|
||||
|
||||
let o = cargo::util::process("foo")
|
||||
.extra_path(format!("{}", p.root().join("target").display()))
|
||||
.exec_with_output()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(std::str::from_utf8(o.output).unwrap(), "i am foo\n");
|
||||
})
|
||||
|
||||
// test!(compiling_project_with_invalid_manifest)
|
||||
|
||||
fn target_path() -> ~str {
|
||||
std::os::getenv("CARGO_BIN_PATH").unwrap_or_else(|| {
|
||||
fail!("CARGO_BIN_PATH wasn't set. Cannot continue running test")
|
||||
})
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
#[feature(macro_rules)];
|
||||
#[allow(deprecated_owned_vector)];
|
||||
|
||||
extern crate cargo;
|
||||
extern crate hamcrest;
|
||||
|
||||
macro_rules! test(
|
||||
($name:ident $expr:expr) => (
|
||||
#[test]
|
||||
fn $name() {
|
||||
setup();
|
||||
$expr;
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
mod support;
|
||||
mod test_cargo_compile;
|
Loading…
Reference in New Issue