Skip to content

Commit 35cc349

Browse files
committed
Add tests for rustdoc json
Move rustdoc/rustdoc-json to rustdoc-json Scaffold rustdoc-json test mode Implement run_rustdoc_json_test Fix up python Make tidy happy
1 parent 36154e5 commit 35cc349

File tree

10 files changed

+115
-25
lines changed

10 files changed

+115
-25
lines changed

src/bootstrap/builder.rs

+1
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,7 @@ impl<'a> Builder<'a> {
424424
test::RustdocJSNotStd,
425425
test::RustdocTheme,
426426
test::RustdocUi,
427+
test::RustdocJson,
427428
// Run bootstrap close to the end as it's unlikely to fail
428429
test::Bootstrap,
429430
// Run run-make last, since these won't pass without make on Windows

src/bootstrap/test.rs

+7
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,12 @@ host_test!(UiFullDeps { path: "src/test/ui-fulldeps", mode: "ui", suite: "ui-ful
935935

936936
host_test!(Rustdoc { path: "src/test/rustdoc", mode: "rustdoc", suite: "rustdoc" });
937937

938+
host_test!(RustdocJson {
939+
path: "src/test/rustdoc-json",
940+
mode: "rustdoc-json",
941+
suite: "rustdoc-json"
942+
});
943+
938944
host_test!(Pretty { path: "src/test/pretty", mode: "pretty", suite: "pretty" });
939945

940946
default_test!(RunMake { path: "src/test/run-make", mode: "run-make", suite: "run-make" });
@@ -1032,6 +1038,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
10321038
|| (mode == "run-make" && suite.ends_with("fulldeps"))
10331039
|| (mode == "ui" && is_rustdoc)
10341040
|| mode == "js-doc-test"
1041+
|| mode == "rustdoc-json"
10351042
{
10361043
cmd.arg("--rustdoc-path").arg(builder.rustdoc(compiler));
10371044
}

src/test/rustdoc/rustdoc-json/check_missing_items.py renamed to src/test/rustdoc-json/check_missing_items.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -130,12 +130,16 @@ def check_type(ty):
130130
work_list |= set(item["inner"]["items"]) - visited
131131
elif item["kind"] == "struct":
132132
check_generics(item["inner"]["generics"])
133-
work_list |= (set(item["inner"]["fields"]) | set(item["inner"]["impls"])) - visited
133+
work_list |= (
134+
set(item["inner"]["fields"]) | set(item["inner"]["impls"])
135+
) - visited
134136
elif item["kind"] == "struct_field":
135137
check_type(item["inner"])
136138
elif item["kind"] == "enum":
137139
check_generics(item["inner"]["generics"])
138-
work_list |= (set(item["inner"]["variants"]) | set(item["inner"]["impls"])) - visited
140+
work_list |= (
141+
set(item["inner"]["variants"]) | set(item["inner"]["impls"])
142+
) - visited
139143
elif item["kind"] == "variant":
140144
if item["inner"]["variant_kind"] == "tuple":
141145
for ty in item["inner"]["variant_inner"]:
@@ -162,7 +166,9 @@ def check_type(ty):
162166
check_generics(item["inner"]["generics"])
163167
for bound in item["inner"]["bounds"]:
164168
check_generic_bound(bound)
165-
work_list |= (set(item["inner"]["items"]) | set(item["inner"]["implementors"])) - visited
169+
work_list |= (
170+
set(item["inner"]["items"]) | set(item["inner"]["implementors"])
171+
) - visited
166172
elif item["kind"] == "impl":
167173
check_generics(item["inner"]["generics"])
168174
if item["inner"]["trait"]:

src/test/rustdoc/rustdoc-json/compare.py renamed to src/test/rustdoc-json/compare.py

+36-12
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def __init__(self, msg, trace):
2424
super().__init__("{}: {}".format(trace, msg))
2525

2626

27-
def check_subset(expected_main, actual_main):
27+
def check_subset(expected_main, actual_main, base_dir):
2828
expected_index = expected_main["index"]
2929
expected_paths = expected_main["paths"]
3030
actual_index = actual_main["index"]
@@ -39,11 +39,24 @@ def _check_subset(expected, actual, trace):
3939
"expected type `{}`, got `{}`".format(expected_type, actual_type), trace
4040
)
4141
if expected_type in (str, int, bool) and expected != actual:
42-
raise SubsetException("expected `{}`, got: `{}`".format(expected, actual), trace)
42+
if expected_type == str and actual.startswith(base_dir):
43+
if actual.replace(base_dir + "/", "") != expected:
44+
raise SubsetException(
45+
"expected `{}`, got: `{}`".format(
46+
expected, actual.replace(base_dir + "/", "")
47+
),
48+
trace,
49+
)
50+
else:
51+
raise SubsetException(
52+
"expected `{}`, got: `{}`".format(expected, actual), trace
53+
)
4354
if expected_type is dict:
4455
for key in expected:
4556
if key not in actual:
46-
raise SubsetException("Key `{}` not found in output".format(key), trace)
57+
raise SubsetException(
58+
"Key `{}` not found in output".format(key), trace
59+
)
4760
new_trace = copy.deepcopy(trace)
4861
new_trace.append(key)
4962
_check_subset(expected[key], actual[key], new_trace)
@@ -52,16 +65,23 @@ def _check_subset(expected, actual, trace):
5265
actual_elements = len(actual)
5366
if expected_elements != actual_elements:
5467
raise SubsetException(
55-
"Found {} items, expected {}".format(expected_elements, actual_elements), trace
68+
"Found {} items, expected {}".format(
69+
expected_elements, actual_elements
70+
),
71+
trace,
5672
)
5773
for expected, actual in zip(expected, actual):
5874
new_trace = copy.deepcopy(trace)
5975
new_trace.append(expected)
6076
_check_subset(expected, actual, new_trace)
6177
elif expected_type is ID and expected not in already_checked:
6278
already_checked.add(expected)
63-
_check_subset(expected_index.get(expected, {}), actual_index.get(actual, {}), trace)
64-
_check_subset(expected_paths.get(expected, {}), actual_paths.get(actual, {}), trace)
79+
_check_subset(
80+
expected_index.get(expected, {}), actual_index.get(actual, {}), trace
81+
)
82+
_check_subset(
83+
expected_paths.get(expected, {}), actual_paths.get(actual, {}), trace
84+
)
6585

6686
_check_subset(expected_main["root"], actual_main["root"], [])
6787

@@ -90,18 +110,22 @@ def rustdoc_object_hook(obj):
90110
return obj
91111

92112

93-
def main(expected_fpath, actual_fpath):
94-
print("checking that {} is a logical subset of {}".format(expected_fpath, actual_fpath))
113+
def main(expected_fpath, actual_fpath, base_dir):
114+
print(
115+
"checking that {} is a logical subset of {}".format(
116+
expected_fpath, actual_fpath
117+
)
118+
)
95119
with open(expected_fpath) as expected_file:
96120
expected_main = json.load(expected_file, object_hook=rustdoc_object_hook)
97121
with open(actual_fpath) as actual_file:
98122
actual_main = json.load(actual_file, object_hook=rustdoc_object_hook)
99-
check_subset(expected_main, actual_main)
123+
check_subset(expected_main, actual_main, base_dir)
100124
print("all checks passed")
101125

102126

103127
if __name__ == "__main__":
104-
if len(sys.argv) < 3:
105-
print("Usage: `compare.py expected.json actual.json`")
128+
if len(sys.argv) < 4:
129+
print("Usage: `compare.py expected.json actual.json test-dir`")
106130
else:
107-
main(sys.argv[1], sys.argv[2])
131+
main(sys.argv[1], sys.argv[2], sys.argv[3])

src/tools/compiletest/src/common.rs

+3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pub enum Mode {
1717
DebugInfo,
1818
Codegen,
1919
Rustdoc,
20+
RustdocJson,
2021
CodegenUnits,
2122
Incremental,
2223
RunMake,
@@ -48,6 +49,7 @@ impl FromStr for Mode {
4849
"debuginfo" => Ok(DebugInfo),
4950
"codegen" => Ok(Codegen),
5051
"rustdoc" => Ok(Rustdoc),
52+
"rustdoc-json" => Ok(RustdocJson),
5153
"codegen-units" => Ok(CodegenUnits),
5254
"incremental" => Ok(Incremental),
5355
"run-make" => Ok(RunMake),
@@ -70,6 +72,7 @@ impl fmt::Display for Mode {
7072
DebugInfo => "debuginfo",
7173
Codegen => "codegen",
7274
Rustdoc => "rustdoc",
75+
RustdocJson => "rustdoc-json",
7376
CodegenUnits => "codegen-units",
7477
Incremental => "incremental",
7578
RunMake => "run-make",

src/tools/compiletest/src/main.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
6868
"mode",
6969
"which sort of compile tests to run",
7070
"compile-fail | run-fail | run-pass-valgrind | pretty | debug-info | codegen | rustdoc \
71-
codegen-units | incremental | run-make | ui | js-doc-test | mir-opt | assembly",
71+
| rustdoc-json | codegen-units | incremental | run-make | ui | js-doc-test | mir-opt | assembly",
7272
)
7373
.reqopt(
7474
"",

src/tools/compiletest/src/runtest.rs

+58-9
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
use crate::common::{expected_output_path, UI_EXTENSIONS, UI_FIXED, UI_STDERR, UI_STDOUT};
44
use crate::common::{output_base_dir, output_base_name, output_testname_unique};
5-
use crate::common::{Assembly, Incremental, JsDocTest, MirOpt, RunMake, Ui};
5+
use crate::common::{Assembly, Incremental, JsDocTest, MirOpt, RunMake, RustdocJson, Ui};
66
use crate::common::{Codegen, CodegenUnits, DebugInfo, Debugger, Rustdoc};
77
use crate::common::{CompareMode, FailMode, PassMode};
88
use crate::common::{CompileFail, Pretty, RunFail, RunPassValgrind};
@@ -342,6 +342,7 @@ impl<'test> TestCx<'test> {
342342
DebugInfo => self.run_debuginfo_test(),
343343
Codegen => self.run_codegen_test(),
344344
Rustdoc => self.run_rustdoc_test(),
345+
RustdocJson => self.run_rustdoc_json_test(),
345346
CodegenUnits => self.run_codegen_units_test(),
346347
Incremental => self.run_incremental_test(),
347348
RunMake => self.run_rmake_test(),
@@ -1564,7 +1565,7 @@ impl<'test> TestCx<'test> {
15641565
self.compose_and_run_compiler(rustc, None)
15651566
}
15661567

1567-
fn document(&self, out_dir: &Path) -> ProcRes {
1568+
fn document(&self, out_dir: &Path, json: bool) -> ProcRes {
15681569
if self.props.build_aux_docs {
15691570
for rel_ab in &self.props.aux_builds {
15701571
let aux_testpaths = self.compute_aux_test_paths(rel_ab);
@@ -1578,7 +1579,7 @@ impl<'test> TestCx<'test> {
15781579
};
15791580
// Create the directory for the stdout/stderr files.
15801581
create_dir_all(aux_cx.output_base_dir()).unwrap();
1581-
let auxres = aux_cx.document(out_dir);
1582+
let auxres = aux_cx.document(out_dir, json);
15821583
if !auxres.status.success() {
15831584
return auxres;
15841585
}
@@ -1600,6 +1601,10 @@ impl<'test> TestCx<'test> {
16001601
.arg(&self.testpaths.file)
16011602
.args(&self.props.compile_flags);
16021603

1604+
if json {
1605+
rustdoc.arg("--output-format").arg("json");
1606+
}
1607+
16031608
if let Some(ref linker) = self.config.linker {
16041609
rustdoc.arg(format!("-Clinker={}", linker));
16051610
}
@@ -1887,7 +1892,9 @@ impl<'test> TestCx<'test> {
18871892
}
18881893

18891894
fn is_rustdoc(&self) -> bool {
1890-
self.config.src_base.ends_with("rustdoc-ui") || self.config.src_base.ends_with("rustdoc-js")
1895+
self.config.src_base.ends_with("rustdoc-ui")
1896+
|| self.config.src_base.ends_with("rustdoc-js")
1897+
|| self.config.src_base.ends_with("rustdoc-json")
18911898
}
18921899

18931900
fn make_compile_args(
@@ -1968,8 +1975,8 @@ impl<'test> TestCx<'test> {
19681975

19691976
rustc.arg(dir_opt);
19701977
}
1971-
RunFail | RunPassValgrind | Pretty | DebugInfo | Codegen | Rustdoc | RunMake
1972-
| CodegenUnits | JsDocTest | Assembly => {
1978+
RunFail | RunPassValgrind | Pretty | DebugInfo | Codegen | Rustdoc | RustdocJson
1979+
| RunMake | CodegenUnits | JsDocTest | Assembly => {
19731980
// do not use JSON output
19741981
}
19751982
}
@@ -2329,7 +2336,7 @@ impl<'test> TestCx<'test> {
23292336
let _ = fs::remove_dir_all(&out_dir);
23302337
create_dir_all(&out_dir).unwrap();
23312338

2332-
let proc_res = self.document(&out_dir);
2339+
let proc_res = self.document(&out_dir, false);
23332340
if !proc_res.status.success() {
23342341
self.fatal_proc_rec("rustdoc failed!", &proc_res);
23352342
}
@@ -2385,7 +2392,7 @@ impl<'test> TestCx<'test> {
23852392
rustc.arg("-L").arg(&new_rustdoc.aux_output_dir_name());
23862393
new_rustdoc.build_all_auxiliary(&mut rustc);
23872394

2388-
let proc_res = new_rustdoc.document(&compare_dir);
2395+
let proc_res = new_rustdoc.document(&compare_dir, false);
23892396
if !proc_res.status.success() {
23902397
proc_res.fatal(Some("failed to run nightly rustdoc"), || ());
23912398
}
@@ -2466,6 +2473,48 @@ impl<'test> TestCx<'test> {
24662473
eprintln!("{}", String::from_utf8_lossy(&output.stderr));
24672474
}
24682475

2476+
fn run_rustdoc_json_test(&self) {
2477+
//FIXME: Add bless option.
2478+
2479+
assert!(self.revision.is_none(), "revisions not relevant here");
2480+
2481+
let out_dir = self.output_base_dir();
2482+
let _ = fs::remove_dir_all(&out_dir);
2483+
create_dir_all(&out_dir).unwrap();
2484+
2485+
let proc_res = self.document(&out_dir, true);
2486+
if !proc_res.status.success() {
2487+
self.fatal_proc_rec("rustdoc failed!", &proc_res);
2488+
}
2489+
2490+
let root = self.config.find_rust_src_root().unwrap();
2491+
let mut json_out = out_dir.join(self.testpaths.file.file_stem().unwrap());
2492+
json_out.set_extension("json");
2493+
let res = self.cmd2procres(
2494+
Command::new(&self.config.docck_python)
2495+
.arg(root.join("src/test/rustdoc-json/check_missing_items.py"))
2496+
.arg(&json_out),
2497+
);
2498+
2499+
if !res.status.success() {
2500+
self.fatal_proc_rec("check_missing_items failed!", &res);
2501+
}
2502+
2503+
let mut expected = self.testpaths.file.clone();
2504+
expected.set_extension("expected");
2505+
let res = self.cmd2procres(
2506+
Command::new(&self.config.docck_python)
2507+
.arg(root.join("src/test/rustdoc-json/compare.py"))
2508+
.arg(&expected)
2509+
.arg(&json_out)
2510+
.arg(&expected.parent().unwrap()),
2511+
);
2512+
2513+
if !res.status.success() {
2514+
self.fatal_proc_rec("compare failed!", &res);
2515+
}
2516+
}
2517+
24692518
fn get_lines<P: AsRef<Path>>(
24702519
&self,
24712520
path: &P,
@@ -3003,7 +3052,7 @@ impl<'test> TestCx<'test> {
30033052
if let Some(nodejs) = &self.config.nodejs {
30043053
let out_dir = self.output_base_dir();
30053054

3006-
self.document(&out_dir);
3055+
self.document(&out_dir, false);
30073056

30083057
let root = self.config.find_rust_src_root().unwrap();
30093058
let file_stem =

0 commit comments

Comments
 (0)