]> git.lizzy.rs Git - rust.git/commitdiff
rustc: Allow the test runner to run unexported tests
authorBrian Anderson <banderson@mozilla.com>
Fri, 6 Jan 2012 02:16:42 +0000 (18:16 -0800)
committerBrian Anderson <banderson@mozilla.com>
Fri, 6 Jan 2012 02:16:56 +0000 (18:16 -0800)
src/comp/front/test.rs
src/comp/middle/resolve.rs
src/test/run-fail/run-unexported-tests.rs [new file with mode: 0644]

index 46293c80310c4827c76e2c0372a1bbd7ae1ccca0..bb2e5426938913f9de7f2e9b0810a6add5441cb3 100644 (file)
@@ -187,9 +187,12 @@ fn mk_test_module(cx: test_ctxt) -> @ast::item {
     let mainfn = mk_main(cx);
     let testmod: ast::_mod = {view_items: [], items: [mainfn, testsfn]};
     let item_ = ast::item_mod(testmod);
+    // This attribute tells resolve to let us call unexported functions
+    let resolve_unexported_attr =
+        attr::mk_attr(attr::mk_word_item("!resolve_unexported"));
     let item: ast::item =
         {ident: "__test",
-         attrs: [],
+         attrs: [resolve_unexported_attr],
          id: cx.sess.next_node_id(),
          node: item_,
          span: dummy_sp()};
index 01be1c4409f50223e0302a523c55a2987a6a30d9..9aa57e182ccad8300b1532d7ee12ab926aeef8a9 100644 (file)
@@ -2,8 +2,9 @@
 import syntax::{ast, ast_util, codemap};
 import syntax::ast::*;
 import ast::{ident, fn_ident, def, def_id, node_id};
-import syntax::ast_util::{local_def, def_id_of_def, is_exported};
+import syntax::ast_util::{local_def, def_id_of_def};
 
+import front::attr;
 import metadata::{csearch, cstore};
 import driver::session::session;
 import util::common::*;
@@ -143,6 +144,7 @@ fn eq(v1: key, v2: key) -> bool {
      mutable reported: [{ident: str, sc: scope}],
      mutable ignored_imports: [node_id],
      mutable current_tp: option::t<uint>,
+     mutable resolve_unexported: bool,
      sess: session};
 
 
@@ -170,6 +172,7 @@ fn resolve_crate(sess: session, amap: ast_map::map, crate: @ast::crate) ->
           mutable reported: [],
           mutable ignored_imports: [],
           mutable current_tp: none,
+          mutable resolve_unexported: false,
           sess: sess};
     map_crate(e, crate);
     resolve_imports(*e);
@@ -231,7 +234,7 @@ fn path_from_scope(sc: scopes, n: str) -> str {
         path
     }
     fn index_i(e: @env, i: @ast::item, sc: scopes, v: vt<scopes>) {
-        visit_item_with_scope(i, sc, v);
+        visit_item_with_scope(e, i, sc, v);
         alt i.node {
           ast::item_mod(md) {
             e.mod_map.insert(i.id,
@@ -257,7 +260,7 @@ fn index_i(e: @env, i: @ast::item, sc: scopes, v: vt<scopes>) {
     let v_link_glob =
         @{visit_view_item: bind link_glob(e, _, _, _),
           visit_block: visit_block_with_scope,
-          visit_item: visit_item_with_scope
+          visit_item: bind visit_item_with_scope(e, _, _, _)
           with *visit::default_visitor::<scopes>()};
     visit::visit_crate(*c, cons(scope_crate, @nil),
                        visit::mk_vt(v_link_glob));
@@ -331,7 +334,7 @@ fn resolve_names(e: @env, c: @ast::crate) {
     e.used_imports.track = true;
     let v =
         @{visit_native_item: visit_native_item_with_scope,
-          visit_item: visit_item_with_scope,
+          visit_item: bind visit_item_with_scope(e, _, _, _),
           visit_block: visit_block_with_scope,
           visit_decl: visit_decl_with_scope,
           visit_arm: visit_arm_with_scope,
@@ -413,7 +416,17 @@ fn walk_pat(e: @env, pat: @ast::pat, sc: scopes, v: vt<scopes>) {
 
 
 // Visit helper functions
-fn visit_item_with_scope(i: @ast::item, sc: scopes, v: vt<scopes>) {
+fn visit_item_with_scope(e: @env, i: @ast::item, sc: scopes, v: vt<scopes>) {
+
+    // Some magic here. Items with the !resolve_unexported attribute
+    // cause us to consider every name to be exported when resolving their
+    // contents. This is used to allow the test runner to run unexported
+    // tests.
+    let old_resolve_unexported = e.resolve_unexported;
+    e.resolve_unexported |=
+        attr::contains_name(attr::attr_metas(i.attrs),
+                            "!resolve_unexported");
+
     let sc = cons(scope_item(i), @sc);
     alt i.node {
       ast::item_impl(tps, ifce, sty, methods) {
@@ -436,6 +449,8 @@ fn visit_item_with_scope(i: @ast::item, sc: scopes, v: vt<scopes>) {
       }
       _ { visit::visit_item(i, sc, v); }
     }
+
+    e.resolve_unexported = old_resolve_unexported;
 }
 
 fn visit_native_item_with_scope(ni: @ast::native_item, sc: scopes,
@@ -1187,10 +1202,14 @@ fn lookup_in_local_native_mod(e: env, node_id: node_id, sp: span, id: ident,
     ret lookup_in_local_mod(e, node_id, sp, id, ns, inside);
 }
 
+fn is_exported(e: env, i: ident, m: _mod) -> bool {
+    ast_util::is_exported(i, m) || e.resolve_unexported
+}
+
 fn lookup_in_local_mod(e: env, node_id: node_id, sp: span, id: ident,
                        ns: namespace, dr: dir) -> option::t<def> {
     let info = e.mod_map.get(node_id);
-    if dr == outside && !is_exported(id, option::get(info.m)) {
+    if dr == outside && !is_exported(e, id, option::get(info.m)) {
         // if we're in a native mod, then dr==inside, so info.m is some _mod
         ret none::<def>; // name is not visible
     }
@@ -1792,7 +1811,10 @@ fn find_impls_in_item(e: env, i: @ast::item, &impls: [@_impl],
     alt i.node {
       ast::item_impl(_, ifce, _, mthds) {
         if alt name { some(n) { n == i.ident } _ { true } } &&
-           alt ck_exports { some(m) { is_exported(i.ident, m) } _ { true } } {
+           alt ck_exports {
+             some(m) { is_exported(e, i.ident, m) }
+             _ { true }
+           } {
             impls += [@{did: local_def(i.id),
                         iface_did: alt ifce {
                             some(@{node: ast::ty_path(_, id), _}) {
diff --git a/src/test/run-fail/run-unexported-tests.rs b/src/test/run-fail/run-unexported-tests.rs
new file mode 100644 (file)
index 0000000..c0512a4
--- /dev/null
@@ -0,0 +1,13 @@
+// error-pattern:runned an unexported test
+// compile-flags:--test
+
+use std;
+
+mod m {
+    export exported;
+
+    fn exported() { }
+
+    #[test]
+    fn unexported() { fail "runned an unexported test"; }
+}