diff options
-rw-r--r-- | erts/doc/src/erl.xml | 36 | ||||
-rw-r--r-- | erts/emulator/internal_doc/dec.erl | 5 | ||||
-rw-r--r-- | erts/emulator/test/code_parallel_load_SUITE.erl | 1 | ||||
-rw-r--r-- | lib/common_test/src/ct_logs.erl | 1026 | ||||
-rw-r--r-- | lib/common_test/src/ct_run.erl | 14 | ||||
-rw-r--r-- | lib/common_test/test/ct_test_support.erl | 39 | ||||
-rw-r--r-- | lib/debugger/src/dbg_istk.erl | 2 | ||||
-rw-r--r-- | lib/dialyzer/test/behaviour_SUITE_data/src/custom_sup.erl | 2 | ||||
-rw-r--r-- | lib/inets/src/http_server/httpd_manager.erl | 4 | ||||
-rw-r--r-- | lib/kernel/test/global_SUITE_data/global_trace.erl | 9 | ||||
-rw-r--r-- | lib/public_key/test/erl_make_certs.erl | 4 | ||||
-rw-r--r-- | lib/runtime_tools/src/ttb_autostart.erl | 1 | ||||
-rw-r--r-- | lib/ssl/test/erl_make_certs.erl | 4 | ||||
-rw-r--r-- | lib/stdlib/doc/src/unicode_usage.xml | 1 | ||||
-rw-r--r-- | lib/stdlib/test/erl_eval_SUITE.erl | 3 | ||||
-rw-r--r-- | lib/stdlib/test/qlc_SUITE_data/join_info_compat.erl | 215 | ||||
-rw-r--r-- | lib/stdlib/test/shell_SUITE.erl | 3 | ||||
-rw-r--r-- | lib/test_server/src/erl2html2.erl | 3 | ||||
-rw-r--r-- | lib/test_server/test/test_server_SUITE.erl | 13 |
19 files changed, 990 insertions, 395 deletions
diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml index 1f7c5b5a7f..a68e62d051 100644 --- a/erts/doc/src/erl.xml +++ b/erts/doc/src/erl.xml @@ -536,15 +536,35 @@ <tag><marker id="file_name_encoding"></marker><c><![CDATA[+fnl]]></c></tag> <item> <p>The VM works with file names as if they are encoded using the ISO-latin-1 encoding, disallowing Unicode characters with codepoints beyond 255. This is default on operating systems that have transparent file naming, i.e. all Unixes except MacOSX.</p> + <p>See <seealso marker="stdlib:unicode_usage#unicode_file_names">STDLIB User's Guide</seealso> for more infomation about unicode file names.</p> </item> - <tag><c><![CDATA[+fnu]]></c></tag> + <tag><c><![CDATA[+fnu[{w|i|e}]]]></c></tag> <item> <p>The VM works with file names as if they are encoded using UTF-8 (or some other system specific Unicode encoding). This is the default on operating systems that enforce Unicode encoding, i.e. Windows and MacOSX.</p> - <p>By enabling Unicode file name translation on systems where this is not default, you open up to the possibility that some file names can not be interpreted by the VM and therefore will be returned to the program as raw binaries. The option is therefore considered experimental.</p> - </item> - <tag><c><![CDATA[+fna]]></c></tag> - <item> - <p>Selection between <c>+fnl</c> and <c>+fnu</c> is done based on the current locale settings in the OS, meaning that if you have set your terminal for UTF-8 encoding, the filesystem is expected to use the same encoding for filenames (use with care).</p> + <p>The <c>+fnu</c> switch can be followed by <c>w</c>, + <c>i</c>, or <c>e</c> to control the way wrongly encoded file + names are to be reported. <c>w</c> means that a warning is + sent to the <c>error_logger</c> whenever a wrongly encoded + file name is "skipped" in directory listings, <c>i</c> means + that those wrongly encoded file names are silently ignored and + <c>e</c> means that the API function will return an error + whenever a wrongly encoded file (or directory) name is + encountered. <c>w</c> is the default. Note that + <c>file:read_link/1</c> will always return an error if the + link points to an invalid file name.</p> + <p>See <seealso marker="stdlib:unicode_usage#unicode_file_names">STDLIB User's Guide</seealso> for more infomation about unicode file names.</p> + </item> + <tag><c><![CDATA[+fna[{w|i|e}]]]></c></tag> + <item> + <p>Selection between <c>+fnl</c> and <c>+fnu</c> is done based on the current locale settings in the OS, meaning that if you have set your terminal for UTF-8 encoding, the filesystem is expected to use the same encoding for file names (use with care).</p> + <p>The <c>+fna</c> switch can be followed by <c>w</c>, + <c>i</c>, or <c>e</c>. This will have effect if the locale + settings cause the behavior of <c>+fnu</c> to be selected. + See the description of <c>+fnu</c> above. If the locale + settings cause the behavior of <c>+fnl</c> to be selected, + then <c>w</c>, <c>i</c>, or <c>e</c> will not have any + effect.</p> + <p>See <seealso marker="stdlib:unicode_usage#unicode_file_names">STDLIB User's Guide</seealso> for more infomation about unicode file names.</p> </item> <tag><c><![CDATA[+hms Size]]></c></tag> <item> @@ -571,9 +591,9 @@ </item> <tag><c><![CDATA[+L]]></c></tag> <item> - <p>Don't load information about source filenames and line numbers. + <p>Don't load information about source file names and line numbers. This will save some memory, but exceptions will not contain - information about the filenames and line numbers. + information about the file names and line numbers. </p> </item> <tag><marker id="erts_alloc"><c><![CDATA[+MFlag Value]]></c></marker></tag> diff --git a/erts/emulator/internal_doc/dec.erl b/erts/emulator/internal_doc/dec.erl index 0315f2a52d..255018abe0 100644 --- a/erts/emulator/internal_doc/dec.erl +++ b/erts/emulator/internal_doc/dec.erl @@ -1,3 +1,4 @@ +%% -*- coding: utf-8 -*- %% %% %CopyrightBegin% %% @@ -25,10 +26,10 @@ %% {RevList,Translation} %% Where 'RevList' is a reversed list of the denormalized repressentation of %% the character 'Translation'. An example would be the swedish character -%% '�', which would be represented in the file as: +%% 'ö', which would be represented in the file as: %% {[776,111],246}, as the denormalized representation of codepoint 246 %% is [111,776] (i.e an 'o' followed by the "double dot accent character 776), -%% while '�' instead is represented as {[776,97],228}, as the denormalized +%% while 'ä' instead is represented as {[776,97],228}, as the denormalized %% form would be [97,776] (same accent but an 'a' instead). %% The datafile is generated from the table on Apple's developer connection %% http://developer.apple.com/library/mac/#technotes/tn/tn1150table.html diff --git a/erts/emulator/test/code_parallel_load_SUITE.erl b/erts/emulator/test/code_parallel_load_SUITE.erl index aa9e4c96c6..d2c80c1ca0 100644 --- a/erts/emulator/test/code_parallel_load_SUITE.erl +++ b/erts/emulator/test/code_parallel_load_SUITE.erl @@ -16,7 +16,6 @@ %% %% %CopyrightEnd% %% -%% Author: Björn-Egil Dahlberg -module(code_parallel_load_SUITE). -export([ diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl index 6dce989a88..1f8160ff03 100644 --- a/lib/common_test/src/ct_logs.erl +++ b/lib/common_test/src/ct_logs.erl @@ -60,6 +60,7 @@ -define(all_runs_name, "all_runs.html"). -define(index_name, "index.html"). -define(totals_name, "totals.info"). +-define(log_cache_name, "ct_log_cache"). -define(table_color1,"#ADD8E6"). -define(table_color2,"#E4F0FE"). @@ -69,6 +70,10 @@ -define(abs(Name), filename:absname(Name)). +-record(log_cache, {version, + all_runs = [], + tests = []}). + %%%----------------------------------------------------------------- %%% @spec init(Mode) -> Result %%% Mode = normal | interactive @@ -94,14 +99,25 @@ init(Mode, Verbosity) -> exit({could_not_start_process,?MODULE,Reason}) end. -make_dirname({{YY,MM,DD},{H,M,S}}) -> - io_lib:format(logdir_node_prefix()++".~w-~2.2.0w-~2.2.0w_~2.2.0w.~2.2.0w.~2.2.0w", - [YY,MM,DD,H,M,S]). - +date2str({{YY,MM,DD},{H,M,S}}) -> + lists:flatten(io_lib:format("~w-~2.2.0w-~2.2.0w_~2.2.0w.~2.2.0w.~2.2.0w", + [YY,MM,DD,H,M,S])). logdir_prefix() -> "ct_run". logdir_node_prefix() -> - logdir_prefix()++"."++atom_to_list(node()). + logdir_prefix() ++ "." ++ atom_to_list(node()). + +make_dirname(DateTime) -> + logdir_node_prefix() ++ "." ++ date2str(DateTime). + +datestr_from_dirname([Y1,Y2,Y3,Y4,$-,Mo1,Mo2,$-,D1,D2,$_, + H1,H2,$.,M1,M2,$.,S1,S2 | _]) -> + [Y1,Y2,Y3,Y4,$-,Mo1,Mo2,$-,D1,D2,$_, + H1,H2,$.,M1,M2,$.,S1,S2]; +datestr_from_dirname([_Ch | Rest]) -> + datestr_from_dirname(Rest); +datestr_from_dirname([]) -> + "". %%%----------------------------------------------------------------- %%% @spec close(Info, StartDir) -> ok @@ -109,8 +125,21 @@ logdir_node_prefix() -> %%% @doc Create index pages with test results and close the CT Log %%% (tool-internal use only). close(Info, StartDir) -> - make_last_run_index(), - + %% close executes on the ct_util process, not on the logger process + %% so we need to use a local copy of the log cache data + LogCacheBin = make_last_run_index(), + put(ct_log_cache,LogCacheBin), + Cache2File = fun() -> + case get(ct_log_cache) of + undefined -> + ok; + CacheBin -> + %% save final version of the log cache to file + file:write_file(?log_cache_name,CacheBin), + put(ct_log_cache,undefined) + end + end, + ct_event:notify(#event{name=stop_logging,node=node(),data=[]}), case whereis(?MODULE) of @@ -133,11 +162,13 @@ close(Info, StartDir) -> io:format("Warning! Cleanup failed: ~p~n", [Error]) end, make_all_suites_index(stop), - make_all_runs_index(stop); + make_all_runs_index(stop), + Cache2File(); true -> file:set_cwd(".."), make_all_suites_index(stop), make_all_runs_index(stop), + Cache2File(), case ct_util:get_profile_data(browser, StartDir) of undefined -> ok; @@ -567,9 +598,10 @@ logger(Parent, Mode, Verbosity) -> ok -> case copy_priv_files(PrivFilesSrc, PrivFilesDestRun) of {error,Src2,Dest2,Reason2} -> - io:format(user, "ERROR! "++ - "Priv file ~p could not be copied to ~p. "++ - "Reason: ~p~n", + io:format(user, + "ERROR! "++ + "Priv file ~p could not be copied to ~p. " + ++"Reason: ~p~n", [Src2,Dest2,Reason2]), exit({priv_file_error,Dest2}); ok -> @@ -693,7 +725,7 @@ logger_loop(State) -> logger_loop(State); {make_last_run_index,From} -> make_last_run_index(State#logger_state.start_time), - return(From,filename:basename(State#logger_state.log_dir)), + return(From,get(ct_log_cache)), logger_loop(State); {set_stylesheet,_,SSFile} when State#logger_state.stylesheet == SSFile -> @@ -963,29 +995,27 @@ close_ctlog(Fd) -> make_last_run_index(StartTime) -> IndexName = ?index_name, AbsIndexName = ?abs(IndexName), - case catch make_last_run_index1(StartTime,IndexName) of - {'EXIT', Reason} -> - io:put_chars("CRASHED while updating " ++ AbsIndexName ++ "!\n"), - io:format("~p~n", [Reason]), - {error, Reason}; - {error, Reason} -> - io:put_chars("FAILED while updating " ++ AbsIndexName ++ "\n"), - io:format("~p~n", [Reason]), - {error, Reason}; - ok -> -% io:put_chars("done\n"), - ok; - Err -> - io:format("Unknown internal error while updating ~ts. " - "Please report.\n(Err: ~p, ID: 1)", - [AbsIndexName,Err]), - {error, Err} - end. + Result = + case catch make_last_run_index1(StartTime,IndexName) of + {'EXIT', Reason} -> + io:put_chars("CRASHED while updating " ++ AbsIndexName ++ "!\n"), + io:format("~p~n", [Reason]), + {error, Reason}; + {error, Reason} -> + io:put_chars("FAILED while updating " ++ AbsIndexName ++ "\n"), + io:format("~p~n", [Reason]), + {error, Reason}; + ok -> + ok; + Err -> + io:format("Unknown internal error while updating ~ts. " + "Please report.\n(Err: ~p, ID: 1)", + [AbsIndexName,Err]), + {error, Err} + end, + Result. make_last_run_index1(StartTime,IndexName) -> - %% this manoeuvre is to ensure the tests get logged - %% in correct order of time (the 1 sec resolution - %% of the dirnames may be too big) Logs1 = case filelib:wildcard([$*|?logdir_ext]) of [Log] -> % first test @@ -1014,6 +1044,7 @@ make_last_run_index1(StartTime,IndexName) -> %% write current Totals to file, later to be used in all_runs log write_totals_file(?totals_name,Label,Logs1,Totals), Index = [Index0|index_footer()], + case force_write_file(IndexName, unicode:characters_to_binary(Index)) of ok -> ok; @@ -1052,22 +1083,26 @@ make_last_run_index([Name|Rest], Result, TotSucc, TotFail, TotNotBuilt1, Missing) end; -make_last_run_index([], Result, TotSucc, TotFail, UserSkip, AutoSkip, TotNotBuilt, _) -> - {ok, [Result|total_row(TotSucc, TotFail, UserSkip, AutoSkip, TotNotBuilt, false)], +make_last_run_index([], Result, TotSucc, TotFail, UserSkip, AutoSkip, + TotNotBuilt, _) -> + {ok, [Result|total_row(TotSucc, TotFail, UserSkip, AutoSkip, + TotNotBuilt, false)], {TotSucc,TotFail,UserSkip,AutoSkip,TotNotBuilt}}. make_last_run_index1(SuiteName, [LogDir | LogDirs], Result, TotSucc, TotFail, UserSkip, AutoSkip, TotNotBuilt, Missing) -> - case make_one_index_entry(SuiteName, LogDir, "-", false, Missing) of - {Result1,Succ,Fail,USkip,ASkip,NotBuilt} -> + case make_one_index_entry(SuiteName, LogDir, "-", false, + Missing, undefined) of + {Result1,Succ,Fail,USkip,ASkip,NotBuilt,_URIs1} -> %% for backwards compatibility AutoSkip1 = case catch AutoSkip+ASkip of {'EXIT',_} -> undefined; Res -> Res end, - make_last_run_index1(SuiteName, LogDirs, [Result|Result1], TotSucc+Succ, - TotFail+Fail, UserSkip+USkip, AutoSkip1, - TotNotBuilt+NotBuilt, Missing); + make_last_run_index1(SuiteName, LogDirs, [Result|Result1], + TotSucc+Succ, + TotFail+Fail, UserSkip+USkip, AutoSkip1, + TotNotBuilt+NotBuilt, Missing); error -> make_last_run_index1(SuiteName, LogDirs, Result, TotSucc, TotFail, UserSkip, AutoSkip, TotNotBuilt, Missing) @@ -1076,35 +1111,49 @@ make_last_run_index1(_, [], Result, TotSucc, TotFail, UserSkip, AutoSkip, TotNotBuilt, _) -> {Result,TotSucc,TotFail,UserSkip,AutoSkip,TotNotBuilt}. -make_one_index_entry(SuiteName, LogDir, Label, All, Missing) -> +make_one_index_entry(SuiteName, LogDir, Label, All, Missing, URIs) -> case count_cases(LogDir) of {Succ,Fail,UserSkip,AutoSkip} -> NotBuilt = not_built(SuiteName, LogDir, All, Missing), - NewResult = make_one_index_entry1(SuiteName, LogDir, Label, Succ, Fail, - UserSkip, AutoSkip, NotBuilt, All, - normal), - {NewResult,Succ,Fail,UserSkip,AutoSkip,NotBuilt}; + {NewResult,URIs1} = make_one_index_entry1(SuiteName, LogDir, Label, + Succ, Fail, + UserSkip, AutoSkip, + NotBuilt, All, + normal, URIs), + {NewResult,Succ,Fail,UserSkip,AutoSkip,NotBuilt,URIs1}; error -> error end. make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip, - NotBuilt, All, Mode) -> + NotBuilt, All, Mode, URIs) -> LogFile = filename:join(Link, ?suitelog_name ++ ".html"), + CtRunDir = filename:dirname(filename:dirname(Link)), + CrashDumpName = SuiteName ++ "_erl_crash.dump", + + URIs1 = {CtRunLogURI,LogFileURI,CrashDumpURI} = + case URIs of + undefined -> + {uri(filename:join(CtRunDir,?ct_log_name)), + uri(LogFile), + uri(CrashDumpName)}; + _ -> + URIs + end, + CrashDumpLink = case Mode of - cached -> + temp -> ""; normal -> - CrashDumpName = SuiteName ++ "_erl_crash.dump", case filelib:is_file(CrashDumpName) of true -> - [" <a href=\"", uri(CrashDumpName), + [" <a href=\"", CrashDumpURI, "\">(CrashDump)</a>"]; false -> "" end end, - CtRunDir = filename:dirname(filename:dirname(Link)), + {Lbl,Timestamp,Node,AllInfo} = case All of {true,OldRuns} -> @@ -1113,7 +1162,9 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip, 0 -> "-"; _ -> NodeOrDate end, + TS = timestamp(CtRunDir), + N = xhtml(["<td align=right><font size=\"-1\">",Node1, "</font></td>\n"], ["<td align=right>",Node1,"</td>\n"]), @@ -1122,28 +1173,31 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip, ["<td align=center><b>",Label,"</b></td>\n"]), T = xhtml(["<td><font size=\"-1\">",TS,"</font></td>\n"], ["<td>",TS,"</td>\n"]), - CtLogFile = filename:join(CtRunDir,?ct_log_name), + OldRunsLink = case OldRuns of [] -> "none"; _ -> "<a href=\""++?all_runs_name++"\">Old Runs</a>" end, - A = xhtml(["<td><font size=\"-1\"><a href=\"",uri(CtLogFile), + + A = xhtml(["<td><font size=\"-1\"><a href=\"",CtRunLogURI, "\">CT Log</a></font></td>\n", - "<td><font size=\"-1\">",OldRunsLink,"</font></td>\n"], - ["<td><a href=\"",uri(CtLogFile),"\">CT Log</a></td>\n", + "<td><font size=\"-1\">",OldRunsLink, + "</font></td>\n"], + ["<td><a href=\"",CtRunLogURI, + "\">CT Log</a></td>\n", "<td>",OldRunsLink,"</td>\n"]), {L,T,N,A}; false -> {"","","",""} end, + NotBuiltStr = if NotBuilt == 0 -> ["<td align=right>",integer_to_list(NotBuilt),"</td>\n"]; true -> - ["<td align=right><a href=\"", - uri(filename:join(CtRunDir,?ct_log_name)),"\">", - integer_to_list(NotBuilt),"</a></td>\n"] + ["<td align=right><a href=\"",CtRunLogURI,"\">", + integer_to_list(NotBuilt),"</a></td>\n"] end, FailStr = if Fail > 0 -> @@ -1162,17 +1216,17 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip, end, {UserSkip+AutoSkip,integer_to_list(UserSkip),ASStr} end, - [xhtml("<tr valign=top>\n", - ["<tr class=\"",odd_or_even(),"\">\n"]), - xhtml("<td><font size=\"-1\"><a href=\"", "<td><a href=\""), - uri(LogFile),"\">",SuiteName,"</a>", CrashDumpLink, - xhtml("</font></td>\n", "</td>\n"), - Lbl, Timestamp, - "<td align=right>",integer_to_list(Success),"</td>\n", - "<td align=right>",FailStr,"</td>\n", - "<td align=right>",integer_to_list(AllSkip), - " (",UserSkipStr,"/",AutoSkipStr,")</td>\n", - NotBuiltStr, Node, AllInfo, "</tr>\n"]. + {[xhtml("<tr valign=top>\n", + ["<tr class=\"",odd_or_even(),"\">\n"]), + xhtml("<td><font size=\"-1\"><a href=\"", "<td><a href=\""), + LogFileURI,"\">",SuiteName,"</a>", CrashDumpLink, + xhtml("</font></td>\n", "</td>\n"), + Lbl, Timestamp, + "<td align=right>",integer_to_list(Success),"</td>\n", + "<td align=right>",FailStr,"</td>\n", + "<td align=right>",integer_to_list(AllSkip), + " (",UserSkipStr,"/",AutoSkipStr,")</td>\n", + NotBuiltStr, Node, AllInfo, "</tr>\n"], URIs1}. total_row(Success, Fail, UserSkip, AutoSkip, NotBuilt, All) -> {Label,TimestampCell,AllInfo} = @@ -1586,35 +1640,169 @@ make_all_runs_index(When) -> if When == start -> ok; true -> io:put_chars("Updating " ++ AbsName ++ "... ") end, + + %% check if log cache should be used, and if it exists + UseCache = + if When == refresh -> + save_only; + true -> + case application:get_env(common_test, disable_log_cache) of + {ok,true} -> + disabled; + _ -> + case get(ct_log_cache) of + undefined -> + file:read_file(?log_cache_name); + LogCacheBin -> + {ok,LogCacheBin} + end + end + end, + Dirs = filelib:wildcard(logdir_prefix()++"*.*"), DirsSorted = (catch sort_all_runs(Dirs)), - Header = all_runs_header(), - Index = [runentry(Dir) || Dir <- DirsSorted], - Result = file:write_file(AbsName, - unicode:characters_to_binary( - Header++Index++all_runs_index_footer())), + + LogCacheInfo = get_cache_data(UseCache), + + Result = + case LogCacheInfo of + {ok,LogCache} -> + %% use the log cache file to generate the index + make_all_runs_from_cache(AbsName,DirsSorted,LogCache); + + _WhyNot -> + %% no cache file exists (or feature has been disabled) + Header = all_runs_header(), + GetLogResult = + fun(Dir,{RunData,LogTxt}) -> + {Tot,XHTML,IxLink} = runentry(Dir, + undefined, + undefined), + {[{Dir,Tot,IxLink}|RunData],[XHTML|LogTxt]} + end, + {AllRunsData,Index} = + lists:foldr(GetLogResult,{[],[]},DirsSorted), + + %% update cache with result unless the cache is disabled + if UseCache == disabled -> ok; + true -> update_all_runs_in_cache(AllRunsData) + end, + %% write all_runs log file + ok = file:write_file(AbsName, + unicode:characters_to_binary( + Header++Index++ + all_runs_index_footer())) + end, + notify_and_unlock_file(AbsName), if When == start -> ok; true -> io:put_chars("done\n") end, - notify_and_unlock_file(AbsName), Result. +make_all_runs_from_cache(AbsName, Dirs, LogCache) -> + Header = all_runs_header(), + + %% Note that both Dirs and the cache is sorted! + AllRunsDirs = dir_diff_all_runs(Dirs, LogCache), + + GetLogResult = + fun({Dir,no_test_data,IxLink},{RunData,LogTxt}) -> + {Tot,XHTML,_} = runentry(Dir,undefined,IxLink), + {[{Dir,Tot,IxLink}|RunData],[XHTML|LogTxt]}; + ({Dir,CachedTotals,IxLink},{RunData,LogTxt}) -> + %% create log entry using cached data + {Tot,XHTML,_} = runentry(Dir,CachedTotals,IxLink), + {[{Dir,Tot,IxLink}|RunData],[XHTML|LogTxt]}; + (Dir,{RunData,LogTxt}) -> + %% create log entry from scratch + {Tot,XHTML,IxLink} = runentry(Dir,undefined,undefined), + {[{Dir,Tot,IxLink}|RunData],[XHTML|LogTxt]} + end, + {AllRunsData,Index} = lists:foldr(GetLogResult,{[],[]},AllRunsDirs), + %% update cache with result + update_all_runs_in_cache(AllRunsData,LogCache), + %% write all_runs log file + ok = file:write_file(AbsName, + unicode:characters_to_binary( + Header++Index++ + all_runs_index_footer())). + +update_all_runs_in_cache(AllRunsData) -> + case get(ct_log_cache) of + undefined -> + LogCache = #log_cache{version = cache_vsn(), + all_runs = AllRunsData}, + case {self(),whereis(?MODULE)} of + {_Pid,_Pid} -> + %% save the cache in RAM so it doesn't have to be + %% read from file as long as this logger process is alive + put(ct_log_cache,term_to_binary(LogCache)); + _ -> + file:write_file(?log_cache_name,term_to_binary(LogCache)) + end; + SavedLogCache -> + update_all_runs_in_cache(AllRunsData,binary_to_term(SavedLogCache)) + end. + +update_all_runs_in_cache(AllRunsData, LogCache) -> + LogCache1 = LogCache#log_cache{all_runs = AllRunsData}, + case {self(),whereis(?MODULE)} of + {_Pid,_Pid} -> + %% save the cache in RAM so it doesn't have to be + %% read from file as long as this logger process is alive + put(ct_log_cache,term_to_binary(LogCache1)); + _ -> + file:write_file(?log_cache_name,term_to_binary(LogCache1)) + end. + sort_all_runs(Dirs) -> %% sort on time string, always last and on the format: %% "YYYY-MM-DD_HH.MM.SS" - KeyList = - lists:map(fun(Dir) -> - case lists:reverse(string:tokens(Dir,[$.,$_])) of - [SS,MM,HH,Date|_] -> - {{Date,HH,MM,SS},Dir}; - _Other -> - throw(Dirs) - end - end,Dirs), - lists:reverse(lists:map(fun({_,Dir}) -> - Dir - end,lists:keysort(1,KeyList))). + lists:sort(fun(Dir1,Dir2) -> + [SS1,MM1,HH1,Date1|_] = + lists:reverse(string:tokens(Dir1,[$.,$_])), + [SS2,MM2,HH2,Date2|_] = + lists:reverse(string:tokens(Dir2,[$.,$_])), + {Date1,HH1,MM1,SS1} > {Date2,HH2,MM2,SS2} + end, Dirs). + +dir_diff_all_runs(Dirs, LogCache) -> + case LogCache#log_cache.all_runs of + [] -> + Dirs; + Cached = [{CDir,_,_}|_] -> + AllRunsDirs = + dir_diff_all_runs(Dirs, Cached, datestr_from_dirname(CDir), []), + lists:reverse(AllRunsDirs) + end. + +dir_diff_all_runs(LogDirs=[Dir|Dirs], Cached=[CElem|CElems], + LatestInCache, AllRunsDirs) -> + DirDate = datestr_from_dirname(Dir), + if DirDate > LatestInCache -> + %% Dir is a new run entry + dir_diff_all_runs(Dirs, Cached, LatestInCache, + [Dir|AllRunsDirs]); + DirDate == LatestInCache, CElems /= [] -> + %% Dir is an existing run entry + dir_diff_all_runs(Dirs, CElems, + datestr_from_dirname(element(1,hd(CElems))), + [CElem|AllRunsDirs]); + DirDate == LatestInCache, CElems == [] -> + %% we're done, Dirs must all be new + lists:reverse(Dirs)++[CElem|AllRunsDirs]; + CElems /= [] -> % DirDate < LatestInCache + %% current CDir not in Dirs, update timestamp and check next + dir_diff_all_runs(LogDirs, CElems, + datestr_from_dirname(element(1,hd(CElems))), + AllRunsDirs); + CElems == [] -> + %% we're done, LogDirs must all be new + lists:reverse(LogDirs)++AllRunsDirs + end; +dir_diff_all_runs([], _Cached, _, AllRunsDirs) -> + AllRunsDirs. interactive_link() -> [Dir|_] = lists:reverse(filelib:wildcard(logdir_prefix()++"*.*")), @@ -1625,12 +1813,14 @@ interactive_link() -> "<html>\n"], ["<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n", "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n", - "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"]), + "<html xmlns=\"http://www.w3.org/1999/xhtml\" ", + "xml:lang=\"en\" lang=\"en\">\n"]), "<!-- autogenerated by '"++atom_to_list(?MODULE)++"' -->\n", "<head>\n", "<title>Last interactive run</title>\n", "<meta http-equiv=\"cache-control\" content=\"no-cache\">\n", - "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n", + "<meta http-equiv=\"content-type\" content=\"text/html; " + "charset=utf-8\">\n", "</head>\n", "<body>\n", "Log from last interactive run: <a href=\"",uri(CtLog),"\">", @@ -1643,98 +1833,120 @@ interactive_link() -> "Any CT activities will be logged here\n", [?abs("last_interactive.html")]). -runentry(Dir) -> +%% use if cache disabled or non-existing +runentry(Dir, undefined, _) -> TotalsFile = filename:join(Dir,?totals_name), - TotalsStr = - case read_totals_file(TotalsFile) of - {Node,Label,Logs,{TotSucc,TotFail,UserSkip,AutoSkip,NotBuilt}} -> - TotFailStr = - if TotFail > 0 -> - ["<font color=\"red\">", - integer_to_list(TotFail),"</font>"]; - true -> - integer_to_list(TotFail) - end, - {AllSkip,UserSkipStr,AutoSkipStr} = - if AutoSkip == undefined -> {UserSkip,"?","?"}; - true -> - ASStr = if AutoSkip > 0 -> - ["<font color=\"brown\">", - integer_to_list(AutoSkip),"</font>"]; - true -> integer_to_list(AutoSkip) - end, - {UserSkip+AutoSkip,integer_to_list(UserSkip),ASStr} - end, - NoOfTests = case length(Logs) of - 0 -> "-"; - N -> integer_to_list(N) - end, - StripExt = - fun(File) -> - string:sub_string(File,1, - length(File)- - length(?logdir_ext)) ++ ", " - end, - Polish = fun(S) -> case lists:reverse(S) of - [32,$,|Rev] -> lists:reverse(Rev); - [$,|Rev] -> lists:reverse(Rev); - _ -> S - end - end, - TestNames = Polish(lists:flatten(lists:map(StripExt,Logs))), - TestNamesTrunc = - if TestNames=="" -> - ""; - length(TestNames) < ?testname_width -> - TestNames; - true -> - Trunc = Polish(string:substr(TestNames,1,?testname_width-3)), - lists:flatten(io_lib:format("~ts...",[Trunc])) - end, - Total = TotSucc+TotFail+AllSkip, - A = xhtml(["<td align=center><font size=\"-1\">",Node, - "</font></td>\n", - "<td align=center><font size=\"-1\"><b>",Label, - "</b></font></td>\n", - "<td align=right>",NoOfTests,"</td>\n"], - ["<td align=center>",Node,"</td>\n", - "<td align=center><b>",Label,"</b></td>\n", - "<td align=right>",NoOfTests,"</td>\n"]), - B = xhtml(["<td align=center title='",TestNames,"'><font size=\"-1\"> ", - TestNamesTrunc,"</font></td>\n"], - ["<td align=center title='",TestNames,"'> ", - TestNamesTrunc,"</td>\n"]), - C = ["<td align=right>",integer_to_list(Total),"</td>\n", - "<td align=right>",integer_to_list(TotSucc),"</td>\n", - "<td align=right>",TotFailStr,"</td>\n", - "<td align=right>",integer_to_list(AllSkip), - " (",UserSkipStr,"/",AutoSkipStr,")</td>\n", - "<td align=right>",integer_to_list(NotBuilt),"</td>\n"], - A++B++C; - _ -> - A = xhtml(["<td align=center><font size=\"-1\" color=\"red\">" - "Test data missing or corrupt</font></td>\n", - "<td align=center><font size=\"-1\">?</font></td>\n", - "<td align=right>?</td>\n"], - ["<td align=center><font color=\"red\">" - "Test data missing or corrupt</font></td>\n", - "<td align=center>?</td>\n", - "<td align=right>?</td>\n"]), - B = xhtml(["<td align=center><font size=\"-1\">?</font></td>\n"], - ["<td align=center>?</td>\n"]), - C = ["<td align=right>?</td>\n", - "<td align=right>?</td>\n", - "<td align=right>?</td>\n", - "<td align=right>?</td>\n", - "<td align=right>?</td>\n"], - A++B++C - end, Index = uri(filename:join(Dir,?index_name)), - [xhtml("<tr>\n", ["<tr class=\"",odd_or_even(),"\">\n"]), - xhtml(["<td><font size=\"-1\"><a href=\"",Index,"\">",timestamp(Dir),"</a>", - TotalsStr,"</font></td>\n"], - ["<td><a href=\"",Index,"\">",timestamp(Dir),"</a>",TotalsStr,"</td>\n"]), - "</tr>\n"]. + runentry(Dir, read_totals_file(TotalsFile), Index); + +%% use cached data +runentry(Dir, Totals={Node,Label,Logs, + {TotSucc,TotFail,UserSkip,AutoSkip,NotBuilt}}, Index) -> + TotFailStr = + if TotFail > 0 -> + ["<font color=\"red\">", + integer_to_list(TotFail),"</font>"]; + true -> + integer_to_list(TotFail) + end, + {AllSkip,UserSkipStr,AutoSkipStr} = + if AutoSkip == undefined -> {UserSkip,"?","?"}; + true -> + ASStr = if AutoSkip > 0 -> + ["<font color=\"brown\">", + integer_to_list(AutoSkip), + "</font>"]; + true -> integer_to_list(AutoSkip) + end, + {UserSkip+AutoSkip,integer_to_list(UserSkip),ASStr} + end, + NoOfTests = case length(Logs) of + 0 -> "-"; + N -> integer_to_list(N) + end, + StripExt = + fun(File) -> + string:sub_string(File,1, + length(File)- + length(?logdir_ext)) ++ ", " + end, + Polish = fun(S) -> case lists:reverse(S) of + [32,$,|Rev] -> lists:reverse(Rev); + [$,|Rev] -> lists:reverse(Rev); + _ -> S + end + end, + TestNames = Polish(lists:flatten(lists:map(StripExt,Logs))), + TestNamesTrunc = + if TestNames=="" -> + ""; + length(TestNames) < ?testname_width -> + TestNames; + true -> + Trunc = Polish(string:substr(TestNames,1, + ?testname_width-3)), + lists:flatten(io_lib:format("~ts...",[Trunc])) + end, + Total = TotSucc+TotFail+AllSkip, + A = xhtml(["<td align=center><font size=\"-1\">",Node, + "</font></td>\n", + "<td align=center><font size=\"-1\"><b>",Label, + "</b></font></td>\n", + "<td align=right>",NoOfTests,"</td>\n"], + ["<td align=center>",Node,"</td>\n", + "<td align=center><b>",Label,"</b></td>\n", + "<td align=right>",NoOfTests,"</td>\n"]), + B = xhtml(["<td align=center title='",TestNames, + "'><font size=\"-1\"> ", + TestNamesTrunc,"</font></td>\n"], + ["<td align=center title='",TestNames,"'> ", + TestNamesTrunc,"</td>\n"]), + C = ["<td align=right>",integer_to_list(Total),"</td>\n", + "<td align=right>",integer_to_list(TotSucc),"</td>\n", + "<td align=right>",TotFailStr,"</td>\n", + "<td align=right>",integer_to_list(AllSkip), + " (",UserSkipStr,"/",AutoSkipStr,")</td>\n", + "<td align=right>",integer_to_list(NotBuilt),"</td>\n"], + TotalsStr = A++B++C, + + XHTML = [xhtml("<tr>\n", ["<tr class=\"",odd_or_even(),"\">\n"]), + xhtml(["<td><font size=\"-1\"><a href=\"",Index,"\">", + timestamp(Dir),"</a>", + TotalsStr,"</font></td>\n"], + ["<td><a href=\"",Index,"\">",timestamp(Dir),"</a>",TotalsStr, + "</td>\n"]), + "</tr>\n"], + {Totals,XHTML,Index}; + +%% handle missing or corrupt data (missing e.g. if the test is in progress) +runentry(Dir, _, _) -> + A = xhtml(["<td align=center><font size=\"-1\" color=\"red\">" + "Test data missing or corrupt</font></td>\n", + "<td align=center><font size=\"-1\">?</font></td>\n", + "<td align=right>?</td>\n"], + ["<td align=center><font color=\"red\">" + "Test data missing or corrupt</font></td>\n", + "<td align=center>?</td>\n", + "<td align=right>?</td>\n"]), + B = xhtml(["<td align=center><font size=\"-1\">?</font></td>\n"], + ["<td align=center>?</td>\n"]), + C = ["<td align=right>?</td>\n", + "<td align=right>?</td>\n", + "<td align=right>?</td>\n", + "<td align=right>?</td>\n", + "<td align=right>?</td>\n"], + TotalsStr = A++B++C, + + Index = uri(filename:join(Dir,?index_name)), + + XHTML = [xhtml("<tr>\n", ["<tr class=\"",odd_or_even(),"\">\n"]), + xhtml(["<td><font size=\"-1\"><a href=\"",Index,"\">", + timestamp(Dir),"</a>", + TotalsStr,"</font></td>\n"], + ["<td><a href=\"",Index,"\">",timestamp(Dir),"</a>",TotalsStr, + "</td>\n"]), + "</tr>\n"], + {no_test_data,XHTML,Index}. write_totals_file(Name,Label,Logs,Totals) -> AbsName = ?abs(Name), @@ -1761,17 +1973,19 @@ read_totals_file(Name) -> _ -> Label end, case Tot of - {_Ok,_Fail,_USkip,_ASkip,_NoBuild} -> % latest format + {_Ok,_Fail,_USkip,_ASkip,_NoBuild} -> % latest format {Node,Label1,Ls,Tot}; {TotSucc,TotFail,AllSkip,NotBuilt} -> - {Node,Label1,Ls,{TotSucc,TotFail,AllSkip,undefined,NotBuilt}} + {Node,Label1,Ls, + {TotSucc,TotFail,AllSkip,undefined,NotBuilt}} end; {Node,Ls,Tot} -> % no label found case Tot of - {_Ok,_Fail,_USkip,_ASkip,_NoBuild} -> % latest format + {_Ok,_Fail,_USkip,_ASkip,_NoBuild} -> % latest format {Node,"-",Ls,Tot}; {TotSucc,TotFail,AllSkip,NotBuilt} -> - {Node,"-",Ls,{TotSucc,TotFail,AllSkip,undefined,NotBuilt}} + {Node,"-",Ls, + {TotSucc,TotFail,AllSkip,undefined,NotBuilt}} end; %% for backwards compatibility {Ls,Tot} -> {"-",Ls,Tot}; @@ -1825,29 +2039,73 @@ timestamp(Dir) -> %% run will not show until after the final refresh. %% ------------------------------------------------------------------------- -%% Creates the top level index file. When == start | refresh. -%% A copy of the dir tree under logdir is cached as a result. +%% Creates the top level index file. When == start | stop | refresh. +%% A copy of the dir tree under logdir is saved temporarily as a result. make_all_suites_index(When) when is_atom(When) -> put(basic_html, basic_html()), AbsIndexName = ?abs(?index_name), notify_and_lock_file(AbsIndexName), + + %% check if log cache should be used, and if it exists + UseCache = + if When == refresh -> + save_only; + true -> + case application:get_env(common_test, disable_log_cache) of + {ok,true} -> + disabled; + _ -> + case get(ct_log_cache) of + undefined -> + file:read_file(?log_cache_name); + LogCacheBin -> + {ok,LogCacheBin} + end + end + end, + LogDirs = filelib:wildcard(logdir_prefix()++".*/*"++?logdir_ext), - Sorted = sort_logdirs(LogDirs, []), - Result = make_all_suites_index1(When, AbsIndexName, Sorted), - notify_and_unlock_file(AbsIndexName), - Result; -%% This updates the top level index file using cached data from -%% the initial index file creation. -make_all_suites_index(NewTestData = {_TestName,DirName}) -> + LogCacheInfo = get_cache_data(UseCache), + + Result = + case LogCacheInfo of + {ok,LogCache} -> + %% use the log cache file to generate the index + make_all_suites_index_from_cache(When,AbsIndexName, + LogDirs,LogCache); + _WhyNot -> + %% no cache file exists (or feature has been disabled) + Sorted = sort_and_filter_logdirs(LogDirs), + TempData = make_all_suites_index1(When,AbsIndexName,Sorted), + notify_and_unlock_file(AbsIndexName), + + %% save new cache file unless the feature is disabled + if UseCache == disabled -> ok; + true -> update_tests_in_cache(TempData) + end, + TempData + end, + + case Result of + Error = {error,_} -> Error; + _ -> ok + end; + +%% This updates the top level index file using data from the initial +%% index file creation, saved temporarily in a table. +make_all_suites_index(NewTestData = {_TestName,DirName}) -> put(basic_html, basic_html()), - %% AllLogDirs = [{TestName,Label,Missing,{LastLogDir,Summary},OldDirs}|...] + + %% AllLogDirs = [{TestName,Label,Missing, + %% {LastLogDir,Summary,URIs},OldDirs}|...] + {AbsIndexName,LogDirData} = ct_util:get_testdata(test_index), CtRunDirPos = length(filename:split(AbsIndexName)), CtRunDir = filename:join(lists:sublist(filename:split(DirName), CtRunDirPos)), - + Label = case read_totals_file(filename:join(CtRunDir, ?totals_name)) of {_,"-",_,_} -> "..."; {_,Lbl,_,_} -> Lbl; @@ -1855,10 +2113,10 @@ make_all_suites_index(NewTestData = {_TestName,DirName}) -> end, notify_and_lock_file(AbsIndexName), Result = - case catch make_all_suites_ix_cached(AbsIndexName, - NewTestData, - Label, - LogDirData) of + case catch make_all_suites_ix_temp(AbsIndexName, + NewTestData, + Label, + LogDirData) of {'EXIT',Reason} -> io:put_chars("CRASHED while updating " ++ AbsIndexName ++ "!\n"), io:format("~p~n", [Reason]), @@ -1875,46 +2133,219 @@ make_all_suites_index(NewTestData = {_TestName,DirName}) -> [AbsIndexName,Err]), {error, Err} end, - notify_and_unlock_file(AbsIndexName), + notify_and_unlock_file(AbsIndexName), Result. -sort_logdirs([Dir|Dirs],Groups) -> +make_all_suites_index_from_cache(When, AbsIndexName, LogDirs, LogCache) -> + + %% The structure of the cache: + %% + %% #log_cache{tests = {TestName,Label,Missing, + %% {LastLogDir,Summary,URIs},OldDirs} + %% } + %% Summary = {Succ,Fail,USkip,ASkip} | error + %% + + {NewAdded,OldTests} = dir_diff_tests(LogDirs,LogCache), + + LogCache1 = delete_tests_from_cache(OldTests,LogCache), + Sorted = sort_and_filter_logdirs(NewAdded, + LogCache1#log_cache.tests), + TempData = + if Sorted /= [] -> + make_all_suites_index1(When,AbsIndexName, + Sorted); + true -> + Data = LogCache1#log_cache.tests, + ct_util:set_testdata_async({test_index,{AbsIndexName, + Data}}), + Data + end, + + notify_and_unlock_file(AbsIndexName), + + update_tests_in_cache(TempData,LogCache1), + TempData. + +sort_and_filter_logdirs(NewDirs,CachedTests) when CachedTests /= [] -> + NewSorted = sort_and_filter_logdirs1(NewDirs,[]), + sort_and_filter_logdirs(NewSorted,CachedTests,[]); + +sort_and_filter_logdirs(NewDirs,_CachedTests) -> + sort_and_filter_logdirs(NewDirs). + +%% sort latest dirs found and combine them with cached entries +sort_and_filter_logdirs([{TestName,IxDirs}|Tests],CachedTests,Combined) -> + case lists:keysearch(TestName,1,CachedTests) of + {value,{TestName,_,_,{IxDir0,_,_},IxDirs0}} -> + Groups = sort_and_filter_logdirs2(TestName, + IxDirs++[IxDir0|IxDirs0], + []), + sort_and_filter_logdirs(Tests,CachedTests,Groups++Combined); + _ -> + IxDirs1 = lists:map(fun(Elem = {_,_}) -> + Elem; + (RunDir) -> + {filename:basename(RunDir),RunDir} + end, IxDirs), + sort_and_filter_logdirs(Tests,CachedTests, + [{TestName,IxDirs1}|Combined]) + end; +sort_and_filter_logdirs([],CachedTests,Combined) -> + Cached1 = lists:foldl(fun({TestName,_},Cached) -> + lists:keydelete(TestName,1,Cached) + end, CachedTests, Combined), + lists:keysort(1,sort_each_group(Combined)++Cached1). + +sort_and_filter_logdirs(Dirs) -> + sort_and_filter_logdirs1(Dirs, []). + +%% sort and filter directories (no cache) +sort_and_filter_logdirs1([Dir|Dirs],Groups) -> TestName = filename:rootname(filename:basename(Dir)), case filelib:wildcard(filename:join(Dir,"run.*")) of RunDirs = [_|_] -> - Groups1 = sort_logdirs1(TestName,RunDirs,Groups), - sort_logdirs(Dirs,Groups1); + Groups1 = sort_and_filter_logdirs2(TestName,RunDirs,Groups), + sort_and_filter_logdirs1(Dirs,Groups1); _ -> % ignore missing run directory - sort_logdirs(Dirs,Groups) + sort_and_filter_logdirs1(Dirs,Groups) end; -sort_logdirs([],Groups) -> +sort_and_filter_logdirs1([],Groups) -> lists:keysort(1,sort_each_group(Groups)). -sort_logdirs1(TestName,[RunDir|RunDirs],Groups) -> +sort_and_filter_logdirs2(TestName,[RunDir|RunDirs],Groups) -> Groups1 = insert_test(TestName,{filename:basename(RunDir),RunDir},Groups), - sort_logdirs1(TestName,RunDirs,Groups1); -sort_logdirs1(_,[],Groups) -> + sort_and_filter_logdirs2(TestName,RunDirs,Groups1); +sort_and_filter_logdirs2(_,[],Groups) -> Groups. +%% new rundir for Test found, add to (not sorted) list of prev rundirs insert_test(Test,IxDir,[{Test,IxDirs}|Groups]) -> [{Test,[IxDir|IxDirs]}|Groups]; +%% first occurance of Test insert_test(Test,IxDir,[]) -> [{Test,[IxDir]}]; insert_test(Test,IxDir,[TestDir|Groups]) -> [TestDir|insert_test(Test,IxDir,Groups)]. - + +%% sort the list of rundirs for each Test sort_each_group([{Test,IxDirs}|Groups]) -> Sorted = lists:reverse([Dir || {_,Dir} <- lists:keysort(1,IxDirs)]), - [{Test,Sorted}| sort_each_group(Groups)]; + [{Test,Sorted}|sort_each_group(Groups)]; sort_each_group([]) -> []. -make_all_suites_index1(When, AbsIndexName, AllLogDirs) -> +dir_diff_tests(LogDirs, #log_cache{tests = CachedTests}) -> + AllTestNames = + [TestName || {TestName,_,_,_,_} <- CachedTests], + dir_diff_tests(LogDirs, CachedTests, [], AllTestNames, [], []). + +dir_diff_tests([LogDir|LogDirs], CachedTests, NewAdded, DeletedTests, + ValidLast, InvalidLast) -> + TestName = filename:rootname(filename:basename(LogDir)), + Time = datestr_from_dirname(LogDir), + %% check if the test already exists in the cache + {New,DeletedTests1,ValidLast1,InvalidLast1} = + case lists:keysearch(TestName,1,CachedTests) of + {value,{_,_,_,{LastLogDir,_,_},_PrevLogDirs}} -> + LastLogTime = datestr_from_dirname(LastLogDir), + if Time > LastLogTime -> + %% this is a new test run, not in cache + {[LogDir|NewAdded], + lists:delete(TestName,DeletedTests), + ValidLast,[{TestName,LastLogDir}|InvalidLast]}; + Time == LastLogTime -> + %% this is the latest test run, already in cache + TDir = {TestName,LastLogDir}, + {NewAdded, + lists:delete(TestName,DeletedTests), + [TDir|ValidLast],InvalidLast}; + true -> + %% this is an old test run + {[], + lists:delete(TestName,DeletedTests), + ValidLast,[{TestName,LastLogDir}|InvalidLast]} + end; + _ -> + %% this is a test run for a new test, not in cache + {[LogDir|NewAdded], + DeletedTests,ValidLast,InvalidLast} + end, + dir_diff_tests(LogDirs, CachedTests, New, DeletedTests1, + ValidLast1,InvalidLast1); + +dir_diff_tests([], _CachedTests, NewAdded, DeletedTests, + ValidLast, InvalidLast) -> + %% We have to check if LastLogDir still exists or if it's been + %% deleted. InvalidLast contains all log dirs that should be deleted, + %% if not present in ValidLast. + InvalidLast1 = + lists:foldl(fun(TDir,IL) -> + case lists:member(TDir,ValidLast) of + true -> + [TD || TD <- IL, TD /= TDir]; + false -> + [TDir | [TD || TD <- IL, TD /= TDir]] + end + end, InvalidLast, InvalidLast), + + %% Collect all tests for which LastLogDir has been deleted. + DeletedTests1 = [T || {T,_} <- InvalidLast1] ++ DeletedTests, + + %% Make sure that directories for tests that are to be deleted are + %% saved in NewAdded so that tests don't disappear from the log if + %% older run dirs for them exist. + NewAdded1 = lists:map(fun({_TestName,RunDir}) -> + [TopDir,TestDir|_] = filename:split(RunDir), + filename:join(TopDir,TestDir) + end, InvalidLast1) ++ NewAdded, + + {NewAdded1,DeletedTests1}. + +delete_tests_from_cache(OldTests, LogCache=#log_cache{tests=Tests}) -> + Tests2 = lists:foldl(fun(T,Tests1) -> + lists:keydelete(T,1,Tests1) + end, Tests, OldTests), + LogCache#log_cache{tests = Tests2}. + +update_tests_in_cache(TempData) -> + case get(ct_log_cache) of + undefined -> + update_tests_in_cache(TempData,#log_cache{version = cache_vsn(), + tests=[]}); + SavedLogCache -> + update_tests_in_cache(TempData,binary_to_term(SavedLogCache)) + end. + +update_tests_in_cache(TempData,LogCache=#log_cache{tests=Tests}) -> + Cached1 = + if Tests == [] -> + []; + true -> + lists:foldl(fun({TestName,_,_,_,_},Cached) -> + lists:keydelete(TestName,1,Cached) + end, Tests, TempData) + end, + Tests1 = lists:keysort(1,TempData++Cached1), + CacheBin = term_to_binary(LogCache#log_cache{tests = Tests1}), + case {self(),whereis(?MODULE)} of + {_Pid,_Pid} -> + put(ct_log_cache,CacheBin); + _ -> + file:write_file(?log_cache_name,CacheBin) + end. + +%% +%% AllTestLogDirs = +%% [{TestName,[IxDir|IxDirs]} | ...] (non-cached), or +%% [{TestName,Label,Missing,{IxDir,Summary,URIs},IxDirs} | ...] (cached) +%% +make_all_suites_index1(When, AbsIndexName, AllTestLogDirs) -> IndexName = ?index_name, if When == start -> ok; true -> io:put_chars("Updating " ++ AbsIndexName ++ "... ") end, - case catch make_all_suites_index2(IndexName, AllLogDirs) of + case catch make_all_suites_index2(IndexName, AllTestLogDirs) of {'EXIT', Reason} -> io:put_chars("CRASHED while updating " ++ AbsIndexName ++ "!\n"), io:format("~p~n", [Reason]), @@ -1923,15 +2354,15 @@ make_all_suites_index1(When, AbsIndexName, AllLogDirs) -> io:put_chars("FAILED while updating " ++ AbsIndexName ++ "\n"), io:format("~p~n", [Reason]), {error, Reason}; - {ok,CacheData} -> + {ok,TempData} -> case When of start -> ct_util:set_testdata_async({test_index,{AbsIndexName, - CacheData}}), - ok; + TempData}}), + TempData; _ -> io:put_chars("done\n"), - ok + TempData end; Err -> io:format("Unknown internal error while updating ~ts. " @@ -1941,21 +2372,57 @@ make_all_suites_index1(When, AbsIndexName, AllLogDirs) -> end. make_all_suites_index2(IndexName, AllTestLogDirs) -> - {ok,Index0,_Totals,CacheData} = + {ok,Index0,_Totals,TempData} = make_all_suites_index3(AllTestLogDirs, all_suites_index_header(), 0, 0, 0, 0, 0, [], []), Index = [Index0|index_footer()], case force_write_file(IndexName, unicode:characters_to_binary(Index)) of ok -> - {ok,CacheData}; + {ok,TempData}; {error, Reason} -> {error,{index_write_error, Reason}} end. +%% +%% AllTestLogDirs = [{TestName,Label,Missing,{LogDir,Summary,URIs},OldDirs}] +%% Summary = {Succ,Fail,UserSkip,AutoSkip} | error +%% URIs = {CtRunLogURI,LogFileURI,CrashDumpURI} | undefined +%% +%% this clause is for handling entries in the log cache +make_all_suites_index3([IxEntry = {TestName,Label,Missing, + {LastLogDir,Summary,URIs},OldDirs} | Rest], + Result, TotSucc, TotFail, UserSkip, AutoSkip, TotNotBuilt, + Labels, TempData) -> + [EntryDir|_] = filename:split(LastLogDir), + Labels1 = [{EntryDir,Label}|Labels], + case Summary of + {Succ,Fail,USkip,ASkip} -> + All = {true,OldDirs}, + NotBuilt = not_built(TestName, LastLogDir, All, Missing), + + {Result1,_} = make_one_index_entry1(TestName, LastLogDir, Label, + Succ, Fail, USkip, ASkip, + NotBuilt, All, temp, URIs), + + AutoSkip1 = case catch AutoSkip+ASkip of + {'EXIT',_} -> undefined; + Res -> Res + end, + make_all_suites_index3(Rest, [Result|Result1], TotSucc+Succ, + TotFail+Fail, UserSkip+USkip, AutoSkip1, + TotNotBuilt+NotBuilt, Labels1, + [IxEntry|TempData]); + error -> + make_all_suites_index3(Rest, Result, TotSucc, TotFail, + UserSkip, AutoSkip, TotNotBuilt, Labels1, + [IxEntry|TempData]) + end; + +%% this clause is for handling non-cached directories make_all_suites_index3([{TestName,[LastLogDir|OldDirs]}|Rest], Result, TotSucc, TotFail, UserSkip, AutoSkip, TotNotBuilt, - Labels, CacheData) -> + Labels, TempData) -> [EntryDir|_] = filename:split(LastLogDir), Missing = case file:read_file(filename:join(EntryDir, ?missing_suites_info)) of @@ -1972,37 +2439,49 @@ make_all_suites_index3([{TestName,[LastLogDir|OldDirs]}|Rest], Lbl -> {Lbl,Labels} end, - case make_one_index_entry(TestName, LastLogDir, Label, {true,OldDirs}, Missing) of - {Result1,Succ,Fail,USkip,ASkip,NotBuilt} -> + case make_one_index_entry(TestName, LastLogDir, Label, + {true,OldDirs}, Missing, undefined) of + {Result1,Succ,Fail,USkip,ASkip,NotBuilt,URIs} -> %% for backwards compatibility AutoSkip1 = case catch AutoSkip+ASkip of {'EXIT',_} -> undefined; Res -> Res end, IxEntry = {TestName,Label,Missing, - {LastLogDir,{Succ,Fail,USkip,ASkip}},OldDirs}, + {LastLogDir,{Succ,Fail,USkip,ASkip},URIs},OldDirs}, + make_all_suites_index3(Rest, [Result|Result1], TotSucc+Succ, TotFail+Fail, UserSkip+USkip, AutoSkip1, TotNotBuilt+NotBuilt, Labels1, - [IxEntry|CacheData]); + [IxEntry|TempData]); error -> - IxEntry = {TestName,Label,Missing,{LastLogDir,error},OldDirs}, + IxEntry = {TestName,Label,Missing, + {LastLogDir,error,undefined},OldDirs}, make_all_suites_index3(Rest, Result, TotSucc, TotFail, UserSkip, AutoSkip, TotNotBuilt, Labels1, - [IxEntry|CacheData]) + [IxEntry|TempData]) end; + +%% something wrong with this test dir, ignore +make_all_suites_index3([_|Rest], Result, TotSucc, TotFail, UserSkip, AutoSkip, + TotNotBuilt, Labels, TempData) -> + make_all_suites_index3(Rest, Result, TotSucc, TotFail, + UserSkip, AutoSkip, TotNotBuilt, Labels, + TempData); + make_all_suites_index3([], Result, TotSucc, TotFail, UserSkip, AutoSkip, - TotNotBuilt, _, CacheData) -> - {ok, [Result|total_row(TotSucc, TotFail, UserSkip, AutoSkip, TotNotBuilt,true)], - {TotSucc,TotFail,UserSkip,AutoSkip,TotNotBuilt}, lists:reverse(CacheData)}. + TotNotBuilt, _, TempData) -> + {ok, [Result|total_row(TotSucc, TotFail, UserSkip, AutoSkip, + TotNotBuilt,true)], + {TotSucc,TotFail,UserSkip,AutoSkip,TotNotBuilt}, lists:reverse(TempData)}. -make_all_suites_ix_cached(AbsIndexName, NewTestData, Label, AllTestLogDirs) -> +make_all_suites_ix_temp(AbsIndexName, NewTestData, Label, AllTestLogDirs) -> AllTestLogDirs1 = insert_new_test_data(NewTestData, Label, AllTestLogDirs), IndexDir = filename:dirname(AbsIndexName), - Index0 = make_all_suites_ix_cached1(AllTestLogDirs1, - all_suites_index_header(IndexDir), - 0, 0, 0, 0, 0), + Index0 = make_all_suites_ix_temp1(AllTestLogDirs1, + all_suites_index_header(IndexDir), + 0, 0, 0, 0, 0), Index = [Index0|index_footer()], case force_write_file(AbsIndexName, unicode:characters_to_binary(Index)) of ok -> @@ -2014,51 +2493,94 @@ make_all_suites_ix_cached(AbsIndexName, NewTestData, Label, AllTestLogDirs) -> insert_new_test_data({NewTestName,NewTestDir}, NewLabel, AllTestLogDirs) -> AllTestLogDirs1 = case lists:keysearch(NewTestName, 1, AllTestLogDirs) of - {value,{_,_,_,{LastLogDir,_},OldDirs}} -> - [{NewTestName,NewLabel,[],{NewTestDir,{0,0,0,0}}, + {value,{_,_,_,{LastLogDir,_,_},OldDirs}} -> + [{NewTestName,NewLabel,[],{NewTestDir,{0,0,0,0},undefined}, [LastLogDir|OldDirs]} | lists:keydelete(NewTestName, 1, AllTestLogDirs)]; false -> - [{NewTestName,NewLabel,[],{NewTestDir,{0,0,0,0}},[]} | + [{NewTestName,NewLabel,[],{NewTestDir,{0,0,0,0},undefined},[]} | AllTestLogDirs] end, lists:keysort(1, AllTestLogDirs1). -make_all_suites_ix_cached1([{TestName,Label,Missing,LastLogDirData,OldDirs}|Rest], - Result, TotSucc, TotFail, UserSkip, AutoSkip, - TotNotBuilt) -> - - case make_one_ix_entry_cached(TestName, LastLogDirData, - Label, {true,OldDirs}, Missing) of - {Result1,Succ,Fail,USkip,ASkip,NotBuilt} -> +make_all_suites_ix_temp1([{TestName,Label,Missing,LastLogDirData,OldDirs}|Rest], + Result, TotSucc, TotFail, UserSkip, AutoSkip, + TotNotBuilt) -> + case make_one_ix_entry_temp(TestName, LastLogDirData, + Label, {true,OldDirs}, Missing) of + {Result1,Succ,Fail,USkip,ASkip,NotBuilt,_URIs} -> %% for backwards compatibility AutoSkip1 = case catch AutoSkip+ASkip of {'EXIT',_} -> undefined; Res -> Res end, - make_all_suites_ix_cached1(Rest, [Result|Result1], TotSucc+Succ, - TotFail+Fail, UserSkip+USkip, AutoSkip1, - TotNotBuilt+NotBuilt); + make_all_suites_ix_temp1(Rest, [Result|Result1], TotSucc+Succ, + TotFail+Fail, UserSkip+USkip, AutoSkip1, + TotNotBuilt+NotBuilt); error -> - make_all_suites_ix_cached1(Rest, Result, TotSucc, TotFail, - UserSkip, AutoSkip, TotNotBuilt) + make_all_suites_ix_temp1(Rest, Result, TotSucc, TotFail, + UserSkip, AutoSkip, TotNotBuilt) end; -make_all_suites_ix_cached1([], Result, TotSucc, TotFail, UserSkip, AutoSkip, - TotNotBuilt) -> +make_all_suites_ix_temp1([], Result, TotSucc, TotFail, UserSkip, AutoSkip, + TotNotBuilt) -> [Result|total_row(TotSucc, TotFail, UserSkip, AutoSkip, TotNotBuilt, true)]. -make_one_ix_entry_cached(TestName, {LogDir,Summary}, Label, All, Missing) -> +make_one_ix_entry_temp(TestName, {LogDir,Summary,URIs}, Label, All, Missing) -> case Summary of {Succ,Fail,UserSkip,AutoSkip} -> NotBuilt = not_built(TestName, LogDir, All, Missing), - NewResult = make_one_index_entry1(TestName, LogDir, Label, - Succ, Fail, UserSkip, AutoSkip, - NotBuilt, All, cached), - {NewResult,Succ,Fail,UserSkip,AutoSkip,NotBuilt}; + {NewResult,URIs1} = make_one_index_entry1(TestName, LogDir, Label, + Succ, Fail, + UserSkip, AutoSkip, + NotBuilt, All, temp, URIs), + {NewResult,Succ,Fail,UserSkip,AutoSkip,NotBuilt,URIs1}; error -> error end. +%%%----------------------------------------------------------------- +%%% +get_cache_data({ok,CacheBin}) -> + case binary_to_term(CacheBin) of + CacheRec when is_record(CacheRec,log_cache) -> + %% make sure we don't use a cache on old format + case is_correct_cache_vsn(CacheRec) of + true -> + {ok,CacheRec}; + false -> + file:delete(?log_cache_name), + {error,old_cache_file} + end; + _ -> + file:delete(?log_cache_name), + {error,invalid_cache_file} + end; +get_cache_data(NoCache) -> + NoCache. + +cache_vsn() -> + application:load(common_test), + case application:get_key(common_test,vsn) of + {ok,VSN} -> + VSN; + _ -> + EbinDir = filename:dirname(code:which(ct)), + VSNfile = filename:join([EbinDir,"..","vsn.mk"]), + case file:read_file(VSNfile) of + {ok,Bin} -> + [_,VSN] = string:tokens(binary_to_list(Bin),[$=,$\n,$ ]), + VSN; + _ -> + undefined + end + end. + +is_correct_cache_vsn(#log_cache{version = CVSN}) -> + case cache_vsn() of + CVSN -> true; + _ -> false + end. + %%----------------------------------------------------------------- %% Remove log files. %% Cwd should always be set to the root logdir when finished. diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl index 57cfab532e..41d53c7b43 100644 --- a/lib/common_test/src/ct_run.erl +++ b/lib/common_test/src/ct_run.erl @@ -329,6 +329,13 @@ script_start1(Parent, Args) -> application:set_env(common_test, basic_html, true), true end, + %% disable_log_cache - used by ct_logs + case proplists:get_value(disable_log_cache, Args) of + undefined -> + application:set_env(common_test, disable_log_cache, false); + _ -> + application:set_env(common_test, disable_log_cache, true) + end, Opts = #opts{label = Label, profile = Profile, vts = Vts, shell = Shell, @@ -1039,6 +1046,13 @@ run_test2(StartOpts) -> BasicHtmlBool end, + case proplists:get_value(disable_log_cache, StartOpts) of + undefined -> + application:set_env(common_test, disable_log_cache, false); + DisableCacheBool -> + application:set_env(common_test, disable_log_cache, DisableCacheBool) + end, + %% stepped execution Step = get_start_opt(step, value, StartOpts), diff --git a/lib/common_test/test/ct_test_support.erl b/lib/common_test/test/ct_test_support.erl index 70dd087358..6bcac12326 100644 --- a/lib/common_test/test/ct_test_support.erl +++ b/lib/common_test/test/ct_test_support.erl @@ -224,11 +224,38 @@ get_opts(Config) -> %%%----------------------------------------------------------------- %%% -run(Opts, Config) when is_list(Opts) -> +run(Opts0, Config) when is_list(Opts0) -> + Opts = + %% read (and override) opts from env variable, the form expected: + %% "[{some_key1,SomeVal2}, {some_key2,SomeVal2}]" + case os:getenv("CT_TEST_OPTS") of + false -> Opts0; + "" -> Opts0; + Terms -> + case erl_scan:string(Terms++".", 0) of + {ok,Tokens,_} -> + case erl_parse:parse_term(Tokens) of + {ok,OROpts} -> + Override = + fun(O={Key,_}, Os) -> + io:format(user, "ADDING START " + "OPTION: ~p~n", [O]), + [O | lists:keydelete(Key, 1, Os)] + end, + lists:foldl(Override, Opts0, OROpts); + _ -> + Opts0 + end; + _ -> + Opts0 + end + end, + %% use ct interface CtRunTestResult=run_ct_run_test(Opts,Config), %% use run_test interface (simulated) ExitStatus=run_ct_script_start(Opts,Config), + check_result(CtRunTestResult,ExitStatus,Opts). run_ct_run_test(Opts,Config) -> @@ -236,9 +263,10 @@ run_ct_run_test(Opts,Config) -> Level = proplists:get_value(trace_level, Config), test_server:format(Level, "~n[RUN #1] Calling ct:run_test(~p) on ~p~n", [Opts, CTNode]), + T0 = now(), CtRunTestResult = rpc:call(CTNode, ct, run_test, [Opts]), - test_server:format(Level, "~n[RUN #1] Got return value ~p~n", - [CtRunTestResult]), + test_server:format(Level, "~n[RUN #1] Got return value ~p after ~p ms~n", + [CtRunTestResult,trunc(timer:now_diff(now(), T0)/1000)]), case rpc:call(CTNode, erlang, whereis, [ct_util_server]) of undefined -> ok; @@ -261,9 +289,10 @@ run_ct_script_start(Opts, Config) -> [common_test, run_test_start_opts, Opts1]), test_server:format(Level, "[RUN #2] Calling ct_run:script_start() on ~p~n", [CTNode]), + T0 = now(), ExitStatus = rpc:call(CTNode, ct_run, script_start, []), - test_server:format(Level, "[RUN #2] Got exit status value ~p~n", - [ExitStatus]), + test_server:format(Level, "[RUN #2] Got exit status value ~p after ~p ms~n", + [ExitStatus,trunc(timer:now_diff(now(), T0)/1000)]), ExitStatus. check_result({_Ok,Failed,{_UserSkipped,_AutoSkipped}},1,_Opts) diff --git a/lib/debugger/src/dbg_istk.erl b/lib/debugger/src/dbg_istk.erl index c6922a80e4..ced42a5f9f 100644 --- a/lib/debugger/src/dbg_istk.erl +++ b/lib/debugger/src/dbg_istk.erl @@ -78,7 +78,7 @@ push(Bs, #ieval{level=Le,module=Mod,function=Name, pop() -> case get(trace_stack) of false -> ignore; - _ -> % all ¦ no_tail + _ -> % all | no_tail case get(?STACK) of [_Entry|Entries] -> put(?STACK, Entries); diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/custom_sup.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/custom_sup.erl index 8ec84d798f..7eb4c6ec97 100644 --- a/lib/dialyzer/test/behaviour_SUITE_data/src/custom_sup.erl +++ b/lib/dialyzer/test/behaviour_SUITE_data/src/custom_sup.erl @@ -1,3 +1,5 @@ +%%% -*- coding: utf-8 -*- +%%% %%% Dialyzer was giving a warning with this input because of a bug in the %%% substitution of remote types in specs. Remote types in the first element of %%% a tuple would not update the tuple's tag set and we could end up with a diff --git a/lib/inets/src/http_server/httpd_manager.erl b/lib/inets/src/http_server/httpd_manager.erl index 672a70a394..c83d06a158 100644 --- a/lib/inets/src/http_server/httpd_manager.erl +++ b/lib/inets/src/http_server/httpd_manager.erl @@ -691,11 +691,11 @@ handle_unblock(S, FromA) -> handle_unblock(S, _FromA, unblocked) -> {ok,S}; handle_unblock(S, FromA, _AdminState) -> - stop_block_tmr(S#state.blocking_tmr), case S#state.blocking_tmr of - {_Tmr,FromB,Ref} -> + {Tmr,FromB,Ref} -> %% Another process is trying to unblock %% Inform the blocker + stop_block_tmr(Tmr), FromB ! {block_reply, {error,{unblocked,FromA}},Ref}; _ -> ok diff --git a/lib/kernel/test/global_SUITE_data/global_trace.erl b/lib/kernel/test/global_SUITE_data/global_trace.erl index 4f253baac4..ddbe608c0a 100644 --- a/lib/kernel/test/global_SUITE_data/global_trace.erl +++ b/lib/kernel/test/global_SUITE_data/global_trace.erl @@ -1,3 +1,4 @@ +%% -*- coding: utf-8 -*- %% %% %CopyrightBegin% %% @@ -122,12 +123,12 @@ state(Else) -> %%% {ops,Ops}] %%% NewKnown = Known ++ AddedNodes %%% AddedNodes = NewNodes -- Known -%%% NewNodes �r h�r den man f�rhandlat med plus de noder den k�nner till. +%%% NewNodes är här den man förhandlat med plus de noder den känner till. %%% {added, AddedNodes}, Extra = [{ops,Ops}] %%% NewKnown = Known ++ AddedNodes -%%% Den (passiva) noden f�r Nodes som �r NewNodes -%%% hos den f�rhandlande. Sedan: AddedNodes = (Nodes -- Known) -- [node()]. -%%% Det �r som hos f�rhandlaren. +%%% Den (passiva) noden får Nodes som är NewNodes +%%% hos den förhandlande. Sedan: AddedNodes = (Nodes -- Known) -- [node()]. +%%% Det är som hos förhandlaren. %%% {nodes_changed, {New,Old}} %%% Every now and then the list [node() | nodes()] is checked for updates. %%% New are the nodes that global does not know of (yet). diff --git a/lib/public_key/test/erl_make_certs.erl b/lib/public_key/test/erl_make_certs.erl index 95e288cd71..897cf2f350 100644 --- a/lib/public_key/test/erl_make_certs.erl +++ b/lib/public_key/test/erl_make_certs.erl @@ -354,13 +354,13 @@ gen_dsa2(LSize, NSize) -> X0 = prime(LSize), P0 = prime((LSize div 2) +1), - %% Choose L-bit prime modulus P such that p–1 is a multiple of q. + %% Choose L-bit prime modulus P such that p-1 is a multiple of q. case dsa_search(X0 div (2*Q*P0), P0, Q, 1000) of error -> gen_dsa2(LSize, NSize); P -> G = crypto:mod_exp(2, (P-1) div Q, P), % Choose G a number whose multiplicative order modulo p is q. - %% such that This may be done by setting g = h^(p–1)/q mod p, commonly h=2 is used. + %% such that This may be done by setting g = h^(p-1)/q mod p, commonly h=2 is used. X = prime(20), %% Choose x by some random method, where 0 < x < q. Y = crypto:mod_exp(G, X, P), %% Calculate y = g^x mod p. diff --git a/lib/runtime_tools/src/ttb_autostart.erl b/lib/runtime_tools/src/ttb_autostart.erl index 4c6971c119..5339507cec 100644 --- a/lib/runtime_tools/src/ttb_autostart.erl +++ b/lib/runtime_tools/src/ttb_autostart.erl @@ -1,3 +1,4 @@ +%%%-*- coding: utf-8 -*- %%%------------------------------------------------------------------- %%% File : ttb_autostart.erl %%% Author : Bartłomiej Puzoń <[email protected]> diff --git a/lib/ssl/test/erl_make_certs.erl b/lib/ssl/test/erl_make_certs.erl index 5b92e551a5..71aa985c4f 100644 --- a/lib/ssl/test/erl_make_certs.erl +++ b/lib/ssl/test/erl_make_certs.erl @@ -349,13 +349,13 @@ gen_dsa2(LSize, NSize) -> X0 = prime(LSize), P0 = prime((LSize div 2) +1), - %% Choose L-bit prime modulus P such that p–1 is a multiple of q. + %% Choose L-bit prime modulus P such that p-1 is a multiple of q. case dsa_search(X0 div (2*Q*P0), P0, Q, 1000) of error -> gen_dsa2(LSize, NSize); P -> G = crypto:mod_exp(2, (P-1) div Q, P), % Choose G a number whose multiplicative order modulo p is q. - %% such that This may be done by setting g = h^(p–1)/q mod p, commonly h=2 is used. + %% such that This may be done by setting g = h^(p-1)/q mod p, commonly h=2 is used. X = prime(20), %% Choose x by some random method, where 0 < x < q. Y = crypto:mod_exp(G, X, P), %% Calculate y = g^x mod p. diff --git a/lib/stdlib/doc/src/unicode_usage.xml b/lib/stdlib/doc/src/unicode_usage.xml index c5d476e54b..1f64b38554 100644 --- a/lib/stdlib/doc/src/unicode_usage.xml +++ b/lib/stdlib/doc/src/unicode_usage.xml @@ -625,6 +625,7 @@ Eshell V5.10.1 (abort with ^G) </section> <section> <title>Unicode File Names</title> + <marker id="unicode_file_names"/> <p>Most modern operating systems support Unicode file names in some way or another. There are several different ways to do this and Erlang by default treats the different approaches differently:</p> diff --git a/lib/stdlib/test/erl_eval_SUITE.erl b/lib/stdlib/test/erl_eval_SUITE.erl index 7ff4c81ea6..18ec17a4bf 100644 --- a/lib/stdlib/test/erl_eval_SUITE.erl +++ b/lib/stdlib/test/erl_eval_SUITE.erl @@ -1,3 +1,4 @@ +%% -*- coding: utf-8 -*- %% %% %CopyrightBegin% %% @@ -992,7 +993,7 @@ otp_10622(Config) when is_list(Config) -> <<0>>), check(fun() -> <<"\x{aa}ff"/utf8>> = <<"\x{aa}ff"/utf8>> end, "<<\"\\x{aa}ff\"/utf8>> = <<\"\\x{aa}ff\"/utf8>>. ", - <<"�\xaaff">>), + <<"Â\xaaff">>), %% The same bug as last example: check(fun() -> case <<"foo"/utf8>> of <<"foo"/utf8>> -> true diff --git a/lib/stdlib/test/qlc_SUITE_data/join_info_compat.erl b/lib/stdlib/test/qlc_SUITE_data/join_info_compat.erl index e0db132c47..b93b907392 100644 --- a/lib/stdlib/test/qlc_SUITE_data/join_info_compat.erl +++ b/lib/stdlib/test/qlc_SUITE_data/join_info_compat.erl @@ -1,3 +1,4 @@ +%% -*- coding: utf-8 -*- %% %% %CopyrightBegin% %% @@ -515,7 +516,7 @@ create_handle() -> $.:8/integer-unit:1-unsigned-big, $x:8/integer-unit:1-unsigned-big, $\234:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ë:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $N:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, @@ -523,16 +524,16 @@ create_handle() -> $-:8/integer-unit:1-unsigned-big, $):8/integer-unit:1-unsigned-big, $-:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $È:8/integer-unit:1-unsigned-big, $I:8/integer-unit:1-unsigned-big, $M:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $ä:8/integer-unit:1-unsigned-big, + $Ê:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ê:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, $\n:8/integer-unit:1-unsigned-big, $0:8/integer-unit:1-unsigned-big, @@ -541,19 +542,19 @@ create_handle() -> $\026:8/integer-unit:1-unsigned-big, $%:8/integer-unit:1-unsigned-big, $r:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $¥:8/integer-unit:1-unsigned-big, $0:8/integer-unit:1-unsigned-big, $0:8/integer-unit:1-unsigned-big, $F:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $ :8/integer-unit:1-unsigned-big, + $ð:8/integer-unit:1-unsigned-big, $":8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $³:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $þ:8/integer-unit:1-unsigned-big, + $Ì:8/integer-unit:1-unsigned-big, $\n:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big>>, + $É:8/integer-unit:1-unsigned-big>>, <<$\203:8/integer-unit:1-unsigned-big, $P:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, @@ -562,7 +563,7 @@ create_handle() -> $<:8/integer-unit:1-unsigned-big, $x:8/integer-unit:1-unsigned-big, $\234:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ë:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $N:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, @@ -570,16 +571,16 @@ create_handle() -> $-:8/integer-unit:1-unsigned-big, $):8/integer-unit:1-unsigned-big, $-:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $È:8/integer-unit:1-unsigned-big, $I:8/integer-unit:1-unsigned-big, $M:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $ä:8/integer-unit:1-unsigned-big, + $Ê:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Î:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, $\n:8/integer-unit:1-unsigned-big, $0:8/integer-unit:1-unsigned-big, @@ -588,22 +589,22 @@ create_handle() -> $\026:8/integer-unit:1-unsigned-big, $%:8/integer-unit:1-unsigned-big, $r:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $¥:8/integer-unit:1-unsigned-big, $0:8/integer-unit:1-unsigned-big, $0:8/integer-unit:1-unsigned-big, $::8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $¡:8/integer-unit:1-unsigned-big, + $ð:8/integer-unit:1-unsigned-big, $":8/integer-unit:1-unsigned-big, $P:8/integer-unit:1-unsigned-big, $x:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $ñ:8/integer-unit:1-unsigned-big, $Y:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $ª:8/integer-unit:1-unsigned-big, $9:8/integer-unit:1-unsigned-big, $\r:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big>>, + $ý:8/integer-unit:1-unsigned-big>>, <<$\203:8/integer-unit:1-unsigned-big, $P:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, @@ -612,51 +613,51 @@ create_handle() -> $I:8/integer-unit:1-unsigned-big, $x:8/integer-unit:1-unsigned-big, $\234:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ë:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $M:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ê:8/integer-unit:1-unsigned-big, $/:8/integer-unit:1-unsigned-big, $H:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $ä:8/integer-unit:1-unsigned-big, $N:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $¶:8/integer-unit:1-unsigned-big, + $µ:8/integer-unit:1-unsigned-big, + $²:8/integer-unit:1-unsigned-big, + $Í:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $\006:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ò:8/integer-unit:1-unsigned-big, $e:8/integer-unit:1-unsigned-big, $\211:8/integer-unit:1-unsigned-big, $E:8/integer-unit:1-unsigned-big, $\s:8/integer-unit:1-unsigned-big, $>:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $£:8/integer-unit:1-unsigned-big, $\023:8/integer-unit:1-unsigned-big, $\210:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ç:8/integer-unit:1-unsigned-big, $\232:8/integer-unit:1-unsigned-big, $\226:8/integer-unit:1-unsigned-big, $\223:8/integer-unit:1-unsigned-big, $\237:8/integer-unit:1-unsigned-big, $X:8/integer-unit:1-unsigned-big, $\222:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $È:8/integer-unit:1-unsigned-big, $\235:8/integer-unit:1-unsigned-big, $l:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $¨:8/integer-unit:1-unsigned-big, $g:8/integer-unit:1-unsigned-big, $i:8/integer-unit:1-unsigned-big, $d:8/integer-unit:1-unsigned-big, $\200:8/integer-unit:1-unsigned-big, $\001:8/integer-unit:1-unsigned-big, $R:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $µ:8/integer-unit:1-unsigned-big, $\r:8/integer-unit:1-unsigned-big, $\214:8/integer-unit:1-unsigned-big, $\030:8/integer-unit:1-unsigned-big, @@ -664,7 +665,7 @@ create_handle() -> $\000:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, $c:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ö:8/integer-unit:1-unsigned-big, $\017:8/integer-unit:1-unsigned-big, $=:8/integer-unit:1-unsigned-big>>, <<$\203:8/integer-unit:1-unsigned-big, @@ -708,24 +709,24 @@ create_handle() -> $*:8/integer-unit:1-unsigned-big, $x:8/integer-unit:1-unsigned-big, $\234:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ë:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $M:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ê:8/integer-unit:1-unsigned-big, $/:8/integer-unit:1-unsigned-big, $H:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $ä:8/integer-unit:1-unsigned-big, $\005:8/integer-unit:1-unsigned-big, $R:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $¶:8/integer-unit:1-unsigned-big, + $¶:8/integer-unit:1-unsigned-big, $\031:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ì:8/integer-unit:1-unsigned-big, $):8/integer-unit:1-unsigned-big, $\f:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ì:8/integer-unit:1-unsigned-big, $e:8/integer-unit:1-unsigned-big, $\211:8/integer-unit:1-unsigned-big, $E:8/integer-unit:1-unsigned-big, @@ -737,7 +738,7 @@ create_handle() -> $/:8/integer-unit:1-unsigned-big, $\022:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ì:8/integer-unit:1-unsigned-big, $\205:8/integer-unit:1-unsigned-big, $\t:8/integer-unit:1-unsigned-big, $\216:8/integer-unit:1-unsigned-big>>, @@ -749,33 +750,33 @@ create_handle() -> $j:8/integer-unit:1-unsigned-big, $x:8/integer-unit:1-unsigned-big, $\234:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ë:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $I:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $I:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Î:8/integer-unit:1-unsigned-big, + $Ï:8/integer-unit:1-unsigned-big, $+:8/integer-unit:1-unsigned-big, $N:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $ú:8/integer-unit:1-unsigned-big, + $ÿ:8/integer-unit:1-unsigned-big, + $ÿ:8/integer-unit:1-unsigned-big, + $ÿ:8/integer-unit:1-unsigned-big, + $·:8/integer-unit:1-unsigned-big, $\f:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $æ:8/integer-unit:1-unsigned-big, $\024:8/integer-unit:1-unsigned-big, $\006:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ö:8/integer-unit:1-unsigned-big, $\222:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ò:8/integer-unit:1-unsigned-big, $\202:8/integer-unit:1-unsigned-big, $\234:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ô:8/integer-unit:1-unsigned-big, $D:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $®:8/integer-unit:1-unsigned-big, $\034:8/integer-unit:1-unsigned-big, $\006:8/integer-unit:1-unsigned-big, $\006:8/integer-unit:1-unsigned-big, @@ -791,7 +792,7 @@ create_handle() -> $W:8/integer-unit:1-unsigned-big, $\n:8/integer-unit:1-unsigned-big, $\003:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $£:8/integer-unit:1-unsigned-big, $\023:8/integer-unit:1-unsigned-big, $\n:8/integer-unit:1-unsigned-big, $/:8/integer-unit:1-unsigned-big, @@ -800,18 +801,18 @@ create_handle() -> $\027:8/integer-unit:1-unsigned-big, $\237:8/integer-unit:1-unsigned-big, $\205:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $¤:8/integer-unit:1-unsigned-big, $\227:8/integer-unit:1-unsigned-big, $\007:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $¤:8/integer-unit:1-unsigned-big, $\227:8/integer-unit:1-unsigned-big, $\021:8/integer-unit:1-unsigned-big, $.:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ï:8/integer-unit:1-unsigned-big, $\003:8/integer-unit:1-unsigned-big, $\224:8/integer-unit:1-unsigned-big, $\217:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ì:8/integer-unit:1-unsigned-big, $\002:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, $\203:8/integer-unit:1-unsigned-big, @@ -1398,7 +1399,7 @@ lookup_handle() -> $.:8/integer-unit:1-unsigned-big, $x:8/integer-unit:1-unsigned-big, $\234:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ë:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $N:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, @@ -1406,16 +1407,16 @@ lookup_handle() -> $-:8/integer-unit:1-unsigned-big, $):8/integer-unit:1-unsigned-big, $-:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $È:8/integer-unit:1-unsigned-big, $I:8/integer-unit:1-unsigned-big, $M:8/integer-unit:1-unsigned-big, $\024:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ì:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ê:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, $\n:8/integer-unit:1-unsigned-big, $0:8/integer-unit:1-unsigned-big, @@ -1424,19 +1425,19 @@ lookup_handle() -> $\026:8/integer-unit:1-unsigned-big, $%:8/integer-unit:1-unsigned-big, $\n:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $¦:8/integer-unit:1-unsigned-big, $0:8/integer-unit:1-unsigned-big, $0:8/integer-unit:1-unsigned-big, $F:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $ :8/integer-unit:1-unsigned-big, + $ð:8/integer-unit:1-unsigned-big, $":8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $³:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, $\206:8/integer-unit:1-unsigned-big, $\n:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big>>, + $Þ:8/integer-unit:1-unsigned-big>>, <<$\203:8/integer-unit:1-unsigned-big, $P:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, @@ -1445,7 +1446,7 @@ lookup_handle() -> $.:8/integer-unit:1-unsigned-big, $x:8/integer-unit:1-unsigned-big, $\234:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ë:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $N:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, @@ -1453,16 +1454,16 @@ lookup_handle() -> $-:8/integer-unit:1-unsigned-big, $):8/integer-unit:1-unsigned-big, $-:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $È:8/integer-unit:1-unsigned-big, $I:8/integer-unit:1-unsigned-big, $M:8/integer-unit:1-unsigned-big, $\024:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ì:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ê:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, $\n:8/integer-unit:1-unsigned-big, $0:8/integer-unit:1-unsigned-big, @@ -1471,19 +1472,19 @@ lookup_handle() -> $\026:8/integer-unit:1-unsigned-big, $%:8/integer-unit:1-unsigned-big, $\n:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $¦:8/integer-unit:1-unsigned-big, $0:8/integer-unit:1-unsigned-big, $0:8/integer-unit:1-unsigned-big, $F:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $ :8/integer-unit:1-unsigned-big, + $ð:8/integer-unit:1-unsigned-big, + $â:8/integer-unit:1-unsigned-big, + $³:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, $\222:8/integer-unit:1-unsigned-big, $\n:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big>>, + $ä:8/integer-unit:1-unsigned-big>>, <<$\203:8/integer-unit:1-unsigned-big, $h:8/integer-unit:1-unsigned-big, $\003:8/integer-unit:1-unsigned-big, @@ -1525,25 +1526,25 @@ lookup_handle() -> $+:8/integer-unit:1-unsigned-big, $x:8/integer-unit:1-unsigned-big, $\234:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ë:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $M:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ê:8/integer-unit:1-unsigned-big, $/:8/integer-unit:1-unsigned-big, $H:8/integer-unit:1-unsigned-big, $\024:8/integer-unit:1-unsigned-big, $N:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $¶:8/integer-unit:1-unsigned-big, + $µ:8/integer-unit:1-unsigned-big, + $²:8/integer-unit:1-unsigned-big, + $Í:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $\006:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ò:8/integer-unit:1-unsigned-big, $e:8/integer-unit:1-unsigned-big, $\211:8/integer-unit:1-unsigned-big, $E:8/integer-unit:1-unsigned-big, @@ -1555,10 +1556,10 @@ lookup_handle() -> $/:8/integer-unit:1-unsigned-big, $\022:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $×:8/integer-unit:1-unsigned-big, $\227:8/integer-unit:1-unsigned-big, $\t:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big>>, + $Û:8/integer-unit:1-unsigned-big>>, <<$\203:8/integer-unit:1-unsigned-big, $P:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, @@ -1567,33 +1568,33 @@ lookup_handle() -> $\\:8/integer-unit:1-unsigned-big, $x:8/integer-unit:1-unsigned-big, $\234:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ë:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $I:8/integer-unit:1-unsigned-big, $a:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $I:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Î:8/integer-unit:1-unsigned-big, + $Ï:8/integer-unit:1-unsigned-big, $+:8/integer-unit:1-unsigned-big, $N:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $ú:8/integer-unit:1-unsigned-big, + $ÿ:8/integer-unit:1-unsigned-big, + $ÿ:8/integer-unit:1-unsigned-big, + $ÿ:8/integer-unit:1-unsigned-big, + $û:8/integer-unit:1-unsigned-big, $\f:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $æ:8/integer-unit:1-unsigned-big, $\024:8/integer-unit:1-unsigned-big, $\006:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ö:8/integer-unit:1-unsigned-big, $\222:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ò:8/integer-unit:1-unsigned-big, $\202:8/integer-unit:1-unsigned-big, $\234:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ô:8/integer-unit:1-unsigned-big, $D:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Á:8/integer-unit:1-unsigned-big, $\034:8/integer-unit:1-unsigned-big, $\006:8/integer-unit:1-unsigned-big, $\006:8/integer-unit:1-unsigned-big, @@ -1605,7 +1606,7 @@ lookup_handle() -> $Y:8/integer-unit:1-unsigned-big, $b:8/integer-unit:1-unsigned-big, $Q:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $¢:8/integer-unit:1-unsigned-big, $`:8/integer-unit:1-unsigned-big, $\n:8/integer-unit:1-unsigned-big, $\003:8/integer-unit:1-unsigned-big, @@ -1616,7 +1617,7 @@ lookup_handle() -> $>:8/integer-unit:1-unsigned-big, $\v:8/integer-unit:1-unsigned-big, $I:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $µ:8/integer-unit:1-unsigned-big, $\020:8/integer-unit:1-unsigned-big, $H:8/integer-unit:1-unsigned-big, $5:8/integer-unit:1-unsigned-big, @@ -1630,7 +1631,7 @@ lookup_handle() -> $\005:8/integer-unit:1-unsigned-big, $\000:8/integer-unit:1-unsigned-big, $\024:8/integer-unit:1-unsigned-big, - $�:8/integer-unit:1-unsigned-big, + $Ù:8/integer-unit:1-unsigned-big, $\031:8/integer-unit:1-unsigned-big, $M:8/integer-unit:1-unsigned-big>>} end, diff --git a/lib/stdlib/test/shell_SUITE.erl b/lib/stdlib/test/shell_SUITE.erl index 681c154463..3c49aaa103 100644 --- a/lib/stdlib/test/shell_SUITE.erl +++ b/lib/stdlib/test/shell_SUITE.erl @@ -1,3 +1,4 @@ +%% -*- coding: utf-8 -*- %% %% %CopyrightBegin% %% @@ -2820,7 +2821,7 @@ otp_10302(Config) when is_list(Config) -> "ok.\n** exception error: an error occurred when evaluating" " an arithmetic expression\n in operator '/'/2\n" - " called as <<\"�\">> / <<\"�\">>.\n" = t({Node,Test7}), + " called as <<\"ª\">> / <<\"ª\">>.\n" = t({Node,Test7}), Test8 = <<"begin A = [1089], diff --git a/lib/test_server/src/erl2html2.erl b/lib/test_server/src/erl2html2.erl index 5584c1e50c..d0f40c47a7 100644 --- a/lib/test_server/src/erl2html2.erl +++ b/lib/test_server/src/erl2html2.erl @@ -1,3 +1,4 @@ +%% -*- coding: utf-8 -*- %% %% %CopyrightBegin% %% @@ -214,7 +215,7 @@ html_encoding(utf8) -> %%% from the source. %%% %%% Example: if the encoding of the file is utf8, and we have a string -%%% containing "�" = [229], then we need to convert this to [195,165] +%%% containing "å" = [229], then we need to convert this to [195,165] %%% before writing. Note that this conversion is only necessary %%% because the destination file is not (necessarily) opened with utf8 %%% encoding - it is opened with default encoding in order to allow diff --git a/lib/test_server/test/test_server_SUITE.erl b/lib/test_server/test/test_server_SUITE.erl index 3db2f5f9f1..8ad5fcfb5c 100644 --- a/lib/test_server/test/test_server_SUITE.erl +++ b/lib/test_server/test/test_server_SUITE.erl @@ -1,3 +1,4 @@ +%% -*- coding: utf-8 -*- %% %% %CopyrightBegin% %% @@ -187,7 +188,7 @@ test_server_unicode(Config) -> %% Create and run two test suites - one with filename and content %% in latin1 (if the default filename mode is latin1) and one with %% filename and content in utf8. Both have name and content - %% including letters ���. Check that all logs are generated with + %% including letters äöå. Check that all logs are generated with %% utf8 encoded filenames. case file:native_name_encoding() of utf8 -> @@ -348,7 +349,7 @@ generate_and_run_unicode_test(Config0,Encoding) -> SuiteHtml = translate_filename(LowerModStr++".src.html",Encoding), true = filelib:is_regular(filename:join(RunDir,SuiteHtml)), - TCLog = translate_filename(LowerModStr++".tc_���.html",Encoding), + TCLog = translate_filename(LowerModStr++".tc_äöå.html",Encoding), true = filelib:is_regular(filename:join(RunDir,TCLog)), ok. @@ -370,7 +371,7 @@ start_node(Config,Name,Args) -> end. create_unicode_test_suite(Dir,Encoding) -> - ModStr = "test_server_"++atom_to_list(Encoding)++"_���_SUITE", + ModStr = "test_server_"++atom_to_list(Encoding)++"_äöå_SUITE", File = filename:join(Dir,ModStr++".erl"), Suite = ["%% -*- ",epp:encoding_to_string(Encoding)," -*-\n", @@ -378,12 +379,12 @@ create_unicode_test_suite(Dir,Encoding) -> "\n" "-export([all/1, init_per_suite/1, end_per_suite/1]).\n" "-export([init_per_testcase/2, end_per_testcase/2]).\n" - "-export([tc_���/1]).\n" + "-export([tc_äöå/1]).\n" "\n" "-include_lib(\"test_server/include/test_server.hrl\").\n" "\n" "all(suite) ->\n" - " [tc_���].\n" + " [tc_äöå].\n" "\n" "init_per_suite(Config) ->\n" " Config.\n" @@ -406,7 +407,7 @@ create_unicode_test_suite(Dir,Encoding) -> " ?t:timetrap_cancel(Dog),\n" " ok.\n" "\n" - "tc_���(Config) when is_list(Config) ->\n" + "tc_äöå(Config) when is_list(Config) ->\n" " true = filelib:is_dir(?config(priv_dir,Config)),\n" " ok.\n"], {ok,Fd} = file:open(raw_filename(File,Encoding),[write,{encoding,Encoding}]), |