cargo/tests/testsuite/cache_messages.rs
Alex Crichton 9115b2c326 Extract support directory to its own crate
Extract out all our test support code to its own standalone crate so it
can be shared between multiple test suites if necessary.
2019-09-16 11:47:09 -07:00

383 lines
11 KiB
Rust

use cargo_test_support::{clippy_is_available, is_nightly, process, project, registry::Package};
use std::path::Path;
fn as_str(bytes: &[u8]) -> &str {
std::str::from_utf8(bytes).expect("valid utf-8")
}
#[cargo_test]
fn simple() {
if !is_nightly() {
// --json-rendered is unstable
return;
}
// A simple example that generates two warnings (unused functions).
let p = project()
.file(
"src/lib.rs",
"
fn a() {}
fn b() {}
",
)
.build();
let agnostic_path = Path::new("src").join("lib.rs");
let agnostic_path_s = agnostic_path.to_str().unwrap();
// Capture what rustc actually emits. This is done to avoid relying on the
// exact message formatting in rustc.
let rustc_output = process("rustc")
.cwd(p.root())
.args(&["--crate-type=lib", agnostic_path_s])
.exec_with_output()
.expect("rustc to run");
assert!(rustc_output.stdout.is_empty());
assert!(rustc_output.status.success());
// -q so the output is the same as rustc (no "Compiling" or "Finished").
let cargo_output1 = p
.cargo("check -Zcache-messages -q --color=never")
.masquerade_as_nightly_cargo()
.exec_with_output()
.expect("cargo to run");
assert_eq!(as_str(&rustc_output.stderr), as_str(&cargo_output1.stderr));
assert!(cargo_output1.stdout.is_empty());
// Check that the cached version is exactly the same.
let cargo_output2 = p
.cargo("check -Zcache-messages -q")
.masquerade_as_nightly_cargo()
.exec_with_output()
.expect("cargo to run");
assert_eq!(as_str(&rustc_output.stderr), as_str(&cargo_output2.stderr));
assert!(cargo_output2.stdout.is_empty());
}
// same as `simple`, except everything is using the short format
#[cargo_test]
fn simple_short() {
if !is_nightly() {
// --json-rendered is unstable
return;
}
let p = project()
.file(
"src/lib.rs",
"
fn a() {}
fn b() {}
",
)
.build();
let agnostic_path = Path::new("src").join("lib.rs");
let agnostic_path_s = agnostic_path.to_str().unwrap();
let rustc_output = process("rustc")
.cwd(p.root())
.args(&["--crate-type=lib", agnostic_path_s, "--error-format=short"])
.exec_with_output()
.expect("rustc to run");
assert!(rustc_output.stdout.is_empty());
assert!(rustc_output.status.success());
let cargo_output1 = p
.cargo("check -Zcache-messages -q --color=never --message-format=short")
.masquerade_as_nightly_cargo()
.exec_with_output()
.expect("cargo to run");
assert_eq!(as_str(&rustc_output.stderr), as_str(&cargo_output1.stderr));
// assert!(cargo_output1.stdout.is_empty());
let cargo_output2 = p
.cargo("check -Zcache-messages -q --message-format=short")
.masquerade_as_nightly_cargo()
.exec_with_output()
.expect("cargo to run");
println!("{}", String::from_utf8_lossy(&cargo_output2.stdout));
assert_eq!(as_str(&rustc_output.stderr), as_str(&cargo_output2.stderr));
assert!(cargo_output2.stdout.is_empty());
}
#[cargo_test]
fn color() {
if !is_nightly() {
// --json-rendered is unstable
return;
}
// Check enabling/disabling color.
let p = project().file("src/lib.rs", "fn a() {}").build();
let agnostic_path = Path::new("src").join("lib.rs");
let agnostic_path_s = agnostic_path.to_str().unwrap();
// Capture the original color output.
let rustc_output = process("rustc")
.cwd(p.root())
.args(&["--crate-type=lib", agnostic_path_s, "--color=always"])
.exec_with_output()
.expect("rustc to run");
assert!(rustc_output.status.success());
let rustc_color = as_str(&rustc_output.stderr);
assert!(rustc_color.contains("\x1b["));
// Capture the original non-color output.
let rustc_output = process("rustc")
.cwd(p.root())
.args(&["--crate-type=lib", agnostic_path_s])
.exec_with_output()
.expect("rustc to run");
let rustc_nocolor = as_str(&rustc_output.stderr);
assert!(!rustc_nocolor.contains("\x1b["));
// First pass, non-cached, with color, should be the same.
let cargo_output1 = p
.cargo("check -Zcache-messages -q --color=always")
.masquerade_as_nightly_cargo()
.exec_with_output()
.expect("cargo to run");
assert_eq!(rustc_color, as_str(&cargo_output1.stderr));
// Replay cached, with color.
let cargo_output2 = p
.cargo("check -Zcache-messages -q --color=always")
.masquerade_as_nightly_cargo()
.exec_with_output()
.expect("cargo to run");
assert_eq!(rustc_color, as_str(&cargo_output2.stderr));
// Replay cached, no color.
let cargo_output_nocolor = p
.cargo("check -Zcache-messages -q --color=never")
.masquerade_as_nightly_cargo()
.exec_with_output()
.expect("cargo to run");
assert_eq!(rustc_nocolor, as_str(&cargo_output_nocolor.stderr));
}
#[cargo_test]
fn cached_as_json() {
if !is_nightly() {
// --json-rendered is unstable
return;
}
// Check that cached JSON output is the same.
let p = project().file("src/lib.rs", "fn a() {}").build();
// Grab the non-cached output, feature disabled.
// NOTE: When stabilizing, this will need to be redone.
let cargo_output = p
.cargo("check --message-format=json")
.exec_with_output()
.expect("cargo to run");
assert!(cargo_output.status.success());
let orig_cargo_out = as_str(&cargo_output.stdout);
assert!(orig_cargo_out.contains("compiler-message"));
p.cargo("clean").run();
// Check JSON output, not fresh.
let cargo_output1 = p
.cargo("check -Zcache-messages --message-format=json")
.masquerade_as_nightly_cargo()
.exec_with_output()
.expect("cargo to run");
assert_eq!(as_str(&cargo_output1.stdout), orig_cargo_out);
// Check JSON output, fresh.
let cargo_output2 = p
.cargo("check -Zcache-messages --message-format=json")
.masquerade_as_nightly_cargo()
.exec_with_output()
.expect("cargo to run");
// The only difference should be this field.
let fix_fresh = as_str(&cargo_output2.stdout).replace("\"fresh\":true", "\"fresh\":false");
assert_eq!(fix_fresh, orig_cargo_out);
}
#[cargo_test]
fn clears_cache_after_fix() {
if !is_nightly() {
// --json-rendered is unstable
return;
}
// Make sure the cache is invalidated when there is no output.
let p = project().file("src/lib.rs", "fn asdf() {}").build();
// Fill the cache.
p.cargo("check -Zcache-messages")
.masquerade_as_nightly_cargo()
.with_stderr_contains("[..]asdf[..]")
.run();
let cpath = p
.glob("target/debug/.fingerprint/foo-*/output")
.next()
.unwrap()
.unwrap();
assert!(std::fs::read_to_string(cpath).unwrap().contains("asdf"));
// Fix it.
p.change_file("src/lib.rs", "");
p.cargo("check -Zcache-messages")
.masquerade_as_nightly_cargo()
.with_stdout("")
.with_stderr(
"\
[CHECKING] foo [..]
[FINISHED] [..]
",
)
.run();
assert_eq!(p.glob("target/debug/.fingerprint/foo-*/output").count(), 0);
// And again, check the cache is correct.
p.cargo("check -Zcache-messages")
.masquerade_as_nightly_cargo()
.with_stdout("")
.with_stderr(
"\
[FINISHED] [..]
",
)
.run();
}
#[cargo_test]
fn rustdoc() {
if !is_nightly() {
// --json-rendered is unstable
return;
}
// Create a warning in rustdoc.
let p = project()
.file(
"src/lib.rs",
"
#![warn(private_doc_tests)]
/// asdf
/// ```
/// let x = 1;
/// ```
fn f() {}
",
)
.build();
// At this time, rustdoc does not support --json-rendered=termcolor. So it
// will always be uncolored with -Zcache-messages.
let rustdoc_output = p
.cargo("doc -Zcache-messages -q")
.masquerade_as_nightly_cargo()
.exec_with_output()
.expect("rustdoc to run");
assert!(rustdoc_output.status.success());
let rustdoc_stderr = as_str(&rustdoc_output.stderr);
assert!(rustdoc_stderr.contains("private"));
// Invert this when --json-rendered is added.
assert!(!rustdoc_stderr.contains("\x1b["));
assert_eq!(p.glob("target/debug/.fingerprint/foo-*/output").count(), 1);
// Check the cached output.
let rustdoc_output = p
.cargo("doc -Zcache-messages -q")
.masquerade_as_nightly_cargo()
.exec_with_output()
.expect("rustdoc to run");
assert_eq!(as_str(&rustdoc_output.stderr), rustdoc_stderr);
}
#[cargo_test]
fn fix() {
if !is_nightly() {
// --json-rendered is unstable
return;
}
// Make sure `fix` is not broken by caching.
let p = project().file("src/lib.rs", "pub fn try() {}").build();
p.cargo("fix --edition --allow-no-vcs -Zcache-messages")
.masquerade_as_nightly_cargo()
.run();
assert_eq!(p.read_file("src/lib.rs"), "pub fn r#try() {}");
}
#[cargo_test]
fn clippy() {
if !is_nightly() {
// --json-rendered is unstable
eprintln!("skipping test: requires nightly");
return;
}
if !clippy_is_available() {
return;
}
// Caching clippy output.
// This is just a random clippy lint (assertions_on_constants) that
// hopefully won't change much in the future.
let p = project()
.file("src/lib.rs", "pub fn f() { assert!(true); }")
.build();
p.cargo("clippy-preview -Zunstable-options -Zcache-messages")
.masquerade_as_nightly_cargo()
.with_stderr_contains("[..]assert!(true)[..]")
.run();
// Again, reading from the cache.
p.cargo("clippy-preview -Zunstable-options -Zcache-messages")
.masquerade_as_nightly_cargo()
.with_stderr_contains("[..]assert!(true)[..]")
.run();
// FIXME: Unfortunately clippy is sharing the same hash with check. This
// causes the cache to be reused when it shouldn't.
p.cargo("check -Zcache-messages")
.masquerade_as_nightly_cargo()
.with_stderr_contains("[..]assert!(true)[..]") // This should not be here.
.run();
}
#[cargo_test]
fn very_verbose() {
if !is_nightly() {
// --json-rendered is unstable
return;
}
// Handle cap-lints in dependencies.
Package::new("bar", "1.0.0")
.file("src/lib.rs", "fn not_used() {}")
.publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[dependencies]
bar = "1.0"
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("check -Zcache-messages -vv")
.masquerade_as_nightly_cargo()
.with_stderr_contains("[..]not_used[..]")
.run();
p.cargo("check -Zcache-messages")
.masquerade_as_nightly_cargo()
.with_stderr("[FINISHED] [..]")
.run();
p.cargo("check -Zcache-messages -vv")
.masquerade_as_nightly_cargo()
.with_stderr_contains("[..]not_used[..]")
.run();
}