mirror of
https://github.com/rust-lang/cargo.git
synced 2025-09-28 11:20:36 +00:00

This allows consumers of the json messages to avoid guessing where exactly the package root is. Having access to the package root is difficult by virtue of requiring logic to guess its location by e.g. walking filesystem from the source file. This guessing logic becomes further complicated in presence of workspaces and nigh impossible to implement correctly in instances where artifacts end up produced from paths above the package root (e.g. `../foo.rs`). Since Cargo has access to this data in the first place, there doesn't seem to be much reason to force consumers to invent their own, possibly flawed, logic.
1895 lines
48 KiB
Rust
1895 lines
48 KiB
Rust
//! Tests for the `cargo doc` command.
|
|
|
|
use cargo::core::compiler::RustDocFingerprint;
|
|
use cargo_test_support::paths::CargoPathExt;
|
|
use cargo_test_support::registry::Package;
|
|
use cargo_test_support::{basic_lib_manifest, basic_manifest, git, project};
|
|
use cargo_test_support::{is_nightly, rustc_host};
|
|
use std::fs;
|
|
use std::str;
|
|
|
|
#[cargo_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();
|
|
|
|
p.cargo("doc")
|
|
.with_stderr(
|
|
"\
|
|
[..] foo v0.0.1 ([CWD])
|
|
[..] foo v0.0.1 ([CWD])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
assert!(p.root().join("target/doc").is_dir());
|
|
assert!(p.root().join("target/doc/foo/index.html").is_file());
|
|
}
|
|
|
|
#[cargo_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();
|
|
|
|
p.cargo("doc").run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn doc_twice() {
|
|
let p = project().file("src/lib.rs", "pub fn foo() {}").build();
|
|
|
|
p.cargo("doc")
|
|
.with_stderr(
|
|
"\
|
|
[DOCUMENTING] foo v0.0.1 ([CWD])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
|
|
p.cargo("doc").with_stdout("").run();
|
|
}
|
|
|
|
#[cargo_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();
|
|
|
|
p.cargo("doc")
|
|
.with_stderr(
|
|
"\
|
|
[..] bar v0.0.1 ([CWD]/bar)
|
|
[..] bar v0.0.1 ([CWD]/bar)
|
|
[DOCUMENTING] foo v0.0.1 ([CWD])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
|
|
assert!(p.root().join("target/doc").is_dir());
|
|
assert!(p.root().join("target/doc/foo/index.html").is_file());
|
|
assert!(p.root().join("target/doc/bar/index.html").is_file());
|
|
|
|
// Verify that it only emits rmeta for the dependency.
|
|
assert_eq!(p.glob("target/debug/**/*.rlib").count(), 0);
|
|
assert_eq!(p.glob("target/debug/deps/libbar-*.rmeta").count(), 1);
|
|
|
|
p.cargo("doc")
|
|
.env("CARGO_LOG", "cargo::ops::cargo_rustc::fingerprint")
|
|
.with_stdout("")
|
|
.run();
|
|
|
|
assert!(p.root().join("target/doc").is_dir());
|
|
assert!(p.root().join("target/doc/foo/index.html").is_file());
|
|
assert!(p.root().join("target/doc/bar/index.html").is_file());
|
|
}
|
|
|
|
#[cargo_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();
|
|
|
|
p.cargo("doc --no-deps")
|
|
.with_stderr(
|
|
"\
|
|
[CHECKING] bar v0.0.1 ([CWD]/bar)
|
|
[DOCUMENTING] foo v0.0.1 ([CWD])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
|
|
assert!(p.root().join("target/doc").is_dir());
|
|
assert!(p.root().join("target/doc/foo/index.html").is_file());
|
|
assert!(!p.root().join("target/doc/bar/index.html").is_file());
|
|
}
|
|
|
|
#[cargo_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();
|
|
|
|
p.cargo("doc -v").run();
|
|
|
|
assert!(p.root().join("target/doc").is_dir());
|
|
assert!(p.root().join("target/doc/bar/index.html").is_file());
|
|
assert!(p.root().join("target/doc/foo/index.html").is_file());
|
|
}
|
|
|
|
#[cargo_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();
|
|
|
|
p.cargo("doc --workspace")
|
|
.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[..]` [..]")
|
|
.run();
|
|
}
|
|
|
|
#[cargo_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();
|
|
|
|
p.cargo("doc --workspace")
|
|
.with_stderr_contains("[DOCUMENTING] foo v0.1.0 ([CWD]/foo)")
|
|
.with_stderr_contains("[DOCUMENTING] bar v0.1.0 ([CWD]/bar)")
|
|
.with_stderr_contains("[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]")
|
|
.run();
|
|
assert!(p.root().join("target/doc").is_dir());
|
|
let doc_file = p.root().join("target/doc/foo_lib/index.html");
|
|
assert!(doc_file.is_file());
|
|
}
|
|
|
|
#[cargo_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();
|
|
|
|
p.cargo("doc --workspace")
|
|
.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[..]` [..]")
|
|
.run();
|
|
}
|
|
|
|
#[cargo_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();
|
|
|
|
p.cargo("doc --workspace").run();
|
|
}
|
|
|
|
#[cargo_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();
|
|
|
|
p.cargo("doc")
|
|
.with_stderr(
|
|
"\
|
|
[DOCUMENTING] foo v0.0.1 ([CWD])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
let doc_html = p.read_file("target/doc/foo/index.html");
|
|
assert!(doc_html.contains("Library"));
|
|
assert!(!doc_html.contains("Binary"));
|
|
}
|
|
|
|
#[cargo_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();
|
|
|
|
p.cargo("doc --lib")
|
|
.with_stderr(
|
|
"\
|
|
[DOCUMENTING] foo v0.0.1 ([CWD])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
let doc_html = p.read_file("target/doc/foo/index.html");
|
|
assert!(doc_html.contains("Library"));
|
|
assert!(!doc_html.contains("Binary"));
|
|
}
|
|
|
|
#[cargo_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();
|
|
|
|
p.cargo("doc --bin foo")
|
|
.with_stderr(
|
|
"\
|
|
[CHECKING] foo v0.0.1 ([CWD])
|
|
[DOCUMENTING] foo v0.0.1 ([CWD])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
let doc_html = p.read_file("target/doc/foo/index.html");
|
|
assert!(!doc_html.contains("Library"));
|
|
assert!(doc_html.contains("Binary"));
|
|
}
|
|
|
|
#[cargo_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();
|
|
|
|
p.cargo("doc --bins")
|
|
.with_stderr(
|
|
"\
|
|
[CHECKING] foo v0.0.1 ([CWD])
|
|
[DOCUMENTING] foo v0.0.1 ([CWD])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
let doc_html = p.read_file("target/doc/foo/index.html");
|
|
assert!(!doc_html.contains("Library"));
|
|
assert!(doc_html.contains("Binary"));
|
|
}
|
|
|
|
#[cargo_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();
|
|
|
|
p.cargo("doc -p a")
|
|
.with_stderr(
|
|
"\
|
|
[..] b v0.0.1 ([CWD]/b)
|
|
[..] b v0.0.1 ([CWD]/b)
|
|
[DOCUMENTING] a v0.0.1 ([CWD]/a)
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn doc_all_exclude() {
|
|
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() { break_the_build(); }")
|
|
.build();
|
|
|
|
p.cargo("doc --workspace --exclude baz")
|
|
.with_stderr_does_not_contain("[DOCUMENTING] baz v0.1.0 [..]")
|
|
.with_stderr(
|
|
"\
|
|
[DOCUMENTING] bar v0.1.0 ([..])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn doc_all_exclude_glob() {
|
|
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() { break_the_build(); }")
|
|
.build();
|
|
|
|
p.cargo("doc --workspace --exclude '*z'")
|
|
.with_stderr_does_not_contain("[DOCUMENTING] baz v0.1.0 [..]")
|
|
.with_stderr(
|
|
"\
|
|
[DOCUMENTING] bar v0.1.0 ([..])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_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();
|
|
|
|
p.cargo("doc").run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn doc_target() {
|
|
if !is_nightly() {
|
|
// no_core, lang_items requires nightly.
|
|
return;
|
|
}
|
|
const TARGET: &str = "arm-unknown-linux-gnueabihf";
|
|
|
|
let p = project()
|
|
.file(
|
|
"src/lib.rs",
|
|
r#"
|
|
#![feature(no_core, lang_items)]
|
|
#![no_core]
|
|
|
|
#[lang = "sized"]
|
|
trait Sized {}
|
|
|
|
extern {
|
|
pub static A: u32;
|
|
}
|
|
"#,
|
|
)
|
|
.build();
|
|
|
|
p.cargo("doc --verbose --target").arg(TARGET).run();
|
|
assert!(p.root().join(&format!("target/{}/doc", TARGET)).is_dir());
|
|
assert!(p
|
|
.root()
|
|
.join(&format!("target/{}/doc/foo/index.html", TARGET))
|
|
.is_file());
|
|
}
|
|
|
|
#[cargo_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();
|
|
|
|
p.cargo("doc").run();
|
|
}
|
|
|
|
#[cargo_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();
|
|
|
|
p.cargo("doc")
|
|
.without_status()
|
|
.with_stderr_contains("[..]☃")
|
|
.with_stderr_contains(r"[..]unknown start of token: \u{2603}")
|
|
.run();
|
|
}
|
|
|
|
#[cargo_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();
|
|
|
|
p.cargo("doc").run();
|
|
}
|
|
|
|
#[cargo_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();
|
|
|
|
p.cargo("doc").run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn doc_release() {
|
|
let p = project().file("src/lib.rs", "").build();
|
|
|
|
p.cargo("build --release").run();
|
|
p.cargo("doc --release -v")
|
|
.with_stderr(
|
|
"\
|
|
[DOCUMENTING] foo v0.0.1 ([..])
|
|
[RUNNING] `rustdoc [..] src/lib.rs [..]`
|
|
[FINISHED] release [optimized] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_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();
|
|
|
|
p.cargo("doc -p bar -p baz -v").run();
|
|
|
|
assert!(p.root().join("target/doc").is_dir());
|
|
assert!(p.root().join("target/doc/bar/index.html").is_file());
|
|
assert!(p.root().join("target/doc/baz/index.html").is_file());
|
|
}
|
|
|
|
#[cargo_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();
|
|
p.cargo("doc --features foo").run();
|
|
assert!(p.root().join("target/doc").is_dir());
|
|
assert!(p.root().join("target/doc/foo/fn.foo.html").is_file());
|
|
assert!(p.root().join("target/doc/bar/fn.bar.html").is_file());
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn rerun_when_dir_removed() {
|
|
let p = project()
|
|
.file(
|
|
"src/lib.rs",
|
|
r#"
|
|
/// dox
|
|
pub fn foo() {}
|
|
"#,
|
|
)
|
|
.build();
|
|
|
|
p.cargo("doc").run();
|
|
assert!(p.root().join("target/doc/foo/index.html").is_file());
|
|
|
|
fs::remove_dir_all(p.root().join("target/doc/foo")).unwrap();
|
|
|
|
p.cargo("doc").run();
|
|
assert!(p.root().join("target/doc/foo/index.html").is_file());
|
|
}
|
|
|
|
#[cargo_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();
|
|
p.cargo("doc --lib").run();
|
|
assert!(p.root().join("target/doc/foo/index.html").is_file());
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn plugins_no_use_target() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
|
|
[lib]
|
|
proc-macro = true
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
p.cargo("doc --target=x86_64-unknown-openbsd -v").run();
|
|
}
|
|
|
|
#[cargo_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
|
|
p.cargo("doc --workspace")
|
|
.with_stderr_contains("[..] Documenting bar v0.1.0 ([..])")
|
|
.with_stderr_contains("[..] Checking bar v0.1.0 ([..])")
|
|
.with_stderr_contains("[..] Documenting foo v0.1.0 ([..])")
|
|
.run();
|
|
}
|
|
|
|
#[cargo_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
|
|
p.cargo("doc --workspace")
|
|
.with_stderr_contains("[..] Documenting baz v0.1.0 ([..])")
|
|
.with_stderr_contains("[..] Documenting bar v0.1.0 ([..])")
|
|
.run();
|
|
}
|
|
|
|
#[cargo_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
|
|
p.cargo("doc")
|
|
.with_stderr_contains("[..] Documenting baz v0.1.0 ([..])")
|
|
.with_stderr_contains("[..] Documenting bar v0.1.0 ([..])")
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn doc_virtual_manifest_one_project() {
|
|
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() { break_the_build(); }")
|
|
.build();
|
|
|
|
p.cargo("doc -p bar")
|
|
.with_stderr_does_not_contain("[DOCUMENTING] baz v0.1.0 [..]")
|
|
.with_stderr(
|
|
"\
|
|
[DOCUMENTING] bar v0.1.0 ([..])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn doc_virtual_manifest_glob() {
|
|
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() { break_the_build(); }")
|
|
.file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0"))
|
|
.file("baz/src/lib.rs", "pub fn baz() {}")
|
|
.build();
|
|
|
|
p.cargo("doc -p '*z'")
|
|
.with_stderr_does_not_contain("[DOCUMENTING] bar v0.1.0 [..]")
|
|
.with_stderr(
|
|
"\
|
|
[DOCUMENTING] baz v0.1.0 ([..])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn doc_all_member_dependency_same_name() {
|
|
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();
|
|
|
|
p.cargo("doc --workspace")
|
|
.with_stderr_contains("[..] Updating `[..]` index")
|
|
.with_stderr_contains("[..] Documenting bar v0.1.0 ([..])")
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
#[cfg(not(windows))] // `echo` may not be available
|
|
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
|
|
p.cargo("doc --workspace --open")
|
|
.env("BROWSER", "echo")
|
|
.with_stderr_contains("[..] Documenting bar v0.1.0 ([..])")
|
|
.with_stderr_contains("[..] Documenting foo v0.1.0 ([..])")
|
|
.with_stderr_contains("[..] Opening [..]/foo/index.html")
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
#[cfg(not(windows))] // `echo` may not be available
|
|
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();
|
|
|
|
p.cargo("doc --open")
|
|
.env("BROWSER", "echo")
|
|
.with_stderr_contains("[..] Documenting foo v0.1.0 ([..])")
|
|
.with_stderr_contains("[..] [CWD]/target/doc/foolib/index.html")
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
#[cfg(not(windows))] // `echo` may not be available
|
|
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();
|
|
|
|
p.cargo("doc --open")
|
|
.env("BROWSER", "echo")
|
|
.with_stderr_contains("[..] Documenting foo v0.1.0 ([..])")
|
|
.with_stderr_contains("[..] Opening [CWD]/target/doc/foobin/index.html")
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
#[cfg(not(windows))] // `echo` may not be available
|
|
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();
|
|
|
|
p.cargo("doc --open")
|
|
.env("BROWSER", "echo")
|
|
.with_stderr_contains("[..] Documenting foo v0.1.0 ([..])")
|
|
.with_stderr_contains("[..] Opening [CWD]/target/doc/foolib/index.html")
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn doc_edition() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
edition = "2018"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("doc -v")
|
|
.with_stderr_contains("[RUNNING] `rustdoc [..]--edition=2018[..]")
|
|
.run();
|
|
|
|
p.cargo("test -v")
|
|
.with_stderr_contains("[RUNNING] `rustdoc [..]--edition=2018[..]")
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn doc_target_edition() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
|
|
[lib]
|
|
edition = "2018"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("doc -v")
|
|
.with_stderr_contains("[RUNNING] `rustdoc [..]--edition=2018[..]")
|
|
.run();
|
|
|
|
p.cargo("test -v")
|
|
.with_stderr_contains("[RUNNING] `rustdoc [..]--edition=2018[..]")
|
|
.run();
|
|
}
|
|
|
|
// Tests an issue where depending on different versions of the same crate depending on `cfg`s
|
|
// caused `cargo doc` to fail.
|
|
#[cargo_test]
|
|
fn issue_5345() {
|
|
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();
|
|
|
|
foo.cargo("build").run();
|
|
foo.cargo("doc").run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn doc_private_items() {
|
|
let foo = project()
|
|
.file("src/lib.rs", "mod private { fn private_item() {} }")
|
|
.build();
|
|
foo.cargo("doc --document-private-items").run();
|
|
|
|
assert!(foo.root().join("target/doc").is_dir());
|
|
assert!(foo
|
|
.root()
|
|
.join("target/doc/foo/private/index.html")
|
|
.is_file());
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn doc_private_ws() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[workspace]
|
|
members = ["a", "b"]
|
|
"#,
|
|
)
|
|
.file("a/Cargo.toml", &basic_manifest("a", "0.0.1"))
|
|
.file("a/src/lib.rs", "fn p() {}")
|
|
.file("b/Cargo.toml", &basic_manifest("b", "0.0.1"))
|
|
.file("b/src/lib.rs", "fn p2() {}")
|
|
.file("b/src/main.rs", "fn main() {}")
|
|
.build();
|
|
p.cargo("doc --workspace --bins --lib --document-private-items -v")
|
|
.with_stderr_contains(
|
|
"[RUNNING] `rustdoc [..] a/src/lib.rs [..]--document-private-items[..]",
|
|
)
|
|
.with_stderr_contains(
|
|
"[RUNNING] `rustdoc [..] b/src/lib.rs [..]--document-private-items[..]",
|
|
)
|
|
.with_stderr_contains(
|
|
"[RUNNING] `rustdoc [..] b/src/main.rs [..]--document-private-items[..]",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
const BAD_INTRA_LINK_LIB: &str = r#"
|
|
#![deny(broken_intra_doc_links)]
|
|
|
|
/// [bad_link]
|
|
pub fn foo() {}
|
|
"#;
|
|
|
|
#[cargo_test]
|
|
fn doc_cap_lints() {
|
|
let a = git::new("a", |p| {
|
|
p.file("Cargo.toml", &basic_lib_manifest("a"))
|
|
.file("src/lib.rs", BAD_INTRA_LINK_LIB)
|
|
});
|
|
|
|
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();
|
|
|
|
p.cargo("doc")
|
|
.with_stderr_unordered(
|
|
"\
|
|
[UPDATING] git repository `[..]`
|
|
[DOCUMENTING] a v0.5.0 ([..])
|
|
[CHECKING] a v0.5.0 ([..])
|
|
[DOCUMENTING] foo v0.0.1 ([..])
|
|
[FINISHED] dev [..]
|
|
",
|
|
)
|
|
.run();
|
|
|
|
p.root().join("target").rm_rf();
|
|
|
|
p.cargo("doc -vv")
|
|
.with_stderr_contains("[WARNING] [..]`bad_link`[..]")
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn doc_message_format() {
|
|
let p = project().file("src/lib.rs", BAD_INTRA_LINK_LIB).build();
|
|
|
|
p.cargo("doc --message-format=json")
|
|
.with_status(101)
|
|
.with_json_contains_unordered(
|
|
r#"
|
|
{
|
|
"message": {
|
|
"children": "{...}",
|
|
"code": "{...}",
|
|
"level": "error",
|
|
"message": "[..]",
|
|
"rendered": "[..]",
|
|
"spans": "{...}"
|
|
},
|
|
"package_id": "foo [..]",
|
|
"manifest_path": "[..]",
|
|
"reason": "compiler-message",
|
|
"target": "{...}"
|
|
}
|
|
"#,
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn short_message_format() {
|
|
let p = project().file("src/lib.rs", BAD_INTRA_LINK_LIB).build();
|
|
p.cargo("doc --message-format=short")
|
|
.with_status(101)
|
|
.with_stderr_contains("src/lib.rs:4:6: error: [..]`bad_link`[..]")
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn doc_example() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
edition = "2018"
|
|
|
|
[[example]]
|
|
crate-type = ["lib"]
|
|
name = "ex1"
|
|
doc = true
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "pub fn f() {}")
|
|
.file(
|
|
"examples/ex1.rs",
|
|
r#"
|
|
use foo::f;
|
|
|
|
/// Example
|
|
pub fn x() { f(); }
|
|
"#,
|
|
)
|
|
.build();
|
|
|
|
p.cargo("doc").run();
|
|
assert!(p
|
|
.build_dir()
|
|
.join("doc")
|
|
.join("ex1")
|
|
.join("fn.x.html")
|
|
.exists());
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn bin_private_items() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
"#,
|
|
)
|
|
.file(
|
|
"src/main.rs",
|
|
"
|
|
pub fn foo_pub() {}
|
|
fn foo_priv() {}
|
|
struct FooStruct;
|
|
enum FooEnum {}
|
|
trait FooTrait {}
|
|
type FooType = u32;
|
|
mod foo_mod {}
|
|
|
|
",
|
|
)
|
|
.build();
|
|
|
|
p.cargo("doc")
|
|
.with_stderr(
|
|
"\
|
|
[DOCUMENTING] foo v0.0.1 ([CWD])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
|
|
assert!(p.root().join("target/doc/foo/index.html").is_file());
|
|
assert!(p.root().join("target/doc/foo/fn.foo_pub.html").is_file());
|
|
assert!(p.root().join("target/doc/foo/fn.foo_priv.html").is_file());
|
|
assert!(p
|
|
.root()
|
|
.join("target/doc/foo/struct.FooStruct.html")
|
|
.is_file());
|
|
assert!(p.root().join("target/doc/foo/enum.FooEnum.html").is_file());
|
|
assert!(p
|
|
.root()
|
|
.join("target/doc/foo/trait.FooTrait.html")
|
|
.is_file());
|
|
assert!(p.root().join("target/doc/foo/type.FooType.html").is_file());
|
|
assert!(p.root().join("target/doc/foo/foo_mod/index.html").is_file());
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn bin_private_items_deps() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
|
|
[dependencies.bar]
|
|
path = "bar"
|
|
"#,
|
|
)
|
|
.file(
|
|
"src/main.rs",
|
|
"
|
|
fn foo_priv() {}
|
|
pub fn foo_pub() {}
|
|
",
|
|
)
|
|
.file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1"))
|
|
.file(
|
|
"bar/src/lib.rs",
|
|
"
|
|
#[allow(dead_code)]
|
|
fn bar_priv() {}
|
|
pub fn bar_pub() {}
|
|
",
|
|
)
|
|
.build();
|
|
|
|
p.cargo("doc")
|
|
.with_stderr_unordered(
|
|
"\
|
|
[DOCUMENTING] bar v0.0.1 ([..])
|
|
[CHECKING] bar v0.0.1 ([..])
|
|
[DOCUMENTING] foo v0.0.1 ([CWD])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
|
|
assert!(p.root().join("target/doc/foo/index.html").is_file());
|
|
assert!(p.root().join("target/doc/foo/fn.foo_pub.html").is_file());
|
|
assert!(p.root().join("target/doc/foo/fn.foo_priv.html").is_file());
|
|
|
|
assert!(p.root().join("target/doc/bar/index.html").is_file());
|
|
assert!(p.root().join("target/doc/bar/fn.bar_pub.html").is_file());
|
|
assert!(!p.root().join("target/doc/bar/fn.bar_priv.html").exists());
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn crate_versions() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.2.4"
|
|
authors = []
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("doc -v")
|
|
.with_stderr(
|
|
"\
|
|
[DOCUMENTING] foo v1.2.4 [..]
|
|
[RUNNING] `rustdoc --crate-type lib --crate-name foo src/lib.rs [..]--crate-version 1.2.4`
|
|
[FINISHED] [..]
|
|
",
|
|
)
|
|
.run();
|
|
|
|
let output_path = p.root().join("target/doc/foo/index.html");
|
|
let output_documentation = fs::read_to_string(&output_path).unwrap();
|
|
|
|
assert!(output_documentation.contains("Version 1.2.4"));
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn crate_versions_flag_is_overridden() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.2.4"
|
|
authors = []
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
let output_documentation = || {
|
|
let output_path = p.root().join("target/doc/foo/index.html");
|
|
fs::read_to_string(&output_path).unwrap()
|
|
};
|
|
let asserts = |html: String| {
|
|
assert!(!html.contains("1.2.4"));
|
|
assert!(html.contains("Version 2.0.3"));
|
|
};
|
|
|
|
p.cargo("doc")
|
|
.env("RUSTDOCFLAGS", "--crate-version 2.0.3")
|
|
.run();
|
|
asserts(output_documentation());
|
|
|
|
p.build_dir().rm_rf();
|
|
|
|
p.cargo("rustdoc -- --crate-version 2.0.3").run();
|
|
asserts(output_documentation());
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn doc_test_in_workspace() {
|
|
if !is_nightly() {
|
|
// -Zdoctest-in-workspace is unstable
|
|
return;
|
|
}
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[workspace]
|
|
members = [
|
|
"crate-a",
|
|
"crate-b",
|
|
]
|
|
"#,
|
|
)
|
|
.file(
|
|
"crate-a/Cargo.toml",
|
|
r#"
|
|
[project]
|
|
name = "crate-a"
|
|
version = "0.1.0"
|
|
"#,
|
|
)
|
|
.file(
|
|
"crate-a/src/lib.rs",
|
|
"\
|
|
//! ```
|
|
//! assert_eq!(1, 1);
|
|
//! ```
|
|
",
|
|
)
|
|
.file(
|
|
"crate-b/Cargo.toml",
|
|
r#"
|
|
[project]
|
|
name = "crate-b"
|
|
version = "0.1.0"
|
|
"#,
|
|
)
|
|
.file(
|
|
"crate-b/src/lib.rs",
|
|
"\
|
|
//! ```
|
|
//! assert_eq!(1, 1);
|
|
//! ```
|
|
",
|
|
)
|
|
.build();
|
|
p.cargo("test -Zdoctest-in-workspace --doc -vv")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr_contains("[DOCTEST] crate-a")
|
|
.with_stdout_contains(
|
|
"
|
|
running 1 test
|
|
test crate-a/src/lib.rs - (line 1) ... ok
|
|
|
|
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out[..]
|
|
|
|
",
|
|
)
|
|
.with_stderr_contains("[DOCTEST] crate-b")
|
|
.with_stdout_contains(
|
|
"
|
|
running 1 test
|
|
test crate-b/src/lib.rs - (line 1) ... ok
|
|
|
|
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out[..]
|
|
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn doc_fingerprint_is_versioning_consistent() {
|
|
// Random rustc verbose version
|
|
let old_rustc_verbose_version = format!(
|
|
"\
|
|
rustc 1.41.1 (f3e1a954d 2020-02-24)
|
|
binary: rustc
|
|
commit-hash: f3e1a954d2ead4e2fc197c7da7d71e6c61bad196
|
|
commit-date: 2020-02-24
|
|
host: {}
|
|
release: 1.41.1
|
|
LLVM version: 9.0
|
|
",
|
|
rustc_host()
|
|
);
|
|
|
|
// Create the dummy project.
|
|
let dummy_project = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.2.4"
|
|
authors = []
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "//! These are the docs!")
|
|
.build();
|
|
|
|
dummy_project.cargo("doc").run();
|
|
|
|
let fingerprint: RustDocFingerprint =
|
|
serde_json::from_str(&dummy_project.read_file("target/.rustdoc_fingerprint.json"))
|
|
.expect("JSON Serde fail");
|
|
|
|
// Check that the fingerprint contains the actual rustc version
|
|
// which has been used to compile the docs.
|
|
let output = std::process::Command::new("rustc")
|
|
.arg("-vV")
|
|
.output()
|
|
.expect("Failed to get actual rustc verbose version");
|
|
assert_eq!(
|
|
fingerprint.rustc_vv,
|
|
(String::from_utf8_lossy(&output.stdout).as_ref())
|
|
);
|
|
|
|
// As the test shows above. Now we have generated the `doc/` folder and inside
|
|
// the rustdoc fingerprint file is located with the correct rustc version.
|
|
// So we will remove it and create a new fingerprint with an old rustc version
|
|
// inside it. We will also place a bogus file inside of the `doc/` folder to ensure
|
|
// it gets removed as we expect on the next doc compilation.
|
|
dummy_project.change_file(
|
|
"target/.rustdoc_fingerprint.json",
|
|
&old_rustc_verbose_version,
|
|
);
|
|
|
|
fs::write(
|
|
dummy_project.build_dir().join("doc/bogus_file"),
|
|
String::from("This is a bogus file and should be removed!"),
|
|
)
|
|
.expect("Error writing test bogus file");
|
|
|
|
// Now if we trigger another compilation, since the fingerprint contains an old version
|
|
// of rustc, cargo should remove the entire `/doc` folder (including the fingerprint)
|
|
// and generating another one with the actual version.
|
|
// It should also remove the bogus file we created above.
|
|
dummy_project.cargo("doc").run();
|
|
|
|
assert!(!dummy_project.build_dir().join("doc/bogus_file").exists());
|
|
|
|
let fingerprint: RustDocFingerprint =
|
|
serde_json::from_str(&dummy_project.read_file("target/.rustdoc_fingerprint.json"))
|
|
.expect("JSON Serde fail");
|
|
|
|
// Check that the fingerprint contains the actual rustc version
|
|
// which has been used to compile the docs.
|
|
assert_eq!(
|
|
fingerprint.rustc_vv,
|
|
(String::from_utf8_lossy(&output.stdout).as_ref())
|
|
);
|
|
}
|
|
|
|
#[cfg(target_os = "linux")]
|
|
#[cargo_test]
|
|
fn doc_fingerprint_respects_target_paths() {
|
|
// Random rustc verbose version
|
|
let old_rustc_verbose_version = format!(
|
|
"\
|
|
rustc 1.41.1 (f3e1a954d 2020-02-24)
|
|
binary: rustc
|
|
commit-hash: f3e1a954d2ead4e2fc197c7da7d71e6c61bad196
|
|
commit-date: 2020-02-24
|
|
host: {}
|
|
release: 1.41.1
|
|
LLVM version: 9.0
|
|
",
|
|
rustc_host()
|
|
);
|
|
|
|
// Create the dummy project.
|
|
let dummy_project = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "1.2.4"
|
|
authors = []
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "//! These are the docs!")
|
|
.build();
|
|
|
|
dummy_project
|
|
.cargo("doc --target x86_64-unknown-linux-gnu")
|
|
.run();
|
|
|
|
let fingerprint: RustDocFingerprint =
|
|
serde_json::from_str(&dummy_project.read_file("target/.rustdoc_fingerprint.json"))
|
|
.expect("JSON Serde fail");
|
|
|
|
// Check that the fingerprint contains the actual rustc version
|
|
// which has been used to compile the docs.
|
|
let output = std::process::Command::new("rustc")
|
|
.arg("-vV")
|
|
.output()
|
|
.expect("Failed to get actual rustc verbose version");
|
|
assert_eq!(
|
|
fingerprint.rustc_vv,
|
|
(String::from_utf8_lossy(&output.stdout).as_ref())
|
|
);
|
|
|
|
// As the test shows above. Now we have generated the `doc/` folder and inside
|
|
// the rustdoc fingerprint file is located with the correct rustc version.
|
|
// So we will remove it and create a new fingerprint with an old rustc version
|
|
// inside it. We will also place a bogus file inside of the `doc/` folder to ensure
|
|
// it gets removed as we expect on the next doc compilation.
|
|
dummy_project.change_file(
|
|
"target/.rustdoc_fingerprint.json",
|
|
&old_rustc_verbose_version,
|
|
);
|
|
|
|
fs::write(
|
|
dummy_project
|
|
.build_dir()
|
|
.join("x86_64-unknown-linux-gnu/doc/bogus_file"),
|
|
String::from("This is a bogus file and should be removed!"),
|
|
)
|
|
.expect("Error writing test bogus file");
|
|
|
|
// Now if we trigger another compilation, since the fingerprint contains an old version
|
|
// of rustc, cargo should remove the entire `/doc` folder (including the fingerprint)
|
|
// and generating another one with the actual version.
|
|
// It should also remove the bogus file we created above.
|
|
dummy_project
|
|
.cargo("doc --target x86_64-unknown-linux-gnu")
|
|
.run();
|
|
|
|
assert!(!dummy_project
|
|
.build_dir()
|
|
.join("x86_64-unknown-linux-gnu/doc/bogus_file")
|
|
.exists());
|
|
|
|
let fingerprint: RustDocFingerprint =
|
|
serde_json::from_str(&dummy_project.read_file("target/.rustdoc_fingerprint.json"))
|
|
.expect("JSON Serde fail");
|
|
|
|
// Check that the fingerprint contains the actual rustc version
|
|
// which has been used to compile the docs.
|
|
assert_eq!(
|
|
fingerprint.rustc_vv,
|
|
(String::from_utf8_lossy(&output.stdout).as_ref())
|
|
);
|
|
}
|