|
| 1 | +create or replace package body ut_suite_builder is |
| 2 | + /* |
| 3 | + utPLSQL - Version 3 |
| 4 | + Copyright 2016 - 2017 utPLSQL Project |
| 5 | + |
| 6 | + Licensed under the Apache License, Version 2.0 (the "License"): |
| 7 | + you may not use this file except in compliance with the License. |
| 8 | + You may obtain a copy of the License at |
| 9 | + |
| 10 | + http://www.apache.org/licenses/LICENSE-2.0 |
| 11 | + |
| 12 | + Unless required by applicable law or agreed to in writing, software |
| 13 | + distributed under the License is distributed on an "AS IS" BASIS, |
| 14 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 15 | + See the License for the specific language governing permissions and |
| 16 | + limitations under the License. |
| 17 | + */ |
| 18 | + |
| 19 | + ------------------ |
| 20 | + |
| 21 | + function create_suite(a_object ut_annotated_object) return ut_logical_suite is |
| 22 | + l_is_suite boolean := false; |
| 23 | + l_is_test boolean := false; |
| 24 | + l_suite_disabled boolean := false; |
| 25 | + l_test_disabled boolean := false; |
| 26 | + l_suite_items ut_suite_items := ut_suite_items(); |
| 27 | + l_suite_name varchar2(4000); |
| 28 | + |
| 29 | + l_default_setup_proc varchar2(250 char); |
| 30 | + l_default_teardown_proc varchar2(250 char); |
| 31 | + l_suite_setup_proc varchar2(250 char); |
| 32 | + l_suite_teardown_proc varchar2(250 char); |
| 33 | + l_suite_path varchar2(4000 char); |
| 34 | + |
| 35 | + l_proc_name varchar2(250 char); |
| 36 | + |
| 37 | + l_suite ut_logical_suite; |
| 38 | + l_test ut_test; |
| 39 | + |
| 40 | + l_suite_rollback integer; |
| 41 | + |
| 42 | + l_beforetest_procedure varchar2(250 char); |
| 43 | + l_aftertest_procedure varchar2(250 char); |
| 44 | + l_rollback_type integer; |
| 45 | + l_displayname varchar2(4000); |
| 46 | + |
| 47 | + begin |
| 48 | + l_suite_rollback := ut_utils.gc_rollback_auto; |
| 49 | + for i in 1 .. a_object.annotations.count loop |
| 50 | + |
| 51 | + if a_object.annotations(i).subobject_name is null then |
| 52 | + |
| 53 | + if a_object.annotations(i).name in ('suite','displayname') then |
| 54 | + l_suite_name := a_object.annotations(i).text; |
| 55 | + if a_object.annotations(i).name = 'suite' then |
| 56 | + l_is_suite := true; |
| 57 | + end if; |
| 58 | + elsif a_object.annotations(i).name = 'disabled' then |
| 59 | + l_suite_disabled := true; |
| 60 | + elsif a_object.annotations(i).name = 'suitepath' and a_object.annotations(i).text is not null then |
| 61 | + l_suite_path := a_object.annotations(i).text || '.' || lower(a_object.object_name); |
| 62 | + elsif a_object.annotations(i).name = 'rollback' then |
| 63 | + if lower(a_object.annotations(i).text) = 'manual' then |
| 64 | + l_suite_rollback := ut_utils.gc_rollback_manual; |
| 65 | + else |
| 66 | + l_suite_rollback := ut_utils.gc_rollback_auto; |
| 67 | + end if; |
| 68 | + end if; |
| 69 | + |
| 70 | + elsif l_is_suite then |
| 71 | + |
| 72 | + l_proc_name := a_object.annotations(i).subobject_name; |
| 73 | + |
| 74 | + if a_object.annotations(i).name = 'beforeeach' and l_default_setup_proc is null then |
| 75 | + l_default_setup_proc := l_proc_name; |
| 76 | + elsif a_object.annotations(i).name = 'aftereach' and l_default_teardown_proc is null then |
| 77 | + l_default_teardown_proc := l_proc_name; |
| 78 | + elsif a_object.annotations(i).name = 'beforeall' and l_suite_setup_proc is null then |
| 79 | + l_suite_setup_proc := l_proc_name; |
| 80 | + elsif a_object.annotations(i).name = 'afterall' and l_suite_teardown_proc is null then |
| 81 | + l_suite_teardown_proc := l_proc_name; |
| 82 | + |
| 83 | + |
| 84 | + elsif a_object.annotations(i).name = 'disabled' then |
| 85 | + l_test_disabled := true; |
| 86 | + elsif a_object.annotations(i).name = 'beforetest' then |
| 87 | + l_beforetest_procedure := a_object.annotations(i).text; |
| 88 | + elsif a_object.annotations(i).name = 'aftertest' then |
| 89 | + l_aftertest_procedure := a_object.annotations(i).text; |
| 90 | + elsif a_object.annotations(i).name in ('displayname','test') then |
| 91 | + l_displayname := a_object.annotations(i).text; |
| 92 | + if a_object.annotations(i).name = 'test' then |
| 93 | + l_is_test := true; |
| 94 | + end if; |
| 95 | + elsif a_object.annotations(i).name = 'rollback' then |
| 96 | + if lower(a_object.annotations(i).text) = 'manual' then |
| 97 | + l_rollback_type := ut_utils.gc_rollback_manual; |
| 98 | + elsif lower(a_object.annotations(i).text) = 'auto' then |
| 99 | + l_rollback_type := ut_utils.gc_rollback_auto; |
| 100 | + end if; |
| 101 | + end if; |
| 102 | + |
| 103 | + if l_is_test |
| 104 | + and (i = a_object.annotations.count |
| 105 | + or l_proc_name != nvl(a_object.annotations(i+1).subobject_name, ' ') ) then |
| 106 | + l_suite_items.extend; |
| 107 | + l_suite_items(l_suite_items.last) := |
| 108 | + ut_test(a_object_owner => a_object.object_owner |
| 109 | + ,a_object_name => a_object.object_name |
| 110 | + ,a_name => l_proc_name |
| 111 | + ,a_description => l_displayname |
| 112 | + ,a_rollback_type => coalesce(l_rollback_type, l_suite_rollback) |
| 113 | + ,a_disabled_flag => l_suite_disabled or l_test_disabled |
| 114 | + ,a_before_test_proc_name => l_beforetest_procedure |
| 115 | + ,a_after_test_proc_name => l_aftertest_procedure); |
| 116 | + |
| 117 | + l_is_test := false; |
| 118 | + l_test_disabled := false; |
| 119 | + l_aftertest_procedure := null; |
| 120 | + l_beforetest_procedure := null; |
| 121 | + l_rollback_type := null; |
| 122 | + end if; |
| 123 | + |
| 124 | + end if; |
| 125 | + end loop; |
| 126 | + |
| 127 | + if l_is_suite then |
| 128 | + l_suite := ut_suite ( |
| 129 | + a_object_owner => a_object.object_owner, |
| 130 | + a_object_name => a_object.object_name, |
| 131 | + a_name => a_object.object_name, --this could be different for sub-suite (context) |
| 132 | + a_path => l_suite_path, --a patch for this suite (excluding the package name of current suite) |
| 133 | + a_description => l_suite_name, |
| 134 | + a_rollback_type => l_suite_rollback, |
| 135 | + a_disabled_flag => l_suite_disabled, |
| 136 | + a_before_all_proc_name => l_suite_setup_proc, |
| 137 | + a_after_all_proc_name => l_suite_teardown_proc |
| 138 | + ); |
| 139 | + for i in 1 .. l_suite_items.count loop |
| 140 | + l_test := treat(l_suite_items(i) as ut_test); |
| 141 | + l_test.set_beforeeach(l_default_setup_proc); |
| 142 | + l_test.set_aftereach(l_default_teardown_proc); |
| 143 | + l_test.path := l_suite.path || '.' || l_test.name; |
| 144 | + l_suite.add_item(l_test); |
| 145 | + end loop; |
| 146 | + end if; |
| 147 | + |
| 148 | + return l_suite; |
| 149 | + |
| 150 | + end create_suite; |
| 151 | + |
| 152 | + function build_suites_hierarchy(a_suites_by_path tt_schema_suites) return tt_schema_suites is |
| 153 | + l_result tt_schema_suites; |
| 154 | + l_suite_path varchar2(4000 char); |
| 155 | + l_parent_path varchar2(4000 char); |
| 156 | + l_name varchar2(4000 char); |
| 157 | + l_suites_by_path tt_schema_suites; |
| 158 | + begin |
| 159 | + l_suites_by_path := a_suites_by_path; |
| 160 | + --were iterating in reverse order of the index by path table |
| 161 | + -- so the first paths will be the leafs of hierarchy and next will their parents |
| 162 | + l_suite_path := l_suites_by_path.last; |
| 163 | + ut_utils.debug_log('Input suites to process = '||l_suites_by_path.count); |
| 164 | + |
| 165 | + while l_suite_path is not null loop |
| 166 | + l_parent_path := substr( l_suite_path, 1, instr(l_suite_path,'.',-1)-1); |
| 167 | + ut_utils.debug_log('Processing l_suite_path = "'||l_suite_path||'", l_parent_path = "'||l_parent_path||'"'); |
| 168 | + --no parent => I'm a root element |
| 169 | + if l_parent_path is null then |
| 170 | + ut_utils.debug_log(' suite "'||l_suite_path||'" is a root element - adding to return list.'); |
| 171 | + l_result(l_suite_path) := l_suites_by_path(l_suite_path); |
| 172 | + -- not a root suite - need to add it to a parent suite |
| 173 | + else |
| 174 | + --parent does not exist and needs to be added |
| 175 | + if not l_suites_by_path.exists(l_parent_path) then |
| 176 | + l_name := substr( l_parent_path, instr(l_parent_path,'.',-1)+1); |
| 177 | + ut_utils.debug_log(' Parent suite "'||l_parent_path||'" not found in the list - Adding suite "'||l_name||'"'); |
| 178 | + l_suites_by_path(l_parent_path) := |
| 179 | + ut_logical_suite( |
| 180 | + a_object_owner => l_suites_by_path(l_suite_path).object_owner, |
| 181 | + a_object_name => l_name, a_name => l_name, a_path => l_parent_path |
| 182 | + ); |
| 183 | + else |
| 184 | + ut_utils.debug_log(' Parent suite "'||l_parent_path||'" found in list of suites'); |
| 185 | + end if; |
| 186 | + ut_utils.debug_log(' adding suite "'||l_suite_path||'" to "'||l_parent_path||'" items'); |
| 187 | + l_suites_by_path(l_parent_path).add_item( l_suites_by_path(l_suite_path) ); |
| 188 | + end if; |
| 189 | + l_suite_path := l_suites_by_path.prior(l_suite_path); |
| 190 | + end loop; |
| 191 | + ut_utils.debug_log(l_result.count||' root suites created.'); |
| 192 | + return l_result; |
| 193 | + end; |
| 194 | + |
| 195 | + function build_suites(a_annotated_objects sys_refcursor) return t_schema_suites_info is |
| 196 | + l_suite ut_logical_suite; |
| 197 | + l_annotated_objects ut_annotated_objects; |
| 198 | + l_all_suites tt_schema_suites; |
| 199 | + l_result t_schema_suites_info; |
| 200 | + begin |
| 201 | + fetch a_annotated_objects bulk collect into l_annotated_objects; |
| 202 | + close a_annotated_objects; |
| 203 | + |
| 204 | + for i in 1 .. l_annotated_objects.count loop |
| 205 | + l_suite := create_suite(l_annotated_objects(i)); |
| 206 | + if l_suite is not null then |
| 207 | + l_all_suites(l_suite.path) := l_suite; |
| 208 | + l_result.suite_paths(l_suite.object_name) := l_suite.path; |
| 209 | + end if; |
| 210 | + end loop; |
| 211 | + |
| 212 | + --build hierarchical structure of the suite |
| 213 | + -- Restructure single-dimension list into hierarchy of suites by the value of %suitepath attribute value |
| 214 | + l_result.schema_suites := build_suites_hierarchy(l_all_suites); |
| 215 | + |
| 216 | + return l_result; |
| 217 | + end; |
| 218 | + |
| 219 | + function build_schema_suites(a_owner_name varchar2) return t_schema_suites_info is |
| 220 | + l_annotations_cursor sys_refcursor; |
| 221 | + begin |
| 222 | + -- form the single-dimension list of suites constructed from parsed packages |
| 223 | + open l_annotations_cursor for |
| 224 | + q'[select value(x) |
| 225 | + from table( |
| 226 | + ]'||ut_utils.ut_owner||q'[.ut_annotation_manager.get_annotated_objects(:a_owner_name, 'PACKAGE') |
| 227 | + )x ]' |
| 228 | + using a_owner_name; |
| 229 | + |
| 230 | + return build_suites(l_annotations_cursor); |
| 231 | + end; |
| 232 | + |
| 233 | +end ut_suite_builder; |
| 234 | +/ |
0 commit comments