Skip to content

Commit d27918a

Browse files
sfackleralexcrichton
authored andcommitted
Restructure test harness
We now build up a set of modules that reexport everything the test framework needs, instead of turning off privacy.
1 parent 456884b commit d27918a

File tree

1 file changed

+53
-32
lines changed

1 file changed

+53
-32
lines changed

src/librustc/front/test.rs

Lines changed: 53 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@ use front::config;
1818

1919
use std::gc::{Gc, GC};
2020
use std::slice;
21+
use std::mem;
2122
use std::vec;
2223
use syntax::ast_util::*;
2324
use syntax::attr::AttrMetaMethods;
2425
use syntax::attr;
2526
use syntax::codemap::{DUMMY_SP, Span, ExpnInfo, NameAndSpan, MacroAttribute};
2627
use syntax::codemap;
2728
use syntax::ext::base::ExtCtxt;
29+
use syntax::ext::build::AstBuilder;
2830
use syntax::ext::expand::ExpansionConfig;
2931
use syntax::fold::Folder;
3032
use syntax::fold;
@@ -46,8 +48,10 @@ struct Test {
4648
struct TestCtxt<'a> {
4749
sess: &'a Session,
4850
path: Vec<ast::Ident>,
51+
reexports: Vec<Vec<ast::Ident>>,
4952
ext_cx: ExtCtxt<'a>,
5053
testfns: Vec<Test>,
54+
reexport_mod_ident: ast::Ident,
5155
is_test_crate: bool,
5256
config: ast::CrateConfig,
5357
}
@@ -107,25 +111,35 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
107111
should_fail: should_fail(i)
108112
};
109113
self.cx.testfns.push(test);
114+
self.cx.reexports.push(self.cx.path.clone());
110115
// debug!("have {} test/bench functions",
111116
// cx.testfns.len());
112117
}
113118
}
114119
}
115120

116-
let res = fold::noop_fold_item(&*i, self);
121+
// We don't want to recurse into anything other than mods, since
122+
// mods or tests inside of functions will break things
123+
let res = match i.node {
124+
ast::ItemMod(..) => fold::noop_fold_item(&*i, self),
125+
_ => SmallVector::one(i),
126+
};
117127
self.cx.path.pop();
118128
res
119129
}
120130

121131
fn fold_mod(&mut self, m: &ast::Mod) -> ast::Mod {
132+
let reexports = mem::replace(&mut self.cx.reexports, Vec::new());
133+
let mut mod_folded = fold::noop_fold_mod(m, self);
134+
let reexports = mem::replace(&mut self.cx.reexports, reexports);
135+
122136
// Remove any #[main] from the AST so it doesn't clash with
123137
// the one we're going to add. Only if compiling an executable.
124138

125139
fn nomain(item: Gc<ast::Item>) -> Gc<ast::Item> {
126140
box(GC) ast::Item {
127141
attrs: item.attrs.iter().filter_map(|attr| {
128-
if !attr.name().equiv(&("main")) {
142+
if !attr.check_name("main") {
129143
Some(*attr)
130144
} else {
131145
None
@@ -135,18 +149,37 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
135149
}
136150
}
137151

138-
let mod_nomain = ast::Mod {
139-
inner: m.inner,
140-
view_items: m.view_items.clone(),
141-
items: m.items.iter().map(|i| nomain(*i)).collect(),
142-
};
152+
for i in mod_folded.items.mut_iter() {
153+
*i = nomain(*i);
154+
}
155+
mod_folded.items.push(mk_reexport_mod(&mut self.cx, reexports));
156+
self.cx.reexports.push(self.cx.path.clone());
157+
158+
mod_folded
159+
}
160+
}
143161

144-
fold::noop_fold_mod(&mod_nomain, self)
162+
fn mk_reexport_mod(cx: &mut TestCtxt, reexports: Vec<Vec<ast::Ident>>)
163+
-> Gc<ast::Item> {
164+
let view_items = reexports.move_iter().map(|r| {
165+
cx.ext_cx.view_use_simple(DUMMY_SP, ast::Public, cx.ext_cx.path(DUMMY_SP, r))
166+
}).collect();
167+
let reexport_mod = ast::Mod {
168+
inner: DUMMY_SP,
169+
view_items: view_items,
170+
items: Vec::new(),
171+
};
172+
box(GC) ast::Item {
173+
ident: cx.reexport_mod_ident.clone(),
174+
attrs: Vec::new(),
175+
id: ast::DUMMY_NODE_ID,
176+
node: ast::ItemMod(reexport_mod),
177+
vis: ast::Public,
178+
span: DUMMY_SP,
145179
}
146180
}
147181

148-
fn generate_test_harness(sess: &Session, krate: ast::Crate)
149-
-> ast::Crate {
182+
fn generate_test_harness(sess: &Session, krate: ast::Crate) -> ast::Crate {
150183
let mut cx: TestCtxt = TestCtxt {
151184
sess: sess,
152185
ext_cx: ExtCtxt::new(&sess.parse_sess, sess.opts.cfg.clone(),
@@ -155,7 +188,9 @@ fn generate_test_harness(sess: &Session, krate: ast::Crate)
155188
crate_name: "test".to_string(),
156189
}),
157190
path: Vec::new(),
191+
reexports: Vec::new(),
158192
testfns: Vec::new(),
193+
reexport_mod_ident: token::str_to_ident("__test_reexports"),
159194
is_test_crate: is_test_crate(&krate),
160195
config: krate.config.clone(),
161196
};
@@ -170,7 +205,7 @@ fn generate_test_harness(sess: &Session, krate: ast::Crate)
170205
});
171206

172207
let mut fold = TestHarnessGenerator {
173-
cx: cx
208+
cx: cx,
174209
};
175210
let res = fold.fold_crate(krate);
176211
fold.cx.ext_cx.bt_pop();
@@ -274,7 +309,6 @@ fn add_test_module(cx: &TestCtxt, m: &ast::Mod) -> ast::Mod {
274309
We're going to be building a module that looks more or less like:
275310
276311
mod __test {
277-
#![!resolve_unexported]
278312
extern crate test (name = "test", vers = "...");
279313
fn main() {
280314
test::test_main_static(::os::args().as_slice(), tests)
@@ -331,15 +365,9 @@ fn mk_test_module(cx: &TestCtxt) -> Gc<ast::Item> {
331365
};
332366
let item_ = ast::ItemMod(testmod);
333367

334-
// This attribute tells resolve to let us call unexported functions
335-
let resolve_unexported_str = InternedString::new("!resolve_unexported");
336-
let resolve_unexported_attr =
337-
attr::mk_attr_inner(attr::mk_attr_id(),
338-
attr::mk_word_item(resolve_unexported_str));
339-
340368
let item = ast::Item {
341369
ident: token::str_to_ident("__test"),
342-
attrs: vec!(resolve_unexported_attr),
370+
attrs: Vec::new(),
343371
id: ast::DUMMY_NODE_ID,
344372
node: item_,
345373
vis: ast::Public,
@@ -367,18 +395,6 @@ fn path_node(ids: Vec<ast::Ident> ) -> ast::Path {
367395
}
368396
}
369397

370-
fn path_node_global(ids: Vec<ast::Ident> ) -> ast::Path {
371-
ast::Path {
372-
span: DUMMY_SP,
373-
global: true,
374-
segments: ids.move_iter().map(|identifier| ast::PathSegment {
375-
identifier: identifier,
376-
lifetimes: Vec::new(),
377-
types: OwnedSlice::empty(),
378-
}).collect()
379-
}
380-
}
381-
382398
fn mk_tests(cx: &TestCtxt) -> Gc<ast::Item> {
383399
// The vector of test_descs for this crate
384400
let test_descs = mk_test_descs(cx);
@@ -430,7 +446,12 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> Gc<ast::Expr> {
430446
span: span
431447
};
432448

433-
let fn_path = path_node_global(path);
449+
let mut visible_path = Vec::new();
450+
for ident in path.move_iter() {
451+
visible_path.push(cx.reexport_mod_ident.clone());
452+
visible_path.push(ident);
453+
}
454+
let fn_path = cx.ext_cx.path_global(DUMMY_SP, visible_path);
434455

435456
let fn_expr = box(GC) ast::Expr {
436457
id: ast::DUMMY_NODE_ID,

0 commit comments

Comments
 (0)