| extern crate cargotest; |
| extern crate hamcrest; |
| extern crate cargo; |
| |
| use std::str; |
| use std::fs; |
| |
| use cargotest::rustc_host; |
| use cargotest::support::{project, execs, path2url}; |
| use cargotest::support::registry::Package; |
| use hamcrest::{assert_that, existing_file, existing_dir, is_not}; |
| use cargo::util::{CargoError, CargoErrorKind}; |
| |
| #[test] |
| fn simple() { |
| let p = project("foo") |
| .file("Cargo.toml", r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| build = "build.rs" |
| "#) |
| .file("build.rs", "fn main() {}") |
| .file("src/lib.rs", r#" |
| pub fn foo() {} |
| "#); |
| |
| assert_that(p.cargo_process("doc"), |
| execs().with_status(0).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("foo") |
| .file("Cargo.toml", r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [[bin]] |
| name = "foo" |
| doc = false |
| "#) |
| .file("src/main.rs", r#" |
| bad code |
| "#); |
| |
| assert_that(p.cargo_process("doc"), |
| execs().with_status(0)); |
| } |
| |
| #[test] |
| fn doc_twice() { |
| let p = project("foo") |
| .file("Cargo.toml", r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| "#) |
| .file("src/lib.rs", r#" |
| pub fn foo() {} |
| "#); |
| |
| assert_that(p.cargo_process("doc"), |
| execs().with_status(0).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_status(0).with_stdout("")) |
| } |
| |
| #[test] |
| fn doc_deps() { |
| let p = project("foo") |
| .file("Cargo.toml", r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [dependencies.bar] |
| path = "bar" |
| "#) |
| .file("src/lib.rs", r#" |
| extern crate bar; |
| pub fn foo() {} |
| "#) |
| .file("bar/Cargo.toml", r#" |
| [package] |
| name = "bar" |
| version = "0.0.1" |
| authors = [] |
| "#) |
| .file("bar/src/lib.rs", r#" |
| pub fn bar() {} |
| "#); |
| |
| assert_that(p.cargo_process("doc"), |
| execs().with_status(0).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()); |
| |
| assert_that(p.cargo("doc") |
| .env("RUST_LOG", "cargo::ops::cargo_rustc::fingerprint"), |
| execs().with_status(0).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("foo") |
| .file("Cargo.toml", r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [dependencies.bar] |
| path = "bar" |
| "#) |
| .file("src/lib.rs", r#" |
| extern crate bar; |
| pub fn foo() {} |
| "#) |
| .file("bar/Cargo.toml", r#" |
| [package] |
| name = "bar" |
| version = "0.0.1" |
| authors = [] |
| "#) |
| .file("bar/src/lib.rs", r#" |
| pub fn bar() {} |
| "#); |
| |
| assert_that(p.cargo_process("doc").arg("--no-deps"), |
| execs().with_status(0).with_stderr(&format!("\ |
| [COMPILING] 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("foo") |
| .file("Cargo.toml", r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [dependencies.bar] |
| path = "bar" |
| "#) |
| .file("src/main.rs", r#" |
| extern crate bar; |
| pub fn foo() {} |
| "#) |
| .file("bar/Cargo.toml", r#" |
| [package] |
| name = "bar" |
| version = "0.0.1" |
| authors = [] |
| "#) |
| .file("bar/src/lib.rs", r#" |
| pub fn bar() {} |
| "#); |
| |
| assert_that(p.cargo_process("doc").arg("-v"), |
| execs().with_status(0)); |
| |
| 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_lib_bin_same_name() { |
| let p = project("foo") |
| .file("Cargo.toml", r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| "#) |
| .file("src/main.rs", "fn main() {}") |
| .file("src/lib.rs", "fn foo() {}"); |
| |
| assert_that(p.cargo_process("doc"), |
| execs().with_status(101) |
| .with_stderr("\ |
| [ERROR] cannot document a package where a library and a binary have the same name. \ |
| Consider renaming one or marking the target as `doc = false` |
| ")); |
| } |
| |
| #[test] |
| fn doc_dash_p() { |
| let p = project("foo") |
| .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", r#" |
| [package] |
| name = "b" |
| version = "0.0.1" |
| authors = [] |
| "#) |
| .file("b/src/lib.rs", ""); |
| |
| assert_that(p.cargo_process("doc").arg("-p").arg("a"), |
| execs().with_status(0) |
| .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("foo") |
| .file("Cargo.toml", r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| "#) |
| .file("src/lib.rs", "") |
| .file("src/bin/main.rs", "fn main() {}") |
| .file("examples/main.rs", "fn main() {}") |
| .file("tests/main.rs", "fn main() {}"); |
| |
| assert_that(p.cargo_process("doc"), |
| execs().with_status(0)); |
| } |
| |
| #[test] |
| fn doc_target() { |
| const TARGET: &'static str = "arm-unknown-linux-gnueabihf"; |
| |
| let p = project("foo") |
| .file("Cargo.toml", r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| "#) |
| .file("src/lib.rs", r#" |
| #![feature(no_core)] |
| #![no_core] |
| |
| extern { |
| pub static A: u32; |
| } |
| "#); |
| |
| assert_that(p.cargo_process("doc").arg("--target").arg(TARGET).arg("--verbose"), |
| execs().with_status(0)); |
| 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("foo") |
| .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", r#" |
| [package] |
| name = "a" |
| version = "0.0.1" |
| authors = [] |
| "#) |
| .file("a/src/lib.rs", "not rust"); |
| |
| assert_that(p.cargo_process("doc"), |
| execs().with_status(0)); |
| } |
| |
| #[test] |
| fn output_not_captured() { |
| let p = project("foo") |
| .file("Cargo.toml", r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [dependencies] |
| a = { path = "a" } |
| "#) |
| .file("src/lib.rs", "") |
| .file("a/Cargo.toml", r#" |
| [package] |
| name = "a" |
| version = "0.0.1" |
| authors = [] |
| "#) |
| .file("a/src/lib.rs", " |
| /// ``` |
| /// ☃ |
| /// ``` |
| pub fn foo() {} |
| "); |
| |
| let error = p.cargo_process("doc").exec_with_output().err().unwrap(); |
| if let CargoError(CargoErrorKind::ProcessErrorKind(perr), ..) = error { |
| 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("foo") |
| .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", r#" |
| [package] |
| name = "a" |
| version = "0.0.1" |
| authors = [] |
| "#) |
| .file("a/src/lib.rs", " |
| /// test |
| pub fn foo() {} |
| "); |
| |
| assert_that(p.cargo_process("doc"), |
| execs().with_status(0)); |
| } |
| |
| #[test] |
| fn no_document_build_deps() { |
| let p = project("foo") |
| .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", r#" |
| [package] |
| name = "a" |
| version = "0.0.1" |
| authors = [] |
| "#) |
| .file("a/src/lib.rs", " |
| /// ``` |
| /// ☃ |
| /// ``` |
| pub fn foo() {} |
| "); |
| |
| assert_that(p.cargo_process("doc"), |
| execs().with_status(0)); |
| } |
| |
| #[test] |
| fn doc_release() { |
| let p = project("foo") |
| .file("Cargo.toml", r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| "#) |
| .file("src/lib.rs", ""); |
| |
| assert_that(p.cargo_process("build").arg("--release"), |
| execs().with_status(0)); |
| assert_that(p.cargo("doc").arg("--release").arg("-v"), |
| execs().with_status(0) |
| .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("foo") |
| .file("Cargo.toml", r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [dependencies.bar] |
| path = "bar" |
| |
| [dependencies.baz] |
| path = "baz" |
| "#) |
| .file("src/lib.rs", r#" |
| extern crate bar; |
| pub fn foo() {} |
| "#) |
| .file("bar/Cargo.toml", r#" |
| [package] |
| name = "bar" |
| version = "0.0.1" |
| authors = [] |
| "#) |
| .file("bar/src/lib.rs", r#" |
| pub fn bar() {} |
| "#) |
| .file("baz/Cargo.toml", r#" |
| [package] |
| name = "baz" |
| version = "0.0.1" |
| authors = [] |
| "#) |
| .file("baz/src/lib.rs", r#" |
| pub fn baz() {} |
| "#); |
| |
| assert_that(p.cargo_process("doc") |
| .arg("-p").arg("bar") |
| .arg("-p").arg("baz") |
| .arg("-v"), |
| execs().with_status(0)); |
| |
| 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("foo") |
| .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() {} |
| "#); |
| assert_that(p.cargo_process("doc").arg("--features").arg("foo"), |
| execs().with_status(0)); |
| 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("foo") |
| .file("Cargo.toml", r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| "#) |
| .file("src/lib.rs", r#" |
| /// dox |
| pub fn foo() {} |
| "#); |
| p.build(); |
| |
| assert_that(p.cargo("doc"), |
| execs().with_status(0)); |
| 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().with_status(0)); |
| assert_that(&p.root().join("target/doc/foo/index.html"), existing_file()); |
| } |
| |
| #[test] |
| fn document_only_lib() { |
| let p = project("foo") |
| .file("Cargo.toml", r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| "#) |
| .file("src/lib.rs", r#" |
| /// dox |
| pub fn foo() {} |
| "#) |
| .file("src/bin/bar.rs", r#" |
| /// ``` |
| /// ☃ |
| /// ``` |
| pub fn foo() {} |
| fn main() { foo(); } |
| "#); |
| assert_that(p.cargo_process("doc").arg("--lib"), |
| execs().with_status(0)); |
| assert_that(&p.root().join("target/doc/foo/index.html"), existing_file()); |
| } |
| |
| #[test] |
| fn plugins_no_use_target() { |
| if !cargotest::is_nightly() { |
| return |
| } |
| let p = project("foo") |
| .file("Cargo.toml", r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [lib] |
| proc-macro = true |
| "#) |
| .file("src/lib.rs", ""); |
| assert_that(p.cargo_process("doc") |
| .arg("--target=x86_64-unknown-openbsd") |
| .arg("-v"), |
| execs().with_status(0)); |
| } |
| |
| #[test] |
| fn doc_all_workspace() { |
| let p = project("foo") |
| .file("Cargo.toml", r#" |
| [project] |
| name = "foo" |
| version = "0.1.0" |
| |
| [dependencies] |
| bar = { path = "bar" } |
| |
| [workspace] |
| "#) |
| .file("src/main.rs", r#" |
| fn main() {} |
| "#) |
| .file("bar/Cargo.toml", r#" |
| [project] |
| name = "bar" |
| version = "0.1.0" |
| "#) |
| .file("bar/src/lib.rs", r#" |
| pub fn bar() {} |
| "#); |
| |
| // The order in which bar is compiled or documented is not deterministic |
| assert_that(p.cargo_process("doc") |
| .arg("--all"), |
| execs().with_status(0) |
| .with_stderr_contains("[..] Documenting bar v0.1.0 ([..])") |
| .with_stderr_contains("[..] Compiling bar v0.1.0 ([..])") |
| .with_stderr_contains("[..] Documenting foo v0.1.0 ([..])")); |
| } |
| |
| #[test] |
| fn doc_all_virtual_manifest() { |
| let p = project("workspace") |
| .file("Cargo.toml", r#" |
| [workspace] |
| members = ["foo", "bar"] |
| "#) |
| .file("foo/Cargo.toml", r#" |
| [project] |
| name = "foo" |
| version = "0.1.0" |
| "#) |
| .file("foo/src/lib.rs", r#" |
| pub fn foo() {} |
| "#) |
| .file("bar/Cargo.toml", r#" |
| [project] |
| name = "bar" |
| version = "0.1.0" |
| "#) |
| .file("bar/src/lib.rs", r#" |
| pub fn bar() {} |
| "#); |
| |
| // The order in which foo and bar are documented is not guaranteed |
| assert_that(p.cargo_process("doc") |
| .arg("--all"), |
| execs().with_status(0) |
| .with_stderr_contains("[..] Documenting bar v0.1.0 ([..])") |
| .with_stderr_contains("[..] Documenting foo v0.1.0 ([..])")); |
| } |
| |
| #[test] |
| fn doc_virtual_manifest_all_implied() { |
| let p = project("workspace") |
| .file("Cargo.toml", r#" |
| [workspace] |
| members = ["foo", "bar"] |
| "#) |
| .file("foo/Cargo.toml", r#" |
| [project] |
| name = "foo" |
| version = "0.1.0" |
| "#) |
| .file("foo/src/lib.rs", r#" |
| pub fn foo() {} |
| "#) |
| .file("bar/Cargo.toml", r#" |
| [project] |
| name = "bar" |
| version = "0.1.0" |
| "#) |
| .file("bar/src/lib.rs", r#" |
| pub fn bar() {} |
| "#); |
| |
| // The order in which foo and bar are documented is not guaranteed |
| assert_that(p.cargo_process("doc"), |
| execs().with_status(0) |
| .with_stderr_contains("[..] Documenting bar v0.1.0 ([..])") |
| .with_stderr_contains("[..] Documenting foo v0.1.0 ([..])")); |
| } |
| |
| #[test] |
| fn doc_all_member_dependency_same_name() { |
| let p = project("workspace") |
| .file("Cargo.toml", r#" |
| [workspace] |
| members = ["a"] |
| "#) |
| .file("a/Cargo.toml", r#" |
| [project] |
| name = "a" |
| version = "0.1.0" |
| |
| [dependencies] |
| a = "0.1.0" |
| "#) |
| .file("a/src/lib.rs", r#" |
| pub fn a() {} |
| "#); |
| |
| Package::new("a", "0.1.0").publish(); |
| |
| assert_that(p.cargo_process("doc") |
| .arg("--all"), |
| execs().with_status(0) |
| .with_stderr_contains("[..] Updating registry `[..]`") |
| .with_stderr_contains("[..] Documenting a v0.1.0 ([..])")); |
| } |