Skip to content

Commit 8fc2ea6

Browse files
committed
Further optimizations to suite parsing.
Changed functions to procedures to avoid copying of large memmory segments.
1 parent 248bf8c commit 8fc2ea6

File tree

5 files changed

+136
-85
lines changed

5 files changed

+136
-85
lines changed

source/api/ut_runner.pkb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ create or replace package body ut_runner is
128128
l_include_object_names := to_ut_object_list(a_include_objects, l_coverage_schema_names);
129129

130130
l_run := ut_run(
131-
ut_suite_manager.configure_execution_by_path(l_paths),
131+
null,
132132
l_paths,
133133
l_coverage_schema_names,
134134
l_exclude_object_names,
@@ -137,6 +137,7 @@ create or replace package body ut_runner is
137137
set(a_test_file_mappings),
138138
a_client_character_set
139139
);
140+
ut_suite_manager.configure_execution_by_path(l_paths, l_run.items);
140141
l_run.do_execute();
141142

142143
finish_run(l_run);

source/core/annotations/ut_annotation_parser.pkb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ create or replace package body ut_annotation_parser as
155155
-- position index is shifted by 1 because gc_annot_comment_pattern contains ^ as first sign
156156
-- but after instr index already points to the char on that line
157157
l_comment_pos := l_comment_pos-1;
158-
l_comment_line := regexp_count(substr(a_source,1,l_comment_pos),chr(10),1,'m')+1;
158+
l_comment_line := length(substr(a_source,1,l_comment_pos))-length(replace(substr(a_source,1,l_comment_pos),chr(10)))+1;
159159
l_comments(l_comment_line) := trim(regexp_substr(srcstr => a_source
160160
,pattern => gc_annot_comment_pattern
161161
,occurrence => 1

source/core/ut_suite_cache_manager.pkb

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,11 @@ create or replace package body ut_suite_cache_manager is
138138
procedure remove_from_cache(a_schema_name varchar2, a_objects ut_varchar2_rows) is
139139
pragma autonomous_transaction;
140140
begin
141-
delete
142-
from ut_suite_cache_package i
141+
delete from ut_suite_cache i
142+
where i.object_owner = a_schema_name
143+
and i.object_name in ( select column_value from table (a_objects) );
144+
145+
delete from ut_suite_cache_package i
143146
where i.object_owner = a_schema_name
144147
and i.object_name in ( select column_value from table (a_objects) );
145148

source/core/ut_suite_manager.pkb

Lines changed: 119 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ create or replace package body ut_suite_manager is
2929
type tt_cached_suites is table of t_cached_suite;
3030
type t_cached_suites_cursor is ref cursor return t_cached_suite;
3131

32+
type t_item_levels is table of ut_suite_items index by binary_integer;
3233
------------------
3334

3435
procedure validate_paths(a_paths in ut_varchar2_list) is
@@ -167,48 +168,30 @@ create or replace package body ut_suite_manager is
167168
end loop;
168169
end;
169170

170-
procedure reconstruct_from_cache(
171-
a_suites out nocopy ut_suite_items,
172-
a_suite_data_cursor sys_refcursor
173-
) is
174-
type t_item_levels is table of ut_suite_items index by binary_integer;
175-
c_bulk_limit constant pls_integer := 1000;
176-
l_items_at_level t_item_levels;
177-
l_rows tt_cached_suites;
178-
l_test ut_test;
179-
l_logical_suite ut_logical_suite;
180-
l_level pls_integer;
181-
l_prev_level pls_integer;
182-
l_idx integer;
171+
function get_logical_suite(
172+
l_rows tt_cached_suites,
173+
l_idx pls_integer,
174+
l_level pls_integer,
175+
l_prev_level pls_integer,
176+
l_items_at_level t_item_levels
177+
) return ut_logical_suite is
183178
begin
184-
a_suites := ut_suite_items();
185-
loop
186-
fetch a_suite_data_cursor bulk collect into l_rows limit c_bulk_limit;
187-
exit when l_rows.count = 0;
188-
189-
l_idx := l_rows.first;
190-
loop
191-
l_test := null;
192-
l_logical_suite := null;
193-
case l_rows(l_idx).self_type
194-
when 'UT_TEST' then
195-
l_test :=
196-
ut_test(
179+
return
180+
case l_rows(l_idx).self_type
181+
when 'UT_SUITE' then
182+
case when l_prev_level > l_level then
183+
ut_suite(
197184
self_type => l_rows(l_idx).self_type,
198185
object_owner => l_rows(l_idx).object_owner, object_name => lower(l_rows(l_idx).object_name),
199186
name => lower(l_rows(l_idx).name), description => l_rows(l_idx).description, path => l_rows(l_idx).path,
200187
rollback_type => l_rows(l_idx).rollback_type, disabled_flag => l_rows(l_idx).disabled_flag,
201188
line_no => l_rows(l_idx).line_no, parse_time => l_rows(l_idx).parse_time,
202189
start_time => null, end_time => null, result => null, warnings => l_rows(l_idx).warnings,
203190
results_count => ut_results_counter(), transaction_invalidators => ut_varchar2_list(),
204-
before_each_list => sort_by_seq_no(l_rows(l_idx).before_each_list), before_test_list => sort_by_seq_no(l_rows(l_idx).before_test_list),
205-
item => l_rows(l_idx).item,
206-
after_test_list => sort_by_seq_no(l_rows(l_idx).after_test_list), after_each_list => sort_by_seq_no(l_rows(l_idx).after_each_list),
207-
all_expectations => ut_expectation_results(), failed_expectations => ut_expectation_results(),
208-
parent_error_stack_trace => null, expected_error_codes => l_rows(l_idx).expected_error_codes
209-
);
210-
when 'UT_SUITE' then
211-
l_logical_suite :=
191+
items => l_items_at_level(l_prev_level),
192+
before_all_list => sort_by_seq_no(l_rows(l_idx).before_all_list), after_all_list => sort_by_seq_no(l_rows(l_idx).after_all_list)
193+
)
194+
else
212195
ut_suite(
213196
self_type => l_rows(l_idx).self_type,
214197
object_owner => l_rows(l_idx).object_owner, object_name => lower(l_rows(l_idx).object_name),
@@ -219,9 +202,22 @@ create or replace package body ut_suite_manager is
219202
results_count => ut_results_counter(), transaction_invalidators => ut_varchar2_list(),
220203
items => ut_suite_items(),
221204
before_all_list => sort_by_seq_no(l_rows(l_idx).before_all_list), after_all_list => sort_by_seq_no(l_rows(l_idx).after_all_list)
222-
);
223-
when 'UT_SUITE_CONTEXT' then
224-
l_logical_suite :=
205+
)
206+
end
207+
when 'UT_SUITE_CONTEXT' then
208+
case when l_prev_level > l_level then
209+
ut_suite_context(
210+
self_type => l_rows(l_idx).self_type,
211+
object_owner => l_rows(l_idx).object_owner, object_name => lower(l_rows(l_idx).object_name),
212+
name => lower(l_rows(l_idx).name), description => l_rows(l_idx).description, path => l_rows(l_idx).path,
213+
rollback_type => l_rows(l_idx).rollback_type, disabled_flag => l_rows(l_idx).disabled_flag,
214+
line_no => l_rows(l_idx).line_no, parse_time => l_rows(l_idx).parse_time,
215+
start_time => null, end_time => null, result => null, warnings => l_rows(l_idx).warnings,
216+
results_count => ut_results_counter(), transaction_invalidators => ut_varchar2_list(),
217+
items => l_items_at_level(l_prev_level),
218+
before_all_list => sort_by_seq_no(l_rows(l_idx).before_all_list), after_all_list => sort_by_seq_no(l_rows(l_idx).after_all_list)
219+
)
220+
else
225221
ut_suite_context(
226222
self_type => l_rows(l_idx).self_type,
227223
object_owner => l_rows(l_idx).object_owner, object_name => lower(l_rows(l_idx).object_name),
@@ -232,9 +228,21 @@ create or replace package body ut_suite_manager is
232228
results_count => ut_results_counter(), transaction_invalidators => ut_varchar2_list(),
233229
items => ut_suite_items(),
234230
before_all_list => sort_by_seq_no(l_rows(l_idx).before_all_list), after_all_list => sort_by_seq_no(l_rows(l_idx).after_all_list)
235-
);
236-
when 'UT_LOGICAL_SUITE' then
237-
l_logical_suite :=
231+
)
232+
end
233+
when 'UT_LOGICAL_SUITE' then
234+
case when l_prev_level > l_level then
235+
ut_logical_suite(
236+
self_type => l_rows(l_idx).self_type,
237+
object_owner => l_rows(l_idx).object_owner, object_name => lower(l_rows(l_idx).object_name),
238+
name => lower(l_rows(l_idx).name), description => l_rows(l_idx).description, path => l_rows(l_idx).path,
239+
rollback_type => l_rows(l_idx).rollback_type, disabled_flag => l_rows(l_idx).disabled_flag,
240+
line_no => l_rows(l_idx).line_no, parse_time => l_rows(l_idx).parse_time,
241+
start_time => null, end_time => null, result => null, warnings => l_rows(l_idx).warnings,
242+
results_count => ut_results_counter(), transaction_invalidators => ut_varchar2_list(),
243+
items => l_items_at_level(l_prev_level)
244+
)
245+
else
238246
ut_logical_suite(
239247
self_type => l_rows(l_idx).self_type,
240248
object_owner => l_rows(l_idx).object_owner, object_name => lower(l_rows(l_idx).object_name),
@@ -244,32 +252,62 @@ create or replace package body ut_suite_manager is
244252
start_time => null, end_time => null, result => null, warnings => l_rows(l_idx).warnings,
245253
results_count => ut_results_counter(), transaction_invalidators => ut_varchar2_list(),
246254
items => ut_suite_items()
247-
);
248-
end case;
255+
)
256+
end
257+
end;
258+
end;
259+
260+
procedure reconstruct_from_cache(
261+
a_suites in out nocopy ut_suite_items,
262+
a_suite_data_cursor sys_refcursor
263+
) is
264+
c_bulk_limit constant pls_integer := 1000;
265+
l_items_at_level t_item_levels;
266+
l_rows tt_cached_suites;
267+
l_logical_suite ut_logical_suite;
268+
l_level pls_integer;
269+
l_prev_level pls_integer;
270+
l_idx integer;
271+
begin
272+
loop
273+
fetch a_suite_data_cursor bulk collect into l_rows limit c_bulk_limit;
274+
exit when l_rows.count = 0;
249275

276+
l_idx := l_rows.first;
277+
loop
250278
l_level := length(l_rows(l_idx).path) - length( replace(l_rows(l_idx).path, '.') ) + 1;
251-
252279
if l_level > 1 then
253-
if l_prev_level > l_level then
254-
l_logical_suite.items := l_items_at_level(l_prev_level);
255-
l_items_at_level(l_prev_level).delete;
256-
end if;
257280
if not l_items_at_level.exists(l_level) then
258281
l_items_at_level(l_level) := ut_suite_items();
259282
end if;
260283
l_items_at_level(l_level).extend;
261-
if l_test is not null then
262-
l_items_at_level(l_level)(l_items_at_level(l_level).last) := l_test;
284+
if l_rows(l_idx).self_type = 'UT_TEST' then
285+
l_items_at_level(l_level)(l_items_at_level(l_level).last) :=
286+
ut_test(
287+
self_type => l_rows(l_idx).self_type,
288+
object_owner => l_rows(l_idx).object_owner, object_name => lower(l_rows(l_idx).object_name),
289+
name => lower(l_rows(l_idx).name), description => l_rows(l_idx).description, path => l_rows(l_idx).path,
290+
rollback_type => l_rows(l_idx).rollback_type, disabled_flag => l_rows(l_idx).disabled_flag,
291+
line_no => l_rows(l_idx).line_no, parse_time => l_rows(l_idx).parse_time,
292+
start_time => null, end_time => null, result => null, warnings => l_rows(l_idx).warnings,
293+
results_count => ut_results_counter(), transaction_invalidators => ut_varchar2_list(),
294+
before_each_list => sort_by_seq_no(l_rows(l_idx).before_each_list), before_test_list => sort_by_seq_no(l_rows(l_idx).before_test_list),
295+
item => l_rows(l_idx).item,
296+
after_test_list => sort_by_seq_no(l_rows(l_idx).after_test_list), after_each_list => sort_by_seq_no(l_rows(l_idx).after_each_list),
297+
all_expectations => ut_expectation_results(), failed_expectations => ut_expectation_results(),
298+
parent_error_stack_trace => null, expected_error_codes => l_rows(l_idx).expected_error_codes
299+
);
263300
else
264-
l_items_at_level(l_level)(l_items_at_level(l_level).last) := l_logical_suite;
265-
end if;
301+
pragma inline(get_logical_suite, 'YES');
302+
l_items_at_level(l_level)(l_items_at_level(l_level).last) := get_logical_suite(l_rows, l_idx, l_level,l_prev_level, l_items_at_level );
303+
end if;
266304
else
267-
if l_prev_level > l_level then
268-
l_logical_suite.items := l_items_at_level(l_prev_level);
269-
l_items_at_level(l_prev_level).delete;
270-
end if;
271305
a_suites.extend;
272-
a_suites(a_suites.last) := l_logical_suite;
306+
pragma inline(get_logical_suite, 'YES');
307+
a_suites(a_suites.last) := get_logical_suite(l_rows, l_idx, l_level,l_prev_level, l_items_at_level );
308+
end if;
309+
if l_prev_level > l_level then
310+
l_items_at_level(l_prev_level).delete;
273311
end if;
274312
l_prev_level := l_level;
275313
l_idx := l_rows.next(l_idx);
@@ -483,18 +521,18 @@ create or replace package body ut_suite_manager is
483521

484522
end;
485523

486-
function get_suites_for_path(
524+
procedure add_suites_for_path(
487525
a_owner_name varchar2,
488526
a_path varchar2 := null,
489527
a_object_name varchar2 := null,
490-
a_procedure_name varchar2 := null
491-
) return ut_suite_items is
492-
l_suites ut_suite_items;
528+
a_procedure_name varchar2 := null,
529+
a_suites in out nocopy ut_suite_items
530+
) is
493531
begin
494532
refresh_cache(a_owner_name);
495533

496534
reconstruct_from_cache(
497-
l_suites,
535+
a_suites,
498536
get_cached_suite_data(
499537
a_owner_name,
500538
a_path,
@@ -503,9 +541,8 @@ create or replace package body ut_suite_manager is
503541
can_skip_all_objects_scan(a_owner_name)
504542
)
505543
);
506-
return l_suites;
507544

508-
end get_suites_for_path;
545+
end;
509546

510547
-----------------------------------------------
511548
-----------------------------------------------
@@ -519,7 +556,7 @@ create or replace package body ut_suite_manager is
519556
a_procedure_name varchar2 := null,
520557
a_skip_all_objects boolean := false
521558
) return ut_suite_items is
522-
l_suites ut_suite_items;
559+
l_suites ut_suite_items := ut_suite_items();
523560
begin
524561
build_and_cache_suites(a_owner_name, a_annotated_objects);
525562

@@ -578,58 +615,59 @@ create or replace package body ut_suite_manager is
578615
end;
579616

580617
function configure_execution_by_path(a_paths in ut_varchar2_list) return ut_suite_items is
618+
l_suites ut_suite_items := ut_suite_items();
619+
begin
620+
configure_execution_by_path(a_paths, l_suites );
621+
return l_suites;
622+
end;
623+
624+
procedure configure_execution_by_path(a_paths in ut_varchar2_list, a_suites out nocopy ut_suite_items) is
581625
l_paths ut_varchar2_list := a_paths;
582626
l_path_items t_path_items;
583627
l_path_item t_path_item;
584628
l_schema varchar2(4000);
585-
l_suites ut_suite_items;
629+
l_suites_count pls_integer := 0;
586630
l_index varchar2(4000 char);
587-
l_objects_to_run ut_suite_items;
588631
l_schema_paths t_schema_paths;
589632
begin
633+
a_suites := ut_suite_items();
590634
--resolve schema names from paths and group paths by schema name
591635
resolve_schema_names(l_paths);
592636

593637
l_schema_paths := group_paths_by_schema(l_paths);
594638

595-
l_objects_to_run := ut_suite_items();
596-
597639
l_schema := l_schema_paths.first;
598640
while l_schema is not null loop
599641
l_path_items := l_schema_paths(l_schema);
600642
for i in 1 .. l_path_items.count loop
601643
l_path_item := l_path_items(i);
602-
l_suites := get_suites_for_path(
644+
add_suites_for_path(
603645
upper(l_schema),
604646
l_path_item.suite_path,
605647
l_path_item.object_name,
606-
l_path_item.procedure_name
648+
l_path_item.procedure_name,
649+
a_suites
607650
);
608-
if l_suites.count = 0 then
651+
if a_suites.count = l_suites_count then
609652
if l_path_item.suite_path is not null then
610653
raise_application_error(ut_utils.gc_suite_package_not_found,'No suite packages found for path '||l_schema||':'||l_path_item.suite_path|| '.');
611654
elsif l_path_item.procedure_name is not null then
612655
raise_application_error(ut_utils.gc_suite_package_not_found,'Suite test '||l_schema||'.'||l_path_item.object_name|| '.'||l_path_item.procedure_name||' does not exist');
613-
else
656+
elsif l_path_item.object_name is not null then
614657
raise_application_error(ut_utils.gc_suite_package_not_found,'Suite package '||l_schema||'.'||l_path_item.object_name|| ' does not exist');
615658
end if;
616659
end if;
617-
l_index := l_suites.first;
618-
while l_index is not null loop
619-
l_objects_to_run.extend;
620-
l_objects_to_run(l_objects_to_run.count) := l_suites(l_index);
621-
l_index := l_suites.next(l_index);
622-
end loop;
660+
l_index := a_suites.first;
661+
l_suites_count := a_suites.count;
623662
end loop;
624663
l_schema := l_schema_paths.next(l_schema);
625664
end loop;
626665

627666
--propagate rollback type to suite items after organizing suites into hierarchy
628-
for i in 1 .. l_objects_to_run.count loop
629-
l_objects_to_run(i).set_rollback_type( l_objects_to_run(i).get_rollback_type() );
667+
for i in 1 .. a_suites.count loop
668+
a_suites(i).set_rollback_type( a_suites(i).get_rollback_type() );
630669
end loop;
631670

632-
return l_objects_to_run;
633671
end configure_execution_by_path;
634672

635673
function get_suites_info(a_owner_name varchar2) return tt_suite_items pipelined is

source/core/ut_suite_manager.pks

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,15 @@ create or replace package ut_suite_manager authid current_user is
3939
*/
4040
function configure_execution_by_path(a_paths in ut_varchar2_list) return ut_suite_items;
4141

42+
/**
43+
* Builds a hierarchical suites based on given suite-paths
44+
*
45+
* @param a_paths list of suite-paths or procedure names or package names or schema names
46+
* @param a_suites returned array containing root suites-ready to be executed
47+
*
48+
*/
49+
procedure configure_execution_by_path(a_paths in ut_varchar2_list, a_suites out nocopy ut_suite_items);
50+
4251
/**
4352
* Cleanup paths by removing leading/trailing whitespace and making paths lowercase
4453
* Get list of schema names from execution paths.

0 commit comments

Comments
 (0)