diff options
Diffstat (limited to 'lib/test_server')
-rw-r--r-- | lib/test_server/doc/src/example_chapter.xml | 28 | ||||
-rw-r--r-- | lib/test_server/doc/src/test_server.xml | 66 | ||||
-rw-r--r-- | lib/test_server/include/test_server.hrl | 2 | ||||
-rw-r--r-- | lib/test_server/src/erl2html2.erl | 48 | ||||
-rw-r--r-- | lib/test_server/src/test_server.app.src | 6 | ||||
-rw-r--r-- | lib/test_server/src/test_server.erl | 6 | ||||
-rw-r--r-- | lib/test_server/src/ts.erl | 18 | ||||
-rw-r--r-- | lib/test_server/test/erl2html2_SUITE.erl | 66 | ||||
-rw-r--r-- | lib/test_server/test/erl2html2_SUITE_data/include/header3.hrl | 1 | ||||
-rw-r--r-- | lib/test_server/test/erl2html2_SUITE_data/m1.erl | 6 | ||||
-rw-r--r-- | lib/test_server/vsn.mk | 2 |
11 files changed, 119 insertions, 130 deletions
diff --git a/lib/test_server/doc/src/example_chapter.xml b/lib/test_server/doc/src/example_chapter.xml index 0ebc85da09..6bc0cfaebe 100644 --- a/lib/test_server/doc/src/example_chapter.xml +++ b/lib/test_server/doc/src/example_chapter.xml @@ -47,7 +47,7 @@ -define(default_timeout, ?t:minutes(1)). init_per_testcase(_Case, Config) -> - ?line Dog=?t:timetrap(?default_timeout), + Dog=?t:timetrap(?default_timeout), [{watchdog, Dog}|Config]. end_per_testcase(_Case, Config) -> Dog=?config(watchdog, Config), @@ -72,8 +72,8 @@ not_started_func1(suite) -> not_started_func1(doc) -> ["Testing function 1 when application is not started"]. not_started_func1(Config) when list(Config) -> - ?line {error, not_started} = myapp:func1(dummy_ref,1), - ?line {error, not_started} = myapp:func1(dummy_ref,2), + {error, not_started} = myapp:func1(dummy_ref,1), + {error, not_started} = myapp:func1(dummy_ref,2), ok. not_started_func2(suite) -> @@ -81,8 +81,8 @@ not_started_func2(suite) -> not_started_func2(doc) -> ["Testing function 2 when application is not started"]. not_started_func2(Config) when list(Config) -> - ?line {error, not_started} = myapp:func2(dummy_ref,1), - ?line {error, not_started} = myapp:func2(dummy_ref,2), + {error, not_started} = myapp:func2(dummy_ref,1), + {error, not_started} = myapp:func2(dummy_ref,2), ok. @@ -90,7 +90,7 @@ not_started_func2(Config) when list(Config) -> start(doc) -> ["Testing start of my application."]; start(Config) when list(Config) -> - ?line Ref = myapp:start(), + Ref = myapp:start(), case erlang:whereis(my_main_process) of Pid when pid(Pid) -> [{myapp_ref,Ref}|Config]; @@ -105,9 +105,9 @@ func1(suite) -> func1(doc) -> ["Test that func1 returns ok when argument is 1 and error if argument is 2"]; func1(Config) when list(Config) -> - ?line Ref = ?config(myapp_ref,Config), - ?line ok = myapp:func1(Ref,1), - ?line error = myapp:func1(Ref,2), + Ref = ?config(myapp_ref,Config), + ok = myapp:func1(Ref,1), + error = myapp:func1(Ref,2), ok. func2(suite) -> @@ -115,17 +115,17 @@ func2(suite) -> func2(doc) -> ["Test that func1 returns ok when argument is 3 and error if argument is 4"]; func2(Config) when list(Config) -> - ?line Ref = ?config(myapp_ref,Config), - ?line ok = myapp:func2(Ref,3), - ?line error = myapp:func2(Ref,4), + Ref = ?config(myapp_ref,Config), + ok = myapp:func2(Ref,3), + error = myapp:func2(Ref,4), ok. %% No specification clause needed for a cleanup function in a conf case!!! stop(doc) -> ["Testing termination of my application"]; stop(Config) when list(Config) -> - ?line Ref = ?config(myapp_ref,Config), - ?line ok = myapp:stop(Ref), + Ref = ?config(myapp_ref,Config), + ok = myapp:stop(Ref), case erlang:whereis(my_main_process) of undefined -> lists:keydelete(myapp_ref,1,Config); diff --git a/lib/test_server/doc/src/test_server.xml b/lib/test_server/doc/src/test_server.xml index ed5569e1fe..b98e434c03 100644 --- a/lib/test_server/doc/src/test_server.xml +++ b/lib/test_server/doc/src/test_server.xml @@ -811,46 +811,12 @@ Only valid for peer nodes. Note that slave nodes always </func> </funcs> - <section> - <title>TEST SUITE LINE NUMBERS</title> - <p>If a test case fails, the test server can report the exact line - number at which it failed. There are two ways of doing this, - either by using the <c>line</c> macro or by using the - <c>test_server_line</c> parse transform. - </p> - <p>The <c>line</c> macro is described under TEST SUITE SUPPORT - MACROS below. The <c>line</c> macro will only report the last line - executed when a test case failed. - </p> - <p>The <c>test_server_line</c> parse transform is activated by - including the headerfile <c>test_server_line.hrl</c> in the test - suite. When doing this, it is important that the - <c>test_server_line</c> module is in the code path of the erlang - node compiling the test suite. The parse transform will report a - history of a maximum of 10 lines when a test case - fails. Consecutive lines in the same function are not shown. - </p> - <p>The attribute <c>-no_lines(FuncList).</c> can be used in the - test suite to exclude specific functions from the parse - transform. This is necessary e.g. for functions that are executed - on old (i.e. <R10B) OTP releases. <c>FuncList = [{Func,Arity}]</c>. - </p> - <p>If both the <c>line</c> macro and the parse transform is used in - the same module, the parse transform will overrule the macro. - </p> - </section> <section> <title>TEST SUITE SUPPORT MACROS</title> <p>There are some macros defined in the <c>test_server.hrl</c> that are quite useful for test suite programmers: </p> - <p>The <em>line</em> macro, is quite - essential when writing test cases. It tells the test server - exactly what line of code that is being executed, so that it can - report this line back if the test case fails. Use this macro at - the beginning of every test case line of code. - </p> <p>The <em>config</em> macro, is used to retrieve information from the <c>Config</c> variable sent to all test cases. It is used with two arguments, where the first is the @@ -867,24 +833,20 @@ Only valid for peer nodes. Note that slave nodes always <item>Whatever added by conf test cases or <c>init_per_testcase/2</c></item> </list> - <p>Examples of the <c>line</c> and <c>config</c> macros can be - seen in the Examples chapter in the user's guide. - </p> - <p>If the <c>line_trace</c> macro is defined, you will get a - timestamp (<c>erlang:now()</c>) in your minor log for each - <c>line</c> macro in your suite. This way you can at any time see - which line is currently being executed, and when the line was - called. - </p> - <p>The <c>line_trace</c> macro can also be used together with the - <c>test_server_line</c> parse transform described above. A - timestamp will then be written for each line in the suite, except - for functions stated in the <c>-no_lines</c> attribute. - </p> - <p>The <c>line_trace</c> macro can e.g. be defined as a compile - option, like this: - <br></br> -<c>erlc -W -Dline_trace my_SUITE.erl</c></p> + <p>Examples of the <c>config</c> macro can be seen in the Examples chapter + in the user's guide.</p> + <p>The <em>line</em> and <em>line_trace</em> macros are deprecated, see + below.</p> + </section> + + <section> + <title>TEST SUITE LINE NUMBERS</title> + <p>In the past, ERTS did not produce line numbers when generating + stacktraces, test_server was thus unable to provide them when reporting + test failures. It had instead two different mecanisms to do it: either by + using the <c>line</c> macro or by using the <c>test_server_line</c> parse + transform. Both are deprecated and should not be used in new tests + anymore.</p> </section> </erlref> diff --git a/lib/test_server/include/test_server.hrl b/lib/test_server/include/test_server.hrl index 36e7e1f83d..f206374116 100644 --- a/lib/test_server/include/test_server.hrl +++ b/lib/test_server/include/test_server.hrl @@ -21,7 +21,7 @@ -line_trace(true). -define(line, io:format(lists:concat([?MODULE,",",integer_to_list(?LINE),": ~p"]), - [erlang:now()]),). + [erlang:monotonic_time()-erlang:system_info(start_time)]),). -else. -define(line,). -endif. diff --git a/lib/test_server/src/erl2html2.erl b/lib/test_server/src/erl2html2.erl index 2e443c7b8b..b0b5c40965 100644 --- a/lib/test_server/src/erl2html2.erl +++ b/lib/test_server/src/erl2html2.erl @@ -109,27 +109,26 @@ parse_file(File, InclPath) -> Error end. -parse_preprocessed_file(Epp,File,InCorrectFile) -> +parse_preprocessed_file(Epp, File, InCorrectFile) -> case epp:parse_erl_form(Epp) of {ok,Form} -> case Form of {attribute,_,file,{File,_}} -> - parse_preprocessed_file(Epp,File,true); + parse_preprocessed_file(Epp, File, true); {attribute,_,file,{_OtherFile,_}} -> - parse_preprocessed_file(Epp,File,false); + parse_preprocessed_file(Epp, File, false); {function,L,F,A,Cs} when InCorrectFile -> {CLs,LastCL} = find_clause_lines(Cs, []), - Clauses = [{clause,get_line(CL)} || - {clause,CL,_,_,_} <- tl(CLs)], - [{atom_to_list(F),A,get_line(L),get_line(LastCL)} | Clauses] ++ - parse_preprocessed_file(Epp,File,true); + %% tl(CLs) cause we know the start line already + [{atom_to_list(F),A,get_line(L),LastCL} | tl(CLs)] ++ + parse_preprocessed_file(Epp, File, true); _ -> - parse_preprocessed_file(Epp,File,InCorrectFile) + parse_preprocessed_file(Epp, File, InCorrectFile) end; {error,Reason={_L,epp,{undefined,_Macro,none}}} -> throw({error,Reason,InCorrectFile}); {error,_Reason} -> - parse_preprocessed_file(Epp,File,InCorrectFile); + parse_preprocessed_file(Epp, File, InCorrectFile); {eof,_Location} -> [] end. @@ -150,9 +149,8 @@ parse_non_preprocessed_file(Epp, File, Location) -> try erl_syntax:revert(Tree) of {function,L,F,A,Cs} -> {CLs,LastCL} = find_clause_lines(Cs, []), - Clauses = [{clause,get_line(CL)} || - {clause,CL,_,_,_} <- tl(CLs)], - [{atom_to_list(F),A,get_line(L),get_line(LastCL)} | Clauses] ++ + %% tl(CLs) cause we know the start line already + [{atom_to_list(F),A,get_line(L),LastCL} | tl(CLs)] ++ parse_non_preprocessed_file(Epp, File, Location1); _ -> parse_non_preprocessed_file(Epp, File, Location1) @@ -172,17 +170,21 @@ get_line(Anno) -> %%% Find the line number of the last expression in the function find_clause_lines([{clause,CL,_Params,_Op,Exprs}], CLs) -> % last clause try tuple_to_list(lists:last(Exprs)) of - [_Type,ExprLine | _] -> - {lists:reverse([{clause,CL}|CLs]), ExprLine}; + [_Type,ExprLine | _] when is_integer(ExprLine) -> + {lists:reverse([{clause,get_line(CL)}|CLs]), get_line(ExprLine)}; + [tree,_ | Exprs1] -> + find_clause_lines([{clause,CL,undefined,undefined,Exprs1}], CLs); + [macro,{_var,ExprLine,_MACRO} | _] when is_integer(ExprLine) -> + {lists:reverse([{clause,get_line(CL)}|CLs]), get_line(ExprLine)}; _ -> - {lists:reverse([{clause,CL}|CLs]), CL} + {lists:reverse([{clause,get_line(CL)}|CLs]), get_line(CL)} catch _:_ -> - {lists:reverse([{clause,CL}|CLs]), CL} + {lists:reverse([{clause,get_line(CL)}|CLs]), get_line(CL)} end; find_clause_lines([{clause,CL,_Params,_Op,_Exprs} | Cs], CLs) -> - find_clause_lines(Cs, [{clause,CL}|CLs]). + find_clause_lines(Cs, [{clause,get_line(CL)}|CLs]). %%%----------------------------------------------------------------- %%% Add a link target for each line and one for each function definition. @@ -190,18 +192,18 @@ build_html(SFd,DFd,Encoding,FuncsAndCs) -> build_html(SFd,DFd,Encoding,file:read_line(SFd),1,FuncsAndCs, false,undefined). -%% function start line found -build_html(SFd,DFd,Enc,{ok,Str},L0,[{F,A,L0,LastL}|FuncsAndCs], - _IsFuncDef,_FAndLastL) -> - FALink = test_server_ctrl:uri_encode(F++"-"++integer_to_list(A),utf8), - file:write(DFd,["<a name=\"",to_raw_list(FALink,Enc),"\"/>"]), - build_html(SFd,DFd,Enc,{ok,Str},L0,FuncsAndCs,true,{F,LastL}); %% line of last expression in function found build_html(SFd,DFd,Enc,{ok,Str},LastL,FuncsAndCs,_IsFuncDef,{F,LastL}) -> LastLineLink = test_server_ctrl:uri_encode(F++"-last_expr",utf8), file:write(DFd,["<a name=\"", to_raw_list(LastLineLink,Enc),"\"/>"]), build_html(SFd,DFd,Enc,{ok,Str},LastL,FuncsAndCs,true,undefined); +%% function start line found +build_html(SFd,DFd,Enc,{ok,Str},L0,[{F,A,L0,LastL}|FuncsAndCs], + _IsFuncDef,_FAndLastL) -> + FALink = test_server_ctrl:uri_encode(F++"-"++integer_to_list(A),utf8), + file:write(DFd,["<a name=\"",to_raw_list(FALink,Enc),"\"/>"]), + build_html(SFd,DFd,Enc,{ok,Str},L0,FuncsAndCs,true,{F,LastL}); build_html(SFd,DFd,Enc,{ok,Str},L,[{clause,L}|FuncsAndCs], _IsFuncDef,FAndLastL) -> build_html(SFd,DFd,Enc,{ok,Str},L,FuncsAndCs,true,FAndLastL); diff --git a/lib/test_server/src/test_server.app.src b/lib/test_server/src/test_server.app.src index 5538e8b851..bdd9d28444 100644 --- a/lib/test_server/src/test_server.app.src +++ b/lib/test_server/src/test_server.app.src @@ -32,7 +32,7 @@ test_server_break_process]}, {applications, [kernel,stdlib]}, {env, []}, - {runtime_dependencies, ["tools-2.6.14","stdlib-2.0","runtime_tools-1.8.14", - "observer-2.0","kernel-3.0","inets-5.10", - "syntax_tools-1.6.16","erts-7.0"]}]}. + {runtime_dependencies, ["tools-2.8","stdlib-2.5","runtime_tools-1.8.16", + "observer-2.1","kernel-4.0","inets-6.0", + "syntax_tools-1.7","erts-7.0"]}]}. diff --git a/lib/test_server/src/test_server.erl b/lib/test_server/src/test_server.erl index 7cb9c4bb5a..785e687b92 100644 --- a/lib/test_server/src/test_server.erl +++ b/lib/test_server/src/test_server.erl @@ -2491,11 +2491,7 @@ appup_test(App) -> %% Checks wether the module is natively compiled or not. is_native(Mod) -> - case catch Mod:module_info(native_addresses) of - [_|_] -> true; - _Other -> false - end. - + (catch Mod:module_info(native)) =:= true. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% comment(String) -> ok diff --git a/lib/test_server/src/ts.erl b/lib/test_server/src/ts.erl index 469593e947..85f97656ff 100644 --- a/lib/test_server/src/ts.erl +++ b/lib/test_server/src/ts.erl @@ -262,18 +262,28 @@ run_all(_Vars) -> run_some([], _Opts) -> ok; -run_some([{App,Mod}|Apps], Opts) -> +run_some(Apps, Opts) -> + case proplists:get_value(test_category, Opts) of + bench -> + check_and_run(fun(Vars) -> ts_benchmark:run(Apps, Opts, Vars) end); + _Other -> + run_some1(Apps, Opts) + end. + +run_some1([], _Opts) -> + ok; +run_some1([{App,Mod}|Apps], Opts) -> case run(App, Mod, Opts) of ok -> ok; Error -> io:format("~p: ~p~n",[{App,Mod},Error]) end, - run_some(Apps, Opts); -run_some([App|Apps], Opts) -> + run_some1(Apps, Opts); +run_some1([App|Apps], Opts) -> case run(App, Opts) of ok -> ok; Error -> io:format("~p: ~p~n",[App,Error]) end, - run_some(Apps, Opts). + run_some1(Apps, Opts). %% This can be used from command line. Both App and %% TestCategory must be specified. App may be 'all' diff --git a/lib/test_server/test/erl2html2_SUITE.erl b/lib/test_server/test/erl2html2_SUITE.erl index 908985c879..796b84dedd 100644 --- a/lib/test_server/test/erl2html2_SUITE.erl +++ b/lib/test_server/test/erl2html2_SUITE.erl @@ -130,15 +130,7 @@ groups() -> %% @end %%-------------------------------------------------------------------- all() -> - [m1]. - -%%-------------------------------------------------------------------- -%% @spec TestCase() -> Info -%% Info = [tuple()] -%% @end -%%-------------------------------------------------------------------- -m1() -> - []. + [macros_defined, macros_undefined]. %%-------------------------------------------------------------------- %% @spec TestCase(Config0) -> @@ -149,19 +141,29 @@ m1() -> %% Comment = term() %% @end %%-------------------------------------------------------------------- -m1(Config) -> - {Src,Dst} = convert_module("m1",Config), +macros_defined(Config) -> + %% let erl2html2 use epp as parser + DataDir = ?config(data_dir,Config), + InclDir = filename:join(DataDir, "include"), + {Src,Dst} = convert_module("m1",[InclDir],Config), {true,L} = check_line_numbers(Src,Dst), - ok = check_link_targets(Src,Dst,L,[{baz,0}]), + ok = check_link_targets(Src,Dst,L,[{baz,0}],[]), ok. -convert_module(Mod,Config) -> +macros_undefined(Config) -> + %% let erl2html2 use epp_dodger as parser + {Src,Dst} = convert_module("m1",[],Config), + {true,L} = check_line_numbers(Src,Dst), + ok = check_link_targets(Src,Dst,L,[{baz,0}],[{quux,0}]), + ok. + +convert_module(Mod,InclDirs,Config) -> DataDir = ?config(data_dir,Config), PrivDir = ?config(priv_dir,Config), Src = filename:join(DataDir,Mod++".erl"), Dst = filename:join(PrivDir,Mod++".erl.html"), io:format("<a href=\"~s\">~s</a>\n",[Src,filename:basename(Src)]), - ok = erl2html2:convert(Src, Dst, [], "<html><body>"), + ok = erl2html2:convert(Src, Dst, InclDirs, "<html><body>"), io:format("<a href=\"~s\">~s</a>\n",[Dst,filename:basename(Dst)]), {Src,Dst}. @@ -229,36 +231,46 @@ check_line_number(Last,Line,OrigLine) -> %% function. %% The test module has -compile(export_all), so all functions are %% found by listing the exported ones. -check_link_targets(Src,Dst,L,RmFncs) -> +check_link_targets(Src,Dst,L,RmFncs,ShouldRemain) -> Mod = list_to_atom(filename:basename(filename:rootname(Src))), Exports = Mod:module_info(exports)--[{module_info,0},{module_info,1}|RmFncs], - {ok,{[],L},_} = xmerl_sax_parser:file(Dst, - [{event_fun,fun sax_event/3}, - {event_state,{Exports,0}}]), + LastExprFuncs = [Func || {Func,_A} <- Exports], + {ok,{FAs,Fs,L},_} = + xmerl_sax_parser:file(Dst, + [{event_fun,fun sax_event/3}, + {event_state,{Exports,LastExprFuncs,0}}]), + true = (length(FAs) == length(ShouldRemain)), + [] = [FA || FA <- FAs, not lists:member(FA,ShouldRemain)], + [] = [F || F <- Fs, not lists:keymember(F,1,ShouldRemain)], ok. sax_event(Event,_Loc,State) -> sax_event(Event,State). -sax_event({startElement,_Uri,"a",_QN,Attrs},{Exports,PrevLine}) -> +sax_event({startElement,_Uri,"a",_QN,Attrs},{Exports,LastExprFuncs,PrevLine}) -> {_,_,"name",Name} = lists:keyfind("name",3,Attrs), case catch list_to_integer(Name) of Line when is_integer(Line) -> case PrevLine + 1 of Line -> -% erlang:display({found_line,Line}), - {Exports,Line}; + {Exports,LastExprFuncs,Line}; Other -> ct:fail({unexpected_line_number_target,Other}) end; {'EXIT',_} -> - {match,[FStr,AStr]} = - re:run(Name,"^(.*)-([0-9]+)$",[{capture,all_but_first,list}]), + {match,[FStr,EndStr]} = + re:run(Name,"^(.*)-(last_expr|[0-9]+)$", + [{capture,all_but_first,list}]), F = list_to_atom(http_uri:decode(FStr)), - A = list_to_integer(AStr), -% erlang:display({found_fnc,F,A}), - A = proplists:get_value(F,Exports), - {lists:delete({F,A},Exports),PrevLine} + case EndStr of + "last_expr" -> + true = lists:member(F,LastExprFuncs), + {Exports,lists:delete(F,LastExprFuncs),PrevLine}; + _ -> + A = list_to_integer(EndStr), + A = proplists:get_value(F,Exports), + {lists:delete({F,A},Exports),LastExprFuncs,PrevLine} + end end; sax_event(_,State) -> State. diff --git a/lib/test_server/test/erl2html2_SUITE_data/include/header3.hrl b/lib/test_server/test/erl2html2_SUITE_data/include/header3.hrl new file mode 100644 index 0000000000..2a20850a3a --- /dev/null +++ b/lib/test_server/test/erl2html2_SUITE_data/include/header3.hrl @@ -0,0 +1 @@ +-define(EPP_SWITCH, on). diff --git a/lib/test_server/test/erl2html2_SUITE_data/m1.erl b/lib/test_server/test/erl2html2_SUITE_data/m1.erl index 156f1d0a51..1d405963a5 100644 --- a/lib/test_server/test/erl2html2_SUITE_data/m1.erl +++ b/lib/test_server/test/erl2html2_SUITE_data/m1.erl @@ -7,9 +7,15 @@ -include("header1.hrl"). -include("header2.hrl"). +-include("header3.hrl"). -define(MACRO1,value). +%% This macro is used to select parser in erl2html2. +%% If EPP_SWITCH is defined epp is used, else epp_dodger. +epp_switch() -> + ?EPP_SWITCH. + %%% Comment foo(x) -> %% Comment diff --git a/lib/test_server/vsn.mk b/lib/test_server/vsn.mk index 2a2ed2b3b0..fd9e4e6d74 100644 --- a/lib/test_server/vsn.mk +++ b/lib/test_server/vsn.mk @@ -1 +1 @@ -TEST_SERVER_VSN = 3.8.1 +TEST_SERVER_VSN = 3.9 |