Skip to content

Commit c00a746

Browse files
authored
Merge pull request #1365 from utPLSQL/bugfix/throws_annotation_inconsistency
`throws` can reference exception without schema or package name
2 parents 1ed9399 + 7b0cc19 commit c00a746

4 files changed

Lines changed: 133 additions & 31 deletions

File tree

docs/userguide/annotations.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1765,11 +1765,11 @@ Keep in mind that when your test runs as autonomous transaction it will not see
17651765
The `--%throws` annotation allows you to specify a list of exceptions as one of:
17661766

17671767
- number literals - example `--%throws(-20134)`
1768-
- variables of type exception defined in a package specification - example `--%throws(exc_pkg.c_exception_No_variable)`
1769-
- variables of type number defined in a package specification - example `--%throws(exc_pkg.c_some_exception)`
1768+
- variables of type `exception` defined in a package specification - example `--%throws(exc_pkg.c_exception_No_variable)`
1769+
- variables of type `number` defined in a package specification - example `--%throws(exc_pkg.c_some_exception)`
17701770
- [predefined oracle exceptions](https://docs.oracle.com/en//database/oracle/oracle-database/19/lnpls/predefined-exceptions.html) - example `--%throws(no_data_found)`
17711771

1772-
The annotation is ignored, when no valid arguments are provided. Examples of invalid annotations `--%throws()`,`--%throws`, `--%throws(abe, 723pf)`.
1772+
The annotation is ignored when no valid arguments are provided. Examples of invalid annotations `--%throws()`,`--%throws`, `--%throws(abe, 723pf)`.
17731773

17741774
If `--%throws` annotation is specified with arguments and no exception is raised, the test is marked as failed.
17751775

@@ -1780,7 +1780,11 @@ The framework will raise a warning, when `--%throws` annotation has invalid argu
17801780
Annotation `--%throws(7894562, operaqk, -=1, -20496, pow74d, posdfk3)` will be interpreted as `--%throws(-20496)`.
17811781

17821782
Please note that `NO_DATA_FOUND` exception is a special case in Oracle. To capture it use `NO_DATA_FOUND` named exception or `-1403` exception No.
1783-
1783+
1784+
Syntax: `--%throws( [[schema.]package.]exception [, ... ])`
1785+
1786+
So the exception name can be provided with or without the schema and package name. The package name is required only when the exception variable is located in another package. The schema name is required only when the exception variable is located in a pacakge in a nother schema.
1787+
17841788
Example:
17851789
```sql linenums="1"
17861790
create or replace package exc_pkg is

source/core/types/ut_executable_test.tpb

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,11 @@ create or replace noneditionable type body ut_executable_test as
6565
return false;
6666
end;
6767

68-
function check_exception_type(a_exception_name in varchar2) return varchar2 is
69-
l_exception_type varchar2(50);
68+
function to_exception_number(a_exception_name in varchar2) return integer is
69+
l_exception_type varchar2(100);
70+
l_exc_no integer;
7071
begin
72+
7173
--check if it is a predefined exception
7274
begin
7375
execute immediate 'begin null; exception when '||a_exception_name||' then null; end;';
@@ -87,29 +89,33 @@ create or replace noneditionable type body ut_executable_test as
8789
end;
8890
end if;
8991
end;
90-
return l_exception_type;
92+
93+
execute immediate
94+
case l_exception_type
95+
when c_integer_exception then
96+
'declare l_exception number; begin :l_exception := '||a_exception_name||'; end;'
97+
when c_named_exception then
98+
'begin raise '||a_exception_name||'; exception when others then :l_exception := sqlcode; end;'
99+
else
100+
'begin :l_exception := null; end;'
101+
end
102+
using out l_exc_no;
103+
return l_exc_no;
91104
end;
92105

93-
function get_exception_number (a_exception_var in varchar2) return integer is
106+
function get_exception_number (a_exception_var in varchar2, a_item ut_suite_item) return integer is
94107
l_exc_no integer;
95108
l_exc_type varchar2(50);
96109
function remap_no_data_found (a_number integer) return integer is
97110
begin
98111
return case a_number when 100 then -1403 else a_number end;
99112
end;
100113
begin
101-
l_exc_type := check_exception_type(a_exception_var);
102-
103-
execute immediate
104-
case l_exc_type
105-
when c_integer_exception then
106-
'declare l_exception number; begin :l_exception := '||a_exception_var||'; end;'
107-
when c_named_exception then
108-
'begin raise '||a_exception_var||'; exception when others then :l_exception := sqlcode; end;'
109-
else
110-
'begin :l_exception := null; end;'
111-
end
112-
using out l_exc_no;
114+
l_exc_no := coalesce(
115+
to_exception_number(a_exception_var),
116+
to_exception_number(a_item.object_owner||'.'||a_exception_var),
117+
to_exception_number(a_item.object_owner||'.'||a_item.object_name||'.'||a_exception_var)
118+
);
113119

114120
return remap_no_data_found(l_exc_no);
115121
end;
@@ -121,7 +127,7 @@ create or replace noneditionable type body ut_executable_test as
121127
* Check if its a valid qualified name and if so try to resolve name to an exception number
122128
*/
123129
if is_valid_qualified_name(a_expected_error_codes(i)) then
124-
l_exception_number := get_exception_number(a_expected_error_codes(i));
130+
l_exception_number := get_exception_number(a_expected_error_codes(i), a_item);
125131
elsif regexp_like(a_expected_error_codes(i), c_regexp_for_exception_no) then
126132
l_exception_number := a_expected_error_codes(i);
127133
end if;

test/ut3_tester/core/annotations/test_annot_throws_exception.pkb

Lines changed: 80 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
create or replace package body test_annot_throws_exception
22
is
33
g_tests_results clob;
4+
g_results_other_schema clob;
45

56
procedure recollect_tests_results is
67
pragma autonomous_transaction;
@@ -25,10 +26,16 @@ is
2526
e_some_exception exception;
2627
pragma exception_init(e_some_exception, -20207);
2728

28-
end;]';
29+
end;
30+
]';
2931

30-
l_package_spec := '
31-
create package annotated_package_with_throws is
32+
l_package_spec := q'[
33+
create or replace package annotated_package_with_throws is
34+
35+
c_local_error_no constant number := -20211;
36+
e_some_local_exception exception;
37+
pragma exception_init(e_some_local_exception, -20212);
38+
3239
--%suite(Dummy package to test annotation throws)
3340

3441
--%test(Throws same annotated exception)
@@ -95,6 +102,22 @@ is
95102
--%throws(exc_pkg.c_e_mix_missin,utter_rubbish)
96103
procedure mixed_list_notexi;
97104

105+
--%test(Success referencing an exception variable when running from another schema)
106+
--%throws(exc_pkg.e_some_exception)
107+
procedure named_exc_pragma_run_from_another_schema;
108+
109+
--%test(Success referencing a numeric exception variable when running from another schema)
110+
--%throws(exc_pkg.c_e_list_1)
111+
procedure exc_number_var_run_from_another_schema;
112+
113+
--%test(Success referencing an exception variable without package name when running from another schema)
114+
--%throws(e_some_local_exception)
115+
procedure named_exc_pragma_run_from_another_schema_no_package_name;
116+
117+
--%test(Success referencing a numeric exception variable without package name when running from another schema)
118+
--%throws(c_local_error_no)
119+
procedure exc_number_var_run_from_another_schema_no_package_name;
120+
98121
--%test(Success resolve and match named exception defined in pragma exception init)
99122
--%throws(exc_pkg.e_some_exception)
100123
procedure named_exc_pragma;
@@ -123,10 +146,10 @@ is
123146
--%throws(exc_pkg.c_e_dummy);
124147
procedure bad_exc_const;
125148
end;
126-
';
149+
]';
127150

128151
l_package_body := '
129-
create package body annotated_package_with_throws is
152+
create or replace package body annotated_package_with_throws is
130153
procedure raised_same_exception is
131154
begin
132155
raise_application_error(-20145, ''Test error'');
@@ -208,6 +231,26 @@ is
208231
raise_application_error(exc_pkg.c_e_mix_missin,''Test'');
209232
end;
210233

234+
procedure named_exc_pragma_run_from_another_schema is
235+
begin
236+
raise exc_pkg.e_some_exception;
237+
end;
238+
239+
procedure exc_number_var_run_from_another_schema is
240+
begin
241+
raise_application_error(exc_pkg.c_e_list_1,''Test'');
242+
end;
243+
244+
procedure named_exc_pragma_run_from_another_schema_no_package_name is
245+
begin
246+
raise e_some_local_exception;
247+
end;
248+
249+
procedure exc_number_var_run_from_another_schema_no_package_name is
250+
begin
251+
raise_application_error(c_local_error_no,''Test'');
252+
end;
253+
211254
procedure named_exc_pragma is
212255
begin
213256
raise exc_pkg.e_some_exception;
@@ -312,7 +355,7 @@ is
312355

313356
procedure one_valid_exception_number is
314357
begin
315-
ut.expect(g_tests_results).to_match('^\s*Detects a valid exception number within many invalid ones \[[\.0-9]+ sec\]\s*$','m');
358+
ut.expect(g_tests_results).to_match('^\s*Detects a valid exception number within many invalid ones \[[,\.0-9]+ sec\]\s*$','m');
316359
ut.expect(g_tests_results).to_match('one_valid_exception_number\s*Invalid parameter value ".*" for "--%throws" annotation. Parameter ignored.','m');
317360
end;
318361

@@ -357,7 +400,37 @@ is
357400
ut.expect(g_tests_results).to_match('^\s*Success resolve and match named exception defined in pragma exception init \[[,\.0-9]+ sec\]\s*$','m');
358401
ut.expect(g_tests_results).not_to_match('named_exc_pragma');
359402
end;
360-
403+
404+
procedure run_from_another_schema is
405+
begin
406+
ut3_tester_helper.run_helper.run(('ut3_tester.annotated_package_with_throws'));
407+
g_results_other_schema := ut3_tester_helper.main_helper.get_dbms_output_as_clob();
408+
end;
409+
410+
procedure named_exc_pragma_run_from_another_schema is
411+
begin
412+
ut.expect(g_results_other_schema).to_match('^\s*Success referencing an exception variable when running from another schema \[[,\.0-9]+ sec\]\s*$','m');
413+
ut.expect(g_results_other_schema).not_to_match('named_exc_pragma_run_from_another_schema');
414+
end;
415+
416+
procedure named_exc_pragma_run_from_another_schema_no_package_name is
417+
begin
418+
ut.expect(g_results_other_schema).to_match('^\s*Success referencing an exception variable without package name when running from another schema \[[,\.0-9]+ sec\]\s*$','m');
419+
ut.expect(g_results_other_schema).not_to_match('named_exc_pragma_run_from_another_schema_no_package_name');
420+
end;
421+
422+
procedure exc_number_var_run_from_another_schema_no_package_name is
423+
begin
424+
ut.expect(g_results_other_schema).to_match('^\s*Success referencing a numeric exception variable without package name when running from another schema \[[,\.0-9]+ sec\]\s*$','m');
425+
ut.expect(g_results_other_schema).not_to_match('exc_number_var_run_from_another_schema_no_package_name');
426+
end;
427+
428+
procedure exc_number_var_run_from_another_schema is
429+
begin
430+
ut.expect(g_results_other_schema).to_match('^\s*Success referencing a numeric exception variable when running from another schema \[[,\.0-9]+ sec\]\s*$','m');
431+
ut.expect(g_results_other_schema).not_to_match('exc_number_var_run_from_another_schema');
432+
end;
433+
361434
procedure named_exc_ora is
362435
begin
363436
ut.expect(g_tests_results).to_match('^\s*Success resolve and match oracle named exception \[[,\.0-9]+ sec\]\s*$','m');

test/ut3_tester/core/annotations/test_annot_throws_exception.pks

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ is
1818
--%test(Gives failure when the raised exception is different that the annotated one)
1919
procedure throws_diff_annotated_except;
2020

21-
--%test(Ignores when the annotation throws is empty)
21+
--%test(Ignores the throws annotation when it is empty)
2222
procedure throws_empty;
2323

2424
--%test(Ignores when only bad parameters are passed, the test raise a exception and it shows errored test)
@@ -56,8 +56,8 @@ is
5656

5757
--%test(Success resolve and match named exception defined in pragma exception init)
5858
procedure named_exc_pragma;
59-
60-
--%test(Success resolve and match oracle named exception no data)
59+
60+
--%test(Success resolve and match oracle named exception no data)
6161
procedure named_exc_ora;
6262

6363
--%test(Success resolve and match oracle named exception dup val index)
@@ -78,5 +78,24 @@ is
7878
--%afterall
7979
procedure drop_test_package;
8080

81+
--%context(referencing exceptions when running from another schema)
82+
83+
--%beforeall
84+
procedure run_from_another_schema;
85+
86+
--%test(Success referencing an exception variable when running from another schema)
87+
procedure named_exc_pragma_run_from_another_schema;
88+
89+
--%test(Success referencing a numeric exception variable when running from another schema)
90+
procedure exc_number_var_run_from_another_schema;
91+
92+
--%test(Success referencing an exception variable without a package name when running from another schema)
93+
procedure named_exc_pragma_run_from_another_schema_no_package_name;
94+
95+
--%test(Success referencing a numeric exception variable without a package name when running from another schema)
96+
procedure exc_number_var_run_from_another_schema_no_package_name;
97+
98+
--%endcontext
99+
81100
end;
82101
/

0 commit comments

Comments
 (0)