blob: 871f459a593bbc5ec21c0a71c052b31db7ccdf66 [file] [log] [blame]
use support;
use std::str;
use std::fs::{self, File};
use std::io::Read;
use support::{is_nightly, rustc_host, ChannelChanger};
use support::{basic_manifest, basic_lib_manifest, execs, git, project, path2url};
use support::paths::CargoPathExt;
use support::registry::Package;
use support::hamcrest::{assert_that, existing_dir, existing_file, is_not};
use cargo::util::ProcessError;
use glob::glob;
#[test]
fn simple() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
build = "build.rs"
"#,
)
.file("build.rs", "fn main() {}")
.file("src/lib.rs", "pub fn foo() {}")
.build();
assert_that(
p.cargo("doc"),
execs().with_stderr(&format!(
"\
[..] foo v0.0.1 ({dir})
[..] foo v0.0.1 ({dir})
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
dir = path2url(p.root())
)),
);
assert_that(&p.root().join("target/doc"), existing_dir());
assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
}
#[test]
fn doc_no_libs() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[[bin]]
name = "foo"
doc = false
"#,
)
.file("src/main.rs", "bad code")
.build();
assert_that(p.cargo("doc"), execs());
}
#[test]
fn doc_twice() {
let p = project()
.file("src/lib.rs", "pub fn foo() {}")
.build();
assert_that(
p.cargo("doc"),
execs().with_stderr(&format!(
"\
[DOCUMENTING] foo v0.0.1 ({dir})
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
dir = path2url(p.root())
)),
);
assert_that(p.cargo("doc"), execs().with_stdout(""))
}
#[test]
fn doc_deps() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies.bar]
path = "bar"
"#,
)
.file("src/lib.rs", "extern crate bar; pub fn foo() {}")
.file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1"))
.file("bar/src/lib.rs", "pub fn bar() {}")
.build();
assert_that(
p.cargo("doc"),
execs().with_stderr(&format!(
"\
[..] bar v0.0.1 ({dir}/bar)
[..] bar v0.0.1 ({dir}/bar)
[DOCUMENTING] foo v0.0.1 ({dir})
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
dir = path2url(p.root())
)),
);
assert_that(&p.root().join("target/doc"), existing_dir());
assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
assert_that(&p.root().join("target/doc/bar/index.html"), existing_file());
// Verify that it only emits rmeta for the dependency.
assert_eq!(
glob(&p.root().join("target/debug/**/*.rlib").to_str().unwrap())
.unwrap()
.count(),
0
);
assert_eq!(
glob(&p.root().join("target/debug/deps/libbar-*.rmeta").to_str().unwrap())
.unwrap()
.count(),
1
);
assert_that(
p.cargo("doc")
.env("RUST_LOG", "cargo::ops::cargo_rustc::fingerprint"),
execs().with_stdout(""),
);
assert_that(&p.root().join("target/doc"), existing_dir());
assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
assert_that(&p.root().join("target/doc/bar/index.html"), existing_file());
}
#[test]
fn doc_no_deps() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies.bar]
path = "bar"
"#,
)
.file("src/lib.rs", "extern crate bar; pub fn foo() {}")
.file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1"))
.file("bar/src/lib.rs", "pub fn bar() {}")
.build();
assert_that(
p.cargo("doc").arg("--no-deps"),
execs().with_stderr(&format!(
"\
[CHECKING] bar v0.0.1 ({dir}/bar)
[DOCUMENTING] foo v0.0.1 ({dir})
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
dir = path2url(p.root())
)),
);
assert_that(&p.root().join("target/doc"), existing_dir());
assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
assert_that(
&p.root().join("target/doc/bar/index.html"),
is_not(existing_file()),
);
}
#[test]
fn doc_only_bin() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies.bar]
path = "bar"
"#,
)
.file("src/main.rs", "extern crate bar; pub fn foo() {}")
.file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1"))
.file("bar/src/lib.rs", "pub fn bar() {}")
.build();
assert_that(p.cargo("doc").arg("-v"), execs());
assert_that(&p.root().join("target/doc"), existing_dir());
assert_that(&p.root().join("target/doc/bar/index.html"), existing_file());
assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
}
#[test]
fn doc_multiple_targets_same_name_lib() {
let p = project()
.file(
"Cargo.toml",
r#"
[workspace]
members = ["foo", "bar"]
"#,
)
.file("foo/Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[lib]
name = "foo_lib"
"#,
)
.file("foo/src/lib.rs", "")
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
version = "0.1.0"
[lib]
name = "foo_lib"
"#,
)
.file("bar/src/lib.rs", "")
.build();
assert_that(
p.cargo("doc").arg("--all"),
execs()
.with_status(101)
.with_stderr_contains("[..] library `foo_lib` is specified [..]")
.with_stderr_contains("[..] `foo v0.1.0[..]` [..]")
.with_stderr_contains("[..] `bar v0.1.0[..]` [..]"),
);
}
#[test]
fn doc_multiple_targets_same_name() {
let p = project()
.file(
"Cargo.toml",
r#"
[workspace]
members = ["foo", "bar"]
"#,
)
.file(
"foo/Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[[bin]]
name = "foo_lib"
path = "src/foo_lib.rs"
"#,
)
.file("foo/src/foo_lib.rs", "")
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
version = "0.1.0"
[lib]
name = "foo_lib"
"#,
)
.file("bar/src/lib.rs", "")
.build();
let root = path2url(p.root());
assert_that(
p.cargo("doc").arg("--all"),
execs()
.with_stderr_contains(&format!("[DOCUMENTING] foo v0.1.0 ({}/foo)", root))
.with_stderr_contains(&format!("[DOCUMENTING] bar v0.1.0 ({}/bar)", root))
.with_stderr_contains("[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]"),
);
assert_that(&p.root().join("target/doc"), existing_dir());
let doc_file = p.root().join("target/doc/foo_lib/index.html");
assert_that(&doc_file, existing_file());
}
#[test]
fn doc_multiple_targets_same_name_bin() {
let p = project()
.file(
"Cargo.toml",
r#"
[workspace]
members = ["foo", "bar"]
"#,
)
.file(
"foo/Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[[bin]]
name = "foo-cli"
"#,
)
.file("foo/src/foo-cli.rs", "")
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
version = "0.1.0"
[[bin]]
name = "foo-cli"
"#,
)
.file("bar/src/foo-cli.rs", "")
.build();
assert_that(
p.cargo("doc").arg("--all"),
execs()
.with_status(101)
.with_stderr_contains("[..] binary `foo_cli` is specified [..]")
.with_stderr_contains("[..] `foo v0.1.0[..]` [..]")
.with_stderr_contains("[..] `bar v0.1.0[..]` [..]"),
);
}
#[test]
fn doc_multiple_targets_same_name_undoced() {
let p = project()
.file(
"Cargo.toml",
r#"
[workspace]
members = ["foo", "bar"]
"#,
)
.file(
"foo/Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[[bin]]
name = "foo-cli"
"#,
)
.file("foo/src/foo-cli.rs", "")
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
version = "0.1.0"
[[bin]]
name = "foo-cli"
doc = false
"#,
)
.file("bar/src/foo-cli.rs", "")
.build();
assert_that(p.cargo("doc").arg("--all"), execs());
}
#[test]
fn doc_lib_bin_same_name_documents_lib() {
let p = project()
.file(
"src/main.rs",
r#"
//! Binary documentation
extern crate foo;
fn main() {
foo::foo();
}
"#,
)
.file(
"src/lib.rs",
r#"
//! Library documentation
pub fn foo() {}
"#,
)
.build();
assert_that(
p.cargo("doc"),
execs().with_stderr(&format!(
"\
[DOCUMENTING] foo v0.0.1 ({dir})
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
dir = path2url(p.root())
)),
);
assert_that(&p.root().join("target/doc"), existing_dir());
let doc_file = p.root().join("target/doc/foo/index.html");
assert_that(&doc_file, existing_file());
let mut doc_html = String::new();
File::open(&doc_file)
.unwrap()
.read_to_string(&mut doc_html)
.unwrap();
assert!(doc_html.contains("Library"));
assert!(!doc_html.contains("Binary"));
}
#[test]
fn doc_lib_bin_same_name_documents_lib_when_requested() {
let p = project()
.file(
"src/main.rs",
r#"
//! Binary documentation
extern crate foo;
fn main() {
foo::foo();
}
"#,
)
.file(
"src/lib.rs",
r#"
//! Library documentation
pub fn foo() {}
"#,
)
.build();
assert_that(
p.cargo("doc").arg("--lib"),
execs().with_stderr(&format!(
"\
[DOCUMENTING] foo v0.0.1 ({dir})
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
dir = path2url(p.root())
)),
);
assert_that(&p.root().join("target/doc"), existing_dir());
let doc_file = p.root().join("target/doc/foo/index.html");
assert_that(&doc_file, existing_file());
let mut doc_html = String::new();
File::open(&doc_file)
.unwrap()
.read_to_string(&mut doc_html)
.unwrap();
assert!(doc_html.contains("Library"));
assert!(!doc_html.contains("Binary"));
}
#[test]
fn doc_lib_bin_same_name_documents_named_bin_when_requested() {
let p = project()
.file(
"src/main.rs",
r#"
//! Binary documentation
extern crate foo;
fn main() {
foo::foo();
}
"#,
)
.file(
"src/lib.rs",
r#"
//! Library documentation
pub fn foo() {}
"#,
)
.build();
assert_that(
p.cargo("doc").arg("--bin").arg("foo"),
execs().with_stderr(&format!(
"\
[CHECKING] foo v0.0.1 ({dir})
[DOCUMENTING] foo v0.0.1 ({dir})
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
dir = path2url(p.root())
)),
);
assert_that(&p.root().join("target/doc"), existing_dir());
let doc_file = p.root().join("target/doc/foo/index.html");
assert_that(&doc_file, existing_file());
let mut doc_html = String::new();
File::open(&doc_file)
.unwrap()
.read_to_string(&mut doc_html)
.unwrap();
assert!(!doc_html.contains("Library"));
assert!(doc_html.contains("Binary"));
}
#[test]
fn doc_lib_bin_same_name_documents_bins_when_requested() {
let p = project()
.file(
"src/main.rs",
r#"
//! Binary documentation
extern crate foo;
fn main() {
foo::foo();
}
"#,
)
.file(
"src/lib.rs",
r#"
//! Library documentation
pub fn foo() {}
"#,
)
.build();
assert_that(
p.cargo("doc").arg("--bins"),
execs().with_stderr(&format!(
"\
[CHECKING] foo v0.0.1 ({dir})
[DOCUMENTING] foo v0.0.1 ({dir})
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
dir = path2url(p.root())
)),
);
assert_that(&p.root().join("target/doc"), existing_dir());
let doc_file = p.root().join("target/doc/foo/index.html");
assert_that(&doc_file, existing_file());
let mut doc_html = String::new();
File::open(&doc_file)
.unwrap()
.read_to_string(&mut doc_html)
.unwrap();
assert!(!doc_html.contains("Library"));
assert!(doc_html.contains("Binary"));
}
#[test]
fn doc_dash_p() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies.a]
path = "a"
"#,
)
.file("src/lib.rs", "extern crate a;")
.file(
"a/Cargo.toml",
r#"
[package]
name = "a"
version = "0.0.1"
authors = []
[dependencies.b]
path = "../b"
"#,
)
.file("a/src/lib.rs", "extern crate b;")
.file("b/Cargo.toml", &basic_manifest("b", "0.0.1"))
.file("b/src/lib.rs", "")
.build();
assert_that(
p.cargo("doc").arg("-p").arg("a"),
execs().with_stderr(
"\
[..] b v0.0.1 (file://[..])
[..] b v0.0.1 (file://[..])
[DOCUMENTING] a v0.0.1 (file://[..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
),
);
}
#[test]
fn doc_same_name() {
let p = project()
.file("src/lib.rs", "")
.file("src/bin/main.rs", "fn main() {}")
.file("examples/main.rs", "fn main() {}")
.file("tests/main.rs", "fn main() {}")
.build();
assert_that(p.cargo("doc"), execs());
}
#[test]
fn doc_target() {
const TARGET: &'static str = "arm-unknown-linux-gnueabihf";
let p = project()
.file(
"src/lib.rs",
r#"
#![feature(no_core)]
#![no_core]
extern {
pub static A: u32;
}
"#,
)
.build();
assert_that(
p.cargo("doc").arg("--target").arg(TARGET).arg("--verbose"),
execs(),
);
assert_that(
&p.root().join(&format!("target/{}/doc", TARGET)),
existing_dir(),
);
assert_that(
&p.root()
.join(&format!("target/{}/doc/foo/index.html", TARGET)),
existing_file(),
);
}
#[test]
fn target_specific_not_documented() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[target.foo.dependencies]
a = { path = "a" }
"#,
)
.file("src/lib.rs", "")
.file("a/Cargo.toml", &basic_manifest("a", "0.0.1"))
.file("a/src/lib.rs", "not rust")
.build();
assert_that(p.cargo("doc"), execs());
}
#[test]
fn output_not_captured() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
a = { path = "a" }
"#,
)
.file("src/lib.rs", "")
.file("a/Cargo.toml", &basic_manifest("a", "0.0.1"))
.file(
"a/src/lib.rs",
"
/// ```
/// ☃
/// ```
pub fn foo() {}
",
)
.build();
let error = p.cargo("doc").exec_with_output().err().unwrap();
if let Ok(perr) = error.downcast::<ProcessError>() {
let output = perr.output.unwrap();
let stderr = str::from_utf8(&output.stderr).unwrap();
assert!(stderr.contains("☃"), "no snowman\n{}", stderr);
assert!(
stderr.contains("unknown start of token"),
"no message{}",
stderr
);
} else {
assert!(
false,
"an error kind other than ProcessErrorKind was encountered"
);
}
}
#[test]
fn target_specific_documented() {
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[target.foo.dependencies]
a = {{ path = "a" }}
[target.{}.dependencies]
a = {{ path = "a" }}
"#,
rustc_host()
),
)
.file(
"src/lib.rs",
"
extern crate a;
/// test
pub fn foo() {}
",
)
.file("a/Cargo.toml", &basic_manifest("a", "0.0.1"))
.file(
"a/src/lib.rs",
"
/// test
pub fn foo() {}
",
)
.build();
assert_that(p.cargo("doc"), execs());
}
#[test]
fn no_document_build_deps() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[build-dependencies]
a = { path = "a" }
"#,
)
.file("src/lib.rs", "pub fn foo() {}")
.file("a/Cargo.toml", &basic_manifest("a", "0.0.1"))
.file(
"a/src/lib.rs",
"
/// ```
/// ☃
/// ```
pub fn foo() {}
",
)
.build();
assert_that(p.cargo("doc"), execs());
}
#[test]
fn doc_release() {
let p = project()
.file("src/lib.rs", "")
.build();
assert_that(p.cargo("build").arg("--release"), execs());
assert_that(
p.cargo("doc").arg("--release").arg("-v"),
execs().with_stderr(
"\
[DOCUMENTING] foo v0.0.1 ([..])
[RUNNING] `rustdoc [..] src/lib.rs [..]`
[FINISHED] release [optimized] target(s) in [..]
",
),
);
}
#[test]
fn doc_multiple_deps() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies.bar]
path = "bar"
[dependencies.baz]
path = "baz"
"#,
)
.file("src/lib.rs", "extern crate bar; pub fn foo() {}")
.file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1"))
.file("bar/src/lib.rs", "pub fn bar() {}")
.file("baz/Cargo.toml", &basic_manifest("baz", "0.0.1"))
.file("baz/src/lib.rs", "pub fn baz() {}")
.build();
assert_that(
p.cargo("doc")
.arg("-p")
.arg("bar")
.arg("-p")
.arg("baz")
.arg("-v"),
execs(),
);
assert_that(&p.root().join("target/doc"), existing_dir());
assert_that(&p.root().join("target/doc/bar/index.html"), existing_file());
assert_that(&p.root().join("target/doc/baz/index.html"), existing_file());
}
#[test]
fn features() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies.bar]
path = "bar"
[features]
foo = ["bar/bar"]
"#,
)
.file("src/lib.rs", r#"#[cfg(feature = "foo")] pub fn foo() {}"#)
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
version = "0.0.1"
authors = []
[features]
bar = []
"#,
)
.file(
"bar/build.rs",
r#"
fn main() {
println!("cargo:rustc-cfg=bar");
}
"#,
)
.file("bar/src/lib.rs", r#"#[cfg(feature = "bar")] pub fn bar() {}"#)
.build();
assert_that(
p.cargo("doc").arg("--features").arg("foo"),
execs(),
);
assert_that(&p.root().join("target/doc"), existing_dir());
assert_that(
&p.root().join("target/doc/foo/fn.foo.html"),
existing_file(),
);
assert_that(
&p.root().join("target/doc/bar/fn.bar.html"),
existing_file(),
);
}
#[test]
fn rerun_when_dir_removed() {
let p = project()
.file(
"src/lib.rs",
r#"
/// dox
pub fn foo() {}
"#,
)
.build();
assert_that(p.cargo("doc"), execs());
assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
fs::remove_dir_all(p.root().join("target/doc/foo")).unwrap();
assert_that(p.cargo("doc"), execs());
assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
}
#[test]
fn document_only_lib() {
let p = project()
.file(
"src/lib.rs",
r#"
/// dox
pub fn foo() {}
"#,
)
.file(
"src/bin/bar.rs",
r#"
/// ```
/// ☃
/// ```
pub fn foo() {}
fn main() { foo(); }
"#,
)
.build();
assert_that(p.cargo("doc").arg("--lib"), execs());
assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
}
#[test]
fn plugins_no_use_target() {
if !support::is_nightly() {
return;
}
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[lib]
proc-macro = true
"#,
)
.file("src/lib.rs", "")
.build();
assert_that(
p.cargo("doc")
.arg("--target=x86_64-unknown-openbsd")
.arg("-v"),
execs(),
);
}
#[test]
fn doc_all_workspace() {
let p = project()
.file(
"Cargo.toml",
r#"
[project]
name = "foo"
version = "0.1.0"
[dependencies]
bar = { path = "bar" }
[workspace]
"#,
)
.file("src/main.rs", "fn main() {}")
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("bar/src/lib.rs", "pub fn bar() {}")
.build();
// The order in which bar is compiled or documented is not deterministic
assert_that(
p.cargo("doc").arg("--all"),
execs()
.with_stderr_contains("[..] Documenting bar v0.1.0 ([..])")
.with_stderr_contains("[..] Checking bar v0.1.0 ([..])")
.with_stderr_contains("[..] Documenting foo v0.1.0 ([..])"),
);
}
#[test]
fn doc_all_virtual_manifest() {
let p = project()
.file(
"Cargo.toml",
r#"
[workspace]
members = ["bar", "baz"]
"#,
)
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("bar/src/lib.rs", "pub fn bar() {}")
.file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0"))
.file("baz/src/lib.rs", "pub fn baz() {}")
.build();
// The order in which bar and baz are documented is not guaranteed
assert_that(
p.cargo("doc").arg("--all"),
execs()
.with_stderr_contains("[..] Documenting baz v0.1.0 ([..])")
.with_stderr_contains("[..] Documenting bar v0.1.0 ([..])"),
);
}
#[test]
fn doc_virtual_manifest_all_implied() {
let p = project()
.file(
"Cargo.toml",
r#"
[workspace]
members = ["bar", "baz"]
"#,
)
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("bar/src/lib.rs", "pub fn bar() {}")
.file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0"))
.file("baz/src/lib.rs", "pub fn baz() {}")
.build();
// The order in which bar and baz are documented is not guaranteed
assert_that(
p.cargo("doc"),
execs()
.with_stderr_contains("[..] Documenting baz v0.1.0 ([..])")
.with_stderr_contains("[..] Documenting bar v0.1.0 ([..])"),
);
}
#[test]
fn doc_all_member_dependency_same_name() {
if !is_nightly() {
// This can be removed once 1.29 is stable (rustdoc --cap-lints).
return;
}
let p = project()
.file(
"Cargo.toml",
r#"
[workspace]
members = ["bar"]
"#,
)
.file(
"bar/Cargo.toml",
r#"
[project]
name = "bar"
version = "0.1.0"
[dependencies]
bar = "0.1.0"
"#,
)
.file("bar/src/lib.rs", "pub fn bar() {}")
.build();
Package::new("bar", "0.1.0").publish();
assert_that(
p.cargo("doc").arg("--all"),
execs()
.with_stderr_contains("[..] Updating registry `[..]`")
.with_stderr_contains("[..] Documenting bar v0.1.0 ([..])"),
);
}
#[test]
fn doc_workspace_open_help_message() {
let p = project()
.file(
"Cargo.toml",
r#"
[workspace]
members = ["foo", "bar"]
"#,
)
.file("foo/Cargo.toml", &basic_manifest("foo", "0.1.0"))
.file("foo/src/lib.rs", "")
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("bar/src/lib.rs", "")
.build();
// The order in which bar is compiled or documented is not deterministic
assert_that(
p.cargo("doc").arg("--all").arg("--open"),
execs()
.with_status(101)
.with_stderr_contains("[..] Documenting bar v0.1.0 ([..])")
.with_stderr_contains("[..] Documenting foo v0.1.0 ([..])")
.with_stderr_contains(
"error: Passing multiple packages and `open` \
is not supported.",
)
.with_stderr_contains(
"Please re-run this command with `-p <spec>` \
where `<spec>` is one of the following:",
)
.with_stderr_contains(" foo")
.with_stderr_contains(" bar"),
);
}
#[test]
#[cfg(not(any(target_os = "windows", target_os = "macos")))]
fn doc_workspace_open_different_library_and_package_names() {
let p = project()
.file(
"Cargo.toml",
r#"
[workspace]
members = ["foo"]
"#,
)
.file(
"foo/Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[lib]
name = "foolib"
"#,
)
.file("foo/src/lib.rs", "")
.build();
assert_that(
p.cargo("doc --open").env("BROWSER", "echo"),
execs()
.with_stderr_contains("[..] Documenting foo v0.1.0 ([..])")
.with_stderr_contains("[..] Opening [..]/foo/target/doc/foolib/index.html")
);
}
#[test]
#[cfg(not(any(target_os = "windows", target_os = "macos")))]
fn doc_workspace_open_binary() {
let p = project()
.file(
"Cargo.toml",
r#"
[workspace]
members = ["foo"]
"#,
)
.file(
"foo/Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[[bin]]
name = "foobin"
path = "src/main.rs"
"#,
)
.file("foo/src/main.rs", "")
.build();
assert_that(
p.cargo("doc --open").env("BROWSER", "echo"),
execs()
.with_stderr_contains("[..] Documenting foo v0.1.0 ([..])")
.with_stderr_contains("[..] Opening [..]/foo/target/doc/foobin/index.html")
);
}
#[test]
#[cfg(not(any(target_os = "windows", target_os = "macos")))]
fn doc_workspace_open_binary_and_library() {
let p = project()
.file(
"Cargo.toml",
r#"
[workspace]
members = ["foo"]
"#,
)
.file(
"foo/Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[lib]
name = "foolib"
[[bin]]
name = "foobin"
path = "src/main.rs"
"#,
)
.file("foo/src/lib.rs", "")
.file("foo/src/main.rs", "")
.build();
assert_that(
p.cargo("doc --open").env("BROWSER", "echo"),
execs()
.with_stderr_contains("[..] Documenting foo v0.1.0 ([..])")
.with_stderr_contains("[..] Opening [..]/foo/target/doc/foolib/index.html")
);
}
#[test]
fn doc_edition() {
if !support::is_nightly() {
// Stable rustdoc won't have the edition option. Remove this once it
// is stabilized.
return;
}
let p = project()
.file(
"Cargo.toml",
r#"
cargo-features = ["edition"]
[package]
name = "foo"
version = "0.0.1"
authors = []
edition = "2018"
"#,
)
.file("src/lib.rs", "")
.build();
assert_that(
p.cargo("doc -v").masquerade_as_nightly_cargo(),
execs()
.with_stderr_contains("[RUNNING] `rustdoc [..]-Zunstable-options --edition=2018[..]"),
);
assert_that(
p.cargo("test -v").masquerade_as_nightly_cargo(),
execs()
.with_stderr_contains("[RUNNING] `rustdoc [..]-Zunstable-options --edition=2018[..]")
);
}
#[test]
fn doc_target_edition() {
if !support::is_nightly() {
return;
}
let p = project()
.file(
"Cargo.toml",
r#"
cargo-features = ["edition"]
[package]
name = "foo"
version = "0.0.1"
authors = []
[lib]
edition = "2018"
"#,
)
.file("src/lib.rs", "")
.build();
assert_that(
p.cargo("doc -v").masquerade_as_nightly_cargo(),
execs()
.with_stderr_contains("[RUNNING] `rustdoc [..]-Zunstable-options --edition=2018[..]"),
);
assert_that(
p.cargo("test -v").masquerade_as_nightly_cargo(),
execs()
.with_stderr_contains("[RUNNING] `rustdoc [..]-Zunstable-options --edition=2018[..]")
);
}
// Tests an issue where depending on different versions of the same crate depending on `cfg`s
// caused `cargo doc` to fail.
#[test]
fn issue_5345() {
if !is_nightly() {
// This can be removed once 1.29 is stable (rustdoc --cap-lints).
return;
}
let foo = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[target.'cfg(all(windows, target_arch = "x86"))'.dependencies]
bar = "0.1"
[target.'cfg(not(all(windows, target_arch = "x86")))'.dependencies]
bar = "0.2"
"#,
)
.file("src/lib.rs", "extern crate bar;")
.build();
Package::new("bar", "0.1.0").publish();
Package::new("bar", "0.2.0").publish();
assert_that(foo.cargo("build"), execs());
assert_that(foo.cargo("doc"), execs());
}
#[test]
fn doc_private_items() {
let foo = project()
.file("src/lib.rs", "mod private { fn private_item() {} }")
.build();
assert_that(foo.cargo("doc").arg("--document-private-items"), execs());
assert_that(&foo.root().join("target/doc"), existing_dir());
assert_that(&foo.root().join("target/doc/foo/private/index.html"), existing_file());
}
#[test]
fn doc_cap_lints() {
if !is_nightly() {
// This can be removed once 1.29 is stable (rustdoc --cap-lints).
return;
}
let a = git::new("a", |p| {
p.file("Cargo.toml", &basic_lib_manifest("a")).file(
"src/lib.rs",
"
#![deny(intra_doc_link_resolution_failure)]
/// [bad_link]
pub fn foo() {}
",
)
}).unwrap();
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
a = {{ git = '{}' }}
"#,
a.url()
),
)
.file("src/lib.rs", "")
.build();
assert_that(
p.cargo("doc"),
execs().with_stderr_unordered(
"\
[UPDATING] git repository `[..]`
[DOCUMENTING] a v0.5.0 ([..])
[CHECKING] a v0.5.0 ([..])
[DOCUMENTING] foo v0.0.1 ([..])
[FINISHED] dev [..]
",
),
);
p.root().join("target").rm_rf();
assert_that(
p.cargo("doc -vv"),
execs().with_stderr_contains(
"\
[WARNING] `[bad_link]` cannot be resolved, ignoring it...
",
),
);
}