From b06ccb45abb5c9ea0b55c8ff8a32831188c2403f Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 6 Jul 2011 14:29:50 -0700 Subject: [PATCH] Begin adding unit testing infrastructure to the compiler Add a --test flag and a pass for transforming the AST to generate a test harness. Issue #428 --- src/comp/driver/rustc.rs | 13 ++++++++--- src/comp/driver/session.rs | 3 ++- src/comp/front/test.rs | 44 ++++++++++++++++++++++++++++++++++++++ src/comp/rustc.rc | 1 + src/comp/syntax/fold.rs | 1 + 5 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 src/comp/front/test.rs diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs index 80b94be4c53..f1bd93a4a5d 100644 --- a/src/comp/driver/rustc.rs +++ b/src/comp/driver/rustc.rs @@ -106,6 +106,10 @@ fn compile_input(session::session sess, ast::crate_cfg cfg, str input, if (sess.get_opts().output_type == link::output_type_none) { ret; } crate = time(time_passes, "configuration", bind front::config::strip_unconfigured_items(crate)); + if (sess.get_opts().test) { + crate = time(time_passes, "building test harness", + bind front::test::modify_for_testing(sess, crate)); + } auto ast_map = time(time_passes, "ast indexing", bind middle::ast_map::map_crate(*crate)); auto d = @@ -229,7 +233,8 @@ fn usage(str argv0) { --time-passes time the individual phases of the compiler --time-llvm-passes time the individual phases of the LLVM backend --sysroot override the system root (default: rustc's directory) - --no-typestate don't run the typestate pass (unsafe!)\n\n"); + --no-typestate don't run the typestate pass (unsafe!) + --test build test harness\n\n"); } fn get_os(str triple) -> session::os { @@ -324,6 +329,7 @@ fn build_session_options(str binary, getopts::match match, str binary_dir) -> case (some(?s)) { s } }; auto cfg = parse_cfgspecs(getopts::opt_strs(match, "cfg")); + auto test = opt_present(match, "test"); let @session::options sopts = @rec(shared=shared, optimize=opt_level, @@ -337,7 +343,8 @@ fn build_session_options(str binary, getopts::match match, str binary_dir) -> output_type=output_type, library_search_paths=library_search_paths, sysroot=sysroot, - cfg=cfg); + cfg=cfg, + test=test); ret sopts; } @@ -367,7 +374,7 @@ fn main(vec[str] args) { optflag("c"), optopt("o"), optflag("g"), optflag("save-temps"), optopt("sysroot"), optflag("stats"), optflag("time-passes"), optflag("time-llvm-passes"), optflag("no-typestate"), - optflag("noverify"), optmulti("cfg")]; + optflag("noverify"), optmulti("cfg"), optflag("test")]; auto binary = vec::shift[str](args); auto binary_dir = fs::dirname(binary); auto match = diff --git a/src/comp/driver/session.rs b/src/comp/driver/session.rs index 3dc947477b8..7dce5b9b068 100644 --- a/src/comp/driver/session.rs +++ b/src/comp/driver/session.rs @@ -37,7 +37,8 @@ str sysroot, // The crate config requested for the session, which may be combined // with additional crate configurations during the compile process - ast::crate_cfg cfg); + ast::crate_cfg cfg, + bool test); type crate_metadata = rec(str name, vec[u8] data); diff --git a/src/comp/front/test.rs b/src/comp/front/test.rs new file mode 100644 index 00000000000..376efc7932e --- /dev/null +++ b/src/comp/front/test.rs @@ -0,0 +1,44 @@ +import driver::session; +import syntax::ast; +import syntax::fold; + +export modify_for_testing; + +type test_ctxt = rec(@session::session sess); + +// Traverse the crate, collecting all the test functions, eliding any +// existing main functions, and synthesizing a main test harness +fn modify_for_testing(&session::session sess, + @ast::crate crate) -> @ast::crate { + + auto cx = rec(sess = @sess); + + auto precursor = rec(fold_crate = bind fold_crate(cx, _, _) + with *fold::default_ast_fold()); + + auto fold = fold::make_fold(precursor); + auto res = @fold.fold_crate(*crate); + // FIXME: This is necessary to break a circular reference + fold::dummy_out(fold); + ret res; +} + +fn fold_crate(&test_ctxt cx, &ast::crate_ c, + fold::ast_fold fld) -> ast::crate_ { + auto folded = fold::noop_fold_crate(c, fld); + ret rec(module = add_test_module(folded.module) + with folded); +} + +fn add_test_module(&ast::_mod m) -> ast::_mod { + ret m; +} + +// Local Variables: +// mode: rust +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/comp/rustc.rc b/src/comp/rustc.rc index fe97761cf8c..69336c5cb61 100644 --- a/src/comp/rustc.rc +++ b/src/comp/rustc.rc @@ -66,6 +66,7 @@ mod syntax { mod front { mod attr; mod config; + mod test; } mod back { diff --git a/src/comp/syntax/fold.rs b/src/comp/syntax/fold.rs index 64c28ad829a..c53665cf71c 100644 --- a/src/comp/syntax/fold.rs +++ b/src/comp/syntax/fold.rs @@ -10,6 +10,7 @@ export default_ast_fold; export make_fold; export dummy_out; +export noop_fold_crate; type ast_fold = @mutable a_f; -- GitLab