@@ -51,6 +51,7 @@ struct TestCtxt<'a> {
51
51
ext_cx : ExtCtxt < ' a > ,
52
52
testfns : Vec < Test > ,
53
53
reexport_mod_ident : ast:: Ident ,
54
+ reexport_test_harness_main : Option < InternedString > ,
54
55
is_test_crate : bool ,
55
56
config : ast:: CrateConfig ,
56
57
}
@@ -64,8 +65,16 @@ pub fn modify_for_testing(sess: &Session,
64
65
// command line options.
65
66
let should_test = attr:: contains_name ( krate. config . as_slice ( ) , "test" ) ;
66
67
68
+ // Check for #[reexport_test_harness_main = "some_name"] which
69
+ // creates a `use some_name = __test::main;`. This needs to be
70
+ // unconditional, so that the attribute is still marked as used in
71
+ // non-test builds.
72
+ let reexport_test_harness_main =
73
+ attr:: first_attr_value_str_by_name ( krate. attrs . as_slice ( ) ,
74
+ "reexport_test_harness_main" ) ;
75
+
67
76
if should_test {
68
- generate_test_harness ( sess, krate)
77
+ generate_test_harness ( sess, reexport_test_harness_main , krate)
69
78
} else {
70
79
strip_test_functions ( krate)
71
80
}
@@ -79,14 +88,17 @@ struct TestHarnessGenerator<'a> {
79
88
80
89
impl < ' a > fold:: Folder for TestHarnessGenerator < ' a > {
81
90
fn fold_crate ( & mut self , c : ast:: Crate ) -> ast:: Crate {
82
- let folded = fold:: noop_fold_crate ( c, self ) ;
91
+ let mut folded = fold:: noop_fold_crate ( c, self ) ;
83
92
84
93
// Add a special __test module to the crate that will contain code
85
94
// generated for the test harness
86
- ast:: Crate {
87
- module : add_test_module ( & self . cx , & folded. module ) ,
88
- .. folded
95
+ let ( mod_, reexport) = mk_test_module ( & self . cx , & self . cx . reexport_test_harness_main ) ;
96
+ folded. module . items . push ( mod_) ;
97
+ match reexport {
98
+ Some ( re) => folded. module . view_items . push ( re) ,
99
+ None => { }
89
100
}
101
+ folded
90
102
}
91
103
92
104
fn fold_item ( & mut self , i : Gc < ast:: Item > ) -> SmallVector < Gc < ast:: Item > > {
@@ -196,7 +208,9 @@ fn mk_reexport_mod(cx: &mut TestCtxt, tests: Vec<ast::Ident>,
196
208
}
197
209
}
198
210
199
- fn generate_test_harness ( sess : & Session , krate : ast:: Crate ) -> ast:: Crate {
211
+ fn generate_test_harness ( sess : & Session ,
212
+ reexport_test_harness_main : Option < InternedString > ,
213
+ krate : ast:: Crate ) -> ast:: Crate {
200
214
let mut cx: TestCtxt = TestCtxt {
201
215
sess : sess,
202
216
ext_cx : ExtCtxt :: new ( & sess. parse_sess , sess. opts . cfg . clone ( ) ,
@@ -207,6 +221,7 @@ fn generate_test_harness(sess: &Session, krate: ast::Crate) -> ast::Crate {
207
221
path : Vec :: new ( ) ,
208
222
testfns : Vec :: new ( ) ,
209
223
reexport_mod_ident : token:: gensym_ident ( "__test_reexports" ) ,
224
+ reexport_test_harness_main : reexport_test_harness_main,
210
225
is_test_crate : is_test_crate ( & krate) ,
211
226
config : krate. config . clone ( ) ,
212
227
} ;
@@ -314,14 +329,6 @@ fn should_fail(i: Gc<ast::Item>) -> bool {
314
329
attr:: contains_name ( i. attrs . as_slice ( ) , "should_fail" )
315
330
}
316
331
317
- fn add_test_module ( cx : & TestCtxt , m : & ast:: Mod ) -> ast:: Mod {
318
- let testmod = mk_test_module ( cx) ;
319
- ast:: Mod {
320
- items : m. items . clone ( ) . append_one ( testmod) ,
321
- ..( * m) . clone ( )
322
- }
323
- }
324
-
325
332
/*
326
333
327
334
We're going to be building a module that looks more or less like:
@@ -359,7 +366,8 @@ fn mk_std(cx: &TestCtxt) -> ast::ViewItem {
359
366
}
360
367
}
361
368
362
- fn mk_test_module ( cx : & TestCtxt ) -> Gc < ast:: Item > {
369
+ fn mk_test_module ( cx : & TestCtxt , reexport_test_harness_main : & Option < InternedString > )
370
+ -> ( Gc < ast:: Item > , Option < ast:: ViewItem > ) {
363
371
// Link to test crate
364
372
let view_items = vec ! ( mk_std( cx) ) ;
365
373
@@ -383,18 +391,35 @@ fn mk_test_module(cx: &TestCtxt) -> Gc<ast::Item> {
383
391
} ;
384
392
let item_ = ast:: ItemMod ( testmod) ;
385
393
394
+ let mod_ident = token:: gensym_ident ( "__test" ) ;
386
395
let item = ast:: Item {
387
- ident : token :: gensym_ident ( "__test" ) ,
396
+ ident : mod_ident ,
388
397
attrs : Vec :: new ( ) ,
389
398
id : ast:: DUMMY_NODE_ID ,
390
399
node : item_,
391
400
vis : ast:: Public ,
392
401
span : DUMMY_SP ,
393
- } ;
402
+ } ;
403
+ let reexport = reexport_test_harness_main. as_ref ( ) . map ( |s| {
404
+ // building `use <ident> = __test::main`
405
+ let reexport_ident = token:: str_to_ident ( s. get ( ) ) ;
406
+
407
+ let use_path =
408
+ nospan ( ast:: ViewPathSimple ( reexport_ident,
409
+ path_node ( vec ! [ mod_ident, token:: str_to_ident( "main" ) ] ) ,
410
+ ast:: DUMMY_NODE_ID ) ) ;
411
+
412
+ ast:: ViewItem {
413
+ node : ast:: ViewItemUse ( box ( GC ) use_path) ,
414
+ attrs : vec ! [ ] ,
415
+ vis : ast:: Inherited ,
416
+ span : DUMMY_SP
417
+ }
418
+ } ) ;
394
419
395
420
debug ! ( "Synthetic test module:\n {}\n " , pprust:: item_to_string( & item) ) ;
396
421
397
- box ( GC ) item
422
+ ( box ( GC ) item, reexport )
398
423
}
399
424
400
425
fn nospan < T > ( t : T ) -> codemap:: Spanned < T > {
0 commit comments