Skip to content

Commit

Permalink
Update books.
Browse files Browse the repository at this point in the history
  • Loading branch information
ehuss committed Feb 13, 2020
1 parent a1912f2 commit 1e1b6ad
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 36 deletions.
82 changes: 58 additions & 24 deletions src/bootstrap/test.rs
Expand Up @@ -1264,28 +1264,75 @@ impl Step for Compiletest {
}
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
struct DocTest {
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct BookTest {
compiler: Compiler,
path: &'static str,
path: PathBuf,
name: &'static str,
is_ext_doc: bool,
}

impl Step for DocTest {
impl Step for BookTest {
type Output = ();
const ONLY_HOSTS: bool = true;

fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.never()
}

/// Runs `rustdoc --test` for all documentation in `src/doc`.
/// Runs the documentation tests for a book in `src/doc`.
///
/// This will run all tests in our markdown documentation (e.g., the book)
/// located in `src/doc`. The `rustdoc` that's run is the one that sits next to
/// `compiler`.
/// This uses the `rustdoc` that sits next to `compiler`.
fn run(self, builder: &Builder<'_>) {
// External docs are different from local because:
// - Some books need pre-processing by mdbook before being tested.
// - They need to save their state to toolstate.
// - They are only tested on the "checktools" builders.
//
// The local docs are tested by default, and we don't want to pay the
// cost of building mdbook, so they use `rustdoc --test` directly.
// Also, the unstable book is special because SUMMARY.md is generated,
// so it is easier to just run `rustdoc` on its files.
if self.is_ext_doc {
self.run_ext_doc(builder);
} else {
self.run_local_doc(builder);
}
}
}

impl BookTest {
/// This runs the equivalent of `mdbook test` (via the rustbook wrapper)
/// which in turn runs `rustdoc --test` on each file in the book.
fn run_ext_doc(self, builder: &Builder<'_>) {
let compiler = self.compiler;

builder.ensure(compile::Std { compiler, target: compiler.host });

// mdbook just executes a binary named "rustdoc", so we need to update
// PATH so that it points to our rustdoc.
let mut rustdoc_path = builder.rustdoc(compiler);
rustdoc_path.pop();
let old_path = env::var_os("PATH").unwrap_or_default();
let new_path = env::join_paths(iter::once(rustdoc_path).chain(env::split_paths(&old_path)))
.expect("could not add rustdoc to PATH");

let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
let path = builder.src.join(&self.path);
rustbook_cmd.env("PATH", new_path).arg("test").arg(path);
builder.add_rust_test_threads(&mut rustbook_cmd);
builder.info(&format!("Testing rustbook {}", self.path.display()));
let _time = util::timeit(&builder);
let toolstate = if try_run(builder, &mut rustbook_cmd) {
ToolState::TestPass
} else {
ToolState::TestFail
};
builder.save_toolstate(self.name, toolstate);
}

/// This runs `rustdoc --test` on all `.md` files in the path.
fn run_local_doc(self, builder: &Builder<'_>) {
let compiler = self.compiler;

builder.ensure(compile::Std { compiler, target: compiler.host });
Expand All @@ -1294,7 +1341,6 @@ impl Step for DocTest {
// tests for all files that end in `*.md`
let mut stack = vec![builder.src.join(self.path)];
let _time = util::timeit(&builder);

let mut files = Vec::new();
while let Some(p) = stack.pop() {
if p.is_dir() {
Expand All @@ -1306,25 +1352,13 @@ impl Step for DocTest {
continue;
}

// The nostarch directory in the book is for no starch, and so isn't
// guaranteed to builder. We don't care if it doesn't build, so skip it.
if p.to_str().map_or(false, |p| p.contains("nostarch")) {
continue;
}

files.push(p);
}

files.sort();

let mut toolstate = ToolState::TestPass;
for file in files {
if !markdown_test(builder, compiler, &file) {
toolstate = ToolState::TestFail;
}
}
if self.is_ext_doc {
builder.save_toolstate(self.name, toolstate);
markdown_test(builder, compiler, &file);
}
}
}
Expand Down Expand Up @@ -1353,9 +1387,9 @@ macro_rules! test_book {
}

fn run(self, builder: &Builder<'_>) {
builder.ensure(DocTest {
builder.ensure(BookTest {
compiler: self.compiler,
path: $path,
path: PathBuf::from($path),
name: $book_name,
is_ext_doc: !$default,
});
Expand Down
2 changes: 1 addition & 1 deletion src/doc/book
Submodule book updated 1993 files
2 changes: 1 addition & 1 deletion src/doc/edition-guide
4 changes: 4 additions & 0 deletions src/doc/rustdoc/book.toml
@@ -0,0 +1,4 @@
[book]
authors = ["The Rust Project Developers"]
src = "src"
title = "The rustdoc book"
34 changes: 27 additions & 7 deletions src/tools/rustbook/src/main.rs
Expand Up @@ -25,6 +25,11 @@ fn main() {
.arg_from_usage(d_message)
.arg_from_usage(dir_message),
)
.subcommand(
SubCommand::with_name("test")
.about("Tests that a book's Rust code samples compile")
.arg_from_usage(dir_message),
)
.subcommand(
SubCommand::with_name("linkcheck")
.about("Run linkcheck with mdBook 3")
Expand All @@ -36,13 +41,12 @@ fn main() {
match matches.subcommand() {
("build", Some(sub_matches)) => {
if let Err(e) = build(sub_matches) {
eprintln!("Error: {}", e);

for cause in e.iter().skip(1) {
eprintln!("\tCaused By: {}", cause);
}

::std::process::exit(101);
handle_error(e);
}
}
("test", Some(sub_matches)) => {
if let Err(e) = test(sub_matches) {
handle_error(e);
}
}
("linkcheck", Some(sub_matches)) => {
Expand Down Expand Up @@ -146,6 +150,12 @@ pub fn build(args: &ArgMatches<'_>) -> Result3<()> {
Ok(())
}

fn test(args: &ArgMatches<'_>) -> Result3<()> {
let book_dir = get_book_dir(args);
let mut book = MDBook::load(&book_dir)?;
book.test(vec![])
}

fn get_book_dir(args: &ArgMatches<'_>) -> PathBuf {
if let Some(dir) = args.value_of("dir") {
// Check if path is relative from current dir, or absolute...
Expand All @@ -155,3 +165,13 @@ fn get_book_dir(args: &ArgMatches<'_>) -> PathBuf {
env::current_dir().unwrap()
}
}

fn handle_error(error: mdbook::errors::Error) -> ! {
eprintln!("Error: {}", error);

for cause in error.iter().skip(1) {
eprintln!("\tCaused By: {}", cause);
}

::std::process::exit(101);
}
1 change: 1 addition & 0 deletions src/tools/tidy/src/lib.rs
Expand Up @@ -58,6 +58,7 @@ fn filter_dirs(path: &Path) -> bool {
"src/tools/rls",
"src/tools/rust-installer",
"src/tools/rustfmt",
"src/doc/book",
// Filter RLS output directories
"target/rls",
];
Expand Down

0 comments on commit 1e1b6ad

Please sign in to comment.