diff options
-rw-r--r-- | erts/emulator/beam/erl_process.c | 7 | ||||
-rw-r--r-- | lib/common_test/doc/src/ct_hooks_chapter.xml | 32 | ||||
-rw-r--r-- | lib/common_test/doc/src/run_test_chapter.xml | 10 | ||||
-rw-r--r-- | lib/common_test/src/Makefile | 3 | ||||
-rw-r--r-- | lib/common_test/src/ct.erl | 2 | ||||
-rw-r--r-- | lib/common_test/src/ct_hooks.erl | 27 | ||||
-rw-r--r-- | lib/common_test/src/ct_logs.erl | 26 | ||||
-rw-r--r-- | lib/common_test/src/ct_run.erl | 106 | ||||
-rw-r--r-- | lib/common_test/src/ct_testspec.erl | 5 | ||||
-rw-r--r-- | lib/common_test/src/ct_util.hrl | 1 | ||||
-rw-r--r-- | lib/common_test/src/cth_log_redirect.erl | 111 | ||||
-rw-r--r-- | lib/erl_docgen/priv/xsl/db_eix.xsl | 180 | ||||
-rw-r--r-- | lib/erl_docgen/priv/xsl/db_pdf.xsl | 21 | ||||
-rw-r--r-- | lib/erl_docgen/priv/xsl/db_pdf_params.xsl | 2 | ||||
-rw-r--r-- | lib/megaco/doc/src/notes.xml | 42 | ||||
-rw-r--r-- | lib/megaco/src/app/megaco.appup.src | 11 | ||||
-rw-r--r-- | lib/megaco/vsn.mk | 2 | ||||
-rw-r--r-- | lib/stdlib/src/error_logger_tty_h.erl | 69 | ||||
-rw-r--r-- | lib/xmerl/src/xmerl_scan.erl | 21 | ||||
-rw-r--r-- | lib/xmerl/src/xmerl_xsd.erl | 6 | ||||
-rw-r--r-- | lib/xmerl/test/xmerl_SUITE.erl | 23 | ||||
-rw-r--r-- | make/otp_release_targets.mk | 4 |
22 files changed, 552 insertions, 159 deletions
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index 44d2683fe0..5ceb4ce9a8 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -1152,13 +1152,6 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq) ASSERT(!(flgs & ERTS_SSI_FLG_SLEEPING)); goto sys_woken; } - if (!(flgs & ERTS_SSI_FLG_SLEEPING)) { - flgs = sched_prep_cont_spin_wait(ssi); - if (!(flgs & ERTS_SSI_FLG_WAITING)) { - ASSERT(!(flgs & ERTS_SSI_FLG_SLEEPING)); - goto sys_woken; - } - } /* * If we got new I/O tasks we aren't allowed to diff --git a/lib/common_test/doc/src/ct_hooks_chapter.xml b/lib/common_test/doc/src/ct_hooks_chapter.xml index dbb4310040..3b9620d0f2 100644 --- a/lib/common_test/doc/src/ct_hooks_chapter.xml +++ b/lib/common_test/doc/src/ct_hooks_chapter.xml @@ -405,6 +405,38 @@ terminate(State) -> ok.</code> </section> + <marker id="builtin_cths"/> + <section> + <title>Built-in CTHs</title> + <p>Common Test is delivered with a couple of general purpose CTHs that + can be enabled by the user to provide some generic testing functionality. + Some of these are enabled by default when starting running common_test, + they can be disabled by setting <c>enable_builtin_hooks</c> to + <c>false</c> on the command line or in the test specification. In the + table below there is a list of all current CTHs which are delivered with + Common Test.</p> + + <table> + <row> + <cell><em>CTH Name</em></cell> + <cell><em>Is Built-in</em></cell> + <cell><em>Description</em></cell> + </row> + <row> + <cell>cth_log_redirect</cell> + <cell>yes</cell> + <cell>Captures all error_logger and SASL logging events and prints them + to the current test case log. If an event can not be associated with a + testcase it will be printed in the common test framework log. This will + happen for testcases which are run in parallel and events which occur + inbetween testcases. You can configure the level of + <seealso marker="sasl:sasl_app">SASL</seealso> events report + using the normal SASL mechanisms. </cell> + </row> + </table> + + </section> + </chapter> diff --git a/lib/common_test/doc/src/run_test_chapter.xml b/lib/common_test/doc/src/run_test_chapter.xml index e668568795..816aa5b1eb 100644 --- a/lib/common_test/doc/src/run_test_chapter.xml +++ b/lib/common_test/doc/src/run_test_chapter.xml @@ -150,6 +150,8 @@ <seealso marker="event_handler_chapter#event_handling">event handlers</seealso> including start arguments.</item> <item><c><![CDATA[-ct_hooks <ct_hooks>]]></c>, to install <seealso marker="ct_hooks_chapter#installing">Common Test Hooks</seealso> including start arguments.</item> + <item><c><![CDATA[-enable_builtin_hooks <bool>]]></c>, to enable/disable + <seealso marker="ct_hooks_chapter#builtin_cths">Built-in Common Test Hooks</seealso>. Default is <c>true</c>.</item> <item><c><![CDATA[-include]]></c>, specifies include directories (see above).</item> <item><c><![CDATA[-no_auto_compile]]></c>, disables the automatic test suite compilation feature (see above).</item> <item><c><![CDATA[-multiply_timetraps <n>]]></c>, extends <seealso marker="write_test_chapter#timetraps">timetrap @@ -450,6 +452,8 @@ {ct_hooks, CTHModules}. {ct_hooks, NodeRefs, CTHModules}. + + {enable_builtin_hooks, Bool}. </pre> <p>Test terms:</p> <pre> @@ -631,7 +635,11 @@ <p>The minor log file contain full details of every single test case, each one in a separate file. This way the files should be easy to compare with previous test runs, even if the set of - test cases change.</p> + test cases change. If SASL is running those logs will also be + printed there by the + <seealso marker="common_test:ct_hooks_chapter#builtin_cths"> + cth_log_redirect built-in hook</seealso>. + </p> <p>Which information goes where is user configurable via the test server controller. Three threshold values determine what diff --git a/lib/common_test/src/Makefile b/lib/common_test/src/Makefile index 5b23558a96..125aa828fb 100644 --- a/lib/common_test/src/Makefile +++ b/lib/common_test/src/Makefile @@ -68,7 +68,8 @@ MODULES= \ ct_config_xml \ ct_slave \ ct_hooks\ - ct_hooks_lock + ct_hooks_lock\ + cth_log_redirect TARGET_MODULES= $(MODULES:%=$(EBIN)/%) BEAM_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) diff --git a/lib/common_test/src/ct.erl b/lib/common_test/src/ct.erl index 66da3ef742..3a96190256 100644 --- a/lib/common_test/src/ct.erl +++ b/lib/common_test/src/ct.erl @@ -149,7 +149,7 @@ run(TestDirs) -> %%% {repeat,N} | {duration,DurTime} | {until,StopTime} | %%% {force_stop,Bool} | {decrypt,DecryptKeyOrFile} | %%% {refresh_logs,LogDir} | {basic_html,Bool} | -%%% {ct_hooks, CTHs} +%%% {ct_hooks, CTHs} | {enable_builtin_hooks,Bool} %%% TestDirs = [string()] | string() %%% Suites = [string()] | string() %%% Cases = [atom()] | atom() diff --git a/lib/common_test/src/ct_hooks.erl b/lib/common_test/src/ct_hooks.erl index d5b585a831..ffafc582cf 100644 --- a/lib/common_test/src/ct_hooks.erl +++ b/lib/common_test/src/ct_hooks.erl @@ -34,6 +34,12 @@ %% If you change this, remember to update ct_util:look -> stop clause as well. -define(config_name, ct_hooks). +%% All of the hooks which are to be started by default. Remove by issuing +%% -enable_builtin_hooks false to when starting common test. +-define(BUILTIN_HOOKS,[#ct_hook_config{ module = cth_log_redirect, + opts = [], + prio = ctfirst }]). + -record(ct_hook_config, {id, module, prio, scope, opts = [], state = []}). %% ------------------------------------------------------------------------- @@ -44,7 +50,8 @@ -spec init(State :: term()) -> ok | {error, Reason :: term()}. init(Opts) -> - call(get_new_hooks(Opts, undefined), ok, init, []). + call(get_new_hooks(Opts, undefined) ++ get_builtin_hooks(Opts), + ok, init, []). %% @doc Called after all suites are done. @@ -283,6 +290,14 @@ get_new_hooks(Config) when is_list(Config) -> get_new_hooks(_Config) -> []. +get_builtin_hooks(Opts) -> + case proplists:get_value(enable_builtin_hooks,Opts) of + false -> + []; + _Else -> + [{HookConf, call_id, undefined} || HookConf <- ?BUILTIN_HOOKS] + end. + save_suite_data_async(Hooks) -> ct_util:save_suite_data_async(?config_name, Hooks). @@ -290,7 +305,7 @@ get_hooks() -> lists:keysort(#ct_hook_config.prio,ct_util:read_suite_data(?config_name)). %% Sort all calls in this order: -%% call_id < call_init < Hook Priority 1 < .. < Hook Priority N +%% call_id < call_init < ctfirst < Priority 1 < .. < Priority N < ctlast %% If Hook Priority is equal, check when it has been installed and %% sort on that instead. resort(Calls, Hooks) -> @@ -311,6 +326,14 @@ resort(Calls, Hooks) -> %% If priorities are equal, we check the position in the %% hooks list pos(Id1,Hooks) < pos(Id2,Hooks); + P1 == ctfirst -> + true; + P2 == ctfirst -> + false; + P1 == ctlast -> + false; + P2 == ctlast -> + true; true -> P1 < P2 end diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl index b839521e24..6a90441d53 100644 --- a/lib/common_test/src/ct_logs.erl +++ b/lib/common_test/src/ct_logs.erl @@ -36,7 +36,7 @@ -export([make_all_suites_index/1,make_all_runs_index/1]). %% Logging stuff directly from testcase --export([tc_log/3,tc_print/3,tc_pal/3, +-export([tc_log/3,tc_print/3,tc_pal/3,ct_log/3, basic_html/0]). %% Simulate logger process for use without ct environment running @@ -360,6 +360,23 @@ tc_pal(Category,Format,Args) -> ok. +%%%----------------------------------------------------------------- +%%% @spec tc_pal(Category,Format,Args) -> ok +%%% Category = atom() +%%% Format = string() +%%% Args = list() +%%% +%%% @doc Print and log to the ct framework log +%%% +%%% <p>This function is called by internal ct functions to +%%% force logging to the ct framework log</p> +ct_log(Category,Format,Args) -> + cast({ct_log,[{div_header(Category),[]}, + {Format,Args}, + {div_footer(),[]}]}), + ok. + + %%%================================================================= %%% Internal functions int_header() -> @@ -516,7 +533,12 @@ logger_loop(State) -> {clear_stylesheet,_} when State#logger_state.stylesheet == undefined -> logger_loop(State); {clear_stylesheet,_} -> - logger_loop(State#logger_state{stylesheet=undefined}); + logger_loop(State#logger_state{stylesheet=undefined}); + {ct_log, List} -> + Fd = State#logger_state.ct_log_fd, + [begin io:format(Fd,Str,Args),io:nl(Fd) end || + {Str,Args} <- List], + logger_loop(State); stop -> io:format(State#logger_state.ct_log_fd, int_header()++int_footer(), diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl index 877ec9c7dd..0715b8abf8 100644 --- a/lib/common_test/src/ct_run.erl +++ b/lib/common_test/src/ct_run.erl @@ -55,6 +55,7 @@ config = [], event_handlers = [], ct_hooks = [], + enable_builtin_hooks = true, include = [], silent_connections, stylesheet, @@ -173,6 +174,10 @@ script_start1(Parent, Args) -> end, false, Args), EvHandlers = event_handler_args2opts(Args), CTHooks = ct_hooks_args2opts(Args), + EnableBuiltinHooks = get_start_opt(enable_builtin_hooks, + fun([CT]) -> list_to_atom(CT); + ([]) -> true + end, true, Args), %% check flags and set corresponding application env variables @@ -237,6 +242,7 @@ script_start1(Parent, Args) -> StartOpts = #opts{label = Label, vts = Vts, shell = Shell, cover = Cover, logdir = LogDir, event_handlers = EvHandlers, ct_hooks = CTHooks, + enable_builtin_hooks = EnableBuiltinHooks, include = IncludeDirs, silent_connections = SilentConns, stylesheet = Stylesheet, @@ -311,6 +317,11 @@ script_start2(StartOpts = #opts{vts = undefined, AllCTHooks = merge_vals( [StartOpts#opts.ct_hooks, SpecStartOpts#opts.ct_hooks]), + + EnableBuiltinHooks = + choose_val( + StartOpts#opts.enable_builtin_hooks, + SpecStartOpts#opts.enable_builtin_hooks), AllInclude = merge_vals([StartOpts#opts.include, SpecStartOpts#opts.include]), @@ -323,6 +334,8 @@ script_start2(StartOpts = #opts{vts = undefined, config = SpecStartOpts#opts.config, event_handlers = AllEvHs, ct_hooks = AllCTHooks, + enable_builtin_hooks = + EnableBuiltinHooks, include = AllInclude, multiply_timetraps = MultTT, scale_timetraps = ScaleTT}} @@ -339,9 +352,7 @@ script_start2(StartOpts = #opts{vts = undefined, {[],_} -> {error,no_testspec_specified}; {undefined,_} -> % no testspec used - case check_and_install_configfiles(InitConfig, TheLogDir, - Opts#opts.event_handlers, - Opts#opts.ct_hooks) of + case check_and_install_configfiles(InitConfig, TheLogDir, Opts) of ok -> % go on read tests from start flags script_start3(Opts#opts{config=InitConfig, logdir=TheLogDir}, Args); @@ -351,9 +362,7 @@ script_start2(StartOpts = #opts{vts = undefined, {_,_} -> % testspec used %% merge config from start flags with config from testspec AllConfig = merge_vals([InitConfig, Opts#opts.config]), - case check_and_install_configfiles(AllConfig, TheLogDir, - Opts#opts.event_handlers, - Opts#opts.ct_hooks) of + case check_and_install_configfiles(AllConfig, TheLogDir, Opts) of ok -> % read tests from spec {Run,Skip} = ct_testspec:prepare_tests(Terms, node()), do_run(Run, Skip, Opts#opts{config=AllConfig, @@ -367,9 +376,7 @@ script_start2(StartOpts, Args) -> %% read config/userconfig from start flags InitConfig = ct_config:prepare_config_list(Args), LogDir = which(logdir, StartOpts#opts.logdir), - case check_and_install_configfiles(InitConfig, LogDir, - StartOpts#opts.event_handlers, - StartOpts#opts.ct_hooks) of + case check_and_install_configfiles(InitConfig, LogDir, StartOpts) of ok -> % go on read tests from start flags script_start3(StartOpts#opts{config=InitConfig, logdir=LogDir}, Args); @@ -377,12 +384,17 @@ script_start2(StartOpts, Args) -> Error end. -check_and_install_configfiles(Configs, LogDir, EvHandlers, CTHooks) -> +check_and_install_configfiles( + Configs, LogDir, #opts{ + event_handlers = EvHandlers, + ct_hooks = CTHooks, + enable_builtin_hooks = EnableBuiltinHooks} ) -> case ct_config:check_config_files(Configs) of false -> install([{config,Configs}, {event_handler,EvHandlers}, - {ct_hooks,CTHooks}], LogDir); + {ct_hooks,CTHooks}, + {enable_builtin_hooks,EnableBuiltinHooks}], LogDir); {value,{error,{nofile,File}}} -> {error,{cant_read_config_file,File}}; {value,{error,{wrong_config,Message}}}-> @@ -451,18 +463,19 @@ script_start4(#opts{vts = true, config = Config, event_handlers = EvHandlers, script_start4(#opts{label = Label, shell = true, config = Config, event_handlers = EvHandlers, ct_hooks = CTHooks, + enable_builtin_hooks = EnableBuiltinHooks, logdir = LogDir, testspecs = Specs}, _Args) -> %% label - used by ct_logs application:set_env(common_test, test_label, Label), - InstallOpts = [{config,Config},{event_handler,EvHandlers}, - {ct_hooks, CTHooks}], if Config == [] -> ok; true -> io:format("\nInstalling: ~p\n\n", [Config]) end, - case install(InstallOpts) of + case install([{config,Config},{event_handler,EvHandlers}, + {ct_hooks, CTHooks}, + {enable_builtin_hooks,EnableBuiltinHooks}]) of ok -> ct_util:start(interactive, LogDir), log_ts_names(Specs), @@ -682,6 +695,11 @@ run_test1(StartOpts) -> %% CT Hooks CTHooks = get_start_opt(ct_hooks, value, [], StartOpts), + EnableBuiltinHooks = get_start_opt(enable_builtin_hooks, + fun(EBH) when EBH == true; + EBH == false -> + EBH + end, true, StartOpts), %% silent connections SilentConns = get_start_opt(silent_connections, @@ -754,6 +772,7 @@ run_test1(StartOpts) -> cover = Cover, step = Step, logdir = LogDir, config = CfgFiles, event_handlers = EvHandlers, ct_hooks = CTHooks, + enable_builtin_hooks = EnableBuiltinHooks, include = Include, silent_connections = SilentConns, stylesheet = Stylesheet, @@ -808,24 +827,28 @@ run_spec_file(Relaxed, AllCTHooks = merge_vals([Opts#opts.ct_hooks, SpecOpts#opts.ct_hooks]), + EnableBuiltinHooks = choose_val(Opts#opts.enable_builtin_hooks, + SpecOpts#opts.enable_builtin_hooks), application:set_env(common_test, include, AllInclude), - case check_and_install_configfiles(AllConfig, - which(logdir,LogDir), - AllEvHs, - AllCTHooks) of + Opts1 = Opts#opts{label = Label, + cover = Cover, + logdir = which(logdir, LogDir), + config = AllConfig, + event_handlers = AllEvHs, + include = AllInclude, + testspecs = AbsSpecs, + multiply_timetraps = MultTT, + scale_timetraps = ScaleTT, + ct_hooks = AllCTHooks, + enable_builtin_hooks = EnableBuiltinHooks + }, + + case check_and_install_configfiles(AllConfig,Opts1#opts.logdir, + Opts1) of ok -> - Opts1 = Opts#opts{label = Label, - cover = Cover, - logdir = which(logdir, LogDir), - config = AllConfig, - event_handlers = AllEvHs, - include = AllInclude, - testspecs = AbsSpecs, - multiply_timetraps = MultTT, - scale_timetraps = ScaleTT, - ct_hooks = AllCTHooks}, + {Run,Skip} = ct_testspec:prepare_tests(TS, node()), reformat_result(catch do_run(Run, Skip, Opts1, StartOpts)); {error,GCFReason} -> @@ -834,13 +857,10 @@ run_spec_file(Relaxed, end. run_prepared(Run, Skip, Opts = #opts{logdir = LogDir, - config = CfgFiles, - event_handlers = EvHandlers, - ct_hooks = CTHooks}, + config = CfgFiles }, StartOpts) -> LogDir1 = which(logdir, LogDir), - case check_and_install_configfiles(CfgFiles, LogDir1, - EvHandlers, CTHooks) of + case check_and_install_configfiles(CfgFiles, LogDir1, Opts) of ok -> reformat_result(catch do_run(Run, Skip, Opts#opts{logdir = LogDir1}, StartOpts)); @@ -872,7 +892,8 @@ check_config_file(Callback, File)-> run_dir(Opts = #opts{logdir = LogDir, config = CfgFiles, event_handlers = EvHandlers, - ct_hooks = CTHook }, StartOpts) -> + ct_hooks = CTHook, + enable_builtin_hooks = EnableBuiltinHooks }, StartOpts) -> LogDir1 = which(logdir, LogDir), Opts1 = Opts#opts{logdir = LogDir1}, AbsCfgFiles = @@ -895,7 +916,8 @@ run_dir(Opts = #opts{logdir = LogDir, end, CfgFiles), case install([{config,AbsCfgFiles}, {event_handler,EvHandlers}, - {ct_hooks, CTHook}], LogDir1) of + {ct_hooks, CTHook}, + {enable_builtin_hooks,EnableBuiltinHooks}], LogDir1) of ok -> ok; {error,IReason} -> exit(IReason) end, @@ -999,9 +1021,8 @@ run_testspec1(TestSpec) -> end, application:set_env(common_test, include, AllInclude), LogDir1 = which(logdir,Opts#opts.logdir), - case check_and_install_configfiles(Opts#opts.config, LogDir1, - Opts#opts.event_handlers, - Opts#opts.ct_hooks) of + case check_and_install_configfiles( + Opts#opts.config, LogDir1, Opts) of ok -> Opts1 = Opts#opts{testspecs = [], logdir = LogDir1, @@ -1020,6 +1041,7 @@ get_data_for_node(#testspec{label = Labels, userconfig = UsrCfgs, event_handler = EvHs, ct_hooks = CTHooks, + enable_builtin_hooks = EnableBuiltinHooks, include = Incl, multiply_timetraps = MTs, scale_timetraps = STs}, Node) -> @@ -1042,6 +1064,7 @@ get_data_for_node(#testspec{label = Labels, config = ConfigFiles, event_handlers = EvHandlers, ct_hooks = FiltCTHooks, + enable_builtin_hooks = EnableBuiltinHooks, include = Include, multiply_timetraps = MT, scale_timetraps = ST}. @@ -2067,8 +2090,11 @@ get_start_opt(Key, IfExists, IfNotExists, Args) -> end. ct_hooks_args2opts(Args) -> - ct_hooks_args2opts( - proplists:get_value(ct_hooks, Args, []),[]). + lists:foldl(fun({ct_hooks,Hooks}, Acc) -> + ct_hooks_args2opts(Hooks,Acc); + (_,Acc) -> + Acc + end,[],Args). ct_hooks_args2opts([CTH,Arg,Prio,"and"| Rest],Acc) -> ct_hooks_args2opts(Rest,[{list_to_atom(CTH), diff --git a/lib/common_test/src/ct_testspec.erl b/lib/common_test/src/ct_testspec.erl index d845358bb2..96971ccfc7 100644 --- a/lib/common_test/src/ct_testspec.erl +++ b/lib/common_test/src/ct_testspec.erl @@ -646,6 +646,10 @@ add_tests([{ct_hooks, _Node, []}|Ts], Spec) -> add_tests([{ct_hooks, Hooks}|Ts], Spec) -> add_tests([{ct_hooks, all_nodes, Hooks}|Ts], Spec); +%% -- enable_builtin_hooks -- +add_tests([{enable_builtin_hooks,Bool}|Ts],Spec) -> + add_tests(Ts, Spec#testspec{ enable_builtin_hooks = Bool }); + %% --- include --- add_tests([{include,all_nodes,InclDirs}|Ts],Spec) -> Tests = lists:map(fun(N) -> {include,N,InclDirs} end, list_nodes(Spec)), @@ -1104,6 +1108,7 @@ valid_terms() -> {event_handler,4}, {ct_hooks,2}, {ct_hooks,3}, + {enable_builtin_hooks,1}, {multiply_timetraps,2}, {multiply_timetraps,3}, {scale_timetraps,2}, diff --git a/lib/common_test/src/ct_util.hrl b/lib/common_test/src/ct_util.hrl index 556f88c84d..dbe9d9b4e6 100644 --- a/lib/common_test/src/ct_util.hrl +++ b/lib/common_test/src/ct_util.hrl @@ -37,6 +37,7 @@ userconfig=[], event_handler=[], ct_hooks=[], + enable_builtin_hooks=true, include=[], multiply_timetraps=[], scale_timetraps=[], diff --git a/lib/common_test/src/cth_log_redirect.erl b/lib/common_test/src/cth_log_redirect.erl new file mode 100644 index 0000000000..14663b7738 --- /dev/null +++ b/lib/common_test/src/cth_log_redirect.erl @@ -0,0 +1,111 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2011. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +-module(cth_log_redirect). + +%%% @doc Common Test Framework functions handling test specifications. +%%% +%%% <p>This module redirects sasl and error logger info to common test log.</p> +%%% @end + + +%% CTH Callbacks +-export([id/1, init/2, post_init_per_group/4, pre_end_per_group/3, + post_end_per_testcase/4]). + +%% Event handler Callbacks +-export([init/1, + handle_event/2, handle_call/2, handle_info/2, + terminate/2]). + +id(_Opts) -> + ?MODULE. + +init(?MODULE, _Opts) -> + error_logger:add_report_handler(?MODULE), + tc_log. + +post_init_per_group(Group, Config, Result, tc_log) -> + case lists:member(parallel,proplists:get_value( + tc_group_properties,Config,[])) of + true -> + {Result, {set_log_func(ct_log),Group}}; + false -> + {Result, tc_log} + end; +post_init_per_group(_Group, _Config, Result, State) -> + {Result, State}. + +post_end_per_testcase(_TC, _Config, Result, State) -> + %% Make sure that the event queue is flushed + %% before ending this test case. + gen_event:call(error_logger, ?MODULE, flush), + {Result, State}. + +pre_end_per_group(Group, Config, {ct_log, Group}) -> + {Config, set_log_func(tc_log)}; +pre_end_per_group(_Group, Config, State) -> + {Config, State}. + + +%% Copied and modified from sasl_report_tty_h.erl +init(_Type) -> + {ok, tc_log}. + +handle_event({_Type, GL, _Msg}, State) when node(GL) /= node() -> + {ok, State}; +handle_event(Event, LogFunc) -> + case lists:keyfind(sasl, 1, application:which_applications()) of + false -> + sasl_not_started; + _Else -> + {ok, ErrLogType} = application:get_env(sasl, errlog_type), + SReport = sasl_report:format_report(group_leader(), ErrLogType, + tag_event(Event)), + if is_list(SReport) -> + ct_logs:LogFunc(sasl, SReport, []); + true -> %% Report is an atom if no logging is to be done + ignore + end + end, + EReport = error_logger_tty_h:write_event( + tag_event(Event),io_lib), + if is_list(EReport) -> + ct_logs:LogFunc(error_logger, EReport, []); + true -> %% Report is an atom if no logging is to be done + ignore + end, + {ok, LogFunc}. + + +handle_info(_,State) -> {ok, State}. + +handle_call(flush,State) -> + {ok, ok, State}; +handle_call({set_logfunc,NewLogFunc},_) -> + {ok, NewLogFunc, NewLogFunc}; +handle_call(_Query, _State) -> {error, bad_query}. + +terminate(_Reason, _Type) -> + []. + +tag_event(Event) -> + {calendar:local_time(), Event}. + +set_log_func(Func) -> + gen_event:call(error_logger, ?MODULE, {set_logfunc, Func}). diff --git a/lib/erl_docgen/priv/xsl/db_eix.xsl b/lib/erl_docgen/priv/xsl/db_eix.xsl index 4545322bc2..7a648ddfd7 100644 --- a/lib/erl_docgen/priv/xsl/db_eix.xsl +++ b/lib/erl_docgen/priv/xsl/db_eix.xsl @@ -22,10 +22,16 @@ <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:exsl="http://exslt.org/common" + extension-element-prefixes="exsl" xmlns:fn="http://www.w3.org/2005/02/xpath-functions"> <xsl:output method="text" encoding="UTF-8" indent="no"/> + <xsl:param name="specs_file" select="''"/> + <xsl:variable name="i" select="document($specs_file)"></xsl:variable> + + <!-- Book --> <xsl:template match="/book"> <xsl:text>%% %% Search data file for </xsl:text><xsl:value-of select="$appname"/><xsl:text> </xsl:text><xsl:value-of select="$appver"/> @@ -50,9 +56,7 @@ <xsl:template match="erlref"> <xsl:text>{"</xsl:text><xsl:value-of select="module"/><xsl:text>.html", {function, {"</xsl:text><xsl:value-of select="$appname"/> <xsl:text>", "</xsl:text><xsl:value-of select="module"/><xsl:text>"}}, [ </xsl:text> - <xsl:apply-templates select="funcs"> - <xsl:with-param name="mod" select="module"/> - </xsl:apply-templates> + <xsl:apply-templates select="funcs"/> <xsl:text>]}. </xsl:text> <xsl:text>{"</xsl:text><xsl:value-of select="module"/><xsl:text>.html", {module, "</xsl:text> <xsl:value-of select="$appname"/><xsl:text>"}, ["</xsl:text><xsl:value-of select="module"/><xsl:text>"]}. </xsl:text> @@ -62,9 +66,7 @@ <xsl:template match="cref"> <xsl:text>{"</xsl:text><xsl:value-of select="lib"/><xsl:text>.html", {function, {"</xsl:text><xsl:value-of select="$appname"/> <xsl:text>", "</xsl:text><xsl:value-of select="lib"/><xsl:text>"}}, [ </xsl:text> - <xsl:apply-templates select="funcs"> - <xsl:with-param name="mod" select="lib"/> - </xsl:apply-templates> + <xsl:apply-templates select="funcs"/> <xsl:text>]}. </xsl:text> <xsl:text>{"</xsl:text><xsl:value-of select="lib"/><xsl:text>.html", {clib, "</xsl:text> <xsl:value-of select="$appname"/><xsl:text>"}, ["</xsl:text><xsl:value-of select="lib"/><xsl:text>"]}. </xsl:text> @@ -91,69 +93,157 @@ <!-- Funcs --> <xsl:template match="funcs"> - <xsl:param name="mod"/> <xsl:variable name="lastfuncsblock"> <xsl:value-of select="position() = last()"/> </xsl:variable> <xsl:apply-templates select="func/name"> - <xsl:with-param name="mod" select="$mod"/> <xsl:with-param name="lastfuncsblock" select="$lastfuncsblock"/> </xsl:apply-templates> </xsl:template> + <xsl:template match="name"> + <xsl:param name="lastfuncsblock"/> + <xsl:choose> + <!-- @arity is mandatory when referring to a specification --> + <xsl:when test="string-length(@arity) > 0"> + <xsl:call-template name="spec_name"/> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="name"/> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + <xsl:template name="err"> + <xsl:param name="f"/> + <xsl:param name="m"/> + <xsl:param name="n"/> + <xsl:param name="a"/> + <xsl:param name="s"/> + <xsl:message terminate="yes"> + Error <xsl:if test="$f != ''">in <xsl:value-of select ="$f"/>:</xsl:if> + <xsl:if test="$m != ''"><xsl:value-of select ="$m"/>:</xsl:if> + <xsl:value-of select="$n"/> + <xsl:if test="$a != ''">/<xsl:value-of + select ="$a"/></xsl:if>: <xsl:value-of select="$s"/> + </xsl:message> + </xsl:template> + <xsl:template name="find_spec"> + <xsl:variable name="curModule" select="ancestor::erlref/module"/> + <xsl:variable name="mod" select="@mod"/> + <xsl:variable name="name" select="@name"/> + <xsl:variable name="arity" select="@arity"/> + <xsl:variable name="clause_i" select="@clause_i"/> + <xsl:variable name="spec0" select= + "$i/specs/module[@name=$curModule]/spec + [name=$name and arity=$arity + and (string-length($mod) = 0 or module = $mod)]"/> + <xsl:variable name="spec" select="$spec0[string-length($clause_i) = 0 + or position() = $clause_i]"/> - <xsl:template match="name"> - <xsl:param name="mod"/> + <xsl:if test="count($spec) != 1"> + <xsl:variable name="why"> + <xsl:choose> + <xsl:when test="count($spec) > 1">ambiguous spec</xsl:when> + <xsl:when test="count($spec) = 0">unknown spec</xsl:when> + </xsl:choose> + </xsl:variable> + <xsl:call-template name="err"> + <xsl:with-param name="f" select="$curModule"/> + <xsl:with-param name="m" select="$mod"/> + <xsl:with-param name="n" select="$name"/> + <xsl:with-param name="a" select="$arity"/> + <xsl:with-param name="s" select="$why"/> + </xsl:call-template> + </xsl:if> + <xsl:copy-of select="$spec"/> + </xsl:template> + + + <xsl:template name="spec_name"> + <xsl:param name="lastfuncsblock"/> + <xsl:variable name="fname" select="@name"/> + <xsl:variable name="arity" select="@arity"/> + <xsl:variable name="spec0"> + <xsl:call-template name="find_spec"/> + </xsl:variable> + <xsl:variable name="spec" select="exsl:node-set($spec0)/spec"/> + + <xsl:variable name="tmpstring"> + <xsl:value-of select="substring-before($spec/contract/clause/head, ' ->')"/> + </xsl:variable> + + <xsl:text> {"</xsl:text><xsl:value-of select="$fname"/> + <xsl:text>", "</xsl:text><xsl:value-of select="$tmpstring"/> + <xsl:text>", "</xsl:text><xsl:value-of select="$fname"/> + <xsl:text>-</xsl:text><xsl:value-of select="$arity"/><xsl:text>"}</xsl:text> + + <xsl:choose> + <xsl:when test="($lastfuncsblock = 'true') and (position() = last())"> + <xsl:text> </xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>, </xsl:text> + </xsl:otherwise> + </xsl:choose> + + </xsl:template> + + + <xsl:template name="name"> <xsl:param name="lastfuncsblock"/> <xsl:variable name="tmpstring"> <xsl:value-of select="substring-before(substring-after(., '('), '->')"/> - </xsl:variable> + </xsl:variable> + <xsl:variable name="ustring"> <xsl:choose> - <xsl:when test="string-length($tmpstring) > 0"> - <xsl:call-template name="remove-paren"> - <xsl:with-param name="string" select="$tmpstring"/> - </xsl:call-template> - </xsl:when> - <xsl:otherwise> - <xsl:call-template name="remove-paren"> - <xsl:with-param name="string" select="substring-after(., '(')"/> - </xsl:call-template> - </xsl:otherwise> + <xsl:when test="string-length($tmpstring) > 0"> + <xsl:call-template name="remove-paren"> + <xsl:with-param name="string" select="$tmpstring"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="remove-paren"> + <xsl:with-param name="string" select="substring-after(., '(')"/> + </xsl:call-template> + </xsl:otherwise> </xsl:choose> - </xsl:variable> + </xsl:variable> + <xsl:variable name="arity"> <xsl:call-template name="calc-arity"> - <xsl:with-param name="string" select="substring-before($ustring, ')')"/> - <xsl:with-param name="no-of-pars" select="0"/> + <xsl:with-param name="string" select="substring-before($ustring, ')')"/> + <xsl:with-param name="no-of-pars" select="0"/> </xsl:call-template> - </xsl:variable> + </xsl:variable> + <xsl:variable name="fname"> <xsl:choose> - <xsl:when test="ancestor::cref"> - <xsl:value-of select="substring-before(nametext, '(')"/> - </xsl:when> - <xsl:when test="ancestor::erlref"> - <xsl:variable name="fname1"> - <xsl:value-of select="substring-before(., '(')"/> - </xsl:variable> - <xsl:variable name="fname2"> - <xsl:value-of select="substring-after($fname1, 'erlang:')"/> - </xsl:variable> - <xsl:choose> - <xsl:when test="string-length($fname2) > 0"> - <xsl:value-of select="$fname2"/> - </xsl:when> - <xsl:otherwise> - <xsl:value-of select="$fname1"/> - </xsl:otherwise> - </xsl:choose> - </xsl:when> + <xsl:when test="ancestor::cref"> + <xsl:value-of select="substring-before(nametext, '(')"/> + </xsl:when> + <xsl:when test="ancestor::erlref"> + <xsl:variable name="fname1"> + <xsl:value-of select="substring-before(., '(')"/> + </xsl:variable> + <xsl:variable name="fname2"> + <xsl:value-of select="substring-after($fname1, 'erlang:')"/> + </xsl:variable> + <xsl:choose> + <xsl:when test="string-length($fname2) > 0"> + <xsl:value-of select="$fname2"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$fname1"/> + </xsl:otherwise> + </xsl:choose> + </xsl:when> </xsl:choose> - </xsl:variable> + </xsl:variable> + <xsl:text> {"</xsl:text><xsl:value-of select="$fname"/> <xsl:text>", "</xsl:text><xsl:value-of select="$fname"/> <xsl:text>(</xsl:text><xsl:value-of select="normalize-space($tmpstring)"/> diff --git a/lib/erl_docgen/priv/xsl/db_pdf.xsl b/lib/erl_docgen/priv/xsl/db_pdf.xsl index 35f6349f70..48a7a026c1 100644 --- a/lib/erl_docgen/priv/xsl/db_pdf.xsl +++ b/lib/erl_docgen/priv/xsl/db_pdf.xsl @@ -732,22 +732,23 @@ <xsl:template name="bookmarks1"> <xsl:param name="entries"/> <xsl:if test="$entries != ''"> + <xsl:for-each select="$entries"> - <fo:bookmark internal-destination="{generate-id(/book/parts/part)}" - starting-state="hide"> - <fo:bookmark-title>User's Guide</fo:bookmark-title> - - <xsl:for-each select="$entries"> + <fo:bookmark internal-destination="{generate-id(header/title)}" + starting-state="hide"> + <fo:bookmark-title><xsl:value-of select="header/title"/></fo:bookmark-title> + <xsl:call-template name="bookmarks2"> <xsl:with-param name="entries" select="chapter[header/title]"/> </xsl:call-template> - </xsl:for-each> - - </fo:bookmark> + + </fo:bookmark> + </xsl:for-each> </xsl:if> </xsl:template> + <xsl:template name="bookmarks2"> <xsl:param name="entries"/> <xsl:for-each select="$entries"> @@ -934,9 +935,9 @@ <xsl:template match="part"> <xsl:variable name="partnum"><xsl:number level="any" from="book" count="part|application"/></xsl:variable> - <fo:block xsl:use-attribute-sets="h1" id="{generate-id()}"> + <fo:block xsl:use-attribute-sets="h1" id="{generate-id(header/title)}"> <xsl:value-of select="$partnum"/>    - <xsl:text>User's Guide</xsl:text> + <xsl:value-of select="header/title"/> </fo:block> <xsl:apply-templates select="description"> diff --git a/lib/erl_docgen/priv/xsl/db_pdf_params.xsl b/lib/erl_docgen/priv/xsl/db_pdf_params.xsl index 3dfecf8b74..d2f0350cf1 100644 --- a/lib/erl_docgen/priv/xsl/db_pdf_params.xsl +++ b/lib/erl_docgen/priv/xsl/db_pdf_params.xsl @@ -29,7 +29,7 @@ <!-- Fixed strings --> <xsl:variable name="companyname"><xsl:value-of select="/book/header/copyright/holder"/></xsl:variable> - <xsl:variable name="copyright">Copyright © <xsl:value-of select="/book/header/copyright/year[1]"/><xsl:text>-</xsl:text><xsl:value-of select="substring-after(substring-after($gendate, ' '), ' ')"/></xsl:variable> + <xsl:variable name="copyright">Copyright © <xsl:value-of select="/book/header/copyright/year[1]"/><xsl:text>-</xsl:text><xsl:value-of select="substring-after(normalize-space(substring-after($gendate, ' ')), ' ')"/></xsl:variable> <!-- FIXME: remove when appendix creation has been fixed --> <!-- xsl:variable name="appendix_title"--> diff --git a/lib/megaco/doc/src/notes.xml b/lib/megaco/doc/src/notes.xml index 4f678a2a1b..2aba8db71b 100644 --- a/lib/megaco/doc/src/notes.xml +++ b/lib/megaco/doc/src/notes.xml @@ -36,6 +36,48 @@ section is the version number of Megaco.</p> + <section><title>Megaco 3.15.1.1</title> + + <p>Version 3.15.1.1 supports code replacement in runtime from/to + version 3.15.1 and 3.15.</p> + + <section> + <title>Improvements and new features</title> + +<!-- + <p>-</p> +--> + + <list type="bulleted"> + <item> + <p>Correct various XML errors. </p> + <p>Own Id: OTP-9550</p> + </item> + + </list> + + </section> + + <section> + <title>Fixed bugs and malfunctions</title> + + <p>-</p> + + <!-- + <list type="bulleted"> + <item> + <p>Fixing miscellaneous things detected by dialyzer. </p> + <p>Own Id: OTP-9075</p> + </item> + + </list> + --> + + </section> + + </section> <!-- 3.15.1.1 --> + + <section><title>Megaco 3.15.1</title> <p>Version 3.15.1 supports code replacement in runtime from/to diff --git a/lib/megaco/src/app/megaco.appup.src b/lib/megaco/src/app/megaco.appup.src index 01b070d79f..7107178d1a 100644 --- a/lib/megaco/src/app/megaco.appup.src +++ b/lib/megaco/src/app/megaco.appup.src @@ -136,10 +136,17 @@ %% | %% v %% 3.15.1 +%% | +%% v +%% 3.15.1.1 %% %% {"%VSN%", [ + {"3.15.1", + [ + ] + }, {"3.15", [ {load_module, megaco_flex_scanner, soft_purge, soft_purge, []}, @@ -153,6 +160,10 @@ } ], [ + {"3.15.1", + [ + ] + }, {"3.15", [ {load_module, megaco_flex_scanner, soft_purge, soft_purge, []}, diff --git a/lib/megaco/vsn.mk b/lib/megaco/vsn.mk index 5f71712360..c1476488ca 100644 --- a/lib/megaco/vsn.mk +++ b/lib/megaco/vsn.mk @@ -18,6 +18,6 @@ # %CopyrightEnd% APPLICATION = megaco -MEGACO_VSN = 3.15.1 +MEGACO_VSN = 3.15.1.1 PRE_VSN = APP_VSN = "$(APPLICATION)-$(MEGACO_VSN)$(PRE_VSN)" diff --git a/lib/stdlib/src/error_logger_tty_h.erl b/lib/stdlib/src/error_logger_tty_h.erl index 435e57aa0e..fa13fbb2bd 100644 --- a/lib/stdlib/src/error_logger_tty_h.erl +++ b/lib/stdlib/src/error_logger_tty_h.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2009. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -34,10 +34,12 @@ handle_event/2, handle_call/2, handle_info/2, terminate/2, code_change/3]). +-export([write_event/2]). + %% This one is used when we takeover from the simple error_logger. init({[], {error_logger, Buf}}) -> User = set_group_leader(), - write_events(Buf), + write_events(Buf,io), {ok, {User, error_logger}}; %% This one is used if someone took over from us, and now wants to %% go back. @@ -52,7 +54,7 @@ init([]) -> handle_event({_Type, GL, _Msg}, State) when node(GL) =/= node() -> {ok, State}; handle_event(Event, State) -> - write_event(tag_event(Event)), + write_event(tag_event(Event),io), {ok, State}. handle_info({'EXIT', User, _Reason}, {User, PrevHandler}) -> @@ -64,10 +66,10 @@ handle_info({'EXIT', User, _Reason}, {User, PrevHandler}) -> PrevHandler, go_back} end; handle_info({emulator, GL, Chars}, State) when node(GL) == node() -> - write_event(tag_event({emulator, GL, Chars})), + write_event(tag_event({emulator, GL, Chars}),io), {ok, State}; handle_info({emulator, noproc, Chars}, State) -> - write_event(tag_event({emulator, noproc, Chars})), + write_event(tag_event({emulator, noproc, Chars}),io), {ok, State}; handle_info(_, State) -> {ok, State}. @@ -97,65 +99,65 @@ set_group_leader() -> tag_event(Event) -> {erlang:localtime(), Event}. -write_events(Events) -> write_events1(lists:reverse(Events)). +write_events(Events,IOMod) -> write_events1(lists:reverse(Events),IOMod). -write_events1([Event|Es]) -> - write_event(Event), - write_events1(Es); -write_events1([]) -> +write_events1([Event|Es],IOMod) -> + write_event(Event,IOMod), + write_events1(Es,IOMod); +write_events1([],_IOMod) -> ok. -write_event({Time, {error, _GL, {Pid, Format, Args}}}) -> +write_event({Time, {error, _GL, {Pid, Format, Args}}},IOMod) -> T = write_time(maybe_utc(Time)), case catch io_lib:format(add_node(Format,Pid), Args) of S when is_list(S) -> - format(T ++ S); + format(IOMod, T ++ S); _ -> F = add_node("ERROR: ~p - ~p~n", Pid), - format(T ++ F, [Format,Args]) + format(IOMod, T ++ F, [Format,Args]) end; -write_event({Time, {emulator, _GL, Chars}}) -> +write_event({Time, {emulator, _GL, Chars}},IOMod) -> T = write_time(maybe_utc(Time)), case catch io_lib:format(Chars, []) of S when is_list(S) -> - format(T ++ S); + format(IOMod, T ++ S); _ -> - format(T ++ "ERROR: ~p ~n", [Chars]) + format(IOMod, T ++ "ERROR: ~p ~n", [Chars]) end; -write_event({Time, {info, _GL, {Pid, Info, _}}}) -> +write_event({Time, {info, _GL, {Pid, Info, _}}},IOMod) -> T = write_time(maybe_utc(Time)), - format(T ++ add_node("~p~n",Pid),[Info]); -write_event({Time, {error_report, _GL, {Pid, std_error, Rep}}}) -> + format(IOMod, T ++ add_node("~p~n",Pid),[Info]); +write_event({Time, {error_report, _GL, {Pid, std_error, Rep}}},IOMod) -> T = write_time(maybe_utc(Time)), S = format_report(Rep), - format(T ++ S ++ add_node("", Pid)); -write_event({Time, {info_report, _GL, {Pid, std_info, Rep}}}) -> + format(IOMod, T ++ S ++ add_node("", Pid)); +write_event({Time, {info_report, _GL, {Pid, std_info, Rep}}},IOMod) -> T = write_time(maybe_utc(Time), "INFO REPORT"), S = format_report(Rep), - format(T ++ S ++ add_node("", Pid)); -write_event({Time, {info_msg, _GL, {Pid, Format, Args}}}) -> + format(IOMod, T ++ S ++ add_node("", Pid)); +write_event({Time, {info_msg, _GL, {Pid, Format, Args}}},IOMod) -> T = write_time(maybe_utc(Time), "INFO REPORT"), case catch io_lib:format(add_node(Format,Pid), Args) of S when is_list(S) -> - format(T ++ S); + format(IOMod, T ++ S); _ -> F = add_node("ERROR: ~p - ~p~n", Pid), - format(T ++ F, [Format,Args]) + format(IOMod, T ++ F, [Format,Args]) end; -write_event({Time, {warning_report, _GL, {Pid, std_warning, Rep}}}) -> +write_event({Time, {warning_report, _GL, {Pid, std_warning, Rep}}},IOMod) -> T = write_time(maybe_utc(Time), "WARNING REPORT"), S = format_report(Rep), - format(T ++ S ++ add_node("", Pid)); -write_event({Time, {warning_msg, _GL, {Pid, Format, Args}}}) -> + format(IOMod, T ++ S ++ add_node("", Pid)); +write_event({Time, {warning_msg, _GL, {Pid, Format, Args}}},IOMod) -> T = write_time(maybe_utc(Time), "WARNING REPORT"), case catch io_lib:format(add_node(Format,Pid), Args) of S when is_list(S) -> - format(T ++ S); + format(IOMod, T ++ S); _ -> F = add_node("ERROR: ~p - ~p~n", Pid), - format(T ++ F, [Format,Args]) + format(IOMod, T ++ F, [Format,Args]) end; -write_event({_Time, _Error}) -> +write_event({_Time, _Error},_IOMod) -> ok. maybe_utc(Time) -> @@ -178,8 +180,9 @@ maybe_utc(Time) -> Time end. -format(String) -> io:format(user, String, []). -format(String, Args) -> io:format(user, String, Args). +format(IOMod, String) -> format(IOMod, String, []). +format(io_lib, String, Args) -> io_lib:format(String, Args); +format(io, String, Args) -> io:format(user, String, Args). format_report(Rep) when is_list(Rep) -> case string_p(Rep) of diff --git a/lib/xmerl/src/xmerl_scan.erl b/lib/xmerl/src/xmerl_scan.erl index e598c5f56d..25c6547497 100644 --- a/lib/xmerl/src/xmerl_scan.erl +++ b/lib/xmerl/src/xmerl_scan.erl @@ -2074,10 +2074,10 @@ scan_element(T, S, Pos, Name, StartL, StartC, Attrs, Lang, Parents, {AttName, NamespaceInfo, T1, S1} = scan_name(T, S), {T2, S2} = scan_eq(T1, S1), {AttType,_DefaultDecl} = get_att_type(S2,AttName,Name), - {AttValue, T3, S3,IsNorm} = scan_att_value(T2, S2, AttType), + {AttValue, T3a, S3a,IsNorm} = scan_att_value(T2, S2, AttType), %% check_default_value(S3,DefaultDecl,AttValue), NewNS = check_namespace(AttName, NamespaceInfo, AttValue, NS), - wfc_whitespace_betw_attrs(hd(T3),S3), + {T3,S3} = wfc_whitespace_betw_attrs(T3a,S3a), ?strip4, AttrPos = case Attrs of [] -> @@ -3284,12 +3284,17 @@ wfc_legal_char(Ch,S) -> end. -wfc_whitespace_betw_attrs(WS,_S) when ?whitespace(WS) -> - ok; -wfc_whitespace_betw_attrs($/,_S) -> - ok; -wfc_whitespace_betw_attrs($>,_S) -> - ok; +wfc_whitespace_betw_attrs([WS |_]=L,S) when ?whitespace(WS) -> + {L,S}; +wfc_whitespace_betw_attrs([$/ |_]=L,S) -> + {L,S}; +wfc_whitespace_betw_attrs([$> |_]=L,S) -> + {L,S}; +wfc_whitespace_betw_attrs([],S=#xmerl_scanner{continuation_fun = F}) -> + ?dbg("cont()...~n", []), + F(fun(MoreBytes, S1) -> wfc_whitespace_betw_attrs(MoreBytes, S1) end, + fun(S1) -> ?fatal(unexpected_end, S1) end, + S); wfc_whitespace_betw_attrs(_,S) -> ?fatal({whitespace_required_between_attributes},S). diff --git a/lib/xmerl/src/xmerl_xsd.erl b/lib/xmerl/src/xmerl_xsd.erl index 50c0a79016..dfdc6138ef 100644 --- a/lib/xmerl/src/xmerl_xsd.erl +++ b/lib/xmerl/src/xmerl_xsd.erl @@ -355,9 +355,9 @@ initiate_state(Opts,Schema) -> XSDBase = filename:dirname(Schema), {{state,S},RestOpts}=new_state(Opts), S2 = create_tables(S), - S3 = initiate_state2(S2#xsd_state{schema_name = Schema, xsd_base=XSDBase, - fetch_fun = fun fetch/2}, - RestOpts). + initiate_state2(S2#xsd_state{schema_name = Schema, xsd_base=XSDBase, + fetch_fun = fun fetch/2}, + RestOpts). initiate_state2(S,[]) -> S; diff --git a/lib/xmerl/test/xmerl_SUITE.erl b/lib/xmerl/test/xmerl_SUITE.erl index 0c809dbcb6..94c38d4d48 100644 --- a/lib/xmerl/test/xmerl_SUITE.erl +++ b/lib/xmerl/test/xmerl_SUITE.erl @@ -58,7 +58,7 @@ groups() -> {ticket_tests, [], [ticket_5998, ticket_7211, ticket_7214, ticket_7430, ticket_6873, ticket_7496, ticket_8156, ticket_8697, - ticket_9411]}, + ticket_9411, ticket_9457]}, {app_test, [], [{xmerl_app_test, all}]}, {appup_test, [], [{xmerl_appup_test, all}]}]. @@ -588,7 +588,26 @@ ticket_9411(Config) -> ?line {E, _} = xmerl_scan:string(Xml), ?line {E, _} = xmerl_xsd:validate(E, Schema). - +ticket_9457(suite) -> []; +ticket_9457(doc) -> + ["Test that xmerl_scan handles continuation correct when current input runs out at the end of an attribute value"]; +ticket_9457(Config) -> + Opts = [{continuation_fun, fun ticket_9457_cont/3, start}, {space, normalize}], + ?line {E, _} = xmerl_scan:string([], Opts). + +ticket_9457_cont(Continue, Exception, GlobalState) -> + case xmerl_scan:cont_state(GlobalState) of + start -> + G1 = xmerl_scan:cont_state(next, GlobalState), + Bytes = "<?xml version=\"1.0\" ?>\r\n<item a=\"b\"", + Continue(Bytes, G1); + next -> + G1 = xmerl_scan:cont_state(last, GlobalState), + Bytes = ">blah</item>\r\n", + Continue(Bytes, G1); + _ -> + Exception(GlobalState) + end. %%====================================================================== %% Support Functions diff --git a/make/otp_release_targets.mk b/make/otp_release_targets.mk index 8058e634d4..229612630d 100644 --- a/make/otp_release_targets.mk +++ b/make/otp_release_targets.mk @@ -74,10 +74,10 @@ ifneq ($(XML_FILES),) # ---------------------------------------------------- # Generation of application index data # ---------------------------------------------------- -$(HTMLDIR)/$(APPLICATION).eix: $(XML_FILES) +$(HTMLDIR)/$(APPLICATION).eix: $(XML_FILES) $(SPECS_FILES) date=`date +"%B %e %Y"`; \ $(XSLTPROC) --stringparam docgen "$(DOCGEN)" \ - --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude \ + --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude $(TOP_SPECS_PARAM) \ -path $(DOCGEN)/priv/docbuilder_dtd -path $(DOCGEN)/priv/dtd_html_entities $(DOCGEN)/priv/xsl/db_eix.xsl book.xml > $@ docs: $(HTMLDIR)/$(APPLICATION).eix |