Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2476c80

Browse files
authored
Merge pull request #670 from lwasylow/invalidspecs
Ability to run test even when package specs of test are invalid
2 parents 9795992 + 0d87f4f commit 2476c80

10 files changed

Lines changed: 203 additions & 65 deletions

old_tests/RunAll.sql

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,6 @@ exec ut_coverage.set_develop_mode(true);
129129
@@lib/RunTest.sql ut_suite_manager/ut_suite_manager.configure_execution_by_path.PrepareRunnerForTheTopPackageProcedureByPathCurUser.sql
130130
@@lib/RunTest.sql ut_suite_manager/ut_suite_manager.configure_execution_by_path.PrepareRunnerForTheTop2PackageProcedureByPath.sql
131131
@@lib/RunTest.sql ut_suite_manager/ut_suite_manager.configure_execution_by_path.PrepareRunnerForTheTop2PackageProcedureByPathCurUser.sql
132-
@@lib/RunTest.sql ut_suite_manager/ut_suite_manager.DoesntFindTheSuiteWhenPackageSpecIsInvalid.sql
133132
@@lib/RunTest.sql ut_suite_manager/ut_suite_manager.emptySuitePath.sql
134133
@@lib/RunTest.sql ut_suite_manager/ut_suite_manager.get_schema_ut_packages.IncludesPackagesWithSutePath.sql
135134
@@lib/RunTest.sql ut_suite_manager/ut_suite_manager.IncludesInvalidPackageBodiesInTheRun.sql

old_tests/ut_suite_manager/ut_suite_manager.DoesntFindTheSuiteWhenPackageSpecIsInvalid.sql

Lines changed: 0 additions & 42 deletions
This file was deleted.

source/core/annotations/ut_annotation_manager.pkb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ create or replace package body ut_annotation_manager as
3636
left join ]'||l_ut_owner||q'[.ut_annotation_cache_info i
3737
on o.owner = i.object_owner and o.object_name = i.object_name and o.object_type = i.object_type
3838
where o.owner = :a_object_owner
39-
and o.object_type = :a_object_type
40-
and o.status = 'VALID' ]';
39+
and o.object_type = :a_object_type]';
4140
open l_result for l_cursor_text using a_object_owner, a_object_type;
4241
return l_result;
4342
end;
@@ -190,6 +189,7 @@ create or replace package body ut_annotation_manager as
190189
l_results ut_annotated_objects;
191190
c_object_fetch_limit constant integer := 10;
192191
begin
192+
193193
l_info_cursor := get_annotation_objs_info_cur(a_object_owner, a_object_type);
194194
fetch l_info_cursor bulk collect into l_info_rows;
195195
close l_info_cursor;

source/core/types/ut_executable.tpb

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,26 +29,41 @@ create or replace type body ut_executable is
2929
return;
3030
end;
3131

32-
member function is_valid(self in out nocopy ut_executable) return boolean is
32+
member function is_defined(self in out nocopy ut_executable) return boolean is
3333
l_result boolean := false;
3434
l_message_part varchar2(4000) := 'Call params for ' || self.associated_event_name || ' are not valid: ';
3535
begin
3636

3737
if self.object_name is null then
3838
self.error_stack := l_message_part || 'package is not defined';
39-
elsif not ut_metadata.package_valid(self.owner_name, self.object_name) then
40-
self.error_stack := l_message_part || 'package does not exist or is invalid: ' ||upper(self.owner_name||'.'||self.object_name);
4139
elsif self.procedure_name is null then
4240
self.error_stack := l_message_part || 'procedure is not defined';
41+
else
42+
l_result := true;
43+
end if;
44+
45+
return l_result;
46+
end is_defined;
47+
48+
/**
49+
* We will check if error raised because package was invalid if not we let it propagate.
50+
**/
51+
member function is_invalid(self in out nocopy ut_executable) return boolean is
52+
l_result boolean := true;
53+
l_message_part varchar2(4000) := 'Call params for ' || self.associated_event_name || ' are not valid: ';
54+
begin
55+
56+
if not ut_metadata.package_valid(self.owner_name, self.object_name) then
57+
self.error_stack := l_message_part || 'package does not exist or is invalid: ' ||upper(self.owner_name||'.'||self.object_name);
4358
elsif not ut_metadata.procedure_exists(self.owner_name, self.object_name, self.procedure_name) then
4459
self.error_stack := l_message_part || 'procedure does not exist '
4560
|| upper(self.owner_name || '.' || self.object_name || '.' ||self.procedure_name);
4661
else
47-
l_result := true;
62+
l_result := false;
4863
end if;
4964

5065
return l_result;
51-
end is_valid;
66+
end is_invalid;
5267

5368
member function form_name return varchar2 is
5469
begin
@@ -66,6 +81,7 @@ create or replace type body ut_executable is
6681
l_status number;
6782
l_cursor_number number;
6883
l_completed_without_errors boolean := true;
84+
l_failed_with_invalid_pck boolean := true;
6985
l_start_transaction_id varchar2(250);
7086
l_end_transaction_id varchar2(250);
7187

@@ -95,7 +111,7 @@ create or replace type body ut_executable is
95111
--listener - before call to executable
96112
ut_event_manager.trigger_event('before_'||self.associated_event_name, self);
97113

98-
l_completed_without_errors := self.is_valid();
114+
l_completed_without_errors := self.is_defined();
99115
if l_completed_without_errors then
100116
l_statement :=
101117
'declare' || chr(10) ||
@@ -117,15 +133,32 @@ create or replace type body ut_executable is
117133
ut_utils.debug_log('ut_executable.do_execute l_statement: ' || l_statement);
118134

119135
l_cursor_number := dbms_sql.open_cursor;
120-
dbms_sql.parse(l_cursor_number, statement => l_statement, language_flag => dbms_sql.native);
121-
dbms_sql.bind_variable(l_cursor_number, 'a_error_stack', to_char(null), 32767);
122-
dbms_sql.bind_variable(l_cursor_number, 'a_error_backtrace', to_char(null), 32767);
123-
124-
l_status := dbms_sql.execute(l_cursor_number);
125-
dbms_sql.variable_value(l_cursor_number, 'a_error_stack', self.error_stack);
126-
dbms_sql.variable_value(l_cursor_number, 'a_error_backtrace', self.error_backtrace);
127-
dbms_sql.close_cursor(l_cursor_number);
128136

137+
/**
138+
* The code will allow to execute once we check if packages are defined
139+
* If it fail with 6550 (usually invalid package) it will check if because of invalid state or missing
140+
* if for any other reason we will propagate it up as we didnt expected.
141+
**/
142+
begin
143+
dbms_sql.parse(l_cursor_number, statement => l_statement, language_flag => dbms_sql.native);
144+
dbms_sql.bind_variable(l_cursor_number, 'a_error_stack', to_char(null), 32767);
145+
dbms_sql.bind_variable(l_cursor_number, 'a_error_backtrace', to_char(null), 32767);
146+
l_status := dbms_sql.execute(l_cursor_number);
147+
dbms_sql.variable_value(l_cursor_number, 'a_error_stack', self.error_stack);
148+
dbms_sql.variable_value(l_cursor_number, 'a_error_backtrace', self.error_backtrace);
149+
dbms_sql.close_cursor(l_cursor_number);
150+
exception
151+
when ut_utils.ex_invalid_package then
152+
l_failed_with_invalid_pck := self.is_invalid();
153+
dbms_sql.close_cursor(l_cursor_number);
154+
if not l_failed_with_invalid_pck then
155+
raise;
156+
end if;
157+
when others then
158+
dbms_sql.close_cursor(l_cursor_number);
159+
raise;
160+
end;
161+
129162
save_dbms_output;
130163

131164
l_completed_without_errors := (self.error_stack||self.error_backtrace) is null;
@@ -144,6 +177,7 @@ create or replace type body ut_executable is
144177
ut_utils.set_client_info(null);
145178

146179
return l_completed_without_errors;
180+
147181
end do_execute;
148182

149183
member function get_error_stack_trace return varchar2 is

source/core/types/ut_executable.tps

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ create or replace type ut_executable under ut_event_item(
2626
error_stack varchar2(4000),
2727
serveroutput clob,
2828
constructor function ut_executable( self in out nocopy ut_executable, a_owner varchar2, a_package varchar2, a_procedure_name varchar2, a_associated_event_name varchar2) return self as result,
29-
member function is_valid(self in out nocopy ut_executable) return boolean,
29+
member function is_invalid(self in out nocopy ut_executable) return boolean,
30+
member function is_defined(self in out nocopy ut_executable) return boolean,
3031
member function form_name return varchar2,
3132
member procedure do_execute(self in out nocopy ut_executable, a_item in out nocopy ut_suite_item),
3233
/**

source/core/ut_utils.pks

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,10 @@ create or replace package ut_utils authid definer is
110110
gc_invalid_version_no constant pls_integer := -20214;
111111
pragma exception_init(ex_invalid_version_no, -20214);
112112

113+
ex_invalid_package exception;
114+
gc_invalid_package constant pls_integer := -6550;
115+
pragma exception_init(ex_invalid_package, -6550);
116+
113117
gc_max_storage_varchar2_len constant integer := 4000;
114118
gc_max_output_string_length constant integer := 4000;
115119
gc_max_input_string_length constant integer := gc_max_output_string_length - 2; --we need to remove 2 chars for quotes around string

test/api/test_ut_run.pkb

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,5 +114,107 @@ Failures:%
114114
execute immediate 'drop package test_stateful';
115115
end;
116116

117+
procedure run_in_invalid_state is
118+
l_results ut3.ut_varchar2_list;
119+
l_actual clob;
120+
l_expected varchar2(32767);
121+
begin
122+
select *
123+
bulk collect into l_results
124+
from table(ut3.ut.run('failing_invalid_spec'));
125+
126+
l_actual := ut3.ut_utils.table_to_clob(l_results);
127+
ut.expect(l_actual).to_be_like('%Call params for % are not valid: package does not exist or is invalid: %FAILING_INVALID_SPEC%');
128+
129+
end;
130+
131+
procedure compile_invalid_package is
132+
ex_compilation_error exception;
133+
pragma exception_init(ex_compilation_error,-24344);
134+
pragma autonomous_transaction;
135+
begin
136+
begin
137+
execute immediate q'[create or replace package failing_invalid_spec as
138+
--%suite
139+
gv_glob_val non_existing_table.id%type := 0;
140+
141+
--%test
142+
procedure test1;
143+
end;]';
144+
exception when ex_compilation_error then null;
145+
end;
146+
begin
147+
execute immediate q'[create or replace package body failing_invalid_spec as
148+
procedure test1 is begin ut.expect(1).to_equal(1); end;
149+
end;]';
150+
exception when ex_compilation_error then null;
151+
end;
152+
end;
153+
procedure drop_invalid_package is
154+
pragma autonomous_transaction;
155+
begin
156+
execute immediate 'drop package failing_invalid_spec';
157+
end;
158+
159+
procedure run_and_revalidate_specs is
160+
l_results ut3.ut_varchar2_list;
161+
l_actual clob;
162+
l_is_invalid number;
163+
begin
164+
execute immediate q'[select count(1) from all_objects o where o.owner = :object_owner and o.object_type = 'PACKAGE'
165+
and o.status = 'INVALID' and o.object_name= :object_name]' into l_is_invalid
166+
using user,'INVALID_PCKAG_THAT_REVALIDATES';
167+
168+
select *
169+
bulk collect into l_results
170+
from table(ut3.ut.run('invalid_pckag_that_revalidates'));
171+
172+
l_actual := ut3.ut_utils.table_to_clob(l_results);
173+
ut.expect(1).to_equal(l_is_invalid);
174+
ut.expect(l_actual).to_be_like('%invalid_pckag_that_revalidates%invalidspecs [% sec]%
175+
%Finished in % seconds%
176+
%1 tests, 0 failed, 0 errored, 0 disabled, 0 warning(s)%');
177+
178+
end;
179+
180+
procedure generate_invalid_spec is
181+
ex_compilation_error exception;
182+
pragma exception_init(ex_compilation_error,-24344);
183+
pragma autonomous_transaction;
184+
begin
185+
186+
execute immediate q'[create or replace package parent_specs as
187+
c_test constant varchar2(1) := 'Y';
188+
end;]';
189+
190+
execute immediate q'[create or replace package invalid_pckag_that_revalidates as
191+
--%suite
192+
g_var varchar2(1) := parent_specs.c_test;
193+
194+
--%test(invalidspecs)
195+
procedure test1;
196+
end;]';
197+
198+
execute immediate q'[create or replace package body invalid_pckag_that_revalidates as
199+
procedure test1 is begin ut.expect('Y').to_equal(g_var); end;
200+
end;]';
201+
202+
-- That should invalidate test package and we can then revers
203+
execute immediate q'[create or replace package parent_specs as
204+
c_test_error constant varchar2(1) := 'Y';
205+
end;]';
206+
207+
execute immediate q'[create or replace package parent_specs as
208+
c_test constant varchar2(1) := 'Y';
209+
end;]';
210+
211+
end;
212+
procedure drop_test_package is
213+
pragma autonomous_transaction;
214+
begin
215+
execute immediate 'drop package invalid_pckag_that_revalidates';
216+
execute immediate 'drop package parent_specs';
217+
end;
218+
117219
end;
118220
/

test/api/test_ut_run.pks

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,20 @@ create or replace package test_ut_run is
88
--%beforetest(create_test_suite)
99
--%aftertest(drop_test_suite)
1010
procedure raise_in_invalid_state;
11+
12+
--%test(ut.run - run invalid package and fail expectation)
13+
--%beforetest(compile_invalid_package)
14+
--%aftertest(drop_invalid_package)
15+
procedure run_in_invalid_state;
16+
procedure compile_invalid_package;
17+
procedure drop_invalid_package;
18+
19+
--%test( Invalidate package specs via rebuild but still execute package)
20+
--%beforetest(generate_invalid_spec)
21+
--%aftertest(drop_test_package)
22+
procedure run_and_revalidate_specs;
23+
procedure generate_invalid_spec;
24+
procedure drop_test_package;
25+
1126
end;
1227
/

test/core/test_suite_manager.pkb

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -872,10 +872,9 @@ end test_package_3;]';
872872
l_objects_to_run ut3.ut_suite_items;
873873
begin
874874
l_objects_to_run := ut3.ut_suite_manager.configure_execution_by_path(ut3.ut_varchar2_list('failing_invalid_spec'));
875-
ut.fail('Invalid package didnt raised exception');
876-
exception
877-
when others then
878-
ut.expect(sqlerrm).to_be_like('%failing_invalid_spec%');
875+
876+
ut3.ut.expect(l_objects_to_run.count).to_be_greater_than(0);
877+
ut3.ut.expect(l_objects_to_run(l_objects_to_run.first).object_name).to_equal('failing_invalid_spec');
879878
end;
880879

881880
procedure compile_invalid_package is
@@ -912,6 +911,26 @@ end;]';
912911
execute immediate 'drop package failing_invalid_spec';
913912
end;
914913

914+
procedure test_search_nonexisting_pck is
915+
l_objects_to_run ut3.ut_suite_items;
916+
begin
917+
l_objects_to_run := ut3.ut_suite_manager.configure_execution_by_path(ut3.ut_varchar2_list('ut3.failing_non_existing'));
918+
ut.fail('Non existing package didnt raised exception');
919+
exception
920+
when others then
921+
ut.expect(sqlerrm).to_be_like('%failing_non_existing%');
922+
end;
923+
924+
procedure test_search_nonexist_sch_pck is
925+
l_objects_to_run ut3.ut_suite_items;
926+
begin
927+
l_objects_to_run := ut3.ut_suite_manager.configure_execution_by_path(ut3.ut_varchar2_list('failing_non_existing'));
928+
ut.fail('Non existing package without schema didnt raised exception');
929+
exception
930+
when others then
931+
ut.expect(sqlerrm).to_be_like('%ORA-44001: invalid schema%');
932+
end;
933+
915934
procedure test_desc_with_comma is
916935
l_objects_to_run ut3.ut_suite_items;
917936
l_suite ut3.ut_suite;

test/core/test_suite_manager.pks

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,18 @@ create or replace package test_suite_manager is
6565
--%test(Prepare runner for the suites package by path for current user)
6666
procedure test_top_subpck_by_path_cu;
6767

68-
--%test(Prepare runner for invalid package)
68+
--%test(Prepare runner for invalid package - it will add to suite but fail on exec )
6969
--%beforetest(compile_invalid_package)
7070
--%aftertest(drop_invalid_package)
7171
procedure test_search_invalid_pck;
7272
procedure compile_invalid_package;
7373
procedure drop_invalid_package;
74+
75+
--%test(Prepare runner for nonexisting package with schema)
76+
procedure test_search_nonexisting_pck;
77+
78+
--%test(Prepare runner for nonexisting package without schema)
79+
procedure test_search_nonexist_sch_pck;
7480

7581
--%test(Test description with comma)
7682
--%beforetest(setup_desc_with_comma)

0 commit comments

Comments
 (0)