diff options
Diffstat (limited to 'lib/test_server')
-rw-r--r-- | lib/test_server/src/erl2html2.erl | 247 | ||||
-rw-r--r-- | lib/test_server/src/test_server_ctrl.erl | 2 | ||||
-rw-r--r-- | lib/test_server/src/test_server_io.erl | 6 | ||||
-rw-r--r-- | lib/test_server/src/test_server_sup.erl | 7 | ||||
-rw-r--r-- | lib/test_server/src/ts.erl | 52 | ||||
-rw-r--r-- | lib/test_server/test/Makefile | 3 | ||||
-rw-r--r-- | lib/test_server/test/erl2html2_SUITE.erl | 254 | ||||
-rw-r--r-- | lib/test_server/test/erl2html2_SUITE_data/Makefile.src | 2 | ||||
-rw-r--r-- | lib/test_server/test/erl2html2_SUITE_data/header1.hrl | 4 | ||||
-rw-r--r-- | lib/test_server/test/erl2html2_SUITE_data/include/header2.hrl | 0 | ||||
-rw-r--r-- | lib/test_server/test/erl2html2_SUITE_data/m1.erl | 46 |
11 files changed, 473 insertions, 150 deletions
diff --git a/lib/test_server/src/erl2html2.erl b/lib/test_server/src/erl2html2.erl index 6891e87e48..9c459c05d4 100644 --- a/lib/test_server/src/erl2html2.erl +++ b/lib/test_server/src/erl2html2.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2011. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. 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 @@ -18,19 +18,9 @@ %% %%%------------------------------------------------------------------ -%%% Purpose:Convert Erlang files to html. (Pretty faaast... :-) +%%% Purpose:Convert Erlang files to html. %%%------------------------------------------------------------------ -%-------------------------------------------------------------------- -% Some stats (Sparc5@110Mhz): -% 4109 lines (erl_parse.erl): 3.00 secs -% 1847 lines (application_controller.erl): 0.57 secs -% 3160 lines (test_server.erl): 1.00 secs -% 1199 lines (ts_estone.erl): 0.35 secs -% -% Avg: ~4.5e-4s/line, or ~0.45s/1000 lines, or ~2200 lines/sec. -%-------------------------------------------------------------------- - -module(erl2html2). -export([convert/2, convert/3]). @@ -52,134 +42,141 @@ convert(File, Dest) -> "<body bgcolor=\"white\" text=\"black\"" " link=\"blue\" vlink=\"purple\" alink=\"red\">\n"], convert(File, Dest, Header). - + + convert(File, Dest, Header) -> - case file:read_file(File) of - {ok, Bin} -> - Code=binary_to_list(Bin), - statistics(runtime), - {Html1, Lines} = root(Code, [], 1), - Html = [Header, - "<pre>\n", Html1, "</pre>\n", - footer(Lines),"</body>\n</html>\n"], - file:write_file(Dest, Html); - {error, Reason} -> - {error, Reason} + %% statistics(runtime), + case parse_file(File) of + {ok,Functions} -> + %% {_, Time1} = statistics(runtime), + %% io:format("Parsed file in ~.2f Seconds.~n",[Time1/1000]), + case file:open(File,[raw,{read_ahead,10000}]) of + {ok,SFd} -> + case file:open(Dest,[write,raw]) of + {ok,DFd} -> + file:write(DFd,[Header,"<pre>\n"]), + Lines = build_html(SFd,DFd,Functions), + file:write(DFd,["</pre>\n",footer(), + "</body>\n</html>\n"]), + %% {_, Time2} = statistics(runtime), + %% io:format("Converted ~p lines in ~.2f Seconds.~n", + %% [Lines, Time2/1000]), + file:close(SFd), + file:close(DFd), + ok; + Error -> + Error + end; + Error -> + Error + end; + Error -> + Error end. -root([], Res, Line) -> - {Res, Line}; -root([Char0|Code], Res, Line0) -> - Char = [Char0], - case Char of - "-" -> - {Match, Line1, NewCode0, AttName} = - read_to_char(Line0+1, Code, [], [$(, $.]), - {_, Line2, NewCode, Stuff} = read_to_char(Line1, NewCode0, [], $\n), - NewRes = [Res,linenum(Line0),"-<b>",AttName, - "</b>",Match, Stuff, "\n"], - root(NewCode, NewRes, Line2); - "%" -> - {_, Line, NewCode, Stuff} = read_to_char(Line0+1, Code, [], $\n), - NewRes = [Res,linenum(Line0),"<i>%",Stuff,"</i>\n"], - root(NewCode, NewRes, Line); - "\n" -> - root(Code, [Res,linenum(Line0), "\n"], Line0+1); - " " -> - {_, Line, NewCode, Stuff} = read_to_char(Line0+1, Code, [], $\n), - root(NewCode, [Res,linenum(Line0)," ",Stuff, "\n"], - Line); - "\t" -> - {_, Line, NewCode, Stuff} = read_to_char(Line0+1, Code, [], $\n), - root(NewCode, [Res,linenum(Line0),"\t",Stuff, "\n"], - Line); - [Chr|_] when Chr>96, Chr<123 -> - %% Assumed to be function/clause start. - %% FIXME: This will trivially generate non-unique anchors - %% (one for each clause) --- which is illegal HTML. - {_, Line1, NewCode0, FName0} = read_to_char(Line0+1, Code, [], $(), - {_, Line2, NewCode, Stuff} = - read_to_char(Line1,NewCode0, [], $\n), - FuncName = [[Chr],FName0], - NewRes=[Res,"<a name=",FuncName,">", - linenum(Line0),"<b>",FuncName,"</b></a>", - "(",Stuff, "\n"], - root(NewCode, NewRes, Line2); - Chr -> - {_, Line, NewCode, Stuff} = read_to_char(Line0+1, Code, [], $\n), - root(NewCode, [Res,linenum(Line0),Chr,Stuff, "\n"], - Line) +%%%----------------------------------------------------------------- +%%% Parse the input file to get the line numbers for all function +%%% definitions. This will be used when creating link targets for each +%%% function in build_html/5. +%%% +%%% All function clauses are also marked in order to allow +%%% possibly_enhance/2 to write these in bold. +parse_file(File) -> + case epp:open(File, [], []) of + {ok,Epp} -> + Forms = parse_file(Epp,File,false), + epp:close(Epp), + {ok,Forms}; + {error,E} -> + {error,E} end. -read_to_char(Line0, [], Res, _Chr) -> - {nomatch, Line0, [], Res}; -read_to_char(Line0, [Char|Code], Res, Chr) -> - case Char of - Chr -> {Char, Line0, Code, Res}; - _ when is_list(Chr) -> - case lists:member(Char,Chr) of - true -> - {Char, Line0, Code, Res}; - false -> - {Line,NewCode,NewRes} = maybe_convert(Line0,Code,Res,Char), - read_to_char(Line, NewCode, NewRes, Chr) + +parse_file(Epp,File,InCorrectFile) -> + case epp:parse_erl_form(Epp) of + {ok,Form} -> + case Form of + {attribute,_,file,{File,_}} -> + parse_file(Epp,File,true); + {attribute,_,file,{_OtherFile,_}} -> + parse_file(Epp,File,false); + {function,L,F,A,[_|C]} when InCorrectFile -> + Clauses = [{clause,CL} || {clause,CL,_,_,_} <- C], + [{atom_to_list(F),A,L} | Clauses] ++ + parse_file(Epp,File,true); + _ -> + parse_file(Epp,File,InCorrectFile) end; - _ -> - {Line,NewCode,NewRes} = maybe_convert(Line0,Code,Res,Char), - read_to_char(Line,NewCode, NewRes, Chr) + {error,_E} -> + parse_file(Epp,File,InCorrectFile); + {eof,_Location} -> + [] end. -maybe_convert(Line0,Code,Res,Chr) -> - case Chr of - %% Quoted stuff should not have the highlighting like normal code - %% FIXME: unbalanced quotes (e.g. in comments) will cause trouble with - %% highlighting and line numbering in the rest of the module. - $" -> - {_, Line1, NewCode, Stuff0} = read_to_char(Line0, Code, [], $"), - {Line2,Stuff} = add_linenumbers(Line1,lists:flatten(Stuff0),[]), - {Line2,NewCode,[Res,$",Stuff,$"]}; - %% These chars have meaning in HTML, and *must* *not* be - %% written as themselves. - $& -> - {Line0, Code, [Res,"&"]}; - $< -> - {Line0, Code, [Res,"<"]}; - $> -> - {Line0, Code, [Res,">"]}; - %% Everything else is simply copied. - OtherChr -> - {Line0, Code, [Res,OtherChr]} - end. +%%%----------------------------------------------------------------- +%%% Add a link target for each line and one for each function definition. +build_html(SFd,DFd,Functions) -> + build_html(SFd,DFd,file:read_line(SFd),1,Functions,false). -add_linenumbers(Line,[Chr|Chrs],Res) -> - case Chr of - $\n -> add_linenumbers(Line+1,Chrs,[Res,$\n,linenum(Line)]); - _ -> add_linenumbers(Line,Chrs,[Res,Chr]) - end; -add_linenumbers(Line,[],Res) -> - {Line,Res}. +build_html(SFd,DFd,{ok,Str},L,[{F,A,L}|Functions],_IsFuncDef) -> + FALink = http_uri:encode(F++"-"++integer_to_list(A)), + file:write(DFd,["<a name=\"",FALink,"\"/>"]), + build_html(SFd,DFd,{ok,Str},L,Functions,true); +build_html(SFd,DFd,{ok,Str},L,[{clause,L}|Functions],_IsFuncDef) -> + build_html(SFd,DFd,{ok,Str},L,Functions,true); +build_html(SFd,DFd,{ok,Str},L,Functions,IsFuncDef) -> + LStr = line_number(L), + Str1 = line(Str,IsFuncDef), + file:write(DFd,[LStr,Str1]), + build_html(SFd,DFd,file:read_line(SFd),L+1,Functions,false); +build_html(_SFd,_DFd,eof,L,_Functions,_IsFuncDef) -> + L. -%% Make nicely indented line numbers. -linenum(Line) -> - Num = integer_to_list(Line), - A = case Line rem 10 of - 0 -> "<a name=\"" ++ Num ++"\"></a>"; - _ -> [] - end, +line_number(L) -> + LStr = integer_to_list(L), Pred = - case length(Num) of + case length(LStr) of Length when Length < 5 -> lists:duplicate(5-Length,$\s); _ -> [] end, - [A,Pred,integer_to_list(Line),":"]. + ["<a name=\"",LStr,"\"/>",Pred,LStr,": "]. + +line(Str,IsFuncDef) -> + Str1 = htmlize(Str), + possibly_enhance(Str1,IsFuncDef). + +%%%----------------------------------------------------------------- +%%% Substitute special characters that should not appear in HTML +htmlize([$<|Str]) -> + [$&,$l,$t,$;|htmlize(Str)]; +htmlize([$>|Str]) -> + [$&,$g,$t,$;|htmlize(Str)]; +htmlize([$&|Str]) -> + [$&,$a,$m,$p,$;|htmlize(Str)]; +htmlize([$"|Str]) -> + [$&,$q,$u,$o,$t,$;|htmlize(Str)]; +htmlize([Ch|Str]) -> + [Ch|htmlize(Str)]; +htmlize([]) -> + []. + +%%%----------------------------------------------------------------- +%%% Write comments in italic and function definitions in bold. +possibly_enhance(Str,true) -> + case lists:splitwith(fun($() -> false; (_) -> true end, Str) of + {_,[]} -> Str; + {F,A} -> ["<b>",F,"</b>",A] + end; +possibly_enhance([$%|_]=Str,_) -> + ["<i>",Str--"\n","</i>","\n"]; +possibly_enhance([$-|_]=Str,_) -> + possibly_enhance(Str,true); +possibly_enhance(Str,false) -> + Str. -footer(_Lines) -> +%%%----------------------------------------------------------------- +%%% End of the file +footer() -> "". -%% {_, Time} = statistics(runtime), -%% io:format("Converted ~p lines in ~.2f Seconds.~n", -%% [Lines, Time/1000]), -%% S = "<i>The transformation of this file (~p lines) took ~.2f seconds</i>", -%% F = lists:flatten(io_lib:format(S, [Lines, Time/1000])), -%% ["<hr size=1>",F,"<br>\n"]. diff --git a/lib/test_server/src/test_server_ctrl.erl b/lib/test_server/src/test_server_ctrl.erl index 7b2ebcefc0..bc08c12089 100644 --- a/lib/test_server/src/test_server_ctrl.erl +++ b/lib/test_server/src/test_server_ctrl.erl @@ -1796,7 +1796,7 @@ start_minor_log_file1(Mod, Func, LogDir, AbsName, MFA) -> lists:member(no_src, get(test_server_logopts))} of {true,false} -> print(Lev, "<a href=\"~s#~s\">source code for ~p:~p/1</a>\n", - [SrcListing,Func,Mod,Func]); + [SrcListing,atom_to_list(Func)++"-1",Mod,Func]); _ -> ok end, diff --git a/lib/test_server/src/test_server_io.erl b/lib/test_server/src/test_server_io.erl index e960b3087a..777b377201 100644 --- a/lib/test_server/src/test_server_io.erl +++ b/lib/test_server/src/test_server_io.erl @@ -307,8 +307,10 @@ do_print_buffered(Q0, St) -> gc(#st{gls=Gls0}) -> InUse0 = [begin - {group_leader,GL} = process_info(P, group_leader), - GL + case process_info(P, group_leader) of + {group_leader,GL} -> GL; + undefined -> undefined + end end || P <- processes()], InUse = ordsets:from_list(InUse0), Gls = gb_sets:to_list(Gls0), diff --git a/lib/test_server/src/test_server_sup.erl b/lib/test_server/src/test_server_sup.erl index ba5bb9f5d2..c7553cccb5 100644 --- a/lib/test_server/src/test_server_sup.erl +++ b/lib/test_server/src/test_server_sup.erl @@ -568,16 +568,11 @@ format_loc1({Mod,Func,Line}) -> {false,[$E,$T,$I,$U,$S,$_|_]} -> io_lib:format("{~s,~w,<a href=\"~s~s#~w\">~w</a>}", [ModStr,Func,downcase(ModStr),?src_listing_ext, - round_to_10(Line),Line]); + Line,Line]); _ -> io_lib:format("{~s,~w,~w}",[ModStr,Func,Line]) end. -round_to_10(N) when (N rem 10) == 0 -> - N; -round_to_10(N) -> - trunc(N/10)*10. - downcase(S) -> downcase(S, []). downcase([Uc|Rest], Result) when $A =< Uc, Uc =< $Z -> downcase(Rest, [Uc-$A+$a|Result]); diff --git a/lib/test_server/src/ts.erl b/lib/test_server/src/ts.erl index 3ddc58fdbc..115e783070 100644 --- a/lib/test_server/src/ts.erl +++ b/lib/test_server/src/ts.erl @@ -259,21 +259,43 @@ run(List, Opts) when is_list(List), is_list(Opts) -> run(Testspec, Config) when is_atom(Testspec), is_list(Config) -> Options=check_test_get_opts(Testspec, Config), File=atom_to_list(Testspec), - Spec = case code:lib_dir(Testspec) of - _ when Testspec == emulator; - Testspec == system; - Testspec == epmd -> - File++".spec"; - {error, bad_name} -> - create_skip_spec(Testspec, tests(Testspec)); - Path -> - case file:read_file_info(filename:join(Path,"ebin")) of - {ok,_} -> - File++".spec"; - _ -> - create_skip_spec(Testspec, tests(Testspec)) - end - end, + WhatToDo = + case Testspec of + %% Known to exist but fails generic tests below + emulator -> test; + system -> test; + erl_interface -> test; + epmd -> test; + _ -> + case code:lib_dir(Testspec) of + {error,bad_name} -> + %% Application does not exist + skip; + Path -> + case file:read_file_info(filename:join(Path,"ebin")) of + {ok,#file_info{type=directory}} -> + %% Erlang application is built + test; + _ -> + case filelib:wildcard( + filename:join([Path,"priv","*.jar"])) of + [] -> + %% The application is not built + skip; + [_|_] -> + %% Java application is built + test + end + end + end + end, + Spec = + case WhatToDo of + skip -> + create_skip_spec(Testspec, tests(Testspec)); + test -> + File++".spec" + end, run_test(File, [{spec,[Spec]}], Options); %% Runs one module in a spec (interactive) run(Testspec, Mod) when is_atom(Testspec), is_atom(Mod) -> diff --git a/lib/test_server/test/Makefile b/lib/test_server/test/Makefile index a3f9820d7f..afccc28662 100644 --- a/lib/test_server/test/Makefile +++ b/lib/test_server/test/Makefile @@ -26,7 +26,8 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk MODULES= \ test_server_SUITE \ - test_server_test_lib + test_server_test_lib \ + erl2html2_SUITE ERL_FILES= $(MODULES:%=%.erl) diff --git a/lib/test_server/test/erl2html2_SUITE.erl b/lib/test_server/test/erl2html2_SUITE.erl new file mode 100644 index 0000000000..96175413a1 --- /dev/null +++ b/lib/test_server/test/erl2html2_SUITE.erl @@ -0,0 +1,254 @@ +%%%------------------------------------------------------------------- +%%% @author Siri Hansen <[email protected]> +%%% @copyright (C) 2012, Siri Hansen +%%% @doc +%%% +%%% @end +%%% Created : 15 Nov 2012 by Siri Hansen <[email protected]> +%%%------------------------------------------------------------------- +-module(erl2html2_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). + + +-define(HEADER, + ["<!DOCTYPE HTML PUBLIC", + "\"-//W3C//DTD HTML 3.2 Final//EN\">\n", + "<!-- autogenerated by 'erl2html2' -->\n", + "<html>\n", + "<head><title>Module ", Src, "</title>\n", + "<meta http-equiv=\"cache-control\" ", + "content=\"no-cache\">\n", + "</head>\n", + "<body bgcolor=\"white\" text=\"black\" ", + "link=\"blue\" vlink=\"purple\" alink=\"red\">\n"]). + +%%-------------------------------------------------------------------- +%% @spec suite() -> Info +%% Info = [tuple()] +%% @end +%%-------------------------------------------------------------------- +suite() -> + [{timetrap,{seconds,30}}, + {ct_hooks,[ts_install_cth,test_server_test_lib]}]. + +%%-------------------------------------------------------------------- +%% @spec init_per_suite(Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%% @end +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + Config. + +%%-------------------------------------------------------------------- +%% @spec end_per_suite(Config0) -> void() | {save_config,Config1} +%% Config0 = Config1 = [tuple()] +%% @end +%%-------------------------------------------------------------------- +end_per_suite(_Config) -> + ok. + +%%-------------------------------------------------------------------- +%% @spec init_per_group(GroupName, Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% GroupName = atom() +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%% @end +%%-------------------------------------------------------------------- +init_per_group(_GroupName, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% @spec end_per_group(GroupName, Config0) -> +%% void() | {save_config,Config1} +%% GroupName = atom() +%% Config0 = Config1 = [tuple()] +%% @end +%%-------------------------------------------------------------------- +end_per_group(_GroupName, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% @spec init_per_testcase(TestCase, Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% TestCase = atom() +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%% @end +%%-------------------------------------------------------------------- +init_per_testcase(_TestCase, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% @spec end_per_testcase(TestCase, Config0) -> +%% void() | {save_config,Config1} | {fail,Reason} +%% TestCase = atom() +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%% @end +%%-------------------------------------------------------------------- +end_per_testcase(_TestCase, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% @spec groups() -> [Group] +%% Group = {GroupName,Properties,GroupsAndTestCases} +%% GroupName = atom() +%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}] +%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase] +%% TestCase = atom() +%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}} +%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail | +%% repeat_until_any_ok | repeat_until_any_fail +%% N = integer() | forever +%% @end +%%-------------------------------------------------------------------- +groups() -> + []. + +%%-------------------------------------------------------------------- +%% @spec all() -> GroupsAndTestCases | {skip,Reason} +%% GroupsAndTestCases = [{group,GroupName} | TestCase] +%% GroupName = atom() +%% TestCase = atom() +%% Reason = term() +%% @end +%%-------------------------------------------------------------------- +all() -> + [m1]. + +%%-------------------------------------------------------------------- +%% @spec TestCase() -> Info +%% Info = [tuple()] +%% @end +%%-------------------------------------------------------------------- +m1() -> + []. + +%%-------------------------------------------------------------------- +%% @spec TestCase(Config0) -> +%% ok | exit() | {skip,Reason} | {comment,Comment} | +%% {save_config,Config1} | {skip_and_save,Reason,Config1} +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%% Comment = term() +%% @end +%%-------------------------------------------------------------------- +m1(Config) -> + {Src,Dst} = convert_module("m1",Config), + {true,L} = check_line_numbers(Src,Dst), + ok = check_link_targets(Src,Dst,L,[{baz,0}]), + ok. + +convert_module(Mod,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>"), + io:format("<a href=\"~s\">~s</a>\n",[Dst,filename:basename(Dst)]), + {Src,Dst}. + +%% Check that there are the same number of lines in each file, and +%% that all line numbers are displayed in the dst file. +check_line_numbers(Src,Dst) -> + {ok,SFd} = file:open(Src,[read]), + {ok,DFd} = file:open(Dst,[read]), + {ok,SN} = count_src_lines(SFd,0), + ok = file:close(SFd), + {ok,DN} = read_dst_line_numbers(DFd), + ok = file:close(DFd), + {SN == DN,SN}. + +count_src_lines(Fd,N) -> + case io:get_line(Fd,"") of + eof -> + {ok,N}; + {error,Reason} -> + {error,Reason,N}; + _Line -> + count_src_lines(Fd,N+1) + end. + +read_dst_line_numbers(Fd) -> + "<html><body><pre>\n" = io:get_line(Fd,""), + read_dst_line_numbers(Fd,0). +read_dst_line_numbers(Fd,Last) when is_integer(Last) -> + case io:get_line(Fd,"") of + eof -> + {ok,Last}; + {error,Reason} -> + {error,Reason,Last}; + "</pre>"++_ -> + {ok,Last}; + "</body>"++_ -> + {ok,Last}; + Line -> + %% erlang:display(Line), + Num = check_line_number(Last,Line,Line), + read_dst_line_numbers(Fd,Num) + end. + +check_line_number(Last,Line,OrigLine) -> + case Line of + "<a name="++_ -> + [$>|Rest] = lists:dropwhile(fun($>) -> false; (_) -> true end,Line), + check_line_number(Last,Rest,OrigLine); + _ -> + [N |_] = string:tokens(Line,":"), +% erlang:display(N), + Num = + try list_to_integer(string:strip(N)) + catch _:_ -> ct:fail({no_line_number_after,Last,OrigLine}) + end, + if Num == Last+1 -> + Num; + true -> + ct:fail({unexpected_integer,Num,Last}) + end + end. + + +%% Check that there is one link target for each line and one for each +%% 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) -> + 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}}]), + ok. + +sax_event(Event,_Loc,State) -> + sax_event(Event,State). + +sax_event({startElement,_Uri,"a",_QN,Attrs},{Exports,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}; + Other -> + ct:fail({unexpected_line_number_target,Other}) + end; + {'EXIT',_} -> + {match,[FStr,AStr]} = + re:run(Name,"^(.*)-([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} + end; +sax_event(_,State) -> + State. diff --git a/lib/test_server/test/erl2html2_SUITE_data/Makefile.src b/lib/test_server/test/erl2html2_SUITE_data/Makefile.src new file mode 100644 index 0000000000..942ac0584b --- /dev/null +++ b/lib/test_server/test/erl2html2_SUITE_data/Makefile.src @@ -0,0 +1,2 @@ +all: + erlc -Iinclude m1.erl
\ No newline at end of file diff --git a/lib/test_server/test/erl2html2_SUITE_data/header1.hrl b/lib/test_server/test/erl2html2_SUITE_data/header1.hrl new file mode 100644 index 0000000000..53d1b79ac5 --- /dev/null +++ b/lib/test_server/test/erl2html2_SUITE_data/header1.hrl @@ -0,0 +1,4 @@ +baz() -> + ok. + +-define(MACRO_DEFINING_A_FUNCTION,quux() -> ok). diff --git a/lib/test_server/test/erl2html2_SUITE_data/include/header2.hrl b/lib/test_server/test/erl2html2_SUITE_data/include/header2.hrl new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/lib/test_server/test/erl2html2_SUITE_data/include/header2.hrl diff --git a/lib/test_server/test/erl2html2_SUITE_data/m1.erl b/lib/test_server/test/erl2html2_SUITE_data/m1.erl new file mode 100644 index 0000000000..156f1d0a51 --- /dev/null +++ b/lib/test_server/test/erl2html2_SUITE_data/m1.erl @@ -0,0 +1,46 @@ +%% Comment with <html> code & </html> +%% and also some "quotes" and 'single quotes' + +-module(m1). + +-compile(export_all). + +-include("header1.hrl"). +-include("header2.hrl"). + +-define(MACRO1,value). + +%%% Comment +foo(x) -> + %% Comment + ok_x; +foo(y) -> + %% Second clause + ok_y. + +'quoted_foo'() -> + ok. + +'quoted_foo_with_"_and_/'() -> + ok. + +'quoted_foo_with_(_and_)'() -> + ok. + +'quoted_foo_with_<_and_>'() -> + ok. + +bar() -> + do_something(), +ok. % indentation error, OTP-9710 + +%% Function inside macro definition +?MACRO_DEFINING_A_FUNCTION. + +%% Two function one one line +quuux() -> ok. quuuux() -> ok. + +%% do_something/0 does something +do_something() -> + ?MACRO1. +%% comments after last line |