about summary refs log tree commit diff
path: root/src/comp/front/test.rs
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2011-07-06 16:28:07 -0700
committerBrian Anderson <banderson@mozilla.com>2011-07-06 18:26:22 -0700
commitcf4c2ac0bee9a23a5f3ec230c6ea54fb2281dbcb (patch)
treed8f55b1efc15d0d4ec80d16d412028b38870cb89 /src/comp/front/test.rs
parent6ca81b34079f6529ae385479d74496187c8063c2 (diff)
downloadrust-cf4c2ac0bee9a23a5f3ec230c6ea54fb2281dbcb.tar.gz
rust-cf4c2ac0bee9a23a5f3ec230c6ea54fb2281dbcb.zip
Generate a main fn for test running. Issue #428
Diffstat (limited to 'src/comp/front/test.rs')
-rw-r--r--src/comp/front/test.rs96
1 files changed, 79 insertions, 17 deletions
diff --git a/src/comp/front/test.rs b/src/comp/front/test.rs
index 376efc7932e..aae0af12536 100644
--- a/src/comp/front/test.rs
+++ b/src/comp/front/test.rs
@@ -1,37 +1,99 @@
-import driver::session;
+// Code that generates a test runner to run all the tests in a crate
+
+import std::option;
 import syntax::ast;
 import syntax::fold;
 
 export modify_for_testing;
 
-type test_ctxt = rec(@session::session sess);
+type node_id_gen = @fn() -> ast::node_id;
+
+type test_ctxt = rec(node_id_gen next_node_id);
 
 // 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 {
+fn modify_for_testing(@ast::crate crate) -> @ast::crate {
+
+    // FIXME: This hackasaurus assumes that 200000 is a safe number to start
+    // generating node_ids at (which is totally not the case). pauls is going
+    // to land a patch that puts parse_sess into session, which will give us
+    // access to the real next node_id.
+    auto next_node_id = @mutable 200000;
+    auto next_node_id_fn = @bind fn(@mutable ast::node_id next_node_id)
+        -> ast::node_id {
+        auto this_node_id = *next_node_id;
+        *next_node_id = next_node_id + 1;
+        ret this_node_id;
+    } (next_node_id);
 
-  auto cx = rec(sess = @sess);
+    auto cx = rec(next_node_id = next_node_id_fn);
 
-  auto precursor = rec(fold_crate = bind fold_crate(cx, _, _)
-                       with *fold::default_ast_fold());
+    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;
+    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);
+    auto folded = fold::noop_fold_crate(c, fld);
+
+    // Add a special __test module to the crate that will contain code
+    // generated for the test harness
+    ret rec(module = add_test_module(cx, folded.module)
+            with folded);
+}
+
+fn add_test_module(&test_ctxt cx, &ast::_mod m) -> ast::_mod {
+    auto testmod = mk_test_module(cx);
+    ret rec(items = m.items + [testmod]
+            with m);
 }
 
-fn add_test_module(&ast::_mod m) -> ast::_mod {
-  ret m;
+fn mk_test_module(&test_ctxt cx) -> @ast::item {
+    auto mainfn = mk_main(cx);
+    let ast::_mod testmod = rec(view_items = [],
+                                items = [mainfn]);
+    auto item_ = ast::item_mod(testmod);
+    let ast::item item = rec(ident = "__test",
+                             attrs = ~[],
+                             id = cx.next_node_id(),
+                             node = item_,
+                             span = rec(lo=0u, hi=0u));
+    ret @item;
+}
+
+fn mk_main(&test_ctxt cx) -> @ast::item {
+    auto ret_ty = @rec(node=ast::ty_nil,
+                       span=rec(lo=0u, hi=0u));
+
+    let ast::fn_decl decl = rec(inputs = [],
+                                output = ret_ty,
+                                purity = ast::impure_fn,
+                                cf = ast::return,
+                                constraints = ~[]);
+    auto proto = ast::proto_fn;
+
+    let ast::block_ body_ = rec(stmts = [],
+                                 expr = option::none,
+                                 id = cx.next_node_id());
+    auto body = rec(node = body_, span = rec(lo=0u, hi=0u));
+
+    auto fn_ = rec(decl = decl,
+                   proto = proto,
+                   body = body);
+
+    auto item_ = ast::item_fn(fn_, []);
+    let ast::item item = rec(ident = "main",
+                             attrs = ~[],
+                             id = cx.next_node_id(),
+                             node = item_,
+                             span = rec(lo=0u, hi=0u));
+    ret @item;
 }
 
 // Local Variables: