@@ -36,6 +36,7 @@ create or replace package body ut_suite_builder is
36
36
gc_throws constant t_annotation_name := 'throws';
37
37
gc_rollback constant t_annotation_name := 'rollback';
38
38
gc_context constant t_annotation_name := 'context';
39
+ gc_name constant t_annotation_name := 'name';
39
40
gc_endcontext constant t_annotation_name := 'endcontext';
40
41
41
42
type tt_annotations is table of t_annotation_name;
@@ -57,6 +58,7 @@ create or replace package body ut_suite_builder is
57
58
gc_throws,
58
59
gc_rollback,
59
60
gc_context,
61
+ gc_name,
60
62
gc_endcontext
61
63
);
62
64
@@ -637,7 +639,7 @@ create or replace package body ut_suite_builder is
637
639
a_suite.path := lower(coalesce(a_suite.path, a_suite.object_name));
638
640
end;
639
641
640
- procedure add_suite_tests (
642
+ procedure add_tests_to_items (
641
643
a_suite in out nocopy ut_suite,
642
644
a_annotations t_annotations_info,
643
645
a_suite_items in out nocopy ut_suite_items
@@ -747,59 +749,120 @@ create or replace package body ut_suite_builder is
747
749
return l_result;
748
750
end;
749
751
750
- procedure get_suite_contexts_items (
751
- a_suite in out nocopy ut_suite,
752
+ procedure get_context_items (
753
+ a_parent in out nocopy ut_suite,
752
754
a_annotations in out nocopy t_annotations_info,
753
- a_suite_items out nocopy ut_suite_items
755
+ a_suite_items out nocopy ut_suite_items,
756
+ a_parent_context_pos in integer := 0
754
757
) is
755
- l_context_pos t_annotation_position;
756
- l_end_context_pos t_annotation_position;
757
- l_context_name t_object_name ;
758
- l_ctx_annotations t_annotations_info;
759
- l_context ut_suite_context;
760
- l_context_no binary_integer := 1;
761
- l_context_items ut_suite_items;
758
+ l_context_pos t_annotation_position;
759
+ l_next_context_pos t_annotation_position;
760
+ l_end_context_pos t_annotation_position ;
761
+ l_ctx_annotations t_annotations_info;
762
+ l_context ut_suite_context;
763
+ l_context_no binary_integer := 1;
764
+ l_context_items ut_suite_items;
762
765
type tt_context_names is table of boolean index by t_object_name;
763
- l_context_names tt_context_names;
766
+ l_used_context_names tt_context_names;
767
+ l_context_name t_object_name;
768
+ l_default_context_name t_object_name;
769
+ function get_context_name(
770
+ a_parent in out nocopy ut_suite,
771
+ a_context_names in tt_annotation_texts,
772
+ a_start_position binary_integer,
773
+ a_end_position binary_integer
774
+ ) return varchar2 is
775
+ l_result t_annotation_name;
776
+ l_found boolean;
777
+ l_annotation_pos binary_integer;
778
+ begin
779
+ l_annotation_pos := a_context_names.first;
780
+ while l_annotation_pos is not null loop
781
+ if l_annotation_pos > a_start_position and l_annotation_pos < a_end_position then
782
+ if l_found then
783
+ add_annotation_ignored_warning(a_parent, gc_name,'Duplicate annotation %%%.', l_annotation_pos);
784
+ else
785
+ l_result := a_context_names(l_annotation_pos);
786
+ end if;
787
+ l_found := true;
788
+ end if;
789
+ l_annotation_pos := a_context_names.next(l_annotation_pos);
790
+ end loop;
791
+ return l_result;
792
+ end;
764
793
begin
765
794
a_suite_items := ut_suite_items();
766
795
if not a_annotations.by_name.exists(gc_context) then
767
796
return;
768
797
end if;
769
798
770
- l_context_pos := a_annotations.by_name( gc_context).first ;
799
+ l_context_pos := a_annotations.by_name( gc_context).next(a_parent_context_pos) ;
771
800
772
801
while l_context_pos is not null loop
802
+ l_default_context_name := 'nested_context_#'||l_context_no;
773
803
l_end_context_pos := get_endcontext_position(l_context_pos, a_annotations.by_name );
774
804
775
- exit when l_end_context_pos is null;
805
+ l_next_context_pos := a_annotations.by_name(gc_context).next(l_context_pos);
806
+ if a_annotations.by_name.exists(gc_name) then
807
+ l_context_name :=
808
+ get_context_name(
809
+ a_parent,
810
+ a_annotations.by_name( gc_name ),
811
+ l_context_pos,
812
+ least(
813
+ coalesce( l_end_context_pos, a_annotations.by_line.last ),
814
+ coalesce( l_next_context_pos, a_annotations.by_line.last )
815
+ )
816
+ );
817
+ end if;
818
+ if not regexp_like( l_context_name, '^(\w|[$#])+$' ) or l_context_name is null then
819
+ if not regexp_like( l_context_name, '^(\w|[$#])+$' ) then
820
+ a_parent.put_warning(
821
+ 'Invalid value "'||l_context_name||'" for context name.' ||
822
+ ' Context name ignored and fallback to auto-name "'||l_default_context_name||'" ' ||
823
+ get_object_reference( a_parent, null, l_context_pos )
824
+ );
825
+ end if;
826
+ l_context_name := l_default_context_name;
827
+ end if;
828
+ if l_used_context_names.exists(l_context_name) then
829
+ add_annotation_ignored_warning(
830
+ a_parent, gc_name,
831
+ 'Context name "'||l_context_name||'" already used in this scope. Name must be unique.' ||
832
+ ' Using fallback name '||l_default_context_name||'.', l_context_pos );
833
+ l_context_name := l_default_context_name;
834
+ end if;
835
+ l_used_context_names(l_context_name) := true;
776
836
777
- l_context_items := ut_suite_items();
778
- --create a sub-set of annotations to process as sub-suite (context)
779
- l_ctx_annotations := get_annotations_in_context( a_annotations, l_context_pos, l_end_context_pos);
837
+ l_context := ut_suite_context(a_parent.object_owner, a_parent.object_name, l_context_name, l_context_pos );
838
+ l_context.path := a_parent.path||'.'||l_context_name;
839
+ l_context.description := coalesce( a_annotations.by_line( l_context_pos ).text, l_context_name );
840
+ l_context.parse_time := a_annotations.parse_time;
780
841
781
- l_context_name := coalesce(
782
- l_ctx_annotations.by_line( l_context_pos ).text
783
- , gc_context||'_'||l_context_no
784
- );
785
- if l_context_names.exists(l_context_name) then
786
- add_annotation_ignored_warning( a_suite, 'context', 'Context name must be unique in a suite. Context and all of it''s content ignored.', l_context_pos );
842
+ --if nested context found
843
+ if l_next_context_pos < l_end_context_pos or l_end_context_pos is null then
844
+ get_context_items( l_context, a_annotations, l_context_items, l_context_pos );
845
+ l_end_context_pos := get_endcontext_position(l_context_pos, a_annotations.by_name );
787
846
else
788
- l_context_names(l_context_name) := true;
847
+ l_context_items := ut_suite_items();
848
+ end if;
789
849
790
- l_context := ut_suite_context(a_suite.object_owner, a_suite.object_name, l_context_name, l_context_pos );
850
+ if l_end_context_pos is null then
851
+ a_parent.put_warning(
852
+ 'Missing "--%endcontext" annotation for a "--%context" annotation. The end of package is considered end of context.'|| get_object_reference( a_parent, null, l_context_pos )
853
+ );
854
+ l_end_context_pos := a_annotations.by_line.last;
855
+ end if;
791
856
792
- l_context.path := a_suite.path||'.'||l_context_name;
793
- l_context.description := l_ctx_annotations.by_line( l_context_pos ).text;
794
- l_context.parse_time := a_annotations.parse_time;
857
+ --create a sub-set of annotations to process as sub-suite (context)
858
+ l_ctx_annotations := get_annotations_in_context( a_annotations, l_context_pos, l_end_context_pos);
795
859
796
- warning_on_duplicate_annot( l_context, l_ctx_annotations.by_name, gc_context );
860
+ warning_on_duplicate_annot( l_context, l_ctx_annotations.by_name, gc_context );
797
861
798
- add_suite_tests( l_context, l_ctx_annotations, l_context_items );
799
- add_items_to_list(a_suite_items, l_context_items);
800
- a_suite_items.extend;
801
- a_suite_items(a_suite_items.last) := l_context;
802
- end if;
862
+ add_tests_to_items( l_context, l_ctx_annotations, l_context_items );
863
+ add_items_to_list(a_suite_items, l_context_items);
864
+ a_suite_items.extend;
865
+ a_suite_items(a_suite_items.last) := l_context;
803
866
-- remove annotations within context after processing them
804
867
delete_annotations_range(a_annotations, l_context_pos, l_end_context_pos);
805
868
@@ -810,27 +873,17 @@ create or replace package body ut_suite_builder is
810
873
end loop;
811
874
end;
812
875
813
- procedure warning_on_incomplete_context (
876
+ procedure warning_on_extra_endcontext (
814
877
a_suite in out nocopy ut_suite,
815
878
a_package_ann_index tt_annotations_by_name
816
879
) is
817
880
l_annotation_pos t_annotation_position;
818
881
begin
819
- if a_package_ann_index.exists(gc_context) then
820
- l_annotation_pos := a_package_ann_index(gc_context).first;
821
- while l_annotation_pos is not null loop
822
- add_annotation_ignored_warning(
823
- a_suite, gc_context, 'Invalid annotation %%%. Cannot find following "--%endcontext".',
824
- l_annotation_pos
825
- );
826
- l_annotation_pos := a_package_ann_index(gc_context).next(l_annotation_pos);
827
- end loop;
828
- end if;
829
882
if a_package_ann_index.exists(gc_endcontext) then
830
883
l_annotation_pos := a_package_ann_index(gc_endcontext).first;
831
884
while l_annotation_pos is not null loop
832
885
add_annotation_ignored_warning(
833
- a_suite, gc_endcontext, 'Invalid annotation %%%. Cannot find preceding "--%context".',
886
+ a_suite, gc_endcontext, 'Extra %%% annotation found . Cannot find corresponding "--%context".',
834
887
l_annotation_pos
835
888
);
836
889
l_annotation_pos := a_package_ann_index(gc_endcontext).next(l_annotation_pos);
@@ -901,12 +954,12 @@ create or replace package body ut_suite_builder is
901
954
warning_on_duplicate_annot( l_suite, l_annotations.by_name, gc_suite );
902
955
903
956
build_suitepath( l_suite, l_annotations );
904
- get_suite_contexts_items ( l_suite, l_annotations, a_suite_items );
957
+ get_context_items ( l_suite, l_annotations, a_suite_items );
905
958
--create suite tests and add
906
- add_suite_tests ( l_suite, l_annotations, a_suite_items );
959
+ add_tests_to_items ( l_suite, l_annotations, a_suite_items );
907
960
908
961
--by this time all contexts were consumed and l_annotations should not have any context/endcontext annotation in it.
909
- warning_on_incomplete_context ( l_suite, l_annotations.by_name );
962
+ warning_on_extra_endcontext ( l_suite, l_annotations.by_name );
910
963
911
964
a_suite_items.extend;
912
965
a_suite_items( a_suite_items.last) := l_suite;
0 commit comments