Skip to content
Merged
Next Next commit
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
  • Loading branch information
pesse committed Dec 19, 2019
commit e8f453291b58f90bde2fbac6a6b8562757997905
56 changes: 46 additions & 10 deletions source/core/ut_suite_builder.pkb
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Comment thread
pesse marked this conversation as resolved.
Outdated
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
Comment thread
pesse marked this conversation as resolved.
Outdated
) 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(
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 :=
Expand Down Expand Up @@ -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;
Expand All @@ -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
Comment thread
pesse marked this conversation as resolved.
Outdated
l_context_pos := null;
end if;
l_context_no := l_context_no + 1;
end loop;
end;
Expand Down
68 changes: 68 additions & 0 deletions test/ut3_tester/core/test_suite_builder.pkb
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add some tests in parent context of nested context before/after nested context.
I wonder if this will still work as expected.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't that already done with nested_contexts test?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right

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(
'<ROWSET><ROW>'||
'<UT_LOGICAL_SUITE>' ||
'%<ITEMS>%' ||
'<UT_SUITE_ITEM>' ||
'%<NAME>context_1</NAME><DESCRIPTION>Level 1</DESCRIPTION><PATH>path.some_package.context_1</PATH>' ||
'%<ITEMS>' ||
'<UT_SUITE_ITEM>' ||
'%<NAME>context_1_1</NAME><DESCRIPTION>Level 1.1</DESCRIPTION><PATH>path.some_package.context_1.context_1_1</PATH>' ||
'%<ITEMS>' ||
'<UT_SUITE_ITEM>' ||
'%<NAME>test_1_1_1</NAME><DESCRIPTION>Test 1.1.1</DESCRIPTION><PATH>path.some_package.context_1.context_1_1.test_1_1_1</PATH>' ||
'%</UT_SUITE_ITEM>' ||
'<UT_SUITE_ITEM>' ||
'%<NAME>test_1_1_2</NAME><DESCRIPTION>Test 1.1.2</DESCRIPTION><PATH>path.some_package.context_1.context_1_1.test_1_1_2</PATH>' ||
'%</UT_SUITE_ITEM>' ||
'</ITEMS>' ||
'%<BEFORE_ALL_LIST/>' ||
'%</UT_SUITE_ITEM>' ||
'</ITEMS>' ||
'%</UT_SUITE_ITEM>' ||
'%</ITEMS>' ||
'%</UT_LOGICAL_SUITE>'||
'</ROW></ROWSET>'
);
-- Test both contexts separately due to ordering
ut.expect(l_actual).to_be_like(
'<ROWSET><ROW>'||
'<UT_LOGICAL_SUITE>' ||
'%<ITEMS>%' ||
'<UT_SUITE_ITEM>' ||
'%<NAME>context_2</NAME><DESCRIPTION>Level 2</DESCRIPTION><PATH>path.some_package.context_2</PATH>' ||
'%<ITEMS>' ||
'<UT_SUITE_ITEM>' ||
'%<NAME>test_2_1</NAME><DESCRIPTION>Test 2.1</DESCRIPTION><PATH>path.some_package.context_2.test_2_1</PATH>' ||
'%</UT_SUITE_ITEM>' ||
'%</ITEMS>' ||
'%</UT_SUITE_ITEM>' ||
'%</ITEMS>' ||
'%</UT_LOGICAL_SUITE>'||
'</ROW></ROWSET>'
);
end;


procedure before_after_in_context is
l_actual clob;
Expand Down
5 changes: 5 additions & 0 deletions test/ut3_tester/core/test_suite_builder.pks
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -105,13 +106,17 @@ create or replace package test_suite_builder is
--%endcontext

--%context(--%context annotation)
--%name(context)
Comment thread
pesse marked this conversation as resolved.
Outdated

--%test(Creates nested suite for content between context/endcontext annotations)
procedure suite_from_context;

--%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;

Expand Down