Skip to content

Commit 895011d

Browse files
committed
Combine run-pass tests into a single crate
1 parent bbb9523 commit 895011d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1085
-263
lines changed

config.toml.example

+3
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,9 @@
290290
# desired in distributions, for example.
291291
#rpath = true
292292

293+
# Merge Rust test files into larger units for faster testing
294+
#combine-tests = false
295+
293296
# Suppresses extraneous output from tests to ensure the output of the test
294297
# harness is relatively clean.
295298
#quiet-tests = false

src/bootstrap/config.rs

+3
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ pub struct Config {
119119
pub low_priority: bool,
120120
pub channel: String,
121121
pub quiet_tests: bool,
122+
pub combine_tests: bool,
122123
pub test_miri: bool,
123124
pub save_toolstates: Option<PathBuf>,
124125
pub print_step_timings: bool,
@@ -290,6 +291,7 @@ struct Rust {
290291
debug: Option<bool>,
291292
dist_src: Option<bool>,
292293
quiet_tests: Option<bool>,
294+
combine_tests: Option<bool>,
293295
test_miri: Option<bool>,
294296
save_toolstates: Option<String>,
295297
codegen_backends: Option<Vec<String>>,
@@ -481,6 +483,7 @@ impl Config {
481483
set(&mut config.backtrace, rust.backtrace);
482484
set(&mut config.channel, rust.channel.clone());
483485
set(&mut config.rust_dist_src, rust.dist_src);
486+
set(&mut config.combine_tests, rust.combine_tests);
484487
set(&mut config.quiet_tests, rust.quiet_tests);
485488
set(&mut config.test_miri, rust.test_miri);
486489
set(&mut config.wasm_syscall, rust.wasm_syscall);

src/bootstrap/configure.py

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ def v(*args):
4848
o("test-miri", "rust.test-miri", "run miri's test suite")
4949
o("debuginfo-tests", "rust.debuginfo-tests", "build tests with debugger metadata")
5050
o("quiet-tests", "rust.quiet-tests", "enable quieter output when running tests")
51+
o("combined-tests", "rust.combine-tests", "merge tests together when possible")
5152
o("ccache", "llvm.ccache", "invoke gcc/clang via ccache to reuse object files between builds")
5253
o("sccache", None, "invoke gcc/clang via sccache to reuse object files between builds")
5354
o("local-rust", None, "use an installed rustc rather than downloading a snapshot")

src/bootstrap/test.rs

+4
Original file line numberDiff line numberDiff line change
@@ -851,6 +851,10 @@ impl Step for Compiletest {
851851
cmd.arg("--run-lib-path").arg(builder.sysroot_libdir(compiler, target));
852852
cmd.arg("--rustc-path").arg(builder.rustc(compiler));
853853

854+
if builder.config.combine_tests && mode == "run-pass" {
855+
cmd.arg("--combine");
856+
}
857+
854858
// Avoid depending on rustdoc when we don't need it.
855859
if mode == "rustdoc" || (mode == "run-make" && suite.ends_with("fulldeps")) {
856860
cmd.arg("--rustdoc-path").arg(builder.rustdoc(compiler.host));

src/librustc/session/config.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1114,6 +1114,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
11141114
"generate comments into the assembly (may change behavior)"),
11151115
no_verify: bool = (false, parse_bool, [TRACKED],
11161116
"skip LLVM verification"),
1117+
combine_tests: bool = (false, parse_bool, [TRACKED],
1118+
"pretend immediate submodules of the crate are crates themselves"),
11171119
borrowck_stats: bool = (false, parse_bool, [UNTRACKED],
11181120
"gather borrowck statistics"),
11191121
no_landing_pads: bool = (false, parse_bool, [TRACKED],

src/librustc/session/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1095,7 +1095,8 @@ pub fn build_session_(
10951095
};
10961096
let target_cfg = config::build_target_config(&sopts, &span_diagnostic);
10971097

1098-
let p_s = parse::ParseSess::with_span_handler(span_diagnostic, codemap);
1098+
let mut p_s = parse::ParseSess::with_span_handler(span_diagnostic, codemap);
1099+
p_s.combine_tests = sopts.debugging_opts.combine_tests;
10991100
let default_sysroot = match sopts.maybe_sysroot {
11001101
Some(_) => None,
11011102
None => Some(filesearch::get_or_default_sysroot()),

src/librustc_driver/driver.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -847,12 +847,30 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
847847
});
848848
}
849849

850+
if sess.opts.debugging_opts.ast_json_noexpand {
851+
println!("\n\n\n\n\n\n\n\nPRE EXPAND:");
852+
println!("{}", json::as_json(&krate));
853+
}
854+
850855
krate = time(sess, "creating allocators", || {
851856
allocator::expand::modify(&sess.parse_sess,
852857
&mut resolver,
853858
krate,
854859
sess.diagnostic())
855860
});
861+
/*
862+
if sess.opts.debugging_opts.submodules_crate_like {
863+
krate = time(sess,
864+
"Pretending submodules are crates",
865+
|| rustc_passes::submodules_crate_like::modify_crate(krate));
866+
eprintln!("expanded module");
867+
}
868+
*/
869+
if sess.opts.debugging_opts.ast_json_noexpand {
870+
println!("\n\n\n\n\n\n\n\nPOST EXPAND: {:#?}", krate);
871+
println!("\n\n\n\n\n\n\n\nPOST EXPAND:");
872+
println!("{}", json::as_json(&krate));
873+
}
856874

857875
after_expand(&krate)?;
858876

@@ -884,7 +902,8 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
884902
&sess.parse_sess,
885903
&sess.features_untracked(),
886904
&attributes,
887-
sess.opts.unstable_features);
905+
sess.opts.unstable_features,
906+
sess.opts.debugging_opts.edition);
888907
})
889908
})?;
890909

src/librustc_driver/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -901,8 +901,8 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
901901
}
902902

903903
if sess.opts.debugging_opts.parse_only ||
904-
sess.opts.debugging_opts.show_span.is_some() ||
905-
sess.opts.debugging_opts.ast_json_noexpand {
904+
sess.opts.debugging_opts.show_span.is_some()/* ||
905+
sess.opts.debugging_opts.ast_json_noexpand*/ {
906906
control.after_parse.stop = Compilation::Stop;
907907
}
908908

src/libsyntax/combine_tests.rs

+211
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use ast::*;
12+
use ptr::P;
13+
use fold;
14+
use fold::Folder;
15+
use symbol::keywords;
16+
use codemap::dummy_spanned;
17+
use syntax_pos::DUMMY_SP;
18+
use syntax_pos::symbol::Symbol;
19+
use ext::base::ExtCtxt;
20+
21+
pub struct RootPathFolder<'a, 'b: 'a> {
22+
pub cx: &'a mut ExtCtxt<'b>,
23+
}
24+
25+
impl<'a, 'b> fold::Folder for RootPathFolder<'a, 'b> {
26+
fn fold_item_simple(&mut self, item: Item) -> Item {
27+
if item.ident.name == keywords::Invalid.name() {
28+
return fold::noop_fold_item_simple(item, self)
29+
}
30+
if let ItemKind::Mod(..) = item.node {
31+
make_crate_like_module(item, self.cx)
32+
} else {
33+
fold::noop_fold_item_simple(item, self)
34+
}
35+
}
36+
37+
fn fold_mac(&mut self, mac: Mac) -> Mac {
38+
mac
39+
}
40+
}
41+
42+
pub struct PathFolder {
43+
pub root: Ident,
44+
}
45+
46+
impl PathFolder {
47+
fn fold_qpath(&mut self, qself: &mut Option<QSelf>, path: &mut Path) {
48+
let old = path.segments.len();
49+
*path = self.fold_path(path.clone());
50+
let add = path.segments.len() - old;
51+
qself.as_mut().map(|qself| {
52+
qself.position += add;
53+
qself.ty = self.fold_ty(qself.ty.clone());
54+
});
55+
}
56+
57+
fn fold_absolute_path(&mut self, path: &mut Path) {
58+
let pos = {
59+
let get = |i| {
60+
path.segments.get(i).map(|p: &PathSegment| p.identifier.name)
61+
};
62+
if get(0) == Some(keywords::SelfValue.name()) ||
63+
get(0) == Some(keywords::DollarCrate.name()) ||
64+
get(0) == Some(keywords::Super.name()) {
65+
None
66+
} else {
67+
let mut i = 0;
68+
if get(i) == Some(keywords::CrateRoot.name()) {
69+
i += 1;
70+
}
71+
if get(i) == Some(keywords::Crate.name()) {
72+
i += 1;
73+
}
74+
Some(i)
75+
}
76+
};
77+
if let Some(pos) = pos {
78+
path.segments.insert(pos, PathSegment {
79+
identifier: self.root,
80+
span: path.span,
81+
parameters: None,
82+
});
83+
}
84+
}
85+
}
86+
87+
impl fold::Folder for PathFolder {
88+
fn fold_use_tree(&mut self, mut use_tree: UseTree) -> UseTree {
89+
self.fold_absolute_path(&mut use_tree.prefix);
90+
use_tree
91+
}
92+
93+
fn fold_vis(&mut self, mut vis: Visibility) -> Visibility {
94+
match vis.node {
95+
VisibilityKind::Restricted { ref mut path, .. } => self.fold_absolute_path(path),
96+
_ => (),
97+
}
98+
vis
99+
}
100+
101+
fn fold_path(&mut self, mut p: Path) -> Path {
102+
if let Some(first) = p.segments.first().cloned() {
103+
if first.identifier.name == keywords::CrateRoot.name() {
104+
let idx = if p.segments.get(1).map(|p| p.identifier.name) ==
105+
Some(keywords::Crate.name()) {
106+
2
107+
} else {
108+
1
109+
};
110+
p.segments.insert(idx, PathSegment {
111+
identifier: self.root,
112+
span: p.span,
113+
parameters: None,
114+
});
115+
}
116+
}
117+
fold::noop_fold_path(p, self)
118+
}
119+
120+
fn fold_ty(&mut self, mut t: P<Ty>) -> P<Ty> {
121+
if match t.node {
122+
TyKind::Path(ref mut qself, ref mut path) => {
123+
self.fold_qpath(qself, path);
124+
true
125+
}
126+
_ => false,
127+
} {
128+
return t;
129+
}
130+
fold::noop_fold_ty(t, self)
131+
}
132+
133+
fn fold_pat(&mut self, mut p: P<Pat>) -> P<Pat> {
134+
if match p.node {
135+
PatKind::Path(ref mut qself, ref mut path) => {
136+
self.fold_qpath(qself, path);
137+
true
138+
}
139+
_ => false,
140+
} {
141+
return p;
142+
}
143+
fold::noop_fold_pat(p, self)
144+
}
145+
146+
fn fold_expr(&mut self, mut e: P<Expr>) -> P<Expr> {
147+
if match e.node {
148+
ExprKind::Path(ref mut qself, ref mut path) => {
149+
self.fold_qpath(qself, path);
150+
true
151+
}
152+
_ => false,
153+
} {
154+
return e;
155+
}
156+
e.map(|e| fold::noop_fold_expr(e, self))
157+
}
158+
159+
fn fold_mac(&mut self, mut mac: Mac) -> Mac {
160+
mac.node.path = self.fold_path(mac.node.path);
161+
mac
162+
}
163+
}
164+
165+
pub fn make_crate_like_module(mut item: Item, cx: &mut ExtCtxt) -> Item {
166+
// Add the module as a prefix on all absolute paths
167+
let mut folder = PathFolder {
168+
root: item.ident
169+
};
170+
item = folder.fold_item_simple(item);
171+
172+
// Create a `use std` item
173+
let std_i = Ident::from_str("std");
174+
let use_std = Item {
175+
ident: keywords::Invalid.ident(),
176+
attrs: Vec::new(),
177+
id: cx.resolver.next_node_id(),
178+
node: ItemKind::Use(P(UseTree {
179+
span: DUMMY_SP,
180+
kind: UseTreeKind::Simple(Some(std_i)),
181+
prefix: Path {
182+
segments: vec![PathSegment {
183+
identifier: std_i,
184+
span: DUMMY_SP,
185+
parameters: None,
186+
}],
187+
span: DUMMY_SP,
188+
},
189+
})),
190+
vis: dummy_spanned(VisibilityKind::Inherited),
191+
span: DUMMY_SP,
192+
tokens: None,
193+
};
194+
195+
match item.node {
196+
ItemKind::Mod(ref mut module) => {
197+
// Add the `use std` item to the module
198+
module.items.push(P(use_std.clone()));
199+
200+
// Make `main` public
201+
let main = Symbol::intern("main");
202+
for mut item in &mut module.items {
203+
if item.ident.name == main {
204+
item.vis = dummy_spanned(VisibilityKind::Public);
205+
}
206+
}
207+
}
208+
_ => panic!("expected module"),
209+
}
210+
item
211+
}

0 commit comments

Comments
 (0)