From e8f453291b58f90bde2fbac6a6b8562757997905 Mon Sep 17 00:00:00 2001 From: pesse Date: Thu, 19 Dec 2019 15:38:07 +0100 Subject: [PATCH 01/11] Skip as many %endcontext as nested %context annotations We need to make sure to calculate the corrent %endcontext annotation, not just the first that is greater than the next nested %context. To operate correctly during recursion we also need information about the parent %endcontext position Fixes #1034 --- source/core/ut_suite_builder.pkb | 56 ++++++++++++++--- test/ut3_tester/core/test_suite_builder.pkb | 68 +++++++++++++++++++++ test/ut3_tester/core/test_suite_builder.pks | 5 ++ 3 files changed, 119 insertions(+), 10 deletions(-) diff --git a/source/core/ut_suite_builder.pkb b/source/core/ut_suite_builder.pkb index c7e968467..f40d2f2a1 100644 --- a/source/core/ut_suite_builder.pkb +++ b/source/core/ut_suite_builder.pkb @@ -708,15 +708,49 @@ create or replace package body ut_suite_builder is a_context_ann_pos t_annotation_position, a_package_annotations in out nocopy tt_annotations_by_name ) return t_annotation_position is - l_result t_annotation_position; + l_next_endcontext_pos t_annotation_position; + l_next_context_pos t_annotation_position; + l_open_count integer := 0; begin if a_package_annotations.exists(gc_endcontext) then - l_result := a_package_annotations(gc_endcontext).first; - while l_result <= a_context_ann_pos loop - l_result := a_package_annotations(gc_endcontext).next(l_result); + l_next_endcontext_pos := a_package_annotations(gc_endcontext).first; + while l_next_endcontext_pos <= a_context_ann_pos loop + l_next_endcontext_pos := a_package_annotations(gc_endcontext).next(l_next_endcontext_pos); end loop; + + l_next_context_pos := a_package_annotations(gc_context).next(a_context_ann_pos); + loop + -- Get all the %context annotations between start and first %endcontext + while l_next_context_pos is not null and l_next_context_pos < l_next_endcontext_pos loop + l_open_count := l_open_count+1; + l_next_context_pos := a_package_annotations(gc_context).next(l_next_context_pos); + end loop; + -- Skip as many %endcontexts as we had additional contexts open + while l_open_count > 0 loop + l_open_count := l_open_count-1; + l_next_endcontext_pos := a_package_annotations(gc_endcontext).next(l_next_endcontext_pos); + end loop; + -- Repeat until the next %context is later than next %endcontext + exit when l_next_context_pos is null or l_next_context_pos > l_next_endcontext_pos; + end loop; end if; - return l_result; + return l_next_endcontext_pos; + end; + + function has_nested_context( + a_context_ann_pos t_annotation_position, + a_package_annotations in out nocopy tt_annotations_by_name + ) return boolean is + l_next_endcontext_pos t_annotation_position; + begin + if ( a_package_annotations.exists(gc_endcontext) and a_package_annotations.exists(gc_context)) then + l_next_endcontext_pos := a_package_annotations(gc_endcontext).first; + while l_next_endcontext_pos <= a_context_ann_pos loop + l_next_endcontext_pos := a_package_annotations(gc_endcontext).next(l_next_endcontext_pos); + end loop; + return l_next_endcontext_pos > a_package_annotations(gc_context).next(a_context_ann_pos); + end if; + return false; end; function get_annotations_in_context( @@ -753,7 +787,8 @@ create or replace package body ut_suite_builder is a_parent in out nocopy ut_suite, a_annotations in out nocopy t_annotations_info, a_suite_items out nocopy ut_suite_items, - a_parent_context_pos in integer := 0 + a_parent_context_pos in integer := 0, + a_parent_end_context_pos in integer default null ) is l_context_pos t_annotation_position; l_next_context_pos t_annotation_position; @@ -802,7 +837,6 @@ create or replace package body ut_suite_builder is l_default_context_name := 'nested_context_#'||l_context_no; l_context_name := null; l_end_context_pos := get_endcontext_position(l_context_pos, a_annotations.by_name ); - l_next_context_pos := a_annotations.by_name(gc_context).next(l_context_pos); if a_annotations.by_name.exists(gc_name) then l_context_name := @@ -841,9 +875,8 @@ create or replace package body ut_suite_builder is l_context.parse_time := a_annotations.parse_time; --if nested context found - if l_next_context_pos < l_end_context_pos or l_end_context_pos is null then - get_context_items( l_context, a_annotations, l_context_items, l_context_pos ); - l_end_context_pos := get_endcontext_position(l_context_pos, a_annotations.by_name ); + if has_nested_context(l_context_pos, a_annotations.by_name) then + get_context_items( l_context, a_annotations, l_context_items, l_context_pos, l_end_context_pos ); else l_context_items := ut_suite_items(); end if; @@ -870,6 +903,9 @@ create or replace package body ut_suite_builder is exit when not a_annotations.by_name.exists( gc_context); l_context_pos := a_annotations.by_name( gc_context).next( l_context_pos); + if ( a_parent_end_context_pos is not null and a_parent_end_context_pos <= l_context_pos ) then + l_context_pos := null; + end if; l_context_no := l_context_no + 1; end loop; end; diff --git a/test/ut3_tester/core/test_suite_builder.pkb b/test/ut3_tester/core/test_suite_builder.pkb index a204a04e6..8250eb96e 100644 --- a/test/ut3_tester/core/test_suite_builder.pkb +++ b/test/ut3_tester/core/test_suite_builder.pkb @@ -767,6 +767,74 @@ create or replace package body test_suite_builder is ); end; + procedure nested_contexts_2 is + l_actual clob; + l_annotations ut3.ut_annotations; + begin + --Arrange + l_annotations := ut3.ut_annotations( + ut3.ut_annotation( 1, 'suite','Cool', null), + ut3.ut_annotation( 2, 'suitepath','path', null), + ut3.ut_annotation( 3, 'context','Level 1', null), + ut3.ut_annotation( 4, 'name','context_1', null), + ut3.ut_annotation( 5, 'context','Level 1.1', null), + ut3.ut_annotation( 6, 'name','context_1_1', null), + ut3.ut_annotation( 7, 'test', 'Test 1.1.1', 'test_1_1_1'), + ut3.ut_annotation( 8, 'test', 'Test 1.1.2', 'test_1_1_2'), + ut3.ut_annotation( 9, 'endcontext', null, null), + ut3.ut_annotation(10, 'endcontext', null, null), + ut3.ut_annotation(11, 'context','Level 2', null), + ut3.ut_annotation(12, 'name','context_2', null), + ut3.ut_annotation(13, 'test', 'Test 2.1', 'test_2_1'), + ut3.ut_annotation(14, 'endcontext',null, null) + ); + --Act + l_actual := invoke_builder_for_annotations(l_annotations, 'SOME_PACKAGE'); + --Assert + ut.expect(l_actual).to_be_like( + ''|| + '' || + '%%' || + '' || + '%context_1Level 1path.some_package.context_1' || + '%' || + '' || + '%context_1_1Level 1.1path.some_package.context_1.context_1_1' || + '%' || + '' || + '%test_1_1_1Test 1.1.1path.some_package.context_1.context_1_1.test_1_1_1' || + '%' || + '' || + '%test_1_1_2Test 1.1.2path.some_package.context_1.context_1_1.test_1_1_2' || + '%' || + '' || + '%' || + '%' || + '' || + '%' || + '%' || + '%'|| + '' + ); + -- Test both contexts separately due to ordering + ut.expect(l_actual).to_be_like( + ''|| + '' || + '%%' || + '' || + '%context_2Level 2path.some_package.context_2' || + '%' || + '' || + '%test_2_1Test 2.1path.some_package.context_2.test_2_1' || + '%' || + '%' || + '%' || + '%' || + '%'|| + '' + ); + end; + procedure before_after_in_context is l_actual clob; diff --git a/test/ut3_tester/core/test_suite_builder.pks b/test/ut3_tester/core/test_suite_builder.pks index 7a85cb946..98a61171e 100644 --- a/test/ut3_tester/core/test_suite_builder.pks +++ b/test/ut3_tester/core/test_suite_builder.pks @@ -3,6 +3,7 @@ create or replace package test_suite_builder is --%suitepath(utplsql.ut3_tester.core) --%context(--%suite annotation) + --%name(suite) --%test(Sets suite name from package name and leaves description empty) procedure no_suite_description; @@ -105,6 +106,7 @@ create or replace package test_suite_builder is --%endcontext --%context(--%context annotation) + --%name(context) --%test(Creates nested suite for content between context/endcontext annotations) procedure suite_from_context; @@ -112,6 +114,9 @@ create or replace package test_suite_builder is --%test(Creates nested contexts inside a context) procedure nested_contexts; + --%test(Creates multiple nested contexts inside a context) + procedure nested_contexts_2; + --%test(Associates before/after all/each to tests in context only) procedure before_after_in_context; From 8df3f7d5d505f463d8ca5162e1bc608e0d8997b3 Mon Sep 17 00:00:00 2001 From: pesse Date: Thu, 19 Dec 2019 15:49:06 +0100 Subject: [PATCH 02/11] Refactoring: Extract function, add variables for readability --- source/core/ut_suite_builder.pkb | 36 ++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/source/core/ut_suite_builder.pkb b/source/core/ut_suite_builder.pkb index f40d2f2a1..a4a1da7ee 100644 --- a/source/core/ut_suite_builder.pkb +++ b/source/core/ut_suite_builder.pkb @@ -704,6 +704,22 @@ create or replace package body ut_suite_builder is set_seq_no(a_suite.after_all_list); end; + function get_next_annotation_of_type( + a_start_position t_annotation_position, + a_annotation_type varchar2, + a_package_annotations in out nocopy tt_annotations_by_name + ) return t_annotation_position is + l_result t_annotation_position; + begin + if a_package_annotations.exists(a_annotation_type) then + l_result := a_package_annotations(a_annotation_type).first; + while l_result <= a_start_position loop + l_result := a_package_annotations(a_annotation_type).next(l_result); + end loop; + end if; + return l_result; + end; + function get_endcontext_position( a_context_ann_pos t_annotation_position, a_package_annotations in out nocopy tt_annotations_by_name @@ -712,13 +728,10 @@ create or replace package body ut_suite_builder is l_next_context_pos t_annotation_position; l_open_count integer := 0; begin - if a_package_annotations.exists(gc_endcontext) then - l_next_endcontext_pos := a_package_annotations(gc_endcontext).first; - while l_next_endcontext_pos <= a_context_ann_pos loop - l_next_endcontext_pos := a_package_annotations(gc_endcontext).next(l_next_endcontext_pos); - end loop; + if a_package_annotations.exists(gc_endcontext) and a_package_annotations.exists(gc_context) then + l_next_endcontext_pos := get_next_annotation_of_type(a_context_ann_pos, gc_endcontext, a_package_annotations); + l_next_context_pos := a_package_annotations(gc_context).next(a_context_ann_pos); - l_next_context_pos := a_package_annotations(gc_context).next(a_context_ann_pos); loop -- Get all the %context annotations between start and first %endcontext while l_next_context_pos is not null and l_next_context_pos < l_next_endcontext_pos loop @@ -742,13 +755,14 @@ create or replace package body ut_suite_builder is a_package_annotations in out nocopy tt_annotations_by_name ) return boolean is l_next_endcontext_pos t_annotation_position; + l_next_context_pos t_annotation_position; begin if ( a_package_annotations.exists(gc_endcontext) and a_package_annotations.exists(gc_context)) then - l_next_endcontext_pos := a_package_annotations(gc_endcontext).first; - while l_next_endcontext_pos <= a_context_ann_pos loop - l_next_endcontext_pos := a_package_annotations(gc_endcontext).next(l_next_endcontext_pos); - end loop; - return l_next_endcontext_pos > a_package_annotations(gc_context).next(a_context_ann_pos); + l_next_endcontext_pos := get_next_annotation_of_type(a_context_ann_pos, gc_endcontext, a_package_annotations); + l_next_context_pos := a_package_annotations(gc_context).next(a_context_ann_pos); + if ( l_next_context_pos < l_next_endcontext_pos ) then + return true; + end if; end if; return false; end; From a4d92dea60e98246ec21db6bbc0dfa9a3fa46971 Mon Sep 17 00:00:00 2001 From: pesse Date: Thu, 19 Dec 2019 15:51:12 +0100 Subject: [PATCH 03/11] Refactoring: Add clarifying comment --- source/core/ut_suite_builder.pkb | 1 + 1 file changed, 1 insertion(+) diff --git a/source/core/ut_suite_builder.pkb b/source/core/ut_suite_builder.pkb index a4a1da7ee..810da27ab 100644 --- a/source/core/ut_suite_builder.pkb +++ b/source/core/ut_suite_builder.pkb @@ -917,6 +917,7 @@ create or replace package body ut_suite_builder is exit when not a_annotations.by_name.exists( gc_context); l_context_pos := a_annotations.by_name( gc_context).next( l_context_pos); + -- don't go on when the next context is outside the parent's context boundaries if ( a_parent_end_context_pos is not null and a_parent_end_context_pos <= l_context_pos ) then l_context_pos := null; end if; From 4d1500f9ac2c89aed17471bddf871ecdaceb200f Mon Sep 17 00:00:00 2001 From: pesse Date: Thu, 19 Dec 2019 21:04:21 +0100 Subject: [PATCH 04/11] Refactoring: Move responsibility to get context name completely to get_context_name --- source/core/ut_suite_builder.pkb | 53 ++++++++++++++++---------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/source/core/ut_suite_builder.pkb b/source/core/ut_suite_builder.pkb index 810da27ab..d013c107e 100644 --- a/source/core/ut_suite_builder.pkb +++ b/source/core/ut_suite_builder.pkb @@ -817,26 +817,35 @@ create or replace package body ut_suite_builder is l_default_context_name t_object_name; function get_context_name( a_parent in out nocopy ut_suite, - a_context_names in tt_annotation_texts, - a_start_position binary_integer, - a_end_position binary_integer + a_start_position binary_integer ) return varchar2 is l_result t_annotation_name; l_found boolean; + l_end_position binary_integer; l_annotation_pos binary_integer; + l_context_names tt_annotation_texts; begin - l_annotation_pos := a_context_names.first; - while l_annotation_pos is not null loop - if l_annotation_pos > a_start_position and l_annotation_pos < a_end_position then - if l_found then - add_annotation_ignored_warning(a_parent, gc_name,'Duplicate annotation %%%.', l_annotation_pos); - else - l_result := a_context_names(l_annotation_pos); - end if; - l_found := true; - end if; - l_annotation_pos := a_context_names.next(l_annotation_pos); - end loop; + if a_annotations.by_name.exists(gc_name) then + l_context_names := a_annotations.by_name( gc_name ); + l_end_position := + least( + coalesce( get_endcontext_position(a_start_position, a_annotations.by_name), a_annotations.by_line.last ), + coalesce( a_annotations.by_name(gc_context).next(a_start_position), a_annotations.by_line.last ) + ); + l_annotation_pos := l_context_names.first; + + while l_annotation_pos is not null loop + if l_annotation_pos > a_start_position and l_annotation_pos < l_end_position then + if l_found then + add_annotation_ignored_warning(a_parent, gc_name,'Duplicate annotation %%%.', l_annotation_pos); + else + l_result := l_context_names(l_annotation_pos); + end if; + l_found := true; + end if; + l_annotation_pos := l_context_names.next(l_annotation_pos); + end loop; + end if; return l_result; end; begin @@ -852,18 +861,8 @@ create or replace package body ut_suite_builder is l_context_name := null; l_end_context_pos := get_endcontext_position(l_context_pos, a_annotations.by_name ); l_next_context_pos := a_annotations.by_name(gc_context).next(l_context_pos); - if a_annotations.by_name.exists(gc_name) then - l_context_name := - get_context_name( - a_parent, - a_annotations.by_name( gc_name ), - l_context_pos, - least( - coalesce( l_end_context_pos, a_annotations.by_line.last ), - coalesce( l_next_context_pos, a_annotations.by_line.last ) - ) - ); - end if; + l_context_name := get_context_name(a_parent, l_context_pos); + if not regexp_like( l_context_name, '^(\w|[$#])+$' ) or l_context_name is null then if not regexp_like( l_context_name, '^(\w|[$#])+$' ) then a_parent.put_warning( From 3c547ecd57d96101b81ca21e70003500e80a99b8 Mon Sep 17 00:00:00 2001 From: pesse Date: Fri, 20 Dec 2019 08:22:23 +0100 Subject: [PATCH 05/11] Fix intendation --- source/core/ut_suite_builder.pkb | 76 ++++++++++++++++---------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/source/core/ut_suite_builder.pkb b/source/core/ut_suite_builder.pkb index d013c107e..0c0730c4b 100644 --- a/source/core/ut_suite_builder.pkb +++ b/source/core/ut_suite_builder.pkb @@ -15,7 +15,7 @@ create or replace package body ut_suite_builder is See the License for the specific language governing permissions and limitations under the License. */ - + subtype t_annotation_text is varchar2(4000); subtype t_annotation_name is varchar2(4000); subtype t_object_name is varchar2(500); @@ -315,13 +315,13 @@ create or replace package body ut_suite_builder is l_annotation_pos := a_throws_ann_text.next(l_annotation_pos); end loop; end; - + procedure add_tags_to_suite_item( a_suite in out nocopy ut_suite, a_tags_ann_text tt_annotation_texts, a_list in out nocopy ut_varchar2_rows, a_procedure_name t_object_name := null - ) is + ) is l_annotation_pos binary_integer; l_tags_list ut_varchar2_list := ut_varchar2_list(); l_tag_items ut_varchar2_list; @@ -354,7 +354,7 @@ create or replace package body ut_suite_builder is --remove empty strings from table list e.g. tag1,,tag2 and convert to rows a_list := ut_utils.convert_collection( ut_utils.filter_list(set(l_tags_list),ut_utils.gc_word_no_space) ); end; - + procedure set_seq_no( a_list in out nocopy ut_executables ) is @@ -533,16 +533,16 @@ create or replace package body ut_suite_builder is ); set_seq_no(l_test.after_test_list); end if; - + if l_proc_annotations.exists( gc_tags) then add_tags_to_suite_item(a_suite, l_proc_annotations( gc_tags), l_test.tags, a_procedure_name); end if; - + if l_proc_annotations.exists( gc_throws) then add_to_throws_numbers_list(a_suite, l_test.expected_error_codes, a_procedure_name, l_proc_annotations( gc_throws)); end if; l_test.disabled_flag := ut_utils.boolean_to_int( l_proc_annotations.exists( gc_disabled)); - + a_suite_items.extend; a_suite_items( a_suite_items.last ) := l_test; @@ -687,7 +687,7 @@ create or replace package body ut_suite_builder is if a_annotations.by_name.exists(gc_aftereach) then l_after_each_list := add_executables( a_suite.object_owner, a_suite.object_name, a_annotations.by_name(gc_aftereach), gc_aftereach ); end if; - + if a_annotations.by_name.exists(gc_tags) then add_tags_to_suite_item(a_suite, a_annotations.by_name(gc_tags),a_suite.tags); end if; @@ -730,22 +730,22 @@ create or replace package body ut_suite_builder is begin if a_package_annotations.exists(gc_endcontext) and a_package_annotations.exists(gc_context) then l_next_endcontext_pos := get_next_annotation_of_type(a_context_ann_pos, gc_endcontext, a_package_annotations); - l_next_context_pos := a_package_annotations(gc_context).next(a_context_ann_pos); + l_next_context_pos := a_package_annotations(gc_context).next(a_context_ann_pos); loop - -- Get all the %context annotations between start and first %endcontext + -- Get all the %context annotations between start and first %endcontext while l_next_context_pos is not null and l_next_context_pos < l_next_endcontext_pos loop - l_open_count := l_open_count+1; - l_next_context_pos := a_package_annotations(gc_context).next(l_next_context_pos); - end loop; - -- Skip as many %endcontexts as we had additional contexts open - while l_open_count > 0 loop - l_open_count := l_open_count-1; - l_next_endcontext_pos := a_package_annotations(gc_endcontext).next(l_next_endcontext_pos); - end loop; - -- Repeat until the next %context is later than next %endcontext - exit when l_next_context_pos is null or l_next_context_pos > l_next_endcontext_pos; - end loop; + l_open_count := l_open_count+1; + l_next_context_pos := a_package_annotations(gc_context).next(l_next_context_pos); + end loop; + -- Skip as many %endcontexts as we had additional contexts open + while l_open_count > 0 loop + l_open_count := l_open_count-1; + l_next_endcontext_pos := a_package_annotations(gc_endcontext).next(l_next_endcontext_pos); + end loop; + -- Repeat until the next %context is later than next %endcontext + exit when l_next_context_pos is null or l_next_context_pos > l_next_endcontext_pos; + end loop; end if; return l_next_endcontext_pos; end; @@ -758,11 +758,11 @@ create or replace package body ut_suite_builder is l_next_context_pos t_annotation_position; begin if ( a_package_annotations.exists(gc_endcontext) and a_package_annotations.exists(gc_context)) then - l_next_endcontext_pos := get_next_annotation_of_type(a_context_ann_pos, gc_endcontext, a_package_annotations); - l_next_context_pos := a_package_annotations(gc_context).next(a_context_ann_pos); - if ( l_next_context_pos < l_next_endcontext_pos ) then - return true; - end if; + l_next_endcontext_pos := get_next_annotation_of_type(a_context_ann_pos, gc_endcontext, a_package_annotations); + l_next_context_pos := a_package_annotations(gc_context).next(a_context_ann_pos); + if ( l_next_context_pos < l_next_endcontext_pos ) then + return true; + end if; end if; return false; end; @@ -834,17 +834,17 @@ create or replace package body ut_suite_builder is ); l_annotation_pos := l_context_names.first; - while l_annotation_pos is not null loop - if l_annotation_pos > a_start_position and l_annotation_pos < l_end_position then - if l_found then - add_annotation_ignored_warning(a_parent, gc_name,'Duplicate annotation %%%.', l_annotation_pos); - else - l_result := l_context_names(l_annotation_pos); - end if; - l_found := true; - end if; - l_annotation_pos := l_context_names.next(l_annotation_pos); - end loop; + while l_annotation_pos is not null loop + if l_annotation_pos > a_start_position and l_annotation_pos < l_end_position then + if l_found then + add_annotation_ignored_warning(a_parent, gc_name,'Duplicate annotation %%%.', l_annotation_pos); + else + l_result := l_context_names(l_annotation_pos); + end if; + l_found := true; + end if; + l_annotation_pos := l_context_names.next(l_annotation_pos); + end loop; end if; return l_result; end; @@ -918,7 +918,7 @@ create or replace package body ut_suite_builder is l_context_pos := a_annotations.by_name( gc_context).next( l_context_pos); -- don't go on when the next context is outside the parent's context boundaries if ( a_parent_end_context_pos is not null and a_parent_end_context_pos <= l_context_pos ) then - l_context_pos := null; + l_context_pos := null; end if; l_context_no := l_context_no + 1; end loop; From b4c1d7235481048da76c1d8d937e0c5129c67375 Mon Sep 17 00:00:00 2001 From: pesse Date: Fri, 20 Dec 2019 08:25:27 +0100 Subject: [PATCH 06/11] Refactoring: Use just one return to improve readability --- source/core/ut_suite_builder.pkb | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/source/core/ut_suite_builder.pkb b/source/core/ut_suite_builder.pkb index 0c0730c4b..32c12c7e5 100644 --- a/source/core/ut_suite_builder.pkb +++ b/source/core/ut_suite_builder.pkb @@ -754,17 +754,14 @@ create or replace package body ut_suite_builder is a_context_ann_pos t_annotation_position, a_package_annotations in out nocopy tt_annotations_by_name ) return boolean is - l_next_endcontext_pos t_annotation_position; - l_next_context_pos t_annotation_position; + l_next_endcontext_pos t_annotation_position := 0; + l_next_context_pos t_annotation_position := 0; begin if ( a_package_annotations.exists(gc_endcontext) and a_package_annotations.exists(gc_context)) then l_next_endcontext_pos := get_next_annotation_of_type(a_context_ann_pos, gc_endcontext, a_package_annotations); l_next_context_pos := a_package_annotations(gc_context).next(a_context_ann_pos); - if ( l_next_context_pos < l_next_endcontext_pos ) then - return true; - end if; end if; - return false; + return ( l_next_context_pos < l_next_endcontext_pos ); end; function get_annotations_in_context( From 86185a87599e71f65d27c4bba10848b74fc01937 Mon Sep 17 00:00:00 2001 From: pesse Date: Fri, 20 Dec 2019 09:02:34 +0100 Subject: [PATCH 07/11] Rewrite get_endcontext_position to be much easier to understand Using simple parenthesis counter and annotations_by_line --- source/core/ut_suite_builder.pkb | 44 +++++++++++++------------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/source/core/ut_suite_builder.pkb b/source/core/ut_suite_builder.pkb index 32c12c7e5..0b00801b8 100644 --- a/source/core/ut_suite_builder.pkb +++ b/source/core/ut_suite_builder.pkb @@ -722,32 +722,25 @@ create or replace package body ut_suite_builder is function get_endcontext_position( a_context_ann_pos t_annotation_position, - a_package_annotations in out nocopy tt_annotations_by_name + a_package_annotations in tt_annotations_by_line ) return t_annotation_position is - l_next_endcontext_pos t_annotation_position; - l_next_context_pos t_annotation_position; - l_open_count integer := 0; + l_result t_annotation_position; + l_open_count integer := 1; + l_idx t_annotation_position := a_package_annotations.next(a_context_ann_pos); begin - if a_package_annotations.exists(gc_endcontext) and a_package_annotations.exists(gc_context) then - l_next_endcontext_pos := get_next_annotation_of_type(a_context_ann_pos, gc_endcontext, a_package_annotations); - l_next_context_pos := a_package_annotations(gc_context).next(a_context_ann_pos); - - loop - -- Get all the %context annotations between start and first %endcontext - while l_next_context_pos is not null and l_next_context_pos < l_next_endcontext_pos loop - l_open_count := l_open_count+1; - l_next_context_pos := a_package_annotations(gc_context).next(l_next_context_pos); - end loop; - -- Skip as many %endcontexts as we had additional contexts open - while l_open_count > 0 loop - l_open_count := l_open_count-1; - l_next_endcontext_pos := a_package_annotations(gc_endcontext).next(l_next_endcontext_pos); - end loop; - -- Repeat until the next %context is later than next %endcontext - exit when l_next_context_pos is null or l_next_context_pos > l_next_endcontext_pos; - end loop; + while l_open_count > 0 and l_idx is not null loop + if ( a_package_annotations(l_idx).name = gc_context ) then + l_open_count := l_open_count+1; + elsif ( a_package_annotations(l_idx).name = gc_endcontext ) then + l_open_count := l_open_count-1; + l_result := l_idx; + end if; + l_idx := a_package_annotations.next(l_idx); + end loop; + if ( l_open_count > 0 ) then + l_result := null; end if; - return l_next_endcontext_pos; + return l_result; end; function has_nested_context( @@ -826,7 +819,7 @@ create or replace package body ut_suite_builder is l_context_names := a_annotations.by_name( gc_name ); l_end_position := least( - coalesce( get_endcontext_position(a_start_position, a_annotations.by_name), a_annotations.by_line.last ), + coalesce( get_endcontext_position(a_start_position, a_annotations.by_line), a_annotations.by_line.last ), coalesce( a_annotations.by_name(gc_context).next(a_start_position), a_annotations.by_line.last ) ); l_annotation_pos := l_context_names.first; @@ -856,10 +849,9 @@ create or replace package body ut_suite_builder is while l_context_pos is not null loop l_default_context_name := 'nested_context_#'||l_context_no; l_context_name := null; - l_end_context_pos := get_endcontext_position(l_context_pos, a_annotations.by_name ); + l_end_context_pos := get_endcontext_position(l_context_pos, a_annotations.by_line ); l_next_context_pos := a_annotations.by_name(gc_context).next(l_context_pos); l_context_name := get_context_name(a_parent, l_context_pos); - if not regexp_like( l_context_name, '^(\w|[$#])+$' ) or l_context_name is null then if not regexp_like( l_context_name, '^(\w|[$#])+$' ) then a_parent.put_warning( From 89df1ddbda8f1521c58483672315b0e41d1eb6dc Mon Sep 17 00:00:00 2001 From: pesse Date: Fri, 20 Dec 2019 09:09:31 +0100 Subject: [PATCH 08/11] Clarify intention of end-position, make it more visible how it's defined --- source/core/ut_suite_builder.pkb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/core/ut_suite_builder.pkb b/source/core/ut_suite_builder.pkb index 0b00801b8..0b4551765 100644 --- a/source/core/ut_suite_builder.pkb +++ b/source/core/ut_suite_builder.pkb @@ -817,10 +817,11 @@ create or replace package body ut_suite_builder is begin if a_annotations.by_name.exists(gc_name) then l_context_names := a_annotations.by_name( gc_name ); + -- Maximum end-position to look for %name annotation is either the next %context or the next %endcontext annotation l_end_position := least( - coalesce( get_endcontext_position(a_start_position, a_annotations.by_line), a_annotations.by_line.last ), - coalesce( a_annotations.by_name(gc_context).next(a_start_position), a_annotations.by_line.last ) + coalesce( get_next_annotation_of_type(a_start_position, gc_endcontext, a_annotations.by_name), a_annotations.by_line.last ), + coalesce( get_next_annotation_of_type(a_start_position, gc_context, a_annotations.by_name), a_annotations.by_line.last ) ); l_annotation_pos := l_context_names.first; From c61abfaed5ce0e6d1d95596400486660f49abfc7 Mon Sep 17 00:00:00 2001 From: pesse Date: Fri, 20 Dec 2019 09:12:55 +0100 Subject: [PATCH 09/11] Get rid of several `in out nocopy` params where `in` would be sufficient --- source/core/ut_suite_builder.pkb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/core/ut_suite_builder.pkb b/source/core/ut_suite_builder.pkb index 0b4551765..a44e73919 100644 --- a/source/core/ut_suite_builder.pkb +++ b/source/core/ut_suite_builder.pkb @@ -707,7 +707,7 @@ create or replace package body ut_suite_builder is function get_next_annotation_of_type( a_start_position t_annotation_position, a_annotation_type varchar2, - a_package_annotations in out nocopy tt_annotations_by_name + a_package_annotations in tt_annotations_by_name ) return t_annotation_position is l_result t_annotation_position; begin @@ -745,7 +745,7 @@ create or replace package body ut_suite_builder is function has_nested_context( a_context_ann_pos t_annotation_position, - a_package_annotations in out nocopy tt_annotations_by_name + a_package_annotations in tt_annotations_by_name ) return boolean is l_next_endcontext_pos t_annotation_position := 0; l_next_context_pos t_annotation_position := 0; From 35acf1438280a5714c26929b4ea17c6132c81e0d Mon Sep 17 00:00:00 2001 From: pesse Date: Fri, 20 Dec 2019 09:15:33 +0100 Subject: [PATCH 10/11] Not necessary to check for IS NOT NULL --- source/core/ut_suite_builder.pkb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/core/ut_suite_builder.pkb b/source/core/ut_suite_builder.pkb index a44e73919..5f468f756 100644 --- a/source/core/ut_suite_builder.pkb +++ b/source/core/ut_suite_builder.pkb @@ -907,7 +907,7 @@ create or replace package body ut_suite_builder is l_context_pos := a_annotations.by_name( gc_context).next( l_context_pos); -- don't go on when the next context is outside the parent's context boundaries - if ( a_parent_end_context_pos is not null and a_parent_end_context_pos <= l_context_pos ) then + if (a_parent_end_context_pos <= l_context_pos ) then l_context_pos := null; end if; l_context_no := l_context_no + 1; From 3327fc371f8a5f3b5be9baea1745fce2dbd8b08d Mon Sep 17 00:00:00 2001 From: pesse Date: Fri, 20 Dec 2019 09:55:20 +0100 Subject: [PATCH 11/11] Fix intendation --- test/ut3_tester/core/test_suite_builder.pkb | 2 +- test/ut3_tester/core/test_suite_builder.pks | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/ut3_tester/core/test_suite_builder.pkb b/test/ut3_tester/core/test_suite_builder.pkb index 8250eb96e..86d86032a 100644 --- a/test/ut3_tester/core/test_suite_builder.pkb +++ b/test/ut3_tester/core/test_suite_builder.pkb @@ -767,7 +767,7 @@ create or replace package body test_suite_builder is ); end; - procedure nested_contexts_2 is + procedure nested_contexts_2 is l_actual clob; l_annotations ut3.ut_annotations; begin diff --git a/test/ut3_tester/core/test_suite_builder.pks b/test/ut3_tester/core/test_suite_builder.pks index 98a61171e..7c7fc77f6 100644 --- a/test/ut3_tester/core/test_suite_builder.pks +++ b/test/ut3_tester/core/test_suite_builder.pks @@ -106,7 +106,7 @@ create or replace package test_suite_builder is --%endcontext --%context(--%context annotation) - --%name(context) + --%name(context) --%test(Creates nested suite for content between context/endcontext annotations) procedure suite_from_context;