mirror of
https://github.com/rust-lang/cargo.git
synced 2025-10-01 11:30:39 +00:00
Add cargo test
This commit is contained in:
parent
920b8b3421
commit
13eb123213
1
Makefile
1
Makefile
@ -11,6 +11,7 @@ BINS = cargo \
|
||||
cargo-rustc \
|
||||
cargo-verify-project \
|
||||
cargo-git-checkout \
|
||||
cargo-test \
|
||||
|
||||
SRC = $(shell find src -name '*.rs' -not -path 'src/bin*')
|
||||
|
||||
|
@ -48,7 +48,7 @@ fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>> {
|
||||
|
||||
let update = options.update_remotes;
|
||||
|
||||
ops::compile(&root, update, shell).map(|_| None).map_err(|err| {
|
||||
ops::compile(&root, update, "compile", shell).map(|_| None).map_err(|err| {
|
||||
CliError::from_boxed(err, 101)
|
||||
})
|
||||
}
|
||||
|
60
src/bin/cargo-test.rs
Normal file
60
src/bin/cargo-test.rs
Normal file
@ -0,0 +1,60 @@
|
||||
#![crate_id="cargo-test"]
|
||||
#![feature(phase)]
|
||||
|
||||
#[phase(plugin, link)]
|
||||
extern crate cargo;
|
||||
extern crate serialize;
|
||||
|
||||
#[phase(plugin, link)]
|
||||
extern crate hammer;
|
||||
|
||||
use std::os;
|
||||
use std::io::fs;
|
||||
|
||||
use cargo::ops;
|
||||
use cargo::{execute_main_without_stdin};
|
||||
use cargo::core::{MultiShell};
|
||||
use cargo::util;
|
||||
use cargo::util::{CliResult, CliError};
|
||||
use cargo::util::important_paths::find_project;
|
||||
|
||||
#[deriving(PartialEq,Clone,Decodable)]
|
||||
struct Options {
|
||||
manifest_path: Option<String>,
|
||||
rest: Vec<String>
|
||||
}
|
||||
|
||||
hammer_config!(Options "Run the package's test suite")
|
||||
|
||||
fn main() {
|
||||
execute_main_without_stdin(execute);
|
||||
}
|
||||
|
||||
fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>> {
|
||||
let root = match options.manifest_path {
|
||||
Some(path) => Path::new(path),
|
||||
None => try!(find_project(os::getcwd(), "Cargo.toml")
|
||||
.map(|path| path.join("Cargo.toml"))
|
||||
.map_err(|_| {
|
||||
CliError::new("Could not find Cargo.toml in this \
|
||||
directory or any parent directory",
|
||||
102)
|
||||
}))
|
||||
};
|
||||
|
||||
try!(ops::compile(&root, false, "test", shell).map(|_| None::<()>).map_err(|err| {
|
||||
CliError::from_boxed(err, 101)
|
||||
}));
|
||||
|
||||
let test_dir = root.dir_path().join("target").join("tests");
|
||||
|
||||
let mut walk = try!(fs::walk_dir(&test_dir).map_err(|e| {
|
||||
CliError::from_error(e, 1)
|
||||
}));
|
||||
|
||||
for file in walk {
|
||||
try!(util::process(file).exec().map_err(|e| CliError::from_boxed(e.box_error(), 1)));
|
||||
}
|
||||
|
||||
Ok(None)
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
use semver::Version;
|
||||
use core::{VersionReq,SourceId};
|
||||
use util::CargoResult;
|
||||
|
||||
@ -10,18 +9,9 @@ pub struct Dependency {
|
||||
}
|
||||
|
||||
impl Dependency {
|
||||
pub fn new(name: &str, req: &VersionReq,
|
||||
namespace: &SourceId) -> Dependency {
|
||||
Dependency {
|
||||
name: name.to_str(),
|
||||
namespace: namespace.clone(),
|
||||
req: req.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse(name: &str, version: Option<&str>,
|
||||
namespace: &SourceId) -> CargoResult<Dependency> {
|
||||
|
||||
namespace: &SourceId) -> CargoResult<Dependency>
|
||||
{
|
||||
let version = match version {
|
||||
Some(v) => try!(VersionReq::parse(v)),
|
||||
None => VersionReq::any()
|
||||
@ -34,15 +24,6 @@ impl Dependency {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn exact(name: &str, version: &Version,
|
||||
namespace: &SourceId) -> Dependency {
|
||||
Dependency {
|
||||
name: name.to_str(),
|
||||
namespace: namespace.clone(),
|
||||
req: VersionReq::exact(version)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_version_req<'a>(&'a self) -> &'a VersionReq {
|
||||
&self.req
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ impl<E, S: Encoder<E>> Encodable<S, E> for Manifest {
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Show,Clone,PartialEq,Encodable)]
|
||||
#[deriving(Show, Clone, PartialEq, Hash, Encodable)]
|
||||
pub enum LibKind {
|
||||
Lib,
|
||||
Rlib,
|
||||
@ -92,17 +92,64 @@ impl LibKind {
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Show,Clone,PartialEq,Encodable)]
|
||||
#[deriving(Show, Clone, Hash, PartialEq, Encodable)]
|
||||
pub enum TargetKind {
|
||||
LibTarget(Vec<LibKind>),
|
||||
BinTarget
|
||||
}
|
||||
|
||||
#[deriving(Clone,PartialEq)]
|
||||
#[deriving(Clone, Hash, PartialEq)]
|
||||
pub struct Profile {
|
||||
env: String, // compile, test, dev, bench, etc.
|
||||
opt_level: uint,
|
||||
debug: bool,
|
||||
test: bool
|
||||
}
|
||||
|
||||
impl Profile {
|
||||
pub fn default(env: &str) -> Profile {
|
||||
Profile {
|
||||
env: env.to_str(), // run in the default environment only
|
||||
opt_level: 0,
|
||||
debug: true,
|
||||
test: false // whether or not to pass --test
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_compile(&self) -> bool {
|
||||
self.env.as_slice() == "compile"
|
||||
}
|
||||
|
||||
pub fn is_test(&self) -> bool {
|
||||
self.test
|
||||
}
|
||||
|
||||
pub fn get_env<'a>(&'a self) -> &'a str {
|
||||
self.env.as_slice()
|
||||
}
|
||||
|
||||
pub fn opt_level(mut self, level: uint) -> Profile {
|
||||
self.opt_level = level;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn debug(mut self, debug: bool) -> Profile {
|
||||
self.debug = debug;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn test(mut self, test: bool) -> Profile {
|
||||
self.test = test;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Clone, Hash, PartialEq)]
|
||||
pub struct Target {
|
||||
kind: TargetKind,
|
||||
name: String,
|
||||
path: Path
|
||||
path: Path,
|
||||
profile: Profile
|
||||
}
|
||||
|
||||
#[deriving(Encodable)]
|
||||
@ -191,19 +238,21 @@ impl Manifest {
|
||||
|
||||
impl Target {
|
||||
pub fn lib_target(name: &str, crate_targets: Vec<LibKind>,
|
||||
path: &Path) -> Target {
|
||||
path: &Path, profile: &Profile) -> Target {
|
||||
Target {
|
||||
kind: LibTarget(crate_targets),
|
||||
name: name.to_str(),
|
||||
path: path.clone()
|
||||
path: path.clone(),
|
||||
profile: profile.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bin_target(name: &str, path: &Path) -> Target {
|
||||
pub fn bin_target(name: &str, path: &Path, profile: &Profile) -> Target {
|
||||
Target {
|
||||
kind: BinTarget,
|
||||
name: name.to_str(),
|
||||
path: path.clone()
|
||||
path: path.clone(),
|
||||
profile: profile.clone()
|
||||
}
|
||||
}
|
||||
|
||||
@ -225,6 +274,10 @@ impl Target {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_profile<'a>(&'a self) -> &'a Profile {
|
||||
&self.profile
|
||||
}
|
||||
|
||||
pub fn rustc_crate_types(&self) -> Vec<&'static str> {
|
||||
match self.kind {
|
||||
LibTarget(ref kinds) => {
|
||||
|
@ -6,6 +6,7 @@ pub use self::manifest::{
|
||||
Manifest,
|
||||
Target,
|
||||
TargetKind,
|
||||
Profile
|
||||
};
|
||||
|
||||
pub use self::package::{
|
||||
@ -36,7 +37,10 @@ pub use self::shell::{
|
||||
ShellConfig
|
||||
};
|
||||
|
||||
pub use self::dependency::Dependency;
|
||||
pub use self::dependency::{
|
||||
Dependency
|
||||
};
|
||||
|
||||
pub use self::version_req::VersionReq;
|
||||
|
||||
pub mod errors;
|
||||
|
@ -39,9 +39,18 @@ macro_rules! some(
|
||||
)
|
||||
)
|
||||
|
||||
// Added so that the try! macro below can refer to cargo::util, while
|
||||
// other external importers of this macro can use it as well.
|
||||
//
|
||||
// "Hygiene strikes again" - @acrichton
|
||||
mod cargo {
|
||||
pub use super::util;
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! try (
|
||||
($expr:expr) => ({
|
||||
use util::CargoError;
|
||||
use cargo::util::CargoError;
|
||||
match $expr.map_err(|err| err.to_error()) {
|
||||
Ok(val) => val,
|
||||
Err(err) => return Err(err)
|
||||
|
@ -24,13 +24,15 @@
|
||||
|
||||
use std::os;
|
||||
use util::config::{Config, ConfigValue};
|
||||
use core::{MultiShell, Source, SourceId, PackageSet, resolver};
|
||||
use core::{MultiShell, Source, SourceId, PackageSet, Target, resolver};
|
||||
use core::registry::PackageRegistry;
|
||||
use ops;
|
||||
use sources::{PathSource};
|
||||
use util::{CargoResult, Wrap, config, internal, human};
|
||||
|
||||
pub fn compile(manifest_path: &Path, update: bool, shell: &mut MultiShell) -> CargoResult<()> {
|
||||
pub fn compile(manifest_path: &Path, update: bool,
|
||||
env: &str, shell: &mut MultiShell) -> CargoResult<()>
|
||||
{
|
||||
log!(4, "compile; manifest-path={}", manifest_path.display());
|
||||
|
||||
let mut source = PathSource::for_path(&manifest_path.dir_path());
|
||||
@ -60,8 +62,13 @@ pub fn compile(manifest_path: &Path, update: bool, shell: &mut MultiShell) -> Ca
|
||||
|
||||
debug!("packages={}", packages);
|
||||
|
||||
let targets = package.get_targets().iter().filter(|target| {
|
||||
target.get_profile().get_env() == env
|
||||
}).collect::<Vec<&Target>>();
|
||||
|
||||
let mut config = try!(Config::new(shell, update));
|
||||
try!(ops::compile_packages(&package, &PackageSet::new(packages.as_slice()), &mut config));
|
||||
try!(ops::compile_targets(targets.as_slice(), &package,
|
||||
&PackageSet::new(packages.as_slice()), &mut config));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ use std::os::args;
|
||||
use std::io;
|
||||
use std::io::{File, IoError};
|
||||
use std::str;
|
||||
use std::hash::sip::SipHasher;
|
||||
use std::hash::Hasher;
|
||||
|
||||
use core::{Package, PackageSet, Target};
|
||||
use util;
|
||||
@ -19,13 +21,14 @@ struct Context<'a, 'b> {
|
||||
config: &'b mut Config<'b>
|
||||
}
|
||||
|
||||
pub fn compile_packages<'a>(pkg: &Package, deps: &PackageSet,
|
||||
config: &'a mut Config<'a>) -> CargoResult<()> {
|
||||
pub fn compile_targets<'a>(targets: &[&Target], pkg: &Package, deps: &PackageSet,
|
||||
config: &'a mut Config<'a>) -> CargoResult<()> {
|
||||
|
||||
debug!("compile_packages; pkg={}; deps={}", pkg, deps);
|
||||
debug!("compile_targets; targets={}; pkg={}; deps={}", targets, pkg, deps);
|
||||
|
||||
let target_dir = pkg.get_absolute_target_dir();
|
||||
let deps_target_dir = target_dir.join("deps");
|
||||
let tests_target_dir = target_dir.join("tests");
|
||||
|
||||
let output = try!(util::process("rustc").arg("-v").exec_with_output());
|
||||
let rustc_version = str::from_utf8(output.output.as_slice()).unwrap();
|
||||
@ -41,6 +44,10 @@ pub fn compile_packages<'a>(pkg: &Package, deps: &PackageSet,
|
||||
internal(format!("Couldn't create the directory for dependencies for {} at {}",
|
||||
pkg.get_name(), deps_target_dir.display()))));
|
||||
|
||||
try!(mk_target(&tests_target_dir).chain_error(||
|
||||
internal(format!("Couldn't create the directory for tests for {} at {}",
|
||||
pkg.get_name(), tests_target_dir.display()))));
|
||||
|
||||
let mut cx = Context {
|
||||
dest: &deps_target_dir,
|
||||
deps_dir: &deps_target_dir,
|
||||
@ -52,19 +59,29 @@ pub fn compile_packages<'a>(pkg: &Package, deps: &PackageSet,
|
||||
|
||||
// Traverse the dependencies in topological order
|
||||
for dep in try!(topsort(deps)).iter() {
|
||||
try!(compile_pkg(dep, &mut cx));
|
||||
let targets = dep.get_targets().iter().filter(|target| {
|
||||
// Only compile lib targets for dependencies
|
||||
target.is_lib() && target.get_profile().is_compile()
|
||||
}).collect::<Vec<&Target>>();
|
||||
|
||||
try!(compile(targets.as_slice(), dep, &mut cx));
|
||||
}
|
||||
|
||||
cx.primary = true;
|
||||
cx.dest = &target_dir;
|
||||
try!(compile_pkg(pkg, &mut cx));
|
||||
|
||||
try!(compile(targets, pkg, &mut cx));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn compile_pkg(pkg: &Package, cx: &mut Context) -> CargoResult<()> {
|
||||
fn compile(targets: &[&Target], pkg: &Package, cx: &mut Context) -> CargoResult<()> {
|
||||
debug!("compile_pkg; pkg={}; targets={}", pkg, pkg.get_targets());
|
||||
|
||||
if targets.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// First check to see if this package is fresh.
|
||||
//
|
||||
// Note that we're compiling things in topological order, so if nothing has
|
||||
@ -74,10 +91,12 @@ fn compile_pkg(pkg: &Package, cx: &mut Context) -> CargoResult<()> {
|
||||
//
|
||||
// This is not quite accurate, we should only trigger forceful
|
||||
// recompilations for downstream dependencies of ourselves, not everyone
|
||||
// compiled afterwards.
|
||||
// compiled afterwards.a
|
||||
//
|
||||
// TODO: Figure out how this works with targets
|
||||
let fingerprint_loc = cx.dest.join(format!(".{}.fingerprint",
|
||||
pkg.get_name()));
|
||||
let (is_fresh, fingerprint) = try!(is_fresh(pkg, &fingerprint_loc, cx));
|
||||
let (is_fresh, fingerprint) = try!(is_fresh(pkg, &fingerprint_loc, cx, targets));
|
||||
if !cx.compiled_anything && is_fresh {
|
||||
try!(cx.config.shell().status("Fresh", pkg));
|
||||
return Ok(())
|
||||
@ -88,6 +107,7 @@ fn compile_pkg(pkg: &Package, cx: &mut Context) -> CargoResult<()> {
|
||||
// command if one is present.
|
||||
try!(cx.config.shell().status("Compiling", pkg));
|
||||
|
||||
// TODO: Should this be on the target or the package?
|
||||
match pkg.get_manifest().get_build() {
|
||||
Some(cmd) => try!(compile_custom(pkg, cmd, cx)),
|
||||
None => {}
|
||||
@ -95,11 +115,8 @@ fn compile_pkg(pkg: &Package, cx: &mut Context) -> CargoResult<()> {
|
||||
|
||||
// After the custom command has run, execute rustc for all targets of our
|
||||
// package.
|
||||
for target in pkg.get_targets().iter() {
|
||||
// Only compile lib targets for dependencies
|
||||
if cx.primary || target.is_lib() {
|
||||
try!(rustc(&pkg.get_root(), target, cx))
|
||||
}
|
||||
for &target in targets.iter() {
|
||||
try!(rustc(&pkg.get_root(), target, cx));
|
||||
}
|
||||
|
||||
// Now that everything has successfully compiled, write our new fingerprint
|
||||
@ -111,13 +128,18 @@ fn compile_pkg(pkg: &Package, cx: &mut Context) -> CargoResult<()> {
|
||||
}
|
||||
|
||||
fn is_fresh(dep: &Package, loc: &Path,
|
||||
cx: &mut Context) -> CargoResult<(bool, String)> {
|
||||
let new_fingerprint = format!("{}{}", cx.rustc_version,
|
||||
cx: &mut Context, targets: &[&Target]) -> CargoResult<(bool, String)>
|
||||
{
|
||||
let new_pkg_fingerprint = format!("{}{}", cx.rustc_version,
|
||||
try!(dep.get_fingerprint(cx.config)));
|
||||
|
||||
let new_fingerprint = fingerprint(new_pkg_fingerprint, hash_targets(targets));
|
||||
|
||||
let mut file = match File::open(loc) {
|
||||
Ok(file) => file,
|
||||
Err(..) => return Ok((false, new_fingerprint)),
|
||||
};
|
||||
|
||||
let old_fingerprint = try!(file.read_to_str());
|
||||
|
||||
log!(5, "old fingerprint: {}", old_fingerprint);
|
||||
@ -126,6 +148,17 @@ fn is_fresh(dep: &Package, loc: &Path,
|
||||
Ok((old_fingerprint == new_fingerprint, new_fingerprint))
|
||||
}
|
||||
|
||||
fn hash_targets(targets: &[&Target]) -> u64 {
|
||||
let hasher = SipHasher::new_with_keys(0,0);
|
||||
let targets = targets.iter().map(|t| (*t).clone()).collect::<Vec<Target>>();
|
||||
hasher.hash(&targets)
|
||||
}
|
||||
|
||||
fn fingerprint(package: String, profiles: u64) -> String {
|
||||
let hasher = SipHasher::new_with_keys(0,0);
|
||||
util::to_hex(hasher.hash(&(package, profiles)))
|
||||
}
|
||||
|
||||
fn mk_target(target: &Path) -> Result<(), IoError> {
|
||||
io::fs::mkdir_recursive(target, io::UserRWX)
|
||||
}
|
||||
@ -170,6 +203,7 @@ fn prepare_rustc(root: &Path, target: &Target, crate_types: Vec<&str>,
|
||||
build_base_args(&mut args, target, crate_types, cx);
|
||||
build_deps_args(&mut args, cx);
|
||||
|
||||
|
||||
util::process("rustc")
|
||||
.cwd(root.clone())
|
||||
.args(args.as_slice())
|
||||
@ -184,8 +218,16 @@ fn build_base_args(into: &mut Args, target: &Target, crate_types: Vec<&str>,
|
||||
into.push("--crate-type".to_str());
|
||||
into.push(crate_type.to_str());
|
||||
}
|
||||
|
||||
let mut out = cx.dest.clone();
|
||||
|
||||
if target.get_profile().is_test() {
|
||||
into.push("--test".to_str());
|
||||
out = out.join("tests");
|
||||
}
|
||||
|
||||
into.push("--out-dir".to_str());
|
||||
into.push(cx.dest.display().to_str());
|
||||
into.push(out.display().to_str());
|
||||
}
|
||||
|
||||
fn build_deps_args(dst: &mut Args, cx: &Context) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
pub use self::cargo_compile::compile;
|
||||
pub use self::cargo_read_manifest::{read_manifest,read_package,read_packages};
|
||||
pub use self::cargo_rustc::compile_packages;
|
||||
pub use self::cargo_rustc::compile_targets;
|
||||
|
||||
mod cargo_compile;
|
||||
mod cargo_read_manifest;
|
||||
|
@ -2,13 +2,11 @@ use std::fmt::{Show,Formatter};
|
||||
use std::fmt;
|
||||
use std::hash::Hasher;
|
||||
use std::hash::sip::SipHasher;
|
||||
use std::io::MemWriter;
|
||||
use std::str;
|
||||
use serialize::hex::ToHex;
|
||||
|
||||
use core::source::{Source, SourceId, GitKind, Location, Remote, Local};
|
||||
use core::{Package,PackageId,Summary};
|
||||
use util::{CargoResult,Config};
|
||||
use util::{CargoResult, Config, to_hex};
|
||||
use sources::PathSource;
|
||||
use sources::git::utils::{GitReference,GitRemote,Master,Other};
|
||||
|
||||
@ -81,12 +79,6 @@ fn ident(location: &Location) -> String {
|
||||
format!("{}-{}", ident, to_hex(hasher.hash(&location.to_str())))
|
||||
}
|
||||
|
||||
fn to_hex(num: u64) -> String {
|
||||
let mut writer = MemWriter::with_capacity(8);
|
||||
writer.write_le_u64(num).unwrap(); // this should never fail
|
||||
writer.get_ref().to_hex()
|
||||
}
|
||||
|
||||
impl<'a, 'b> Show for GitSource<'a, 'b> {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
try!(write!(f, "git repo at {}", self.remote.get_location()));
|
||||
|
10
src/cargo/util/hex.rs
Normal file
10
src/cargo/util/hex.rs
Normal file
@ -0,0 +1,10 @@
|
||||
use std::io::MemWriter;
|
||||
|
||||
use serialize::hex::ToHex;
|
||||
|
||||
pub fn to_hex(num: u64) -> String {
|
||||
let mut writer = MemWriter::with_capacity(8);
|
||||
writer.write_le_u64(num).unwrap(); // this should never fail
|
||||
writer.get_ref().to_hex()
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ pub use self::errors::{CargoResult, CargoError, BoxError, ChainError, CliResult}
|
||||
pub use self::errors::{CliError, FromError, ProcessError};
|
||||
pub use self::errors::{process_error, internal_error, internal, human};
|
||||
pub use self::paths::realpath;
|
||||
pub use self::hex::to_hex;
|
||||
|
||||
pub mod graph;
|
||||
pub mod process_builder;
|
||||
@ -14,3 +15,4 @@ pub mod result;
|
||||
pub mod toml;
|
||||
pub mod paths;
|
||||
pub mod errors;
|
||||
pub mod hex;
|
||||
|
@ -51,7 +51,7 @@ impl ProcessBuilder {
|
||||
|
||||
pub fn extra_path(mut self, path: Path) -> ProcessBuilder {
|
||||
// For now, just convert to a string, but we should do something better
|
||||
self.path.push(path.display().to_str());
|
||||
self.path.unshift(path.display().to_str());
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ use toml;
|
||||
use url;
|
||||
|
||||
use core::{SourceId, GitKind};
|
||||
use core::manifest::{LibKind, Lib};
|
||||
use core::manifest::{LibKind, Lib, Profile};
|
||||
use core::{Summary, Manifest, Target, Dependency, PackageId};
|
||||
use core::source::{Location, Local, Remote};
|
||||
use util::{CargoResult, Require, human};
|
||||
@ -66,6 +66,7 @@ pub enum TomlDependency {
|
||||
DetailedDep(DetailedTomlDependency)
|
||||
}
|
||||
|
||||
|
||||
#[deriving(Encodable,Decodable,PartialEq,Clone,Show)]
|
||||
pub struct DetailedTomlDependency {
|
||||
version: Option<String>,
|
||||
@ -184,28 +185,46 @@ impl TomlManifest {
|
||||
struct TomlTarget {
|
||||
name: String,
|
||||
crate_type: Option<Vec<String>>,
|
||||
path: Option<String>
|
||||
path: Option<String>,
|
||||
test: Option<bool>
|
||||
}
|
||||
|
||||
fn normalize(lib: Option<&[TomlLibTarget]>,
|
||||
bin: Option<&[TomlBinTarget]>) -> Vec<Target> {
|
||||
log!(4, "normalizing toml targets; lib={}; bin={}", lib, bin);
|
||||
|
||||
fn target_profiles(target: &TomlTarget) -> Vec<Profile> {
|
||||
let mut ret = vec!(Profile::default("compile"));
|
||||
|
||||
match target.test {
|
||||
Some(true) | None => ret.push(Profile::default("test").test(true)),
|
||||
_ => {}
|
||||
};
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
fn lib_targets(dst: &mut Vec<Target>, libs: &[TomlLibTarget]) {
|
||||
let l = &libs[0];
|
||||
let path = l.path.clone().unwrap_or_else(|| format!("src/{}.rs", l.name));
|
||||
let crate_types = l.crate_type.clone().and_then(|kinds| {
|
||||
LibKind::from_strs(kinds).ok()
|
||||
}).unwrap_or_else(|| vec!(Lib));
|
||||
dst.push(Target::lib_target(l.name.as_slice(), crate_types,
|
||||
&Path::new(path)));
|
||||
|
||||
for profile in target_profiles(l).iter() {
|
||||
dst.push(Target::lib_target(l.name.as_slice(), crate_types.clone(),
|
||||
&Path::new(path.as_slice()), profile));
|
||||
}
|
||||
}
|
||||
|
||||
fn bin_targets(dst: &mut Vec<Target>, bins: &[TomlBinTarget],
|
||||
default: |&TomlBinTarget| -> String) {
|
||||
for bin in bins.iter() {
|
||||
let path = bin.path.clone().unwrap_or_else(|| default(bin));
|
||||
dst.push(Target::bin_target(bin.name.as_slice(), &Path::new(path)));
|
||||
|
||||
for profile in target_profiles(bin).iter() {
|
||||
dst.push(Target::bin_target(bin.name.as_slice(), &Path::new(path.as_slice()), profile));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -357,3 +357,21 @@ impl<T> Tap for T {
|
||||
pub fn escape_path(p: &Path) -> String {
|
||||
p.display().to_str().as_slice().replace("\\", "\\\\")
|
||||
}
|
||||
|
||||
pub fn basic_bin_manifest(name: &str) -> String {
|
||||
format!(r#"
|
||||
[project]
|
||||
|
||||
name = "{}"
|
||||
version = "0.5.0"
|
||||
authors = ["wycats@example.com"]
|
||||
|
||||
[[bin]]
|
||||
|
||||
name = "{}"
|
||||
"#, name, name)
|
||||
}
|
||||
|
||||
pub static COMPILING: &'static str = " Compiling";
|
||||
pub static FRESH: &'static str = " Fresh";
|
||||
pub static UPDATING: &'static str = " Updating";
|
||||
|
@ -2,7 +2,8 @@ use std::io::fs;
|
||||
use std::os;
|
||||
use std::path;
|
||||
|
||||
use support::{ResultTest, project, execs, main_file, escape_path};
|
||||
use support::{ResultTest, project, execs, main_file, escape_path, basic_bin_manifest};
|
||||
use support::COMPILING;
|
||||
use hamcrest::{assert_that, existing_file};
|
||||
use cargo;
|
||||
use cargo::util::{process, realpath};
|
||||
@ -10,22 +11,6 @@ use cargo::util::{process, realpath};
|
||||
fn setup() {
|
||||
}
|
||||
|
||||
static COMPILING: &'static str = " Compiling";
|
||||
|
||||
fn basic_bin_manifest(name: &str) -> String {
|
||||
format!(r#"
|
||||
[project]
|
||||
|
||||
name = "{}"
|
||||
version = "0.5.0"
|
||||
authors = ["wycats@example.com"]
|
||||
|
||||
[[bin]]
|
||||
|
||||
name = "{}"
|
||||
"#, name, name)
|
||||
}
|
||||
|
||||
test!(cargo_compile_simple {
|
||||
let p = project("foo")
|
||||
.file("Cargo.toml", basic_bin_manifest("foo").as_slice())
|
||||
|
@ -2,14 +2,11 @@ use std::io::File;
|
||||
|
||||
use support::{ProjectBuilder, ResultTest, project, execs, main_file, paths};
|
||||
use support::{escape_path, cargo_dir};
|
||||
use support::{COMPILING, FRESH, UPDATING};
|
||||
use hamcrest::{assert_that,existing_file};
|
||||
use cargo;
|
||||
use cargo::util::{ProcessError, process};
|
||||
|
||||
static COMPILING: &'static str = " Compiling";
|
||||
static FRESH: &'static str = " Fresh";
|
||||
static UPDATING: &'static str = " Updating";
|
||||
|
||||
fn setup() {
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ use std::io::File;
|
||||
use std::io::timer;
|
||||
|
||||
use support::{ResultTest, project, execs, main_file, escape_path, cargo_dir};
|
||||
use support::{COMPILING, FRESH};
|
||||
use hamcrest::{assert_that, existing_file};
|
||||
use cargo;
|
||||
use cargo::util::{process};
|
||||
@ -9,9 +10,6 @@ use cargo::util::{process};
|
||||
fn setup() {
|
||||
}
|
||||
|
||||
static COMPILING: &'static str = " Compiling";
|
||||
static FRESH: &'static str = " Fresh";
|
||||
|
||||
test!(cargo_compile_with_nested_deps_shorthand {
|
||||
let p = project("foo")
|
||||
.file("Cargo.toml", r#"
|
||||
|
40
tests/test_cargo_test.rs
Normal file
40
tests/test_cargo_test.rs
Normal file
@ -0,0 +1,40 @@
|
||||
use support::{project, execs, basic_bin_manifest, COMPILING};
|
||||
use hamcrest::{assert_that, existing_file};
|
||||
use cargo::util::process;
|
||||
|
||||
fn setup() {}
|
||||
|
||||
test!(cargo_test_simple {
|
||||
let p = project("foo")
|
||||
.file("Cargo.toml", basic_bin_manifest("foo").as_slice())
|
||||
.file("src/foo.rs", r#"
|
||||
fn hello() -> &'static str {
|
||||
"hello"
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
println!("{}", hello())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hello() {
|
||||
assert_eq!(hello(), "hello")
|
||||
}"#);
|
||||
|
||||
assert_that(p.cargo_process("cargo-build"), execs());
|
||||
assert_that(&p.bin("foo"), existing_file());
|
||||
|
||||
assert_that(
|
||||
process(p.bin("foo")),
|
||||
execs().with_stdout("hello\n"));
|
||||
|
||||
assert_that(p.cargo_process("cargo-test"),
|
||||
execs().with_stdout(format!("{} foo v0.5.0 (file:{})\n\n\
|
||||
running 1 test\n\
|
||||
test test_hello ... ok\n\n\
|
||||
test result: ok. 1 passed; 0 failed; \
|
||||
0 ignored; 0 measured\n\n",
|
||||
COMPILING, p.root().display())));
|
||||
|
||||
assert_that(&p.bin("tests/foo"), existing_file());
|
||||
})
|
@ -23,4 +23,5 @@ macro_rules! test(
|
||||
mod test_cargo_compile;
|
||||
mod test_cargo_compile_git_deps;
|
||||
mod test_cargo_compile_path_deps;
|
||||
mod test_cargo_test;
|
||||
mod test_shell;
|
||||
|
Loading…
x
Reference in New Issue
Block a user