]> git.lizzy.rs Git - rust.git/commitdiff
Use fn~ to simplify the core::test interface
authorBrian Anderson <banderson@mozilla.com>
Thu, 19 Jan 2012 21:00:30 +0000 (13:00 -0800)
committerBrian Anderson <banderson@mozilla.com>
Thu, 19 Jan 2012 21:37:01 +0000 (13:37 -0800)
src/comp/front/test.rs
src/compiletest/compiletest.rs
src/compiletest/runtest.rs
src/libstd/test.rs

index bbe08b7316575fb16a268c58f4f3a87bbf3158f8..1e0c9c22bba94500e93077d20e742be0feac8299 100644 (file)
@@ -249,19 +249,10 @@ fn mk_path(cx: test_ctxt, path: [ast::ident]) -> [ast::ident] {
 
 // The ast::ty of [std::test::test_desc]
 fn mk_test_desc_vec_ty(cx: test_ctxt) -> @ast::ty {
-    let test_fn_ty: ast::ty = nospan(
-        ast::ty_path(
-            @nospan({
-                global: false,
-                idents: mk_path(cx, ["test", "default_test_fn"]),
-                types: []
-            }),
-            cx.sess.next_node_id()));
-
     let test_desc_ty_path =
         @nospan({global: false,
                  idents: mk_path(cx, ["test", "test_desc"]),
-                 types: [@test_fn_ty]});
+                 types: []});
 
     let test_desc_ty: ast::ty =
         nospan(ast::ty_path(test_desc_ty_path, cx.sess.next_node_id()));
index 1747147ea5107a8354ec78b7a43360b8f44fc753..ccbafa0f1591af79f512f5263299c9dc21194ac1 100644 (file)
@@ -115,7 +115,7 @@ fn run_tests(config: config) {
     let opts = test_opts(config);
     let cx = {config: config, procsrv: procsrv::mk()};
     let tests = make_tests(cx);
-    let res = test::run_tests_console_(opts, tests.tests, tests.to_task);
+    let res = test::run_tests_console(opts, tests);
     procsrv::close(cx.procsrv);
     if !res { fail "Some tests failed"; }
 }
@@ -129,23 +129,17 @@ fn test_opts(config: config) -> test::test_opts {
      run_ignored: config.run_ignored}
 }
 
-type tests_and_conv_fn = {
-    tests: [test::test_desc<fn@()>],
-    to_task: fn@(fn@()) -> test::joinable
-};
-
-fn make_tests(cx: cx) -> tests_and_conv_fn {
+fn make_tests(cx: cx) -> [test::test_desc] {
     #debug("making tests from %s", cx.config.src_base);
-    let configport = port::<[u8]>();
     let tests = [];
     for file: str in fs::list_dir(cx.config.src_base) {
         let file = file;
         #debug("inspecting file %s", file);
         if is_test(cx.config, file) {
-            tests += [make_test(cx, file, configport)];
+            tests += [make_test(cx, file)]
         }
     }
-    ret {tests: tests, to_task: bind closure_to_task(cx, configport, _)};
+    ret tests;
 }
 
 fn is_test(config: config, testfile: str) -> bool {
@@ -168,40 +162,31 @@ fn is_test(config: config, testfile: str) -> bool {
     ret valid;
 }
 
-fn make_test(cx: cx, testfile: str, configport: port<[u8]>) ->
-   test::test_desc<fn@()> {
-    {name: make_test_name(cx.config, testfile),
-     fn: make_test_closure(testfile, chan(configport)),
-     ignore: header::is_test_ignored(cx.config, testfile),
-     should_fail: false}
+fn make_test(cx: cx, testfile: str) ->
+   test::test_desc {
+    {
+        name: make_test_name(cx.config, testfile),
+        fn: make_test_closure(cx, testfile),
+        ignore: header::is_test_ignored(cx.config, testfile),
+        should_fail: false
+    }
 }
 
 fn make_test_name(config: config, testfile: str) -> str {
     #fmt["[%s] %s", mode_str(config.mode), testfile]
 }
 
-fn make_test_closure(testfile: str,
-                     configchan: chan<[u8]>) -> test::test_fn<fn@()> {
-    bind send_config(testfile, configchan)
-}
-
-fn send_config(testfile: str, configchan: chan<[u8]>) {
-    send(configchan, str::bytes(testfile));
-}
-
-fn closure_to_task(cx: cx, configport: port<[u8]>, testfn: fn@()) ->
-   test::joinable {
-    testfn();
-    let testfile = recv(configport);
-    let (config, chan) = (cx.config, cx.procsrv.chan);
-    ret task::spawn_joinable {||
+fn make_test_closure(cx: cx, testfile: str) -> test::test_fn {
+    let config = cx.config;
+    let chan = cx.procsrv.chan;
+    ret {||
         run_test_task(config, chan, testfile);
     };
 }
 
 fn run_test_task(config: common::config,
                  procsrv_chan: procsrv::reqchan,
-                 testfile: [u8]) {
+                 testfile: str) {
     test::configure_test_task();
 
     let procsrv = procsrv::from_chan(procsrv_chan);
index 73064d1adf5052f27c8ff5884ded6ca4e407f90d..2d0f16870f4e241954465dce9dd2ebc473fa99d7 100644 (file)
@@ -15,8 +15,7 @@
 
 export run;
 
-fn run(cx: cx, -_testfile: [u8]) {
-    let testfile = str::unsafe_from_bytes(_testfile);
+fn run(cx: cx, testfile: str) {
     if cx.config.verbose {
         // We're going to be dumping a lot of info. Start on a new line.
         io::stdout().write_str("\n\n");
index fbb87d93e857d1d3782b8cea9feaacb7b51e2b0e..eb86b882718d8633aa97ea89643ebf1f0273b2ba 100644 (file)
@@ -9,7 +9,6 @@
 
 export test_name;
 export test_fn;
-export default_test_fn;
 export test_desc;
 export test_main;
 export test_result;
 export tr_failed;
 export tr_ignored;
 export run_tests_console;
-export run_tests_console_;
-export run_test;
-export filter_tests;
-export parse_opts;
-export test_to_task;
-export default_test_to_task;
 export configure_test_task;
-export joinable;
 
 #[abi = "cdecl"]
 native mod rustrt {
 // the test succeeds; if the function fails then the test fails. We
 // may need to come up with a more clever definition of test in order
 // to support isolation of tests into tasks.
-type test_fn<T> = T;
-
-type default_test_fn = test_fn<fn~()>;
+type test_fn = fn~();
 
 // The definition of a single test. A test runner will run a list of
 // these.
-type test_desc<T> = {
+type test_desc = {
     name: test_name,
-    fn: test_fn<T>,
+    fn: test_fn,
     ignore: bool,
     should_fail: bool
 };
 
 // The default console test runner. It accepts the command line
 // arguments and a vector of test_descs (generated at compile time).
-fn test_main(args: [str], tests: [test_desc<default_test_fn>]) {
+fn test_main(args: [str], tests: [test_desc]) {
     check (vec::is_not_empty(args));
     let opts =
         alt parse_opts(args) {
@@ -96,22 +86,9 @@ fn parse_opts(args: [str]) : vec::is_not_empty(args) -> opt_res {
 
 tag test_result { tr_ok; tr_failed; tr_ignored; }
 
-type joinable = (task::task, comm::port<task::task_notification>);
-
-// To get isolation and concurrency tests have to be run in their own tasks.
-// In cases where test functions are closures it is not ok to just dump them
-// into a task and run them, so this transformation gives the caller a chance
-// to create the test task.
-type test_to_task<T> = fn@(test_fn<T>) -> joinable;
-
 // A simple console test runner
 fn run_tests_console(opts: test_opts,
-                         tests: [test_desc<default_test_fn>]) -> bool {
-    run_tests_console_(opts, tests, default_test_to_task)
-}
-
-fn run_tests_console_<T: copy>(opts: test_opts, tests: [test_desc<T>],
-                              to_task: test_to_task<T>) -> bool {
+                     tests: [test_desc]) -> bool {
 
     type test_state =
         @{out: io::writer,
@@ -120,9 +97,9 @@ fn run_tests_console_<T: copy>(opts: test_opts, tests: [test_desc<T>],
           mutable passed: uint,
           mutable failed: uint,
           mutable ignored: uint,
-          mutable failures: [test_desc<T>]};
+          mutable failures: [test_desc]};
 
-    fn callback<T: copy>(event: testevent<T>, st: test_state) {
+    fn callback(event: testevent, st: test_state) {
         alt event {
           te_filtered(filtered_tests) {
             st.total = vec::len(filtered_tests);
@@ -161,14 +138,14 @@ fn callback<T: copy>(event: testevent<T>, st: test_state) {
           mutable ignored: 0u,
           mutable failures: []};
 
-    run_tests(opts, tests, to_task, bind callback(_, st));
+    run_tests(opts, tests, bind callback(_, st));
 
     assert (st.passed + st.failed + st.ignored == st.total);
     let success = st.failed == 0u;
 
     if !success {
         st.out.write_line("\nfailures:");
-        for test: test_desc<T> in st.failures {
+        for test: test_desc in st.failures {
             let testname = test.name; // Satisfy alias analysis
             st.out.write_line(#fmt["    %s", testname]);
         }
@@ -209,22 +186,20 @@ fn write_pretty(out: io::writer, word: str, color: u8, use_color: bool) {
 
 fn use_color() -> bool { ret get_concurrency() == 1u; }
 
-tag testevent<T> {
-    te_filtered([test_desc<T>]);
-    te_wait(test_desc<T>);
-    te_result(test_desc<T>, test_result);
+tag testevent {
+    te_filtered([test_desc]);
+    te_wait(test_desc);
+    te_result(test_desc, test_result);
 }
 
-fn run_tests<T: copy>(opts: test_opts, tests: [test_desc<T>],
-                     to_task: test_to_task<T>,
-                     callback: fn@(testevent<T>)) {
+fn run_tests(opts: test_opts, tests: [test_desc],
+             callback: fn@(testevent)) {
 
     let filtered_tests = filter_tests(opts, tests);
     callback(te_filtered(filtered_tests));
 
-    // It's tempting to just spawn all the tests at once but that doesn't
-    // provide a great user experience because you might sit waiting for the
-    // result of a particular test for an unusually long amount of time.
+    // It's tempting to just spawn all the tests at once, but since we have many
+    // tests that run in other processes we would be making a big mess.
     let concurrency = get_concurrency();
     #debug("using %u test tasks", concurrency);
     let total = vec::len(filtered_tests);
@@ -234,7 +209,7 @@ fn run_tests<T: copy>(opts: test_opts, tests: [test_desc<T>],
 
     while wait_idx < total {
         while vec::len(futures) < concurrency && run_idx < total {
-            futures += [run_test(filtered_tests[run_idx], to_task)];
+            futures += [run_test(filtered_tests[run_idx])];
             run_idx += 1u;
         }
 
@@ -249,8 +224,8 @@ fn run_tests<T: copy>(opts: test_opts, tests: [test_desc<T>],
 
 fn get_concurrency() -> uint { rustrt::sched_threads() }
 
-fn filter_tests<T: copy>(opts: test_opts,
-                        tests: [test_desc<T>]) -> [test_desc<T>] {
+fn filter_tests(opts: test_opts,
+                tests: [test_desc]) -> [test_desc] {
     let filtered = tests;
 
     // Remove tests that don't match the test filter
@@ -263,8 +238,8 @@ fn filter_tests<T: copy>(opts: test_opts,
           option::none { "" }
         };
 
-        fn filter_fn<T: copy>(test: test_desc<T>, filter_str: str) ->
-            option::t<test_desc<T>> {
+        fn filter_fn(test: test_desc, filter_str: str) ->
+            option::t<test_desc> {
             if str::find(test.name, filter_str) >= 0 {
                 ret option::some(test);
             } else { ret option::none; }
@@ -279,7 +254,7 @@ fn filter_fn<T: copy>(test: test_desc<T>, filter_str: str) ->
     filtered = if !opts.run_ignored {
         filtered
     } else {
-        fn filter<T: copy>(test: test_desc<T>) -> option::t<test_desc<T>> {
+        fn filter(test: test_desc) -> option::t<test_desc> {
             if test.ignore {
                 ret option::some({name: test.name,
                                   fn: test.fn,
@@ -294,7 +269,7 @@ fn filter<T: copy>(test: test_desc<T>) -> option::t<test_desc<T>> {
     // Sort the tests alphabetically
     filtered =
         {
-            fn lteq<T>(t1: test_desc<T>, t2: test_desc<T>) -> bool {
+            fn lteq(t1: test_desc, t2: test_desc) -> bool {
                 str::lteq(t1.name, t2.name)
             }
             sort::merge_sort(bind lteq(_, _), filtered)
@@ -303,15 +278,14 @@ fn lteq<T>(t1: test_desc<T>, t2: test_desc<T>) -> bool {
     ret filtered;
 }
 
-type test_future<T> = {test: test_desc<T>, wait: fn@() -> test_result};
+type test_future = {test: test_desc, wait: fn@() -> test_result};
 
-fn run_test<T: copy>(test: test_desc<T>,
-                    to_task: test_to_task<T>) -> test_future<T> {
+fn run_test(test: test_desc) -> test_future {
     if test.ignore {
         ret {test: test, wait: fn@() -> test_result { tr_ignored }};
     }
 
-    let test_task = to_task(test.fn);
+    let test_task = test_to_task(test.fn);
     ret {test: test,
          wait: fn@() -> test_result {
              alt task::join(test_task) {
@@ -330,7 +304,7 @@ fn run_test<T: copy>(test: test_desc<T>,
 
 // We need to run our tests in another task in order to trap test failures.
 // This function only works with functions that don't contain closures.
-fn default_test_to_task(&&f: default_test_fn) -> joinable {
+fn test_to_task(&&f: test_fn) -> task::joinable_task {
     ret task::spawn_joinable(fn~[copy f]() {
         configure_test_task();
         f();
@@ -356,9 +330,9 @@ fn do_not_run_ignored_tests() {
             ignore: true,
             should_fail: false
         };
-        let future = test::run_test(desc, test::default_test_to_task);
+        let future = run_test(desc);
         let result = future.wait();
-        assert result != test::tr_ok;
+        assert result != tr_ok;
     }
 
     #[test]
@@ -370,8 +344,8 @@ fn f() { }
             ignore: true,
             should_fail: false
         };
-        let res = test::run_test(desc, test::default_test_to_task).wait();
-        assert (res == test::tr_ignored);
+        let res = run_test(desc).wait();
+        assert (res == tr_ignored);
     }
 
     #[test]
@@ -384,8 +358,8 @@ fn test_should_fail() {
             ignore: false,
             should_fail: true
         };
-        let res = test::run_test(desc, test::default_test_to_task).wait();
-        assert res == test::tr_ok;
+        let res = run_test(desc).wait();
+        assert res == tr_ok;
     }
 
     #[test]
@@ -397,15 +371,15 @@ fn f() { }
             ignore: false,
             should_fail: true
         };
-        let res = test::run_test(desc, test::default_test_to_task).wait();
-        assert res == test::tr_failed;
+        let res = run_test(desc).wait();
+        assert res == tr_failed;
     }
 
     #[test]
     fn first_free_arg_should_be_a_filter() {
         let args = ["progname", "filter"];
         check (vec::is_not_empty(args));
-        let opts = alt test::parse_opts(args) { either::left(o) { o } };
+        let opts = alt parse_opts(args) { either::left(o) { o } };
         assert (str::eq("filter", option::get(opts.filter)));
     }
 
@@ -413,7 +387,7 @@ fn first_free_arg_should_be_a_filter() {
     fn parse_ignored_flag() {
         let args = ["progname", "filter", "--ignored"];
         check (vec::is_not_empty(args));
-        let opts = alt test::parse_opts(args) { either::left(o) { o } };
+        let opts = alt parse_opts(args) { either::left(o) { o } };
         assert (opts.run_ignored);
     }
 
@@ -424,9 +398,9 @@ fn filter_for_ignored_option() {
 
         let opts = {filter: option::none, run_ignored: true};
         let tests =
-            [{name: "1", fn: fn@() { }, ignore: true, should_fail: false},
-             {name: "2", fn: fn@() { }, ignore: false, should_fail: false}];
-        let filtered = test::filter_tests(opts, tests);
+            [{name: "1", fn: fn~() { }, ignore: true, should_fail: false},
+             {name: "2", fn: fn~() { }, ignore: false, should_fail: false}];
+        let filtered = filter_tests(opts, tests);
 
         assert (vec::len(filtered) == 1u);
         assert (filtered[0].name == "1");
@@ -446,7 +420,7 @@ fn sort_tests() {
              "test::sort_tests"];
         let tests =
         {
-        let testfn = fn@() { };
+        let testfn = fn~() { };
         let tests = [];
         for name: str in names {
             let test = {name: name, fn: testfn, ignore: false,
@@ -455,7 +429,7 @@ fn sort_tests() {
         }
         tests
     };
-    let filtered = test::filter_tests(opts, tests);
+    let filtered = filter_tests(opts, tests);
 
     let expected =
         ["int::test_pow", "int::test_to_str", "sha1::test",
@@ -469,7 +443,7 @@ fn sort_tests() {
 
 
     for (a, b) in pairs { assert (a == b.name); }
-}
+    }
 }