aboutsummaryrefslogtreecommitdiffstats
path: root/lib/eunit
diff options
context:
space:
mode:
Diffstat (limited to 'lib/eunit')
-rw-r--r--lib/eunit/doc/overview.edoc6
-rw-r--r--lib/eunit/include/eunit.hrl270
-rw-r--r--lib/eunit/src/Makefile2
-rw-r--r--lib/eunit/src/eunit.app.src2
-rw-r--r--lib/eunit/src/eunit.erl2
-rw-r--r--lib/eunit/src/eunit_autoexport.erl11
-rw-r--r--lib/eunit/src/eunit_data.erl2
-rw-r--r--lib/eunit/src/eunit_internal.hrl4
-rw-r--r--lib/eunit/src/eunit_lib.erl42
-rw-r--r--lib/eunit/src/eunit_proc.erl7
-rw-r--r--lib/eunit/src/eunit_server.erl2
-rw-r--r--lib/eunit/src/eunit_surefire.erl37
-rw-r--r--lib/eunit/src/eunit_tty.erl24
-rw-r--r--lib/eunit/test/Makefile4
-rw-r--r--lib/eunit/test/eunit_SUITE.erl38
-rw-r--r--lib/eunit/test/tlatin.erl15
-rw-r--r--lib/eunit/test/tutf8.erl15
-rw-r--r--lib/eunit/vsn.mk2
18 files changed, 177 insertions, 308 deletions
diff --git a/lib/eunit/doc/overview.edoc b/lib/eunit/doc/overview.edoc
index 872a017440..df716cdeea 100644
--- a/lib/eunit/doc/overview.edoc
+++ b/lib/eunit/doc/overview.edoc
@@ -569,6 +569,9 @@ Examples:
```?assertMatch({found, {fred, _}}, lookup(bloggs, Table))'''
```?assertMatch([X|_] when X > 0, binary_to_list(B))'''
</dd>
+<dt>`assertNotMatch(GuardedPattern, Expr)'</dt>
+<dd>The inverse case of assertMatch, for convenience.
+</dd>
<dt>`assertEqual(Expect, Expr)'</dt>
<dd>Evaluates the expressions `Expect' and `Expr' and compares the
results for equality, if testing is enabled. If the values are not
@@ -583,6 +586,9 @@ Examples:
```?assertEqual("b" ++ "a", lists:reverse("ab"))'''
```?assertEqual(foo(X), bar(Y))'''
</dd>
+<dt>`assertNotEqual(Unexpected, Expr)'</dt>
+<dd>The inverse case of assertEqual, for convenience.
+</dd>
<dt>`assertException(ClassPattern, TermPattern, Expr)'</dt>
<dt>`assertError(TermPattern, Expr)'</dt>
<dt>`assertExit(TermPattern, Expr)'</dt>
diff --git a/lib/eunit/include/eunit.hrl b/lib/eunit/include/eunit.hrl
index 9e8d34567a..88e9d6c19b 100644
--- a/lib/eunit/include/eunit.hrl
+++ b/lib/eunit/include/eunit.hrl
@@ -15,11 +15,14 @@
%%
%% Copyright (C) 2004-2006 Mickaël Rémond, Richard Carlsson
+-ifndef(EUNIT_HRL).
+-define(EUNIT_HRL, true).
+
%% Including this file turns on testing and defines TEST, unless NOTEST
%% is defined before the file is included. If both NOTEST and TEST are
%% already defined, then TEST takes precedence, and NOTEST will become
%% undefined.
-%%
+%%
%% If NODEBUG is defined before this file is included, the debug macros
%% are disabled, unless DEBUG is also defined, in which case NODEBUG
%% will become undefined. NODEBUG also implies NOASSERT, unless testing
@@ -31,14 +34,10 @@
%% even if NODEBUG is defined. If both ASSERT and NOASSERT are defined
%% before the file is included, then ASSERT takes precedence, and NOASSERT
%% will become undefined regardless of TEST.
-%%
+%%
%% After including this file, EUNIT will be defined if and only if TEST
%% is defined.
--ifndef(EUNIT_HRL).
--define(EUNIT_HRL, true).
-
-
%% allow defining TEST to override NOTEST
-ifdef(TEST).
-undef(NOTEST).
@@ -49,13 +48,6 @@
-undef(NODEBUG).
-endif.
-%% allow NODEBUG to imply NOASSERT, unless overridden below
--ifdef(NODEBUG).
--ifndef(NOASSERT).
--define(NOASSERT, true).
--endif.
--endif.
-
%% note that the main switch used within this file is NOTEST; however,
%% both TEST and EUNIT may be used to check whether testing is enabled
-ifndef(NOTEST).
@@ -70,10 +62,8 @@
-undef(EUNIT).
-endif.
-%% allow ASSERT to override NOASSERT (regardless of TEST/NOTEST)
--ifdef(ASSERT).
--undef(NOASSERT).
--endif.
+%% include the assert macros; ASSERT overrides NOASSERT if defined
+-include_lib("stdlib/include/assert.hrl").
%% Parse transforms for automatic exporting/stripping of test functions.
%% (Note that although automatic stripping is convenient, it will make
@@ -91,7 +81,7 @@
%% All macros should be available even if testing is turned off, and
%% should preferably not require EUnit to be present at runtime.
-%%
+%%
%% We must use fun-call wrappers ((fun () -> ... end)()) to avoid
%% exporting local variables, and furthermore we only use variable names
%% prefixed with "__", that hopefully will not be bound outside the fun.
@@ -128,211 +118,24 @@
current_function)))).
-endif.
-%% The plain assert macro should be defined to do nothing if this file
-%% is included when debugging/testing is turned off.
--ifdef(NOASSERT).
--ifndef(assert).
--define(assert(BoolExpr),ok).
--endif.
--else.
-%% The assert macro is written the way it is so as not to cause warnings
-%% for clauses that cannot match, even if the expression is a constant.
--undef(assert).
--define(assert(BoolExpr),
- begin
- ((fun () ->
- case (BoolExpr) of
- true -> ok;
- __V -> erlang:error({assertion_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {expression, (??BoolExpr)},
- {expected, true},
- {value, case __V of false -> __V;
- _ -> {not_a_boolean,__V}
- end}]})
- end
- end)())
- end).
--endif.
--define(assertNot(BoolExpr), ?assert(not (BoolExpr))).
+%% General test macros
-define(_test(Expr), {?LINE, fun () -> (Expr) end}).
-
-define(_assert(BoolExpr), ?_test(?assert(BoolExpr))).
-
-define(_assertNot(BoolExpr), ?_assert(not (BoolExpr))).
-
-%% 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).
--else.
--define(assertMatch(Guard, Expr),
- begin
- ((fun () ->
- case (Expr) of
- Guard -> ok;
- __V -> erlang:error({assertMatch_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {expression, (??Expr)},
- {pattern, (??Guard)},
- {value, __V}]})
- end
- 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),
- begin
- ((fun () ->
- __V = (Expr),
- case __V of
- Guard -> erlang:error({assertNotMatch_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {expression, (??Expr)},
- {pattern, (??Guard)},
- {value, __V}]});
- _ -> ok
- end
- 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).
--else.
--define(assertEqual(Expect, Expr),
- begin
- ((fun (__X) ->
- case (Expr) of
- __X -> ok;
- __V -> erlang:error({assertEqual_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {expression, (??Expr)},
- {expected, __X},
- {value, __V}]})
- end
- end)(Expect))
- end).
--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),
- begin
- ((fun (__X) ->
- case (Expr) of
- __X -> erlang:error({assertNotEqual_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {expression, (??Expr)},
- {value, __X}]});
- _ -> ok
- end
- end)(Unexpected))
- end).
--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).
--else.
--define(assertException(Class, Term, Expr),
- begin
- ((fun () ->
- try (Expr) of
- __V -> erlang:error({assertException_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {expression, (??Expr)},
- {pattern,
- "{ "++(??Class)++" , "++(??Term)
- ++" , [...] }"},
- {unexpected_success, __V}]})
- catch
- Class:Term -> ok;
- __C:__T ->
- erlang:error({assertException_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {expression, (??Expr)},
- {pattern,
- "{ "++(??Class)++" , "++(??Term)
- ++" , [...] }"},
- {unexpected_exception,
- {__C, __T,
- erlang:get_stacktrace()}}]})
- end
- end)())
- end).
--endif.
-
--define(assertError(Term, Expr), ?assertException(error, Term, Expr)).
--define(assertExit(Term, Expr), ?assertException(exit, Term, Expr)).
--define(assertThrow(Term, Expr), ?assertException(throw, Term, Expr)).
-
-define(_assertException(Class, Term, Expr),
?_test(?assertException(Class, Term, Expr))).
-define(_assertError(Term, Expr), ?_assertException(error, Term, Expr)).
-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),
- begin
- ((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)())
- end).
--endif.
-define(_assertNotException(Class, Term, Expr),
?_test(?assertNotException(Class, Term, Expr))).
+-define(_assertReceive(Guard, Expr), ?_test(?assertReceive(Guard, Expr))).
%% Macros for running operating system commands. (Note that these
%% require EUnit to be present at runtime, or at least eunit_lib.)
@@ -364,18 +167,18 @@
-else.
-define(assertCmdStatus(N, Cmd),
begin
- ((fun () ->
- case ?_cmd_(Cmd) of
- {(N), _} -> ok;
- {__N, _} -> erlang:error({assertCmd_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {command, (Cmd)},
- {expected_status,(N)},
- {status,__N}]})
- end
- end)())
- end).
+ ((fun () ->
+ case ?_cmd_(Cmd) of
+ {(N), _} -> ok;
+ {__N, _} -> erlang:error({assertCmd_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {command, (Cmd)},
+ {expected_status,(N)},
+ {status,__N}]})
+ end
+ end)())
+ end).
-endif.
-define(assertCmd(Cmd), ?assertCmdStatus(0, Cmd)).
@@ -384,17 +187,17 @@
-else.
-define(assertCmdOutput(T, Cmd),
begin
- ((fun () ->
- case ?_cmd_(Cmd) of
- {_, (T)} -> ok;
- {_, __T} -> erlang:error({assertCmdOutput_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {command,(Cmd)},
- {expected_output,(T)},
- {output,__T}]})
- end
- end)())
+ ((fun () ->
+ case ?_cmd_(Cmd) of
+ {_, (T)} -> ok;
+ {_, __T} -> erlang:error({assertCmdOutput_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {command,(Cmd)},
+ {expected_output,(T)},
+ {output,__T}]})
+ end
+ end)())
end).
-endif.
@@ -414,7 +217,7 @@
-else.
-define(debugMsg(S),
begin
- io:fwrite(user, <<"~s:~w:~w: ~s\n">>,
+ io:fwrite(user, <<"~ts:~w:~w: ~ts\n">>,
[?FILE, ?LINE, self(), S]),
ok
end).
@@ -423,7 +226,7 @@
-define(debugVal(E),
begin
((fun (__V) ->
- ?debugFmt(<<"~s = ~P">>, [(??E), __V, 15]),
+ ?debugFmt(<<"~ts = ~tP">>, [(??E), __V, 15]),
__V
end)(E))
end).
@@ -433,11 +236,10 @@
{__T0, _} = statistics(wall_clock),
__V = (E),
{__T1, _} = statistics(wall_clock),
- ?debugFmt(<<"~s: ~.3f s">>, [(S), (__T1-__T0)/1000]),
+ ?debugFmt(<<"~ts: ~.3f s">>, [(S), (__T1-__T0)/1000]),
__V
end)())
end).
-endif.
-
-endif. % EUNIT_HRL
diff --git a/lib/eunit/src/Makefile b/lib/eunit/src/Makefile
index 47aef104ff..86a6d8831e 100644
--- a/lib/eunit/src/Makefile
+++ b/lib/eunit/src/Makefile
@@ -24,7 +24,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/eunit-$(VSN)
EBIN = ../ebin
INCLUDE=../include
-ERL_COMPILE_FLAGS += -pa $(EBIN) -I$(INCLUDE) +warn_unused_vars +nowarn_shadow_vars +warn_unused_import +warn_obsolete_guard
+ERL_COMPILE_FLAGS += -pa $(EBIN) -pa ../../stdlib/ebin -I$(INCLUDE) +warn_unused_vars +nowarn_shadow_vars +warn_unused_import +warn_obsolete_guard
PARSE_TRANSFORM = eunit_autoexport.erl
diff --git a/lib/eunit/src/eunit.app.src b/lib/eunit/src/eunit.app.src
index 7a3978e200..b4ff6c9242 100644
--- a/lib/eunit/src/eunit.app.src
+++ b/lib/eunit/src/eunit.app.src
@@ -19,4 +19,4 @@
{registered,[]},
{applications, [kernel,stdlib]},
{env, []},
- {runtime_dependencies, ["stdlib-2.0","kernel-3.0","erts-6.0"]}]}.
+ {runtime_dependencies, ["stdlib-2.5","kernel-3.0","erts-6.0"]}]}.
diff --git a/lib/eunit/src/eunit.erl b/lib/eunit/src/eunit.erl
index 9c589dfa86..fbfd123c43 100644
--- a/lib/eunit/src/eunit.erl
+++ b/lib/eunit/src/eunit.erl
@@ -231,7 +231,7 @@ event_logger(LogFile) ->
event_logger_loop(Reference, FD) ->
receive
{status, _Id, _Info}=Msg ->
- io:fwrite(FD, "~p.\n", [Msg]),
+ io:fwrite(FD, "~tp.\n", [Msg]),
event_logger_loop(Reference, FD);
{stop, Reference, _ReplyTo} ->
%% no need to reply, just exit
diff --git a/lib/eunit/src/eunit_autoexport.erl b/lib/eunit/src/eunit_autoexport.erl
index 36ae3b71d7..7bb78f5ea8 100644
--- a/lib/eunit/src/eunit_autoexport.erl
+++ b/lib/eunit/src/eunit_autoexport.erl
@@ -79,11 +79,12 @@ rewrite([{function,_,test,0,_}=F | Fs], As, Module, _Test) ->
rewrite([F | Fs], As, Module, Test) ->
rewrite(Fs, [F | As], Module, Test);
rewrite([], As, Module, Test) ->
+ L = erl_anno:new(0),
{if Test ->
- [{function,0,test,0,
- [{clause,0,[],[],
- [{call,0,{remote,0,{atom,0,eunit},{atom,0,test}},
- [{atom,0,Module}]}]}]}
+ [{function,L,test,0,
+ [{clause,L,[],[],
+ [{call,L,{remote,L,{atom,L,eunit},{atom,L,test}},
+ [{atom,L,Module}]}]}]}
| As];
true ->
As
@@ -96,4 +97,4 @@ module_decl(Name, M, Fs, Exports) ->
Es = if Test -> [{test,0} | Exports];
true -> Exports
end,
- [M, {attribute,0,export,Es} | lists:reverse(Fs1)].
+ [M, {attribute,erl_anno:new(0),export,Es} | lists:reverse(Fs1)].
diff --git a/lib/eunit/src/eunit_data.erl b/lib/eunit/src/eunit_data.erl
index cbbc6fbc15..8b53a3681d 100644
--- a/lib/eunit/src/eunit_data.erl
+++ b/lib/eunit/src/eunit_data.erl
@@ -391,7 +391,7 @@ parse({with, X, As}=T) when is_list(As) ->
parse({S, T1} = T) when is_list(S) ->
case eunit_lib:is_string(S) of
true ->
- group(#group{tests = T1, desc = list_to_binary(S)});
+ group(#group{tests = T1, desc = unicode:characters_to_binary(S)});
false ->
bad_test(T)
end;
diff --git a/lib/eunit/src/eunit_internal.hrl b/lib/eunit/src/eunit_internal.hrl
index 92694ec39b..8e1e27811f 100644
--- a/lib/eunit/src/eunit_internal.hrl
+++ b/lib/eunit/src/eunit_internal.hrl
@@ -14,8 +14,8 @@
-define(DEFAULT_MODULE_WRAPPER_NAME, eunit_wrapper_).
-ifdef(DEBUG).
--define(debugmsg(S),io:fwrite("\n* ~s: ~s\n", [?MODULE,S])).
--define(debugmsg1(S,As),io:fwrite("\n* ~s: " ++ S ++ "\n", [?MODULE] ++ As)).
+-define(debugmsg(S),io:fwrite("\n* ~ts: ~ts\n", [?MODULE,S])).
+-define(debugmsg1(S,As),io:fwrite("\n* ~ts: " ++ S ++ "\n", [?MODULE] ++ As)).
-else.
-define(debugmsg(S),ok).
-define(debugmsg1(S,As),ok).
diff --git a/lib/eunit/src/eunit_lib.erl b/lib/eunit/src/eunit_lib.erl
index 40bae93298..d8f98cffa5 100644
--- a/lib/eunit/src/eunit_lib.erl
+++ b/lib/eunit/src/eunit_lib.erl
@@ -57,7 +57,7 @@ format_exception({Class,Term,Trace}, Depth)
when is_atom(Class), is_list(Trace) ->
case is_stacktrace(Trace) of
true ->
- io_lib:format("~s**~w:~s",
+ io_lib:format("~ts**~w:~ts",
[format_stacktrace(Trace), Class,
format_term(Term, Depth)]);
false ->
@@ -67,11 +67,11 @@ format_exception(Term, Depth) ->
format_term(Term, Depth).
format_term(Term, Depth) ->
- io_lib:format("~P\n", [Term, Depth]).
+ io_lib:format("~tP\n", [Term, Depth]).
format_exit_term(Term) ->
{Reason, Trace} = analyze_exit_term(Term),
- io_lib:format("~P~s", [Reason, 15, Trace]).
+ io_lib:format("~tP~ts", [Reason, 15, Trace]).
analyze_exit_term({Reason, [_|_]=Trace}=Term) ->
case is_stacktrace(Trace) of
@@ -102,7 +102,7 @@ format_stacktrace(Trace) ->
format_stacktrace(Trace, "in function", "in call from").
format_stacktrace([{M,F,A,L}|Fs], Pre, Pre1) when is_integer(A) ->
- [io_lib:fwrite("~s ~w:~w/~w~s\n",
+ [io_lib:fwrite("~ts ~w:~w/~w~ts\n",
[Pre, M, F, A, format_stacktrace_location(L)])
| format_stacktrace(Fs, Pre1, Pre1)];
format_stacktrace([{M,F,As,L}|Fs], Pre, Pre1) when is_list(As) ->
@@ -110,15 +110,15 @@ format_stacktrace([{M,F,As,L}|Fs], Pre, Pre1) when is_list(As) ->
C = case is_op(M,F,A) of
true when A =:= 1 ->
[A1] = As,
- io_lib:fwrite("~s ~s", [F,format_arg(A1)]);
+ io_lib:fwrite("~ts ~ts", [F,format_arg(A1)]);
true when A =:= 2 ->
[A1, A2] = As,
- io_lib:fwrite("~s ~s ~s",
+ io_lib:fwrite("~ts ~ts ~ts",
[format_arg(A1),F,format_arg(A2)]);
false ->
- io_lib:fwrite("~w(~s)", [F,format_arglist(As)])
+ io_lib:fwrite("~w(~ts)", [F,format_arglist(As)])
end,
- [io_lib:fwrite("~s ~w:~w/~w~s\n called as ~s\n",
+ [io_lib:fwrite("~ts ~w:~w/~w~ts\n called as ~ts\n",
[Pre,M,F,A,format_stacktrace_location(L),C])
| format_stacktrace(Fs,Pre1,Pre1)];
format_stacktrace([{M,F,As}|Fs], Pre, Pre1) ->
@@ -130,18 +130,18 @@ format_stacktrace_location(Location) ->
File = proplists:get_value(file, Location),
Line = proplists:get_value(line, Location),
if File =/= undefined, Line =/= undefined ->
- io_lib:format(" (~s, line ~w)", [File, Line]);
+ io_lib:format(" (~ts, line ~w)", [File, Line]);
true ->
""
end.
format_arg(A) ->
- io_lib:format("~P",[A,15]).
+ io_lib:format("~tP",[A,15]).
format_arglist([A]) ->
format_arg(A);
format_arglist([A|As]) ->
- [io_lib:format("~P,",[A,15]) | format_arglist(As)];
+ [io_lib:format("~tP,",[A,15]) | format_arglist(As)];
format_arglist([]) ->
"".
@@ -155,41 +155,41 @@ is_op(_M, _F, _A) ->
false.
format_error({bad_test, Term}) ->
- error_msg("bad test descriptor", "~P", [Term, 15]);
+ error_msg("bad test descriptor", "~tP", [Term, 15]);
format_error({bad_generator, {{M,F,A}, Term}}) ->
error_msg(io_lib:format("result from generator ~w:~w/~w is not a test",
[M,F,A]),
- "~P", [Term, 15]);
+ "~tP", [Term, 15]);
format_error({generator_failed, {{M,F,A}, Exception}}) ->
error_msg(io_lib:format("test generator ~w:~w/~w failed",[M,F,A]),
- "~s", [format_exception(Exception)]);
+ "~ts", [format_exception(Exception)]);
format_error({no_such_function, {M,F,A}})
when is_atom(M), is_atom(F), is_integer(A) ->
error_msg(io_lib:format("no such function: ~w:~w/~w", [M,F,A]),
"", []);
format_error({module_not_found, M}) ->
- error_msg("test module not found", "~p", [M]);
+ error_msg("test module not found", "~tp", [M]);
format_error({application_not_found, A}) when is_atom(A) ->
error_msg("application not found", "~w", [A]);
format_error({file_read_error, {_R, Msg, F}}) ->
- error_msg("error reading file", "~s: ~s", [Msg, F]);
+ error_msg("error reading file", "~ts: ~ts", [Msg, F]);
format_error({setup_failed, Exception}) ->
- error_msg("context setup failed", "~s",
+ error_msg("context setup failed", "~ts",
[format_exception(Exception)]);
format_error({cleanup_failed, Exception}) ->
- error_msg("context cleanup failed", "~s",
+ error_msg("context cleanup failed", "~ts",
[format_exception(Exception)]);
format_error({{bad_instantiator, {{M,F,A}, Term}}, _DummyException}) ->
error_msg(io_lib:format("result from instantiator ~w:~w/~w is not a test",
[M,F,A]),
- "~P", [Term, 15]);
+ "~tP", [Term, 15]);
format_error({instantiation_failed, Exception}) ->
- error_msg("instantiation of subtests failed", "~s",
+ error_msg("instantiation of subtests failed", "~ts",
[format_exception(Exception)]).
error_msg(Title, Fmt, Args) ->
Msg = io_lib:format("**"++Fmt, Args), % gets indentation right
- io_lib:fwrite("*** ~s ***\n~s\n\n", [Title, Msg]).
+ io_lib:fwrite("*** ~ts ***\n~ts\n\n", [Title, Msg]).
-ifdef(TEST).
format_exception_test_() ->
diff --git a/lib/eunit/src/eunit_proc.erl b/lib/eunit/src/eunit_proc.erl
index 03d1a18321..98ae31d54b 100644
--- a/lib/eunit/src/eunit_proc.erl
+++ b/lib/eunit/src/eunit_proc.erl
@@ -230,7 +230,7 @@ insulator_wait(Child, Parent, Buf, St) ->
message_super(Id, {progress, 'begin', {Type, Data}}, St),
insulator_wait(Child, Parent, [[] | Buf], St);
{child, Child, Id, {'end', Status, Time}} ->
- Data = [{time, Time}, {output, buffer_to_binary(hd(Buf))}],
+ Data = [{time, Time}, {output, lists:reverse(hd(Buf))}],
message_super(Id, {progress, 'end', {Status, Data}}, St),
insulator_wait(Child, Parent, tl(Buf), St);
{child, Child, Id, {skipped, Reason}} ->
@@ -272,9 +272,6 @@ kill_task(Child, St) ->
exit(Child, kill),
terminate_insulator(St).
-buffer_to_binary([B]) when is_binary(B) -> B; % avoid unnecessary copying
-buffer_to_binary(Buf) -> list_to_binary(lists:reverse(Buf)).
-
%% Unlinking before exit avoids polluting the parent process with exit
%% signals from the insulator. The child process is already dead here.
@@ -597,7 +594,7 @@ group_leader_loop(Runner, Wait, Buf) ->
%% no more messages and nothing to wait for; we ought to
%% have collected all immediately pending output now
process_flag(priority, normal),
- Runner ! {self(), buffer_to_binary(Buf)}
+ Runner ! {self(), lists:reverse(Buf)}
end.
group_leader_sync(G) ->
diff --git a/lib/eunit/src/eunit_server.erl b/lib/eunit/src/eunit_server.erl
index 2002930abb..387976eba1 100644
--- a/lib/eunit/src/eunit_server.erl
+++ b/lib/eunit/src/eunit_server.erl
@@ -200,7 +200,7 @@ server_command(From, stop, St) ->
server(St#state{stopped = true});
server_command(From, {watch, Target, _Opts}, St) ->
%% the code watcher is only started on demand
- %% FIXME: this is disabled for now in the OTP distribution
+ %% TODO: this is disabled for now
%%code_monitor:monitor(self()),
%% TODO: propagate options to testing stage
St1 = add_watch(Target, St),
diff --git a/lib/eunit/src/eunit_surefire.erl b/lib/eunit/src/eunit_surefire.erl
index 2d1f0b1497..f3e58a3d1c 100644
--- a/lib/eunit/src/eunit_surefire.erl
+++ b/lib/eunit/src/eunit_surefire.erl
@@ -203,9 +203,9 @@ handle_cancel(test, Data, St) ->
testcases=[TestCase|TestSuite#testsuite.testcases] },
St#state{testsuites=store_suite(NewTestSuite, TestSuites)}.
-format_name({Module, Function, Arity}, Line) ->
- lists:flatten([atom_to_list(Module), ":", atom_to_list(Function), "/",
- integer_to_list(Arity), "_", integer_to_list(Line)]).
+format_name({Module, Function, _Arity}, Line) ->
+ lists:flatten([atom_to_list(Module), ":", integer_to_list(Line), " ",
+ atom_to_list(Function)]).
format_desc(undefined) ->
"";
format_desc(Desc) when is_binary(Desc) ->
@@ -279,7 +279,7 @@ write_report_to(TestSuite, FileDescriptor) ->
%% Write the XML header.
%% ----------------------------------------------------------------------------
write_header(FileDescriptor) ->
- file:write(FileDescriptor, [<<"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>">>, ?NEWLINE]).
+ io:format(FileDescriptor, "~ts~ts", [<<"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>">>, ?NEWLINE]).
%% ----------------------------------------------------------------------------
%% Write the testsuite start tag, with attributes describing the statistics
@@ -303,7 +303,7 @@ write_start_tag(
<<"\" time=\"">>, format_time(Time),
<<"\" name=\"">>, escape_attr(Name),
<<"\">">>, ?NEWLINE],
- file:write(FileDescriptor, StartTag).
+ io:format(FileDescriptor, "~ts", [StartTag]).
%% ----------------------------------------------------------------------------
%% Recursive function to write the test cases.
@@ -317,7 +317,7 @@ write_testcases([TestCase| Tail], FileDescriptor) ->
%% Write the testsuite end tag.
%% ----------------------------------------------------------------------------
write_end_tag(FileDescriptor) ->
- file:write(FileDescriptor, [<<"</testsuite>">>, ?NEWLINE]).
+ io:format(FileDescriptor, "~ts~ts", [<<"</testsuite>">>, ?NEWLINE]).
%% ----------------------------------------------------------------------------
%% Write a test case, as a testcase tag.
@@ -334,17 +334,16 @@ write_testcase(
FileDescriptor) ->
DescriptionAttr = case Description of
[] -> [];
- _ -> [<<" description=\"">>, escape_attr(Description), <<"\"">>]
+ _ -> [<<" (">>, escape_attr(Description), <<")">>]
end,
StartTag = [
?INDENT, <<"<testcase time=\"">>, format_time(Time),
- <<"\" name=\"">>, escape_attr(Name), <<"\"">>,
- DescriptionAttr],
+ <<"\" name=\"">>, escape_attr(Name), DescriptionAttr, <<"\"">>],
ContentAndEndTag = case {Result, Output} of
{ok, <<>>} -> [<<"/>">>, ?NEWLINE];
_ -> [<<">">>, ?NEWLINE, format_testcase_result(Result), format_testcase_output(Output), ?INDENT, <<"</testcase>">>, ?NEWLINE]
end,
- file:write(FileDescriptor, [StartTag, ContentAndEndTag]).
+ io:format(FileDescriptor, "~ts~ts", [StartTag, ContentAndEndTag]).
%% ----------------------------------------------------------------------------
%% Format the result of the test.
@@ -427,7 +426,7 @@ escape_suitename([Char | Tail], Acc) -> escape_suitename(Tail, [Char | Acc]).
%% Replace < with &lt;, > with &gt; and & with &amp;
%% ----------------------------------------------------------------------------
escape_text(Text) when is_binary(Text) -> escape_text(binary_to_list(Text));
-escape_text(Text) -> escape_xml(lists:flatten(Text), [], false).
+escape_text(Text) -> escape_xml(to_utf8(lists:flatten(Text)), [], false).
%% ----------------------------------------------------------------------------
@@ -435,7 +434,7 @@ escape_text(Text) -> escape_xml(lists:flatten(Text), [], false).
%% Replace < with &lt;, > with &gt; and & with &amp;
%% ----------------------------------------------------------------------------
escape_attr(Text) when is_binary(Text) -> escape_attr(binary_to_list(Text));
-escape_attr(Text) -> escape_xml(lists:flatten(Text), [], true).
+escape_attr(Text) -> escape_xml(to_utf8(lists:flatten(Text)), [], true).
escape_xml([], Acc, _ForAttr) -> lists:reverse(Acc);
escape_xml([$< | Tail], Acc, ForAttr) -> escape_xml(Tail, [$;, $t, $l, $& | Acc], ForAttr);
@@ -443,3 +442,17 @@ escape_xml([$> | Tail], Acc, ForAttr) -> escape_xml(Tail, [$;, $t, $g, $& | Acc]
escape_xml([$& | Tail], Acc, ForAttr) -> escape_xml(Tail, [$;, $p, $m, $a, $& | Acc], ForAttr);
escape_xml([$" | Tail], Acc, true) -> escape_xml(Tail, [$;, $t, $o, $u, $q, $& | Acc], true); % "
escape_xml([Char | Tail], Acc, ForAttr) when is_integer(Char) -> escape_xml(Tail, [Char | Acc], ForAttr).
+
+%% the input may be utf8 or latin1; the resulting list is unicode
+to_utf8(Desc) when is_binary(Desc) ->
+ case unicode:characters_to_list(Desc) of
+ {_,_,_} -> unicode:characters_to_list(Desc, latin1);
+ X -> X
+ end;
+to_utf8(Desc) when is_list(Desc) ->
+ try
+ to_utf8(list_to_binary(Desc))
+ catch
+ _:_ ->
+ Desc
+ end.
diff --git a/lib/eunit/src/eunit_tty.erl b/lib/eunit/src/eunit_tty.erl
index f21b2da3d3..699d2adaca 100644
--- a/lib/eunit/src/eunit_tty.erl
+++ b/lib/eunit/src/eunit_tty.erl
@@ -83,7 +83,7 @@ terminate({ok, Data}, St) ->
sync_end(error)
end;
terminate({error, Reason}, _St) ->
- fwrite("Internal error: ~P.\n", [Reason, 25]),
+ fwrite("Internal error: ~tP.\n", [Reason, 25]),
sync_end(error).
sync_end(Result) ->
@@ -177,7 +177,7 @@ indent(_N) ->
print_group_start(I, Desc) ->
indent(I),
- fwrite("~s\n", [Desc]).
+ fwrite("~ts\n", [Desc]).
print_group_end(I, Time) ->
if Time > 0 ->
@@ -195,13 +195,13 @@ print_test_begin(I, Data) ->
true -> io_lib:fwrite("~w:", [Line])
end,
D = if Desc =:= "" ; Desc =:= undefined -> "";
- true -> io_lib:fwrite(" (~s)", [Desc])
+ true -> io_lib:fwrite(" (~ts)", [Desc])
end,
case proplists:get_value(source, Data) of
{Module, Name, _Arity} ->
- fwrite("~s:~s ~s~s...", [Module, L, Name, D]);
+ fwrite("~ts:~ts ~ts~ts...", [Module, L, Name, D]);
_ ->
- fwrite("~s~s...", [L, D])
+ fwrite("~ts~ts...", [L, D])
end.
print_test_end(Data) ->
@@ -209,21 +209,21 @@ print_test_end(Data) ->
T = if Time > 0 -> io_lib:fwrite("[~.3f s] ", [Time/1000]);
true -> ""
end,
- fwrite("~sok\n", [T]).
+ fwrite("~tsok\n", [T]).
print_test_error({error, Exception}, Data) ->
Output = proplists:get_value(output, Data),
- fwrite("*failed*\n~s", [eunit_lib:format_exception(Exception)]),
+ fwrite("*failed*\n~ts", [eunit_lib:format_exception(Exception)]),
case Output of
<<>> ->
fwrite("\n\n");
<<Text:800/binary, _:1/binary, _/binary>> ->
- fwrite(" output:<<\"~s\">>...\n\n", [Text]);
+ fwrite(" output:<<\"~ts\">>...\n\n", [Text]);
_ ->
- fwrite(" output:<<\"~s\">>\n\n", [Output])
+ fwrite(" output:<<\"~ts\">>\n\n", [Output])
end;
print_test_error({skipped, Reason}, _) ->
- fwrite("*did not run*\n::~s\n", [format_skipped(Reason)]).
+ fwrite("*did not run*\n::~ts\n", [format_skipped(Reason)]).
format_skipped({module_not_found, M}) ->
io_lib:fwrite("missing module: ~w", [M]);
@@ -244,12 +244,12 @@ format_cancel(undefined) ->
format_cancel(timeout) ->
"*timed out*\n";
format_cancel({startup, Reason}) ->
- io_lib:fwrite("*could not start test process*\n::~P\n\n",
+ io_lib:fwrite("*could not start test process*\n::~tP\n\n",
[Reason, 15]);
format_cancel({blame, _SubId}) ->
"*cancelled because of subtask*\n";
format_cancel({exit, Reason}) ->
- io_lib:fwrite("*unexpected termination of test process*\n::~P\n\n",
+ io_lib:fwrite("*unexpected termination of test process*\n::~tP\n\n",
[Reason, 15]);
format_cancel({abort, Reason}) ->
eunit_lib:format_error(Reason).
diff --git a/lib/eunit/test/Makefile b/lib/eunit/test/Makefile
index e4ddf4e42c..b0dde64c67 100644
--- a/lib/eunit/test/Makefile
+++ b/lib/eunit/test/Makefile
@@ -20,7 +20,9 @@ include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
MODULES = \
- eunit_SUITE
+ eunit_SUITE \
+ tlatin \
+ tutf8
ERL_FILES= $(MODULES:%=%.erl)
diff --git a/lib/eunit/test/eunit_SUITE.erl b/lib/eunit/test/eunit_SUITE.erl
index d13dc73923..2ac6fafe5d 100644
--- a/lib/eunit/test/eunit_SUITE.erl
+++ b/lib/eunit/test/eunit_SUITE.erl
@@ -1,35 +1,35 @@
%%
%% %CopyrightBegin%
-%%
+%%
%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
-%%
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
-module(eunit_SUITE).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
- app_test/1,appup_test/1,eunit_test/1]).
-
+ app_test/1,appup_test/1,eunit_test/1,surefire_utf8_test/1,surefire_latin_test/1]).
+
-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
-all() ->
- [app_test, appup_test, eunit_test].
+all() ->
+ [app_test, appup_test, eunit_test, surefire_utf8_test, surefire_latin_test].
-groups() ->
+groups() ->
[].
init_per_suite(Config) ->
@@ -54,3 +54,21 @@ eunit_test(Config) when is_list(Config) ->
ok = file:set_cwd(code:lib_dir(eunit)),
ok = eunit:test(eunit).
+surefire_latin_test(Config) when is_list(Config) ->
+ ok = file:set_cwd(proplists:get_value(priv_dir, Config, ".")),
+ check_surefire(tlatin),
+ ok.
+
+surefire_utf8_test(Config) when is_list(Config) ->
+ ok = file:set_cwd(proplists:get_value(priv_dir, Config, ".")),
+ check_surefire(tutf8),
+ ok.
+
+check_surefire(Module) ->
+ File = "TEST-"++atom_to_list(Module)++".xml",
+ file:delete(File),
+ % ignore test result, some fail on purpose
+ eunit:test(Module, [{report,{eunit_surefire,[{dir,"."}]}}]),
+ {ok, Bin} = file:read_file(File),
+ [_|_] = unicode:characters_to_list(Bin, unicode),
+ ok. \ No newline at end of file
diff --git a/lib/eunit/test/tlatin.erl b/lib/eunit/test/tlatin.erl
new file mode 100644
index 0000000000..a42e67d581
--- /dev/null
+++ b/lib/eunit/test/tlatin.erl
@@ -0,0 +1,15 @@
+% coding: latin-1
+
+-module(tlatin).
+
+-include_lib("eunit/include/eunit.hrl").
+
+'foo_�_test_'() ->
+ [
+ {"1�1", fun() -> io:format("1�1 ~s ~w",[<<"a�">>, 'Z�k']), io:format([128,64,255,255]), ?assert("g�"=="g�") end}
+ ,{<<"2�2">>, fun() -> io:format("2�2 ~s",[<<"b�">>]), io:format([128,64]), ?assert("g�"=="g�") end}
+ ,{<<"3�3"/utf8>>, fun() -> io:format("3�3 ~ts",[<<"c�"/utf8>>]), io:format([128,64]), ?assert("g�"=="g�") end}
+ ,{"1�1", fun() -> io:format("1�1 ~s ~w",[<<"a�">>,'Zb�d']), io:format([128,64,255,255]), ?assert("w�"=="w�") end}
+ ,{<<"2�2">>, fun() -> io:format("2�2 ~s",[<<"b�">>]), io:format([128,64]), ?assert("w�"=="w�") end}
+ ,{<<"3�3"/utf8>>, fun() -> io:format("3�3 ~ts",[<<"c�"/utf8>>]), io:format([128,64]), ?assert("w�"=="w�") end}
+ ].
diff --git a/lib/eunit/test/tutf8.erl b/lib/eunit/test/tutf8.erl
new file mode 100644
index 0000000000..c902f3ad18
--- /dev/null
+++ b/lib/eunit/test/tutf8.erl
@@ -0,0 +1,15 @@
+%% coding: utf-8
+
+-module(tutf8).
+
+-include_lib("eunit/include/eunit.hrl").
+
+'foo_ö_test_'() ->
+ [
+ {"1ö汉1", fun() -> io:format("1å汉1 ~s ~w",[<<"aö汉">>, 'Zök']), io:format([128,64,255,255]), ?assert("gö汉"=="gö汉") end}
+ ,{<<"2ö汉2">>, fun() -> io:format("2å汉2 ~s",[<<"bö汉">>]), io:format([128,64]), ?assert("gö汉"=="gö汉") end}
+ ,{<<"3ö汉3"/utf8>>, fun() -> io:format("3å汉3 ~ts",[<<"cö汉"/utf8>>]), io:format([128,64]), ?assert("gö汉"=="gö汉") end}
+ ,{"1ä汉1", fun() -> io:format("1ä汉1 ~s ~w",[<<"aä汉">>, 'Zbäd']), io:format([128,64,255,255]), ?assert("wå汉"=="wä汉") end}
+ ,{<<"2ä汉2">>, fun() -> io:format("2ä汉2 ~s",[<<"bä汉">>]), io:format([128,64]), ?assert("wå汉"=="wä汉") end}
+ ,{<<"3ä汉"/utf8>>, fun() -> io:format("3ä汉3 ~ts",[<<"cä汉"/utf8>>]), io:format([128,64]), ?assert("wå汉"=="wä汉") end}
+ ].
diff --git a/lib/eunit/vsn.mk b/lib/eunit/vsn.mk
index dca8b3ece0..b551ee6eb6 100644
--- a/lib/eunit/vsn.mk
+++ b/lib/eunit/vsn.mk
@@ -1 +1 @@
-EUNIT_VSN = 2.2.9
+EUNIT_VSN = 2.3