diff --git a/source/core/ut_expectation_processor.pkb b/source/core/ut_expectation_processor.pkb index 8767d8d8b..e961ca908 100644 --- a/source/core/ut_expectation_processor.pkb +++ b/source/core/ut_expectation_processor.pkb @@ -88,7 +88,7 @@ create or replace package body ut_expectation_processor as begin add_expectation_result(ut_expectation_result(ut_utils.gc_failure, null, a_message)); end; - + function get_session_parameters return tt_nls_params is l_session_params tt_nls_params; begin diff --git a/source/core/ut_expectation_processor.pks b/source/core/ut_expectation_processor.pks index f58de2441..ab3b70f76 100644 --- a/source/core/ut_expectation_processor.pks +++ b/source/core/ut_expectation_processor.pks @@ -35,7 +35,7 @@ create or replace package ut_expectation_processor authid current_user as procedure add_expectation_result(a_expectation_result ut_expectation_result); procedure report_failure(a_message in varchar2); - + procedure set_xml_nls_params; procedure reset_nls_params; diff --git a/source/core/ut_utils.pkb b/source/core/ut_utils.pkb index b29e7fa60..25ef3fb3f 100644 --- a/source/core/ut_utils.pkb +++ b/source/core/ut_utils.pkb @@ -737,5 +737,20 @@ create or replace package body ut_utils is return l_results; end; + function remove_error_from_stack(a_error_stack varchar2, a_ora_code number) return varchar2 is + l_caller_stack_line varchar2(4000); + l_ora_search_pattern varchar2(500) := '^ORA'||a_ora_code||': (.*)$'; + begin + l_caller_stack_line := regexp_replace(srcstr => a_error_stack + ,pattern => l_ora_search_pattern + ,replacestr => null + ,position => 1 + ,occurrence => 1 + ,modifier => 'm'); + return l_caller_stack_line; + end; + + + end ut_utils; / diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 4bf155ce7..abe3b2d90 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -109,6 +109,14 @@ create or replace package ut_utils authid definer is gc_value_too_large constant pls_integer := -20217; pragma exception_init (ex_value_too_large, -20217); + ex_xml_processing exception; + gc_xml_processing constant pls_integer := -19202; + pragma exception_init (ex_xml_processing, -19202); + + ex_failed_open_cur exception; + gc_failed_open_cur constant pls_integer := -20218; + pragma exception_init (ex_failed_open_cur, -20218); + gc_max_storage_varchar2_len constant integer := 4000; gc_max_output_string_length constant integer := 4000; gc_more_data_string constant varchar2(5) := '[...]'; @@ -368,6 +376,11 @@ create or replace package ut_utils authid definer is * Returns list of sub-type reporters for given list of super-type reporters */ function get_child_reporters(a_for_reporters ut_reporters_info := null) return ut_reporters_info; - + + /** + * Remove given ORA error from stack + */ + function remove_error_from_stack(a_error_stack varchar2, a_ora_code number) return varchar2; + end ut_utils; / diff --git a/source/expectations/data_values/ut_compound_data_helper.pkb b/source/expectations/data_values/ut_compound_data_helper.pkb index d8367e8c4..dd55036bb 100644 --- a/source/expectations/data_values/ut_compound_data_helper.pkb +++ b/source/expectations/data_values/ut_compound_data_helper.pkb @@ -18,8 +18,10 @@ create or replace package body ut_compound_data_helper is g_diff_count integer; type t_type_name_map is table of varchar2(128) index by binary_integer; + type t_types_no_length is table of varchar2(128) index by varchar2(128); g_type_name_map t_type_name_map; g_anytype_name_map t_type_name_map; + g_type_no_length_map t_types_no_length; g_compare_sql_template varchar2(4000) := q'[ @@ -231,8 +233,7 @@ create or replace package body ut_compound_data_helper is elsif a_data_info.is_sql_diffable = 1 and a_data_info.column_type in ('DATE','TIMESTAMP','TIMESTAMP WITH TIME ZONE', 'TIMESTAMP WITH LOCAL TIME ZONE') then l_col_type := 'VARCHAR2(50)'; - elsif a_data_info.is_sql_diffable = 1 and a_data_info.column_type in ('INTERVAL DAY TO SECOND', - 'INTERVAL YEAR TO MONTH', 'BINARY_FLOAT', 'BINARY_DOUBLE') then + elsif a_data_info.is_sql_diffable = 1 and type_no_length(a_data_info.column_type) then l_col_type := a_data_info.column_type; else l_col_type := a_data_info.column_type @@ -570,6 +571,8 @@ create or replace package body ut_compound_data_helper is --clob/blob/xmltype/object/nestedcursor/nestedtable if a_type_name IN (g_type_name_map(dbms_sql.blob_type), g_type_name_map(dbms_sql.clob_type), + g_type_name_map(dbms_sql.long_type), + g_type_name_map(dbms_sql.long_raw_type), g_type_name_map(dbms_sql.bfile_type), g_anytype_name_map(dbms_types.typecode_namedcollection)) then @@ -596,6 +599,24 @@ create or replace package body ut_compound_data_helper is open l_diff_cursor for a_diff_cursor_text using a_self_id, a_other_id; return l_diff_cursor; end; + + function create_err_cursor_msg(a_error_stack varchar2) return varchar2 is + begin + return 'SQL exception thrown when fetching data from cursor:'|| + ut_utils.remove_error_from_stack(sqlerrm,ut_utils.gc_xml_processing)||chr(10)|| + ut_expectation_processor.who_called_expectation(a_error_stack)|| + 'Check the query and data for errors.'; + end; + + function type_no_length ( a_type_name varchar2) return boolean is + begin + return case + when g_type_no_length_map.exists(a_type_name) then + true + else + false + end; + end; begin g_anytype_name_map(dbms_types.typecode_date) := 'DATE'; @@ -642,6 +663,15 @@ begin g_type_name_map( dbms_sql.urowid_type ) := 'UROWID'; g_type_name_map( dbms_sql.user_defined_type ) := 'USER_DEFINED_TYPE'; g_type_name_map( dbms_sql.ref_type ) := 'REF_TYPE'; - + + + /** + * List of types that have no length but can produce a max_len from desc_cursor function. + */ + g_type_no_length_map('ROWID') := 'ROWID'; + g_type_no_length_map('INTERVAL DAY TO SECOND') := 'INTERVAL DAY TO SECOND'; + g_type_no_length_map('INTERVAL YEAR TO MONTH') := 'INTERVAL YEAR TO MONTH'; + g_type_no_length_map('BINARY_DOUBLE') := 'BINARY_DOUBLE'; + g_type_no_length_map('BINARY_FLOAT') := 'BINARY_FLOAT'; end; / diff --git a/source/expectations/data_values/ut_compound_data_helper.pks b/source/expectations/data_values/ut_compound_data_helper.pks index bf3182500..1c00d2263 100644 --- a/source/expectations/data_values/ut_compound_data_helper.pks +++ b/source/expectations/data_values/ut_compound_data_helper.pks @@ -92,5 +92,12 @@ create or replace package ut_compound_data_helper authid definer is function get_compare_cursor(a_diff_cursor_text in clob,a_self_id raw, a_other_id raw) return sys_refcursor; + function create_err_cursor_msg(a_error_stack varchar2) return varchar2; + + /* + * Function to return true or false if the type dont have an length + */ + function type_no_length ( a_type_name varchar2) return boolean; + end; / diff --git a/source/expectations/data_values/ut_data_value_refcursor.tpb b/source/expectations/data_values/ut_data_value_refcursor.tpb index 83bd1502f..23dca3dcf 100644 --- a/source/expectations/data_values/ut_data_value_refcursor.tpb +++ b/source/expectations/data_values/ut_data_value_refcursor.tpb @@ -96,6 +96,12 @@ create or replace type body ut_data_value_refcursor as exception when cursor_not_open then raise_application_error(-20155, 'Cursor is not open'); + when ut_utils.ex_xml_processing then + if l_cursor%isopen then + close l_cursor; + end if; + raise_application_error(ut_utils.gc_failed_open_cur, + ut_compound_data_helper.create_err_cursor_msg(dbms_utility.format_call_stack())); when others then if l_cursor%isopen then close l_cursor; @@ -111,7 +117,9 @@ create or replace type body ut_data_value_refcursor as dbms_lob.createtemporary(l_result, true); ut_utils.append_to_clob(l_result, 'Data-types:'||chr(10)); - ut_utils.append_to_clob( l_result, self.cursor_details.get_xml_children().getclobval() ); + if self.cursor_details.cursor_columns_info.count > 0 then + ut_utils.append_to_clob( l_result, self.cursor_details.get_xml_children().getclobval() ); + end if; ut_utils.append_to_clob(l_result,chr(10)||(self as ut_compound_data_value).to_string()); l_result_string := ut_utils.to_string(l_result,null); dbms_lob.freetemporary(l_result); diff --git a/test/ut3_user/expectations/test_expectations_cursor.pkb b/test/ut3_user/expectations/test_expectations_cursor.pkb index f8bb92878..9b41a259c 100644 --- a/test/ut3_user/expectations/test_expectations_cursor.pkb +++ b/test/ut3_user/expectations/test_expectations_cursor.pkb @@ -994,18 +994,16 @@ Rows: [ 4 differences ] procedure reports_on_exception_in_cursor as l_actual sys_refcursor; - l_error_code integer := -19202; --Error occurred in XML processing begin --Act open l_actual for select 1/0 as error_column from dual connect by level < 10; - begin ut3.ut.expect(l_actual).to_be_empty(); - --Assert - ut.fail('Expected '||l_error_code||' but nothing was raised'); - exception - when others then - ut.expect(sqlcode).to_equal(l_error_code); - end; + + ut.fail('Expected exception on cursor fetch'); + exception + when others then + ut.expect(sqlerrm).to_be_like('%ORA-20218: SQL exception thrown when fetching data from cursor:% +%ORA-01476: divisor is equal to zero%Check the query and data for errors%'); end; procedure exception_when_closed_cursor @@ -2545,5 +2543,80 @@ Diff:% ut.expect(l_actual_message).to_be_like(l_expected_message); end; + procedure xml_error_actual is + l_actual sys_refcursor; + l_expected sys_refcursor; + l_exp_message varchar2(32000); + begin + l_exp_message :='ORA-20218: SQL exception thrown when fetching data from cursor: +ORA-01476: divisor is equal to zero +at "UT3$USER#.TEST_EXPECTATIONS_CURSOR%", line 2561 ut3.ut.expect(l_actual).to_equal(l_expected);% +Check the query and data for errors.'; + + open l_actual for + select 1 as test from dual; + open l_expected for + select 1/0 as test from dual; + + ut3.ut.expect(l_actual).to_equal(l_expected); + --Line that error relates to in expected messag + + ut.fail('Expected exception on cursor fetch'); + exception + when others then + ut.expect(sqlerrm).to_be_like(l_exp_message); + end; + + procedure xml_error_expected is + l_actual sys_refcursor; + l_expected sys_refcursor; + l_exp_message varchar2(32000); + begin + + l_exp_message :='ORA-20218: SQL exception thrown when fetching data from cursor: +ORA-01476: divisor is equal to zero +at "UT3$USER#.TEST_EXPECTATIONS_CURSOR%", line 2586 ut3.ut.expect(l_actual).to_equal(l_expected);% +Check the query and data for errors.'; + + open l_expected for + select 1/0 as test from dual; + open l_actual for + select 1 as test from dual; + + ut3.ut.expect(l_actual).to_equal(l_expected); + + ut.fail('Expected exception on cursor fetch'); + exception + when others then + ut.expect(sqlerrm).to_be_like(l_exp_message); + end; + + procedure no_length_datatypes is + l_actual sys_refcursor; + l_expected sys_refcursor; + begin + ut3.ut.set_nls; + open l_expected for + select cast(3.14 as binary_double) as pi_double, + cast(3.14 as binary_float) as pi_float, + rowid as row_rowid, + numtodsinterval(1.12345678912, 'day') row_ds_interval, + numtoyminterval(1.1, 'year') row_ym_interval + from dual; + + open l_actual for + select cast(3.14 as binary_double) as pi_double, + cast(3.14 as binary_float) as pi_float, + rowid as row_rowid, + numtodsinterval(1.12345678912, 'day') row_ds_interval, + numtoyminterval(1.1, 'year') row_ym_interval + from dual; + --Act + ut3.ut.expect( l_actual ).to_equal( l_expected ); + --Assert + ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0); + ut3.ut.reset_nls; + + end; end; / diff --git a/test/ut3_user/expectations/test_expectations_cursor.pks b/test/ut3_user/expectations/test_expectations_cursor.pks index d0b9a6e54..b662ba61b 100644 --- a/test/ut3_user/expectations/test_expectations_cursor.pks +++ b/test/ut3_user/expectations/test_expectations_cursor.pks @@ -393,11 +393,21 @@ create or replace package test_expectations_cursor is --%test(Cursor to contain duplicates fail) procedure to_contain_duplicates_fail; - + --%test(Display a message with a uer defined type with only type name not structure on equal) procedure udt_messg_format_eq; --%test(Display a message with a uer defined type with only type name not structure on empty) - procedure udt_messg_format_empt; + procedure udt_messg_format_empt; + + --%test(Fail to process a cursor for actual) + procedure xml_error_actual; + + --%test(Fail to process a cursor for expected) + procedure xml_error_expected; + + --%test(Check that cursor correctly handles no length dataypes) + procedure no_length_datatypes; + end; /