From 421d3a2d7f6b09ff5f233a9ef4b9294a8ad9116d Mon Sep 17 00:00:00 2001 From: Jacek Date: Fri, 14 Jul 2017 15:25:01 +0100 Subject: [PATCH] The `who_called_expectation` is now more relaxed on the stacktrace format. Resolves #401 Resolves issues with stacktrace not getting parsed properly on some machines. --- source/core/types/ut_expectation_result.tpb | 2 +- source/core/ut_expectation_processor.pkb | 24 ++++++------- source/core/ut_expectation_processor.pks | 2 +- tests/RunAll.sql | 2 ++ ...who_called_expectation.parseStackTrace.sql | 34 +++++++++++++++++++ ...lled_expectation.parseStackTraceWith0x.sql | 28 +++++++++++++++ 6 files changed, 77 insertions(+), 15 deletions(-) create mode 100644 tests/ut_expectation_processor/who_called_expectation.parseStackTrace.sql create mode 100644 tests/ut_expectation_processor/who_called_expectation.parseStackTraceWith0x.sql diff --git a/source/core/types/ut_expectation_result.tpb b/source/core/types/ut_expectation_result.tpb index 03207c1b7..9452defcd 100644 --- a/source/core/types/ut_expectation_result.tpb +++ b/source/core/types/ut_expectation_result.tpb @@ -23,7 +23,7 @@ create or replace type body ut_expectation_result is self.description := a_description; self.message := a_message; if self.status = ut_utils.tr_failure then - self.caller_info := ut_expectation_processor.who_called_expectation(); + self.caller_info := ut_expectation_processor.who_called_expectation(dbms_utility.format_call_stack()); end if; return; end; diff --git a/source/core/ut_expectation_processor.pkb b/source/core/ut_expectation_processor.pkb index f088bef23..2a16af70e 100644 --- a/source/core/ut_expectation_processor.pkb +++ b/source/core/ut_expectation_processor.pkb @@ -120,30 +120,28 @@ create or replace package body ut_expectation_processor as end; - function who_called_expectation return varchar2 is - c_call_stack constant varchar2(32767) := dbms_utility.format_call_stack(); + function who_called_expectation(a_call_stack varchar2) return varchar2 is l_caller_stack_line varchar2(4000); - l_caller_type_and_name varchar2(4000); l_line_no integer; l_owner varchar2(1000); - l_object_name varchar2(1000); + l_object_name varchar2(1000); + l_result varchar2(4000); -- in 12.2 format_call_stack reportes not only package name, but also the procedure name -- when 11g and 12c reports only package name - c_expectation_search_pattern constant varchar2(500) := + c_expectation_search_pattern constant varchar2(500) := '(.*\.(UT_EXPECTATION[A-Z0-9#_$]*|UT|UTASSERT2?)(\.[A-Z0-9#_$]+)?\s+)+(.*)'; begin - l_caller_stack_line := regexp_substr( c_call_stack, c_expectation_search_pattern, 1, 1, 'm', 4); - l_line_no := to_number( regexp_substr(l_caller_stack_line,'0x[0-9a-f]+\s+(\d+)',subexpression => 1) ); - l_caller_type_and_name := trim(regexp_substr(l_caller_stack_line,'0x[0-9a-f]+\s+\d+\s+(.+)',subexpression => 1)); + l_caller_stack_line := regexp_substr( a_call_stack, c_expectation_search_pattern, 1, 1, 'm', 4); if l_caller_stack_line like '%.%' then + l_line_no := to_number( regexp_substr(l_caller_stack_line,'(0x)?[0-9a-f]+\s+(\d+)',subexpression => 2) ); l_owner := regexp_substr(l_caller_stack_line,'([A-Za-z0-9$#_]+)\.([A-Za-z0-9$#_]|\.)+',subexpression => 1); l_object_name := regexp_substr(l_caller_stack_line,'([A-Za-z0-9$#_]+)\.(([A-Za-z0-9$#_]|\.)+)',subexpression => 2); + if l_owner is not null and l_object_name is not null and l_line_no is not null then + l_result := 'at "' || l_owner || '.' || l_object_name || '", line '|| l_line_no || ' ' + || ut_metadata.get_source_definition_line(l_owner, l_object_name, l_line_no); + end if; end if; - return - case when l_owner is not null and l_object_name is not null and l_line_no is not null then - 'at "' || l_owner || '.' || l_object_name || '", line '|| l_line_no || ' ' || - ut_metadata.get_source_definition_line(l_owner, l_object_name, l_line_no) - end; + return l_result; end; end; / diff --git a/source/core/ut_expectation_processor.pks b/source/core/ut_expectation_processor.pks index 0ed03c46f..4541c3f64 100644 --- a/source/core/ut_expectation_processor.pks +++ b/source/core/ut_expectation_processor.pks @@ -44,7 +44,7 @@ create or replace package ut_expectation_processor authid current_user as -- if found, it returns a text: -- at: owner.name:line "source code line text" -- The text is to be consumed by expectation result - function who_called_expectation return varchar2; + function who_called_expectation(a_call_stack varchar2) return varchar2; end; / diff --git a/tests/RunAll.sql b/tests/RunAll.sql index d312f4f84..21142354e 100644 --- a/tests/RunAll.sql +++ b/tests/RunAll.sql @@ -48,6 +48,8 @@ exec ut_coverage.coverage_start_develop(); @@lib/RunTest.sql ut_annotations/ut_annotations.parse_package_annotations.ParsePackageLevelAnnotationWithKeyValue.sql @@lib/RunTest.sql ut_annotations/ut_annotations.parse_package_annotations.ParsePackageLevelAnnotationWithMultilineComment.sql @@lib/RunTest.sql ut_annotations/ut_annotations.parse_package_annotations.spaceBeforeAnnotationParams.sql +@@lib/RunTest.sql ut_expectation_processor/who_called_expectation.parseStackTrace.sql +@@lib/RunTest.sql ut_expectation_processor/who_called_expectation.parseStackTraceWith0x.sql @@ut_expectations/ut.expect.not_to_be_null.sql @@lib/RunTest.sql ut_expectations/ut.expect.to_be_false.GivesFailureWhenExpessionIsNotBoolean.sql @@lib/RunTest.sql ut_expectations/ut.expect.to_be_false.GivesFailureWhenExpessionIsNull.sql diff --git a/tests/ut_expectation_processor/who_called_expectation.parseStackTrace.sql b/tests/ut_expectation_processor/who_called_expectation.parseStackTrace.sql new file mode 100644 index 000000000..dcf28a0b8 --- /dev/null +++ b/tests/ut_expectation_processor/who_called_expectation.parseStackTrace.sql @@ -0,0 +1,34 @@ +declare + l_stack_trace varchar2(4000); + l_source_line varchar2(4000); +begin +l_stack_trace := q'[----- PL/SQL Call Stack ----- + object line object + handle number name +34f88e4420 124 package body SCH_TEST.UT_EXPECTATION_PROCESSOR +353dfeb2f8 26 SCH_TEST.UT_EXPECTATION_RESULT +cba249ce0 112 SCH_TEST.UT_EXPECTATION +3539881cf0 21 SCH_TEST.UT_EXPECTATION_NUMBER +351a608008 28 package body SCH_TEST.TPKG_PRIOR_YEAR_GENERATION +351a6862b8 6 anonymous block +351fe31010 1825 package body SYS.DBMS_SQL +20befbe4d8 129 SCH_TEST.UT_EXECUTABLE +20befbe4d8 65 SCH_TEST.UT_EXECUTABLE +34f8ab7cd8 80 SCH_TEST.UT_TEST +34f8ab98f0 48 SCH_TEST.UT_SUITE_ITEM +34f8ab9b10 74 SCH_TEST.UT_SUITE +34f8ab98f0 48 SCH_TEST.UT_SUITE_ITEM +cba24bfd0 75 SCH_TEST.UT_LOGICAL_SUITE +353dfecf30 59 SCH_TEST.UT_RUN +34f8ab98f0 48 SCH_TEST.UT_SUITE_ITEM +357f5421e8 77 package body SCH_TEST.UT_RUNNER +357f5421e8 111 package body SCH_TEST.UT_RUNNER +20be951ab0 292 package body SCH_TEST.UT +20be951ab0 320 package body SCH_TEST.UT +]'; + l_source_line := ut_expectation_processor.WHO_CALLED_EXPECTATION(l_stack_trace); + if l_source_line like 'at "SCH_TEST.TPKG_PRIOR_YEAR_GENERATION", line 28 %' then + :test_result := ut_utils.tr_success; + end if; +end; +/ diff --git a/tests/ut_expectation_processor/who_called_expectation.parseStackTraceWith0x.sql b/tests/ut_expectation_processor/who_called_expectation.parseStackTraceWith0x.sql new file mode 100644 index 000000000..febc5652f --- /dev/null +++ b/tests/ut_expectation_processor/who_called_expectation.parseStackTraceWith0x.sql @@ -0,0 +1,28 @@ +declare + l_stack_trace varchar2(4000); + l_source_line varchar2(4000); +begin +l_stack_trace := q'[----- PL/SQL Call Stack ----- + object line object + handle number name +0x80e701d8 26 UT3.UT_EXPECTATION_RESULT +0x85e10150 112 UT3.UT_EXPECTATION +0x8b54bad8 21 UT3.UT_EXPECTATION_NUMBER +0x85cfd238 20 package body UT3.UT_EXAMPLETEST +0x85def380 6 anonymous block +0x85e93750 1825 package body SYS.DBMS_SQL +0x80f4f608 129 UT3.UT_EXECUTABLE +0x80f4f608 65 UT3.UT_EXECUTABLE +0x8a116010 76 UT3.UT_TEST +0x8a3348a0 48 UT3.UT_SUITE_ITEM +0x887e9948 67 UT3.UT_LOGICAL_SUITE +0x8a26de20 59 UT3.UT_RUN +0x8a3348a0 48 UT3.UT_SUITE_ITEM +0x838d17c0 28 anonymous block +]'; + l_source_line := ut_expectation_processor.WHO_CALLED_EXPECTATION(l_stack_trace); + if l_source_line like 'at "UT3.UT_EXAMPLETEST", line 20 %' then + :test_result := ut_utils.tr_success; + end if; +end; +/