aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/eunit/doc/overview.edoc2
-rw-r--r--lib/eunit/include/eunit.hrl102
-rw-r--r--lib/eunit/src/eunit.app.src16
-rw-r--r--lib/eunit/src/eunit.erl2
-rw-r--r--lib/eunit/src/eunit_data.erl70
-rw-r--r--lib/eunit/src/eunit_server.erl7
-rw-r--r--lib/eunit/src/eunit_surefire.erl2
-rw-r--r--lib/eunit/src/eunit_test.erl72
-rw-r--r--lib/eunit/src/eunit_tests.erl26
-rw-r--r--lib/eunit/vsn.mk2
10 files changed, 236 insertions, 65 deletions
diff --git a/lib/eunit/doc/overview.edoc b/lib/eunit/doc/overview.edoc
index be05a13fba..2583f0be25 100644
--- a/lib/eunit/doc/overview.edoc
+++ b/lib/eunit/doc/overview.edoc
@@ -913,7 +913,7 @@ To make the descriptions simpler, we first list some definitions:
<td>`CleanupX'</td><td>`(X::any(), R::any()) -> any()'</td>
</tr>
<tr>
-<td>`Instantiator'</td><td>`((R::any()) -> Tests | {with, [AbstractTestFun::((any()) -> any())]}'</td>
+<td>`Instantiator'</td><td>`((R::any()) -> Tests) | {with, [AbstractTestFun::((any()) -> any())]}'</td>
</tr>
<tr>
<td>`Where'</td><td>`local | spawn | {spawn, Node::atom()}'</td>
diff --git a/lib/eunit/include/eunit.hrl b/lib/eunit/include/eunit.hrl
index 82ba982f03..493ba60a2d 100644
--- a/lib/eunit/include/eunit.hrl
+++ b/lib/eunit/include/eunit.hrl
@@ -39,6 +39,7 @@
-ifndef(EUNIT_HRL).
-define(EUNIT_HRL, true).
+
%% allow defining TEST to override NOTEST
-ifdef(TEST).
-undef(NOTEST).
@@ -164,7 +165,7 @@
%% This is mostly a convenience which gives more detailed reports.
%% Note: Guard is a guarded pattern, and can not be used for value.
-ifdef(NOASSERT).
--define(assertMatch(Guard,Expr),ok).
+-define(assertMatch(Guard, Expr), ok).
-else.
-define(assertMatch(Guard, Expr),
((fun () ->
@@ -174,17 +175,37 @@
[{module, ?MODULE},
{line, ?LINE},
{expression, (??Expr)},
- {expected, (??Guard)},
+ {pattern, (??Guard)},
{value, __V}]})
end
end)())).
-endif.
-define(_assertMatch(Guard, Expr), ?_test(?assertMatch(Guard, Expr))).
+%% This is the inverse case of assertMatch, for convenience.
+-ifdef(NOASSERT).
+-define(assertNotMatch(Guard, Expr), ok).
+-else.
+-define(assertNotMatch(Guard, Expr),
+ ((fun () ->
+ __V = (Expr),
+ case __V of
+ Guard -> .erlang:error({assertNotMatch_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {expression, (??Expr)},
+ {pattern, (??Guard)},
+ {value, __V}]});
+ _ -> ok
+ end
+ end)())).
+-endif.
+-define(_assertNotMatch(Guard, Expr), ?_test(?assertNotMatch(Guard, Expr))).
+
%% This is a convenience macro which gives more detailed reports when
%% the expected LHS value is not a pattern, but a computed value
-ifdef(NOASSERT).
--define(assertEqual(Expect,Expr),ok).
+-define(assertEqual(Expect, Expr), ok).
-else.
-define(assertEqual(Expect, Expr),
((fun (__X) ->
@@ -201,9 +222,29 @@
-endif.
-define(_assertEqual(Expect, Expr), ?_test(?assertEqual(Expect, Expr))).
+%% This is the inverse case of assertEqual, for convenience.
+-ifdef(NOASSERT).
+-define(assertNotEqual(Unexpected, Expr), ok).
+-else.
+-define(assertNotEqual(Unexpected, Expr),
+ ((fun (__X) ->
+ case (Expr) of
+ __X -> .erlang:error({assertNotEqual_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {expression, (??Expr)},
+ {value, __X}]});
+ _ -> ok
+ end
+ end)(Unexpected))).
+-endif.
+-define(_assertNotEqual(Unexpected, Expr),
+ ?_test(?assertNotEqual(Unexpected, Expr))).
+
%% Note: Class and Term are patterns, and can not be used for value.
+%% Term can be a guarded pattern, but Class cannot.
-ifdef(NOASSERT).
--define(assertException(Class, Term, Expr),ok).
+-define(assertException(Class, Term, Expr), ok).
-else.
-define(assertException(Class, Term, Expr),
((fun () ->
@@ -212,7 +253,7 @@
[{module, ?MODULE},
{line, ?LINE},
{expression, (??Expr)},
- {expected,
+ {pattern,
"{ "++(??Class)++" , "++(??Term)
++" , [...] }"},
{unexpected_success, __V}]})
@@ -223,7 +264,7 @@
[{module, ?MODULE},
{line, ?LINE},
{expression, (??Expr)},
- {expected,
+ {pattern,
"{ "++(??Class)++" , "++(??Term)
++" , [...] }"},
{unexpected_exception,
@@ -243,6 +284,43 @@
-define(_assertExit(Term, Expr), ?_assertException(exit, Term, Expr)).
-define(_assertThrow(Term, Expr), ?_assertException(throw, Term, Expr)).
+%% This is the inverse case of assertException, for convenience.
+%% Note: Class and Term are patterns, and can not be used for value.
+%% Both Class and Term can be guarded patterns.
+-ifdef(NOASSERT).
+-define(assertNotException(Class, Term, Expr), ok).
+-else.
+-define(assertNotException(Class, Term, Expr),
+ ((fun () ->
+ try (Expr) of
+ _ -> ok
+ catch
+ __C:__T ->
+ case __C of
+ Class ->
+ case __T of
+ Term ->
+ .erlang:error({assertNotException_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {expression, (??Expr)},
+ {pattern,
+ "{ "++(??Class)++" , "
+ ++(??Term)++" , [...] }"},
+ {unexpected_exception,
+ {__C, __T,
+ .erlang:get_stacktrace()
+ }}]});
+ _ -> ok
+ end;
+ _ -> ok
+ end
+ end
+ end)())).
+-endif.
+-define(_assertNotException(Class, Term, Expr),
+ ?_test(?assertNotException(Class, Term, Expr))).
+
%% Macros for running operating system commands. (Note that these
%% require EUnit to be present at runtime, or at least eunit_lib.)
@@ -267,7 +345,7 @@
%% these are only used for testing; they always return 'ok' on success,
%% and have no effect if debugging/testing is turned off
-ifdef(NOASSERT).
--define(assertCmdStatus(N, Cmd),ok).
+-define(assertCmdStatus(N, Cmd), ok).
-else.
-define(assertCmdStatus(N, Cmd),
((fun () ->
@@ -285,7 +363,7 @@
-define(assertCmd(Cmd), ?assertCmdStatus(0, Cmd)).
-ifdef(NOASSERT).
--define(assertCmdOutput(T, Cmd),ok).
+-define(assertCmdOutput(T, Cmd), ok).
-else.
-define(assertCmdOutput(T, Cmd),
((fun () ->
@@ -313,11 +391,12 @@
-define(debugHere, ok).
-define(debugFmt(S, As), ok).
-define(debugVal(E), (E)).
--define(debugTime(S,E), (E)).
+-define(debugTime(S, E), (E)).
-else.
-define(debugMsg(S),
(begin
- .io:fwrite(user, <<"~s:~w: ~s\n">>, [?FILE, ?LINE, S]),
+ .io:fwrite(user, <<"~s:~w:~w: ~s\n">>,
+ [?FILE, ?LINE, self(), S]),
ok
end)).
-define(debugHere, (?debugMsg("<-"))).
@@ -327,7 +406,7 @@
?debugFmt(<<"~s = ~P">>, [(??E), __V, 15]),
__V
end)(E))).
--define(debugTime(S,E),
+-define(debugTime(S, E),
((fun () ->
{__T0, _} = statistics(wall_clock),
__V = (E),
@@ -337,4 +416,5 @@
end)())).
-endif.
+
-endif. % EUNIT_HRL
diff --git a/lib/eunit/src/eunit.app.src b/lib/eunit/src/eunit.app.src
index 4fd76588c3..5e16dfa2ce 100644
--- a/lib/eunit/src/eunit.app.src
+++ b/lib/eunit/src/eunit.app.src
@@ -5,17 +5,17 @@
{vsn, "%VSN%"},
{modules, [eunit,
eunit_autoexport,
- eunit_striptests,
- eunit_server,
+ eunit_data,
+ eunit_lib,
+ eunit_listener,
eunit_proc,
eunit_serial,
+ eunit_server,
+ eunit_striptests,
+ eunit_surefire,
eunit_test,
eunit_tests,
- eunit_lib,
- eunit_listener,
- eunit_data,
- eunit_tty,
- eunit_surefire]},
+ eunit_tty]},
{registered,[]},
- {applications, [stdlib]},
+ {applications, [kernel,stdlib]},
{env, []}]}.
diff --git a/lib/eunit/src/eunit.erl b/lib/eunit/src/eunit.erl
index da35c5c2ec..15fc3bdf32 100644
--- a/lib/eunit/src/eunit.erl
+++ b/lib/eunit/src/eunit.erl
@@ -16,7 +16,7 @@
%% $Id: eunit.erl 339 2009-04-05 14:10:47Z rcarlsson $
%%
%% @copyright 2004-2009 Micka�l R�mond, Richard Carlsson
-%% @author Micka&euml;l R&eacute;mond <[email protected]>
+%% @author Micka�l R�mond <[email protected]>
%% [http://www.process-one.net/]
%% @author Richard Carlsson <[email protected]>
%% [http://user.it.uu.se/~richardc/]
diff --git a/lib/eunit/src/eunit_data.erl b/lib/eunit/src/eunit_data.erl
index 0543b6c543..288dd74ddf 100644
--- a/lib/eunit/src/eunit_data.erl
+++ b/lib/eunit/src/eunit_data.erl
@@ -146,8 +146,10 @@ iter_next(I = #iter{next = [T | Ts]}) ->
iter_prev(#iter{prev = []}) ->
none;
-iter_prev(#iter{prev = [T | Ts], next = Next, pos = Pos} = I) ->
- {T, I#iter{prev = Ts, next = [T | Next], pos = Pos - 1}}.
+iter_prev(#iter{prev = [T | Ts]} = I) ->
+ {T, I#iter{prev = Ts,
+ next = [T | I#iter.next],
+ pos = I#iter.pos - 1}}.
%% ---------------------------------------------------------------------
@@ -363,7 +365,8 @@ parse({file, F} = T) when is_list(F) ->
parse({dir, D}=T) when is_list(D) ->
case eunit_lib:is_string(D) of
true ->
- {data, {"directory \"" ++ D ++ "\"", get_directory_modules(D)}};
+ {data, {"directory \"" ++ D ++ "\"",
+ get_directory_module_tests(D)}};
false ->
bad_test(T)
end;
@@ -385,10 +388,10 @@ parse({S, T1} = T) when is_list(S) ->
end;
parse({S, T1}) when is_binary(S) ->
group(#group{tests = T1, desc = S});
-parse(T) when tuple_size(T) > 2, is_list(element(1, T)) ->
+parse(T) when is_tuple(T), size(T) > 2, is_list(element(1, T)) ->
[S | Es] = tuple_to_list(T),
parse({S, list_to_tuple(Es)});
-parse(T) when tuple_size(T) > 2, is_binary(element(1, T)) ->
+parse(T) when is_tuple(T), size(T) > 2, is_binary(element(1, T)) ->
[S | Es] = tuple_to_list(T),
parse({S, list_to_tuple(Es)});
parse(M) when is_atom(M) ->
@@ -596,7 +599,7 @@ testfuns(Es, M, TestSuffix, GeneratorSuffix) ->
%% ---------------------------------------------------------------------
-%% Getting a test set from a file
+%% Getting a test set from a file (text file or object file)
%% @throws {file_read_error, {Reason::atom(), Message::string(),
%% fileName()}}
@@ -625,17 +628,23 @@ get_file_tests(F) ->
is_module_filename(F) ->
filename:extension(F) =:= code:objfile_extension().
+objfile_test({M, File}) ->
+ {setup,
+ fun () ->
+ %% TODO: better error/stacktrace for this internal fun
+ code:purge(M),
+ {module,M} = code:load_abs(filename:rootname(File)),
+ ok
+ end,
+ {module, M}};
objfile_test(File) ->
+ objfile_test({objfile_module(File), File}).
+
+objfile_module(File) ->
try
- {module, M} = lists:keyfind(module, 1, beam_lib:info(File)),
- {setup,
- fun () ->
- %% TODO: better error/stacktrace for this internal fun
- code:purge(M),
- {module,M} = code:load_abs(filename:rootname(File)),
- ok
- end,
- {module, M}}
+ {value, {module, M}} = lists:keysearch(module, 1,
+ beam_lib:info(File)),
+ M
catch
_:_ ->
throw({file_read_error,
@@ -644,15 +653,34 @@ objfile_test(File) ->
%% ---------------------------------------------------------------------
-%% Getting a list of module names from object files in a directory
-
-%% @throws {file_read_error, {Reason::atom(), Message::string(),
-%% fileName()}}
+%% Getting a set of module tests from the object files in a directory
+
+%% @throws {file_read_error,
+%% {Reason::atom(), Message::string(), fileName()}}
+
+get_directory_module_tests(D) ->
+ Ms = get_directory_modules(D),
+ %% for all 'm' in the set, remove 'm_tests' if present
+ F = fun ({M,_}, S) ->
+ Name = atom_to_list(M),
+ case lists:suffix(?DEFAULT_TESTMODULE_SUFFIX, Name) of
+ false ->
+ Name1 = Name ++ ?DEFAULT_TESTMODULE_SUFFIX,
+ M1 = list_to_atom(Name1),
+ dict:erase(M1, S);
+ true ->
+ S
+ end
+ end,
+ [objfile_test(Obj)
+ || Obj <- dict:to_list(lists:foldl(F, dict:from_list(Ms), Ms))].
%% TODO: handle packages (recursive search for files)
-
get_directory_modules(D) ->
- [objfile_test(filename:join(D, F))
+ [begin
+ F1 = filename:join(D, F),
+ {objfile_module(F1), F1}
+ end
|| F <- eunit_lib:list_dir(D), is_module_filename(F)].
diff --git a/lib/eunit/src/eunit_server.erl b/lib/eunit/src/eunit_server.erl
index bf1bb9bcef..2cdfef2668 100644
--- a/lib/eunit/src/eunit_server.erl
+++ b/lib/eunit/src/eunit_server.erl
@@ -59,8 +59,9 @@ watch(Server, Module, Opts) when is_atom(Module) ->
watch_path(Server, Path, Opts) ->
command(Server, {watch, {path, filename:flatten(Path)}, Opts}).
+%% note that the user must use $ at the end to match whole paths only
watch_regexp(Server, Regex, Opts) ->
- case regexp:parse(Regex) of
+ case re:compile(Regex,[anchored]) of
{ok, R} ->
command(Server, {watch, {regexp, R}, Opts});
{error, _}=Error ->
@@ -278,8 +279,8 @@ is_watched(Path, St) ->
match_any(sets:to_list(St#state.regexps), Path).
match_any([R | Rs], Str) ->
- case regexp:first_match(Str, R) of
- {match, _, _} -> true;
+ case re:run(Str, R, [{capture,none}]) of
+ match -> true;
_ -> match_any(Rs, Str)
end;
match_any([], _Str) -> false.
diff --git a/lib/eunit/src/eunit_surefire.erl b/lib/eunit/src/eunit_surefire.erl
index 25b5cde09c..6e0a447105 100644
--- a/lib/eunit/src/eunit_surefire.erl
+++ b/lib/eunit/src/eunit_surefire.erl
@@ -15,7 +15,7 @@
%%
%% $Id: $
%%
-%% @author Micka&euml;l R&eacute;mond <[email protected]>
+%% @author Micka�l R�mond <[email protected]>
%% @copyright 2009 Micka�l R�mond, Paul Guyot
%% @see eunit
%% @doc Surefire reports for EUnit (Format used by Maven and Atlassian
diff --git a/lib/eunit/src/eunit_test.erl b/lib/eunit/src/eunit_test.erl
index d322c4b420..9ac1d1e7d9 100644
--- a/lib/eunit/src/eunit_test.erl
+++ b/lib/eunit/src/eunit_test.erl
@@ -131,12 +131,27 @@ macro_test_() ->
[{module,_},
{line,_},
{expression,_},
- {expected,"[ _ ]"},
+ {pattern,"[ _ ]"},
{value,[]}]},
_}}
= run_testfun(F)
end),
?_test(begin
+ {?LINE, F} = ?_assertNotMatch(ok, error),
+ {ok, ok} = run_testfun(F)
+ end),
+ ?_test(begin
+ {?LINE, F} = ?_assertNotMatch([_], [42]),
+ {error,{error,{assertNotMatch_failed,
+ [{module,_},
+ {line,_},
+ {expression,_},
+ {pattern,"[ _ ]"},
+ {value,[42]}]},
+ _}}
+ = run_testfun(F)
+ end),
+ ?_test(begin
{?LINE, F} = ?_assertEqual(ok, ok),
{ok, ok} = run_testfun(F)
end),
@@ -152,6 +167,20 @@ macro_test_() ->
= run_testfun(F)
end),
?_test(begin
+ {?LINE, F} = ?_assertNotEqual(1, 0),
+ {ok, ok} = run_testfun(F)
+ end),
+ ?_test(begin
+ {?LINE, F} = ?_assertNotEqual(2, 1+1),
+ {error,{error,{assertNotEqual_failed,
+ [{module,_},
+ {line,_},
+ {expression,_},
+ {value,2}]},
+ _}}
+ = run_testfun(F)
+ end),
+ ?_test(begin
{?LINE, F} = ?_assertException(error, badarith,
erlang:error(badarith)),
{ok, ok} = run_testfun(F)
@@ -162,7 +191,7 @@ macro_test_() ->
[{module,_},
{line,_},
{expression,_},
- {expected,_},
+ {pattern,_},
{unexpected_success,ok}]},
_}}
= run_testfun(F)
@@ -174,15 +203,48 @@ macro_test_() ->
[{module,_},
{line,_},
{expression,_},
- {expected,_},
+ {pattern,_},
+ {unexpected_exception,
+ {error,badarith,_}}]},
+ _}}
+ = run_testfun(F)
+ end),
+ ?_test(begin
+ {?LINE, F} = ?_assertError(badarith,
+ erlang:error(badarith)),
+ {ok, ok} = run_testfun(F)
+ end),
+ ?_test(begin
+ {?LINE, F} = ?_assertExit(normal, exit(normal)),
+ {ok, ok} = run_testfun(F)
+ end),
+ ?_test(begin
+ {?LINE, F} = ?_assertThrow(foo, throw(foo)),
+ {ok, ok} = run_testfun(F)
+ end),
+ ?_test(begin
+ {?LINE, F} = ?_assertNotException(error, badarith, 42),
+ {ok, ok} = run_testfun(F)
+ end),
+ ?_test(begin
+ {?LINE, F} = ?_assertNotException(error, badarith,
+ erlang:error(badarg)),
+ {ok, ok} = run_testfun(F)
+ end),
+ ?_test(begin
+ {?LINE, F} = ?_assertNotException(error, badarith,
+ erlang:error(badarith)),
+ {error,{error,{assertNotException_failed,
+ [{module,_},
+ {line,_},
+ {expression,_},
+ {pattern,_},
{unexpected_exception,
{error,badarith,_}}]},
_}}
= run_testfun(F)
end)
]}.
-
-under_eunit_test() -> ?assert(?UNDER_EUNIT).
-endif.
diff --git a/lib/eunit/src/eunit_tests.erl b/lib/eunit/src/eunit_tests.erl
index 37c0b4d6ae..a63d102d98 100644
--- a/lib/eunit/src/eunit_tests.erl
+++ b/lib/eunit/src/eunit_tests.erl
@@ -26,17 +26,17 @@
-include("eunit.hrl").
-ifdef(TEST).
-%% Cause all the other modules to be tested as well as this one.
-full_test_() ->
- %%{application, eunit}. % this currently causes a loop
- %% We use the below until loop detection is implemented
- [eunit_autoexport,
- eunit_striptests,
- eunit_server,
- eunit_proc,
- eunit_serial,
- eunit_test,
- eunit_lib,
- eunit_data,
- eunit_tty].
+id(X) -> X. % for suppressing compiler warnings
-endif.
+
+under_eunit_test() -> ?assert(?UNDER_EUNIT).
+
+let_test() -> ?assertEqual(42, ?LET(X, 17, X+25)).
+
+if_test_() ->
+ [?_assertEqual(17, ?IF(id(1) > 0, 17, 42)),
+ ?_assertEqual(42, ?IF(id(1) < 0, 17, 42))].
+
+matches_test_() ->
+ [?_assert(?MATCHES("hel"++_, "hello")),
+ ?_assertNot(?MATCHES("hal"++_, "hello"))].
diff --git a/lib/eunit/vsn.mk b/lib/eunit/vsn.mk
index d7edd7977b..d933085bbc 100644
--- a/lib/eunit/vsn.mk
+++ b/lib/eunit/vsn.mk
@@ -1 +1 @@
-EUNIT_VSN = 2.1.7
+EUNIT_VSN = 2.2.0