Skip to content

Commit 2a88bdc

Browse files
committed
Added buffering of dbms_output before the run.
`dbms_output` buffer content is now cached before the run starts. The outcomes from the output are spooled back to the buffer at the end of the run. That results in the outputs getting shown in the right order when executing `ut.run` in a PLSQL block that has some buffered data already. Resolves #482
1 parent e448d70 commit 2a88bdc

File tree

8 files changed

+128
-0
lines changed

8 files changed

+128
-0
lines changed

source/api/ut_runner.pkb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ create or replace package body ut_runner is
6666
begin
6767
begin
6868
ut_output_buffer.cleanup_buffer();
69+
ut_utils.save_dbms_output_to_cache();
6970

7071
ut_console_reporter_base.set_color_enabled(a_color_console);
7172
if a_reporters is null or a_reporters.count = 0 then
@@ -87,11 +88,13 @@ create or replace package body ut_runner is
8788
ut_utils.cleanup_temp_tables;
8889
ut_output_buffer.close(l_listener.reporters);
8990
ut_metadata.reset_source_definition_cache;
91+
ut_utils.read_cache_to_dbms_output();
9092
exception
9193
when others then
9294
ut_utils.cleanup_temp_tables;
9395
ut_output_buffer.close(l_listener.reporters);
9496
ut_metadata.reset_source_definition_cache;
97+
ut_utils.read_cache_to_dbms_output();
9598
dbms_output.put_line(dbms_utility.format_error_backtrace);
9699
dbms_output.put_line(dbms_utility.format_error_stack);
97100
raise;
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
create global temporary table ut_dbms_output_cache(
2+
/*
3+
utPLSQL - Version X.X.X.X
4+
Copyright 2016 - 2017 utPLSQL Project
5+
Licensed under the Apache License, Version 2.0 (the "License"):
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.
14+
*/
15+
/*
16+
* This table is not a global temporary table as it needs to allow cross-session data exchange
17+
* It is used however as a temporary table with multiple writers.
18+
* This is why it has very high initrans and has nologging
19+
*/
20+
seq_no number(20,0) not null,
21+
text varchar2(4000),
22+
constraint ut_dbms_output_cache_pk primary key(seq_no)
23+
) on commit preserve rows;

source/core/ut_utils.pkb

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,5 +397,56 @@ create or replace package body ut_utils is
397397
end if;
398398
return l_result;
399399
end;
400+
401+
procedure save_dbms_output_to_cache is
402+
l_status number;
403+
l_line varchar2(32767);
404+
l_line_no integer := 1;
405+
l_lines ut_varchar2_rows := ut_varchar2_rows();
406+
c_lines_limit constant integer := 100;
407+
pragma autonomous_transaction;
408+
409+
procedure flush_lines is
410+
begin
411+
insert into ut_dbms_output_cache (seq_no,text)
412+
select rownum, column_value
413+
from table(l_lines);
414+
l_lines.delete;
415+
end;
416+
begin
417+
loop
418+
dbms_output.get_line(line => l_line, status => l_status);
419+
exit when l_status = 1;
420+
l_lines := l_lines multiset union all ut_utils.convert_collection(ut_utils.clob_to_table(l_line||chr(7),4000));
421+
if l_lines.count > c_lines_limit then
422+
flush_lines();
423+
end if;
424+
end loop;
425+
flush_lines();
426+
commit;
427+
end;
428+
429+
procedure read_cache_to_dbms_output is
430+
l_lines_data sys_refcursor;
431+
l_lines ut_varchar2_rows;
432+
c_lines_limit constant integer := 100;
433+
pragma autonomous_transaction;
434+
begin
435+
open l_lines_data for select text from ut_dbms_output_cache order by seq_no;
436+
loop
437+
fetch l_lines_data bulk collect into l_lines limit c_lines_limit;
438+
for i in 1 .. l_lines.count loop
439+
if substr(l_lines(i),-1) = chr(7) then
440+
dbms_output.put_line(rtrim(l_lines(i),chr(7)));
441+
else
442+
dbms_output.put(l_lines(i));
443+
end if;
444+
end loop;
445+
exit when l_lines_data%notfound;
446+
end loop;
447+
delete from ut_dbms_output_cache;
448+
commit;
449+
end;
450+
400451
end ut_utils;
401452
/

source/core/ut_utils.pks

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,5 +257,20 @@ create or replace package ut_utils authid definer is
257257
*/
258258
function to_version(a_version_no varchar2) return t_version;
259259

260+
261+
/**
262+
* Saves data from dbms_output buffer into a global temporary table (cache)
263+
* used to store dbms_output buffer captured before the run
264+
*
265+
*/
266+
procedure save_dbms_output_to_cache;
267+
268+
/**
269+
* Reads data from global temporary table (cache) abd puts it back into dbms_output
270+
* used to recover dbms_output buffer data after a run is complete
271+
*
272+
*/
273+
procedure read_cache_to_dbms_output;
274+
260275
end ut_utils;
261276
/

source/install.sql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ alter session set current_schema = &&ut3_owner;
3232
alter session set plsql_warnings = 'ENABLE:ALL', 'DISABLE:(5004,5018,6000,6001,6003,6009,6010,7206)';
3333
--set define off
3434

35+
--dbms_output buffer cache table
36+
@@install_component.sql 'core/ut_dbms_output_cache.sql'
37+
3538
--common utilities
3639
@@install_component.sql 'core/types/ut_varchar2_list.tps'
3740
@@install_component.sql 'core/types/ut_varchar2_rows.tps'

source/uninstall.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ drop package ut_suite_manager;
7878

7979
drop package ut;
8080

81+
drop table ut_dbms_output_cache;
82+
8183
drop type ut_expectation_yminterval force;
8284

8385
drop type ut_expectation_varchar2 force;

test/ut_runner/test_ut_runner.pkb

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,5 +97,33 @@ end;';
9797
drop_test_package();
9898
end;
9999

100+
procedure run_keep_dbms_output_buffer is
101+
l_expected dbmsoutput_linesarray;
102+
l_actual dbmsoutput_linesarray;
103+
l_lines number := 100;
104+
begin
105+
--Arrange
106+
create_test_spec();
107+
create_test_body(0);
108+
l_expected := dbmsoutput_linesarray(
109+
'A text placed into DBMS_OUTPUT',
110+
'Another line',
111+
lpad('A very long line',10000,'a')
112+
);
113+
dbms_output.enable;
114+
dbms_output.put_line(l_expected(1));
115+
dbms_output.put_line(l_expected(2));
116+
dbms_output.put_line(l_expected(3));
117+
--Act
118+
ut3.ut.run('test_cache');
119+
120+
--Assert
121+
dbms_output.get_lines(lines => l_actual, numlines => l_lines);
122+
for i in 1 .. l_expected.count loop
123+
ut.expect(l_actual(i)).to_equal(l_expected(i));
124+
end loop;
125+
drop_test_package();
126+
end;
127+
100128
end;
101129
/

test/ut_runner/test_ut_runner.pks

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,8 @@ create or replace package test_ut_runner is
1818
--%test(run resets cache of package body after every run)
1919
procedure run_reset_package_body_cache;
2020

21+
--%test(does not consume dbms_output from before the run)
22+
procedure run_keep_dbms_output_buffer;
23+
2124
end;
2225
/

0 commit comments

Comments
 (0)