Skip to content

Commit

Permalink
Auto merge of #3426 - nrc:check-fix-2, r=alexcrichton
Browse files Browse the repository at this point in the history
Test for #3419

Based on top of #3425.

I'm not sure if this is an acceptable test because it downloads rustc-serialize.

r? @alexcrichton
  • Loading branch information
bors committed Dec 26, 2016
2 parents bf559b9 + 129ce53 commit 836c22d
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 41 deletions.
25 changes: 13 additions & 12 deletions src/cargo/ops/cargo_rustc/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,9 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
kind: Kind)
-> CargoResult<()> {
let rustflags = env_args(self.config,
&self.build_config,
kind,
"RUSTFLAGS")?;
&self.build_config,
kind,
"RUSTFLAGS")?;
let mut process = self.config.rustc()?.process();
process.arg("-")
.arg("--crate-name").arg("___")
Expand Down Expand Up @@ -613,17 +613,10 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
match self.get_package(id) {
Ok(pkg) => {
pkg.targets().iter().find(|t| t.is_lib()).map(|t| {
let profile = if unit.profile.check &&
!t.is_custom_build()
&& !t.for_host() {
&self.profiles.check
} else {
self.lib_profile()
};
let unit = Unit {
pkg: pkg,
target: t,
profile: profile,
profile: self.lib_or_check_profile(unit, t),
kind: unit.kind.for_target(t),
};
Ok(unit)
Expand Down Expand Up @@ -780,7 +773,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
Unit {
pkg: unit.pkg,
target: t,
profile: self.lib_profile(),
profile: self.lib_or_check_profile(unit, t),
kind: unit.kind.for_target(t),
}
})
Expand Down Expand Up @@ -848,6 +841,14 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
}
}

pub fn lib_or_check_profile(&self, unit: &Unit, target: &Target) -> &'a Profile {
if unit.profile.check && !target.is_custom_build() && !target.for_host() {
&self.profiles.check
} else {
self.lib_profile()
}
}

pub fn build_script_profile(&self, _pkg: &PackageId) -> &'a Profile {
// TODO: should build scripts always be built with the same library
// profile? How is this controlled at the CLI layer?
Expand Down
100 changes: 71 additions & 29 deletions tests/cargotest/support/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,8 @@ pub struct Execs {
expect_exit_code: Option<i32>,
expect_stdout_contains: Vec<String>,
expect_stderr_contains: Vec<String>,
expect_stdout_not_contains: Vec<String>,
expect_stderr_not_contains: Vec<String>,
expect_json: Option<Vec<Json>>,
}

Expand Down Expand Up @@ -292,6 +294,16 @@ impl Execs {
self
}

pub fn with_stdout_does_not_contain<S: ToString>(mut self, expected: S) -> Execs {
self.expect_stdout_not_contains.push(expected.to_string());
self
}

pub fn with_stderr_does_not_contain<S: ToString>(mut self, expected: S) -> Execs {
self.expect_stderr_not_contains.push(expected.to_string());
self
}

pub fn with_json(mut self, expected: &str) -> Execs {
self.expect_json = Some(expected.split("\n\n").map(|obj| {
Json::from_str(obj).unwrap()
Expand Down Expand Up @@ -321,14 +333,22 @@ impl Execs {

fn match_stdout(&self, actual: &Output) -> ham::MatchResult {
self.match_std(self.expect_stdout.as_ref(), &actual.stdout,
"stdout", &actual.stderr, false)?;
"stdout", &actual.stderr, MatchKind::Exact)?;
for expect in self.expect_stdout_contains.iter() {
self.match_std(Some(expect), &actual.stdout, "stdout",
&actual.stderr, true)?;
&actual.stderr, MatchKind::Partial)?;
}
for expect in self.expect_stderr_contains.iter() {
self.match_std(Some(expect), &actual.stderr, "stderr",
&actual.stdout, true)?;
&actual.stdout, MatchKind::Partial)?;
}
for expect in self.expect_stdout_not_contains.iter() {
self.match_std(Some(expect), &actual.stdout, "stdout",
&actual.stderr, MatchKind::NotPresent)?;
}
for expect in self.expect_stderr_not_contains.iter() {
self.match_std(Some(expect), &actual.stderr, "stderr",
&actual.stdout, MatchKind::NotPresent)?;
}

if let Some(ref objects) = self.expect_json {
Expand All @@ -349,12 +369,12 @@ impl Execs {

fn match_stderr(&self, actual: &Output) -> ham::MatchResult {
self.match_std(self.expect_stderr.as_ref(), &actual.stderr,
"stderr", &actual.stdout, false)
"stderr", &actual.stdout, MatchKind::Exact)
}

fn match_std(&self, expected: Option<&String>, actual: &[u8],
description: &str, extra: &[u8],
partial: bool) -> ham::MatchResult {
kind: MatchKind) -> ham::MatchResult {
let out = match expected {
Some(out) => out,
None => return ham::success(),
Expand All @@ -368,33 +388,46 @@ impl Execs {
let actual = actual.replace("\r", "");
let actual = actual.replace("\t", "<tab>");

let mut a = actual.lines();
let e = out.lines();

if partial {
let mut diffs = self.diff_lines(a.clone(), e.clone(), partial);
while let Some(..) = a.next() {
let a = self.diff_lines(a.clone(), e.clone(), partial);
if a.len() < diffs.len() {
diffs = a;
match kind {
MatchKind::Exact => {
let a = actual.lines();
let e = out.lines();

let diffs = self.diff_lines(a, e, false);
ham::expect(diffs.is_empty(),
format!("differences:\n\
{}\n\n\
other output:\n\
`{}`", diffs.join("\n"),
String::from_utf8_lossy(extra)))
}
MatchKind::Partial => {
let mut a = actual.lines();
let e = out.lines();

let mut diffs = self.diff_lines(a.clone(), e.clone(), true);
while let Some(..) = a.next() {
let a = self.diff_lines(a.clone(), e.clone(), true);
if a.len() < diffs.len() {
diffs = a;
}
}
ham::expect(diffs.is_empty(),
format!("expected to find:\n\
{}\n\n\
did not find in output:\n\
{}", out,
actual))
}
MatchKind::NotPresent => {
ham::expect(!actual.contains(out),
format!("expected not to find:\n\
{}\n\n\
but found in output:\n\
{}", out,
actual))
}
ham::expect(diffs.is_empty(),
format!("expected to find:\n\
{}\n\n\
did not find in output:\n\
{}", out,
actual))
} else {
let diffs = self.diff_lines(a, e, partial);
ham::expect(diffs.is_empty(),
format!("differences:\n\
{}\n\n\
other output:\n\
`{}`", diffs.join("\n"),
String::from_utf8_lossy(extra)))
}

}

fn match_json(&self, expected: &Json, line: &str) -> ham::MatchResult {
Expand Down Expand Up @@ -441,6 +474,13 @@ impl Execs {
}
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
enum MatchKind {
Exact,
Partial,
NotPresent,
}

pub fn lines_match(expected: &str, mut actual: &str) -> bool {
let expected = substitute_macros(expected);
for (i, part) in expected.split("[..]").enumerate() {
Expand Down Expand Up @@ -589,6 +629,8 @@ pub fn execs() -> Execs {
expect_exit_code: None,
expect_stdout_contains: Vec::new(),
expect_stderr_contains: Vec::new(),
expect_stdout_not_contains: Vec::new(),
expect_stderr_not_contains: Vec::new(),
expect_json: None,
}
}
Expand Down
81 changes: 81 additions & 0 deletions tests/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ extern crate hamcrest;

use cargotest::is_nightly;
use cargotest::support::{execs, project};
use cargotest::support::registry::Package;
use hamcrest::assert_that;

#[test]
Expand Down Expand Up @@ -219,3 +220,83 @@ fn build_check() {
assert_that(foo.cargo_process("check"),
execs().with_status(0));
}

// Checks that where a project has both a lib and a bin, the lib is only checked
// not built.
#[test]
fn issue_3418() {
if !is_nightly() {
return;
}

let foo = project("foo")
.file("Cargo.toml", r#"
[package]
name = "foo"
version = "0.1.0"
authors = []
[dependencies]
"#)
.file("src/lib.rs", "")
.file("src/main.rs", "fn main() {}");
foo.build();

assert_that(foo.cargo_process("check").arg("-v"),
execs().with_status(0)
.with_stderr_does_not_contain("--crate-type lib"));
}

// Some weirdness that seems to be caused by a crate being built as well as
// checked, but in this case with a proc macro too.
#[test]
fn issue_3419() {
if !is_nightly() {
return;
}

let foo = project("foo")
.file("Cargo.toml", r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
rustc-serialize = "*"
"#)
.file("src/lib.rs", r#"
extern crate rustc_serialize;
use rustc_serialize::Decodable;
pub fn take<T: Decodable>() {}
"#)
.file("src/main.rs", r#"
extern crate rustc_serialize;
extern crate foo;
#[derive(RustcDecodable)]
pub struct Foo;
fn main() {
foo::take::<Foo>();
}
"#);

Package::new("rustc-serialize", "1.0.0")
.file("src/lib.rs",
r#"pub trait Decodable: Sized {
fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error>;
}
pub trait Decoder {
type Error;
fn read_struct<T, F>(&mut self, s_name: &str, len: usize, f: F)
-> Result<T, Self::Error>
where F: FnOnce(&mut Self) -> Result<T, Self::Error>;
} "#).publish();

assert_that(foo.cargo_process("check"),
execs().with_status(0));
}

0 comments on commit 836c22d

Please sign in to comment.