From edc9191921a9ef8ff8438a10b5f315ae9190e48c Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Sat, 9 Aug 2014 00:01:05 +1000 Subject: [PATCH] testsuite: implement #[reexport_test_harness_name] to get access to the default entrypoint of the --test binary. This allows one to, e.g., run tests under libgreen by starting it manually, passing in the test entrypoint. --- src/librustc/front/test.rs | 61 +++++++++++++------ src/librustuv/lib.rs | 8 +-- src/libstd/lib.rs | 8 +-- src/test/run-pass/core-run-destroy.rs | 4 +- .../run-pass/reexport-test-harness-main.rs | 21 +++++++ src/test/run-pass/tcp-connect-timeouts.rs | 3 +- 6 files changed, 75 insertions(+), 30 deletions(-) create mode 100644 src/test/run-pass/reexport-test-harness-main.rs diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs index c2581fb888f..14cda7d62c3 100644 --- a/src/librustc/front/test.rs +++ b/src/librustc/front/test.rs @@ -51,6 +51,7 @@ struct TestCtxt<'a> { ext_cx: ExtCtxt<'a>, testfns: Vec, reexport_mod_ident: ast::Ident, + reexport_test_harness_main: Option, is_test_crate: bool, config: ast::CrateConfig, } @@ -64,8 +65,16 @@ pub fn modify_for_testing(sess: &Session, // command line options. let should_test = attr::contains_name(krate.config.as_slice(), "test"); + // Check for #[reexport_test_harness_main = "some_name"] which + // creates a `use some_name = __test::main;`. This needs to be + // unconditional, so that the attribute is still marked as used in + // non-test builds. + let reexport_test_harness_main = + attr::first_attr_value_str_by_name(krate.attrs.as_slice(), + "reexport_test_harness_main"); + if should_test { - generate_test_harness(sess, krate) + generate_test_harness(sess, reexport_test_harness_main, krate) } else { strip_test_functions(krate) } @@ -79,14 +88,17 @@ struct TestHarnessGenerator<'a> { impl<'a> fold::Folder for TestHarnessGenerator<'a> { fn fold_crate(&mut self, c: ast::Crate) -> ast::Crate { - let folded = fold::noop_fold_crate(c, self); + let mut folded = fold::noop_fold_crate(c, self); // Add a special __test module to the crate that will contain code // generated for the test harness - ast::Crate { - module: add_test_module(&self.cx, &folded.module), - .. folded + let (mod_, reexport) = mk_test_module(&self.cx, &self.cx.reexport_test_harness_main); + folded.module.items.push(mod_); + match reexport { + Some(re) => folded.module.view_items.push(re), + None => {} } + folded } fn fold_item(&mut self, i: Gc) -> SmallVector> { @@ -196,7 +208,9 @@ fn mk_reexport_mod(cx: &mut TestCtxt, tests: Vec, } } -fn generate_test_harness(sess: &Session, krate: ast::Crate) -> ast::Crate { +fn generate_test_harness(sess: &Session, + reexport_test_harness_main: Option, + krate: ast::Crate) -> ast::Crate { let mut cx: TestCtxt = TestCtxt { sess: sess, 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 { path: Vec::new(), testfns: Vec::new(), reexport_mod_ident: token::gensym_ident("__test_reexports"), + reexport_test_harness_main: reexport_test_harness_main, is_test_crate: is_test_crate(&krate), config: krate.config.clone(), }; @@ -314,14 +329,6 @@ fn should_fail(i: Gc) -> bool { attr::contains_name(i.attrs.as_slice(), "should_fail") } -fn add_test_module(cx: &TestCtxt, m: &ast::Mod) -> ast::Mod { - let testmod = mk_test_module(cx); - ast::Mod { - items: m.items.clone().append_one(testmod), - ..(*m).clone() - } -} - /* 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 { } } -fn mk_test_module(cx: &TestCtxt) -> Gc { +fn mk_test_module(cx: &TestCtxt, reexport_test_harness_main: &Option) + -> (Gc, Option) { // Link to test crate let view_items = vec!(mk_std(cx)); @@ -383,18 +391,35 @@ fn mk_test_module(cx: &TestCtxt) -> Gc { }; let item_ = ast::ItemMod(testmod); + let mod_ident = token::gensym_ident("__test"); let item = ast::Item { - ident: token::gensym_ident("__test"), + ident: mod_ident, attrs: Vec::new(), id: ast::DUMMY_NODE_ID, node: item_, vis: ast::Public, span: DUMMY_SP, - }; + }; + let reexport = reexport_test_harness_main.as_ref().map(|s| { + // building `use = __test::main` + let reexport_ident = token::str_to_ident(s.get()); + + let use_path = + nospan(ast::ViewPathSimple(reexport_ident, + path_node(vec![mod_ident, token::str_to_ident("main")]), + ast::DUMMY_NODE_ID)); + + ast::ViewItem { + node: ast::ViewItemUse(box(GC) use_path), + attrs: vec![], + vis: ast::Inherited, + span: DUMMY_SP + } + }); debug!("Synthetic test module:\n{}\n", pprust::item_to_string(&item)); - box(GC) item + (box(GC) item, reexport) } fn nospan(t: T) -> codemap::Spanned { diff --git a/src/librustuv/lib.rs b/src/librustuv/lib.rs index 24b8c297858..dd80ab3ee78 100644 --- a/src/librustuv/lib.rs +++ b/src/librustuv/lib.rs @@ -48,6 +48,8 @@ via `close` and `delete` methods. #![deny(unused_result, unused_must_use)] #![allow(visible_private_types)] +#![reexport_test_harness_main = "test_main"] + #[cfg(test)] extern crate green; #[cfg(test)] extern crate debug; #[cfg(test)] extern crate realrustuv = "rustuv"; @@ -76,13 +78,9 @@ pub use self::timer::TimerWatcher; pub use self::tty::TtyWatcher; // Run tests with libgreen instead of libnative. -// -// FIXME: This egregiously hacks around starting the test runner in a different -// threading mode than the default by reaching into the auto-generated -// '__test' module. #[cfg(test)] #[start] fn start(argc: int, argv: *const *const u8) -> int { - green::start(argc, argv, event_loop, __test::main) + green::start(argc, argv, event_loop, test_main) } mod macros; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 125c3fdf5d9..20fc7efeb57 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -114,6 +114,8 @@ #![allow(deprecated)] #![deny(missing_doc)] +#![reexport_test_harness_main = "test_main"] + // When testing libstd, bring in libuv as the I/O backend so tests can print // things and all of the std::io tests have an I/O interface to run on top // of @@ -186,13 +188,9 @@ pub use unicode::char; pub use core_sync::comm; // Run tests with libgreen instead of libnative. -// -// FIXME: This egregiously hacks around starting the test runner in a different -// threading mode than the default by reaching into the auto-generated -// '__test' module. #[cfg(test)] #[start] fn start(argc: int, argv: *const *const u8) -> int { - green::start(argc, argv, rustuv::event_loop, __test::main) + green::start(argc, argv, rustuv::event_loop, test_main) } /* Exported macros */ diff --git a/src/test/run-pass/core-run-destroy.rs b/src/test/run-pass/core-run-destroy.rs index 8e84278c10e..d187a6a8afe 100644 --- a/src/test/run-pass/core-run-destroy.rs +++ b/src/test/run-pass/core-run-destroy.rs @@ -16,6 +16,8 @@ // instead of in std. #![feature(macro_rules)] +#![reexport_test_harness_main = "test_main"] + extern crate libc; extern crate native; @@ -55,7 +57,7 @@ macro_rules! iotest ( #[cfg(test)] #[start] fn start(argc: int, argv: *const *const u8) -> int { - green::start(argc, argv, rustuv::event_loop, __test::main) + green::start(argc, argv, rustuv::event_loop, test_main) } iotest!(fn test_destroy_once() { diff --git a/src/test/run-pass/reexport-test-harness-main.rs b/src/test/run-pass/reexport-test-harness-main.rs new file mode 100644 index 00000000000..309ae1bcc56 --- /dev/null +++ b/src/test/run-pass/reexport-test-harness-main.rs @@ -0,0 +1,21 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-pretty +// compile-flags:--test + +#![reexport_test_harness_main = "test_main"] + +#[cfg(test)] +fn _unused() { + // should resolve to the entry point function the --test harness + // creates. + test_main(); +} diff --git a/src/test/run-pass/tcp-connect-timeouts.rs b/src/test/run-pass/tcp-connect-timeouts.rs index d2408509fc5..6f6fff15814 100644 --- a/src/test/run-pass/tcp-connect-timeouts.rs +++ b/src/test/run-pass/tcp-connect-timeouts.rs @@ -18,6 +18,7 @@ #![feature(macro_rules, globs)] #![allow(experimental)] +#![reexport_test_harness_main = "test_main"] extern crate native; extern crate green; @@ -25,7 +26,7 @@ extern crate rustuv; #[cfg(test)] #[start] fn start(argc: int, argv: *const *const u8) -> int { - green::start(argc, argv, rustuv::event_loop, __test::main) + green::start(argc, argv, rustuv::event_loop, test_main) } macro_rules! iotest (