about summary refs log tree commit diff
path: root/tests/rustdoc-ui/doctest
diff options
context:
space:
mode:
Diffstat (limited to 'tests/rustdoc-ui/doctest')
-rw-r--r--tests/rustdoc-ui/doctest/auxiliary/extern_macros.rs7
-rw-r--r--tests/rustdoc-ui/doctest/block-doc-comment.rs17
-rw-r--r--tests/rustdoc-ui/doctest/block-doc-comment.stdout5
-rw-r--r--tests/rustdoc-ui/doctest/cfg-test.rs31
-rw-r--r--tests/rustdoc-ui/doctest/cfg-test.stdout7
-rw-r--r--tests/rustdoc-ui/doctest/check-attr-test.rs31
-rw-r--r--tests/rustdoc-ui/doctest/check-attr-test.stderr151
-rw-r--r--tests/rustdoc-ui/doctest/check-cfg-test.rs12
-rw-r--r--tests/rustdoc-ui/doctest/check-cfg-test.stderr11
-rw-r--r--tests/rustdoc-ui/doctest/check-cfg-test.stdout6
-rw-r--r--tests/rustdoc-ui/doctest/display-output.rs15
-rw-r--r--tests/rustdoc-ui/doctest/display-output.stdout43
-rw-r--r--tests/rustdoc-ui/doctest/doc-comment-multi-line-attr.rs11
-rw-r--r--tests/rustdoc-ui/doctest/doc-comment-multi-line-attr.stdout6
-rw-r--r--tests/rustdoc-ui/doctest/doc-comment-multi-line-cfg-attr.rs12
-rw-r--r--tests/rustdoc-ui/doctest/doc-comment-multi-line-cfg-attr.stdout6
-rw-r--r--tests/rustdoc-ui/doctest/doc-test-attr-pass.rs8
-rw-r--r--tests/rustdoc-ui/doctest/doc-test-attr.rs14
-rw-r--r--tests/rustdoc-ui/doctest/doc-test-attr.stderr34
-rw-r--r--tests/rustdoc-ui/doctest/doc-test-doctest-feature.rs13
-rw-r--r--tests/rustdoc-ui/doctest/doc-test-doctest-feature.stdout6
-rw-r--r--tests/rustdoc-ui/doctest/doc-test-rustdoc-feature.rs15
-rw-r--r--tests/rustdoc-ui/doctest/doc-test-rustdoc-feature.stdout6
-rw-r--r--tests/rustdoc-ui/doctest/doctest-edition.rs16
-rw-r--r--tests/rustdoc-ui/doctest/doctest-edition.stderr22
-rw-r--r--tests/rustdoc-ui/doctest/doctest-multiline-crate-attribute.rs10
-rw-r--r--tests/rustdoc-ui/doctest/doctest-multiline-crate-attribute.stdout6
-rw-r--r--tests/rustdoc-ui/doctest/doctest-output.rs28
-rw-r--r--tests/rustdoc-ui/doctest/doctest-output.stdout8
-rw-r--r--tests/rustdoc-ui/doctest/failed-doctest-compile-fail.rs12
-rw-r--r--tests/rustdoc-ui/doctest/failed-doctest-compile-fail.stdout14
-rw-r--r--tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.rs18
-rw-r--r--tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stdout24
-rw-r--r--tests/rustdoc-ui/doctest/failed-doctest-missing-codes.rs12
-rw-r--r--tests/rustdoc-ui/doctest/failed-doctest-missing-codes.stdout25
-rw-r--r--tests/rustdoc-ui/doctest/failed-doctest-output-windows.rs28
-rw-r--r--tests/rustdoc-ui/doctest/failed-doctest-output-windows.stdout39
-rw-r--r--tests/rustdoc-ui/doctest/failed-doctest-output.rs28
-rw-r--r--tests/rustdoc-ui/doctest/failed-doctest-output.stdout39
-rw-r--r--tests/rustdoc-ui/doctest/failed-doctest-should-panic.rs12
-rw-r--r--tests/rustdoc-ui/doctest/failed-doctest-should-panic.stdout14
-rw-r--r--tests/rustdoc-ui/doctest/no-run-flag-error.rs6
-rw-r--r--tests/rustdoc-ui/doctest/no-run-flag-error.stderr2
-rw-r--r--tests/rustdoc-ui/doctest/no-run-flag.rs38
-rw-r--r--tests/rustdoc-ui/doctest/no-run-flag.stdout12
-rw-r--r--tests/rustdoc-ui/doctest/nocapture-fail.rs12
-rw-r--r--tests/rustdoc-ui/doctest/nocapture-fail.stderr18
-rw-r--r--tests/rustdoc-ui/doctest/nocapture-fail.stdout6
-rw-r--r--tests/rustdoc-ui/doctest/nocapture.rs10
-rw-r--r--tests/rustdoc-ui/doctest/nocapture.stderr1
-rw-r--r--tests/rustdoc-ui/doctest/nocapture.stdout7
-rw-r--r--tests/rustdoc-ui/doctest/private-doc-test.rs12
-rw-r--r--tests/rustdoc-ui/doctest/private-item-doc-test.rs11
-rw-r--r--tests/rustdoc-ui/doctest/private-item-doc-test.stderr18
-rw-r--r--tests/rustdoc-ui/doctest/private-public-item-doc-test.rs11
-rw-r--r--tests/rustdoc-ui/doctest/private-public-item-doc-test.stderr18
-rw-r--r--tests/rustdoc-ui/doctest/public-reexported-item-doc-test.rs16
-rw-r--r--tests/rustdoc-ui/doctest/run-directory.correct.stdout6
-rw-r--r--tests/rustdoc-ui/doctest/run-directory.incorrect.stdout6
-rw-r--r--tests/rustdoc-ui/doctest/run-directory.rs23
-rw-r--r--tests/rustdoc-ui/doctest/test-compile-fail1.rs8
-rw-r--r--tests/rustdoc-ui/doctest/test-compile-fail1.stderr14
-rw-r--r--tests/rustdoc-ui/doctest/test-compile-fail2.rs3
-rw-r--r--tests/rustdoc-ui/doctest/test-compile-fail2.stderr8
-rw-r--r--tests/rustdoc-ui/doctest/test-compile-fail3.rs3
-rw-r--r--tests/rustdoc-ui/doctest/test-compile-fail3.stderr9
-rw-r--r--tests/rustdoc-ui/doctest/test-no_std.rs13
-rw-r--r--tests/rustdoc-ui/doctest/test-no_std.stdout6
-rw-r--r--tests/rustdoc-ui/doctest/test-type.rs26
-rw-r--r--tests/rustdoc-ui/doctest/test-type.stdout10
-rw-r--r--tests/rustdoc-ui/doctest/unparseable-doc-test.rs11
-rw-r--r--tests/rustdoc-ui/doctest/unparseable-doc-test.stdout23
72 files changed, 1189 insertions, 0 deletions
diff --git a/tests/rustdoc-ui/doctest/auxiliary/extern_macros.rs b/tests/rustdoc-ui/doctest/auxiliary/extern_macros.rs
new file mode 100644
index 00000000000..ee1fec4c5c2
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/auxiliary/extern_macros.rs
@@ -0,0 +1,7 @@
+#[macro_export]
+macro_rules! attrs_on_struct {
+    ( $( #[$attr:meta] )* ) => {
+        $( #[$attr] )*
+        pub struct ExpandedStruct;
+    }
+}
diff --git a/tests/rustdoc-ui/doctest/block-doc-comment.rs b/tests/rustdoc-ui/doctest/block-doc-comment.rs
new file mode 100644
index 00000000000..ce529916e5e
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/block-doc-comment.rs
@@ -0,0 +1,17 @@
+// check-pass
+// compile-flags:--test
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+// This test ensures that no code block is detected in the doc comments.
+
+pub mod Wormhole {
+    /** # Returns
+     *
+     */
+    pub fn foofoo() {}
+    /**
+     * # Returns
+     *
+     */
+    pub fn barbar() {}
+}
diff --git a/tests/rustdoc-ui/doctest/block-doc-comment.stdout b/tests/rustdoc-ui/doctest/block-doc-comment.stdout
new file mode 100644
index 00000000000..7326c0a25a0
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/block-doc-comment.stdout
@@ -0,0 +1,5 @@
+
+running 0 tests
+
+test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/cfg-test.rs b/tests/rustdoc-ui/doctest/cfg-test.rs
new file mode 100644
index 00000000000..a263baa9738
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/cfg-test.rs
@@ -0,0 +1,31 @@
+// check-pass
+// compile-flags:--test --test-args --test-threads=1
+// normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+// Crates like core have doctests gated on `cfg(not(test))` so we need to make
+// sure `cfg(test)` is not active when running `rustdoc --test`.
+
+/// this doctest will be ignored:
+///
+/// ```
+/// assert!(false);
+/// ```
+#[cfg(test)]
+pub struct Foo;
+
+/// this doctest will be tested:
+///
+/// ```
+/// assert!(true);
+/// ```
+#[cfg(not(test))]
+pub struct Foo;
+
+/// this doctest will be tested, but will not appear in documentation:
+///
+/// ```
+/// assert!(true)
+/// ```
+#[cfg(doctest)]
+pub struct Bar;
diff --git a/tests/rustdoc-ui/doctest/cfg-test.stdout b/tests/rustdoc-ui/doctest/cfg-test.stdout
new file mode 100644
index 00000000000..2960ff8d3b4
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/cfg-test.stdout
@@ -0,0 +1,7 @@
+
+running 2 tests
+test $DIR/cfg-test.rs - Bar (line 27) ... ok
+test $DIR/cfg-test.rs - Foo (line 19) ... ok
+
+test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/check-attr-test.rs b/tests/rustdoc-ui/doctest/check-attr-test.rs
new file mode 100644
index 00000000000..e955470148a
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/check-attr-test.rs
@@ -0,0 +1,31 @@
+// compile-flags:--test
+
+#![deny(rustdoc::invalid_codeblock_attributes)]
+
+/// foo
+///
+/// ```compile-fail,compilefail,comPile_fail
+/// boo
+/// ```
+pub fn foo() {}
+
+/// bar
+///
+/// ```should-panic,shouldpanic,shOuld_panic
+/// boo
+/// ```
+pub fn bar() {}
+
+/// foobar
+///
+/// ```no-run,norun,nO_run
+/// boo
+/// ```
+pub fn foobar() {}
+
+/// b
+///
+/// ```test-harness,testharness,tesT_harness
+/// boo
+/// ```
+pub fn b() {}
diff --git a/tests/rustdoc-ui/doctest/check-attr-test.stderr b/tests/rustdoc-ui/doctest/check-attr-test.stderr
new file mode 100644
index 00000000000..01beba1ffc4
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/check-attr-test.stderr
@@ -0,0 +1,151 @@
+error: unknown attribute `compile-fail`. Did you mean `compile_fail`?
+ --> $DIR/check-attr-test.rs:5:1
+  |
+5 | / /// foo
+6 | | ///
+7 | | /// ```compile-fail,compilefail,comPile_fail
+8 | | /// boo
+9 | | /// ```
+  | |_______^
+  |
+  = help: the code block will either not be tested if not marked as a rust one or won't fail if it compiles successfully
+note: the lint level is defined here
+ --> $DIR/check-attr-test.rs:3:9
+  |
+3 | #![deny(rustdoc::invalid_codeblock_attributes)]
+  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unknown attribute `compilefail`. Did you mean `compile_fail`?
+ --> $DIR/check-attr-test.rs:5:1
+  |
+5 | / /// foo
+6 | | ///
+7 | | /// ```compile-fail,compilefail,comPile_fail
+8 | | /// boo
+9 | | /// ```
+  | |_______^
+  |
+  = help: the code block will either not be tested if not marked as a rust one or won't fail if it compiles successfully
+
+error: unknown attribute `comPile_fail`. Did you mean `compile_fail`?
+ --> $DIR/check-attr-test.rs:5:1
+  |
+5 | / /// foo
+6 | | ///
+7 | | /// ```compile-fail,compilefail,comPile_fail
+8 | | /// boo
+9 | | /// ```
+  | |_______^
+  |
+  = help: the code block will either not be tested if not marked as a rust one or won't fail if it compiles successfully
+
+error: unknown attribute `should-panic`. Did you mean `should_panic`?
+  --> $DIR/check-attr-test.rs:12:1
+   |
+12 | / /// bar
+13 | | ///
+14 | | /// ```should-panic,shouldpanic,shOuld_panic
+15 | | /// boo
+16 | | /// ```
+   | |_______^
+   |
+   = help: the code block will either not be tested if not marked as a rust one or won't fail if it doesn't panic when running
+
+error: unknown attribute `shouldpanic`. Did you mean `should_panic`?
+  --> $DIR/check-attr-test.rs:12:1
+   |
+12 | / /// bar
+13 | | ///
+14 | | /// ```should-panic,shouldpanic,shOuld_panic
+15 | | /// boo
+16 | | /// ```
+   | |_______^
+   |
+   = help: the code block will either not be tested if not marked as a rust one or won't fail if it doesn't panic when running
+
+error: unknown attribute `shOuld_panic`. Did you mean `should_panic`?
+  --> $DIR/check-attr-test.rs:12:1
+   |
+12 | / /// bar
+13 | | ///
+14 | | /// ```should-panic,shouldpanic,shOuld_panic
+15 | | /// boo
+16 | | /// ```
+   | |_______^
+   |
+   = help: the code block will either not be tested if not marked as a rust one or won't fail if it doesn't panic when running
+
+error: unknown attribute `no-run`. Did you mean `no_run`?
+  --> $DIR/check-attr-test.rs:19:1
+   |
+19 | / /// foobar
+20 | | ///
+21 | | /// ```no-run,norun,nO_run
+22 | | /// boo
+23 | | /// ```
+   | |_______^
+   |
+   = help: the code block will either not be tested if not marked as a rust one or will be run (which you might not want)
+
+error: unknown attribute `norun`. Did you mean `no_run`?
+  --> $DIR/check-attr-test.rs:19:1
+   |
+19 | / /// foobar
+20 | | ///
+21 | | /// ```no-run,norun,nO_run
+22 | | /// boo
+23 | | /// ```
+   | |_______^
+   |
+   = help: the code block will either not be tested if not marked as a rust one or will be run (which you might not want)
+
+error: unknown attribute `nO_run`. Did you mean `no_run`?
+  --> $DIR/check-attr-test.rs:19:1
+   |
+19 | / /// foobar
+20 | | ///
+21 | | /// ```no-run,norun,nO_run
+22 | | /// boo
+23 | | /// ```
+   | |_______^
+   |
+   = help: the code block will either not be tested if not marked as a rust one or will be run (which you might not want)
+
+error: unknown attribute `test-harness`. Did you mean `test_harness`?
+  --> $DIR/check-attr-test.rs:26:1
+   |
+26 | / /// b
+27 | | ///
+28 | | /// ```test-harness,testharness,tesT_harness
+29 | | /// boo
+30 | | /// ```
+   | |_______^
+   |
+   = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
+
+error: unknown attribute `testharness`. Did you mean `test_harness`?
+  --> $DIR/check-attr-test.rs:26:1
+   |
+26 | / /// b
+27 | | ///
+28 | | /// ```test-harness,testharness,tesT_harness
+29 | | /// boo
+30 | | /// ```
+   | |_______^
+   |
+   = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
+
+error: unknown attribute `tesT_harness`. Did you mean `test_harness`?
+  --> $DIR/check-attr-test.rs:26:1
+   |
+26 | / /// b
+27 | | ///
+28 | | /// ```test-harness,testharness,tesT_harness
+29 | | /// boo
+30 | | /// ```
+   | |_______^
+   |
+   = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
+
+error: aborting due to 12 previous errors
+
diff --git a/tests/rustdoc-ui/doctest/check-cfg-test.rs b/tests/rustdoc-ui/doctest/check-cfg-test.rs
new file mode 100644
index 00000000000..49a801c3fb3
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/check-cfg-test.rs
@@ -0,0 +1,12 @@
+// check-pass
+// compile-flags: --test --nocapture --check-cfg=values(feature,"test") -Z unstable-options
+// normalize-stderr-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+// normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+/// The doctest will produce a warning because feature invalid is unexpected
+/// ```
+/// #[cfg(feature = "invalid")]
+/// assert!(false);
+/// ```
+pub struct Foo;
diff --git a/tests/rustdoc-ui/doctest/check-cfg-test.stderr b/tests/rustdoc-ui/doctest/check-cfg-test.stderr
new file mode 100644
index 00000000000..9770be2f191
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/check-cfg-test.stderr
@@ -0,0 +1,11 @@
+warning: unexpected `cfg` condition value
+  --> $DIR/check-cfg-test.rs:9:7
+   |
+LL | #[cfg(feature = "invalid")]
+   |       ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: expected values for `feature` are: test
+   = note: `#[warn(unexpected_cfgs)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/rustdoc-ui/doctest/check-cfg-test.stdout b/tests/rustdoc-ui/doctest/check-cfg-test.stdout
new file mode 100644
index 00000000000..b7db49bcfa8
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/check-cfg-test.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/check-cfg-test.rs - Foo (line 8) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/display-output.rs b/tests/rustdoc-ui/doctest/display-output.rs
new file mode 100644
index 00000000000..7a26dbff986
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/display-output.rs
@@ -0,0 +1,15 @@
+// Test that `--show-output` has an effect and `allow(unused)` can be overridden.
+
+// check-pass
+// edition:2018
+// compile-flags:--test --test-args=--show-output
+// normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+/// ```
+/// #![warn(unused)]
+/// let x = 12;
+///
+/// fn foo(x: &dyn std::fmt::Display) {}
+/// ```
+pub fn foo() {}
diff --git a/tests/rustdoc-ui/doctest/display-output.stdout b/tests/rustdoc-ui/doctest/display-output.stdout
new file mode 100644
index 00000000000..ad25d1ce541
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/display-output.stdout
@@ -0,0 +1,43 @@
+
+running 1 test
+test $DIR/display-output.rs - foo (line 9) ... ok
+
+successes:
+
+---- $DIR/display-output.rs - foo (line 9) stdout ----
+warning: unused variable: `x`
+  --> $DIR/display-output.rs:11:5
+   |
+LL | let x = 12;
+   |     ^ help: if this is intentional, prefix it with an underscore: `_x`
+   |
+note: the lint level is defined here
+  --> $DIR/display-output.rs:9:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
+
+warning: unused variable: `x`
+  --> $DIR/display-output.rs:13:8
+   |
+LL | fn foo(x: &dyn std::fmt::Display) {}
+   |        ^ help: if this is intentional, prefix it with an underscore: `_x`
+
+warning: function `foo` is never used
+  --> $DIR/display-output.rs:13:4
+   |
+LL | fn foo(x: &dyn std::fmt::Display) {}
+   |    ^^^
+   |
+   = note: `#[warn(dead_code)]` implied by `#[warn(unused)]`
+
+warning: 3 warnings emitted
+
+
+
+successes:
+    $DIR/display-output.rs - foo (line 9)
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/doc-comment-multi-line-attr.rs b/tests/rustdoc-ui/doctest/doc-comment-multi-line-attr.rs
new file mode 100644
index 00000000000..75508f435b3
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/doc-comment-multi-line-attr.rs
@@ -0,0 +1,11 @@
+// Regression test for #97440: Multiline inner attribute triggers ICE during doctest
+// compile-flags:--test
+// normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// check-pass
+
+//! ```rust
+//! #![deny(
+//! unused_parens,
+//! )]
+//! ```
diff --git a/tests/rustdoc-ui/doctest/doc-comment-multi-line-attr.stdout b/tests/rustdoc-ui/doctest/doc-comment-multi-line-attr.stdout
new file mode 100644
index 00000000000..e47edbd2a81
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/doc-comment-multi-line-attr.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/doc-comment-multi-line-attr.rs - (line 7) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/doc-comment-multi-line-cfg-attr.rs b/tests/rustdoc-ui/doctest/doc-comment-multi-line-cfg-attr.rs
new file mode 100644
index 00000000000..3b0b27edb7d
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/doc-comment-multi-line-cfg-attr.rs
@@ -0,0 +1,12 @@
+// compile-flags:--test
+// normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// check-pass
+
+/// ```
+/// # #![cfg_attr(not(dox), deny(missing_abi,
+/// # non_ascii_idents))]
+///
+/// pub struct Bar;
+/// ```
+pub struct Bar;
diff --git a/tests/rustdoc-ui/doctest/doc-comment-multi-line-cfg-attr.stdout b/tests/rustdoc-ui/doctest/doc-comment-multi-line-cfg-attr.stdout
new file mode 100644
index 00000000000..bf3521e4f91
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/doc-comment-multi-line-cfg-attr.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/doc-comment-multi-line-cfg-attr.rs - Bar (line 6) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/doc-test-attr-pass.rs b/tests/rustdoc-ui/doctest/doc-test-attr-pass.rs
new file mode 100644
index 00000000000..12608f24450
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/doc-test-attr-pass.rs
@@ -0,0 +1,8 @@
+// check-pass
+
+#![crate_type = "lib"]
+#![deny(invalid_doc_attributes)]
+#![doc(test(no_crate_inject))]
+#![doc(test(attr(deny(warnings))))]
+
+pub fn foo() {}
diff --git a/tests/rustdoc-ui/doctest/doc-test-attr.rs b/tests/rustdoc-ui/doctest/doc-test-attr.rs
new file mode 100644
index 00000000000..46178ad865a
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/doc-test-attr.rs
@@ -0,0 +1,14 @@
+#![crate_type = "lib"]
+#![deny(invalid_doc_attributes)]
+
+#![doc(test)]
+//~^ ERROR `#[doc(test(...)]` takes a list of attributes
+//~^^ WARN this was previously accepted by the compiler
+#![doc(test = "hello")]
+//~^ ERROR `#[doc(test(...)]` takes a list of attributes
+//~^^ WARN this was previously accepted by the compiler
+#![doc(test(a))]
+//~^ ERROR unknown `doc(test)` attribute `a`
+//~^^ WARN this was previously accepted by the compiler
+
+pub fn foo() {}
diff --git a/tests/rustdoc-ui/doctest/doc-test-attr.stderr b/tests/rustdoc-ui/doctest/doc-test-attr.stderr
new file mode 100644
index 00000000000..5e6014954a4
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/doc-test-attr.stderr
@@ -0,0 +1,34 @@
+error: `#[doc(test(...)]` takes a list of attributes
+  --> $DIR/doc-test-attr.rs:4:8
+   |
+LL | #![doc(test)]
+   |        ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+note: the lint level is defined here
+  --> $DIR/doc-test-attr.rs:2:9
+   |
+LL | #![deny(invalid_doc_attributes)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+error: `#[doc(test(...)]` takes a list of attributes
+  --> $DIR/doc-test-attr.rs:7:8
+   |
+LL | #![doc(test = "hello")]
+   |        ^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: unknown `doc(test)` attribute `a`
+  --> $DIR/doc-test-attr.rs:10:13
+   |
+LL | #![doc(test(a))]
+   |             ^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/rustdoc-ui/doctest/doc-test-doctest-feature.rs b/tests/rustdoc-ui/doctest/doc-test-doctest-feature.rs
new file mode 100644
index 00000000000..9c1f4936eab
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/doc-test-doctest-feature.rs
@@ -0,0 +1,13 @@
+// check-pass
+// compile-flags:--test
+// normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+// Make sure `cfg(doctest)` is set when finding doctests but not inside
+// the doctests.
+
+/// ```
+/// assert!(!cfg!(doctest));
+/// ```
+#[cfg(doctest)]
+pub struct Foo;
diff --git a/tests/rustdoc-ui/doctest/doc-test-doctest-feature.stdout b/tests/rustdoc-ui/doctest/doc-test-doctest-feature.stdout
new file mode 100644
index 00000000000..d7de1f10522
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/doc-test-doctest-feature.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/doc-test-doctest-feature.rs - Foo (line 9) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/doc-test-rustdoc-feature.rs b/tests/rustdoc-ui/doctest/doc-test-rustdoc-feature.rs
new file mode 100644
index 00000000000..1f90d13af84
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/doc-test-rustdoc-feature.rs
@@ -0,0 +1,15 @@
+// check-pass
+// compile-flags:--test
+// normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+#![feature(doc_cfg)]
+
+// Make sure `cfg(doc)` is set when finding doctests but not inside the doctests.
+
+/// ```
+/// #![feature(doc_cfg)]
+/// assert!(!cfg!(doc));
+/// ```
+#[cfg(doc)]
+pub struct Foo;
diff --git a/tests/rustdoc-ui/doctest/doc-test-rustdoc-feature.stdout b/tests/rustdoc-ui/doctest/doc-test-rustdoc-feature.stdout
new file mode 100644
index 00000000000..5b07fc4c87a
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/doc-test-rustdoc-feature.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/doc-test-rustdoc-feature.rs - Foo (line 10) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/doctest-edition.rs b/tests/rustdoc-ui/doctest/doctest-edition.rs
new file mode 100644
index 00000000000..b0787be972f
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/doctest-edition.rs
@@ -0,0 +1,16 @@
+// edition:2021
+
+#![deny(rustdoc::invalid_rust_codeblocks)]
+//~^ NOTE lint level is defined here
+
+// By default, rustdoc should use the edition of the crate.
+//! ```
+//! foo'b'
+//! ```
+//~^^^ ERROR could not parse
+//~| NOTE prefix `foo` is unknown
+
+// Rustdoc should respect `edition2018` when highlighting syntax.
+//! ```edition2018
+//! foo'b'
+//! ```
diff --git a/tests/rustdoc-ui/doctest/doctest-edition.stderr b/tests/rustdoc-ui/doctest/doctest-edition.stderr
new file mode 100644
index 00000000000..8a3329aa3ed
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/doctest-edition.stderr
@@ -0,0 +1,22 @@
+error: could not parse code block as Rust code
+  --> $DIR/doctest-edition.rs:7:5
+   |
+LL |   //! ```
+   |  _____^
+LL | | //! foo'b'
+LL | | //! ```
+   | |_______^
+   |
+   = note: error from rustc: prefix `foo` is unknown
+note: the lint level is defined here
+  --> $DIR/doctest-edition.rs:3:9
+   |
+LL | #![deny(rustdoc::invalid_rust_codeblocks)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: mark blocks that do not contain Rust code as text
+   |
+LL | //! ```text
+   |        ++++
+
+error: aborting due to previous error
+
diff --git a/tests/rustdoc-ui/doctest/doctest-multiline-crate-attribute.rs b/tests/rustdoc-ui/doctest/doctest-multiline-crate-attribute.rs
new file mode 100644
index 00000000000..a3bde6cb941
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/doctest-multiline-crate-attribute.rs
@@ -0,0 +1,10 @@
+// compile-flags:--test --test-args=--test-threads=1
+// normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// check-pass
+
+/// ```
+/// #![deprecated(since = "5.2", note = "foo was rarely used. \
+///    Users should instead use bar")]
+/// ```
+pub fn f() {}
diff --git a/tests/rustdoc-ui/doctest/doctest-multiline-crate-attribute.stdout b/tests/rustdoc-ui/doctest/doctest-multiline-crate-attribute.stdout
new file mode 100644
index 00000000000..07a4f657dea
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/doctest-multiline-crate-attribute.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/doctest-multiline-crate-attribute.rs - f (line 6) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/doctest-output.rs b/tests/rustdoc-ui/doctest/doctest-output.rs
new file mode 100644
index 00000000000..26754b73f0b
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/doctest-output.rs
@@ -0,0 +1,28 @@
+// edition:2018
+// aux-build:extern_macros.rs
+// compile-flags:--test --test-args=--test-threads=1
+// normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// check-pass
+
+//! ```
+//! assert_eq!(1 + 1, 2);
+//! ```
+
+extern crate extern_macros as macros;
+
+use macros::attrs_on_struct;
+
+pub mod foo {
+
+    /// ```
+    /// assert_eq!(1 + 1, 2);
+    /// ```
+    pub fn bar() {}
+}
+
+attrs_on_struct! {
+    /// ```
+    /// assert!(true);
+    /// ```
+}
diff --git a/tests/rustdoc-ui/doctest/doctest-output.stdout b/tests/rustdoc-ui/doctest/doctest-output.stdout
new file mode 100644
index 00000000000..35b0e366fb5
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/doctest-output.stdout
@@ -0,0 +1,8 @@
+
+running 3 tests
+test $DIR/doctest-output.rs - (line 8) ... ok
+test $DIR/doctest-output.rs - ExpandedStruct (line 24) ... ok
+test $DIR/doctest-output.rs - foo::bar (line 18) ... ok
+
+test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/failed-doctest-compile-fail.rs b/tests/rustdoc-ui/doctest/failed-doctest-compile-fail.rs
new file mode 100644
index 00000000000..53b3857dfde
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/failed-doctest-compile-fail.rs
@@ -0,0 +1,12 @@
+// FIXME: if/when the output of the test harness can be tested on its own, this test should be
+// adapted to use that, and that normalize line can go away
+
+// compile-flags:--test
+// normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// failure-status: 101
+
+/// ```compile_fail
+/// println!("Hello");
+/// ```
+pub struct Foo;
diff --git a/tests/rustdoc-ui/doctest/failed-doctest-compile-fail.stdout b/tests/rustdoc-ui/doctest/failed-doctest-compile-fail.stdout
new file mode 100644
index 00000000000..af3a90a7410
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/failed-doctest-compile-fail.stdout
@@ -0,0 +1,14 @@
+
+running 1 test
+test $DIR/failed-doctest-compile-fail.rs - Foo (line 9) - compile fail ... FAILED
+
+failures:
+
+---- $DIR/failed-doctest-compile-fail.rs - Foo (line 9) stdout ----
+Test compiled successfully, but it's marked `compile_fail`.
+
+failures:
+    $DIR/failed-doctest-compile-fail.rs - Foo (line 9)
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.rs b/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.rs
new file mode 100644
index 00000000000..84e4d61603a
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.rs
@@ -0,0 +1,18 @@
+// FIXME: if/when the output of the test harness can be tested on its own, this test should be
+// adapted to use that, and that normalize line can go away
+
+// compile-flags:--test
+// normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// failure-status: 101
+
+/// <https://github.com/rust-lang/rust/issues/91014>
+///
+/// ```rust
+/// struct S {}; // unexpected semicolon after struct def
+///
+/// fn main() {
+///    assert_eq!(0, 1);
+/// }
+/// ```
+mod m {}
diff --git a/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stdout b/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stdout
new file mode 100644
index 00000000000..61468b6c745
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stdout
@@ -0,0 +1,24 @@
+
+running 1 test
+test $DIR/failed-doctest-extra-semicolon-on-item.rs - m (line 11) ... FAILED
+
+failures:
+
+---- $DIR/failed-doctest-extra-semicolon-on-item.rs - m (line 11) stdout ----
+error: expected item, found `;`
+  --> $DIR/failed-doctest-extra-semicolon-on-item.rs:12:12
+   |
+LL | struct S {}; // unexpected semicolon after struct def
+   |            ^ help: remove this semicolon
+   |
+   = help: braced struct declarations are not followed by a semicolon
+
+error: aborting due to previous error
+
+Couldn't compile the test.
+
+failures:
+    $DIR/failed-doctest-extra-semicolon-on-item.rs - m (line 11)
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/failed-doctest-missing-codes.rs b/tests/rustdoc-ui/doctest/failed-doctest-missing-codes.rs
new file mode 100644
index 00000000000..4e3b848fc02
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/failed-doctest-missing-codes.rs
@@ -0,0 +1,12 @@
+// FIXME: if/when the output of the test harness can be tested on its own, this test should be
+// adapted to use that, and that normalize line can go away
+
+// compile-flags:--test
+// normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// failure-status: 101
+
+/// ```compile_fail,E0004
+/// let x: () = 5i32;
+/// ```
+pub struct Foo;
diff --git a/tests/rustdoc-ui/doctest/failed-doctest-missing-codes.stdout b/tests/rustdoc-ui/doctest/failed-doctest-missing-codes.stdout
new file mode 100644
index 00000000000..bacbb47b5f9
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/failed-doctest-missing-codes.stdout
@@ -0,0 +1,25 @@
+
+running 1 test
+test $DIR/failed-doctest-missing-codes.rs - Foo (line 9) - compile fail ... FAILED
+
+failures:
+
+---- $DIR/failed-doctest-missing-codes.rs - Foo (line 9) stdout ----
+error[E0308]: mismatched types
+  --> $DIR/failed-doctest-missing-codes.rs:10:13
+   |
+LL | let x: () = 5i32;
+   |        --   ^^^^ expected `()`, found `i32`
+   |        |
+   |        expected due to this
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
+Some expected error codes were not found: ["E0004"]
+
+failures:
+    $DIR/failed-doctest-missing-codes.rs - Foo (line 9)
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/failed-doctest-output-windows.rs b/tests/rustdoc-ui/doctest/failed-doctest-output-windows.rs
new file mode 100644
index 00000000000..6bc6c33c76e
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/failed-doctest-output-windows.rs
@@ -0,0 +1,28 @@
+// only-windows
+// There's a parallel generic version of this test for non-windows platforms.
+
+// Issue #51162: A failed doctest was not printing its stdout/stderr
+// FIXME: if/when the output of the test harness can be tested on its own, this test should be
+// adapted to use that, and that normalize line can go away
+
+// compile-flags:--test --test-args --test-threads=1
+// rustc-env:RUST_BACKTRACE=0
+// normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// failure-status: 101
+
+// doctest fails at runtime
+/// ```
+/// println!("stdout 1");
+/// eprintln!("stderr 1");
+/// println!("stdout 2");
+/// eprintln!("stderr 2");
+/// panic!("oh no");
+/// ```
+pub struct SomeStruct;
+
+// doctest fails at compile time
+/// ```
+/// no
+/// ```
+pub struct OtherStruct;
diff --git a/tests/rustdoc-ui/doctest/failed-doctest-output-windows.stdout b/tests/rustdoc-ui/doctest/failed-doctest-output-windows.stdout
new file mode 100644
index 00000000000..6c147054da3
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/failed-doctest-output-windows.stdout
@@ -0,0 +1,39 @@
+
+running 2 tests
+test $DIR/failed-doctest-output-windows.rs - OtherStruct (line 25) ... FAILED
+test $DIR/failed-doctest-output-windows.rs - SomeStruct (line 15) ... FAILED
+
+failures:
+
+---- $DIR/failed-doctest-output-windows.rs - OtherStruct (line 25) stdout ----
+error[E0425]: cannot find value `no` in this scope
+  --> $DIR/failed-doctest-output-windows.rs:26:1
+   |
+LL | no
+   | ^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
+Couldn't compile the test.
+---- $DIR/failed-doctest-output-windows.rs - SomeStruct (line 15) stdout ----
+Test executable failed (exit code: 101).
+
+stdout:
+stdout 1
+stdout 2
+
+stderr:
+stderr 1
+stderr 2
+thread 'main' panicked at 'oh no', $DIR/failed-doctest-output-windows.rs:7:1
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+
+
+
+failures:
+    $DIR/failed-doctest-output-windows.rs - OtherStruct (line 25)
+    $DIR/failed-doctest-output-windows.rs - SomeStruct (line 15)
+
+test result: FAILED. 0 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/failed-doctest-output.rs b/tests/rustdoc-ui/doctest/failed-doctest-output.rs
new file mode 100644
index 00000000000..3e1312382ee
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/failed-doctest-output.rs
@@ -0,0 +1,28 @@
+// ignore-windows
+// There's a parallel version of this test for Windows.
+
+// Issue #51162: A failed doctest was not printing its stdout/stderr
+// FIXME: if/when the output of the test harness can be tested on its own, this test should be
+// adapted to use that, and that normalize line can go away
+
+// compile-flags:--test --test-args --test-threads=1
+// rustc-env:RUST_BACKTRACE=0
+// normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// failure-status: 101
+
+// doctest fails at runtime
+/// ```
+/// println!("stdout 1");
+/// eprintln!("stderr 1");
+/// println!("stdout 2");
+/// eprintln!("stderr 2");
+/// panic!("oh no");
+/// ```
+pub struct SomeStruct;
+
+// doctest fails at compile time
+/// ```
+/// no
+/// ```
+pub struct OtherStruct;
diff --git a/tests/rustdoc-ui/doctest/failed-doctest-output.stdout b/tests/rustdoc-ui/doctest/failed-doctest-output.stdout
new file mode 100644
index 00000000000..630198a561a
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/failed-doctest-output.stdout
@@ -0,0 +1,39 @@
+
+running 2 tests
+test $DIR/failed-doctest-output.rs - OtherStruct (line 25) ... FAILED
+test $DIR/failed-doctest-output.rs - SomeStruct (line 15) ... FAILED
+
+failures:
+
+---- $DIR/failed-doctest-output.rs - OtherStruct (line 25) stdout ----
+error[E0425]: cannot find value `no` in this scope
+  --> $DIR/failed-doctest-output.rs:26:1
+   |
+LL | no
+   | ^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
+Couldn't compile the test.
+---- $DIR/failed-doctest-output.rs - SomeStruct (line 15) stdout ----
+Test executable failed (exit status: 101).
+
+stdout:
+stdout 1
+stdout 2
+
+stderr:
+stderr 1
+stderr 2
+thread 'main' panicked at 'oh no', $DIR/failed-doctest-output.rs:7:1
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+
+
+
+failures:
+    $DIR/failed-doctest-output.rs - OtherStruct (line 25)
+    $DIR/failed-doctest-output.rs - SomeStruct (line 15)
+
+test result: FAILED. 0 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/failed-doctest-should-panic.rs b/tests/rustdoc-ui/doctest/failed-doctest-should-panic.rs
new file mode 100644
index 00000000000..36284e814f3
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/failed-doctest-should-panic.rs
@@ -0,0 +1,12 @@
+// FIXME: if/when the output of the test harness can be tested on its own, this test should be
+// adapted to use that, and that normalize line can go away
+
+// compile-flags:--test
+// normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// failure-status: 101
+
+/// ```should_panic
+/// println!("Hello, world!");
+/// ```
+pub struct Foo;
diff --git a/tests/rustdoc-ui/doctest/failed-doctest-should-panic.stdout b/tests/rustdoc-ui/doctest/failed-doctest-should-panic.stdout
new file mode 100644
index 00000000000..57a20092a5d
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/failed-doctest-should-panic.stdout
@@ -0,0 +1,14 @@
+
+running 1 test
+test $DIR/failed-doctest-should-panic.rs - Foo (line 9) ... FAILED
+
+failures:
+
+---- $DIR/failed-doctest-should-panic.rs - Foo (line 9) stdout ----
+Test executable succeeded, but it's marked `should_panic`.
+
+failures:
+    $DIR/failed-doctest-should-panic.rs - Foo (line 9)
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/no-run-flag-error.rs b/tests/rustdoc-ui/doctest/no-run-flag-error.rs
new file mode 100644
index 00000000000..4ead621482b
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/no-run-flag-error.rs
@@ -0,0 +1,6 @@
+// test the behavior of the --no-run flag without the --test flag
+
+// compile-flags:-Z unstable-options --no-run --test-args=--test-threads=1
+// error-pattern: the `--test` flag must be passed
+
+pub fn f() {}
diff --git a/tests/rustdoc-ui/doctest/no-run-flag-error.stderr b/tests/rustdoc-ui/doctest/no-run-flag-error.stderr
new file mode 100644
index 00000000000..d032646c365
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/no-run-flag-error.stderr
@@ -0,0 +1,2 @@
+error: the `--test` flag must be passed to enable `--no-run`
+
diff --git a/tests/rustdoc-ui/doctest/no-run-flag.rs b/tests/rustdoc-ui/doctest/no-run-flag.rs
new file mode 100644
index 00000000000..1cf3b7c4bb3
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/no-run-flag.rs
@@ -0,0 +1,38 @@
+// test the behavior of the --no-run flag
+
+// check-pass
+// compile-flags:-Z unstable-options --test --no-run --test-args=--test-threads=1
+// normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+/// ```
+/// let a = true;
+/// ```
+/// ```should_panic
+/// panic!()
+/// ```
+/// ```ignore (incomplete-code)
+/// fn foo() {
+/// ```
+/// ```no_run
+/// loop {
+///     println!("Hello, world");
+/// }
+/// ```
+/// fails to compile
+/// ```compile_fail
+/// let x = 5;
+/// x += 2; // shouldn't compile!
+/// ```
+/// Ok the test does not run
+/// ```
+/// panic!()
+/// ```
+/// Ok the test does not run
+/// ```should_panic
+/// loop {
+///     println!("Hello, world");
+/// panic!()
+/// }
+/// ```
+pub fn f() {}
diff --git a/tests/rustdoc-ui/doctest/no-run-flag.stdout b/tests/rustdoc-ui/doctest/no-run-flag.stdout
new file mode 100644
index 00000000000..02f28aaf60d
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/no-run-flag.stdout
@@ -0,0 +1,12 @@
+
+running 7 tests
+test $DIR/no-run-flag.rs - f (line 11) - compile ... ok
+test $DIR/no-run-flag.rs - f (line 14) ... ignored
+test $DIR/no-run-flag.rs - f (line 17) - compile ... ok
+test $DIR/no-run-flag.rs - f (line 23) - compile fail ... ok
+test $DIR/no-run-flag.rs - f (line 28) - compile ... ok
+test $DIR/no-run-flag.rs - f (line 32) - compile ... ok
+test $DIR/no-run-flag.rs - f (line 8) - compile ... ok
+
+test result: ok. 6 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/nocapture-fail.rs b/tests/rustdoc-ui/doctest/nocapture-fail.rs
new file mode 100644
index 00000000000..ce487a43db4
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/nocapture-fail.rs
@@ -0,0 +1,12 @@
+// check-pass
+// compile-flags:--test -Zunstable-options --nocapture
+// normalize-stderr-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+// normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+/// ```compile_fail
+/// fn foo() {
+///     Input: 123
+/// }
+/// ```
+pub struct Foo;
diff --git a/tests/rustdoc-ui/doctest/nocapture-fail.stderr b/tests/rustdoc-ui/doctest/nocapture-fail.stderr
new file mode 100644
index 00000000000..b65b622c1ed
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/nocapture-fail.stderr
@@ -0,0 +1,18 @@
+error: struct literal body without path
+  --> $DIR/nocapture-fail.rs:8:10
+   |
+LL |   fn foo() {
+   |  __________^
+LL | |     Input: 123
+LL | | }
+   | |_^
+   |
+help: you might have forgotten to add the struct literal inside the block
+   |
+LL ~ fn foo() { SomeStruct {
+LL |     Input: 123
+LL ~ } }
+   |
+
+error: aborting due to previous error
+
diff --git a/tests/rustdoc-ui/doctest/nocapture-fail.stdout b/tests/rustdoc-ui/doctest/nocapture-fail.stdout
new file mode 100644
index 00000000000..754f77db53c
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/nocapture-fail.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/nocapture-fail.rs - Foo (line 7) - compile fail ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/nocapture.rs b/tests/rustdoc-ui/doctest/nocapture.rs
new file mode 100644
index 00000000000..25fbcf857e2
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/nocapture.rs
@@ -0,0 +1,10 @@
+// check-pass
+// compile-flags:--test -Zunstable-options --nocapture
+// normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+/// ```
+/// println!("hello!");
+/// eprintln!("stderr");
+/// ```
+pub struct Foo;
diff --git a/tests/rustdoc-ui/doctest/nocapture.stderr b/tests/rustdoc-ui/doctest/nocapture.stderr
new file mode 100644
index 00000000000..af6415db3c7
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/nocapture.stderr
@@ -0,0 +1 @@
+stderr
diff --git a/tests/rustdoc-ui/doctest/nocapture.stdout b/tests/rustdoc-ui/doctest/nocapture.stdout
new file mode 100644
index 00000000000..4880e75da70
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/nocapture.stdout
@@ -0,0 +1,7 @@
+
+running 1 test
+hello!
+test $DIR/nocapture.rs - Foo (line 6) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/private-doc-test.rs b/tests/rustdoc-ui/doctest/private-doc-test.rs
new file mode 100644
index 00000000000..a1f9f8dca08
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/private-doc-test.rs
@@ -0,0 +1,12 @@
+// check-pass
+
+#![deny(rustdoc::private_doc_tests)]
+
+mod foo {
+    /// private doc test
+    ///
+    /// ```ignore (used for testing ignored doc tests)
+    /// assert!(false);
+    /// ```
+    fn bar() {}
+}
diff --git a/tests/rustdoc-ui/doctest/private-item-doc-test.rs b/tests/rustdoc-ui/doctest/private-item-doc-test.rs
new file mode 100644
index 00000000000..1a3d6cc636d
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/private-item-doc-test.rs
@@ -0,0 +1,11 @@
+#![deny(rustdoc::private_doc_tests)]
+
+mod foo {
+    /// private doc test
+    ///
+    /// ```
+    /// assert!(false);
+    /// ```
+    //~^^^^^ ERROR documentation test in private item
+    fn bar() {}
+}
diff --git a/tests/rustdoc-ui/doctest/private-item-doc-test.stderr b/tests/rustdoc-ui/doctest/private-item-doc-test.stderr
new file mode 100644
index 00000000000..5df6132987c
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/private-item-doc-test.stderr
@@ -0,0 +1,18 @@
+error: documentation test in private item
+  --> $DIR/private-item-doc-test.rs:4:5
+   |
+LL | /     /// private doc test
+LL | |     ///
+LL | |     /// ```
+LL | |     /// assert!(false);
+LL | |     /// ```
+   | |___________^
+   |
+note: the lint level is defined here
+  --> $DIR/private-item-doc-test.rs:1:9
+   |
+LL | #![deny(rustdoc::private_doc_tests)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/rustdoc-ui/doctest/private-public-item-doc-test.rs b/tests/rustdoc-ui/doctest/private-public-item-doc-test.rs
new file mode 100644
index 00000000000..7cc62b38cc2
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/private-public-item-doc-test.rs
@@ -0,0 +1,11 @@
+#![deny(rustdoc::private_doc_tests)]
+
+mod foo {
+    /// private doc test
+    ///
+    /// ```
+    /// assert!(false);
+    /// ```
+    //~^^^^^ ERROR documentation test in private item
+    pub fn bar() {}
+}
diff --git a/tests/rustdoc-ui/doctest/private-public-item-doc-test.stderr b/tests/rustdoc-ui/doctest/private-public-item-doc-test.stderr
new file mode 100644
index 00000000000..f50dbd1844e
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/private-public-item-doc-test.stderr
@@ -0,0 +1,18 @@
+error: documentation test in private item
+  --> $DIR/private-public-item-doc-test.rs:4:5
+   |
+LL | /     /// private doc test
+LL | |     ///
+LL | |     /// ```
+LL | |     /// assert!(false);
+LL | |     /// ```
+   | |___________^
+   |
+note: the lint level is defined here
+  --> $DIR/private-public-item-doc-test.rs:1:9
+   |
+LL | #![deny(rustdoc::private_doc_tests)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/rustdoc-ui/doctest/public-reexported-item-doc-test.rs b/tests/rustdoc-ui/doctest/public-reexported-item-doc-test.rs
new file mode 100644
index 00000000000..b86a53305a1
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/public-reexported-item-doc-test.rs
@@ -0,0 +1,16 @@
+// check-pass
+
+#![deny(rustdoc::private_doc_tests)]
+
+pub fn foo() {}
+
+mod private {
+    /// re-exported doc test
+    ///
+    /// ```
+    /// assert!(true);
+    /// ```
+    pub fn bar() {}
+}
+
+pub use private::bar;
diff --git a/tests/rustdoc-ui/doctest/run-directory.correct.stdout b/tests/rustdoc-ui/doctest/run-directory.correct.stdout
new file mode 100644
index 00000000000..e9b2754794a
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/run-directory.correct.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/run-directory.rs - foo (line 10) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/run-directory.incorrect.stdout b/tests/rustdoc-ui/doctest/run-directory.incorrect.stdout
new file mode 100644
index 00000000000..97a5dbc5c0c
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/run-directory.incorrect.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/run-directory.rs - foo (line 19) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/run-directory.rs b/tests/rustdoc-ui/doctest/run-directory.rs
new file mode 100644
index 00000000000..1ff0af2d17c
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/run-directory.rs
@@ -0,0 +1,23 @@
+// this test asserts that the cwd of doctest invocations is set correctly.
+
+// revisions: correct incorrect
+// check-pass
+// [correct]compile-flags:--test --test-run-directory={{src-base}}
+// [incorrect]compile-flags:--test --test-run-directory={{src-base}}/coverage
+// normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+/// ```
+/// assert_eq!(
+///     std::fs::read_to_string("doctest/run-directory.rs").unwrap(),
+///     include_str!("run-directory.rs"),
+/// );
+/// ```
+#[cfg(correct)]
+pub fn foo() {}
+
+/// ```
+/// assert!(std::fs::read_to_string("doctest/run-directory.rs").is_err());
+/// ```
+#[cfg(incorrect)]
+pub fn foo() {}
diff --git a/tests/rustdoc-ui/doctest/test-compile-fail1.rs b/tests/rustdoc-ui/doctest/test-compile-fail1.rs
new file mode 100644
index 00000000000..a0539023878
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/test-compile-fail1.rs
@@ -0,0 +1,8 @@
+// compile-flags:--test
+
+/// ```
+/// assert!(true)
+/// ```
+pub fn f() {}
+
+pub fn f() {}
diff --git a/tests/rustdoc-ui/doctest/test-compile-fail1.stderr b/tests/rustdoc-ui/doctest/test-compile-fail1.stderr
new file mode 100644
index 00000000000..72915e46bec
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/test-compile-fail1.stderr
@@ -0,0 +1,14 @@
+error[E0428]: the name `f` is defined multiple times
+ --> $DIR/test-compile-fail1.rs:8:1
+  |
+6 | pub fn f() {}
+  | ---------- previous definition of the value `f` here
+7 |
+8 | pub fn f() {}
+  | ^^^^^^^^^^ `f` redefined here
+  |
+  = note: `f` must be defined only once in the value namespace of this module
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/tests/rustdoc-ui/doctest/test-compile-fail2.rs b/tests/rustdoc-ui/doctest/test-compile-fail2.rs
new file mode 100644
index 00000000000..651ded0a047
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/test-compile-fail2.rs
@@ -0,0 +1,3 @@
+// compile-flags:--test
+
+fail
diff --git a/tests/rustdoc-ui/doctest/test-compile-fail2.stderr b/tests/rustdoc-ui/doctest/test-compile-fail2.stderr
new file mode 100644
index 00000000000..cee5b63cf50
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/test-compile-fail2.stderr
@@ -0,0 +1,8 @@
+error: expected one of `!` or `::`, found `<eof>`
+ --> $DIR/test-compile-fail2.rs:3:1
+  |
+3 | fail
+  | ^^^^ expected one of `!` or `::`
+
+error: aborting due to previous error
+
diff --git a/tests/rustdoc-ui/doctest/test-compile-fail3.rs b/tests/rustdoc-ui/doctest/test-compile-fail3.rs
new file mode 100644
index 00000000000..faa30ad8367
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/test-compile-fail3.rs
@@ -0,0 +1,3 @@
+// compile-flags:--test
+
+"fail
diff --git a/tests/rustdoc-ui/doctest/test-compile-fail3.stderr b/tests/rustdoc-ui/doctest/test-compile-fail3.stderr
new file mode 100644
index 00000000000..fab801b3bea
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/test-compile-fail3.stderr
@@ -0,0 +1,9 @@
+error[E0765]: unterminated double quote string
+ --> $DIR/test-compile-fail3.rs:3:1
+  |
+3 | "fail
+  | ^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0765`.
diff --git a/tests/rustdoc-ui/doctest/test-no_std.rs b/tests/rustdoc-ui/doctest/test-no_std.rs
new file mode 100644
index 00000000000..fd651d1a344
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/test-no_std.rs
@@ -0,0 +1,13 @@
+// compile-flags:--test
+// normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// check-pass
+
+#![no_std]
+
+extern crate alloc;
+
+/// ```
+/// assert!(true)
+/// ```
+pub fn f() {}
diff --git a/tests/rustdoc-ui/doctest/test-no_std.stdout b/tests/rustdoc-ui/doctest/test-no_std.stdout
new file mode 100644
index 00000000000..8d5a30804c1
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/test-no_std.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/test-no_std.rs - f (line 10) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/test-type.rs b/tests/rustdoc-ui/doctest/test-type.rs
new file mode 100644
index 00000000000..036d37f9db2
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/test-type.rs
@@ -0,0 +1,26 @@
+// compile-flags: --test --test-args=--test-threads=1
+// check-pass
+// normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+/// ```
+/// let a = true;
+/// ```
+/// ```should_panic
+/// panic!()
+/// ```
+/// ```ignore (incomplete-code)
+/// fn foo() {
+/// ```
+/// ```no_run
+/// loop {
+///     println!("Hello, world");
+/// }
+/// ```
+/// fails to compile
+/// ```compile_fail
+/// let x = 5;
+/// x += 2; // shouldn't compile!
+/// ```
+
+pub fn f() {}
diff --git a/tests/rustdoc-ui/doctest/test-type.stdout b/tests/rustdoc-ui/doctest/test-type.stdout
new file mode 100644
index 00000000000..a66fd240d34
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/test-type.stdout
@@ -0,0 +1,10 @@
+
+running 5 tests
+test $DIR/test-type.rs - f (line 12) ... ignored
+test $DIR/test-type.rs - f (line 15) - compile ... ok
+test $DIR/test-type.rs - f (line 21) - compile fail ... ok
+test $DIR/test-type.rs - f (line 6) ... ok
+test $DIR/test-type.rs - f (line 9) ... ok
+
+test result: ok. 4 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/unparseable-doc-test.rs b/tests/rustdoc-ui/doctest/unparseable-doc-test.rs
new file mode 100644
index 00000000000..fd8b2094d02
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/unparseable-doc-test.rs
@@ -0,0 +1,11 @@
+// compile-flags: --test
+// normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// failure-status: 101
+// rustc-env: RUST_BACKTRACE=0
+
+/// ```rust
+/// let x = 7;
+/// "unterminated
+/// ```
+pub fn foo() {}
diff --git a/tests/rustdoc-ui/doctest/unparseable-doc-test.stdout b/tests/rustdoc-ui/doctest/unparseable-doc-test.stdout
new file mode 100644
index 00000000000..2641c66f25e
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/unparseable-doc-test.stdout
@@ -0,0 +1,23 @@
+
+running 1 test
+test $DIR/unparseable-doc-test.rs - foo (line 7) ... FAILED
+
+failures:
+
+---- $DIR/unparseable-doc-test.rs - foo (line 7) stdout ----
+error[E0765]: unterminated double quote string
+  --> $DIR/unparseable-doc-test.rs:9:1
+   |
+LL | "unterminated
+   | ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0765`.
+Couldn't compile the test.
+
+failures:
+    $DIR/unparseable-doc-test.rs - foo (line 7)
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+