diff --git a/source/api/ut_runner.pkb b/source/api/ut_runner.pkb index e3141b527..fcf44ba7b 100644 --- a/source/api/ut_runner.pkb +++ b/source/api/ut_runner.pkb @@ -66,6 +66,7 @@ create or replace package body ut_runner is begin begin ut_output_buffer.cleanup_buffer(); + ut_utils.save_dbms_output_to_cache(); ut_console_reporter_base.set_color_enabled(a_color_console); if a_reporters is null or a_reporters.count = 0 then @@ -87,11 +88,13 @@ create or replace package body ut_runner is ut_utils.cleanup_temp_tables; ut_output_buffer.close(l_listener.reporters); ut_metadata.reset_source_definition_cache; + ut_utils.read_cache_to_dbms_output(); exception when others then ut_utils.cleanup_temp_tables; ut_output_buffer.close(l_listener.reporters); ut_metadata.reset_source_definition_cache; + ut_utils.read_cache_to_dbms_output(); dbms_output.put_line(dbms_utility.format_error_backtrace); dbms_output.put_line(dbms_utility.format_error_stack); raise; diff --git a/source/core/ut_dbms_output_cache.sql b/source/core/ut_dbms_output_cache.sql new file mode 100644 index 000000000..4ac1a9191 --- /dev/null +++ b/source/core/ut_dbms_output_cache.sql @@ -0,0 +1,23 @@ +create global temporary table ut_dbms_output_cache( + /* + utPLSQL - Version X.X.X.X + Copyright 2016 - 2017 utPLSQL Project + Licensed under the Apache License, Version 2.0 (the "License"): + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + /* + * This table is not a global temporary table as it needs to allow cross-session data exchange + * It is used however as a temporary table with multiple writers. + * This is why it has very high initrans and has nologging + */ + seq_no number(20,0) not null, + text varchar2(4000), + constraint ut_dbms_output_cache_pk primary key(seq_no) +) on commit preserve rows; diff --git a/source/core/ut_utils.pkb b/source/core/ut_utils.pkb index ceb962f23..83edb74a4 100644 --- a/source/core/ut_utils.pkb +++ b/source/core/ut_utils.pkb @@ -397,5 +397,56 @@ create or replace package body ut_utils is end if; return l_result; end; + + procedure save_dbms_output_to_cache is + l_status number; + l_line varchar2(32767); + l_line_no integer := 1; + l_lines ut_varchar2_rows := ut_varchar2_rows(); + c_lines_limit constant integer := 100; + pragma autonomous_transaction; + + procedure flush_lines is + begin + insert into ut_dbms_output_cache (seq_no,text) + select rownum, column_value + from table(l_lines); + l_lines.delete; + end; + begin + loop + dbms_output.get_line(line => l_line, status => l_status); + exit when l_status = 1; + l_lines := l_lines multiset union all ut_utils.convert_collection(ut_utils.clob_to_table(l_line||chr(7),4000)); + if l_lines.count > c_lines_limit then + flush_lines(); + end if; + end loop; + flush_lines(); + commit; + end; + + procedure read_cache_to_dbms_output is + l_lines_data sys_refcursor; + l_lines ut_varchar2_rows; + c_lines_limit constant integer := 100; + pragma autonomous_transaction; + begin + open l_lines_data for select text from ut_dbms_output_cache order by seq_no; + loop + fetch l_lines_data bulk collect into l_lines limit c_lines_limit; + for i in 1 .. l_lines.count loop + if substr(l_lines(i),-1) = chr(7) then + dbms_output.put_line(rtrim(l_lines(i),chr(7))); + else + dbms_output.put(l_lines(i)); + end if; + end loop; + exit when l_lines_data%notfound; + end loop; + delete from ut_dbms_output_cache; + commit; + end; + end ut_utils; / diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 4d2c2c070..fe7b73a69 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -257,5 +257,20 @@ create or replace package ut_utils authid definer is */ function to_version(a_version_no varchar2) return t_version; + + /** + * Saves data from dbms_output buffer into a global temporary table (cache) + * used to store dbms_output buffer captured before the run + * + */ + procedure save_dbms_output_to_cache; + + /** + * Reads data from global temporary table (cache) abd puts it back into dbms_output + * used to recover dbms_output buffer data after a run is complete + * + */ + procedure read_cache_to_dbms_output; + end ut_utils; / diff --git a/source/install.sql b/source/install.sql index 71bc70eeb..bd19576d3 100644 --- a/source/install.sql +++ b/source/install.sql @@ -32,6 +32,9 @@ alter session set current_schema = &&ut3_owner; alter session set plsql_warnings = 'ENABLE:ALL', 'DISABLE:(5004,5018,6000,6001,6003,6009,6010,7206)'; --set define off +--dbms_output buffer cache table +@@install_component.sql 'core/ut_dbms_output_cache.sql' + --common utilities @@install_component.sql 'core/types/ut_varchar2_list.tps' @@install_component.sql 'core/types/ut_varchar2_rows.tps' diff --git a/source/uninstall.sql b/source/uninstall.sql index 48aba7d04..a786fb330 100644 --- a/source/uninstall.sql +++ b/source/uninstall.sql @@ -78,6 +78,8 @@ drop package ut_suite_manager; drop package ut; +drop table ut_dbms_output_cache; + drop type ut_expectation_yminterval force; drop type ut_expectation_varchar2 force; diff --git a/test/ut_runner/test_ut_runner.pkb b/test/ut_runner/test_ut_runner.pkb index 5c8e4fb26..b6f958413 100644 --- a/test/ut_runner/test_ut_runner.pkb +++ b/test/ut_runner/test_ut_runner.pkb @@ -97,5 +97,33 @@ end;'; drop_test_package(); end; + procedure run_keep_dbms_output_buffer is + l_expected dbmsoutput_linesarray; + l_actual dbmsoutput_linesarray; + l_lines number := 100; + begin + --Arrange + create_test_spec(); + create_test_body(0); + l_expected := dbmsoutput_linesarray( + 'A text placed into DBMS_OUTPUT', + 'Another line', + lpad('A very long line',10000,'a') + ); + dbms_output.enable; + dbms_output.put_line(l_expected(1)); + dbms_output.put_line(l_expected(2)); + dbms_output.put_line(l_expected(3)); + --Act + ut3.ut.run('test_cache'); + + --Assert + dbms_output.get_lines(lines => l_actual, numlines => l_lines); + for i in 1 .. l_expected.count loop + ut.expect(l_actual(i)).to_equal(l_expected(i)); + end loop; + drop_test_package(); + end; + end; / diff --git a/test/ut_runner/test_ut_runner.pks b/test/ut_runner/test_ut_runner.pks index 993cd1770..06a212a8a 100644 --- a/test/ut_runner/test_ut_runner.pks +++ b/test/ut_runner/test_ut_runner.pks @@ -18,5 +18,8 @@ create or replace package test_ut_runner is --%test(run resets cache of package body after every run) procedure run_reset_package_body_cache; + --%test(does not consume dbms_output from before the run) + procedure run_keep_dbms_output_buffer; + end; /