From 60de64108d7cd8aa04fc69749f24d2b97b84a34f Mon Sep 17 00:00:00 2001 From: Harlan Harris Date: Sat, 10 Mar 2012 10:39:31 -0500 Subject: [PATCH 01/12] start new test suite --- jl/test.jl | 2 ++ test/test.jl | 1 + 2 files changed, 3 insertions(+) create mode 100644 jl/test.jl create mode 100644 test/test.jl diff --git a/jl/test.jl b/jl/test.jl new file mode 100644 index 0000000000000..c362fef593a0c --- /dev/null +++ b/jl/test.jl @@ -0,0 +1,2 @@ +# test suite functions and macros + diff --git a/test/test.jl b/test/test.jl new file mode 100644 index 0000000000000..9146ab1a717cc --- /dev/null +++ b/test/test.jl @@ -0,0 +1 @@ +# test file to test testing From 4c5c1024b15c570fa096a90f5d6feb8ab187b3ec Mon Sep 17 00:00:00 2001 From: Harlan Harris Date: Sat, 10 Mar 2012 11:49:25 -0500 Subject: [PATCH 02/12] basic test functions written, don't run yet --- jl/test.jl | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++ test/test.jl | 29 ++++++++++++++++++ 2 files changed, 116 insertions(+) diff --git a/jl/test.jl b/jl/test.jl index c362fef593a0c..fd6f650d28e83 100644 --- a/jl/test.jl +++ b/jl/test.jl @@ -1,2 +1,89 @@ # test suite functions and macros +# runtests +function runtests(onestr::String) + # if onestr is an existing readable file, pass it to the primary testing function + if (is_file_readable(onestr)) + runtests([onestr], test_printer_simple) + else + # if it's a directory name, find all test_*.jl in that and subdirectories, and pass + # that list + + # otherwise, throw an error + error("not a file or directory: $onestr") + end +end + +function runtests(filenames, outputter::Function) + # run these files as a task + println("a") + hdl = Task(Nothing -> _runtests_task(filenames)) + println("b") + outputter(hdl) + println("c") +end + +function _runtests_task(filenames) + println("C") + for fn = filenames + println("d") + load(fn) + println("e") + end +end + +# the default printer +function test_printer_simple(hdl::Task) + for t = hdl + show(t) + end +end + +# things to set state +function test_context(context::String) + tls(:context, context) +end +function test_group(group::String) + tls(:group, group) +end + +# data structures +type TestResult + context + group + expr_str::String + result::Bool + elapsed::Float + exception_thrown::Exception + operation + arg1 + arg2 + arg3 +end + +# the primary macros +macro test(ex) + tr = gensym() + quote + local $tr = TestResult() + + # store things we know already + $tr.expr_str = $string(ex) + $tr.context = tls(:context) + $tr.group = tls(:group) + + # evaluate the expression while timing it and catching exceptions + try + $tr.elapsed = @elapsed ($tr.result = assert_test($ex)) + catch except + $tr.result = False + $tr.exception_thrown = except + end + + + # figure out the parts + + # don't return anything, just produce it + produce($tr) + end +end \ No newline at end of file diff --git a/test/test.jl b/test/test.jl index 9146ab1a717cc..e1e5b80266a95 100644 --- a/test/test.jl +++ b/test/test.jl @@ -1 +1,30 @@ # test file to test testing + + +test_context("Testing test tests") +# setup goes here + +test_group("string tests") +println("f") +@test strip("\t hi \n") == "hi" +println("g") + + +test_group("array tests") + + + +test_group("random tests") + + + +test_group("exception tests") + + + +test_group("printing tests") + + + + +# shutdown goes here From 0cf1060138666903e797a4589341cf35eacd7acc Mon Sep 17 00:00:00 2001 From: Harlan Harris Date: Sat, 10 Mar 2012 15:11:25 -0500 Subject: [PATCH 03/12] trying to get the macro to work -- no joy yet --- jl/test.jl | 53 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/jl/test.jl b/jl/test.jl index fd6f650d28e83..7f70e1a99483a 100644 --- a/jl/test.jl +++ b/jl/test.jl @@ -17,7 +17,7 @@ end function runtests(filenames, outputter::Function) # run these files as a task println("a") - hdl = Task(Nothing -> _runtests_task(filenames)) + hdl = Task(() -> _runtests_task(filenames)) println("b") outputter(hdl) println("c") @@ -48,6 +48,9 @@ function test_group(group::String) end # data structures +type NoException <: Exception +end + type TestResult context group @@ -60,30 +63,34 @@ type TestResult arg2 arg3 end +TestResult() = TestResult("", "", "", false, NaN, NoException(), Nothing, Nothing, Nothing, Nothing) -# the primary macros +# the macro captures the expression, then calls a function that does the actual work macro test(ex) - tr = gensym() quote - local $tr = TestResult() - - # store things we know already - $tr.expr_str = $string(ex) - $tr.context = tls(:context) - $tr.group = tls(:group) - - # evaluate the expression while timing it and catching exceptions - try - $tr.elapsed = @elapsed ($tr.result = assert_test($ex)) - catch except - $tr.result = False - $tr.exception_thrown = except - end - - - # figure out the parts - - # don't return anything, just produce it - produce($tr) + produce(_dotest(:(ex), $string(ex))) end +end + +function _dotest(ex::Expr, ex_str::String) + tr = TestResult() + + # store things we already know + tr.expr_str = ex_str + tr.context = tls(:context) + tr.group = tls(:group) + + # evaluate the expression while timing it and catching exceptions + #try + #$(tr).elapsed = @elapsed ( + tr.result = assert_test(eval(ex)) + # catch except + # $tr.result = False + # $tr.exception_thrown = except + # end + + + # figure out the parts of the expression and evaluate separately + + tr end \ No newline at end of file From 290bdea9f0660915c08fc4b5cc27cfb67816b1df Mon Sep 17 00:00:00 2001 From: Harlan Harris Date: Sat, 10 Mar 2012 15:21:04 -0500 Subject: [PATCH 04/12] test macro runs! couldn't figure out how to access fields of a struct in a macro, so I gave up and only construct the struct at the end --- jl/test.jl | 43 +++++++++++++------------------------------ test/test.jl | 2 -- 2 files changed, 13 insertions(+), 32 deletions(-) diff --git a/jl/test.jl b/jl/test.jl index 7f70e1a99483a..bc7999b2f62f2 100644 --- a/jl/test.jl +++ b/jl/test.jl @@ -16,19 +16,13 @@ end function runtests(filenames, outputter::Function) # run these files as a task - println("a") hdl = Task(() -> _runtests_task(filenames)) - println("b") outputter(hdl) - println("c") end function _runtests_task(filenames) - println("C") for fn = filenames - println("d") load(fn) - println("e") end end @@ -67,30 +61,19 @@ TestResult() = TestResult("", "", "", false, NaN, NoException(), Nothing, Nothin # the macro captures the expression, then calls a function that does the actual work macro test(ex) + res, elapsed, exc, op, arg1, arg2, arg3 = gensym(7) quote - produce(_dotest(:(ex), $string(ex))) + local $elapsed = NaN + local $res = false + local $exc = NoException() + + try + $elapsed = @elapsed $res = assert_test($ex) + catch except + $exc = except + end + produce(TestResult(tls(:context), tls(:group), $string(ex), $res, $elapsed, + $exc, Nothing, Nothing, Nothing, Nothing)) + #produce(_dotest(:(ex), $string(ex))) end end - -function _dotest(ex::Expr, ex_str::String) - tr = TestResult() - - # store things we already know - tr.expr_str = ex_str - tr.context = tls(:context) - tr.group = tls(:group) - - # evaluate the expression while timing it and catching exceptions - #try - #$(tr).elapsed = @elapsed ( - tr.result = assert_test(eval(ex)) - # catch except - # $tr.result = False - # $tr.exception_thrown = except - # end - - - # figure out the parts of the expression and evaluate separately - - tr -end \ No newline at end of file diff --git a/test/test.jl b/test/test.jl index e1e5b80266a95..528ff3c3effd5 100644 --- a/test/test.jl +++ b/test/test.jl @@ -5,9 +5,7 @@ test_context("Testing test tests") # setup goes here test_group("string tests") -println("f") @test strip("\t hi \n") == "hi" -println("g") test_group("array tests") From dc3e41e222bbfe4d166ff94330b0cc708d0e3933 Mon Sep 17 00:00:00 2001 From: Harlan Harris Date: Sat, 10 Mar 2012 15:41:05 -0500 Subject: [PATCH 05/12] comparison failures store evaled LHS/RHS only failures print --- jl/test.jl | 25 +++++++++++++++++++++++-- test/test.jl | 2 +- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/jl/test.jl b/jl/test.jl index bc7999b2f62f2..ef30b07879684 100644 --- a/jl/test.jl +++ b/jl/test.jl @@ -29,7 +29,13 @@ end # the default printer function test_printer_simple(hdl::Task) for t = hdl - show(t) + if (t.result) + print(".") + else + println("") + show(t) + println("") + end end end @@ -66,14 +72,29 @@ macro test(ex) local $elapsed = NaN local $res = false local $exc = NoException() + local $op = Nothing + local $arg1 = Nothing + local $arg2 = Nothing try $elapsed = @elapsed $res = assert_test($ex) catch except $exc = except end + + # if we failed without an exception, pull apart the expression and see if we can't evaluate its + # parts + if ($res == false && $exc == NoException()) + if ($string(ex.head) == "comparison") + $op = $string(ex.head) + $arg1 = eval($ex.args[1]) + $arg2 = eval($ex.args[3]) + end + + end + produce(TestResult(tls(:context), tls(:group), $string(ex), $res, $elapsed, - $exc, Nothing, Nothing, Nothing, Nothing)) + $exc, $op, $arg1, $arg2, Nothing)) #produce(_dotest(:(ex), $string(ex))) end end diff --git a/test/test.jl b/test/test.jl index 528ff3c3effd5..33c5d1279a6d6 100644 --- a/test/test.jl +++ b/test/test.jl @@ -6,7 +6,7 @@ test_context("Testing test tests") test_group("string tests") @test strip("\t hi \n") == "hi" - +@test strip("\t this should fail \n") == "hi" test_group("array tests") From 3f9a9442315169d076660351276bcfbbea1da326 Mon Sep 17 00:00:00 2001 From: Harlan Harris Date: Sat, 10 Mar 2012 15:54:04 -0500 Subject: [PATCH 06/12] approx_eq test fn --- jl/test.jl | 18 ++++++++++++++++-- test/test.jl | 7 ++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/jl/test.jl b/jl/test.jl index ef30b07879684..28a4eaffaae11 100644 --- a/jl/test.jl +++ b/jl/test.jl @@ -65,7 +65,8 @@ type TestResult end TestResult() = TestResult("", "", "", false, NaN, NoException(), Nothing, Nothing, Nothing, Nothing) -# the macro captures the expression, then calls a function that does the actual work +# had some issues with struct access inside the macro, so don't build the TestResult until the end, +# which is ugly and should be fixed macro test(ex) res, elapsed, exc, op, arg1, arg2, arg3 = gensym(7) quote @@ -89,12 +90,25 @@ macro test(ex) $op = $string(ex.head) $arg1 = eval($ex.args[1]) $arg2 = eval($ex.args[3]) + elseif ($string(ex.head) == "call") + if ($string(ex.args[1]) == "approx_eq") + $op = "approx_eq" + $arg1 = eval($ex.args[2]) + $arg2 = eval($ex.args[3]) + end end end produce(TestResult(tls(:context), tls(:group), $string(ex), $res, $elapsed, $exc, $op, $arg1, $arg2, Nothing)) - #produce(_dotest(:(ex), $string(ex))) end end + +# helpful utility tests, supported by the macro +function approx_eq(a, b, tol) + abs(a - b) < tol +end +approx_eq(a, b) = approx_eq(a, b, 1e-6) + + diff --git a/test/test.jl b/test/test.jl index 33c5d1279a6d6..1293cd6a35e7b 100644 --- a/test/test.jl +++ b/test/test.jl @@ -6,7 +6,12 @@ test_context("Testing test tests") test_group("string tests") @test strip("\t hi \n") == "hi" -@test strip("\t this should fail \n") == "hi" +@test strip("\t this should fail \n") == "hi" #fail + + +test_group("numeric tests") +@test approx_eq(airy(1.8), 0.0470362) +@test approx_eq(airy(1, 1.8), 1 + -0.0685248) # fail test_group("array tests") From 07b50f49cea70fc9875e3e23245507ef26e6582e Mon Sep 17 00:00:00 2001 From: Harlan Harris Date: Sat, 10 Mar 2012 16:50:58 -0500 Subject: [PATCH 07/12] more tests --- test/test.jl | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/test/test.jl b/test/test.jl index 1293cd6a35e7b..b71c72263096a 100644 --- a/test/test.jl +++ b/test/test.jl @@ -11,23 +11,31 @@ test_group("string tests") test_group("numeric tests") @test approx_eq(airy(1.8), 0.0470362) -@test approx_eq(airy(1, 1.8), 1 + -0.0685248) # fail +@test approx_eq(airy(1, 1.8), 1 + -0.0685248) # fail, using helper function test_group("array tests") - +a = Array(Float64, 2, 2, 2, 2, 2) +a[1,1,1,1,1] = 10 +@test a[1,1,1,1,1] == 10 +@test a[1,1,1,1,1] == 2 # fail test_group("random tests") - - +@test rand() != rand() # not very likely to fail +@test rand() == rand() # fail test_group("exception tests") - - +@test complex(1,2) > 0 # fail test_group("printing tests") - - - +@test print_to_string(show, :(1+2)) == "+(1,2)" +# could we do something like: +# @test prints(show, ([1,2]), "[1, 2]") +# where prints() applies the 2nd-arg tuple to the first arg in print_to_string? + +test_group("performance tests") +fib(n) = n < 2 ? n : fib(n-1) + fib(n-2) +@test fib(20) == 6765 +# @test takes_less_than(fib(20), .1) # shutdown goes here From 1ad51980d350d128c581cc196a99cc0860d811c9 Mon Sep 17 00:00:00 2001 From: Harlan Harris Date: Sat, 10 Mar 2012 17:27:12 -0500 Subject: [PATCH 08/12] prints and takes_less_than helpers --- jl/test.jl | 29 ++++++++++++++++++++++++++--- test/test.jl | 7 +++---- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/jl/test.jl b/jl/test.jl index 28a4eaffaae11..b34e22426927a 100644 --- a/jl/test.jl +++ b/jl/test.jl @@ -8,6 +8,7 @@ function runtests(onestr::String) else # if it's a directory name, find all test_*.jl in that and subdirectories, and pass # that list + # TODO # otherwise, throw an error error("not a file or directory: $onestr") @@ -33,7 +34,7 @@ function test_printer_simple(hdl::Task) print(".") else println("") - show(t) + show(t) # TODO spiff up println("") end end @@ -66,7 +67,7 @@ end TestResult() = TestResult("", "", "", false, NaN, NoException(), Nothing, Nothing, Nothing, Nothing) # had some issues with struct access inside the macro, so don't build the TestResult until the end, -# which is ugly and should be fixed +# which is ugly and should be fixed (TODO) macro test(ex) res, elapsed, exc, op, arg1, arg2, arg3 = gensym(7) quote @@ -78,7 +79,7 @@ macro test(ex) local $arg2 = Nothing try - $elapsed = @elapsed $res = assert_test($ex) + $elapsed = @elapsed $res = eval($ex) catch except $exc = except end @@ -95,9 +96,20 @@ macro test(ex) $op = "approx_eq" $arg1 = eval($ex.args[2]) $arg2 = eval($ex.args[3]) + elseif ($string(ex.args[1]) == "prints") + $op = "prints" + $arg1 = print_to_string(eval($ex.args[2]), eval($ex.args[3])...) + #$arg2 = eval($ex.args[4]) # TODO fails?! end end + end + # if we're running takes_less_than, see how we did + if ($string(ex.args[1]) == "takes_less_than") + $res = $elapsed < eval($ex.args[3]) + $op = "takes_less_than" + $arg1 = $elapsed + $arg2 = eval($ex.args[3]) end produce(TestResult(tls(:context), tls(:group), $string(ex), $res, $elapsed, @@ -106,9 +118,20 @@ macro test(ex) end # helpful utility tests, supported by the macro +# + function approx_eq(a, b, tol) abs(a - b) < tol end approx_eq(a, b) = approx_eq(a, b, 1e-6) +function prints(fn::Function, args, expected::String) + print_to_string(fn, args...) == expected +end + +#@test takes_less_than(fib(20), .1) +function takes_less_than(anything, expected) + # the magic happens in @test + true +end diff --git a/test/test.jl b/test/test.jl index b71c72263096a..2a81ac1967989 100644 --- a/test/test.jl +++ b/test/test.jl @@ -29,13 +29,12 @@ test_group("exception tests") test_group("printing tests") @test print_to_string(show, :(1+2)) == "+(1,2)" -# could we do something like: -# @test prints(show, ([1,2]), "[1, 2]") -# where prints() applies the 2nd-arg tuple to the first arg in print_to_string? +@test prints(print_joined, ([1,2,3], " : "), "1 : 2 : 3") # prints is a helper +@test prints(print_joined, ([1,2,3], " ! "), "1 : 2 : 3") # fail test_group("performance tests") fib(n) = n < 2 ? n : fib(n-1) + fib(n-2) @test fib(20) == 6765 -# @test takes_less_than(fib(20), .1) +@test takes_less_than(fib(20), 1e-6) # shutdown goes here From 821d2eb0264b188c99f6d626fa0345a18a341947 Mon Sep 17 00:00:00 2001 From: Harlan Harris Date: Sat, 10 Mar 2012 18:13:59 -0500 Subject: [PATCH 09/12] fix runtests(), rename test/test.jl load jl/test.jl on startup --- jl/sysimg.jl | 1 + jl/test.jl | 31 +++++++++++++++++++------------ test/{test.jl => test_test.jl} | 0 3 files changed, 20 insertions(+), 12 deletions(-) rename test/{test.jl => test_test.jl} (100%) diff --git a/jl/sysimg.jl b/jl/sysimg.jl index 31ba5ef266d0c..c989b17e26173 100644 --- a/jl/sysimg.jl +++ b/jl/sysimg.jl @@ -85,6 +85,7 @@ include("darray.jl") include("version.jl") include("util.jl") include("datafmt.jl") +include("test.jl") ## Load optional external libraries diff --git a/jl/test.jl b/jl/test.jl index b34e22426927a..90e462b0bb9a3 100644 --- a/jl/test.jl +++ b/jl/test.jl @@ -1,25 +1,33 @@ # test suite functions and macros # runtests -function runtests(onestr::String) - # if onestr is an existing readable file, pass it to the primary testing function - if (is_file_readable(onestr)) - runtests([onestr], test_printer_simple) - else - # if it's a directory name, find all test_*.jl in that and subdirectories, and pass - # that list - # TODO - - # otherwise, throw an error - error("not a file or directory: $onestr") +function runtests(onestr::String, outputter::Function) + # if onestr is an existing file, pass it to the primary testing function + stat = strip(readall(`stat -f "%HT" $onestr`)) + if (stat == "Regular File") + runtests([onestr], outputter) + elseif (stat == "Directory") + # if it's a directory name, find all test_*.jl in that and subdirectories, and pass + # that list + files_str = strip(readall(`find $onestr -name test_*.jl -print`)) + if (length(files_str) > 0) + runtests(split(files_str, "\n"), outputter) + else + # otherwise, throw an error + error("no test_*.jl files in directory: $onestr") + end end end +runtests(onestr::String) = runtests(onestr, test_printer_simple) +runtests(fn::Function) = runtests(".", fn) +runtests() = runtests(".") function runtests(filenames, outputter::Function) # run these files as a task hdl = Task(() -> _runtests_task(filenames)) outputter(hdl) end +runtests(filenames) = runtests(filenames, test_printer_simple) function _runtests_task(filenames) for fn = filenames @@ -129,7 +137,6 @@ function prints(fn::Function, args, expected::String) print_to_string(fn, args...) == expected end -#@test takes_less_than(fib(20), .1) function takes_less_than(anything, expected) # the magic happens in @test true diff --git a/test/test.jl b/test/test_test.jl similarity index 100% rename from test/test.jl rename to test/test_test.jl From 9813b48f751425cebab9f04064863950644c445a Mon Sep 17 00:00:00 2001 From: Harlan Harris Date: Sat, 10 Mar 2012 18:25:29 -0500 Subject: [PATCH 10/12] rename runtests()->tests() to prevent collision with existing build test suite --- jl/test.jl | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/jl/test.jl b/jl/test.jl index 90e462b0bb9a3..986da05542b92 100644 --- a/jl/test.jl +++ b/jl/test.jl @@ -1,35 +1,35 @@ # test suite functions and macros -# runtests -function runtests(onestr::String, outputter::Function) +# tests +function tests(onestr::String, outputter::Function) # if onestr is an existing file, pass it to the primary testing function stat = strip(readall(`stat -f "%HT" $onestr`)) if (stat == "Regular File") - runtests([onestr], outputter) + tests([onestr], outputter) elseif (stat == "Directory") # if it's a directory name, find all test_*.jl in that and subdirectories, and pass # that list files_str = strip(readall(`find $onestr -name test_*.jl -print`)) if (length(files_str) > 0) - runtests(split(files_str, "\n"), outputter) + tests(split(files_str, "\n"), outputter) else # otherwise, throw an error error("no test_*.jl files in directory: $onestr") end end end -runtests(onestr::String) = runtests(onestr, test_printer_simple) -runtests(fn::Function) = runtests(".", fn) -runtests() = runtests(".") +tests(onestr::String) = tests(onestr, test_printer_simple) +tests(fn::Function) = tests(".", fn) +tests() = tests(".") -function runtests(filenames, outputter::Function) +function tests(filenames, outputter::Function) # run these files as a task - hdl = Task(() -> _runtests_task(filenames)) + hdl = Task(() -> _tests_task(filenames)) outputter(hdl) end -runtests(filenames) = runtests(filenames, test_printer_simple) +tests(filenames) = tests(filenames, test_printer_simple) -function _runtests_task(filenames) +function _tests_task(filenames) for fn = filenames load(fn) end From 27cd4756eb2d2ce7c5fd1dd651855f263cbc2422 Mon Sep 17 00:00:00 2001 From: Harlan Harris Date: Sun, 11 Mar 2012 10:51:04 -0400 Subject: [PATCH 11/12] commented out filesystem code tests("test/test_test.jl") should work OK --- jl/test.jl | 48 ++++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/jl/test.jl b/jl/test.jl index 986da05542b92..9e2f1cd00ce71 100644 --- a/jl/test.jl +++ b/jl/test.jl @@ -1,33 +1,37 @@ # test suite functions and macros # tests -function tests(onestr::String, outputter::Function) - # if onestr is an existing file, pass it to the primary testing function - stat = strip(readall(`stat -f "%HT" $onestr`)) - if (stat == "Regular File") - tests([onestr], outputter) - elseif (stat == "Directory") - # if it's a directory name, find all test_*.jl in that and subdirectories, and pass - # that list - files_str = strip(readall(`find $onestr -name test_*.jl -print`)) - if (length(files_str) > 0) - tests(split(files_str, "\n"), outputter) - else - # otherwise, throw an error - error("no test_*.jl files in directory: $onestr") - end - end -end -tests(onestr::String) = tests(onestr, test_printer_simple) -tests(fn::Function) = tests(".", fn) -tests() = tests(".") +# TODO: re-enable when filesystem tests become available! +# function tests(onestr::String, outputter::Function) +# # if onestr is an existing file, pass it to the primary testing function +# stat = strip(readall(`stat -f "%HT" $onestr`)) +# if (stat == "Regular File") +# tests([onestr], outputter) +# elseif (stat == "Directory") +# # if it's a directory name, find all test_*.jl in that and subdirectories, and pass +# # that list +# files_str = strip(readall(`find $onestr -name test_*.jl -print`)) +# if (length(files_str) > 0) +# tests(split(files_str, "\n"), outputter) +# else +# # otherwise, throw an error +# error("no test_*.jl files in directory: $onestr") +# end +# end +# end +# tests(onestr::String) = tests(onestr, test_printer_raw) +# tests(fn::Function) = tests(".", fn) +# tests() = tests(".") +tests(onestr::String, outputter::Function) = tests([onestr], outputter) +tests(onestr::String) = tests([onestr], test_printer_raw) + function tests(filenames, outputter::Function) # run these files as a task hdl = Task(() -> _tests_task(filenames)) outputter(hdl) end -tests(filenames) = tests(filenames, test_printer_simple) +tests(filenames) = tests(filenames, test_printer_raw) function _tests_task(filenames) for fn = filenames @@ -36,7 +40,7 @@ function _tests_task(filenames) end # the default printer -function test_printer_simple(hdl::Task) +function test_printer_raw(hdl::Task) for t = hdl if (t.result) print(".") From f5c3fa398f6a7b04d683d66e3934af0806d30f69 Mon Sep 17 00:00:00 2001 From: Harlan Harris Date: Mon, 12 Mar 2012 16:16:39 -0400 Subject: [PATCH 12/12] replace giant macro with tiny macro and medium-sized function Thanks to Jeff and Stefan for hints on getting this to work! Note that the expression indexing issue went away, and I wasn't able to reproduce it in a simpler test case. --- jl/test.jl | 97 +++++++++++++++++++++++++++++------------------------- 1 file changed, 52 insertions(+), 45 deletions(-) diff --git a/jl/test.jl b/jl/test.jl index 9e2f1cd00ce71..bfce6fade4a9c 100644 --- a/jl/test.jl +++ b/jl/test.jl @@ -78,55 +78,62 @@ type TestResult end TestResult() = TestResult("", "", "", false, NaN, NoException(), Nothing, Nothing, Nothing, Nothing) -# had some issues with struct access inside the macro, so don't build the TestResult until the end, -# which is ugly and should be fixed (TODO) +# the macro just wraps the expression in a couple layers of quotes, then passes it to a function +# that does the real work macro test(ex) - res, elapsed, exc, op, arg1, arg2, arg3 = gensym(7) quote - local $elapsed = NaN - local $res = false - local $exc = NoException() - local $op = Nothing - local $arg1 = Nothing - local $arg2 = Nothing - - try - $elapsed = @elapsed $res = eval($ex) - catch except - $exc = except - end - - # if we failed without an exception, pull apart the expression and see if we can't evaluate its - # parts - if ($res == false && $exc == NoException()) - if ($string(ex.head) == "comparison") - $op = $string(ex.head) - $arg1 = eval($ex.args[1]) - $arg2 = eval($ex.args[3]) - elseif ($string(ex.head) == "call") - if ($string(ex.args[1]) == "approx_eq") - $op = "approx_eq" - $arg1 = eval($ex.args[2]) - $arg2 = eval($ex.args[3]) - elseif ($string(ex.args[1]) == "prints") - $op = "prints" - $arg1 = print_to_string(eval($ex.args[2]), eval($ex.args[3])...) - #$arg2 = eval($ex.args[4]) # TODO fails?! - end + $_test(expr(:quote, ex)) + end +end + +function _test(ex::Expr) + local tr = TestResult() + tr.context = tls(:context) + tr.group = tls(:group) + + # unwrap once + ex = eval(ex) + + # save the string + tr.expr_str = string(ex) + + # eval the whole thing, capturing exceptions and times + try + tr.elapsed = @elapsed tr.result = eval(ex) + catch except + tr.exception_thrown = except + end + + # if we failed without an exception, pull apart the expression and see about evaluating + # the parts + if (tr.result == false && tr.exception_thrown == NoException()) + if (ex.head == :comparison) + tr.operation = ex.head + tr.arg1 = eval(ex.args[1]) + tr.arg2 = eval(ex.args[3]) + elseif (ex.head == :call) # is it a helper we know about? + if (ex.args[1] == :approx_eq) + tr.operation = ex.args[1] + tr.arg1 = eval(ex.args[2]) + tr.arg2 = eval(ex.args[3]) + elseif (ex.args[1] == :prints) + tr.operation = ex.args[1] + tr.arg1 = print_to_string(eval(ex.args[2]), eval(ex.args[3])...) + tr.arg2 = eval(ex.args[4]) end end - - # if we're running takes_less_than, see how we did - if ($string(ex.args[1]) == "takes_less_than") - $res = $elapsed < eval($ex.args[3]) - $op = "takes_less_than" - $arg1 = $elapsed - $arg2 = eval($ex.args[3]) - end - - produce(TestResult(tls(:context), tls(:group), $string(ex), $res, $elapsed, - $exc, $op, $arg1, $arg2, Nothing)) end + + # if we're running takes_less_than, see how we did + if (ex.args[1] == :takes_less_than) + tr.result = tr.elapsed < eval(ex.args[3]) + tr.operation = ex.args[1] + tr.arg1 = tr.elapsed + tr.arg2 = eval(ex.args[3]) + end + + + produce(tr) end # helpful utility tests, supported by the macro @@ -142,7 +149,7 @@ function prints(fn::Function, args, expected::String) end function takes_less_than(anything, expected) - # the magic happens in @test + # the magic happens in _test true end