Current section

Files

Jump to
yamerl testsuite etest.in
Raw

testsuite/etest.in

#!@ESCRIPT@
% -*-erlang-*-
% vim:ft=erlang:
%-
% Copyright (c) 2012-2014 Yakaz
% Copyright (c) 2016 Jean-Sébastien Pédron <jean-sebastien.pedron@dumbbell.fr>
% All rights reserved.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions
% are met:
% 1. Redistributions of source code must retain the above copyright
% notice, this list of conditions and the following disclaimer.
% 2. Redistributions in binary form must reproduce the above copyright
% notice, this list of conditions and the following disclaimer in the
% documentation and/or other materials provided with the distribution.
%
% THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
% ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
% FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
% DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
% OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
% HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
% LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
% SUCH DAMAGE.
%% @doc
%% When this script is called without arguments, it'll run the EUnit
%% test based on the script name. Our homebrew eunit_tty will not print
%% anything but will indicate if the test was successful or not. The
%% exit code is based on that.
main([]) ->
case filename:basename(escript:script_name()) of
"etest" -> main(usage);
_ -> main([escript:script_name()])
end;
%% @doc
%% A single argument is considered as the test name. See main([]).
main([Test]) ->
code:add_patha(filename:join(["@top_builddir@", "ebin"])),
Test1 = filename:join(
filename:dirname(Test),
filename:basename(Test)),
Ret = run_test(Test1, [@EMKOPTS@]),
stop(Ret);
%% @doc
%% In all other cases, we print the usage.
main(Bad_Args) ->
usage(filename:basename(escript:script_name())),
case Bad_Args of
usage -> stop(ok);
_ -> stop(error)
end.
stop(ok) ->
halt(0);
stop(skipped) ->
halt(77);
stop(error) ->
halt(1);
stop(Other) ->
io:format("Bad return value from eunit_tty: ~p~n", [Other]),
halt(1).
% --------------------------------------------------------------------
% Single test run.
% --------------------------------------------------------------------
%% @spec (Test, Compiler_Options) -> ok | skipped | error
%% Test = string()
%% Compiler_Options = list()
%% @doc Compile and run a single EUnit test.
run_test(Test, Compiler_Options) ->
case load_test(Test, Compiler_Options) of
{error, compile, Errors, Warnings} ->
print_compile_errors(Test, Errors, Warnings),
error;
{error, load, Module, Reason} ->
print_load_error(Test, Module, Reason),
error;
{ok, Module, []} ->
eunit:test([Module], [{report, {eunit_surefire, [{dir,"."}]}}]);
{ok, _Module, Warnings} ->
print_compile_errors(Test, [], Warnings),
error
end.
%% @spec (Test, Compiler_Options) -> Success | Error
%% Test = string()
%% Compiler_Options = list()
%% Success = {ok, Module, Warnings}
%% Module = atom()
%% Error = {error, compile, Errors, Warnings} |
%% {error, load, Module, Reason}
%% Errors = list()
%% Warnings = list()
%% Reason = Term()
%% @doc Compile and load the module from `Test'.
%%
%% Options `binary', `debug_info' and `return' are prepended to
%% `Compiler_Options'.
load_test(Test, Compiler_Options) ->
Default_Options = [
binary,
debug_info,
return,
{i, "@top_srcdir@/include"},
{i, "@top_builddir@/include"}
],
Compiler_Options1 = Compiler_Options --
[report, report_errors, report_warnings],
Options = Default_Options ++ Compiler_Options1,
case compile:file(Test, Options) of
{ok, Module, Binary, Warnings} ->
case code:load_binary(Module, Test, Binary) of
{module, Module} ->
{ok, Module, Warnings};
{error, Reason} ->
{error, load, Module, Reason}
end;
{error, Errors, Warnings} ->
{error, compile, Errors, Warnings}
end.
% --------------------------------------------------------------------
% Error reporting.
% --------------------------------------------------------------------
print_compile_errors(Test, [{File, Error_Infos} | Rest], Warnings) ->
print_error_infos(File, Error_Infos),
print_compile_errors(Test, Rest, Warnings);
print_compile_errors(Test, [], [{File, Warning_Infos} | Rest]) ->
print_warning_infos(File, Warning_Infos),
print_compile_errors(Test, [], Rest);
print_compile_errors(_Test, [], []) ->
ok.
print_error_infos(File, [{Line, IO_Module, Desc} | Rest]) ->
io:format("~s:~p: ~s~n",
[File, Line, IO_Module:format_error(Desc)]),
print_error_infos(File, Rest);
print_error_infos(_File, []) ->
ok.
print_warning_infos(File, [{Line, IO_Module, Desc} | Rest]) ->
io:format("~s:~p: Warning: ~s~n",
[File, Line, IO_Module:format_error(Desc)]),
print_warning_infos(File, Rest);
print_warning_infos(_File, []) ->
ok.
print_load_error(Test, Module, Reason) ->
io:format("Can't load module ~s (~s): ~p~n",
[Module, Test ++ ".erl", Reason]).
% --------------------------------------------------------------------
% Usage.
% --------------------------------------------------------------------
version() ->
io:format("~s testsuite~n", ["@PACKAGE_STRING@"]).
usage(Prog_Name) ->
version(),
io:format(
"~n"
"Usage: ~s <TESTNAME>~n",
[Prog_Name]).