Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions docs/userguide/annotations.md
Original file line number Diff line number Diff line change
Expand Up @@ -1753,11 +1753,11 @@ Keep in mind that when your test runs as autonomous transaction it will not see
The `--%throws` annotation allows you to specify a list of exceptions as one of:

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

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

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

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

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.


Syntax: `--%throws( [[schema.]package.]exception [, ... ])`

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.

Example:
```sql linenums="1"
create or replace package exc_pkg is
Expand Down
40 changes: 23 additions & 17 deletions source/core/types/ut_executable_test.tpb
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,11 @@
return false;
end;

function check_exception_type(a_exception_name in varchar2) return varchar2 is
l_exception_type varchar2(50);
function to_exception_number(a_exception_name in varchar2) return integer is
l_exception_type varchar2(100);
l_exc_no integer;
begin

--check if it is a predefined exception
begin
execute immediate 'begin null; exception when '||a_exception_name||' then null; end;';
Expand All @@ -87,29 +89,33 @@
end;
end if;
end;
return l_exception_type;

execute immediate
case l_exception_type
when c_integer_exception then
'declare l_exception number; begin :l_exception := '||a_exception_name||'; end;'
when c_named_exception then
'begin raise '||a_exception_name||'; exception when others then :l_exception := sqlcode; end;'
else
'begin :l_exception := null; end;'
end
using out l_exc_no;
return l_exc_no;
end;

function get_exception_number (a_exception_var in varchar2) return integer is
function get_exception_number (a_exception_var in varchar2, a_item ut_suite_item) return integer is
l_exc_no integer;
l_exc_type varchar2(50);

Check warning on line 108 in source/core/types/ut_executable_test.tpb

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the unused local variable "l_exc_type".

See more on https://sonarcloud.io/project/issues?id=utPLSQL_utPLSQL&issues=AZ6nmJ12YJQZHzfQuVfQ&open=AZ6nmJ12YJQZHzfQuVfQ&pullRequest=1365
function remap_no_data_found (a_number integer) return integer is
begin
return case a_number when 100 then -1403 else a_number end;
end;
begin
l_exc_type := check_exception_type(a_exception_var);

execute immediate
case l_exc_type
when c_integer_exception then
'declare l_exception number; begin :l_exception := '||a_exception_var||'; end;'
when c_named_exception then
'begin raise '||a_exception_var||'; exception when others then :l_exception := sqlcode; end;'
else
'begin :l_exception := null; end;'
end
using out l_exc_no;
l_exc_no := coalesce(
to_exception_number(a_exception_var),
to_exception_number(a_item.object_owner||'.'||a_exception_var),
to_exception_number(a_item.object_owner||'.'||a_item.object_name||'.'||a_exception_var)
);

return remap_no_data_found(l_exc_no);
end;
Expand All @@ -121,7 +127,7 @@
* Check if its a valid qualified name and if so try to resolve name to an exception number
*/
if is_valid_qualified_name(a_expected_error_codes(i)) then
l_exception_number := get_exception_number(a_expected_error_codes(i));
l_exception_number := get_exception_number(a_expected_error_codes(i), a_item);
elsif regexp_like(a_expected_error_codes(i), c_regexp_for_exception_no) then
l_exception_number := a_expected_error_codes(i);
end if;
Expand Down
87 changes: 80 additions & 7 deletions test/ut3_tester/core/annotations/test_annot_throws_exception.pkb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
create or replace package body test_annot_throws_exception
is
g_tests_results clob;
g_results_other_schema clob;

procedure recollect_tests_results is
pragma autonomous_transaction;
Expand All @@ -25,10 +26,16 @@ is
e_some_exception exception;
pragma exception_init(e_some_exception, -20207);

end;]';
end;
]';

l_package_spec := '
create package annotated_package_with_throws is
l_package_spec := q'[
create or replace package annotated_package_with_throws is

c_local_error_no constant number := -20211;
e_some_local_exception exception;
pragma exception_init(e_some_local_exception, -20212);

--%suite(Dummy package to test annotation throws)

--%test(Throws same annotated exception)
Expand Down Expand Up @@ -95,6 +102,22 @@ is
--%throws(exc_pkg.c_e_mix_missin,utter_rubbish)
procedure mixed_list_notexi;

--%test(Success referencing an exception variable when running from another schema)
--%throws(exc_pkg.e_some_exception)
procedure named_exc_pragma_run_from_another_schema;

--%test(Success referencing a numeric exception variable when running from another schema)
--%throws(exc_pkg.c_e_list_1)
procedure exc_number_var_run_from_another_schema;

--%test(Success referencing an exception variable without package name when running from another schema)
--%throws(e_some_local_exception)
procedure named_exc_pragma_run_from_another_schema_no_package_name;

--%test(Success referencing a numeric exception variable without package name when running from another schema)
--%throws(c_local_error_no)
procedure exc_number_var_run_from_another_schema_no_package_name;

--%test(Success resolve and match named exception defined in pragma exception init)
--%throws(exc_pkg.e_some_exception)
procedure named_exc_pragma;
Expand Down Expand Up @@ -123,10 +146,10 @@ is
--%throws(exc_pkg.c_e_dummy);
procedure bad_exc_const;
end;
';
]';

l_package_body := '
create package body annotated_package_with_throws is
create or replace package body annotated_package_with_throws is
procedure raised_same_exception is
begin
raise_application_error(-20145, ''Test error'');
Expand Down Expand Up @@ -208,6 +231,26 @@ is
raise_application_error(exc_pkg.c_e_mix_missin,''Test'');
end;

procedure named_exc_pragma_run_from_another_schema is
begin
raise exc_pkg.e_some_exception;
end;

procedure exc_number_var_run_from_another_schema is
begin
raise_application_error(exc_pkg.c_e_list_1,''Test'');
end;

procedure named_exc_pragma_run_from_another_schema_no_package_name is
begin
raise e_some_local_exception;
end;

procedure exc_number_var_run_from_another_schema_no_package_name is
begin
raise_application_error(c_local_error_no,''Test'');
end;

procedure named_exc_pragma is
begin
raise exc_pkg.e_some_exception;
Expand Down Expand Up @@ -312,7 +355,7 @@ is

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

Expand Down Expand Up @@ -357,7 +400,37 @@ is
ut.expect(g_tests_results).to_match('^\s*Success resolve and match named exception defined in pragma exception init \[[,\.0-9]+ sec\]\s*$','m');
ut.expect(g_tests_results).not_to_match('named_exc_pragma');
end;


procedure run_from_another_schema is
begin
ut3_tester_helper.run_helper.run(('ut3_tester.annotated_package_with_throws'));
g_results_other_schema := ut3_tester_helper.main_helper.get_dbms_output_as_clob();
end;

procedure named_exc_pragma_run_from_another_schema is
begin
ut.expect(g_results_other_schema).to_match('^\s*Success referencing an exception variable when running from another schema \[[,\.0-9]+ sec\]\s*$','m');
ut.expect(g_results_other_schema).not_to_match('named_exc_pragma_run_from_another_schema');
end;

procedure named_exc_pragma_run_from_another_schema_no_package_name is
begin
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');
ut.expect(g_results_other_schema).not_to_match('named_exc_pragma_run_from_another_schema_no_package_name');
end;

procedure exc_number_var_run_from_another_schema_no_package_name is
begin
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');
ut.expect(g_results_other_schema).not_to_match('exc_number_var_run_from_another_schema_no_package_name');
end;

procedure exc_number_var_run_from_another_schema is
begin
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');
ut.expect(g_results_other_schema).not_to_match('exc_number_var_run_from_another_schema');
end;

procedure named_exc_ora is
begin
ut.expect(g_tests_results).to_match('^\s*Success resolve and match oracle named exception \[[,\.0-9]+ sec\]\s*$','m');
Expand Down
25 changes: 22 additions & 3 deletions test/ut3_tester/core/annotations/test_annot_throws_exception.pks
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ is
--%test(Gives failure when the raised exception is different that the annotated one)
procedure throws_diff_annotated_except;

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

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

--%test(Success resolve and match named exception defined in pragma exception init)
procedure named_exc_pragma;
--%test(Success resolve and match oracle named exception no data)

--%test(Success resolve and match oracle named exception no data)
procedure named_exc_ora;

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

--%context(referencing exceptions when running from another schema)

--%beforeall
procedure run_from_another_schema;

--%test(Success referencing an exception variable when running from another schema)
procedure named_exc_pragma_run_from_another_schema;

--%test(Success referencing a numeric exception variable when running from another schema)
procedure exc_number_var_run_from_another_schema;

--%test(Success referencing an exception variable without a package name when running from another schema)
procedure named_exc_pragma_run_from_another_schema_no_package_name;

--%test(Success referencing a numeric exception variable without a package name when running from another schema)
procedure exc_number_var_run_from_another_schema_no_package_name;

--%endcontext

end;
/
Loading