about summary refs log tree commit diff
path: root/src/bootstrap
diff options
context:
space:
mode:
Diffstat (limited to 'src/bootstrap')
-rw-r--r--src/bootstrap/test.rs82
1 files changed, 58 insertions, 24 deletions
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 1580091488f..43561fa4f2f 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1264,15 +1264,15 @@ 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;
 
@@ -1280,12 +1280,59 @@ impl Step for DocTest {
         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 });
@@ -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() {
@@ -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);
         }
     }
 }
@@ -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,
                     });