Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 05f1b00

Browse files
authoredMay 26, 2023
Rollup merge of rust-lang#111348 - ozkanonur:remove-hardcoded-rustdoc-flags, r=albertlarsan68,oli-obk
new tool `rustdoc-gui-test` Implements new tool `rustdoc-gui-test` that allows using compiletest headers for `rustdoc-gui` tests.
2 parents c71b92f + c7cec29 commit 05f1b00

File tree

18 files changed

+1435
-1231
lines changed

18 files changed

+1435
-1231
lines changed
 

‎Cargo.lock

+9
Original file line numberDiff line numberDiff line change
@@ -4379,6 +4379,15 @@ dependencies = [
43794379
"tracing-tree",
43804380
]
43814381

4382+
[[package]]
4383+
name = "rustdoc-gui-test"
4384+
version = "0.1.0"
4385+
dependencies = [
4386+
"compiletest",
4387+
"getopts",
4388+
"walkdir",
4389+
]
4390+
43824391
[[package]]
43834392
name = "rustdoc-json-types"
43844393
version = "0.1.0"

‎Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ members = [
4040
"src/tools/generate-copyright",
4141
"src/tools/suggest-tests",
4242
"src/tools/generate-windows-sys",
43+
"src/tools/rustdoc-gui-test",
4344
]
4445

4546
exclude = [

‎library/test/src/options.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,21 @@ pub enum ShouldPanic {
1616
}
1717

1818
/// Whether should console output be colored or not
19-
#[derive(Copy, Clone, Debug)]
19+
#[derive(Copy, Clone, Default, Debug)]
2020
pub enum ColorConfig {
21+
#[default]
2122
AutoColor,
2223
AlwaysColor,
2324
NeverColor,
2425
}
2526

2627
/// Format of the test results output
27-
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
28+
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
2829
pub enum OutputFormat {
2930
/// Verbose output
3031
Pretty,
3132
/// Quiet output
33+
#[default]
3234
Terse,
3335
/// JSON output
3436
Json,

‎src/bootstrap/builder.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,8 @@ impl<'a> Builder<'a> {
689689
tool::Miri,
690690
tool::CargoMiri,
691691
llvm::Lld,
692-
llvm::CrtBeginEnd
692+
llvm::CrtBeginEnd,
693+
tool::RustdocGUITest,
693694
),
694695
Kind::Check | Kind::Clippy | Kind::Fix => describe!(
695696
check::Std,

‎src/bootstrap/test.rs

+28-88
Original file line numberDiff line numberDiff line change
@@ -944,28 +944,6 @@ fn get_browser_ui_test_version(npm: &Path) -> Option<String> {
944944
.or_else(|| get_browser_ui_test_version_inner(npm, true))
945945
}
946946

947-
fn compare_browser_ui_test_version(installed_version: &str, src: &Path) {
948-
match fs::read_to_string(
949-
src.join("src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version"),
950-
) {
951-
Ok(v) => {
952-
if v.trim() != installed_version {
953-
eprintln!(
954-
"⚠️ Installed version of browser-ui-test (`{}`) is different than the \
955-
one used in the CI (`{}`)",
956-
installed_version, v
957-
);
958-
eprintln!(
959-
"You can install this version using `npm update browser-ui-test` or by using \
960-
`npm install browser-ui-test@{}`",
961-
v,
962-
);
963-
}
964-
}
965-
Err(e) => eprintln!("Couldn't find the CI browser-ui-test version: {:?}", e),
966-
}
967-
}
968-
969947
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
970948
pub struct RustdocGUI {
971949
pub target: TargetSelection,
@@ -997,94 +975,56 @@ impl Step for RustdocGUI {
997975
}
998976

999977
fn run(self, builder: &Builder<'_>) {
1000-
let nodejs = builder.config.nodejs.as_ref().expect("nodejs isn't available");
1001-
let npm = builder.config.npm.as_ref().expect("npm isn't available");
1002-
1003978
builder.ensure(compile::Std::new(self.compiler, self.target));
1004979

1005-
// The goal here is to check if the necessary packages are installed, and if not, we
1006-
// panic.
1007-
match get_browser_ui_test_version(&npm) {
1008-
Some(version) => {
1009-
// We also check the version currently used in CI and emit a warning if it's not the
1010-
// same one.
1011-
compare_browser_ui_test_version(&version, &builder.build.src);
1012-
}
1013-
None => {
1014-
eprintln!(
1015-
"error: rustdoc-gui test suite cannot be run because npm `browser-ui-test` \
1016-
dependency is missing",
1017-
);
1018-
eprintln!(
1019-
"If you want to install the `{0}` dependency, run `npm install {0}`",
1020-
"browser-ui-test",
1021-
);
1022-
panic!("Cannot run rustdoc-gui tests");
1023-
}
1024-
}
980+
let mut cmd = builder.tool_cmd(Tool::RustdocGUITest);
1025981

1026982
let out_dir = builder.test_out(self.target).join("rustdoc-gui");
1027-
1028-
// We remove existing folder to be sure there won't be artifacts remaining.
1029983
builder.clear_if_dirty(&out_dir, &builder.rustdoc(self.compiler));
1030984

1031-
let src_path = builder.build.src.join("tests/rustdoc-gui/src");
1032-
// We generate docs for the libraries present in the rustdoc-gui's src folder.
1033-
for entry in src_path.read_dir().expect("read_dir call failed") {
1034-
if let Ok(entry) = entry {
1035-
let path = entry.path();
985+
if let Some(src) = builder.config.src.to_str() {
986+
cmd.arg("--rust-src").arg(src);
987+
}
1036988

1037-
if !path.is_dir() {
1038-
continue;
1039-
}
989+
if let Some(out_dir) = out_dir.to_str() {
990+
cmd.arg("--out-dir").arg(out_dir);
991+
}
1040992

1041-
let mut cargo = Command::new(&builder.initial_cargo);
1042-
cargo
1043-
.arg("doc")
1044-
.arg("--target-dir")
1045-
.arg(&out_dir)
1046-
.env("RUSTC_BOOTSTRAP", "1")
1047-
.env("RUSTDOC", builder.rustdoc(self.compiler))
1048-
.env("RUSTC", builder.rustc(self.compiler))
1049-
.current_dir(path);
1050-
// FIXME: implement a `// compile-flags` command or similar
1051-
// instead of hard-coding this test
1052-
if entry.file_name() == "link_to_definition" {
1053-
cargo.env("RUSTDOCFLAGS", "-Zunstable-options --generate-link-to-definition");
1054-
} else if entry.file_name() == "scrape_examples" {
1055-
cargo.arg("-Zrustdoc-scrape-examples");
1056-
} else if entry.file_name() == "extend_css" {
1057-
cargo.env("RUSTDOCFLAGS", &format!("--extend-css extra.css"));
1058-
}
1059-
builder.run(&mut cargo);
1060-
}
993+
if let Some(initial_cargo) = builder.config.initial_cargo.to_str() {
994+
cmd.arg("--initial-cargo").arg(initial_cargo);
1061995
}
1062996

1063-
// We now run GUI tests.
1064-
let mut command = Command::new(&nodejs);
1065-
command
1066-
.arg(builder.build.src.join("src/tools/rustdoc-gui/tester.js"))
1067-
.arg("--jobs")
1068-
.arg(&builder.jobs().to_string())
1069-
.arg("--doc-folder")
1070-
.arg(out_dir.join("doc"))
1071-
.arg("--tests-folder")
1072-
.arg(builder.build.src.join("tests/rustdoc-gui"));
997+
cmd.arg("--jobs").arg(builder.jobs().to_string());
998+
999+
cmd.env("RUSTDOC", builder.rustdoc(self.compiler))
1000+
.env("RUSTC", builder.rustc(self.compiler));
1001+
10731002
for path in &builder.paths {
10741003
if let Some(p) = util::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) {
10751004
if !p.ends_with(".goml") {
10761005
eprintln!("A non-goml file was given: `{}`", path.display());
10771006
panic!("Cannot run rustdoc-gui tests");
10781007
}
10791008
if let Some(name) = path.file_name().and_then(|f| f.to_str()) {
1080-
command.arg("--file").arg(name);
1009+
cmd.arg("--goml-file").arg(name);
10811010
}
10821011
}
10831012
}
1013+
10841014
for test_arg in builder.config.test_args() {
1085-
command.arg(test_arg);
1015+
cmd.arg("--test-arg").arg(test_arg);
10861016
}
1087-
builder.run(&mut command);
1017+
1018+
if let Some(ref nodejs) = builder.config.nodejs {
1019+
cmd.arg("--nodejs").arg(nodejs);
1020+
}
1021+
1022+
if let Some(ref npm) = builder.config.npm {
1023+
cmd.arg("--npm").arg(npm);
1024+
}
1025+
1026+
let _time = util::timeit(&builder);
1027+
crate::render_tests::try_run_tests(builder, &mut cmd);
10881028
}
10891029
}
10901030

‎src/bootstrap/tool.rs

+1
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ bootstrap_tool!(
302302
GenerateCopyright, "src/tools/generate-copyright", "generate-copyright";
303303
SuggestTests, "src/tools/suggest-tests", "suggest-tests";
304304
GenerateWindowsSys, "src/tools/generate-windows-sys", "generate-windows-sys";
305+
RustdocGUITest, "src/tools/rustdoc-gui-test", "rustdoc-gui-test", is_unstable_tool = true, allow_features = "test";
305306
);
306307

307308
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]

‎src/tools/compiletest/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ name = "compiletest"
33
version = "0.0.0"
44
edition = "2021"
55

6+
[lib]
7+
doctest = false
8+
69
[dependencies]
710
colored = "2"
811
diff = "0.1.10"

‎src/tools/compiletest/src/common.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ string_enum! {
6969
}
7070
}
7171

72+
impl Default for Mode {
73+
fn default() -> Self {
74+
Mode::Ui
75+
}
76+
}
77+
7278
impl Mode {
7379
pub fn disambiguator(self) -> &'static str {
7480
// Pretty-printing tests could run concurrently, and if they do,
@@ -125,7 +131,7 @@ pub enum PanicStrategy {
125131
}
126132

127133
/// Configuration for compiletest
128-
#[derive(Debug, Clone)]
134+
#[derive(Debug, Default, Clone)]
129135
pub struct Config {
130136
/// `true` to overwrite stderr/stdout files instead of complaining about changes in output.
131137
pub bless: bool,

‎src/tools/compiletest/src/lib.rs

+1,136
Large diffs are not rendered by default.

‎src/tools/compiletest/src/main.rs

+2-1,135
Large diffs are not rendered by default.

‎src/tools/rustdoc-gui-test/Cargo.toml

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "rustdoc-gui-test"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
compiletest = { path = "../compiletest" }
8+
getopts = "0.2"
9+
walkdir = "2"
+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
use getopts::Options;
2+
use std::{env, path::PathBuf};
3+
4+
pub(crate) struct Config {
5+
pub(crate) nodejs: PathBuf,
6+
pub(crate) npm: PathBuf,
7+
pub(crate) rust_src: PathBuf,
8+
pub(crate) out_dir: PathBuf,
9+
pub(crate) initial_cargo: PathBuf,
10+
pub(crate) jobs: String,
11+
pub(crate) test_args: Vec<PathBuf>,
12+
pub(crate) goml_files: Vec<PathBuf>,
13+
pub(crate) rustc: PathBuf,
14+
pub(crate) rustdoc: PathBuf,
15+
pub(crate) verbose: bool,
16+
}
17+
18+
impl Config {
19+
pub(crate) fn from_args(args: Vec<String>) -> Self {
20+
let mut opts = Options::new();
21+
opts.reqopt("", "nodejs", "absolute path of nodejs", "PATH")
22+
.reqopt("", "npm", "absolute path of npm", "PATH")
23+
.reqopt("", "out-dir", "output path of doc compilation", "PATH")
24+
.reqopt("", "rust-src", "root source of the rust source", "PATH")
25+
.reqopt(
26+
"",
27+
"initial-cargo",
28+
"path to cargo to use for compiling tests/rustdoc-gui/src/*",
29+
"PATH",
30+
)
31+
.reqopt("", "jobs", "jobs arg of browser-ui-test", "JOBS")
32+
.optflag("", "verbose", "run tests verbosely, showing all output")
33+
.optmulti("", "test-arg", "args for browser-ui-test", "FLAGS")
34+
.optmulti("", "goml-file", "goml files for testing with browser-ui-test", "LIST");
35+
36+
let (argv0, args_) = args.split_first().unwrap();
37+
if args.len() == 1 || args[1] == "-h" || args[1] == "--help" {
38+
let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
39+
println!("{}", opts.usage(&message));
40+
std::process::exit(1);
41+
}
42+
43+
let matches = &match opts.parse(args_) {
44+
Ok(m) => m,
45+
Err(f) => panic!("{:?}", f),
46+
};
47+
48+
Self {
49+
nodejs: matches.opt_str("nodejs").map(PathBuf::from).expect("nodejs isn't available"),
50+
npm: matches.opt_str("npm").map(PathBuf::from).expect("npm isn't available"),
51+
rust_src: matches.opt_str("rust-src").map(PathBuf::from).unwrap(),
52+
out_dir: matches.opt_str("out-dir").map(PathBuf::from).unwrap(),
53+
initial_cargo: matches.opt_str("initial-cargo").map(PathBuf::from).unwrap(),
54+
jobs: matches.opt_str("jobs").unwrap(),
55+
goml_files: matches.opt_strs("goml-file").iter().map(PathBuf::from).collect(),
56+
test_args: matches.opt_strs("test-arg").iter().map(PathBuf::from).collect(),
57+
rustc: env::var("RUSTC").map(PathBuf::from).unwrap(),
58+
rustdoc: env::var("RUSTDOC").map(PathBuf::from).unwrap(),
59+
verbose: matches.opt_present("verbose"),
60+
}
61+
}
62+
}
+162
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
use compiletest::header::TestProps;
2+
use config::Config;
3+
use std::path::{Path, PathBuf};
4+
use std::process::Command;
5+
use std::sync::Arc;
6+
use std::{env, fs};
7+
8+
mod config;
9+
10+
fn get_browser_ui_test_version_inner(npm: &Path, global: bool) -> Option<String> {
11+
let mut command = Command::new(&npm);
12+
command.arg("list").arg("--parseable").arg("--long").arg("--depth=0");
13+
if global {
14+
command.arg("--global");
15+
}
16+
let lines = command
17+
.output()
18+
.map(|output| String::from_utf8_lossy(&output.stdout).into_owned())
19+
.unwrap_or(String::new());
20+
lines
21+
.lines()
22+
.find_map(|l| l.split(':').nth(1)?.strip_prefix("browser-ui-test@"))
23+
.map(|v| v.to_owned())
24+
}
25+
26+
fn get_browser_ui_test_version(npm: &Path) -> Option<String> {
27+
get_browser_ui_test_version_inner(npm, false)
28+
.or_else(|| get_browser_ui_test_version_inner(npm, true))
29+
}
30+
31+
fn compare_browser_ui_test_version(installed_version: &str, src: &Path) {
32+
match fs::read_to_string(
33+
src.join("src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version"),
34+
) {
35+
Ok(v) => {
36+
if v.trim() != installed_version {
37+
eprintln!(
38+
"⚠️ Installed version of browser-ui-test (`{}`) is different than the \
39+
one used in the CI (`{}`)",
40+
installed_version, v
41+
);
42+
eprintln!(
43+
"You can install this version using `npm update browser-ui-test` or by using \
44+
`npm install browser-ui-test@{}`",
45+
v,
46+
);
47+
}
48+
}
49+
Err(e) => eprintln!("Couldn't find the CI browser-ui-test version: {:?}", e),
50+
}
51+
}
52+
53+
fn find_librs<P: AsRef<Path>>(path: P) -> Option<PathBuf> {
54+
for entry in walkdir::WalkDir::new(path) {
55+
let entry = entry.ok()?;
56+
if entry.file_type().is_file() && entry.file_name() == "lib.rs" {
57+
return Some(entry.path().to_path_buf());
58+
}
59+
}
60+
None
61+
}
62+
63+
// FIXME: move `bootstrap::util::try_run` into `build_helper` crate
64+
// and use that one instead of creating this function.
65+
fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool {
66+
let status = match cmd.status() {
67+
Ok(status) => status,
68+
Err(e) => panic!("failed to execute command: {:?}\nerror: {}", cmd, e),
69+
};
70+
if !status.success() && print_cmd_on_fail {
71+
println!(
72+
"\n\ncommand did not execute successfully: {:?}\n\
73+
expected success, got: {}\n\n",
74+
cmd, status
75+
);
76+
}
77+
status.success()
78+
}
79+
80+
fn main() {
81+
let config = Arc::new(Config::from_args(env::args().collect()));
82+
83+
// The goal here is to check if the necessary packages are installed, and if not, we
84+
// panic.
85+
match get_browser_ui_test_version(&config.npm) {
86+
Some(version) => {
87+
// We also check the version currently used in CI and emit a warning if it's not the
88+
// same one.
89+
compare_browser_ui_test_version(&version, &config.rust_src);
90+
}
91+
None => {
92+
eprintln!(
93+
r#"
94+
error: rustdoc-gui test suite cannot be run because npm `browser-ui-test` dependency is missing.
95+
96+
If you want to install the `browser-ui-test` dependency, run `npm install browser-ui-test`
97+
"#,
98+
);
99+
100+
panic!("Cannot run rustdoc-gui tests");
101+
}
102+
}
103+
104+
let src_path = config.rust_src.join("tests/rustdoc-gui/src");
105+
for entry in src_path.read_dir().expect("read_dir call failed") {
106+
if let Ok(entry) = entry {
107+
let path = entry.path();
108+
109+
if !path.is_dir() {
110+
continue;
111+
}
112+
113+
let mut cargo = Command::new(&config.initial_cargo);
114+
cargo
115+
.arg("doc")
116+
.arg("--target-dir")
117+
.arg(&config.out_dir)
118+
.env("RUSTC_BOOTSTRAP", "1")
119+
.env("RUSTDOC", &config.rustdoc)
120+
.env("RUSTC", &config.rustc)
121+
.current_dir(path);
122+
123+
if let Some(librs) = find_librs(entry.path()) {
124+
let compiletest_c = compiletest::common::Config {
125+
edition: None,
126+
mode: compiletest::common::Mode::Rustdoc,
127+
..Default::default()
128+
};
129+
130+
let test_props = TestProps::from_file(&librs, None, &compiletest_c);
131+
132+
if !test_props.compile_flags.is_empty() {
133+
cargo.env("RUSTDOCFLAGS", test_props.compile_flags.join(" "));
134+
}
135+
136+
if let Some(flags) = &test_props.run_flags {
137+
cargo.arg(flags);
138+
}
139+
}
140+
141+
try_run(&mut cargo, config.verbose);
142+
}
143+
}
144+
145+
let mut command = Command::new(&config.nodejs);
146+
command
147+
.arg(config.rust_src.join("src/tools/rustdoc-gui/tester.js"))
148+
.arg("--jobs")
149+
.arg(&config.jobs)
150+
.arg("--doc-folder")
151+
.arg(config.out_dir.join("doc"))
152+
.arg("--tests-folder")
153+
.arg(config.rust_src.join("tests/rustdoc-gui"));
154+
155+
for file in &config.goml_files {
156+
command.arg("--file").arg(file);
157+
}
158+
159+
command.args(&config.test_args);
160+
161+
try_run(&mut command, config.verbose);
162+
}

‎tests/rustdoc-gui/source-anchor-scroll.goml

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ set-window-size: (600, 800)
88
assert-property: ("html", {"scrollTop": "0"})
99

1010
click: '//a[text() = "barbar"]'
11-
assert-property: ("html", {"scrollTop": "125"})
11+
assert-property: ("html", {"scrollTop": "149"})
1212
click: '//a[text() = "bar"]'
13-
assert-property: ("html", {"scrollTop": "156"})
13+
assert-property: ("html", {"scrollTop": "180"})
1414
click: '//a[text() = "sub_fn"]'
15-
assert-property: ("html", {"scrollTop": "53"})
15+
assert-property: ("html", {"scrollTop": "77"})
1616

1717
// We now check that clicking on lines doesn't change the scroll
1818
// Extra information: the "sub_fn" function header is on line 1.
1919
click: '//*[@id="6"]'
20-
assert-property: ("html", {"scrollTop": "53"})
20+
assert-property: ("html", {"scrollTop": "77"})
+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
// compile-flags: --extend-css extra.css
12
//! <div class="extend">text in red</div>

‎tests/rustdoc-gui/src/link_to_definition/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// compile-flags: -Zunstable-options --generate-link-to-definition
12
pub fn sub_fn() {
23
barbar();
34
}

‎tests/rustdoc-gui/src/scrape_examples/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// run-flags:-Zrustdoc-scrape-examples
12
/// # Examples
23
///
34
/// ```

‎triagebot.toml

+2
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ trigger_files = [
190190
"src/stage0.json",
191191
"src/tools/compiletest",
192192
"src/tools/tidy",
193+
"src/tools/rustdoc-gui-test",
193194
]
194195

195196
[autolabel."T-infra"]
@@ -640,3 +641,4 @@ style-team = [
640641
"/src/tools/rustdoc-themes" = ["rustdoc"]
641642
"/src/tools/tidy" = ["bootstrap"]
642643
"/src/tools/x" = ["bootstrap"]
644+
"/src/tools/rustdoc-gui-test" = ["bootstrap", "@ozkanonur"]

0 commit comments

Comments
 (0)
Please sign in to comment.